diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 82090a7..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -.uasset filter=lfs diff=lfs merge=lfs -text -*.uasset filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index dbb6a2c..010cf74 100644 --- a/.gitignore +++ b/.gitignore @@ -240,17 +240,14 @@ pip-log.txt #Unreal Engine +.vs/ +.vs/* Binaries/ -Plugins/ -Plugins/* + Content/* +Substance/ +Substance/* !Content/Blueprints/ -!Plugins/GameInventorySystem/Content -!Plugins/GameInventorySystem/Source -!Plugins/GameAttributes/Content -!Plugins/GameAttributes/Source -!Plugins/TimeOfDay/Content -!Plugins/TimeOfDay/Source DerivedDataCache/ Intermediate/ Saved/ @@ -266,3 +263,9 @@ Saved/ CodeBackup/States/GASAbilityStateCooldown.h *.bin *.pak +Config/DefaultARGame.ini +Plugins/* +!Plugins/AbilityFramework/ +!Plugins/AbilityFramework/Source/ +!!Plugins/AbilityFrameworkEditor/ +!Plugins/AbilityFrameworkEditor/Source/ \ No newline at end of file diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json deleted file mode 100644 index 38c5f00..0000000 --- a/.vs/ProjectSettings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "CurrentProjectSetting": "x86-Debug" -} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json deleted file mode 100644 index 4fd6934..0000000 --- a/.vs/VSWorkspaceState.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "ExpandedNodes": [ - "", - "\\Content\\Blueprints", - "\\Source" - ], - "SelectedNode": "\\Content", - "PreviewInSolutionExplorer": false -} \ No newline at end of file diff --git a/.vs/config/applicationhost.config b/.vs/config/applicationhost.config deleted file mode 100644 index 4b9bf47..0000000 --- a/.vs/config/applicationhost.config +++ /dev/null @@ -1,1031 +0,0 @@ - - - - - - - -
-
-
-
-
-
-
-
- - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
- -
-
- -
-
-
- - -
-
-
-
-
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite deleted file mode 100644 index 0316013..0000000 Binary files a/.vs/slnx.sqlite and /dev/null differ diff --git a/ActionRPGGame.uproject b/ActionRPGGame.uproject index 683712d..633f105 100644 --- a/ActionRPGGame.uproject +++ b/ActionRPGGame.uproject @@ -1,43 +1,262 @@ { "FileVersion": 3, - "EngineAssociation": "{A035B080-4493-F253-AA70-EF8A66B855F8}", + "EngineAssociation": "", "Category": "", "Description": "", "Modules": [ { "Name": "ActionRPGGame", "Type": "Runtime", - "LoadingPhase": "Default" + "LoadingPhase": "Default", + "AdditionalDependencies": [ + "AbilityFramework", + "InventoryFramework", + "Engine", + "AIModule", + "UMG", + "CoreUObject", + "Slate", + "SlateCore", + "InventoryFrameworkUI" + ] + }, + { + "Name": "ActionRPGGameEditor", + "Type": "Editor", + "LoadingPhase": "Default", + "AdditionalDependencies": [ + "AbilityFramework", + "AbilityFrameworkEditor", + "InventoryFramework", + "Engine", + "AIModule", + "UMG", + "CoreUObject" + ] } ], "Plugins": [ { - "Name": "CodeView", + "Name": "ActorSequence", + "Enabled": true + }, + { + "Name": "AbilityFramework", + "Enabled": true + }, + { + "Name": "InventoryFramework", + "Enabled": true + }, + { + "Name": "InventoryFrameworkUI", + "Enabled": true + }, + { + "Name": "ActorSequenceEditor", + "Enabled": true + }, + { + "Name": "ImagePlate", + "Enabled": true + }, + { + "Name": "PerformanceMonitor", + "Enabled": true + }, + { + "Name": "OnlineFramework", + "Enabled": true + }, + { + "Name": "ActionRPGGameUI", "Enabled": true, - "Type": "Editor" + "BlacklistTargets": [ + "Server" + ] + }, + { + "Name": "GRPC", + "Enabled": true + }, + { + "Name": "SteamVR", + "Enabled": false + }, + { + "Name": "OculusVR", + "Enabled": false + }, + { + "Name": "Niagara", + "Enabled": true + }, + { + "Name": "SoundUtilities", + "Enabled": true + }, + { + "Name": "SoundVisualizations", + "Enabled": true + }, + { + "Name": "BlueprintStats", + "Enabled": true + }, + { + "Name": "LocationServicesBPLibrary", + "Enabled": false + }, + { + "Name": "WindowsDeviceProfileSelector", + "Enabled": true + }, + { + "Name": "AndroidDeviceProfileSelector", + "Enabled": false + }, + { + "Name": "IOSDeviceProfileSelector", + "Enabled": false + }, + { + "Name": "AndroidMedia", + "Enabled": false }, { - "Name": "MessagingDebugger", + "Name": "MobileLauncherProfileWizard", + "Enabled": false + }, + { + "Name": "MobilePatchingUtils", + "Enabled": false + }, + { + "Name": "AndroidMoviePlayer", + "Enabled": false + }, + { + "Name": "AppleMoviePlayer", + "Enabled": false + }, + { + "Name": "GoogleCloudMessaging", + "Enabled": false + }, + { + "Name": "OnlineSubsystemIOS", + "Enabled": false, + "SupportedTargetPlatforms": [ + "IOS", + "TVOS" + ] + }, + { + "Name": "OnlineSubsystemGooglePlay", + "Enabled": false, + "SupportedTargetPlatforms": [ + "Android" + ] + }, + { + "Name": "ApexDestruction", + "Enabled": true + }, + { + "Name": "AndroidPermission", + "Enabled": false + }, + { + "Name": "AppleARKit", + "Enabled": false + }, + { + "Name": "GLTFImporter", + "Enabled": true + }, + { + "Name": "SteamAudio", "Enabled": true, - "Type": "Editor" + "BlacklistTargets": [ + "Server", + "Client" + ] }, { - "Name": "ControlRig", + "Name": "ResonanceAudio", + "Enabled": false, + "BlacklistTargets": [ + "Server", + "Client" + ] + }, + { + "Name": "CodeView", + "Enabled": true + }, + { + "Name": "SignificanceManager", + "Enabled": true + }, + { + "Name": "CustomAnimNode", "Enabled": true, - "Type": "Editor" + "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/8901af6d589b40b68d763b44c9ced66c" }, { - "Name": "PerformanceMonitor", + "Name": "Substance", "Enabled": true, - "Type": "Editor" + "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/2f6439c2f9584f49809d9b13b16c2ba4", + "BlacklistTargets": [ + "Server", + "Client" + ] }, { - "Name": "ActorSequenceEditor", + "Name": "LiveLink", + "Enabled": true + }, + { + "Name": "ReplicationGraph", + "Enabled": true + }, + { + "Name": "NiagaraExtras", + "Enabled": true + }, + { + "Name": "MagicLeapMedia", + "Enabled": false, + "SupportedTargetPlatforms": [ + "Lumin" + ] + }, + { + "Name": "MagicLeapEmulator", + "Enabled": false, + "SupportedTargetPlatforms": [ + "Lumin" + ] + }, + { + "Name": "MagicLeap", + "Enabled": false, + "SupportedTargetPlatforms": [ + "Lumin" + ] + }, + { + "Name": "AppleVision", + "Enabled": false + }, + { + "Name": "RootMotionExtractor", "Enabled": true, - "Type": "Editor" + "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/4b450f82f56040338a4d5744b3eda4f9" } ], "TargetPlatforms": [ + "LinuxNoEditor", "WindowsNoEditor" ] } \ No newline at end of file diff --git a/Agones/Agones.uplugin b/Agones/Agones.uplugin new file mode 100644 index 0000000..ac3651f --- /dev/null +++ b/Agones/Agones.uplugin @@ -0,0 +1,25 @@ +{ + "FileVersion" : 3, + + "FriendlyName" : "Agones Plugin", + "Version" : 1, + "VersionName" : "1.0", + "CreatedBy" : "Epic Games, Inc.", + "CreatedByURL" : "http://epicgames.com", + "Description" : "Integration with Kuberenetes Agones.", + "Category" : "Dedicated Server", + "EnabledByDefault" : false, + + "Modules": [ + { + "Name": "Agones", + "Type": "Runtime" + } + ] + "Plugins": [ + { + "Name": "GRPC", + "Enabled": true + } + ] +} diff --git a/Agones/Resources/Icon128.png b/Agones/Resources/Icon128.png new file mode 100644 index 0000000..3033ae0 Binary files /dev/null and b/Agones/Resources/Icon128.png differ diff --git a/Agones/Source/Agones/Agones.Build.cs b/Agones/Source/Agones/Agones.Build.cs new file mode 100644 index 0000000..9e54b47 --- /dev/null +++ b/Agones/Source/Agones/Agones.Build.cs @@ -0,0 +1,80 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. +using System; +using System.IO; +using System.Text.RegularExpressions; + +namespace UnrealBuildTool.Rules +{ + public class Agones : ModuleRules + { + public Agones(ReadOnlyTargetRules Target) : base(Target) + { + PrivateIncludePaths.AddRange( + new string[] { + "Agones/Private", + } + ); + + PublicDefinitions.Add("GPR_FORBID_UNREACHABLE_CODE=1"); + PublicDefinitions.Add("GOOGLE_PROTOBUF_NO_RTTI=1"); + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "Projects", + "OpenSSL", + "zlib", + "GRPC" + } + ); + PublicIncludePathModuleNames.AddRange( + new string[] + { + "GRPC" + } + ); + + PrivateDependencyModuleNames.AddRange( + new string[] + { + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + } + ); + + + + if (Target.Type == TargetRules.TargetType.Server) + { + if (Target.Platform == UnrealTargetPlatform.Linux) + { + PublicDefinitions.Add("ENABLE_AGONES=1"); + + string BaseDirectory = System.IO.Path.GetFullPath(System.IO.Path.Combine(ModuleDirectory, "..")); + string SDKDirectory = System.IO.Path.Combine(BaseDirectory, "ThirdParty", "x86_64-unknown-linux-gnu"); + //PublicIncludePaths.Add(System.IO.Path.Combine(SDKDirectory, "include")); + + // PublicLibraryPaths.Add(SDKDirectory); + // PublicAdditionalLibraries.Add(System.IO.Path.Combine(SDKDirectory, "libagonessdk.a")); + PublicAdditionalLibraries.Add(System.IO.Path.Combine(SDKDirectory, "libgpr.a")); + PublicAdditionalLibraries.Add(System.IO.Path.Combine(SDKDirectory, "libgrpc.a")); + PublicAdditionalLibraries.Add(System.IO.Path.Combine(SDKDirectory, "libgrpc_unsecure.a")); + PublicAdditionalLibraries.Add(System.IO.Path.Combine(SDKDirectory, "libprotobuf.a")); + } + else + { + PublicDefinitions.Add("ENABLE_AGONES=0"); + } + } + else + { + PublicDefinitions.Add("ENABLE_AGONES=0"); + } + } + } +} diff --git a/Agones/Source/Agones/Private/Agones.cpp b/Agones/Source/Agones/Private/Agones.cpp new file mode 100644 index 0000000..3bf38f8 --- /dev/null +++ b/Agones/Source/Agones/Private/Agones.cpp @@ -0,0 +1,49 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. + +#include "IAgones.h" + +#if ENABLE_AGONES +#include "grpc/support/time.h" +#include "grpc++/grpc++.h" +#include "sdk.h" +#endif + +class FAgones : public IAgones +{ +#if ENABLE_AGONES + + agones::SDK* AgonesSDK; +#endif + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; + +IMPLEMENT_MODULE( FAgones, Agones) + + + +void FAgones::StartupModule() +{ +#if ENABLE_AGONES + + grpc::string out = grpc::Version(); + FString ver = FString(ANSI_TO_TCHAR(out.c_str())); + UE_LOG(LogTemp, Warning, TEXT("FGRPC::StartupModule Version: %s "), *ver); + AgonesSDK = new agones::SDK(); +#endif +} + + +void FAgones::ShutdownModule() +{ +#if ENABLE_AGONES + //if (AgonesSDK) + //{ + // delete AgonesSDK; + // AgonesSDK = nullptr; + //} +#endif + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} diff --git a/Agones/Source/Agones/Private/sdk.cc b/Agones/Source/Agones/Private/sdk.cc new file mode 100644 index 0000000..4cc211f --- /dev/null +++ b/Agones/Source/Agones/Private/sdk.cc @@ -0,0 +1,62 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "sdk.h" +#include "sdk.pb.h" + +namespace agones { + + const int port = 59357; + + SDK::SDK() { + channel = grpc::CreateChannel("localhost:" + std::to_string(port), grpc::InsecureChannelCredentials()); + } + + bool SDK::Connect() { + if (!channel->WaitForConnected(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(30, GPR_TIMESPAN)))) { + return false; + } + + stub = stable::agones::dev::sdk::SDK::NewStub(channel); + + // make the health connection + stable::agones::dev::sdk::Empty response; + health = stub->Health(new grpc::ClientContext(), &response); + + return true; + } + + grpc::Status SDK::Ready() { + grpc::ClientContext *context = new grpc::ClientContext(); + context->set_deadline(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(30, GPR_TIMESPAN))); + stable::agones::dev::sdk::Empty request; + stable::agones::dev::sdk::Empty response; + + return stub->Ready(context, request, &response); + } + + bool SDK::Health() { + stable::agones::dev::sdk::Empty request; + return health->Write(request); + } + + grpc::Status SDK::Shutdown() { + grpc::ClientContext *context = new grpc::ClientContext(); + context->set_deadline(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(30, GPR_TIMESPAN))); + stable::agones::dev::sdk::Empty request; + stable::agones::dev::sdk::Empty response; + + return stub->Shutdown(context, request, &response); + } +} \ No newline at end of file diff --git a/Agones/Source/Agones/Private/sdk.grpc.pb.cc b/Agones/Source/Agones/Private/sdk.grpc.pb.cc new file mode 100644 index 0000000..664bf89 --- /dev/null +++ b/Agones/Source/Agones/Private/sdk.grpc.pb.cc @@ -0,0 +1,136 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This code was autogenerated. Do not edit directly. +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: sdk.proto + +#include "sdk.pb.h" +#include "sdk.grpc.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +namespace stable { +namespace agones { +namespace dev { +namespace sdk { + +static const char* SDK_method_names[] = { + "/stable.agones.dev.sdk.SDK/Ready", + "/stable.agones.dev.sdk.SDK/Shutdown", + "/stable.agones.dev.sdk.SDK/Health", +}; + +std::unique_ptr< SDK::Stub> SDK::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { + std::unique_ptr< SDK::Stub> stub(new SDK::Stub(channel)); + return stub; +} + +SDK::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel) + : channel_(channel), rpcmethod_Ready_(SDK_method_names[0], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Shutdown_(SDK_method_names[1], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Health_(SDK_method_names[2], ::grpc::internal::RpcMethod::CLIENT_STREAMING, channel) + {} + +::grpc::Status SDK::Stub::Ready(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::stable::agones::dev::sdk::Empty* response) { + return ::grpc::internal::BlockingUnaryCall(channel_.get(), rpcmethod_Ready_, context, request, response); +} + +::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* SDK::Stub::AsyncReadyRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), cq, rpcmethod_Ready_, context, request, true); +} + +::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* SDK::Stub::PrepareAsyncReadyRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), cq, rpcmethod_Ready_, context, request, false); +} + +::grpc::Status SDK::Stub::Shutdown(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::stable::agones::dev::sdk::Empty* response) { + return ::grpc::internal::BlockingUnaryCall(channel_.get(), rpcmethod_Shutdown_, context, request, response); +} + +::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* SDK::Stub::AsyncShutdownRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), cq, rpcmethod_Shutdown_, context, request, true); +} + +::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* SDK::Stub::PrepareAsyncShutdownRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), cq, rpcmethod_Shutdown_, context, request, false); +} + +::grpc::ClientWriter< ::stable::agones::dev::sdk::Empty>* SDK::Stub::HealthRaw(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response) { + return ::grpc::internal::ClientWriterFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), rpcmethod_Health_, context, response); +} + +::grpc::ClientAsyncWriter< ::stable::agones::dev::sdk::Empty>* SDK::Stub::AsyncHealthRaw(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response, ::grpc::CompletionQueue* cq, void* tag) { + return ::grpc::internal::ClientAsyncWriterFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), cq, rpcmethod_Health_, context, response, true, tag); +} + +::grpc::ClientAsyncWriter< ::stable::agones::dev::sdk::Empty>* SDK::Stub::PrepareAsyncHealthRaw(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncWriterFactory< ::stable::agones::dev::sdk::Empty>::Create(channel_.get(), cq, rpcmethod_Health_, context, response, false, nullptr); +} + +SDK::Service::Service() { + AddMethod(new ::grpc::internal::RpcServiceMethod( + SDK_method_names[0], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< SDK::Service, ::stable::agones::dev::sdk::Empty, ::stable::agones::dev::sdk::Empty>( + std::mem_fn(&SDK::Service::Ready), this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + SDK_method_names[1], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< SDK::Service, ::stable::agones::dev::sdk::Empty, ::stable::agones::dev::sdk::Empty>( + std::mem_fn(&SDK::Service::Shutdown), this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + SDK_method_names[2], + ::grpc::internal::RpcMethod::CLIENT_STREAMING, + new ::grpc::internal::ClientStreamingHandler< SDK::Service, ::stable::agones::dev::sdk::Empty, ::stable::agones::dev::sdk::Empty>( + std::mem_fn(&SDK::Service::Health), this))); +} + +SDK::Service::~Service() { +} + +::grpc::Status SDK::Service::Ready(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::Empty* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status SDK::Service::Shutdown(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::Empty* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status SDK::Service::Health(::grpc::ServerContext* context, ::grpc::ServerReader< ::stable::agones::dev::sdk::Empty>* reader, ::stable::agones::dev::sdk::Empty* response) { + (void) context; + (void) reader; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + + +} // namespace stable +} // namespace agones +} // namespace dev +} // namespace sdk + diff --git a/Agones/Source/Agones/Private/sdk.pb.cc b/Agones/Source/Agones/Private/sdk.pb.cc new file mode 100644 index 0000000..cf68357 --- /dev/null +++ b/Agones/Source/Agones/Private/sdk.pb.cc @@ -0,0 +1,342 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This code was autogenerated. Do not edit directly. +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: sdk.proto + +#include "sdk.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +// This is a temporary google only hack +#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS +#include "third_party/protobuf/version.h" +#endif +// @@protoc_insertion_point(includes) +namespace stable { +namespace agones { +namespace dev { +namespace sdk { +class EmptyDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _Empty_default_instance_; +} // namespace sdk +} // namespace dev +} // namespace agones +} // namespace stable +namespace protobuf_sdk_2eproto { +void InitDefaultsEmptyImpl() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + +#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS + ::google::protobuf::internal::InitProtobufDefaultsForceUnique(); +#else + ::google::protobuf::internal::InitProtobufDefaults(); +#endif // GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS + { + void* ptr = &::stable::agones::dev::sdk::_Empty_default_instance_; + new (ptr) ::stable::agones::dev::sdk::Empty(); + ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); + } + ::stable::agones::dev::sdk::Empty::InitAsDefaultInstance(); +} + +void InitDefaultsEmpty() { + static GOOGLE_PROTOBUF_DECLARE_ONCE(once); + ::google::protobuf::GoogleOnceInit(&once, &InitDefaultsEmptyImpl); +} + +::google::protobuf::Metadata file_level_metadata[1]; + +const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::stable::agones::dev::sdk::Empty, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ +}; +static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(::stable::agones::dev::sdk::Empty)}, +}; + +static ::google::protobuf::Message const * const file_default_instances[] = { + reinterpret_cast(&::stable::agones::dev::sdk::_Empty_default_instance_), +}; + +void protobuf_AssignDescriptors() { + AddDescriptors(); + ::google::protobuf::MessageFactory* factory = NULL; + AssignDescriptors( + "sdk.proto", schemas, file_default_instances, TableStruct::offsets, factory, + file_level_metadata, NULL, NULL); +} + +void protobuf_AssignDescriptorsOnce() { + static GOOGLE_PROTOBUF_DECLARE_ONCE(once); + ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors); +} + +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD; +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); +} + +void AddDescriptorsImpl() { + InitDefaults(); + static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + "\n\tsdk.proto\022\025stable.agones.dev.sdk\"\007\n\005Em" + "pty2\340\001\n\003SDK\022E\n\005Ready\022\034.stable.agones.dev" + ".sdk.Empty\032\034.stable.agones.dev.sdk.Empty" + "\"\000\022H\n\010Shutdown\022\034.stable.agones.dev.sdk.E" + "mpty\032\034.stable.agones.dev.sdk.Empty\"\000\022H\n\006" + "Health\022\034.stable.agones.dev.sdk.Empty\032\034.s" + "table.agones.dev.sdk.Empty\"\000(\001B\005Z\003sdkb\006p" + "roto3" + }; + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + descriptor, 285); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "sdk.proto", &protobuf_RegisterTypes); +} + +void AddDescriptors() { + static GOOGLE_PROTOBUF_DECLARE_ONCE(once); + ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl); +} +// Force AddDescriptors() to be called at dynamic initialization time. +struct StaticDescriptorInitializer { + StaticDescriptorInitializer() { + AddDescriptors(); + } +} static_descriptor_initializer; +} // namespace protobuf_sdk_2eproto +namespace stable { +namespace agones { +namespace dev { +namespace sdk { + +// =================================================================== + +void Empty::InitAsDefaultInstance() { +} +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 + +Empty::Empty() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) { + ::protobuf_sdk_2eproto::InitDefaultsEmpty(); + } + SharedCtor(); + // @@protoc_insertion_point(constructor:stable.agones.dev.sdk.Empty) +} +Empty::Empty(const Empty& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL), + _cached_size_(0) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + // @@protoc_insertion_point(copy_constructor:stable.agones.dev.sdk.Empty) +} + +void Empty::SharedCtor() { + _cached_size_ = 0; +} + +Empty::~Empty() { + // @@protoc_insertion_point(destructor:stable.agones.dev.sdk.Empty) + SharedDtor(); +} + +void Empty::SharedDtor() { +} + +void Empty::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* Empty::descriptor() { + ::protobuf_sdk_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_sdk_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +} + +const Empty& Empty::default_instance() { + ::protobuf_sdk_2eproto::InitDefaultsEmpty(); + return *internal_default_instance(); +} + +Empty* Empty::New(::google::protobuf::Arena* arena) const { + Empty* n = new Empty; + if (arena != NULL) { + arena->Own(n); + } + return n; +} + +void Empty::Clear() { +// @@protoc_insertion_point(message_clear_start:stable.agones.dev.sdk.Empty) + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _internal_metadata_.Clear(); +} + +bool Empty::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:stable.agones.dev.sdk.Empty) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + } +success: + // @@protoc_insertion_point(parse_success:stable.agones.dev.sdk.Empty) + return true; +failure: + // @@protoc_insertion_point(parse_failure:stable.agones.dev.sdk.Empty) + return false; +#undef DO_ +} + +void Empty::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:stable.agones.dev.sdk.Empty) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); + } + // @@protoc_insertion_point(serialize_end:stable.agones.dev.sdk.Empty) +} + +::google::protobuf::uint8* Empty::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { + (void)deterministic; // Unused + // @@protoc_insertion_point(serialize_to_array_start:stable.agones.dev.sdk.Empty) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:stable.agones.dev.sdk.Empty) + return target; +} + +size_t Empty::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:stable.agones.dev.sdk.Empty) + size_t total_size = 0; + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); + } + int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = cached_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void Empty::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:stable.agones.dev.sdk.Empty) + GOOGLE_DCHECK_NE(&from, this); + const Empty* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); + if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:stable.agones.dev.sdk.Empty) + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:stable.agones.dev.sdk.Empty) + MergeFrom(*source); + } +} + +void Empty::MergeFrom(const Empty& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:stable.agones.dev.sdk.Empty) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + +} + +void Empty::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:stable.agones.dev.sdk.Empty) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Empty::CopyFrom(const Empty& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:stable.agones.dev.sdk.Empty) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Empty::IsInitialized() const { + return true; +} + +void Empty::Swap(Empty* other) { + if (other == this) return; + InternalSwap(other); +} +void Empty::InternalSwap(Empty* other) { + using std::swap; + _internal_metadata_.Swap(&other->_internal_metadata_); + swap(_cached_size_, other->_cached_size_); +} + +::google::protobuf::Metadata Empty::GetMetadata() const { + protobuf_sdk_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_sdk_2eproto::file_level_metadata[kIndexInFileMessages]; +} + + +// @@protoc_insertion_point(namespace_scope) +} // namespace sdk +} // namespace dev +} // namespace agones +} // namespace stable + +// @@protoc_insertion_point(global_scope) diff --git a/Agones/Source/Agones/Public/IAgones.h b/Agones/Source/Agones/Public/IAgones.h new file mode 100644 index 0000000..f686a8e --- /dev/null +++ b/Agones/Source/Agones/Public/IAgones.h @@ -0,0 +1,38 @@ +// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "ModuleManager.h" + + +/** + * The public interface to this module. In most cases, this interface is only public to sibling modules + * within this plugin. + */ +class IAgones : public IModuleInterface +{ + +public: + + /** + * Singleton-like access to this module's interface. This is just for convenience! + * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. + * + * @return Returns singleton instance, loading the module on demand if needed + */ + static inline IAgones& Get() + { + return FModuleManager::LoadModuleChecked< IAgones >( "Agones" ); + } + + /** + * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. + * + * @return True if the module is loaded and ready to use + */ + static inline bool IsAvailable() + { + return FModuleManager::Get().IsModuleLoaded( "Agones" ); + } +}; + diff --git a/Agones/Source/Agones/Public/sdk.grpc.pb.h b/Agones/Source/Agones/Public/sdk.grpc.pb.h new file mode 100644 index 0000000..0706399 --- /dev/null +++ b/Agones/Source/Agones/Public/sdk.grpc.pb.h @@ -0,0 +1,307 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: sdk.proto +// Original file comments: +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#ifndef GRPC_sdk_2eproto__INCLUDED +#define GRPC_sdk_2eproto__INCLUDED +#define GPR_FORBID_UNREACHABLE_CODE 1 +#define GOOGLE_PROTOBUF_NO_RTTI 1 +#include "sdk.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace grpc { +class CompletionQueue; +class Channel; +class ServerCompletionQueue; +class ServerContext; +} // namespace grpc + +namespace stable { +namespace agones { +namespace dev { +namespace sdk { + +// SDK service to be used in the GameServer SDK to the Pod Sidecar +class SDK final { + public: + static constexpr char const* service_full_name() { + return "stable.agones.dev.sdk.SDK"; + } + class StubInterface { + public: + virtual ~StubInterface() {} + // Call when the GameServer is ready + virtual ::grpc::Status Ready(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::stable::agones::dev::sdk::Empty* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>> AsyncReady(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>>(AsyncReadyRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>> PrepareAsyncReady(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>>(PrepareAsyncReadyRaw(context, request, cq)); + } + // Call when the GmaeServer is shutting down + virtual ::grpc::Status Shutdown(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::stable::agones::dev::sdk::Empty* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>> AsyncShutdown(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>>(AsyncShutdownRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>> PrepareAsyncShutdown(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>>(PrepareAsyncShutdownRaw(context, request, cq)); + } + // Send a Empty every d Duration to declare that this GameSever is healthy + std::unique_ptr< ::grpc::ClientWriterInterface< ::stable::agones::dev::sdk::Empty>> Health(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response) { + return std::unique_ptr< ::grpc::ClientWriterInterface< ::stable::agones::dev::sdk::Empty>>(HealthRaw(context, response)); + } + std::unique_ptr< ::grpc::ClientAsyncWriterInterface< ::stable::agones::dev::sdk::Empty>> AsyncHealth(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response, ::grpc::CompletionQueue* cq, void* tag) { + return std::unique_ptr< ::grpc::ClientAsyncWriterInterface< ::stable::agones::dev::sdk::Empty>>(AsyncHealthRaw(context, response, cq, tag)); + } + std::unique_ptr< ::grpc::ClientAsyncWriterInterface< ::stable::agones::dev::sdk::Empty>> PrepareAsyncHealth(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncWriterInterface< ::stable::agones::dev::sdk::Empty>>(PrepareAsyncHealthRaw(context, response, cq)); + } + private: + virtual ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>* AsyncReadyRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>* PrepareAsyncReadyRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>* AsyncShutdownRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::stable::agones::dev::sdk::Empty>* PrepareAsyncShutdownRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientWriterInterface< ::stable::agones::dev::sdk::Empty>* HealthRaw(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response) = 0; + virtual ::grpc::ClientAsyncWriterInterface< ::stable::agones::dev::sdk::Empty>* AsyncHealthRaw(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response, ::grpc::CompletionQueue* cq, void* tag) = 0; + virtual ::grpc::ClientAsyncWriterInterface< ::stable::agones::dev::sdk::Empty>* PrepareAsyncHealthRaw(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response, ::grpc::CompletionQueue* cq) = 0; + }; + class Stub final : public StubInterface { + public: + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel); + ::grpc::Status Ready(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::stable::agones::dev::sdk::Empty* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>> AsyncReady(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>>(AsyncReadyRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>> PrepareAsyncReady(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>>(PrepareAsyncReadyRaw(context, request, cq)); + } + ::grpc::Status Shutdown(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::stable::agones::dev::sdk::Empty* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>> AsyncShutdown(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>>(AsyncShutdownRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>> PrepareAsyncShutdown(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>>(PrepareAsyncShutdownRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientWriter< ::stable::agones::dev::sdk::Empty>> Health(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response) { + return std::unique_ptr< ::grpc::ClientWriter< ::stable::agones::dev::sdk::Empty>>(HealthRaw(context, response)); + } + std::unique_ptr< ::grpc::ClientAsyncWriter< ::stable::agones::dev::sdk::Empty>> AsyncHealth(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response, ::grpc::CompletionQueue* cq, void* tag) { + return std::unique_ptr< ::grpc::ClientAsyncWriter< ::stable::agones::dev::sdk::Empty>>(AsyncHealthRaw(context, response, cq, tag)); + } + std::unique_ptr< ::grpc::ClientAsyncWriter< ::stable::agones::dev::sdk::Empty>> PrepareAsyncHealth(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncWriter< ::stable::agones::dev::sdk::Empty>>(PrepareAsyncHealthRaw(context, response, cq)); + } + + private: + std::shared_ptr< ::grpc::ChannelInterface> channel_; + ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* AsyncReadyRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* PrepareAsyncReadyRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* AsyncShutdownRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::stable::agones::dev::sdk::Empty>* PrepareAsyncShutdownRaw(::grpc::ClientContext* context, const ::stable::agones::dev::sdk::Empty& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientWriter< ::stable::agones::dev::sdk::Empty>* HealthRaw(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response) override; + ::grpc::ClientAsyncWriter< ::stable::agones::dev::sdk::Empty>* AsyncHealthRaw(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response, ::grpc::CompletionQueue* cq, void* tag) override; + ::grpc::ClientAsyncWriter< ::stable::agones::dev::sdk::Empty>* PrepareAsyncHealthRaw(::grpc::ClientContext* context, ::stable::agones::dev::sdk::Empty* response, ::grpc::CompletionQueue* cq) override; + const ::grpc::internal::RpcMethod rpcmethod_Ready_; + const ::grpc::internal::RpcMethod rpcmethod_Shutdown_; + const ::grpc::internal::RpcMethod rpcmethod_Health_; + }; + static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + + class Service : public ::grpc::Service { + public: + Service(); + virtual ~Service(); + // Call when the GameServer is ready + virtual ::grpc::Status Ready(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::Empty* response); + // Call when the GmaeServer is shutting down + virtual ::grpc::Status Shutdown(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::Empty* response); + // Send a Empty every d Duration to declare that this GameSever is healthy + virtual ::grpc::Status Health(::grpc::ServerContext* context, ::grpc::ServerReader< ::stable::agones::dev::sdk::Empty>* reader, ::stable::agones::dev::sdk::Empty* response); + }; + template + class WithAsyncMethod_Ready : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithAsyncMethod_Ready() { + ::grpc::Service::MarkMethodAsync(0); + } + ~WithAsyncMethod_Ready() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Ready(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestReady(::grpc::ServerContext* context, ::stable::agones::dev::sdk::Empty* request, ::grpc::ServerAsyncResponseWriter< ::stable::agones::dev::sdk::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_Shutdown : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithAsyncMethod_Shutdown() { + ::grpc::Service::MarkMethodAsync(1); + } + ~WithAsyncMethod_Shutdown() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Shutdown(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestShutdown(::grpc::ServerContext* context, ::stable::agones::dev::sdk::Empty* request, ::grpc::ServerAsyncResponseWriter< ::stable::agones::dev::sdk::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_Health : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithAsyncMethod_Health() { + ::grpc::Service::MarkMethodAsync(2); + } + ~WithAsyncMethod_Health() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Health(::grpc::ServerContext* context, ::grpc::ServerReader< ::stable::agones::dev::sdk::Empty>* reader, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestHealth(::grpc::ServerContext* context, ::grpc::ServerAsyncReader< ::stable::agones::dev::sdk::Empty, ::stable::agones::dev::sdk::Empty>* reader, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncClientStreaming(2, context, reader, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_Ready > > AsyncService; + template + class WithGenericMethod_Ready : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithGenericMethod_Ready() { + ::grpc::Service::MarkMethodGeneric(0); + } + ~WithGenericMethod_Ready() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Ready(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_Shutdown : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithGenericMethod_Shutdown() { + ::grpc::Service::MarkMethodGeneric(1); + } + ~WithGenericMethod_Shutdown() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Shutdown(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_Health : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithGenericMethod_Health() { + ::grpc::Service::MarkMethodGeneric(2); + } + ~WithGenericMethod_Health() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Health(::grpc::ServerContext* context, ::grpc::ServerReader< ::stable::agones::dev::sdk::Empty>* reader, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithStreamedUnaryMethod_Ready : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithStreamedUnaryMethod_Ready() { + ::grpc::Service::MarkMethodStreamed(0, + new ::grpc::internal::StreamedUnaryHandler< ::stable::agones::dev::sdk::Empty, ::stable::agones::dev::sdk::Empty>(std::bind(&WithStreamedUnaryMethod_Ready::StreamedReady, this, std::placeholders::_1, std::placeholders::_2))); + } + ~WithStreamedUnaryMethod_Ready() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status Ready(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedReady(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::stable::agones::dev::sdk::Empty,::stable::agones::dev::sdk::Empty>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_Shutdown : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithStreamedUnaryMethod_Shutdown() { + ::grpc::Service::MarkMethodStreamed(1, + new ::grpc::internal::StreamedUnaryHandler< ::stable::agones::dev::sdk::Empty, ::stable::agones::dev::sdk::Empty>(std::bind(&WithStreamedUnaryMethod_Shutdown::StreamedShutdown, this, std::placeholders::_1, std::placeholders::_2))); + } + ~WithStreamedUnaryMethod_Shutdown() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status Shutdown(::grpc::ServerContext* context, const ::stable::agones::dev::sdk::Empty* request, ::stable::agones::dev::sdk::Empty* response) final override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedShutdown(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::stable::agones::dev::sdk::Empty,::stable::agones::dev::sdk::Empty>* server_unary_streamer) = 0; + }; + typedef WithStreamedUnaryMethod_Ready > StreamedUnaryService; + typedef Service SplitStreamedService; + typedef WithStreamedUnaryMethod_Ready > StreamedService; +}; + +} // namespace sdk +} // namespace dev +} // namespace agones +} // namespace stable + + +#endif // GRPC_sdk_2eproto__INCLUDED diff --git a/Agones/Source/Agones/Public/sdk.h b/Agones/Source/Agones/Public/sdk.h new file mode 100644 index 0000000..313120b --- /dev/null +++ b/Agones/Source/Agones/Public/sdk.h @@ -0,0 +1,50 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#define GPR_FORBID_UNREACHABLE_CODE 1 +#define GOOGLE_PROTOBUF_NO_RTTI 1 +#include +#include "sdk.grpc.pb.h" + +namespace agones { + + // The Agones SDK + class SDK { + public: + // Creates a new instance of the SDK. + // Does not connect to anything. + SDK(); + + // Must be called before any other functions on the SDK. + // This will attempt to do a handshake with the sdk server, timing out + // after 30 seconds. + // Returns true if the connection was successful, false if not. + bool Connect(); + + // Marks the Game Server as ready to receive connections + grpc::Status Ready(); + + // Send Health ping. This is a synchronous request. + bool Health(); + + // Marks the Game Server as ready to shutdown + grpc::Status Shutdown(); + + ~SDK(); + + private: + std::shared_ptr channel; + std::unique_ptr stub; + std::unique_ptr< ::grpc::ClientWriter< ::stable::agones::dev::sdk::Empty>> health; + }; +} diff --git a/Agones/Source/Agones/Public/sdk.pb.h b/Agones/Source/Agones/Public/sdk.pb.h new file mode 100644 index 0000000..812f0cd --- /dev/null +++ b/Agones/Source/Agones/Public/sdk.pb.h @@ -0,0 +1,202 @@ +// Copyright 2018 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This code was autogenerated. Do not edit directly. +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: sdk.proto + +#ifndef PROTOBUF_sdk_2eproto__INCLUDED +#define PROTOBUF_sdk_2eproto__INCLUDED + +#include + +#include + +#define GPR_FORBID_UNREACHABLE_CODE 1 +#define GOOGLE_PROTOBUF_NO_RTTI 1 + + +#if GOOGLE_PROTOBUF_VERSION < 3005000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3005000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +// @@protoc_insertion_point(includes) + +namespace protobuf_sdk_2eproto { +// Internal implementation detail -- do not use these members. +struct TableStruct { + static const ::google::protobuf::internal::ParseTableField entries[]; + static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; + static const ::google::protobuf::internal::ParseTable schema[1]; + static const ::google::protobuf::internal::FieldMetadata field_metadata[]; + static const ::google::protobuf::internal::SerializationTable serialization_table[]; + static const ::google::protobuf::uint32 offsets[]; +}; +void AddDescriptors(); +void InitDefaultsEmptyImpl(); +void InitDefaultsEmpty(); +inline void InitDefaults() { + InitDefaultsEmpty(); +} +} // namespace protobuf_sdk_2eproto +namespace stable { +namespace agones { +namespace dev { +namespace sdk { +class Empty; +class EmptyDefaultTypeInternal; +extern EmptyDefaultTypeInternal _Empty_default_instance_; +} // namespace sdk +} // namespace dev +} // namespace agones +} // namespace stable +namespace stable { +namespace agones { +namespace dev { +namespace sdk { + +// =================================================================== + +class Empty : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:stable.agones.dev.sdk.Empty) */ { + public: + Empty(); + virtual ~Empty(); + + Empty(const Empty& from); + + inline Empty& operator=(const Empty& from) { + CopyFrom(from); + return *this; + } + #if LANG_CXX11 + Empty(Empty&& from) noexcept + : Empty() { + *this = ::std::move(from); + } + + inline Empty& operator=(Empty&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + #endif + static const ::google::protobuf::Descriptor* descriptor(); + static const Empty& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const Empty* internal_default_instance() { + return reinterpret_cast( + &_Empty_default_instance_); + } + static PROTOBUF_CONSTEXPR int const kIndexInFileMessages = + 0; + + void Swap(Empty* other); + friend void swap(Empty& a, Empty& b) { + a.Swap(&b); + } + + // implements Message ---------------------------------------------- + + inline Empty* New() const PROTOBUF_FINAL { return New(NULL); } + + Empty* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL; + void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL; + void CopyFrom(const Empty& from); + void MergeFrom(const Empty& from); + void Clear() PROTOBUF_FINAL; + bool IsInitialized() const PROTOBUF_FINAL; + + size_t ByteSizeLong() const PROTOBUF_FINAL; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL; + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL; + int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const PROTOBUF_FINAL; + void InternalSwap(Empty* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return NULL; + } + inline void* MaybeArenaPtr() const { + return NULL; + } + public: + + ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // @@protoc_insertion_point(class_scope:stable.agones.dev.sdk.Empty) + private: + + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; + mutable int _cached_size_; + friend struct ::protobuf_sdk_2eproto::TableStruct; + friend void ::protobuf_sdk_2eproto::InitDefaultsEmptyImpl(); +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// Empty + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +} // namespace sdk +} // namespace dev +} // namespace agones +} // namespace stable + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_sdk_2eproto__INCLUDED diff --git a/Config/DefaultEditor.ini b/Config/DefaultEditor.ini index c2cf80a..b229537 100644 --- a/Config/DefaultEditor.ini +++ b/Config/DefaultEditor.ini @@ -1,23 +1,10 @@ -[UnrealEd.SimpleMap] -SimpleMapName=/Game/ThirdPerson/Maps/ThirdPersonExampleMap - [EditoronlyBP] bAllowClassAndBlueprintPinMatching=true bReplaceBlueprintWithClass= true bDontLoadBlueprintOutsideEditor= true bBlueprintIsNotBlueprintType= true -[/Script/Engine.AssetViewerSettings] --Profiles=(ProfileName="Default",DirectionalLightIntensity=2.620000,DirectionalLightColor=(R=0.990000,G=0.839850,B=0.732600,A=1.000000),SkyLightIntensity=0.880000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=True,EnvironmentCubeMap=TextureCube'/Engine/EngineSky/EpicQuadPanorama_CC+EV1.EpicQuadPanorama_CC+EV1',PostProcessingSettings=(bOverride_WhiteTemp=True,bOverride_WhiteTint=False,bOverride_ColorSaturation=True,bOverride_ColorContrast=True,bOverride_ColorGamma=True,bOverride_ColorGain=True,bOverride_ColorOffset=True,bOverride_FilmWhitePoint=False,bOverride_FilmSaturation=False,bOverride_FilmChannelMixerRed=False,bOverride_FilmChannelMixerGreen=False,bOverride_FilmChannelMixerBlue=False,bOverride_FilmContrast=False,bOverride_FilmDynamicRange=False,bOverride_FilmHealAmount=False,bOverride_FilmToeAmount=False,bOverride_FilmShadowTint=False,bOverride_FilmShadowTintBlend=False,bOverride_FilmShadowTintAmount=False,bOverride_FilmSlope=True,bOverride_FilmToe=True,bOverride_FilmShoulder=True,bOverride_FilmBlackClip=True,bOverride_FilmWhiteClip=True,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomIntensity=True,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_AutoExposureMethod=True,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=True,bOverride_AutoExposureMaxBrightness=True,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=True,bOverride_HistogramLogMin=True,bOverride_HistogramLogMax=True,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=True,bOverride_GrainIntensity=False,bOverride_GrainJitter=False,bOverride_AmbientOcclusionIntensity=True,bOverride_AmbientOcclusionStaticFraction=True,bOverride_AmbientOcclusionRadius=True,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionDistance=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=True,bOverride_AmbientOcclusionBias=True,bOverride_AmbientOcclusionQuality=True,bOverride_AmbientOcclusionMipBlend=True,bOverride_AmbientOcclusionMipScale=True,bOverride_AmbientOcclusionMipThreshold=True,bOverride_LPVIntensity=False,bOverride_LPVDirectionalOcclusionIntensity=False,bOverride_LPVDirectionalOcclusionRadius=False,bOverride_LPVDiffuseOcclusionExponent=False,bOverride_LPVSpecularOcclusionExponent=False,bOverride_LPVDiffuseOcclusionIntensity=False,bOverride_LPVSpecularOcclusionIntensity=False,bOverride_LPVSize=False,bOverride_LPVSecondaryOcclusionIntensity=False,bOverride_LPVSecondaryBounceIntensity=False,bOverride_LPVGeometryVolumeBias=False,bOverride_LPVVplInjectionBias=False,bOverride_LPVEmissiveInjectionIntensity=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=True,bOverride_ColorGradingLUT=True,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=True,bOverride_DepthOfFieldMaxBokehSize=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_DepthOfFieldMethod=True,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldBokehShape=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldColorThreshold=False,bOverride_DepthOfFieldSizeThreshold=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ScreenPercentage=False,bOverride_ScreenSpaceReflectionIntensity=True,bOverride_ScreenSpaceReflectionQuality=True,bOverride_ScreenSpaceReflectionMaxRoughness=True,bOverride_ScreenSpaceReflectionRoughnessScale=False,WhiteTemp=6700.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000),ColorOffset=(X=0.005000,Y=0.005000,Z=0.005000),FilmWhitePoint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTintBlend=0.500000,FilmShadowTintAmount=0.000000,FilmSaturation=1.000000,FilmChannelMixerRed=(R=1.000000,G=0.000000,B=0.000000,A=1.000000),FilmChannelMixerGreen=(R=0.000000,G=1.000000,B=0.000000,A=1.000000),FilmChannelMixerBlue=(R=0.000000,G=0.000000,B=1.000000,A=1.000000),FilmContrast=0.030000,FilmToeAmount=1.000000,FilmHealAmount=0.180000,FilmDynamicRange=4.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,BloomIntensity=1.000000,BloomThreshold=1.000000,BloomSizeScale=4.000000,Bloom1Size=1.000000,Bloom2Size=4.000000,Bloom3Size=16.000000,Bloom4Size=32.000000,Bloom5Size=64.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom2Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom3Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom4Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom5Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom6Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMaskIntensity=1.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMask=None,LPVIntensity=1.000000,LPVVplInjectionBias=0.640000,LPVSize=5312.000000,LPVSecondaryOcclusionIntensity=0.000000,LPVSecondaryBounceIntensity=0.000000,LPVGeometryVolumeBias=0.384000,LPVEmissiveInjectionIntensity=1.000000,LPVDirectionalOcclusionIntensity=0.000000,LPVDirectionalOcclusionRadius=8.000000,LPVDiffuseOcclusionExponent=1.000000,LPVSpecularOcclusionExponent=7.000000,LPVDiffuseOcclusionIntensity=1.000000,LPVSpecularOcclusionIntensity=1.000000,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,AutoExposureMethod=AEM_Histogram,AutoExposureLowPercent=80.000000,AutoExposureHighPercent=98.300003,AutoExposureMinBrightness=1.000000,AutoExposureMaxBrightness=1.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,AutoExposureBias=0.330000,HistogramLogMin=-8.000000,HistogramLogMax=4.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.161468,GrainJitter=0.000000,GrainIntensity=0.000000,AmbientOcclusionIntensity=1.000000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=73.477997,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionDistance=80.000000,AmbientOcclusionPower=1.200000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=100.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,ColorGradingIntensity=0.000000,ColorGradingLUT=Texture2D'/Engine/EditorResources/RGBTable16x1_AssetViewer.RGBTable16x1_AssetViewer',DepthOfFieldMethod=DOFM_BokehDOF,bMobileHQGaussian=False,DepthOfFieldFstop=4.000000,DepthOfFieldSensorWidth=24.576000,DepthOfFieldFocalDistance=1000.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldMaxBokehSize=15.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldBokehShape=None,DepthOfFieldOcclusion=0.400000,DepthOfFieldColorThreshold=1.000000,DepthOfFieldSizeThreshold=0.080000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurPerObjectSize=0.500000,ScreenPercentage=100.000000,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=100.000000,ScreenSpaceReflectionMaxRoughness=1.000000,WeightedBlendables=(Array=),Blendables=),bPostProcessingEnabled=True,LightingRigRotation=109.389069,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-40.000000,Yaw=-67.500000,Roll=0.000000)) --Profiles=(ProfileName="Default",DirectionalLightIntensity=2.620000,DirectionalLightColor=(R=0.990000,G=0.839850,B=0.732600,A=1.000000),SkyLightIntensity=0.880000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=True,EnvironmentCubeMap=TextureCube'/Engine/EngineSky/EpicQuadPanorama_CC+EV1.EpicQuadPanorama_CC+EV1',PostProcessingSettings=(bOverride_WhiteTemp=True,bOverride_WhiteTint=False,bOverride_ColorSaturation=True,bOverride_ColorContrast=True,bOverride_ColorGamma=True,bOverride_ColorGain=True,bOverride_ColorOffset=True,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_FilmWhitePoint=False,bOverride_FilmSaturation=False,bOverride_FilmChannelMixerRed=False,bOverride_FilmChannelMixerGreen=False,bOverride_FilmChannelMixerBlue=False,bOverride_FilmContrast=False,bOverride_FilmDynamicRange=False,bOverride_FilmHealAmount=False,bOverride_FilmToeAmount=False,bOverride_FilmShadowTint=False,bOverride_FilmShadowTintBlend=False,bOverride_FilmShadowTintAmount=False,bOverride_FilmSlope=True,bOverride_FilmToe=True,bOverride_FilmShoulder=True,bOverride_FilmBlackClip=True,bOverride_FilmWhiteClip=True,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomIntensity=True,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_AutoExposureMethod=True,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=True,bOverride_AutoExposureMaxBrightness=True,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=True,bOverride_HistogramLogMin=True,bOverride_HistogramLogMax=True,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=True,bOverride_GrainIntensity=False,bOverride_GrainJitter=False,bOverride_AmbientOcclusionIntensity=True,bOverride_AmbientOcclusionStaticFraction=True,bOverride_AmbientOcclusionRadius=True,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionDistance=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=True,bOverride_AmbientOcclusionBias=True,bOverride_AmbientOcclusionQuality=True,bOverride_AmbientOcclusionMipBlend=True,bOverride_AmbientOcclusionMipScale=True,bOverride_AmbientOcclusionMipThreshold=True,bOverride_LPVIntensity=False,bOverride_LPVDirectionalOcclusionIntensity=False,bOverride_LPVDirectionalOcclusionRadius=False,bOverride_LPVDiffuseOcclusionExponent=False,bOverride_LPVSpecularOcclusionExponent=False,bOverride_LPVDiffuseOcclusionIntensity=False,bOverride_LPVSpecularOcclusionIntensity=False,bOverride_LPVSize=False,bOverride_LPVSecondaryOcclusionIntensity=False,bOverride_LPVSecondaryBounceIntensity=False,bOverride_LPVGeometryVolumeBias=False,bOverride_LPVVplInjectionBias=False,bOverride_LPVEmissiveInjectionIntensity=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=True,bOverride_ColorGradingLUT=True,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=True,bOverride_DepthOfFieldMaxBokehSize=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_DepthOfFieldMethod=True,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldBokehShape=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldColorThreshold=False,bOverride_DepthOfFieldSizeThreshold=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ScreenPercentage=False,bOverride_ScreenSpaceReflectionIntensity=True,bOverride_ScreenSpaceReflectionQuality=True,bOverride_ScreenSpaceReflectionMaxRoughness=True,bOverride_ScreenSpaceReflectionRoughnessScale=False,WhiteTemp=6700.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.005000,Y=0.005000,Z=0.005000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionShadowsMax=0.090000,ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,FilmWhitePoint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTintBlend=0.500000,FilmShadowTintAmount=0.000000,FilmSaturation=1.000000,FilmChannelMixerRed=(R=1.000000,G=0.000000,B=0.000000,A=1.000000),FilmChannelMixerGreen=(R=0.000000,G=1.000000,B=0.000000,A=1.000000),FilmChannelMixerBlue=(R=0.000000,G=0.000000,B=1.000000,A=1.000000),FilmContrast=0.030000,FilmToeAmount=1.000000,FilmHealAmount=0.180000,FilmDynamicRange=4.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,BloomIntensity=1.000000,BloomThreshold=1.000000,BloomSizeScale=4.000000,Bloom1Size=1.000000,Bloom2Size=4.000000,Bloom3Size=16.000000,Bloom4Size=32.000000,Bloom5Size=64.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom2Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom3Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom4Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom5Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom6Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMaskIntensity=1.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMask=None,LPVIntensity=1.000000,LPVVplInjectionBias=0.640000,LPVSize=5312.000000,LPVSecondaryOcclusionIntensity=0.000000,LPVSecondaryBounceIntensity=0.000000,LPVGeometryVolumeBias=0.384000,LPVEmissiveInjectionIntensity=1.000000,LPVDirectionalOcclusionIntensity=0.000000,LPVDirectionalOcclusionRadius=8.000000,LPVDiffuseOcclusionExponent=1.000000,LPVSpecularOcclusionExponent=7.000000,LPVDiffuseOcclusionIntensity=1.000000,LPVSpecularOcclusionIntensity=1.000000,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,AutoExposureMethod=AEM_Histogram,AutoExposureLowPercent=80.000000,AutoExposureHighPercent=98.300003,AutoExposureMinBrightness=1.000000,AutoExposureMaxBrightness=1.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,AutoExposureBias=0.330000,HistogramLogMin=-8.000000,HistogramLogMax=4.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.161468,GrainJitter=0.000000,GrainIntensity=0.000000,AmbientOcclusionIntensity=1.000000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=73.477997,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionDistance=80.000000,AmbientOcclusionPower=1.200000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=100.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,ColorGradingIntensity=0.000000,ColorGradingLUT=Texture2D'/Engine/EditorResources/RGBTable16x1_AssetViewer.RGBTable16x1_AssetViewer',DepthOfFieldMethod=DOFM_BokehDOF,bMobileHQGaussian=False,DepthOfFieldFstop=4.000000,DepthOfFieldSensorWidth=24.576000,DepthOfFieldFocalDistance=1000.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldMaxBokehSize=15.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldBokehShape=None,DepthOfFieldOcclusion=0.400000,DepthOfFieldColorThreshold=1.000000,DepthOfFieldSizeThreshold=0.080000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurPerObjectSize=0.500000,ScreenPercentage=100.000000,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=100.000000,ScreenSpaceReflectionMaxRoughness=1.000000,WeightedBlendables=(Array=),Blendables=),bPostProcessingEnabled=True,LightingRigRotation=109.389069,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-39.999985,Yaw=-67.500015,Roll=0.000000)) -+Profiles=(ProfileName="Default",DirectionalLightIntensity=2.620000,DirectionalLightColor=(R=0.990000,G=0.839850,B=0.732600,A=1.000000),SkyLightIntensity=0.880000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=True,EnvironmentCubeMap=TextureCube'/Engine/EngineSky/EpicQuadPanorama_CC+EV1.EpicQuadPanorama_CC+EV1',PostProcessingSettings=(bOverride_WhiteTemp=True,bOverride_WhiteTint=False,bOverride_ColorSaturation=True,bOverride_ColorContrast=True,bOverride_ColorGamma=True,bOverride_ColorGain=True,bOverride_ColorOffset=True,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_FilmWhitePoint=False,bOverride_FilmSaturation=False,bOverride_FilmChannelMixerRed=False,bOverride_FilmChannelMixerGreen=False,bOverride_FilmChannelMixerBlue=False,bOverride_FilmContrast=False,bOverride_FilmDynamicRange=False,bOverride_FilmHealAmount=False,bOverride_FilmToeAmount=False,bOverride_FilmShadowTint=False,bOverride_FilmShadowTintBlend=False,bOverride_FilmShadowTintAmount=False,bOverride_FilmSlope=True,bOverride_FilmToe=True,bOverride_FilmShoulder=True,bOverride_FilmBlackClip=True,bOverride_FilmWhiteClip=True,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomIntensity=True,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_AutoExposureMethod=True,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=True,bOverride_AutoExposureMaxBrightness=True,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=True,bOverride_HistogramLogMin=True,bOverride_HistogramLogMax=True,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=True,bOverride_GrainIntensity=False,bOverride_GrainJitter=False,bOverride_AmbientOcclusionIntensity=True,bOverride_AmbientOcclusionStaticFraction=True,bOverride_AmbientOcclusionRadius=True,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionDistance=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=True,bOverride_AmbientOcclusionBias=True,bOverride_AmbientOcclusionQuality=True,bOverride_AmbientOcclusionMipBlend=True,bOverride_AmbientOcclusionMipScale=True,bOverride_AmbientOcclusionMipThreshold=True,bOverride_LPVIntensity=False,bOverride_LPVDirectionalOcclusionIntensity=False,bOverride_LPVDirectionalOcclusionRadius=False,bOverride_LPVDiffuseOcclusionExponent=False,bOverride_LPVSpecularOcclusionExponent=False,bOverride_LPVDiffuseOcclusionIntensity=False,bOverride_LPVSpecularOcclusionIntensity=False,bOverride_LPVSize=False,bOverride_LPVSecondaryOcclusionIntensity=False,bOverride_LPVSecondaryBounceIntensity=False,bOverride_LPVGeometryVolumeBias=False,bOverride_LPVVplInjectionBias=False,bOverride_LPVEmissiveInjectionIntensity=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=True,bOverride_ColorGradingLUT=True,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=True,bOverride_DepthOfFieldMaxBokehSize=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_DepthOfFieldMethod=True,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldBokehShape=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldColorThreshold=False,bOverride_DepthOfFieldSizeThreshold=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ScreenPercentage=False,bOverride_ScreenSpaceReflectionIntensity=True,bOverride_ScreenSpaceReflectionQuality=True,bOverride_ScreenSpaceReflectionMaxRoughness=True,bOverride_ScreenSpaceReflectionRoughnessScale=False,WhiteTemp=6700.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.005000,Y=0.005000,Z=0.005000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionShadowsMax=0.090000,ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,FilmWhitePoint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTintBlend=0.500000,FilmShadowTintAmount=0.000000,FilmSaturation=1.000000,FilmChannelMixerRed=(R=1.000000,G=0.000000,B=0.000000,A=1.000000),FilmChannelMixerGreen=(R=0.000000,G=1.000000,B=0.000000,A=1.000000),FilmChannelMixerBlue=(R=0.000000,G=0.000000,B=1.000000,A=1.000000),FilmContrast=0.030000,FilmToeAmount=1.000000,FilmHealAmount=0.180000,FilmDynamicRange=4.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,BloomIntensity=1.000000,BloomThreshold=1.000000,BloomSizeScale=4.000000,Bloom1Size=1.000000,Bloom2Size=4.000000,Bloom3Size=16.000000,Bloom4Size=32.000000,Bloom5Size=64.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom2Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom3Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom4Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom5Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom6Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMaskIntensity=1.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMask=None,LPVIntensity=1.000000,LPVVplInjectionBias=0.640000,LPVSize=5312.000000,LPVSecondaryOcclusionIntensity=0.000000,LPVSecondaryBounceIntensity=0.000000,LPVGeometryVolumeBias=0.384000,LPVEmissiveInjectionIntensity=1.000000,LPVDirectionalOcclusionIntensity=0.000000,LPVDirectionalOcclusionRadius=8.000000,LPVDiffuseOcclusionExponent=1.000000,LPVSpecularOcclusionExponent=7.000000,LPVDiffuseOcclusionIntensity=1.000000,LPVSpecularOcclusionIntensity=1.000000,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,AutoExposureMethod=AEM_Histogram,AutoExposureLowPercent=80.000000,AutoExposureHighPercent=98.300003,AutoExposureMinBrightness=1.000000,AutoExposureMaxBrightness=1.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,AutoExposureBias=0.330000,HistogramLogMin=-8.000000,HistogramLogMax=4.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.161468,GrainJitter=0.000000,GrainIntensity=0.000000,AmbientOcclusionIntensity=1.000000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=73.477997,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionDistance=80.000000,AmbientOcclusionPower=1.200000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=100.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,ColorGradingIntensity=0.000000,ColorGradingLUT=Texture2D'/Engine/EditorResources/RGBTable16x1_AssetViewer.RGBTable16x1_AssetViewer',DepthOfFieldMethod=DOFM_BokehDOF,bMobileHQGaussian=False,DepthOfFieldFstop=4.000000,DepthOfFieldSensorWidth=24.576000,DepthOfFieldFocalDistance=1000.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldMaxBokehSize=15.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldBokehShape=None,DepthOfFieldOcclusion=0.400000,DepthOfFieldColorThreshold=1.000000,DepthOfFieldSizeThreshold=0.080000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurPerObjectSize=0.500000,ScreenPercentage=100.000000,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=100.000000,ScreenSpaceReflectionMaxRoughness=1.000000,WeightedBlendables=(Array=),Blendables=),bPostProcessingEnabled=True,LightingRigRotation=109.389069,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-39.999985,Yaw=-67.500015,Roll=0.000000)) - -[/Script/UnrealEd.AssetViewerSettings] --Profiles=(ProfileName="Default",DirectionalLightIntensity=2.620000,DirectionalLightColor=(R=0.990000,G=0.839850,B=0.732600,A=1.000000),SkyLightIntensity=0.880000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=True,EnvironmentCubeMapPath="/Engine/EditorMaterials/AssetViewer/EpicQuadPanorama_CC+EV1.EpicQuadPanorama_CC+EV1",PostProcessingSettings=(bOverride_WhiteTemp=True,bOverride_WhiteTint=False,bOverride_ColorSaturation=True,bOverride_ColorContrast=True,bOverride_ColorGamma=True,bOverride_ColorGain=True,bOverride_ColorOffset=True,bOverride_FilmWhitePoint=False,bOverride_FilmSaturation=False,bOverride_FilmChannelMixerRed=False,bOverride_FilmChannelMixerGreen=False,bOverride_FilmChannelMixerBlue=False,bOverride_FilmContrast=False,bOverride_FilmDynamicRange=False,bOverride_FilmHealAmount=False,bOverride_FilmToeAmount=False,bOverride_FilmShadowTint=False,bOverride_FilmShadowTintBlend=False,bOverride_FilmShadowTintAmount=False,bOverride_FilmSlope=True,bOverride_FilmToe=True,bOverride_FilmShoulder=True,bOverride_FilmBlackClip=True,bOverride_FilmWhiteClip=True,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomIntensity=True,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_AutoExposureMethod=True,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=True,bOverride_AutoExposureMaxBrightness=True,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=True,bOverride_HistogramLogMin=True,bOverride_HistogramLogMax=True,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=True,bOverride_GrainIntensity=False,bOverride_GrainJitter=False,bOverride_AmbientOcclusionIntensity=True,bOverride_AmbientOcclusionStaticFraction=True,bOverride_AmbientOcclusionRadius=True,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionDistance=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=True,bOverride_AmbientOcclusionBias=True,bOverride_AmbientOcclusionQuality=True,bOverride_AmbientOcclusionMipBlend=True,bOverride_AmbientOcclusionMipScale=True,bOverride_AmbientOcclusionMipThreshold=True,bOverride_LPVIntensity=False,bOverride_LPVDirectionalOcclusionIntensity=False,bOverride_LPVDirectionalOcclusionRadius=False,bOverride_LPVDiffuseOcclusionExponent=False,bOverride_LPVSpecularOcclusionExponent=False,bOverride_LPVDiffuseOcclusionIntensity=False,bOverride_LPVSpecularOcclusionIntensity=False,bOverride_LPVSize=False,bOverride_LPVSecondaryOcclusionIntensity=False,bOverride_LPVSecondaryBounceIntensity=False,bOverride_LPVGeometryVolumeBias=False,bOverride_LPVVplInjectionBias=False,bOverride_LPVEmissiveInjectionIntensity=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=True,bOverride_ColorGradingLUT=True,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=True,bOverride_DepthOfFieldMaxBokehSize=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_DepthOfFieldMethod=True,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldBokehShape=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldColorThreshold=False,bOverride_DepthOfFieldSizeThreshold=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ScreenPercentage=False,bOverride_ScreenSpaceReflectionIntensity=True,bOverride_ScreenSpaceReflectionQuality=True,bOverride_ScreenSpaceReflectionMaxRoughness=True,bOverride_ScreenSpaceReflectionRoughnessScale=False,WhiteTemp=6700.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000),ColorOffset=(X=0.005000,Y=0.005000,Z=0.005000),FilmWhitePoint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTintBlend=0.500000,FilmShadowTintAmount=0.000000,FilmSaturation=1.000000,FilmChannelMixerRed=(R=1.000000,G=0.000000,B=0.000000,A=1.000000),FilmChannelMixerGreen=(R=0.000000,G=1.000000,B=0.000000,A=1.000000),FilmChannelMixerBlue=(R=0.000000,G=0.000000,B=1.000000,A=1.000000),FilmContrast=0.030000,FilmToeAmount=1.000000,FilmHealAmount=1.000000,FilmDynamicRange=4.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,BloomIntensity=0.675000,BloomThreshold=-1.000000,BloomSizeScale=4.000000,Bloom1Size=0.300000,Bloom2Size=1.000000,Bloom3Size=2.000000,Bloom4Size=10.000000,Bloom5Size=30.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.346500,G=0.346500,B=0.346500,A=1.000000),Bloom2Tint=(R=0.138000,G=0.138000,B=0.138000,A=1.000000),Bloom3Tint=(R=0.117600,G=0.117600,B=0.117600,A=1.000000),Bloom4Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom5Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom6Tint=(R=0.061000,G=0.061000,B=0.061000,A=1.000000),BloomDirtMaskIntensity=0.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMask=None,LPVIntensity=1.000000,LPVVplInjectionBias=0.640000,LPVSize=5312.000000,LPVSecondaryOcclusionIntensity=0.000000,LPVSecondaryBounceIntensity=0.000000,LPVGeometryVolumeBias=0.384000,LPVEmissiveInjectionIntensity=1.000000,LPVDirectionalOcclusionIntensity=0.000000,LPVDirectionalOcclusionRadius=8.000000,LPVDiffuseOcclusionExponent=1.000000,LPVSpecularOcclusionExponent=7.000000,LPVDiffuseOcclusionIntensity=1.000000,LPVSpecularOcclusionIntensity=1.000000,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,AutoExposureMethod=AEM_Histogram,AutoExposureLowPercent=80.000000,AutoExposureHighPercent=98.300003,AutoExposureMinBrightness=1.000000,AutoExposureMaxBrightness=1.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,AutoExposureBias=0.330000,HistogramLogMin=-8.000000,HistogramLogMax=4.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.161468,GrainJitter=0.000000,GrainIntensity=0.000000,AmbientOcclusionIntensity=1.000000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=73.477997,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionDistance=80.000000,AmbientOcclusionPower=1.200000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=100.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,ColorGradingIntensity=0.000000,ColorGradingLUT=Texture2D'/Engine/EditorResources/RGBTable16x1_AssetViewer.RGBTable16x1_AssetViewer',DepthOfFieldMethod=DOFM_BokehDOF,bMobileHQGaussian=False,DepthOfFieldFstop=4.000000,DepthOfFieldSensorWidth=24.576000,DepthOfFieldFocalDistance=1000.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldMaxBokehSize=15.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldBokehShape=None,DepthOfFieldOcclusion=0.400000,DepthOfFieldColorThreshold=1.000000,DepthOfFieldSizeThreshold=0.080000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurPerObjectSize=0.500000,ScreenPercentage=100.000000,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=100.000000,ScreenSpaceReflectionMaxRoughness=1.000000,WeightedBlendables=(Array=),Blendables=),bPostProcessingEnabled=True,LightingRigRotation=109.389069,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-40.000000,Yaw=-67.500000,Roll=0.000000)) --Profiles=(ProfileName="Default",DirectionalLightIntensity=2.620000,DirectionalLightColor=(R=0.990000,G=0.839850,B=0.732600,A=1.000000),SkyLightIntensity=0.880000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=True,EnvironmentCubeMapPath="/Engine/EditorMaterials/AssetViewer/EpicQuadPanorama_CC+EV1.EpicQuadPanorama_CC+EV1",PostProcessingSettings=(bOverride_WhiteTemp=True,bOverride_WhiteTint=False,bOverride_ColorSaturation=True,bOverride_ColorContrast=True,bOverride_ColorGamma=True,bOverride_ColorGain=True,bOverride_ColorOffset=True,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_FilmWhitePoint=False,bOverride_FilmSaturation=False,bOverride_FilmChannelMixerRed=False,bOverride_FilmChannelMixerGreen=False,bOverride_FilmChannelMixerBlue=False,bOverride_FilmContrast=False,bOverride_FilmDynamicRange=False,bOverride_FilmHealAmount=False,bOverride_FilmToeAmount=False,bOverride_FilmShadowTint=False,bOverride_FilmShadowTintBlend=False,bOverride_FilmShadowTintAmount=False,bOverride_FilmSlope=True,bOverride_FilmToe=True,bOverride_FilmShoulder=True,bOverride_FilmBlackClip=True,bOverride_FilmWhiteClip=True,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomIntensity=True,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_AutoExposureMethod=True,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=True,bOverride_AutoExposureMaxBrightness=True,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=True,bOverride_HistogramLogMin=True,bOverride_HistogramLogMax=True,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=True,bOverride_GrainIntensity=False,bOverride_GrainJitter=False,bOverride_AmbientOcclusionIntensity=True,bOverride_AmbientOcclusionStaticFraction=True,bOverride_AmbientOcclusionRadius=True,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionDistance=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=True,bOverride_AmbientOcclusionBias=True,bOverride_AmbientOcclusionQuality=True,bOverride_AmbientOcclusionMipBlend=True,bOverride_AmbientOcclusionMipScale=True,bOverride_AmbientOcclusionMipThreshold=True,bOverride_LPVIntensity=False,bOverride_LPVDirectionalOcclusionIntensity=False,bOverride_LPVDirectionalOcclusionRadius=False,bOverride_LPVDiffuseOcclusionExponent=False,bOverride_LPVSpecularOcclusionExponent=False,bOverride_LPVDiffuseOcclusionIntensity=False,bOverride_LPVSpecularOcclusionIntensity=False,bOverride_LPVSize=False,bOverride_LPVSecondaryOcclusionIntensity=False,bOverride_LPVSecondaryBounceIntensity=False,bOverride_LPVGeometryVolumeBias=False,bOverride_LPVVplInjectionBias=False,bOverride_LPVEmissiveInjectionIntensity=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=True,bOverride_ColorGradingLUT=True,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=True,bOverride_DepthOfFieldMaxBokehSize=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_DepthOfFieldMethod=True,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldBokehShape=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldColorThreshold=False,bOverride_DepthOfFieldSizeThreshold=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ScreenPercentage=False,bOverride_ScreenSpaceReflectionIntensity=True,bOverride_ScreenSpaceReflectionQuality=True,bOverride_ScreenSpaceReflectionMaxRoughness=True,bOverride_ScreenSpaceReflectionRoughnessScale=False,WhiteTemp=6700.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.005000,Y=0.005000,Z=0.005000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionShadowsMax=0.090000,ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,FilmWhitePoint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTintBlend=0.500000,FilmShadowTintAmount=0.000000,FilmSaturation=1.000000,FilmChannelMixerRed=(R=1.000000,G=0.000000,B=0.000000,A=1.000000),FilmChannelMixerGreen=(R=0.000000,G=1.000000,B=0.000000,A=1.000000),FilmChannelMixerBlue=(R=0.000000,G=0.000000,B=1.000000,A=1.000000),FilmContrast=0.030000,FilmToeAmount=1.000000,FilmHealAmount=0.180000,FilmDynamicRange=4.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,BloomIntensity=1.000000,BloomThreshold=1.000000,BloomSizeScale=4.000000,Bloom1Size=1.000000,Bloom2Size=4.000000,Bloom3Size=16.000000,Bloom4Size=32.000000,Bloom5Size=64.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom2Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom3Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom4Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom5Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom6Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMaskIntensity=1.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMask=None,LPVIntensity=1.000000,LPVVplInjectionBias=0.640000,LPVSize=5312.000000,LPVSecondaryOcclusionIntensity=0.000000,LPVSecondaryBounceIntensity=0.000000,LPVGeometryVolumeBias=0.384000,LPVEmissiveInjectionIntensity=1.000000,LPVDirectionalOcclusionIntensity=0.000000,LPVDirectionalOcclusionRadius=8.000000,LPVDiffuseOcclusionExponent=1.000000,LPVSpecularOcclusionExponent=7.000000,LPVDiffuseOcclusionIntensity=1.000000,LPVSpecularOcclusionIntensity=1.000000,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,AutoExposureMethod=AEM_Histogram,AutoExposureLowPercent=80.000000,AutoExposureHighPercent=98.300003,AutoExposureMinBrightness=1.000000,AutoExposureMaxBrightness=1.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,AutoExposureBias=0.330000,HistogramLogMin=-8.000000,HistogramLogMax=4.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.161468,GrainJitter=0.000000,GrainIntensity=0.000000,AmbientOcclusionIntensity=1.000000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=73.477997,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionDistance=80.000000,AmbientOcclusionPower=1.200000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=100.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,ColorGradingIntensity=0.000000,ColorGradingLUT=Texture2D'/Engine/EditorResources/RGBTable16x1_AssetViewer.RGBTable16x1_AssetViewer',DepthOfFieldMethod=DOFM_BokehDOF,bMobileHQGaussian=False,DepthOfFieldFstop=4.000000,DepthOfFieldSensorWidth=24.576000,DepthOfFieldFocalDistance=1000.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldMaxBokehSize=15.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldBokehShape=None,DepthOfFieldOcclusion=0.400000,DepthOfFieldColorThreshold=1.000000,DepthOfFieldSizeThreshold=0.080000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurPerObjectSize=0.500000,ScreenPercentage=100.000000,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=100.000000,ScreenSpaceReflectionMaxRoughness=1.000000,WeightedBlendables=(Array=),Blendables=),bPostProcessingEnabled=True,LightingRigRotation=109.389069,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-39.999985,Yaw=-67.500015,Roll=0.000000)) --Profiles=(ProfileName="Profile_0",DirectionalLightIntensity=1.000000,DirectionalLightColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SkyLightIntensity=1.000000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=True,EnvironmentCubeMapPath=,PostProcessingSettings=(bOverride_WhiteTemp=False,bOverride_WhiteTint=False,bOverride_ColorSaturation=False,bOverride_ColorContrast=False,bOverride_ColorGamma=False,bOverride_ColorGain=False,bOverride_ColorOffset=False,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_FilmWhitePoint=False,bOverride_FilmSaturation=False,bOverride_FilmChannelMixerRed=False,bOverride_FilmChannelMixerGreen=False,bOverride_FilmChannelMixerBlue=False,bOverride_FilmContrast=False,bOverride_FilmDynamicRange=False,bOverride_FilmHealAmount=False,bOverride_FilmToeAmount=False,bOverride_FilmShadowTint=False,bOverride_FilmShadowTintBlend=False,bOverride_FilmShadowTintAmount=False,bOverride_FilmSlope=False,bOverride_FilmToe=False,bOverride_FilmShoulder=False,bOverride_FilmBlackClip=False,bOverride_FilmWhiteClip=False,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomIntensity=False,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_AutoExposureMethod=False,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=False,bOverride_AutoExposureMaxBrightness=False,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=False,bOverride_HistogramLogMin=False,bOverride_HistogramLogMax=False,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=False,bOverride_GrainIntensity=False,bOverride_GrainJitter=False,bOverride_AmbientOcclusionIntensity=False,bOverride_AmbientOcclusionStaticFraction=False,bOverride_AmbientOcclusionRadius=False,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionDistance=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=False,bOverride_AmbientOcclusionBias=False,bOverride_AmbientOcclusionQuality=False,bOverride_AmbientOcclusionMipBlend=False,bOverride_AmbientOcclusionMipScale=False,bOverride_AmbientOcclusionMipThreshold=False,bOverride_LPVIntensity=False,bOverride_LPVDirectionalOcclusionIntensity=False,bOverride_LPVDirectionalOcclusionRadius=False,bOverride_LPVDiffuseOcclusionExponent=False,bOverride_LPVSpecularOcclusionExponent=False,bOverride_LPVDiffuseOcclusionIntensity=False,bOverride_LPVSpecularOcclusionIntensity=False,bOverride_LPVSize=False,bOverride_LPVSecondaryOcclusionIntensity=False,bOverride_LPVSecondaryBounceIntensity=False,bOverride_LPVGeometryVolumeBias=False,bOverride_LPVVplInjectionBias=False,bOverride_LPVEmissiveInjectionIntensity=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=False,bOverride_ColorGradingLUT=False,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=False,bOverride_DepthOfFieldMaxBokehSize=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_DepthOfFieldMethod=False,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldBokehShape=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldColorThreshold=False,bOverride_DepthOfFieldSizeThreshold=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ScreenPercentage=False,bOverride_ScreenSpaceReflectionIntensity=False,bOverride_ScreenSpaceReflectionQuality=False,bOverride_ScreenSpaceReflectionMaxRoughness=False,bOverride_ScreenSpaceReflectionRoughnessScale=False,WhiteTemp=6500.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionShadowsMax=0.090000,ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,FilmWhitePoint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTintBlend=0.500000,FilmShadowTintAmount=0.000000,FilmSaturation=1.000000,FilmChannelMixerRed=(R=1.000000,G=0.000000,B=0.000000,A=1.000000),FilmChannelMixerGreen=(R=0.000000,G=1.000000,B=0.000000,A=1.000000),FilmChannelMixerBlue=(R=0.000000,G=0.000000,B=1.000000,A=1.000000),FilmContrast=0.030000,FilmToeAmount=1.000000,FilmHealAmount=0.180000,FilmDynamicRange=4.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,BloomIntensity=1.000000,BloomThreshold=1.000000,BloomSizeScale=4.000000,Bloom1Size=1.000000,Bloom2Size=4.000000,Bloom3Size=16.000000,Bloom4Size=32.000000,Bloom5Size=64.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom2Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom3Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom4Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom5Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom6Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMaskIntensity=1.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMask=None,LPVIntensity=1.000000,LPVVplInjectionBias=0.640000,LPVSize=5312.000000,LPVSecondaryOcclusionIntensity=0.000000,LPVSecondaryBounceIntensity=0.000000,LPVGeometryVolumeBias=0.384000,LPVEmissiveInjectionIntensity=1.000000,LPVDirectionalOcclusionIntensity=0.000000,LPVDirectionalOcclusionRadius=8.000000,LPVDiffuseOcclusionExponent=1.000000,LPVSpecularOcclusionExponent=7.000000,LPVDiffuseOcclusionIntensity=1.000000,LPVSpecularOcclusionIntensity=1.000000,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,AutoExposureMethod=AEM_Histogram,AutoExposureLowPercent=80.000000,AutoExposureHighPercent=98.300003,AutoExposureMinBrightness=0.030000,AutoExposureMaxBrightness=2.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,AutoExposureBias=0.000000,HistogramLogMin=-8.000000,HistogramLogMax=4.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.400000,GrainJitter=0.000000,GrainIntensity=0.000000,AmbientOcclusionIntensity=0.500000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=200.000000,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionDistance=80.000000,AmbientOcclusionPower=2.000000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=50.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,ColorGradingIntensity=1.000000,ColorGradingLUT=None,DepthOfFieldMethod=DOFM_BokehDOF,bMobileHQGaussian=False,DepthOfFieldFstop=4.000000,DepthOfFieldSensorWidth=24.576000,DepthOfFieldFocalDistance=1000.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldMaxBokehSize=15.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldBokehShape=None,DepthOfFieldOcclusion=0.400000,DepthOfFieldColorThreshold=1.000000,DepthOfFieldSizeThreshold=0.080000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurPerObjectSize=0.500000,ScreenPercentage=100.000000,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=50.000000,ScreenSpaceReflectionMaxRoughness=0.600000,WeightedBlendables=(Array=),Blendables=),bPostProcessingEnabled=True,LightingRigRotation=0.000000,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-40.000000,Yaw=-67.500000,Roll=0.000000)) -+Profiles=(ProfileName="Default",DirectionalLightIntensity=2.620000,DirectionalLightColor=(R=0.990000,G=0.839850,B=0.732600,A=1.000000),SkyLightIntensity=0.880000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=True,EnvironmentCubeMapPath="/Engine/EditorMaterials/AssetViewer/EpicQuadPanorama_CC+EV1.EpicQuadPanorama_CC+EV1",PostProcessingSettings=(bOverride_WhiteTemp=True,bOverride_WhiteTint=False,bOverride_ColorSaturation=True,bOverride_ColorContrast=True,bOverride_ColorGamma=True,bOverride_ColorGain=True,bOverride_ColorOffset=True,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_FilmWhitePoint=False,bOverride_FilmSaturation=False,bOverride_FilmChannelMixerRed=False,bOverride_FilmChannelMixerGreen=False,bOverride_FilmChannelMixerBlue=False,bOverride_FilmContrast=False,bOverride_FilmDynamicRange=False,bOverride_FilmHealAmount=False,bOverride_FilmToeAmount=False,bOverride_FilmShadowTint=False,bOverride_FilmShadowTintBlend=False,bOverride_FilmShadowTintAmount=False,bOverride_FilmSlope=True,bOverride_FilmToe=True,bOverride_FilmShoulder=True,bOverride_FilmBlackClip=True,bOverride_FilmWhiteClip=True,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomIntensity=True,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_AutoExposureMethod=True,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=True,bOverride_AutoExposureMaxBrightness=True,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=True,bOverride_HistogramLogMin=True,bOverride_HistogramLogMax=True,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=True,bOverride_GrainIntensity=False,bOverride_GrainJitter=False,bOverride_AmbientOcclusionIntensity=True,bOverride_AmbientOcclusionStaticFraction=True,bOverride_AmbientOcclusionRadius=True,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionDistance=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=True,bOverride_AmbientOcclusionBias=True,bOverride_AmbientOcclusionQuality=True,bOverride_AmbientOcclusionMipBlend=True,bOverride_AmbientOcclusionMipScale=True,bOverride_AmbientOcclusionMipThreshold=True,bOverride_LPVIntensity=False,bOverride_LPVDirectionalOcclusionIntensity=False,bOverride_LPVDirectionalOcclusionRadius=False,bOverride_LPVDiffuseOcclusionExponent=False,bOverride_LPVSpecularOcclusionExponent=False,bOverride_LPVDiffuseOcclusionIntensity=False,bOverride_LPVSpecularOcclusionIntensity=False,bOverride_LPVSize=False,bOverride_LPVSecondaryOcclusionIntensity=False,bOverride_LPVSecondaryBounceIntensity=False,bOverride_LPVGeometryVolumeBias=False,bOverride_LPVVplInjectionBias=False,bOverride_LPVEmissiveInjectionIntensity=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=True,bOverride_ColorGradingLUT=True,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=True,bOverride_DepthOfFieldMaxBokehSize=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_DepthOfFieldMethod=True,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldBokehShape=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldColorThreshold=False,bOverride_DepthOfFieldSizeThreshold=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ScreenPercentage=False,bOverride_ScreenSpaceReflectionIntensity=True,bOverride_ScreenSpaceReflectionQuality=True,bOverride_ScreenSpaceReflectionMaxRoughness=True,bOverride_ScreenSpaceReflectionRoughnessScale=False,WhiteTemp=6700.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.005000,Y=0.005000,Z=0.005000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionShadowsMax=0.090000,ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,FilmWhitePoint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTintBlend=0.500000,FilmShadowTintAmount=0.000000,FilmSaturation=1.000000,FilmChannelMixerRed=(R=1.000000,G=0.000000,B=0.000000,A=1.000000),FilmChannelMixerGreen=(R=0.000000,G=1.000000,B=0.000000,A=1.000000),FilmChannelMixerBlue=(R=0.000000,G=0.000000,B=1.000000,A=1.000000),FilmContrast=0.030000,FilmToeAmount=1.000000,FilmHealAmount=1.000000,FilmDynamicRange=4.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,BloomIntensity=0.675000,BloomThreshold=-1.000000,BloomSizeScale=4.000000,Bloom1Size=0.300000,Bloom2Size=1.000000,Bloom3Size=2.000000,Bloom4Size=10.000000,Bloom5Size=30.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.346500,G=0.346500,B=0.346500,A=1.000000),Bloom2Tint=(R=0.138000,G=0.138000,B=0.138000,A=1.000000),Bloom3Tint=(R=0.117600,G=0.117600,B=0.117600,A=1.000000),Bloom4Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom5Tint=(R=0.066000,G=0.066000,B=0.066000,A=1.000000),Bloom6Tint=(R=0.061000,G=0.061000,B=0.061000,A=1.000000),BloomDirtMaskIntensity=0.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMask=None,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,AutoExposureMethod=AEM_Histogram,AutoExposureLowPercent=80.000000,AutoExposureHighPercent=98.300003,AutoExposureMinBrightness=1.000000,AutoExposureMaxBrightness=1.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,AutoExposureBias=0.330000,HistogramLogMin=-8.000000,HistogramLogMax=4.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.161468,GrainJitter=0.000000,GrainIntensity=0.000000,AmbientOcclusionIntensity=1.000000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=73.477997,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionDistance=80.000000,AmbientOcclusionPower=1.200000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=100.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,ColorGradingIntensity=0.000000,ColorGradingLUT=Texture2D'/Engine/EditorResources/RGBTable16x1_AssetViewer.RGBTable16x1_AssetViewer',DepthOfFieldMethod=DOFM_BokehDOF,bMobileHQGaussian=False,DepthOfFieldFstop=4.000000,DepthOfFieldSensorWidth=24.576000,DepthOfFieldFocalDistance=1000.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldMaxBokehSize=15.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldBokehShape=None,DepthOfFieldOcclusion=0.400000,DepthOfFieldColorThreshold=1.000000,DepthOfFieldSizeThreshold=0.080000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurPerObjectSize=0.500000,LPVIntensity=1.000000,LPVVplInjectionBias=0.640000,LPVSize=5312.000000,LPVSecondaryOcclusionIntensity=0.000000,LPVSecondaryBounceIntensity=0.000000,LPVGeometryVolumeBias=0.384000,LPVEmissiveInjectionIntensity=1.000000,LPVDirectionalOcclusionIntensity=0.000000,LPVDirectionalOcclusionRadius=8.000000,LPVDiffuseOcclusionExponent=1.000000,LPVSpecularOcclusionExponent=7.000000,LPVDiffuseOcclusionIntensity=1.000000,LPVSpecularOcclusionIntensity=1.000000,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=100.000000,ScreenSpaceReflectionMaxRoughness=1.000000,ScreenPercentage=100.000000,WeightedBlendables=(Array=),Blendables=),bPostProcessingEnabled=True,LightingRigRotation=109.389069,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-39.999985,Yaw=-67.500015,Roll=0.000000)) -+Profiles=(ProfileName="Default",DirectionalLightIntensity=2.620000,DirectionalLightColor=(R=0.990000,G=0.839850,B=0.732600,A=1.000000),SkyLightIntensity=0.880000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=True,EnvironmentCubeMapPath="/Engine/EditorMaterials/AssetViewer/EpicQuadPanorama_CC+EV1.EpicQuadPanorama_CC+EV1",PostProcessingSettings=(bOverride_WhiteTemp=True,bOverride_WhiteTint=False,bOverride_ColorSaturation=True,bOverride_ColorContrast=True,bOverride_ColorGamma=True,bOverride_ColorGain=True,bOverride_ColorOffset=True,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_FilmWhitePoint=False,bOverride_FilmSaturation=False,bOverride_FilmChannelMixerRed=False,bOverride_FilmChannelMixerGreen=False,bOverride_FilmChannelMixerBlue=False,bOverride_FilmContrast=False,bOverride_FilmDynamicRange=False,bOverride_FilmHealAmount=False,bOverride_FilmToeAmount=False,bOverride_FilmShadowTint=False,bOverride_FilmShadowTintBlend=False,bOverride_FilmShadowTintAmount=False,bOverride_FilmSlope=True,bOverride_FilmToe=True,bOverride_FilmShoulder=True,bOverride_FilmBlackClip=True,bOverride_FilmWhiteClip=True,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomIntensity=True,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_AutoExposureMethod=True,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=True,bOverride_AutoExposureMaxBrightness=True,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=True,bOverride_HistogramLogMin=True,bOverride_HistogramLogMax=True,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=True,bOverride_GrainIntensity=False,bOverride_GrainJitter=False,bOverride_AmbientOcclusionIntensity=True,bOverride_AmbientOcclusionStaticFraction=True,bOverride_AmbientOcclusionRadius=True,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionDistance=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=True,bOverride_AmbientOcclusionBias=True,bOverride_AmbientOcclusionQuality=True,bOverride_AmbientOcclusionMipBlend=True,bOverride_AmbientOcclusionMipScale=True,bOverride_AmbientOcclusionMipThreshold=True,bOverride_LPVIntensity=False,bOverride_LPVDirectionalOcclusionIntensity=False,bOverride_LPVDirectionalOcclusionRadius=False,bOverride_LPVDiffuseOcclusionExponent=False,bOverride_LPVSpecularOcclusionExponent=False,bOverride_LPVDiffuseOcclusionIntensity=False,bOverride_LPVSpecularOcclusionIntensity=False,bOverride_LPVSize=False,bOverride_LPVSecondaryOcclusionIntensity=False,bOverride_LPVSecondaryBounceIntensity=False,bOverride_LPVGeometryVolumeBias=False,bOverride_LPVVplInjectionBias=False,bOverride_LPVEmissiveInjectionIntensity=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=True,bOverride_ColorGradingLUT=True,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=True,bOverride_DepthOfFieldMaxBokehSize=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_DepthOfFieldMethod=True,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldBokehShape=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldColorThreshold=False,bOverride_DepthOfFieldSizeThreshold=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ScreenPercentage=False,bOverride_ScreenSpaceReflectionIntensity=True,bOverride_ScreenSpaceReflectionQuality=True,bOverride_ScreenSpaceReflectionMaxRoughness=True,bOverride_ScreenSpaceReflectionRoughnessScale=False,WhiteTemp=6700.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.005000,Y=0.005000,Z=0.005000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionShadowsMax=0.090000,ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,FilmWhitePoint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTintBlend=0.500000,FilmShadowTintAmount=0.000000,FilmSaturation=1.000000,FilmChannelMixerRed=(R=1.000000,G=0.000000,B=0.000000,A=1.000000),FilmChannelMixerGreen=(R=0.000000,G=1.000000,B=0.000000,A=1.000000),FilmChannelMixerBlue=(R=0.000000,G=0.000000,B=1.000000,A=1.000000),FilmContrast=0.030000,FilmToeAmount=1.000000,FilmHealAmount=0.180000,FilmDynamicRange=4.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,BloomIntensity=1.000000,BloomThreshold=1.000000,BloomSizeScale=4.000000,Bloom1Size=1.000000,Bloom2Size=4.000000,Bloom3Size=16.000000,Bloom4Size=32.000000,Bloom5Size=64.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom2Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom3Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom4Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom5Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom6Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMaskIntensity=1.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMask=None,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,AutoExposureMethod=AEM_Histogram,AutoExposureLowPercent=80.000000,AutoExposureHighPercent=98.300003,AutoExposureMinBrightness=1.000000,AutoExposureMaxBrightness=1.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,AutoExposureBias=0.330000,HistogramLogMin=-8.000000,HistogramLogMax=4.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.161468,GrainJitter=0.000000,GrainIntensity=0.000000,AmbientOcclusionIntensity=1.000000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=73.477997,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionDistance=80.000000,AmbientOcclusionPower=1.200000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=100.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,ColorGradingIntensity=0.000000,ColorGradingLUT=Texture2D'/Engine/EditorResources/RGBTable16x1_AssetViewer.RGBTable16x1_AssetViewer',DepthOfFieldMethod=DOFM_BokehDOF,bMobileHQGaussian=False,DepthOfFieldFstop=4.000000,DepthOfFieldSensorWidth=24.576000,DepthOfFieldFocalDistance=1000.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldMaxBokehSize=15.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldBokehShape=None,DepthOfFieldOcclusion=0.400000,DepthOfFieldColorThreshold=1.000000,DepthOfFieldSizeThreshold=0.080000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurPerObjectSize=0.500000,LPVIntensity=1.000000,LPVVplInjectionBias=0.640000,LPVSize=5312.000000,LPVSecondaryOcclusionIntensity=0.000000,LPVSecondaryBounceIntensity=0.000000,LPVGeometryVolumeBias=0.384000,LPVEmissiveInjectionIntensity=1.000000,LPVDirectionalOcclusionIntensity=0.000000,LPVDirectionalOcclusionRadius=8.000000,LPVDiffuseOcclusionExponent=1.000000,LPVSpecularOcclusionExponent=7.000000,LPVDiffuseOcclusionIntensity=1.000000,LPVSpecularOcclusionIntensity=1.000000,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=100.000000,ScreenSpaceReflectionMaxRoughness=1.000000,ScreenPercentage=100.000000,WeightedBlendables=(Array=),Blendables=),bPostProcessingEnabled=True,LightingRigRotation=109.389069,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-39.999985,Yaw=-67.500015,Roll=0.000000)) -+Profiles=(ProfileName="Profile_0",DirectionalLightIntensity=1.000000,DirectionalLightColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SkyLightIntensity=1.000000,bRotateLightingRig=False,bShowEnvironment=True,bShowFloor=True,EnvironmentCubeMapPath="",PostProcessingSettings=(bOverride_WhiteTemp=False,bOverride_WhiteTint=False,bOverride_ColorSaturation=False,bOverride_ColorContrast=False,bOverride_ColorGamma=False,bOverride_ColorGain=False,bOverride_ColorOffset=False,bOverride_ColorSaturationShadows=False,bOverride_ColorContrastShadows=False,bOverride_ColorGammaShadows=False,bOverride_ColorGainShadows=False,bOverride_ColorOffsetShadows=False,bOverride_ColorSaturationMidtones=False,bOverride_ColorContrastMidtones=False,bOverride_ColorGammaMidtones=False,bOverride_ColorGainMidtones=False,bOverride_ColorOffsetMidtones=False,bOverride_ColorSaturationHighlights=False,bOverride_ColorContrastHighlights=False,bOverride_ColorGammaHighlights=False,bOverride_ColorGainHighlights=False,bOverride_ColorOffsetHighlights=False,bOverride_ColorCorrectionShadowsMax=False,bOverride_ColorCorrectionHighlightsMin=False,bOverride_FilmWhitePoint=False,bOverride_FilmSaturation=False,bOverride_FilmChannelMixerRed=False,bOverride_FilmChannelMixerGreen=False,bOverride_FilmChannelMixerBlue=False,bOverride_FilmContrast=False,bOverride_FilmDynamicRange=False,bOverride_FilmHealAmount=False,bOverride_FilmToeAmount=False,bOverride_FilmShadowTint=False,bOverride_FilmShadowTintBlend=False,bOverride_FilmShadowTintAmount=False,bOverride_FilmSlope=False,bOverride_FilmToe=False,bOverride_FilmShoulder=False,bOverride_FilmBlackClip=False,bOverride_FilmWhiteClip=False,bOverride_SceneColorTint=False,bOverride_SceneFringeIntensity=False,bOverride_AmbientCubemapTint=False,bOverride_AmbientCubemapIntensity=False,bOverride_BloomIntensity=False,bOverride_BloomThreshold=False,bOverride_Bloom1Tint=False,bOverride_Bloom1Size=False,bOverride_Bloom2Size=False,bOverride_Bloom2Tint=False,bOverride_Bloom3Tint=False,bOverride_Bloom3Size=False,bOverride_Bloom4Tint=False,bOverride_Bloom4Size=False,bOverride_Bloom5Tint=False,bOverride_Bloom5Size=False,bOverride_Bloom6Tint=False,bOverride_Bloom6Size=False,bOverride_BloomSizeScale=False,bOverride_BloomDirtMaskIntensity=False,bOverride_BloomDirtMaskTint=False,bOverride_BloomDirtMask=False,bOverride_AutoExposureMethod=False,bOverride_AutoExposureLowPercent=False,bOverride_AutoExposureHighPercent=False,bOverride_AutoExposureMinBrightness=False,bOverride_AutoExposureMaxBrightness=False,bOverride_AutoExposureSpeedUp=False,bOverride_AutoExposureSpeedDown=False,bOverride_AutoExposureBias=False,bOverride_HistogramLogMin=False,bOverride_HistogramLogMax=False,bOverride_LensFlareIntensity=False,bOverride_LensFlareTint=False,bOverride_LensFlareTints=False,bOverride_LensFlareBokehSize=False,bOverride_LensFlareBokehShape=False,bOverride_LensFlareThreshold=False,bOverride_VignetteIntensity=False,bOverride_GrainIntensity=False,bOverride_GrainJitter=False,bOverride_AmbientOcclusionIntensity=False,bOverride_AmbientOcclusionStaticFraction=False,bOverride_AmbientOcclusionRadius=False,bOverride_AmbientOcclusionFadeDistance=False,bOverride_AmbientOcclusionFadeRadius=False,bOverride_AmbientOcclusionDistance=False,bOverride_AmbientOcclusionRadiusInWS=False,bOverride_AmbientOcclusionPower=False,bOverride_AmbientOcclusionBias=False,bOverride_AmbientOcclusionQuality=False,bOverride_AmbientOcclusionMipBlend=False,bOverride_AmbientOcclusionMipScale=False,bOverride_AmbientOcclusionMipThreshold=False,bOverride_LPVIntensity=False,bOverride_LPVDirectionalOcclusionIntensity=False,bOverride_LPVDirectionalOcclusionRadius=False,bOverride_LPVDiffuseOcclusionExponent=False,bOverride_LPVSpecularOcclusionExponent=False,bOverride_LPVDiffuseOcclusionIntensity=False,bOverride_LPVSpecularOcclusionIntensity=False,bOverride_LPVSize=False,bOverride_LPVSecondaryOcclusionIntensity=False,bOverride_LPVSecondaryBounceIntensity=False,bOverride_LPVGeometryVolumeBias=False,bOverride_LPVVplInjectionBias=False,bOverride_LPVEmissiveInjectionIntensity=False,bOverride_IndirectLightingColor=False,bOverride_IndirectLightingIntensity=False,bOverride_ColorGradingIntensity=False,bOverride_ColorGradingLUT=False,bOverride_DepthOfFieldFocalDistance=False,bOverride_DepthOfFieldFstop=False,bOverride_DepthOfFieldSensorWidth=False,bOverride_DepthOfFieldDepthBlurRadius=False,bOverride_DepthOfFieldDepthBlurAmount=False,bOverride_DepthOfFieldFocalRegion=False,bOverride_DepthOfFieldNearTransitionRegion=False,bOverride_DepthOfFieldFarTransitionRegion=False,bOverride_DepthOfFieldScale=False,bOverride_DepthOfFieldMaxBokehSize=False,bOverride_DepthOfFieldNearBlurSize=False,bOverride_DepthOfFieldFarBlurSize=False,bOverride_DepthOfFieldMethod=False,bOverride_MobileHQGaussian=False,bOverride_DepthOfFieldBokehShape=False,bOverride_DepthOfFieldOcclusion=False,bOverride_DepthOfFieldColorThreshold=False,bOverride_DepthOfFieldSizeThreshold=False,bOverride_DepthOfFieldSkyFocusDistance=False,bOverride_DepthOfFieldVignetteSize=False,bOverride_MotionBlurAmount=False,bOverride_MotionBlurMax=False,bOverride_MotionBlurPerObjectSize=False,bOverride_ScreenPercentage=False,bOverride_ScreenSpaceReflectionIntensity=False,bOverride_ScreenSpaceReflectionQuality=False,bOverride_ScreenSpaceReflectionMaxRoughness=False,bOverride_ScreenSpaceReflectionRoughnessScale=False,WhiteTemp=6500.000000,WhiteTint=0.000000,ColorSaturation=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrast=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGamma=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGain=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffset=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainShadows=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetShadows=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionShadowsMax=0.090000,ColorSaturationMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainMidtones=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetMidtones=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorSaturationHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorContrastHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGammaHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorGainHighlights=(X=1.000000,Y=1.000000,Z=1.000000,W=1.000000),ColorOffsetHighlights=(X=0.000000,Y=0.000000,Z=0.000000,W=0.000000),ColorCorrectionHighlightsMin=0.500000,FilmWhitePoint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),FilmShadowTintBlend=0.500000,FilmShadowTintAmount=0.000000,FilmSaturation=1.000000,FilmChannelMixerRed=(R=1.000000,G=0.000000,B=0.000000,A=1.000000),FilmChannelMixerGreen=(R=0.000000,G=1.000000,B=0.000000,A=1.000000),FilmChannelMixerBlue=(R=0.000000,G=0.000000,B=1.000000,A=1.000000),FilmContrast=0.030000,FilmToeAmount=1.000000,FilmHealAmount=0.180000,FilmDynamicRange=4.000000,FilmSlope=0.880000,FilmToe=0.550000,FilmShoulder=0.260000,FilmBlackClip=0.000000,FilmWhiteClip=0.040000,SceneColorTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),SceneFringeIntensity=0.000000,BloomIntensity=1.000000,BloomThreshold=1.000000,BloomSizeScale=4.000000,Bloom1Size=1.000000,Bloom2Size=4.000000,Bloom3Size=16.000000,Bloom4Size=32.000000,Bloom5Size=64.000000,Bloom6Size=64.000000,Bloom1Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom2Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom3Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom4Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom5Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),Bloom6Tint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMaskIntensity=1.000000,BloomDirtMaskTint=(R=0.500000,G=0.500000,B=0.500000,A=1.000000),BloomDirtMask=None,AmbientCubemapTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),AmbientCubemapIntensity=1.000000,AmbientCubemap=None,AutoExposureMethod=AEM_Histogram,AutoExposureLowPercent=80.000000,AutoExposureHighPercent=98.300003,AutoExposureMinBrightness=0.030000,AutoExposureMaxBrightness=2.000000,AutoExposureSpeedUp=3.000000,AutoExposureSpeedDown=1.000000,AutoExposureBias=0.000000,HistogramLogMin=-8.000000,HistogramLogMax=4.000000,LensFlareIntensity=1.000000,LensFlareTint=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),LensFlareBokehSize=3.000000,LensFlareThreshold=8.000000,LensFlareBokehShape=None,LensFlareTints[0]=(R=1.000000,G=0.800000,B=0.400000,A=0.600000),LensFlareTints[1]=(R=1.000000,G=1.000000,B=0.600000,A=0.530000),LensFlareTints[2]=(R=0.800000,G=0.800000,B=1.000000,A=0.460000),LensFlareTints[3]=(R=0.500000,G=1.000000,B=0.400000,A=0.390000),LensFlareTints[4]=(R=0.500000,G=0.800000,B=1.000000,A=0.310000),LensFlareTints[5]=(R=0.900000,G=1.000000,B=0.800000,A=0.270000),LensFlareTints[6]=(R=1.000000,G=0.800000,B=0.400000,A=0.220000),LensFlareTints[7]=(R=0.900000,G=0.700000,B=0.700000,A=0.150000),VignetteIntensity=0.400000,GrainJitter=0.000000,GrainIntensity=0.000000,AmbientOcclusionIntensity=0.500000,AmbientOcclusionStaticFraction=1.000000,AmbientOcclusionRadius=200.000000,AmbientOcclusionRadiusInWS=False,AmbientOcclusionFadeDistance=8000.000000,AmbientOcclusionFadeRadius=5000.000000,AmbientOcclusionDistance=80.000000,AmbientOcclusionPower=2.000000,AmbientOcclusionBias=3.000000,AmbientOcclusionQuality=50.000000,AmbientOcclusionMipBlend=0.600000,AmbientOcclusionMipScale=1.700000,AmbientOcclusionMipThreshold=0.010000,IndirectLightingColor=(R=1.000000,G=1.000000,B=1.000000,A=1.000000),IndirectLightingIntensity=1.000000,ColorGradingIntensity=1.000000,ColorGradingLUT=None,DepthOfFieldMethod=DOFM_BokehDOF,bMobileHQGaussian=False,DepthOfFieldFstop=4.000000,DepthOfFieldSensorWidth=24.576000,DepthOfFieldFocalDistance=1000.000000,DepthOfFieldDepthBlurAmount=1.000000,DepthOfFieldDepthBlurRadius=0.000000,DepthOfFieldFocalRegion=0.000000,DepthOfFieldNearTransitionRegion=300.000000,DepthOfFieldFarTransitionRegion=500.000000,DepthOfFieldScale=0.000000,DepthOfFieldMaxBokehSize=15.000000,DepthOfFieldNearBlurSize=15.000000,DepthOfFieldFarBlurSize=15.000000,DepthOfFieldBokehShape=None,DepthOfFieldOcclusion=0.400000,DepthOfFieldColorThreshold=1.000000,DepthOfFieldSizeThreshold=0.080000,DepthOfFieldSkyFocusDistance=0.000000,DepthOfFieldVignetteSize=200.000000,MotionBlurAmount=0.500000,MotionBlurMax=5.000000,MotionBlurPerObjectSize=0.500000,LPVIntensity=1.000000,LPVVplInjectionBias=0.640000,LPVSize=5312.000000,LPVSecondaryOcclusionIntensity=0.000000,LPVSecondaryBounceIntensity=0.000000,LPVGeometryVolumeBias=0.384000,LPVEmissiveInjectionIntensity=1.000000,LPVDirectionalOcclusionIntensity=0.000000,LPVDirectionalOcclusionRadius=8.000000,LPVDiffuseOcclusionExponent=1.000000,LPVSpecularOcclusionExponent=7.000000,LPVDiffuseOcclusionIntensity=1.000000,LPVSpecularOcclusionIntensity=1.000000,ScreenSpaceReflectionIntensity=100.000000,ScreenSpaceReflectionQuality=50.000000,ScreenSpaceReflectionMaxRoughness=0.600000,ScreenPercentage=100.000000,WeightedBlendables=(Array=),Blendables=),bPostProcessingEnabled=True,LightingRigRotation=0.000000,RotationSpeed=2.000000,DirectionalLightRotation=(Pitch=-40.000000,Yaw=-67.500000,Roll=0.000000)) +[/Script/UnrealEd.EditorProjectAppearanceSettings] +bDisplayUnitsOnComponentTransforms=True diff --git a/Config/DefaultEditorPerProjectUserSettings.ini b/Config/DefaultEditorPerProjectUserSettings.ini index 831e211..8916a8c 100644 --- a/Config/DefaultEditorPerProjectUserSettings.ini +++ b/Config/DefaultEditorPerProjectUserSettings.ini @@ -1,31 +1,35 @@ +[ContentBrowser] +ContentBrowserTab1.SelectedPaths=/Game/ThirdPersonCPP [/Script/UnrealEd.EditorExperimentalSettings] bProceduralFoliage=True -bEnableLocalizationDashboard=False +bEnableLocalizationDashboard=True bEnableTranslationPicker=False bEnableEditorUtilityBlueprints=False -bUnifiedBlueprintEditor=True -bBlueprintableComponents=True -bActorMerging=False +bEnableFavoriteSystem=False bDeviceOutputLog=False ConsoleForGamepadLabels=None bToolbarCustomization=False bBreakOnExceptions=False -bBlueprintPerformanceAnalysisTools=True -BlueprintProfilerAverageSampleCount=20 -bEnableWidgetVisualDiff=False -bEnableAnimVisualDiff=False +bBlueprintPerformanceAnalysisTools=False bEnableFindAndReplaceReferences=False bDrawMidpointArrowsInBlueprints=False -bShowAudioStreamingOptions=True bContextMenuChunkAssignments=False bDisableCookInEditor=False +bSharedCookedBuilds=False MultiProcessCooking=0 bEQSEditor=True -bLiveStreamingFromEditor=False -bFeatureLevelES31Preview=False +bAllowLateJoinInPIE=False +bAllowVulkanPreview=False bEnableMultithreadedLightmapEncoding=False bEnableMultithreadedShadowmapEncoding=False +bUseOpenCLForConvexHullDecomp=False +bAllowPotentiallyUnsafePropertyEditing=False +bFacialAnimationImporter=False +bClothingTools=True +bEnableLiveRecompilationOfAnimationBlueprints=True +bMobilePIEPreviewDeviceLaunch=False +bAssetMaterialBaking=False [/Script/SourceCodeAccess.SourceCodeAccessSettings] PreferredAccessor=VisualStudio2017 diff --git a/Config/DefaultEditorUserSettings.ini b/Config/DefaultEditorUserSettings.ini deleted file mode 100644 index 15fb13e..0000000 --- a/Config/DefaultEditorUserSettings.ini +++ /dev/null @@ -1,2 +0,0 @@ -[ContentBrowser] -ContentBrowserTab1.SelectedPaths=/Game/ThirdPerson \ No newline at end of file diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index dc1439b..dc8bea1 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -1,96 +1,85 @@ -[/Script/Engine.Engine] -+ActiveGameNameRedirects=(OldGameName="TP_ThirdPerson",NewGameName="/Script/ActionRPGGame") -+ActiveGameNameRedirects=(OldGameName="/Script/TP_ThirdPerson",NewGameName="/Script/ActionRPGGame") -+ActiveClassRedirects=(OldClassName="TP_ThirdPersonGameMode",NewClassName="ActionRPGGameGameMode") -+ActiveClassRedirects=(OldClassName="TP_ThirdPersonCharacter",NewClassName="ActionRPGGameCharacter") +[/Script/IOSRuntimeSettings.IOSRuntimeSettings] +MinimumiOSVersion=IOS_8 -+ActiveClassRedirects=(OldClassName="/Script/GameAbilities.GAGameEffectSpec", NewClassName="/Script/AbilityFramework.GAGameEffectSpec") -+ActiveClassRedirects=(OldClassName="/Script/GameAbilitiesEditor.GAEK2Node_LatentAction", NewClassName="/Script/AbilityFrameworkEditor.GAEK2Node_LatentAction") - - -+ActiveStructRedirects=(OldStructName="/Script/GameAbilities.GAEffectProperty", NewStructName="/Script/AbilityFramework.GAEffectProperty") -+ActiveStructRedirects=(OldStructName="/Script/GameAbilities.GAEffectHandle", NewStructName="/Script/AbilityFramework.GAEffectHandle") +[/Script/HardwareTargeting.HardwareTargetingSettings] +TargetedHardwareClass=Desktop +AppliedTargetedHardwareClass=Desktop +DefaultGraphicsPerformance=Maximum +AppliedDefaultGraphicsPerformance=Maximum -GameEngine=/Script/ActionRPGGame.AREngine -EditorEngine=/Script/ActionRPGGameEditor.AREditorEngine -UnrealEdEngine=/Script/ActionRPGGameEditor.ARUnrealEdEngine -bSmoothFrameRate=False +[/Script/EngineSettings.GameMapsSettings] +GlobalDefaultGameMode=/Game/Prototypes/ProtGameMode.ProtGameMode_C +GameDefaultMap=/Game/Maps/MenuMap.MenuMap +ServerDefaultMap=/Game/Maps/TestMap.TestMap +EditorStartupMap=/Game/Maps/TestMap.TestMap +GameInstanceClass=/Script/ActionRPGGame.ARGameInstance +TransitionMap=/Game/Maps/TransitionMap.TransitionMap [/Script/Engine.RendererSettings] -r.MobileHDR=True -r.AllowOcclusionQueries=True -r.MinScreenRadiusForLights=0.030000 -r.MinScreenRadiusForDepthPrepass=0.030000 -r.PrecomputedVisibilityWarning=False -r.TextureStreaming=True -Compat.UseDXT5NormalMaps=False r.AllowStaticLighting=False -r.NormalMapsForStaticLighting=False -r.GBuffer=True r.GenerateMeshDistanceFields=True -r.Shadow.DistanceFieldPenumbraSize=0.050000 -r.TessellationAdaptivePixelsPerTriangle=48.000000 -r.SeparateTranslucency=True -r.TranslucentSortPolicy=0 -TranslucentSortAxis=(X=0.000000,Y=-1.000000,Z=0.000000) -r.CustomDepth=1 -r.DefaultFeature.Bloom=True -r.DefaultFeature.AmbientOcclusion=True -r.DefaultFeature.AmbientOcclusionStaticFraction=True -r.DefaultFeature.AutoExposure=True -r.DefaultFeature.MotionBlur=True -r.DefaultFeature.LensFlare=True -r.DefaultFeature.AntiAliasing=2 -r.EarlyZPass=3 -r.EarlyZPassMovable=False -r.DBuffer=False -r.ClearSceneMethod=1 -r.WireframeCullThreshold=5.000000 - -r.Shadow.CSM.MaxCascades=10 -r.Shadow.MaxResolution=2048 -UIScaleRule=ShortestSide -UIScaleCurve=(EditorCurveData=(Keys=),ExternalCurve=None) -r.BasePassOutputsVelocity=True -r.ClearCoatNormal=True -bDefaultParticleCutouts=True -r.SkinCache.CompileShaders=False +r.DistanceFieldBuild.EightBit=True r.SupportStationarySkylight=False r.SupportLowQualityLightmaps=False +r.ClearCoatNormal=True +r.DefaultFeature.LensFlare=True +r.GenerateLandscapeGIData=True +r.TemporalAA.Upsampling=False +bDefaultParticleCutouts=True +r.SupportMaterialLayers=True +r.UsePreExposure=True -[/Script/HardwareTargeting.HardwareTargetingSettings] -TargetedHardwareClass=Desktop -AppliedTargetedHardwareClass=Desktop -DefaultGraphicsPerformance=Maximum -AppliedDefaultGraphicsPerformance=Maximum +[/Script/Engine.StreamingSettings] +s.AsyncLoadingThreadEnabled=True -[/Script/EngineSettings.GameMapsSettings] -EditorStartupMap=/Game/Maps/TestLevel/TestLevel.TestLevel -GameDefaultMap=/Game/Maps/TestLevel/TestLevel.TestLevel -GlobalDefaultGameMode=/Game/ThirdPersonBP/Blueprints/ThirdPersonGameMode.ThirdPersonGameMode_C -GlobalDefaultServerGameMode=/Game/ThirdPersonBP/Blueprints/ThirdPersonGameMode.ThirdPersonGameMode_C -bUseSplitscreen=False -ServerDefaultMap=/Game/Maps/TestLevel/TestLevel.TestLevel -TransitionMap=/Game/Maps/TestLevel/TestLevel.TestLevel +[/Script/Engine.UserInterfaceSettings] +bLoadWidgetsOnDedicatedServer=False +UIScaleRule=ShortestSide +UIScaleCurve=(EditorCurveData=(PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant,DefaultValue=340282346638528859811704183484516925440.000000,Keys=((Time=395.331543,Value=0.450000),(Time=668.674805,Value=0.670000),(Time=870.085693,Value=1.000000),(Time=8640.000000,Value=8.000000))),ExternalCurve=None) [/Script/AIModule.AISystem] -bEnableBTAITasks=True -bAllowStrafing=True HotSpotManagerClassName=/Script/AIModule.AIHotSpotManager -bAllowControllersAsEQSQuerier=True +bAllowStrafing=True +bEnableBTAITasks=True + +[PacketSimulationSettings] +PktLag=250 +PktLagVariance=20 +PktLoss=10 +PktOrder=5 +PktDup=0 + +[/Script/UnrealEd.HierarchicalLODSettings] +bForceSettingsInAllMaps=False + +[/Script/Engine.ProxyLODMeshSimplificationSettings] +r.ProxyLODMeshReductionModule=ProxyLODMeshReduction + +[/Script/Engine.NavigationSystemV1] +bAutoCreateNavigationData=True +bAllowClientSideNavigation=False +bInitialBuildingLocked=False +bSkipAgentHeightCheckWhenPickingNavData=False +DataGatheringMode=Lazy +bGenerateNavigationOnlyAroundNavigationInvokers=False +ActiveTilesUpdateInterval=1.000000 ++SupportedAgents=(Name="Default",Color=(B=0,G=255,R=140,A=164),DefaultQueryExtent=(X=50.000000,Y=50.000000,Z=250.000000),NavigationDataClassName=/Script/Engine.RecastNavMesh,AgentRadius=35.000000,AgentHeight=144.000000,AgentStepHeight=-1.000000,NavWalkingSearchHeightScale=0.500000,PreferredNavData=Class'"/Script/Engine.RecastNavMesh"',bCanCrouch=True,bCanJump=True,bCanWalk=True,bCanSwim=True,bCanFly=False) +DirtyAreasUpdateFreq=60.000000 + +[/Script/Engine.AnimationSettings] +bTickAnimationOnSkeletalMeshInit=True [/Script/Engine.GarbageCollectionSettings] -gc.TimeBetweenPurgingPendingKillObjects=20.000000 +gc.TimeBetweenPurgingPendingKillObjects=30.000000 +gc.NumRetriesBeforeForcingGC=0 +gc.ActorClusteringEnabled=True +gc.BlueprintClusteringEnabled=True -[/Script/Engine.AutomationTestSettings] -+EditorTestModules=GameAttributes +[/Script/NoesisRuntime.NoesisSettings] +GlyphTextureSize=x4096 [/Script/Engine.CollisionProfile] --Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.",bCanModify=False) --Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.",bCanModify=False) --Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) --Profiles=(Name="ProjectileBlock",CollisionEnabled=QueryOnly,ObjectTypeName="Projectile",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="Projectile",Response=ECR_Overlap)),HelpMessage="Needs description",bCanModify=True) -Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision",bCanModify=False) -Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False) -Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) @@ -99,16 +88,16 @@ gc.TimeBetweenPurgingPendingKillObjects=20.000000 -Profiles=(Name="IgnoreOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that ignores Pawn and Vehicle. All other channels will be set to default.",bCanModify=False) -Profiles=(Name="OverlapOnlyPawn",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Pawn",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that overlaps Pawn, Camera, and Vehicle. All other channels will be set to default. ",bCanModify=False) -Profiles=(Name="Pawn",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object. Can be used for capsule of any playerable character or AI. ",bCanModify=False) --Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic"),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.",bCanModify=False) +-Profiles=(Name="Spectator",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="WorldStatic",Response=ECR_Block),(Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="PhysicsBody",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Destructible",Response=ECR_Ignore)),HelpMessage="Pawn object that ignores all other actors except WorldStatic.",bCanModify=False) -Profiles=(Name="CharacterMesh",CollisionEnabled=QueryOnly,ObjectTypeName="Pawn",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Vehicle",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Pawn object that is used for Character Mesh. All other channels will be set to default.",bCanModify=False) -Profiles=(Name="PhysicsActor",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=,HelpMessage="Simulating actors",bCanModify=False) -Profiles=(Name="Destructible",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Destructible",CustomResponses=,HelpMessage="Destructible actors",bCanModify=False) -Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.",bCanModify=False) -Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.",bCanModify=False) -Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.",bCanModify=False) -+Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.",bCanModify=False) -+Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) -+Profiles=(Name="ProjectileBlock",CollisionEnabled=QueryOnly,ObjectTypeName="Projectile",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="Projectile",Response=ECR_Overlap)),HelpMessage="Needs description",bCanModify=True) +-Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.",bCanModify=False) +-Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Block),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision",bCanModify=False) +Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False) +Profiles=(Name="OverlapAll",CollisionEnabled=QueryOnly,ObjectTypeName="WorldStatic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Overlap),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) @@ -124,25 +113,24 @@ gc.TimeBetweenPurgingPendingKillObjects=20.000000 +Profiles=(Name="InvisibleWall",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldStatic object that is invisible.",bCanModify=False) +Profiles=(Name="InvisibleWallDynamic",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore)),HelpMessage="WorldDynamic object that is invisible.",bCanModify=False) +Profiles=(Name="Trigger",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility",Response=ECR_Ignore),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldDynamic object that is used for trigger. All other channels will be set to default.",bCanModify=False) -+Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.",bCanModify=False) --DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,Name="EffectField",DefaultResponse=ECR_Overlap,bTraceType=False,bStaticObject=False) --DefaultChannelResponses=(Channel=ECC_GameTraceChannel3,Name="PawnMesh",DefaultResponse=ECR_Ignore,bTraceType=False,bStaticObject=False) --DefaultChannelResponses=(Channel=ECC_GameTraceChannel4,Name="Weapon",DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False) --DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,Name="Projectile",DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False) -+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,Name="Projectile",DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False) -+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,Name="EffectField",DefaultResponse=ECR_Overlap,bTraceType=False,bStaticObject=False) -+DefaultChannelResponses=(Channel=ECC_GameTraceChannel3,Name="PawnMesh",DefaultResponse=ECR_Ignore,bTraceType=False,bStaticObject=False) -+DefaultChannelResponses=(Channel=ECC_GameTraceChannel4,Name="Weapon",DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False) ++Profiles=(Name="Ragdoll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="PhysicsBody",CustomResponses=((Channel="Pawn",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Ignore)),HelpMessage="Simulating Skeletal Mesh Component. All other channels will be set to default.",bCanModify=False) ++Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.",bCanModify=False) ++Profiles=(Name="UI",CollisionEnabled=QueryOnly,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ",bCanModify=False) ++DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,Name="Enemy",DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False) ++DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,Name="Pickup",DefaultResponse=ECR_Overlap,bTraceType=True,bStaticObject=False) ++DefaultChannelResponses=(Channel=ECC_GameTraceChannel3,Name="Weapon",DefaultResponse=ECR_Overlap,bTraceType=True,bStaticObject=False) ++DefaultChannelResponses=(Channel=ECC_GameTraceChannel4,Name="PikcupObject",DefaultResponse=ECR_Ignore,bTraceType=False,bStaticObject=False) ++EditProfiles=(Name="Pawn",CustomResponses=((Channel="Enemy",Response=ECR_Overlap))) +-ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") -ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") +-ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") -ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor") --ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") -ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic") --ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") ++ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") ++ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") +ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") +ProfileRedirects=(OldName="SkeletalMeshActor",NewName="PhysicsActor") +ProfileRedirects=(OldName="InvisibleActor",NewName="InvisibleWallDynamic") -+ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") -+ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") -CollisionChannelRedirects=(OldName="Static",NewName="WorldStatic") -CollisionChannelRedirects=(OldName="Dynamic",NewName="WorldDynamic") -CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle") @@ -152,51 +140,21 @@ gc.TimeBetweenPurgingPendingKillObjects=20.000000 +CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle") +CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn") -[/Script/Engine.UserInterfaceSettings] -RenderFocusRule=NavigationOnly -DefaultCursor=None -TextEditBeamCursor=None -CrosshairsCursor=None -HandCursor=None -GrabHandCursor=None -GrabHandClosedCursor=None -SlashedCircleCursor=None -ApplicationScale=1.000000 -UIScaleRule=ShortestSide -CustomScalingRuleClass=None -UIScaleCurve=(EditorCurveData=(PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant,Keys=((Time=480.000000,Value=0.444000),(Time=720.000000,Value=0.666000),(Time=1080.000000,Value=1.000000),(Time=8640.000000,Value=8.000000)),DefaultValue=340282346638528859811704183484516925440.000000),ExternalCurve=None) - -[/Script/UMGEditor.UMGEditorProjectSettings] -bShowWidgetsFromEngineContent=True - -[/Script/Engine.StreamingSettings] -s.AsyncLoadingThreadEnabled=True -s.EventDrivenLoaderEnabled=True - -[Niagara] -EnableNiagara=true - -[/Script/Engine.NavigationSystem] -bAutoCreateNavigationData=True -bAllowClientSideNavigation=False -bInitialBuildingLocked=False -bSkipAgentHeightCheckWhenPickingNavData=False -DataGatheringMode=Instant -bGenerateNavigationOnlyAroundNavigationInvokers=False -ActiveTilesUpdateInterval=1.000000 -+SupportedAgents=(Name="Default",Color=(B=0,G=255,R=140,A=164),DefaultQueryExtent=(X=50.000000,Y=50.000000,Z=250.000000),NavigationDataClassName=/Script/Engine.RecastNavMesh,AgentRadius=35.000000,AgentHeight=144.000000,AgentStepHeight=-1.000000,NavWalkingSearchHeightScale=0.500000,PreferredNavData=None,bCanCrouch=False,bCanJump=False,bCanWalk=False,bCanSwim=False,bCanFly=False) -DirtyAreasUpdateFreq=60.000000 - -[/Script/Engine.MeshSimplificationSettings] -r.MeshReductionModule=SimplygonMeshReduction - [/Script/WindowsTargetPlatform.WindowsTargetSettings] -Compiler=VisualStudio2017 - -[/Script/Niagara.NiagaraSettings] -DefaultEffect=None -DefaultEmitter=None -DefaultScript=None +Compiler=Default +-TargetedRHIs=PCD3D_SM5 +-TargetedRHIs=PCD3D_SM4 ++TargetedRHIs=PCD3D_SM5 +MinimumOSVersion=MSOS_Vista +AudioDevice= +AudioSampleRate=48000 +AudioCallbackBufferFrameSize=1024 +AudioNumBuffersToEnqueue=1 +AudioMaxChannels=0 +AudioNumSourceWorkers=4 +SpatializationPlugin= +ReverbPlugin= +OcclusionPlugin= [/Script/Engine.PhysicsSettings] DefaultGravityZ=-980.000000 @@ -207,10 +165,11 @@ RagdollAggregateThreshold=4 TriangleMeshTriangleMinAreaThreshold=5.000000 bEnableAsyncScene=True bEnableShapeSharing=True -bEnablePCM=False -bEnableStabilization=False +bEnablePCM=True +bEnableStabilization=True bWarnMissingLocks=True bEnable2DPhysics=False +PhysicErrorCorrection=(PingExtrapolation=0.100000,ErrorPerLinearDifference=1.000000,ErrorPerAngularDifference=1.000000,MaxRestoredStateError=1.000000,PositionLerp=0.000000,AngleLerp=0.400000,LinearVelocityCoefficient=100.000000,AngularVelocityCoefficient=10.000000,ErrorAccumulationSeconds=0.500000,ErrorAccumulationDistanceSq=15.000000,ErrorAccumulationSimilarity=100.000000) LockedAxis=Invalid DefaultDegreesOfFreedom=Full3D BounceThresholdVelocity=200.000000 @@ -218,23 +177,29 @@ FrictionCombineMode=Average RestitutionCombineMode=Average MaxAngularVelocity=3600.000000 MaxDepenetrationVelocity=0.000000 -ContactOffsetMultiplier=0.010000 -MinContactOffset=0.000100 -MaxContactOffset=1.000000 +ContactOffsetMultiplier=0.020000 +MinContactOffset=2.000000 +MaxContactOffset=8.000000 bSimulateSkeletalMeshOnDedicatedServer=True DefaultShapeComplexity=CTF_UseSimpleAndComplex bDefaultHasComplexCollision=True bSuppressFaceRemapTable=False bSupportUVFromHitResults=False bDisableActiveActors=False +bDisableKinematicStaticPairs=False +bDisableKinematicKinematicPairs=False bDisableCCD=False -bEnableEnhancedDeterminism=False +bEnableEnhancedDeterminism=True MaxPhysicsDeltaTime=0.033333 -bSubstepping=False -bSubsteppingAsync=False -MaxSubstepDeltaTime=0.016667 -MaxSubsteps=6 +bSubstepping=True +bSubsteppingAsync=True +MaxSubstepDeltaTime=0.033000 +MaxSubsteps=2 SyncSceneSmoothingFactor=0.000000 AsyncSceneSmoothingFactor=0.990000 InitialAverageFrameRate=0.016667 PhysXTreeRebuildRate=10 +ClientBroadphaseSettings=(bUseMBP=False,MBPBounds=(Min=(X=0.000000,Y=0.000000,Z=0.000000),Max=(X=0.000000,Y=0.000000,Z=0.000000),IsValid=0),MBPNumSubdivs=2) +ServerBroadphaseSettings=(bUseMBP=False,MBPBounds=(Min=(X=0.000000,Y=0.000000,Z=0.000000),Max=(X=0.000000,Y=0.000000,Z=0.000000),IsValid=0),MBPNumSubdivs=2) + + diff --git a/Config/DefaultGame.ini b/Config/DefaultGame.ini index 7b3a394..6c6fd12 100644 --- a/Config/DefaultGame.ini +++ b/Config/DefaultGame.ini @@ -1,63 +1,58 @@ -[StartupActions] -bAddPacks=True -InsertPack=(PackSource="StarterContent.upack",PackName="StarterContent") - [/Script/EngineSettings.GeneralProjectSettings] -CompanyName= -CopyrightNotice=Fill out your copyright notice in the Description page of Project Settings. -Description= -Homepage= -LicensingTerms= -PrivacyPolicy= -ProjectID=4EF791F14E9D23C40368B18C5D926129 -ProjectName= -ProjectVersion= -SupportContact= -ProjectDisplayedTitle= +ProjectID=53E63CC7411F280A64FAD489EBFD3E33 +ProjectName=Third Person Game Template -[/Script/Engine.AssetManagerSettings] --PrimaryAssetTypesToScan=(PrimaryAssetType="Map",AssetBaseClass=/Script/Engine.World,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game/Maps")),SpecificAssets=,Rules=(Priority=-1,bApplyRecursively=True,ChunkId=-1,CookRule=Unknown)) --PrimaryAssetTypesToScan=(PrimaryAssetType="Map",AssetBaseClass=/Script/Engine.World,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game/Maps")),SpecificAssets=,Rules=(Priority=-1,bApplyRecursively=True,ChunkId=-1,CookRule=Unknown)) --PrimaryAssetTypesToScan=(PrimaryAssetType="Level",AssetBaseClass=/Script/Engine.Level,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="Maps")),SpecificAssets=,Rules=(Priority=-1,bApplyRecursively=True,ChunkId=-1,CookRule=AlwaysCook)) -+PrimaryAssetTypesToScan=(PrimaryAssetType="Map",AssetBaseClass=/Script/Engine.World,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game/Maps")),SpecificAssets=,Rules=(Priority=-1,bApplyRecursively=True,ChunkId=-1,CookRule=Unknown)) -+PrimaryAssetTypesToScan=(PrimaryAssetType="Map",AssetBaseClass=/Script/Engine.World,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game/Maps")),SpecificAssets=,Rules=(Priority=-1,bApplyRecursively=True,ChunkId=-1,CookRule=Unknown)) -bOnlyCookProductionAssets=False +[/Script/AbilityFramework.AFCueManager] +DefaultCueSet=/Game/Prototypes/ProtCueSet.ProtCueSet [/Script/UnrealEd.ProjectPackagingSettings] -BuildConfiguration=PPBC_Shipping -StagingDirectory=(Path="") +Build=IfProjectHasCode +BuildConfiguration=PPBC_Development +StagingDirectory=(Path="D:/Unreal/UE-Master/ActionRPGGame/Saved/StagedBuilds") FullRebuild=False ForDistribution=False -IncludeDebugFiles=True +IncludeDebugFiles=False BlueprintNativizationMethod=Disabled -bWarnIfPackagedWithoutNativizationFlag=True +bIncludeNativizedAssetsInProjectGeneration=False +bExcludeMonolithicEngineHeadersInNativizedCode=False UsePakFile=True -bGenerateChunks=False +bGenerateChunks=True bGenerateNoChunks=False bChunkHardReferencesOnly=False bBuildHttpChunkInstallData=False HttpChunkInstallDataDirectory=(Path="") HttpChunkInstallDataVersion= IncludePrerequisites=True -IncludeAppLocalPrerequisites=False +IncludeAppLocalPrerequisites=True bShareMaterialShaderCode=False bSharedMaterialNativeLibraries=False -ApplocalPrerequisitesDirectory=(Path="") -IncludeCrashReporter=True +ApplocalPrerequisitesDirectory=(Path="$(EngineDir)/Binaries/ThirdParty/AppLocalDependencies") +IncludeCrashReporter=False InternationalizationPreset=English -CulturesToStage=en +CulturesToStage=en -DefaultCulture=en bCookAll=False bCookMapsOnly=False bCompressed=False bEncryptIniFiles=False bEncryptPakIndex=False bSkipEditorContent=False --DirectoriesToAlwaysCook=(Path="") -+DirectoriesToAlwaysCook=(Path="Prototypes") +bSkipMovies=False bNativizeBlueprintAssets=False bNativizeOnlySelectedBlueprints=False -[/Script/AbilityFramework.AFCueManager] -DefaultCueSet=/Game/Prototypes/TestCueSet.TestCueSet +[/Script/Engine.AssetManagerSettings] +-PrimaryAssetTypesToScan=(PrimaryAssetType="Map",AssetBaseClass=/Script/Engine.World,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game/Maps"))) +-PrimaryAssetTypesToScan=(PrimaryAssetType="PrimaryAssetLabel",AssetBaseClass=/Script/Engine.PrimaryAssetLabel,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game"))) ++PrimaryAssetTypesToScan=(PrimaryAssetType="Map",AssetBaseClass=/Script/Engine.World,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game/Maps")),SpecificAssets=,Rules=(Priority=-1,bApplyRecursively=True,ChunkId=-1,CookRule=Unknown)) ++PrimaryAssetTypesToScan=(PrimaryAssetType="PrimaryAssetLabel",AssetBaseClass=/Script/Engine.PrimaryAssetLabel,bHasBlueprintClasses=False,bIsEditorOnly=True,Directories=((Path="/Game")),SpecificAssets=,Rules=(Priority=-1,bApplyRecursively=True,ChunkId=-1,CookRule=Unknown)) ++PrimaryAssetTypesToScan=(PrimaryAssetType="Ability",AssetBaseClass=/Script/AbilityFramework.GAAbilityBase,bHasBlueprintClasses=True,bIsEditorOnly=False,Directories=((Path="/Game")),SpecificAssets=,Rules=(Priority=1,bApplyRecursively=True,ChunkId=-1,CookRule=AlwaysCook)) ++PrimaryAssetTypesToScan=(PrimaryAssetType="ActorCue",AssetBaseClass=/Script/AbilityFramework.AFCueActor,bHasBlueprintClasses=True,bIsEditorOnly=False,Directories=((Path="/Game")),SpecificAssets=,Rules=(Priority=1,bApplyRecursively=True,ChunkId=-1,CookRule=AlwaysCook)) ++PrimaryAssetTypesToScan=(PrimaryAssetType="StaticCue",AssetBaseClass=/Script/AbilityFramework.AFCueStatic,bHasBlueprintClasses=True,bIsEditorOnly=False,Directories=((Path="/Game")),SpecificAssets=,Rules=(Priority=-1,bApplyRecursively=True,ChunkId=-1,CookRule=AlwaysCook)) +bOnlyCookProductionAssets=False +bShouldManagerDetermineTypeAndName=False +bShouldGuessTypeAndNameInEditor=True +bShouldAcquireMissingChunksOnLoad=False +MetaDataTagsForAssetRegistry=() + + diff --git a/Config/DefaultGameplayTags.ini b/Config/DefaultGameplayTags.ini index 96fcac8..17e90cc 100644 --- a/Config/DefaultGameplayTags.ini +++ b/Config/DefaultGameplayTags.ini @@ -5,108 +5,57 @@ WarnOnInvalidTags=True FastReplication=False NumBitsForContainerSize=6 NetIndexFirstBitSegment=16 --GameplayTagList=(Tag="Ability.Blizzard",DevComment="") --GameplayTagList=(Tag="Ability.Fireball",DevComment="") --GameplayTagList=(Tag="Ability.Fireball.Activation",DevComment="") --GameplayTagList=(Tag="Ability.Fireblast",DevComment="") --GameplayTagList=(Tag="Ability.ForstBolt",DevComment="") --GameplayTagList=(Tag="Ability.MachineGun.Damage",DevComment="") --GameplayTagList=(Tag="Ability.TestAbility",DevComment="") --GameplayTagList=(Tag="Action01",DevComment="") --GameplayTagList=(Tag="Attribute.Health",DevComment="") --GameplayTagList=(Tag="Binding.MouseLeftAction",DevComment="") --GameplayTagList=(Tag="Binding.MouseRightAction",DevComment="") --GameplayTagList=(Tag="Buff",DevComment="") --GameplayTagList=(Tag="Condition",DevComment="") --GameplayTagList=(Tag="Condition.Burning",DevComment="") --GameplayTagList=(Tag="Damage.Acid",DevComment="") --GameplayTagList=(Tag="Damage.Basic",DevComment="") --GameplayTagList=(Tag="Damage.Buff",DevComment="") --GameplayTagList=(Tag="Damage.Buffable",DevComment="") --GameplayTagList=(Tag="Damage.Buffed.FireBuff",DevComment="") --GameplayTagList=(Tag="Damage.Darkness",DevComment="") --GameplayTagList=(Tag="Damage.Earth",DevComment="") --GameplayTagList=(Tag="Damage.Electricity",DevComment="") --GameplayTagList=(Tag="Damage.Fire",DevComment="") --GameplayTagList=(Tag="Damage.Ice",DevComment="") --GameplayTagList=(Tag="Damage.Mitigated.Armor",DevComment="") --GameplayTagList=(Tag="Damage.Necrotic",DevComment="") --GameplayTagList=(Tag="Damage.Physical",DevComment="") --GameplayTagList=(Tag="Damage.Radiant",DevComment="") --GameplayTagList=(Tag="Damage.Reduce",DevComment="") --GameplayTagList=(Tag="Damage.Spell",DevComment="") --GameplayTagList=(Tag="Damage.Type1",DevComment="") --GameplayTagList=(Tag="Damage.Type2",DevComment="") --GameplayTagList=(Tag="Damage.Water",DevComment="") --GameplayTagList=(Tag="Enchantment",DevComment="") --GameplayTagList=(Tag="GameplayCue.Burning",DevComment="") --GameplayTagList=(Tag="GameplayCue.Test.X",DevComment="") --GameplayTagList=(Tag="Hex",DevComment="") --GameplayTagList=(Tag="Immune",DevComment="") --GameplayTagList=(Tag="Immune.Fire",DevComment="") --GameplayTagList=(Tag="Immune.Ice",DevComment="") --GameplayTagList=(Tag="Item.Rune",DevComment="") --GameplayTagList=(Tag="Lifesteal",DevComment="") --GameplayTagList=(Tag="Perk.Ability.Fireball.Damage",DevComment="") --GameplayTagList=(Tag="Protect.Damage",DevComment="") --GameplayTagList=(Tag="Shield",DevComment="") --GameplayTagList=(Tag="ShieldAbsorb",DevComment="") --GameplayTagList=(Tag="Spell",DevComment="") --GameplayTagList=(Tag="Stack",DevComment="") --GameplayTagList=(Tag="Stack.CappedNumber",DevComment="") --GameplayTagList=(Tag="Stack.DiminishingReturns",DevComment="") --GameplayTagList=(Tag="Stackable",DevComment="") -+GameplayTagList=(Tag="Ability.Blizzard",DevComment="") -+GameplayTagList=(Tag="Ability.Fireball",DevComment="") -+GameplayTagList=(Tag="Ability.Fireball.Activation",DevComment="") -+GameplayTagList=(Tag="Ability.Fireblast",DevComment="") -+GameplayTagList=(Tag="Ability.ForstBolt",DevComment="") -+GameplayTagList=(Tag="Ability.MachineGun.Damage",DevComment="") -+GameplayTagList=(Tag="Ability.TestAbility",DevComment="") -+GameplayTagList=(Tag="Action01",DevComment="") -+GameplayTagList=(Tag="Attribute.Health",DevComment="") -+GameplayTagList=(Tag="Binding.MouseLeftAction",DevComment="") -+GameplayTagList=(Tag="Binding.MouseRightAction",DevComment="") -+GameplayTagList=(Tag="Buff",DevComment="") -+GameplayTagList=(Tag="Condition",DevComment="") -+GameplayTagList=(Tag="Condition.Burning",DevComment="") -+GameplayTagList=(Tag="Damage.Acid",DevComment="") -+GameplayTagList=(Tag="Damage.Basic",DevComment="") -+GameplayTagList=(Tag="Damage.Buff",DevComment="") -+GameplayTagList=(Tag="Damage.Buffable",DevComment="") -+GameplayTagList=(Tag="Damage.Buffed.FireBuff",DevComment="") -+GameplayTagList=(Tag="Damage.Darkness",DevComment="") -+GameplayTagList=(Tag="Damage.Earth",DevComment="") -+GameplayTagList=(Tag="Damage.Electricity",DevComment="") ++GameplayTagList=(Tag="Ability.AbilityCooldow01.Cooldown",DevComment="") ++GameplayTagList=(Tag="Ability.AbilityCooldown02.Cooldown",DevComment="") ++GameplayTagList=(Tag="Ability.Corruption",DevComment="") ++GameplayTagList=(Tag="Ability.Corruption.Cooldown",DevComment="") ++GameplayTagList=(Tag="Ability.DurationInstance",DevComment="") ++GameplayTagList=(Tag="Ability.EffectInstance",DevComment="") ++GameplayTagList=(Tag="Ability.EffectInstance.Damage",DevComment="") ++GameplayTagList=(Tag="Ability.Input.GolsterWeapon",DevComment="") ++GameplayTagList=(Tag="Ability.Input.HolsterWeapon",DevComment="") ++GameplayTagList=(Tag="Ability.Input.Jump",DevComment="") ++GameplayTagList=(Tag="Ability.Input.NextWeapon",DevComment="") ++GameplayTagList=(Tag="Ability.Input.PreviousWeapon",DevComment="") ++GameplayTagList=(Tag="Ability.Input.SetAbilityGroup01",DevComment="") ++GameplayTagList=(Tag="Ability.Input.SetAbilityGroup02",DevComment="") ++GameplayTagList=(Tag="Ability.Input.SwitchAbilities",DevComment="") ++GameplayTagList=(Tag="Ability.Rifle",DevComment="") ++GameplayTagList=(Tag="Ability.Rifle.Activate",DevComment="") ++GameplayTagList=(Tag="Ability.Rifle.Ammo",DevComment="") ++GameplayTagList=(Tag="Ability.Rifle.Damage",DevComment="") ++GameplayTagList=(Tag="Ability.Rifle.Reload",DevComment="") ++GameplayTagList=(Tag="Ability.Rifle.Shoot",DevComment="") ++GameplayTagList=(Tag="Ability.Shotgun",DevComment="") ++GameplayTagList=(Tag="Ability.UI.NextWeapon",DevComment="") ++GameplayTagList=(Tag="Ability.UI.PreviousWeapon",DevComment="") ++GameplayTagList=(Tag="Action.Shooting",DevComment="") ++GameplayTagList=(Tag="AI.HaveAxe",DevComment="") ++GameplayTagList=(Tag="AI.HaveOre",DevComment="") ++GameplayTagList=(Tag="AI.HavePick",DevComment="") ++GameplayTagList=(Tag="AI.HaveWood",DevComment="") ++GameplayTagList=(Tag="AI.WoodCollected",DevComment="") ++GameplayTagList=(Tag="Cue.Ability.Shoot",DevComment="") ++GameplayTagList=(Tag="Damage",DevComment="") ++GameplayTagList=(Tag="Damage.Damage",DevComment="") +GameplayTagList=(Tag="Damage.Fire",DevComment="") -+GameplayTagList=(Tag="Damage.Ice",DevComment="") -+GameplayTagList=(Tag="Damage.Mitigated.Armor",DevComment="") -+GameplayTagList=(Tag="Damage.Necrotic",DevComment="") -+GameplayTagList=(Tag="Damage.Physical",DevComment="") -+GameplayTagList=(Tag="Damage.Radiant",DevComment="") -+GameplayTagList=(Tag="Damage.Reduce",DevComment="") -+GameplayTagList=(Tag="Damage.Spell",DevComment="") -+GameplayTagList=(Tag="Damage.Type1",DevComment="") -+GameplayTagList=(Tag="Damage.Type2",DevComment="") -+GameplayTagList=(Tag="Damage.Water",DevComment="") -+GameplayTagList=(Tag="Enchantment",DevComment="") -+GameplayTagList=(Tag="Event.Damage",DevComment="") -+GameplayTagList=(Tag="GameplayCue.Burning",DevComment="") -+GameplayTagList=(Tag="GameplayCue.Test.X",DevComment="") -+GameplayTagList=(Tag="Hex",DevComment="") -+GameplayTagList=(Tag="Immune",DevComment="") -+GameplayTagList=(Tag="Immune.Fire",DevComment="") -+GameplayTagList=(Tag="Immune.Ice",DevComment="") -+GameplayTagList=(Tag="Item.Rune",DevComment="") -+GameplayTagList=(Tag="Lifesteal",DevComment="") -+GameplayTagList=(Tag="Perk.Ability.Fireball.Damage",DevComment="") -+GameplayTagList=(Tag="Protect.Damage",DevComment="") -+GameplayTagList=(Tag="Shield",DevComment="") -+GameplayTagList=(Tag="ShieldAbsorb",DevComment="") -+GameplayTagList=(Tag="Spell",DevComment="") -+GameplayTagList=(Tag="Stack",DevComment="") -+GameplayTagList=(Tag="Stack.CappedNumber",DevComment="") -+GameplayTagList=(Tag="Stack.DiminishingReturns",DevComment="") -+GameplayTagList=(Tag="Stackable",DevComment="") ++GameplayTagList=(Tag="Effect.InstancedDuration",DevComment="") ++GameplayTagList=(Tag="EffectEvent.Expired.InstancedDuration",DevComment="") ++GameplayTagList=(Tag="Event.Executed.Damage.Fire",DevComment="") ++GameplayTagList=(Tag="Event.Executed.Shoot.AssaultRifle",DevComment="") ++GameplayTagList=(Tag="Fire",DevComment="") ++GameplayTagList=(Tag="Input.Ability01.Activate",DevComment="") ++GameplayTagList=(Tag="Input.Ability02",DevComment="") ++GameplayTagList=(Tag="Input.Ability02.Activate",DevComment="") ++GameplayTagList=(Tag="Input.Ability03",DevComment="") ++GameplayTagList=(Tag="Input.Ability03.Activate",DevComment="") ++GameplayTagList=(Tag="Input.Gun.Reload",DevComment="") ++GameplayTagList=(Tag="Input.Gun.Shoot",DevComment="") ++GameplayTagList=(Tag="Input.UI.Holster",DevComment="") ++GameplayTagList=(Tag="Input.UI.SetAbilityGroup01",DevComment="") ++GameplayTagList=(Tag="Input.UI.SetAbilityGroup02",DevComment="") ++GameplayTagList=(Tag="Input.UI.WeaponNext",DevComment="") ++GameplayTagList=(Tag="Input.UI.WeaponPrevious",DevComment="") ++GameplayTagList=(Tag="Item.Weapon.AssaultRifle",DevComment="") diff --git a/Config/DefaultInput.ini b/Config/DefaultInput.ini index 1bcd62d..8dd4a35 100644 --- a/Config/DefaultInput.ini +++ b/Config/DefaultInput.ini @@ -1,26 +1,17 @@ [/Script/Engine.InputSettings] --AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MotionController_Right_TriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MotionController_Right_Grip1Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MotionController_Right_Grip2Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="Gamepad_Special_Left_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="Gamepad_Special_Left_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.250000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.000000,Sensitivity=0.070000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MouseWheelAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="Gamepad_LeftTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="Gamepad_RightTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MotionController_Left_TriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MotionController_Left_Grip1Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MotionController_Left_Grip2Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) --AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) +-AxisConfig=(AxisKeyName="Gamepad_LeftX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_LeftY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_RightX",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="Gamepad_RightY",AxisProperties=(DeadZone=0.25,Exponent=1.f,Sensitivity=1.f)) +-AxisConfig=(AxisKeyName="MouseX",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) +-AxisConfig=(AxisKeyName="MouseY",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) ++AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MotionController_Left_TriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MotionController_Left_Grip1Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MotionController_Left_Grip2Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) +AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) +AxisConfig=(AxisKeyName="MotionController_Right_TriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) +AxisConfig=(AxisKeyName="MotionController_Right_Grip1Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) @@ -36,75 +27,49 @@ +AxisConfig=(AxisKeyName="MouseWheelAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) +AxisConfig=(AxisKeyName="Gamepad_LeftTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) +AxisConfig=(AxisKeyName="Gamepad_RightTriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) -+AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) -+AxisConfig=(AxisKeyName="MotionController_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) -+AxisConfig=(AxisKeyName="MotionController_Left_TriggerAxis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) -+AxisConfig=(AxisKeyName="MotionController_Left_Grip1Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) -+AxisConfig=(AxisKeyName="MotionController_Left_Grip2Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) -+AxisConfig=(AxisKeyName="MotionController_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) bAltEnterTogglesFullscreen=True bF11TogglesFullscreen=True bUseMouseForTouch=False -bEnableMouseSmoothing=False +bEnableMouseSmoothing=True bEnableFOVScaling=True -FOVScale=0.011110 -DoubleClickTime=0.200000 bCaptureMouseOnLaunch=True -DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown bDefaultViewportMouseLock=False -DefaultViewportMouseLockMode=LockOnCapture --ActionMappings=(ActionName="Jump",Key=SpaceBar,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --ActionMappings=(ActionName="Jump",Key=Gamepad_FaceButton_Bottom,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --ActionMappings=(ActionName="Action01",Key=One,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --ActionMappings=(ActionName="Action02",Key=Two,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --ActionMappings=(ActionName="Action03",Key=Three,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --ActionMappings=(ActionName="Action04",Key=Four,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --ActionMappings=(ActionName="Action05",Key=Five,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --ActionMappings=(ActionName="Action06",Key=Six,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --ActionMappings=(ActionName="Action07",Key=Seven,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --ActionMappings=(ActionName="Binding.MouseLeftAction",Key=LeftMouseButton,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --ActionMappings=(ActionName="Bind.MouseRightAction",Key=RightMouseButton,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Jump",Key=SpaceBar,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Jump",Key=Gamepad_FaceButton_Bottom,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Action01",Key=One,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Action02",Key=Two,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Action03",Key=Three,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Action04",Key=Four,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Action05",Key=Five,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Action06",Key=Six,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Action07",Key=Seven,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Binding.MouseLeftAction",Key=LeftMouseButton,bShift=False,bCtrl=False,bAlt=False,bCmd=False) -+ActionMappings=(ActionName="Binding.MouseRightAction",Key=RightMouseButton,bShift=False,bCtrl=False,bAlt=False,bCmd=False) --AxisMappings=(AxisName="MoveForward",Key=W,Scale=1.000000) --AxisMappings=(AxisName="MoveForward",Key=S,Scale=-0.750000) --AxisMappings=(AxisName="MoveForward",Key=Up,Scale=1.000000) --AxisMappings=(AxisName="MoveForward",Key=Down,Scale=-1.000000) --AxisMappings=(AxisName="MoveForward",Key=Gamepad_LeftY,Scale=1.000000) --AxisMappings=(AxisName="MoveRight",Key=A,Scale=-1.000000) --AxisMappings=(AxisName="MoveRight",Key=D,Scale=1.000000) --AxisMappings=(AxisName="MoveRight",Key=Gamepad_LeftX,Scale=1.000000) --AxisMappings=(AxisName="TurnRate",Key=Gamepad_RightX,Scale=1.000000) --AxisMappings=(AxisName="TurnRate",Key=Left,Scale=-1.000000) --AxisMappings=(AxisName="TurnRate",Key=Right,Scale=1.000000) --AxisMappings=(AxisName="Turn",Key=MouseX,Scale=1.000000) --AxisMappings=(AxisName="LookUpRate",Key=Gamepad_RightY,Scale=1.000000) --AxisMappings=(AxisName="LookUp",Key=MouseY,Scale=-1.000000) -+AxisMappings=(AxisName="MoveForward",Key=W,Scale=1.000000) -+AxisMappings=(AxisName="MoveForward",Key=S,Scale=-0.750000) -+AxisMappings=(AxisName="MoveForward",Key=Up,Scale=1.000000) -+AxisMappings=(AxisName="MoveForward",Key=Down,Scale=-1.000000) -+AxisMappings=(AxisName="MoveForward",Key=Gamepad_LeftY,Scale=1.000000) -+AxisMappings=(AxisName="MoveRight",Key=A,Scale=-1.000000) -+AxisMappings=(AxisName="MoveRight",Key=D,Scale=1.000000) -+AxisMappings=(AxisName="MoveRight",Key=Gamepad_LeftX,Scale=1.000000) -+AxisMappings=(AxisName="TurnRate",Key=Gamepad_RightX,Scale=1.000000) -+AxisMappings=(AxisName="TurnRate",Key=Left,Scale=-1.000000) -+AxisMappings=(AxisName="TurnRate",Key=Right,Scale=1.000000) -+AxisMappings=(AxisName="Turn",Key=MouseX,Scale=1.000000) -+AxisMappings=(AxisName="LookUpRate",Key=Gamepad_RightY,Scale=1.000000) -+AxisMappings=(AxisName="LookUp",Key=MouseY,Scale=-1.000000) bAlwaysShowTouchInterface=False bShowConsoleOnFourFingerTap=True +bEnableGestureRecognizer=False +bUseAutocorrect=False +DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown +DefaultViewportMouseLockMode=LockOnCapture +FOVScale=0.011110 +DoubleClickTime=0.200000 ++ActionMappings=(ActionName="Jump",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=SpaceBar) ++ActionMappings=(ActionName="Jump",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Gamepad_FaceButton_Bottom) ++ActionMappings=(ActionName="Shoot",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton) ++ActionMappings=(ActionName="Reload",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=R) ++ActionMappings=(ActionName="SwitchAbilitySet",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=B) ++ActionMappings=(ActionName="InputAbilityManager",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=K) ++ActionMappings=(ActionName="NextWeapon",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MouseScrollUp) ++ActionMappings=(ActionName="Input.UI.WeaponPrevious",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=MouseScrollDown) ++ActionMappings=(ActionName="InputInventory",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=I) ++ActionMappings=(ActionName="Input.UI.Holster",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=O) ++ActionMappings=(ActionName="Ability01",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=One) ++ActionMappings=(ActionName="Ability02",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Two) ++ActionMappings=(ActionName="Ability03",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Three) ++ActionMappings=(ActionName="Ability04",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=Four) ++AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=W) ++AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=S) ++AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=Up) ++AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=Down) ++AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=Gamepad_LeftY) ++AxisMappings=(AxisName="MoveRight",Scale=-1.000000,Key=A) ++AxisMappings=(AxisName="MoveRight",Scale=1.000000,Key=D) ++AxisMappings=(AxisName="MoveRight",Scale=1.000000,Key=Gamepad_LeftX) ++AxisMappings=(AxisName="TurnRate",Scale=1.000000,Key=Gamepad_RightX) ++AxisMappings=(AxisName="TurnRate",Scale=-1.000000,Key=Left) ++AxisMappings=(AxisName="TurnRate",Scale=1.000000,Key=Right) ++AxisMappings=(AxisName="Turn",Scale=1.000000,Key=MouseX) ++AxisMappings=(AxisName="LookUpRate",Scale=1.000000,Key=Gamepad_RightY) ++AxisMappings=(AxisName="LookUp",Scale=-1.000000,Key=MouseY) DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks ConsoleKey=None -ConsoleKeys=Tilde diff --git a/Content/Blueprints/Test_CameraManager.uasset b/Content/Blueprints/Test_CameraManager.uasset new file mode 100644 index 0000000..4695021 Binary files /dev/null and b/Content/Blueprints/Test_CameraManager.uasset differ diff --git a/Plugins/AbilityFramework/AbilityFramework.uplugin b/Plugins/AbilityFramework/AbilityFramework.uplugin new file mode 100644 index 0000000..49c5851 --- /dev/null +++ b/Plugins/AbilityFramework/AbilityFramework.uplugin @@ -0,0 +1,34 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "AbilityFramework", + "Description": "", + "Category": "Gameplay", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": true, + "Installed": true, + "Modules": [ + { + "Name": "AbilityFramework", + "Type": "Runtime", + "LoadingPhase": "Default" + }, + { + "Name": "AbilityFrameworkEditor", + "Type": "Editor", + "LoadingPhase": "PostEngineInit" + } + ], + "Plugins": [ + { + "Name": "ActorSequence", + "Enabled": true + } + ] +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/AbilityFramework.Build.cs b/Plugins/AbilityFramework/Source/AbilityFramework/AbilityFramework.Build.cs new file mode 100644 index 0000000..3230335 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/AbilityFramework.Build.cs @@ -0,0 +1,56 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +namespace UnrealBuildTool.Rules +{ + public class AbilityFramework : ModuleRules + { + public AbilityFramework(ReadOnlyTargetRules Target) : base(Target) + { + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "CoreUObject", + "Engine", + "GameplayTags", + "InputCore", + "UMG", + "Slate", + "SlateCore", + "AIModule", + "MovieScene", + "MovieSceneTracks", + "AssetRegistry" + // ... add other public dependencies that you statically link with here ... + } + ); + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "ActorSequence", + "TimeManagement" + // ... add private dependencies that you statically link with here ... + } + ); + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + + // ... add any modules that your module loads dynamically here ... + } + ); + if (Target.Type == TargetRules.TargetType.Editor) + { + PublicDependencyModuleNames.AddRange(new string[] { "UnrealEd", "PropertyEditor" }); + } + } + } +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAbilityComponent.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAbilityComponent.cpp new file mode 100644 index 0000000..2b1665d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAbilityComponent.cpp @@ -0,0 +1,526 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" + +#include "Abilities/GAAbilityBase.h" +#include "Abilities/Tasks/GAAbilityTask.h" +#include "IAbilityFramework.h" + +#include "Net/UnrealNetwork.h" +#include "Engine/ActorChannel.h" +#include "Animation/AnimInstance.h" +#include "Animation/AnimMontage.h" +#include "Attributes/GAAttributesBase.h" +#include "AFAbilityInterface.h" +#include "Effects/GAEffectExecution.h" +#include "Effects/GAGameEffect.h" + +#include "Effects/GAEffectExtension.h" +#include "Effects/AFCueActor.h" +#include "AFCueManager.h" +#include "Effects/GABlueprintLibrary.h" +#include "Async.h" + +#include "AFAbilityComponent.h" +#include "AFEffectsComponent.h" +#include "AFAbilityInterface.h" + +DEFINE_STAT(STAT_ApplyEffect); +DEFINE_STAT(STAT_ModifyAttribute); + + + +void FAFReplicatedAttributeItem::PreReplicatedRemove(const struct FAFReplicatedAttributeContainer& InArraySerializer) +{ + FAFReplicatedAttributeContainer& ArraySerializer = const_cast(InArraySerializer); + ArraySerializer.AttributeMap.Remove(AttributeTag); +} +void FAFReplicatedAttributeItem::PostReplicatedAdd(const struct FAFReplicatedAttributeContainer& InArraySerializer) +{ + FAFReplicatedAttributeContainer& ArraySerializer = const_cast(InArraySerializer); + UGAAttributesBase*& Attribute = ArraySerializer.AttributeMap.FindOrAdd(AttributeTag); + Attribute = Attributes; + InArraySerializer.OnAttributeReplicated(AttributeTag, Attributes); +} +void FAFReplicatedAttributeItem::PostReplicatedChange(const struct FAFReplicatedAttributeContainer& InArraySerializer) +{ + +} +UGAAttributesBase* FAFReplicatedAttributeContainer::Add(const FGameplayTag InTag, UGAAttributesBase* InAttributes, class UAFAbilityComponent* InOuter) +{ + UGAAttributesBase* AttributesDup = DuplicateObject(InAttributes, InOuter); + FAFReplicatedAttributeItem Item; + Item.AttributeTag = InTag; + Item.Attributes = AttributesDup; + Attributes.Add(Item); + MarkItemDirty(Item); + UGAAttributesBase*& Added = AttributeMap.FindOrAdd(InTag); + Added = AttributesDup; + OnAttributeReplicated(InTag, AttributesDup); + return AttributesDup; +} +UAFAbilityComponent::UAFAbilityComponent(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + bWantsInitializeComponent = true; + bIsAnyAbilityActive = false; + bAutoActivate = true; + bAutoRegister = true; + PrimaryComponentTick.bCanEverTick = true; + PrimaryComponentTick.bStartWithTickEnabled = true; + PrimaryComponentTick.bRunOnAnyThread = false; + PrimaryComponentTick.bAllowTickOnDedicatedServer = true; + PrimaryComponentTick.TickGroup = ETickingGroup::TG_DuringPhysics; +} + +void UAFAbilityComponent::BroadcastAttributeChange(const FGAAttribute& InAttribute, + const FAFAttributeChangedData& InData) +{ + FAFAttributeChangedDelegate* Delegate = AttributeChanged.Find(InAttribute); + if (Delegate) + { + Delegate->Broadcast(InData); + } +} + +void UAFAbilityComponent::ModifyAttribute(FGAEffectMod& ModIn + , const FGAEffectHandle& HandleIn + , FGAEffectProperty& InProperty + , const FGAEffectContext& InContext) +{ + //OnAttributePreModifed.Broadcast(ModIn, 0); + //Add log. + if (!DefaultAttributes) + { + return; + } + float NewValue = DefaultAttributes->ModifyAttribute(ModIn, HandleIn, InProperty, InContext); + FAFAttributeChangedData Data; + Data.Mod = ModIn; + Data.Target = InContext.Target; + Data.Location = InContext.HitResult.Location; + OnAttributeModifed.Broadcast(Data); + InContext.InstigatorComp->NotifyInstigatorTargetAttributeChanged(Data, InContext); + //add default replication (PropertyRep) that attribute changed. +}; +void UAFAbilityComponent::NotifyInstigatorTargetAttributeChanged(const FAFAttributeChangedData& InData, + const FGAEffectContext& InContext) +{ + ENetMode NM = GetOwner()->GetNetMode(); + + switch (NM) + { + case NM_Standalone: + ClientNotifyAttributeModifier(InData); + break; + case NM_DedicatedServer: + ServerOnTargetAttributeModifed.Broadcast(InData); + ClientNotifyAttributeModifier(InData); + break; + case NM_ListenServer: + ServerOnTargetAttributeModifed.Broadcast(InData); + ClientNotifyAttributeModifier(InData); + break; + case NM_Client: + ClientNotifyAttributeModifier(InData); + break; + case NM_MAX: + break; + default: + break; + } +} +void UAFAbilityComponent::ClientNotifyAttributeModifier_Implementation(const FAFAttributeChangedData& InData) +{ + OnTargetAttributeModifed.Broadcast(InData); +} +void UAFAbilityComponent::GetAttributeStructTest(FGAAttribute Name) +{ + DefaultAttributes->GetAttribute(Name); +} + +void UAFAbilityComponent::OnRep_GameEffectContainer() +{ + float test = 0; +} +void UAFAbilityComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + UActorComponent::TickComponent(DeltaTime, TickType, ThisTickFunction); + if (DefaultAttributes) + { + DefaultAttributes->Tick(DeltaTime); + } +} + +void UAFAbilityComponent::BeginPlay() +{ + Super::BeginPlay(); + //FAFEffectTimerManager::Get(); +} +void UAFAbilityComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + +} +void UAFAbilityComponent::DestroyComponent(bool bPromoteChildren) +{ + Super::DestroyComponent(bPromoteChildren); + +} + +void UAFAbilityComponent::OnAttributeModified(const FGAEffectMod& InMod, + const FGAEffectHandle& InHandle, UGAAttributesBase* InAttributeSet) +{ + +} + +void UAFAbilityComponent::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const +{ + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + //possibly replicate it to everyone + //to allow prediction for UI. + DOREPLIFETIME(UAFAbilityComponent, DefaultAttributes); + DOREPLIFETIME(UAFAbilityComponent, RepAttributes); + + DOREPLIFETIME(UAFAbilityComponent, ActiveCues); + DOREPLIFETIME_CONDITION(UAFAbilityComponent, AbilityContainer, COND_OwnerOnly); + DOREPLIFETIME_CONDITION(UAFAbilityComponent, RepMontage, COND_SkipOwner); +} +void UAFAbilityComponent::OnRep_ActiveEffects() +{ + +} +void UAFAbilityComponent::OnRep_ActiveCues() +{ + +} + +bool UAFAbilityComponent::ReplicateSubobjects(class UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) +{ + bool WroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags); + + if (DefaultAttributes) + { + WroteSomething |= Channel->ReplicateSubobject(const_cast(DefaultAttributes), *Bunch, *RepFlags); + } + for (const FAFAbilitySpec& Ability : AbilityContainer.ActivatableAbilities) + { + //if (Set.InputOverride) + // WroteSomething |= Channel->ReplicateSubobject(const_cast(Set.InputOverride), *Bunch, *RepFlags); + + if (Ability.Ability) + WroteSomething |= Channel->ReplicateSubobject(const_cast(Ability.Ability), *Bunch, *RepFlags); + } + + for (const FAFReplicatedAttributeItem& Attribute : RepAttributes.Attributes) + { + //if (Set.InputOverride) + // WroteSomething |= Channel->ReplicateSubobject(const_cast(Set.InputOverride), *Bunch, *RepFlags); + + if (Attribute.Attributes) + WroteSomething |= Channel->ReplicateSubobject(const_cast(Attribute.Attributes), *Bunch, *RepFlags); + } + + return WroteSomething; +} +void UAFAbilityComponent::GetSubobjectsWithStableNamesForNetworking(TArray& Objs) +{ + if (DefaultAttributes && DefaultAttributes->IsNameStableForNetworking()) + { + Objs.Add(const_cast(DefaultAttributes)); + } +} + +void UAFAbilityComponent::GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const +{ + if (IAFAbilityInterface* ABInterface = Cast(GetOwner())) + { + TagContainer = ABInterface->NativeGetEffectsComponent()->AppliedTags.AllTags; + } +} + + + +void UAFAbilityComponent::InitializeComponent() +{ + Super::InitializeComponent(); + //PawnInterface = Cast(GetOwner()); + UInputComponent* InputComponent = GetOwner()->FindComponentByClass(); + AbilityContainer.AbilitiesComp = this; + //EffectTimerManager = MakeShareable(new FAFEffectTimerManager()); + + //EffectTimerManager.InitThread(); + if (DefaultAttributes) + { + DefaultAttributes->InitializeAttributes(this); + DefaultAttributes->InitializeAttributesFromTable(); + } + ActiveCues.OwningComp = this; + //ActiveCues.OwningComponent = this; + AppliedTags.AddTagContainer(DefaultTags); + InitializeInstancedAbilities(); + + AActor* MyOwner = GetOwner(); + if (!MyOwner || !MyOwner->IsTemplate()) + { + ULevel* ComponentLevel = (MyOwner ? MyOwner->GetLevel() : GetWorld()->PersistentLevel); + } +} +void UAFAbilityComponent::UninitializeComponent() +{ + Super::UninitializeComponent(); + //EffectTimerManager.Deinitialize(); + //EffectTimerManager.Reset(); + //GameEffectContainer +} +void UAFAbilityComponent::BindInputs(class UInputComponent* InputComponent, FString BindEnum) +{ + UEnum* bindEnum = FindObject(ANY_PACKAGE, *BindEnum); + if (!bindEnum) + return; + + int32 num = bindEnum->NumEnums(); + + for (uint8 Idx = 0; Idx < num; Idx++) + { + FString Name = bindEnum->GetNameStringByIndex(Idx); + { + FInputActionBinding AB(FName(*Name), IE_Pressed); + AB.ActionDelegate.GetDelegateForManualSet().BindUObject(this, &UAFAbilityComponent::NativeInputPressed, Idx); + InputComponent->AddActionBinding(AB); + } + + // Released event + { + FInputActionBinding AB(FName(*Name), IE_Released); + AB.ActionDelegate.GetDelegateForManualSet().BindUObject(this, &UAFAbilityComponent::NativeInputReleased, Idx); + InputComponent->AddActionBinding(AB); + } + } +} + +void UAFAbilityComponent::SetBlockedInput(const FGameplayTag& InActionName, bool bBlock) +{ +} + + + +TSoftClassPtr UAFAbilityComponent::IsAbilityBoundToAction(const TSoftClassPtr& InAbilityPtr, const TArray& InInputTag) +{ + return TSoftClassPtr(); +} + + +void UAFAbilityComponent::BindAbilityToInputIDs(const FAFAbilitySpecHandle Handle, TArray InputIDs) +{ + AbilityContainer.BindAbilityToInputIDs(Handle, InputIDs); + ENetRole role = GetOwnerRole(); + if (GetOwner()->GetNetMode() == ENetMode::NM_Client + && role == ENetRole::ROLE_AutonomousProxy) + { + /*for (int32 Idx = 0; Idx < InAbilitiesActions.Num(); Idx++) + { + if (InputDelegate[Idx].IsBound()) + { + AddOnAbilityInputReadyDelegate(InAbilitiesActions[Idx].AbilityTag, InputDelegate[Idx]); + } + }*/ + + ServerBindAbilityToInputIDs(Handle, InputIDs); + } +} + +void UAFAbilityComponent::ServerBindAbilityToInputIDs_Implementation(const FAFAbilitySpecHandle Handle, const TArray& InputIDs) +{ + AbilityContainer.BindAbilityToInputIDs(Handle, InputIDs); +} +bool UAFAbilityComponent::ServerBindAbilityToInputIDs_Validate(const FAFAbilitySpecHandle Handle, const TArray& InputIDs) +{ + return true; +} + +void UAFAbilityComponent::NativeInputPressed(uint8 InputID) +{ + FAFPredictionHandle PredHandle; + if (GetOwner()->GetNetMode() == ENetMode::NM_Client) + { + PredHandle = FAFPredictionHandle::GenerateClientHandle(this); + AbilityContainer.HandleInputPressed(InputID, PredHandle); + } + ServerNativeInputPressed(InputID, PredHandle); +} + +void UAFAbilityComponent::ServerNativeInputPressed_Implementation(uint8 InputID, FAFPredictionHandle InPredictionHandle) +{ + AbilityContainer.HandleInputPressed(InputID, InPredictionHandle); +} +bool UAFAbilityComponent::ServerNativeInputPressed_Validate(uint8 InputID, FAFPredictionHandle InPredictionHandle) +{ + return true; +} + +void UAFAbilityComponent::NativeInputReleased(uint8 InputID) +{ + if (GetOwner()->GetNetMode() == ENetMode::NM_Client) + { + AbilityContainer.HandleInputReleased(InputID); + } + ServerNativeInputReleased(InputID); +} + +void UAFAbilityComponent::ServerNativeInputReleased_Implementation(uint8 InputID) +{ + AbilityContainer.HandleInputReleased(InputID); +} +bool UAFAbilityComponent::ServerNativeInputReleased_Validate(uint8 InputID) +{ + return true; +} + +void UAFAbilityComponent::BP_AddAbility(TSoftClassPtr InAbility, + TArray InInputTag) +{ +} + +void UAFAbilityComponent::NativeAddAbility(TSoftClassPtr InAbility, const FAFAbilitySpecHandle ClientHandle) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + ServerNativeAddAbility(InAbility.ToSoftObjectPath(), ClientHandle); + } +} + +void UAFAbilityComponent::NativeAddAbilityFromObject(UGAAbilityBase* InAbility, const FAFAbilitySpecHandle ClientHandle) +{ + +} + +void UAFAbilityComponent::ServerNativeAddAbility_Implementation(const FSoftObjectPath& InAbility, const FAFAbilitySpecHandle& ClientHandle) +{ + FAFAbilitySpecHandle ServerHandle = FAFAbilitySpecHandle::GenerateHandle(); + + if (UAssetManager* Manager = UAssetManager::GetIfValid()) + { + FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked("AssetRegistry"); + IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); + FStreamableManager& StreamManager = UAssetManager::GetStreamableManager(); + { + TSoftClassPtr Ab(InAbility); + FStreamableDelegate del = FStreamableDelegate::CreateUObject(this, &UAFAbilityComponent::OnFinishedLoad, Ab, ServerHandle, ClientHandle); + + StreamManager.RequestAsyncLoad(InAbility + , del); + } + } +} + +bool UAFAbilityComponent::ServerNativeAddAbility_Validate(const FSoftObjectPath& InAbility, const FAFAbilitySpecHandle& ClientHandle) +{ + return true; +} +void UAFAbilityComponent::OnFinishedLoad(TSoftClassPtr InAbility, const FAFAbilitySpecHandle Handle, const FAFAbilitySpecHandle ClientHandle) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + return; + } + FStreamableManager& Manager = UAssetManager::GetStreamableManager(); + + TSubclassOf cls = InAbility.Get(); + if (cls) + { + UGAAbilityBase* ability = AbilityContainer.AddAbility(cls, Handle, ClientHandle); + AbilityContainer.MarkArrayDirty(); + } + + { + Manager.Unload(InAbility.ToSoftObjectPath()); + } +} + +void UAFAbilityComponent::BP_RemoveAbility(TSoftClassPtr TagIn) +{ + +} +void UAFAbilityComponent::NativeRemoveAbility(const FAFAbilitySpecHandle InHandle) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + ServerNativeRemoveAbility(InHandle); + } + AbilityContainer.RemoveAbility(InHandle); +} +void UAFAbilityComponent::ServerNativeRemoveAbility_Implementation(const FAFAbilitySpecHandle& InHandle) +{ + AbilityContainer.RemoveAbility(InHandle); +} + +bool UAFAbilityComponent::ServerNativeRemoveAbility_Validate(const FAFAbilitySpecHandle& InHandle) +{ + return true; +} + +UGAAbilityBase* UAFAbilityComponent::BP_GetAbilityByHandle(FAFAbilitySpecHandle TagIn) +{ + return AbilityContainer.GetAbility(TagIn); +} + + +void UAFAbilityComponent::OnRep_InstancedAbilities() +{ +} +void UAFAbilityComponent::NotifyOnAbilityAdded(const FGameplayTag& InAbilityTag) +{ + OnAbilityAdded.Broadcast(InAbilityTag); + +} +void UAFAbilityComponent::InitializeInstancedAbilities() +{ +} + +void UAFAbilityComponent::OnRep_PlayMontage() +{ + ACharacter* MyChar = Cast(GetOwner()); + if (MyChar) + { + UAnimInstance* AnimInst = MyChar->GetMesh()->GetAnimInstance(); + AnimInst->Montage_Play(RepMontage.CurrentMontage); + if (RepMontage.SectionName != NAME_None) + { + AnimInst->Montage_JumpToSection(RepMontage.SectionName, RepMontage.CurrentMontage); + } + UE_LOG(AbilityFramework, Log, TEXT("OnRep_PlayMontage MontageName: %s SectionNAme: %s ForceRep: %s"), *RepMontage.CurrentMontage->GetName(), *RepMontage.SectionName.ToString(), *FString::FormatAsNumber(RepMontage.ForceRep)); + } +} + +void UAFAbilityComponent::PlayMontage(UAnimMontage* MontageIn, FName SectionName, float Speed) +{ + //if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + //Probabaly want to do something different here for client non authority montage plays. + //return; + } + ACharacter* MyChar = Cast(GetOwner()); + if (MyChar) + { + UAnimInstance* AnimInst = MyChar->GetMesh()->GetAnimInstance(); + AnimInst->Montage_Play(MontageIn, Speed); + if (SectionName != NAME_None) + { + //AnimInst->Montage_JumpToSection(SectionName, MontageIn); + } + + UE_LOG(AbilityFramework, Log, TEXT("PlayMontage MontageName: %s SectionNAme: %s Where: %s"), *MontageIn->GetName(), *SectionName.ToString(), (GetOwnerRole() < ENetRole::ROLE_Authority ? TEXT("Client") : TEXT("Server"))); + RepMontage.SectionName = SectionName; + RepMontage.CurrentMontage = MontageIn; + RepMontage.ForceRep++; + } +} +void UAFAbilityComponent::MulticastPlayMontage_Implementation(UAnimMontage* MontageIn, FName SectionName, float Speed = 1) +{ + +} +void UAFAbilityComponent::ClientNotifyAbilityInputReady_Implementation(const TSoftClassPtr& InAbilityPtr) +{ + +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAbilityInterface.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAbilityInterface.cpp new file mode 100644 index 0000000..b3b15e7 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAbilityInterface.cpp @@ -0,0 +1,24 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "AFAbilityInterface.h" +#include "AFAbilityComponent.h" +#include "AFEffectsComponent.h" +#include "AFAttributeComponent.h" +UAFAbilityInterface::UAFAbilityInterface(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +//class UGAAttributesBase* IAFAbilityInterface::GetAttributes() +//{ +// return nullptr;// GetAbilityComp()->DefaultAttributes; +//} + +FGAEffectHandle IAFAbilityInterface::ApplyEffectToTarget( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + return GetEffectsComponent()->ApplyEffectToTarget(EffectIn, Params, Modifier); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAbilityTypes.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAbilityTypes.cpp new file mode 100644 index 0000000..f6673d5 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAbilityTypes.cpp @@ -0,0 +1,155 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAbilityComponent.h" +#include "Abilities/GAAbilityBase.h" +#include "AFAbilityTypes.h" + +void FAFAbilitySpec::PreReplicatedRemove(const struct FAFAbilityContainer& InArraySerializer) +{ + if (InArraySerializer.AbilitiesComp.IsValid()) + { + FAFAbilityContainer& InArraySerializerC = const_cast(InArraySerializer); + InArraySerializerC.SpecMap.Remove(Handle); + //remove attributes + //UGAAttributesBase* attr = InArraySerializer.AbilitiesComp->RepAttributes.AttributeMap.FindRef(Ability->AbilityTag); + Ability->Attributes = nullptr; + } +} +void FAFAbilitySpec::PostReplicatedAdd(const struct FAFAbilityContainer& InArraySerializer) +{ + if (InArraySerializer.AbilitiesComp.IsValid()) + { + //should be safe, since we only modify the non replicated part of struct. + FAFAbilityContainer& InArraySerializerC = const_cast(InArraySerializer); + Ability->AbilityComponent = InArraySerializer.AbilitiesComp.Get(); + if (InArraySerializer.AbilitiesComp.IsValid()) + { + APawn* POwner = Cast(InArraySerializer.AbilitiesComp->GetOwner()); + Ability->POwner = POwner; + Ability->PCOwner = Cast(POwner->Controller); + Ability->OwnerCamera = nullptr; + } + Ability->InitAbility(); + Ability->Attributes = nullptr; + + //TODO - CHANGE ATTRIBUTE HANDLING + UGAAttributesBase* attr = InArraySerializer.AbilitiesComp->RepAttributes.AttributeMap.FindRef(Ability->AbilityTag); + Ability->Attributes = attr; + InArraySerializerC.SpecMap.Add(Handle, *this); + InArraySerializerC.AbilitiesComp->NotifyOnAbilityReady(*this, Handle, ClientHandle); + } +} +void FAFAbilitySpec::PostReplicatedChange(const struct FAFAbilityContainer& InArraySerializer) +{ + +} + +UGAAbilityBase* FAFAbilityContainer::AddAbility(TSubclassOf AbilityIn + , const FAFAbilitySpecHandle Handle, const FAFAbilitySpecHandle ClientHandle) +{ + ENetMode NetMode = AbilitiesComp->GetNetMode(); + if (AbilityIn && AbilitiesComp.IsValid()) + { + UGAAbilityBase* ability = NewObject(AbilitiesComp->GetOwner(), AbilityIn); + ability->AbilityComponent = AbilitiesComp.Get(); + if (AbilitiesComp.IsValid()) + { + APawn* POwner = Cast(AbilitiesComp->GetOwner()); + ability->POwner = POwner; + ability->PCOwner = Cast(POwner->Controller); + ability->OwnerCamera = nullptr; + } + ability->InitAbility(); + FGameplayTag Tag = ability->AbilityTag; + FAFAbilitySpec Spec; + Spec.Ability = ability; + Spec.Handle = Handle; + Spec.ClientHandle = ClientHandle; + MarkItemDirty(Spec); + ActivatableAbilities.Add(Spec); + SpecMap.Add(Handle, Spec); + + MarkArrayDirty(); + if (AbilitiesComp->GetNetMode() == ENetMode::NM_Standalone + || AbilitiesComp->GetOwnerRole() == ENetRole::ROLE_Authority) + { + //AbilitiesComp->NotifyOnAbilityReady(InClassPtr); + } + + return ability; + } + return nullptr; +} + +void FAFAbilityContainer::RemoveAbility(const FAFAbilitySpecHandle AbilityIn) +{ + auto pred = [AbilityIn](const FAFAbilitySpec& Item) -> bool + { + if (Item.Handle == AbilityIn) + { + return true; + } + else + { + return false; + } + }; + int32 Index = ActivatableAbilities.IndexOfByPredicate(pred); + + if (Index == INDEX_NONE) + return; + + UGAAbilityBase* Ability = SpecMap.FindRef(AbilityIn).Ability; + + + for (auto It = Ability->AbilityTasks.CreateIterator(); It; ++It) + { + AbilitiesComp->ReplicatedTasks.Remove(It->Value); + } + Ability->AbilityTasks.Reset(); + + SpecMap.Remove(AbilityIn); + MarkItemDirty(ActivatableAbilities[Index]); + ActivatableAbilities.RemoveAt(Index); + MarkArrayDirty(); +} + + +UGAAbilityBase* FAFAbilityContainer::GetAbility(FAFAbilitySpecHandle InAbiltyPtr) +{ + UGAAbilityBase* retAbility = SpecMap.FindRef(InAbiltyPtr).Ability; + return retAbility; +} + +void FAFAbilityContainer::HandleInputPressed(const uint8 InputID, const FAFPredictionHandle& InPredictionHandle) +{ + FAFAbilitySpec Spec = InputToAbilitySpec.FindRef(InputID); + + + ENetMode NetMode = AbilitiesComp->GetNetMode(); + if(Spec.Ability) + Spec.Ability->OnNativeInputPressed(InputID, InPredictionHandle); +} +void FAFAbilityContainer::HandleInputReleased(const uint8 InputID) +{ + FAFAbilitySpec Spec = InputToAbilitySpec.FindRef(InputID); + + ENetMode NetMode = AbilitiesComp->GetNetMode(); + if(Spec.Ability) + Spec.Ability->OnNativeInputReleased(InputID); +} + +void FAFAbilityContainer::BindAbilityToInputIDs(const FAFAbilitySpecHandle Handle, TArray InputIDs) +{ + ENetMode NetMode = AbilitiesComp->GetNetMode(); + + FAFAbilitySpec Spec = SpecMap[Handle]; + + for (uint8 ID : InputIDs) + { + FAFAbilitySpec& Ref = InputToAbilitySpec.FindOrAdd(ID); + Ref = Spec; + } + Spec.Ability->OnAbilityInputReady(); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAttributeComponent.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAttributeComponent.cpp new file mode 100644 index 0000000..3362503 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAttributeComponent.cpp @@ -0,0 +1,35 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAttributeComponent.h" + + +// Sets default values for this component's properties +UAFAttributeComponent::UAFAttributeComponent() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = true; + + // ... +} + + +// Called when the game starts +void UAFAttributeComponent::BeginPlay() +{ + Super::BeginPlay(); + + // ... + +} + + +// Called every frame +void UAFAttributeComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // ... +} + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAttributeInterface.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAttributeInterface.cpp new file mode 100644 index 0000000..a771935 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFAttributeInterface.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAttributeInterface.h" + + +// Add default functionality here for any IAFAttributeInterface functions that are not pure virtual. diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFBlueprintFunctionLibrary.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFBlueprintFunctionLibrary.cpp new file mode 100644 index 0000000..6c0bc22 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFBlueprintFunctionLibrary.cpp @@ -0,0 +1,46 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" + +#include "Abilities/GAAbilityBase.h" +#include "Effects/GAEffectField.h" +#include "AFAbilityInterface.h" +#include "AFAbilityComponent.h" +#include "AFBlueprintFunctionLibrary.h" + +void UAFBlueprintFunctionLibrary::TriggerAbilityPressedByTag(UObject* Target, + const FGameplayTag& AbilityTag, FGameplayTag ActionTag) +{ + IAFAbilityInterface* Interface = Cast(Target); + if (!Interface) + { + UE_LOG(AbilityFramework, Log, TEXT("TriggerAbilityPressedByTag: Invalid Target")); + return; + } + UAFAbilityComponent* Comp = Interface->GetAbilityComp(); + if (!Comp) + { + UE_LOG(AbilityFramework, Log, TEXT("TriggerAbilityPressedByTag: Target %s InvalidComponent"), *Target->GetName()); + return; + } + + //Comp->NativeInputPressed(ActionTag); +} +void UAFBlueprintFunctionLibrary::TriggerAbilityReleasedByTag(UObject* Target, + const FGameplayTag& AbilityTag, FGameplayTag ActionTag) +{ + IAFAbilityInterface* Interface = Cast(Target); + if (!Interface) + { + UE_LOG(AbilityFramework, Log, TEXT("TriggerAbilityReleasedByTag: Invalid Target")); + return; + } + UAFAbilityComponent* Comp = Interface->GetAbilityComp(); + if (!Comp) + { + UE_LOG(AbilityFramework, Log, TEXT("TriggerAbilityReleasedByTag: Target %s InvalidComponent"), *Target->GetName()); + return; + } + + //Comp->NativeInputReleased(ActionTag); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFCueInterface.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFCueInterface.cpp new file mode 100644 index 0000000..2fac5ab --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFCueInterface.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFCueInterface.h" + + +// Add default functionality here for any IAFCueInterface functions that are not pure virtual. diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFCueManager.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFCueManager.cpp new file mode 100644 index 0000000..d812d46 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFCueManager.cpp @@ -0,0 +1,176 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "Effects/AFCueActor.h" +#include "Effects/AFCueStatic.h" +#include "AFCueManager.h" +#include "GameplayTagsManager.h" + +#include "Engine/ObjectLibrary.h" + +#if WITH_EDITOR +#include "Editor.h" +#endif + +UAFCueManager* UAFCueManager::ManagerInstance = nullptr; +//UWorld* UAFCueManager::CurrentWorld = nullptr; + +UAFCueManager* UAFCueManager::Get() +{ + if (ManagerInstance) + { + return ManagerInstance; + } + ManagerInstance = NewObject(GEngine, UAFCueManager::StaticClass(), "UAFCueManagerInstance", + RF_MarkAsRootSet); + ManagerInstance->AddToRoot(); + ManagerInstance->Initialize(); + + return ManagerInstance; +} +void UAFCueManager::Initialize() +{ +#if WITH_EDITORONLY_DATA + FEditorDelegates::EndPIE.AddUObject(this, &UAFCueManager::HandleOnPIEEnd); +#endif //WITH_EDITORONLY_DATA + FCoreUObjectDelegates::PreLoadMap.AddUObject(this, &UAFCueManager::HandlePreLoadMap); + FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(this, &UAFCueManager::HandlePostLoadMap); + + StaticCues = UObjectLibrary::CreateLibrary(UAFCueStatic::StaticClass(), true, GIsEditor); + if (GIsEditor) + { + StaticCues->bIncludeOnlyOnDiskAssets = true; + } + + TArray Paths; + Paths.Add("/Game"); + StaticCues->LoadBlueprintAssetDataFromPaths(Paths, true); + + TArray StaticCueAssets; + StaticCues->GetAssetDataList(StaticCueAssets); + + FName TagProperty = GET_MEMBER_NAME_CHECKED(UAFCueStatic, EffectCueTagSearch); + UGameplayTagsManager& TagManager = UGameplayTagsManager::Get(); + + for (const FAssetData& CueAsset : StaticCueAssets) + { + const FName Tag = CueAsset.GetTagValueRef(TagProperty); + + if (!Tag.IsNone()) + { + const FString GeneratedClassTag = CueAsset.GetTagValueRef(FBlueprintTags::GeneratedClassPath); + + FGameplayTag ReqTag = TagManager.RequestGameplayTag(Tag); + FSoftObjectPath AssetPath; + AssetPath.SetPath(FPackageName::ExportTextPathToObjectPath(*GeneratedClassTag)); + FAFCueData CueData; + CueData.CueTag = ReqTag; + CueData.AssetId = CueAsset.GetPrimaryAssetId(); + Cues.Add(CueData); + } + } + + for (int32 Idx = 0; Idx < Cues.Num(); Idx++) + { + int32& i = CuesMap.FindOrAdd(Cues[Idx].CueTag); + i = Idx; + } +} +#if WITH_EDITOR +void UAFCueManager::HandleOnPIEEnd(bool InVal) +{ + CurrentWorld = nullptr; +} +#endif //WITH_EDITOR +void UAFCueManager::HandlePreLoadMap(const FString& InMapName) +{ + CurrentWorld = nullptr; +} +void UAFCueManager::HandlePostLoadMap(UWorld* InWorld) +{ + CurrentWorld = InWorld; +} + + +void UAFCueManager::HandleCue(const FGameplayTagContainer& Tags + , const FGAEffectCueParams& CueParams + , EAFCueEvent CueEvent) +{ + if (!CurrentWorld) + CurrentWorld = CueParams.Instigator->GetWorld(); + + + if (UAssetManager* Manager = UAssetManager::GetIfValid()) + { + for (const FGameplayTag& CueTag : Tags) + { + int32 Idx = CuesMap[CueTag]; + FAFCueData Data = Cues[Idx]; + + if (Data.CueClass) + { + HandleCueEvent(Cues[Idx].CueClass, CueParams, CueEvent); + } + else //load cue asynchronously + { + FPrimaryAssetId PrimaryAssetId = Data.AssetId; + FPrimaryAssetTypeInfo Info; + if (Manager->GetPrimaryAssetTypeInfo(PrimaryAssetId.PrimaryAssetType, Info)) + { + FStreamableDelegate StreamDelegate = FStreamableDelegate::CreateUObject(this, &UAFCueManager::OnFinishedLoad, Idx, Data.AssetId, CueParams, CueEvent); + TSharedPtr Handle = Manager->LoadPrimaryAsset(PrimaryAssetId, TArray(), StreamDelegate); + } + } + } + } +} + +void UAFCueManager::OnFinishedLoad(int32 Idx + , FPrimaryAssetId InPrimaryAssetId + , FGAEffectCueParams CueParams + , EAFCueEvent CueEvent) +{ + if (UAssetManager* Manager = UAssetManager::GetIfValid()) + { + UObject* CueClass = Manager->GetPrimaryAssetObject(InPrimaryAssetId); + size_t classSize = sizeof(*CueClass); + + Cues[Idx].CueClass = Cast(CueClass); + HandleCueEvent(Cues[Idx].CueClass, CueParams, CueEvent); + } +} + +void UAFCueManager::HandleRemoveCue(const FGameplayTagContainer& Tags, + const FGAEffectCueParams& CueParams, FAFCueHandle InHandle) +{ + +} + +void UAFCueManager::HandleCueEvent(UClass* InCueClass, const FGAEffectCueParams& InCueParams, EAFCueEvent CueEvent) +{ + if (UAFCueStatic* StaticCue = Cast(InCueClass->ClassDefaultObject)) + { + switch (CueEvent) + { + case Activated: + StaticCue->OnActivate(InCueParams); + break; + case Executed: + StaticCue->OnExecuted(InCueParams); + break; + case Expire: + StaticCue->OnExpire(InCueParams); + break; + case Removed: + StaticCue->OnRemoved(InCueParams); + break; + default: + break; + } + + } + else if (AAFCueActor* ActorCue = Cast(InCueClass->ClassDefaultObject)) + { + + } +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFEffectsComponent.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFEffectsComponent.cpp new file mode 100644 index 0000000..72e906c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFEffectsComponent.cpp @@ -0,0 +1,501 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFEffectsComponent.h" + +#include "Net/UnrealNetwork.h" +#include "Engine/ActorChannel.h" + +#include "AFAbilityInterface.h" +#include "Effects/GAEffectExecution.h" +#include "Effects/GAGameEffect.h" +#include "Effects/GAEffectExtension.h" +#include "Effects/AFCueActor.h" +#include "AFCueManager.h" +#include "Effects/GABlueprintLibrary.h" + +// Sets default values for this component's properties +UAFEffectsComponent::UAFEffectsComponent(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = true; + + // ... +} + + +// Called when the game starts +void UAFEffectsComponent::BeginPlay() +{ + Super::BeginPlay(); + GameEffectContainer.OwningComponent = this; + // ... + +} +void UAFEffectsComponent::InitializeComponent() +{ + Super::InitializeComponent(); + + GameEffectContainer.OwningComponent = this; +} + +// Called every frame +void UAFEffectsComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // ... +} + +FGAEffectHandle UAFEffectsComponent::ApplyEffectToSelf( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + FGAEffectProperty& InProperty = Params.GetProperty(); + const FGameplayTagContainer& AppliedEventTags = InProperty.GetSpecData()->AppliedEventTags; + + FAFEventData Data; + + for (const FGameplayTag& Tag : AppliedEventTags) + { + if (TArray* Events = EffectEvents.Find(Tag)) + { + for (const FAFEventDelegate& Event : *Events) + Event.Execute(Data); + } + + } + OnAppliedToSelf.Broadcast(Params.Context, Params.Property, Params.EffectSpec); + + if (FAFEffectEvent* Delegate = OnEffectApplyToSelf.Find(InProperty.GetSpecData()->EffectTag)) + { + Delegate->ExecuteIfBound(); + } + + FGAEffectHandle Handle = GameEffectContainer.ApplyEffect(EffectIn, Params, Modifier); + GameEffectContainer.MarkArrayDirty(); + return Handle; +} + +FGAEffectHandle UAFEffectsComponent::ApplyEffectToTarget( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + const FGAEffectProperty& InProperty = Params.GetProperty(); + const FGAEffectContext& InContext = Params.GetContext(); + if (FAFEffectEvent* Delegate = OnEffectApplyToTarget.Find(InProperty.GetSpecData()->EffectTag)) + { + Delegate->ExecuteIfBound(); + } + ENetRole role = GetOwnerRole(); + ENetMode mode = GetOwner()->GetNetMode(); + + FAFCueHandle CueHandle = FAFCueHandle::GenerateHandle(); + + if (InProperty.GetSpecData()->Cues.CueTags.Num() > 0) + { + FGAEffectCueParams CueParams(InContext, InProperty); + MulticastApplyEffectCue(CueParams, CueHandle); + } + + OnAppliedToTarget.Broadcast(Params.Context, Params.Property, Params.EffectSpec); + + if (InContext.TargetComp.IsValid()) + { + FGAEffectHandle Handle; + Handle = InContext.GetTargetEffectsComponent()->ApplyEffectToSelf(EffectIn, Params, Modifier); + //if (!PropertyByHandle.Contains(Handle)) + // PropertyByHandle.Add(Handle, &InProperty); + + EffectToCue.Add(Handle, CueHandle); + + return Handle; + } + return FGAEffectHandle(); +} + + +/* Have to to copy handle around, because timer delegates do not support references. */ +void UAFEffectsComponent::ExecuteEffect(FGAEffectHandle HandleIn + , FAFEffectParams Params + , FAFFunctionModifier Modifier) +{ + const FGAEffectContext& Context = Params.Context; + FGAEffectProperty& Property = Params.Property.GetRef(); + const FAFEffectSpec& EffectSpec = Params.GetSpec(); + /* + this patth will give effects chance to do any replicated events, like applying cues. + WE do not make any replication at the ApplyEffect because some effect might want to apply cues + on periods on expiration etc, and all those will go trouch ExecuteEffect path. + */ + const FGameplayTagContainer& ExecutionDenyTags = Property.GetSpecData()->ExecutionDenyTags; + if (ExecutionDenyTags.Num() > 0) + { + if (HasAny(ExecutionDenyTags)) + { + UE_LOG(GameAttributesEffects, Log, TEXT("UAFEffectsComponent:: Effect %s not executed, execution denyied by tags: %s"), *Property.GetSpecData()->GetName(), *ExecutionDenyTags.ToString()); + return; + } + } + + //apply execution events: + const FGameplayTagContainer& ExecuteEventTags = Property.GetSpecData()->ExecuteEventTags; + FAFEventData Data(Params); + for (const FGameplayTag& Tag : ExecuteEventTags) + { + TriggerExecuteEvent(Tag, Data); + } + + //OnEffectExecuted.Broadcast(HandleIn, HandleIn.GetEffectSpec()->OwnedTags); + UE_LOG(GameAttributesEffects, Log, TEXT("UAFAbilityComponent:: Effect %s executed"), *Property.GetSpecData()->GetName()); + + FGAEffectMod Mod = FAFStatics::GetAttributeModifier(Property.GetAttributeModifier() + , Property.GetSpecData() + , Context + , HandleIn); + + EffectSpec.OnExecuted(); + ExecuteEffectEvent(Property.GetSpecData()->OnPeriodEvent); + + FAFCueHandle* CueHandle = EffectToCue.Find(HandleIn); + FGAEffectCueParams CueParams(Context, Property); + if (CueHandle) + MulticastExecuteEffectCue(Params.GetProperty().GetSpecData()->StaticClass(), CueParams); + + Property.ExecuteEffect(HandleIn, Mod, Params, Modifier); + PostExecuteEffect(); +} + +void UAFEffectsComponent::PostExecuteEffect() +{ + +} +/* ExpireEffect is used to remove existing effect naturally when their time expires. */ +void UAFEffectsComponent::ExpireEffect(FGAEffectHandle HandleIn + , FAFEffectParams Params) +{ + //call effect internal delegate: + FGAEffectProperty& InProperty = Params.GetProperty(); + const FGAEffectContext& InContext = Params.GetContext(); + const FAFEffectSpec& EffectSpec = Params.GetSpec(); + FGAEffect* Effect = GameEffectContainer.GetEffect(HandleIn); + EffectSpec.OnExpired(); + ENetRole role = GetOwnerRole(); + ENetMode mode = GetOwner()->GetNetMode(); + ExecuteEffectEvent(InProperty.GetSpecData()->OnExpiredEvent); + if (mode == ENetMode::NM_DedicatedServer + || mode == ENetMode::NM_ListenServer) + { + ClientExpireEffect(InProperty.GetPredictionHandle()); + } + + if (InProperty.GetSpecData()->Cues.CueTags.Num() > 0) + { + FGAEffectCueParams CueParams(InContext, InProperty); + + FAFCueHandle* CueHandle = EffectToCue.Find(HandleIn); + if (CueHandle) + { + MulticastRemoveEffectCue(CueParams, *CueHandle); + } + } + + TArray handles = GameEffectContainer.RemoveEffect(Params.Property, InContext); +} + +void UAFEffectsComponent::ClientExpireEffect_Implementation(FAFPredictionHandle PredictionHandle) +{ + +} + +void UAFEffectsComponent::RemoveEffect(const FAFPropertytHandle& InProperty + , const FGAEffectContext& InContext + , const FGAEffectHandle& InHandle) +{ + if (!InProperty.IsValid()) + { + UE_LOG(AFEffects, Log, TEXT("RemoveEffect - Trying to Remove invalid effect.")); + return; + } + //if (GetOwnerRole() == ENetRole::ROLE_Authority + // || GetOwner()->GetNetMode() == ENetMode::NM_Standalone) + { + InternalRemoveEffect(InProperty, InContext); + } + ExecuteEffectEvent(InProperty.GetSpecData()->OnRemovedEvent); + FGAEffectCueParams CueParams(InContext, InProperty.GetRef()); + + FAFCueHandle* CueHandle = EffectToCue.Find(InHandle); + if (CueHandle) + { + MulticastRemoveEffectCue(CueParams, *CueHandle); + } +} +void UAFEffectsComponent::InternalRemoveEffect(const FAFPropertytHandle& InProperty, const FGAEffectContext& InContext) +{ + UE_LOG(GameAttributesEffects, Log, TEXT("UAFAbilityComponent:: Reset Timers and Remove Effect")); + + //MulticastRemoveEffectCue(HandleIn); + if (InProperty.GetSpecData()->Cues.CueTags.Num() > 0) + { + FGAEffectCueParams CueParams(InContext, InProperty.GetRef()); + ENetRole role = GetOwnerRole(); + ENetMode mode = GetOwner()->GetNetMode(); + if (mode == ENetMode::NM_Standalone + || role >= ENetRole::ROLE_Authority) + { + //MulticastRemoveEffectCue(CueParams); + } + } + + TArray handles = GameEffectContainer.RemoveEffect(InProperty, InContext); +} + +void UAFEffectsComponent::AddEffectEvent(const FGameplayTag& InEventTag, const FSimpleDelegate& InEvent) +{ + if (!InEventTag.IsValid()) + return; + if (!OnEffectEvent.Contains(InEventTag)) + { + UE_LOG(AbilityFramework, Log, TEXT("AddEffectEvent: %s"), *InEventTag.ToString()); + OnEffectEvent.Add(InEventTag, InEvent); + } +} +void UAFEffectsComponent::ExecuteEffectEvent(const FGameplayTag& InEventTag) +{ + if (!InEventTag.IsValid()) + return; + FSimpleDelegate* Delegate = OnEffectEvent.Find(InEventTag); + if (Delegate) + { + UE_LOG(AbilityFramework, Log, TEXT("ExecuteEffectEvent: %s"), *InEventTag.ToString()); + Delegate->ExecuteIfBound(); + } +} +void UAFEffectsComponent::RemoveEffectEvent(const FGameplayTag& InEventTag) +{ + if (!InEventTag.IsValid()) + return; + UE_LOG(AbilityFramework, Log, TEXT("RemoveEffectEvent: %s"), *InEventTag.ToString()); + OnEffectEvent.Remove(InEventTag); +} +TArray& UAFEffectsComponent::GetTagEvent(FGameplayTag TagIn) +{ + TArray& Delegate = EffectEvents.FindChecked(TagIn); + return Delegate; +} + +void UAFEffectsComponent::NativeTriggerTagEvent(FGameplayTag TagIn, const FAFEventData& InEventData) +{ + TArray* Delegate = EffectEvents.Find(TagIn); + if (Delegate) + { + for (const FAFEventDelegate& Event : *Delegate) + { + if (Event.IsBound()) + { + Event.Execute(InEventData); + } + } + } +} + +void UAFEffectsComponent::AddAppliedEvent(const FGameplayTag& EventTag, FAFEventDelegate& EventDelegate) +{ + TArray& Events = AppliedEvents.FindOrAdd(EventTag); + Events.Add(EventDelegate); +} +void UAFEffectsComponent::RemoveAppliedEvent(const FGameplayTag& EventTag, const FDelegateHandle& EventDelegate) +{ + TArray* Events = AppliedEvents.Find(EventTag); + if (Events) + { + int32 Idx = Events->IndexOfByPredicate([&](const FAFEventDelegate& Other) + { + return Other.GetHandle() == EventDelegate; + }); + + Events->RemoveAt(Idx, 1, true); + } +} +void UAFEffectsComponent::TriggerAppliedEvent(FGameplayTag TagIn, const FAFEventData& InEventData) +{ + TArray* Delegate = AppliedEvents.Find(TagIn); + if (Delegate) + { + for (const FAFEventDelegate& Event : *Delegate) + { + if (Event.IsBound()) + { + Event.Execute(InEventData); + } + } + } +} + +void UAFEffectsComponent::AddExecuteEvent(const FGameplayTag& EventTag, FAFEventDelegate& EventDelegate) +{ + TArray& Events = ExecutedEvents.FindOrAdd(EventTag); + Events.Add(EventDelegate); +} +void UAFEffectsComponent::RemoveExecuteEvent(const FGameplayTag& EventTag, const FDelegateHandle& EventDelegate) +{ + TArray* Events = ExecutedEvents.Find(EventTag); + if (Events) + { + int32 Idx = Events->IndexOfByPredicate([&](const FAFEventDelegate& Other) + { + return Other.GetHandle() == EventDelegate; + }); + + Events->RemoveAt(Idx, 1, true); + } +} +void UAFEffectsComponent::TriggerExecuteEvent(FGameplayTag TagIn, const FAFEventData& InEventData) +{ + TArray* Delegate = ExecutedEvents.Find(TagIn); + if (Delegate) + { + for (const FAFEventDelegate& Event : *Delegate) + { + if (Event.IsBound()) + { + Event.Execute(InEventData); + } + } + } +} + + +void UAFEffectsComponent::AddEvent(const FGameplayTag& EventTag, FAFEventDelegate& EventDelegate) +{ + TArray& Events = EffectEvents.FindOrAdd(EventTag); + Events.Add(EventDelegate); +} + +void UAFEffectsComponent::RemoveEvent(const FGameplayTag& EventTag, const FDelegateHandle& EventDelegate) +{ + TArray* Events = EffectEvents.Find(EventTag); + if (Events) + { + + int32 Idx = Events->IndexOfByPredicate([&](const FAFEventDelegate& Other) + { + return Other.GetHandle() == EventDelegate; + }); + + Events->RemoveAt(Idx, 1, true); + } +} + +bool UAFEffectsComponent::IsEffectActive(const FGAEffectHandle& InHandle) const +{ + return GameEffectContainer.IsEffectActive(InHandle); +} + +bool UAFEffectsComponent::DenyEffectApplication(const FGameplayTagContainer& InTags) +{ + bool bDenyApplication = false; + if (InTags.Num() > 0) + { + bDenyApplication = HasAny(InTags); + } + return bDenyApplication; +} + +bool UAFEffectsComponent::HaveEffectRquiredTags(const FGameplayTagContainer& InTags) +{ + bool bAllowApplication = true; + if (InTags.Num() > 0) + { + bAllowApplication = HasAll(InTags); + } + return bAllowApplication; +} + +FGAEffect* UAFEffectsComponent::GetEffect(const FGAEffectHandle& InHandle) +{ + return *GameEffectContainer.ActiveEffects.Find(InHandle); +} + +/* +Need prediction for spawning effects on client, +and then on updateing them predicitvely on all other clients. +*/ +/* + +*/ +void UAFEffectsComponent::MulticastApplyEffectCue_Implementation(FGAEffectCueParams CueParams, FAFCueHandle InHandle) +{ + ENetRole role = GetOwnerRole(); + ENetMode mode = GetOwner()->GetNetMode(); + if (mode == ENetMode::NM_Standalone + || role != ENetRole::ROLE_Authority) + { + UAFCueManager::Get()->HandleCue(CueParams.CueTags, CueParams, EAFCueEvent::Activated); + } +} +void UAFEffectsComponent::MulticastExecuteEffectCue_Implementation(TSubclassOf EffectSpec, FGAEffectCueParams CueParams) +{ + ENetRole role = GetOwnerRole(); + ENetMode mode = GetOwner()->GetNetMode(); + if (mode == ENetMode::NM_Standalone + || role != ENetRole::ROLE_Authority) + { + UAFCueManager::Get()->HandleCue(CueParams.CueTags, CueParams, EAFCueEvent::Executed); + } +} + +void UAFEffectsComponent::MulticastRemoveEffectCue_Implementation(FGAEffectCueParams CueParams, FAFCueHandle InHandle) +{ + ENetRole role = GetOwnerRole(); + ENetMode mode = GetOwner()->GetNetMode(); + if (mode == ENetMode::NM_Standalone + || role != ENetRole::ROLE_Authority) + { + UAFCueManager::Get()->HandleCue(CueParams.CueTags, CueParams, EAFCueEvent::Removed); + } +} + +void UAFEffectsComponent::MulticastUpdateDurationCue_Implementation(FGAEffectHandle EffectHandle, float NewDurationIn) +{ + +} + +void UAFEffectsComponent::MulticastUpdatePeriodCue_Implementation(FGAEffectHandle EffectHandle, float NewPeriodIn) +{ + +} + +void UAFEffectsComponent::MulticastUpdateTimersCue_Implementation(FGAEffectHandle EffectHandle, float NewDurationIn, float NewPeriodIn) +{ + +} + +void UAFEffectsComponent::MulticastExtendDurationCue_Implementation(FGAEffectHandle EffectHandle, float NewDurationIn) +{ + +} + + +/*Network Functions - BEGIN */ + +void UAFEffectsComponent::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const +{ + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + + DOREPLIFETIME(UAFEffectsComponent, GameEffectContainer); + DOREPLIFETIME(UAFEffectsComponent, AppliedTags); + DOREPLIFETIME(UAFEffectsComponent, ImmunityTags); +} + +void UAFEffectsComponent::OnRep_GameEffectContainer() +{ + +} + +/*Network Functions - END */ \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFSimpleInterface.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFSimpleInterface.cpp new file mode 100644 index 0000000..bb19175 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AFSimpleInterface.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFSimpleInterface.h" + + +// Add default functionality here for any IAFSimpleInterface functions that are not pure virtual. diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityActivationSpec.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityActivationSpec.cpp new file mode 100644 index 0000000..dbb9013 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityActivationSpec.cpp @@ -0,0 +1,13 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "../Effects/CustomApplications/AFAtributeDurationAdd.h" +#include "AFAbilityActivationSpec.h" + + + +UAFAbilityActivationSpec::UAFAbilityActivationSpec() + :Super() +{ + Application = UAFAtributeDurationAdd::StaticClass(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityCooldownSpec.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityCooldownSpec.cpp new file mode 100644 index 0000000..045614d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityCooldownSpec.cpp @@ -0,0 +1,14 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "Effects/CustomApplications/AFAtributeDurationAdd.h" +#include "AFAbilityCooldownSpec.h" + + + + +UAFAbilityCooldownSpec::UAFAbilityCooldownSpec() + : Super() +{ + Application = UAFAtributeDurationAdd::StaticClass(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityInfiniteDurationSpec.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityInfiniteDurationSpec.cpp new file mode 100644 index 0000000..19cf6ce --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityInfiniteDurationSpec.cpp @@ -0,0 +1,13 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "Effects/CustomApplications/AFAttributeDurationInfinite.h" +#include "AFAbilityInfiniteDurationSpec.h" + + + +UAFAbilityInfiniteDurationSpec::UAFAbilityInfiniteDurationSpec() + :Super() +{ + Application = UAFAttributeDurationInfinite::StaticClass(); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityPeriodSpec.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityPeriodSpec.cpp new file mode 100644 index 0000000..49cb210 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityPeriodSpec.cpp @@ -0,0 +1,13 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAbilityPeriodSpec.h" +#include "../Effects/CustomApplications/AFPeriodApplicationAdd.h" + + + +UAFAbilityPeriodSpec::UAFAbilityPeriodSpec() + :Super() +{ + Application = UAFPeriodApplicationAdd::StaticClass(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityPeriodicInfiniteSpec.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityPeriodicInfiniteSpec.cpp new file mode 100644 index 0000000..a77c62a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/AFAbilityPeriodicInfiniteSpec.cpp @@ -0,0 +1,14 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "Effects/CustomApplications/AFPeriodApplicationInfiniteAdd.h" +#include "AFAbilityPeriodicInfiniteSpec.h" + + + + +UAFAbilityPeriodicInfiniteSpec::UAFAbilityPeriodicInfiniteSpec() + :Super() +{ + Application = UAFPeriodApplicationInfiniteAdd::StaticClass(); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/GAAbilityBase.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/GAAbilityBase.cpp new file mode 100644 index 0000000..57cb4a6 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/GAAbilityBase.cpp @@ -0,0 +1,974 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + + +#include "AbilityFramework.h" +#include "Tasks/GAAbilityTask.h" +#include "Effects/GAGameEffect.h" +#include "GAGlobalTypes.h" +#include "Effects/GAEffectGlobalTypes.h" +#include "AFAbilityComponent.h" +#include "AFEffectsComponent.h" + +#include "GameplayTagContainer.h" +#include "Net/UnrealNetwork.h" +#include "Animation/AnimMontage.h" +#include "Effects/GABlueprintLibrary.h" +#include "Camera/CameraComponent.h" +#include "Kismet/KismetSystemLibrary.h" + +#include "GAAbilityBase.h" +FAFPredictionHandle UGAAbilityBase::GetPredictionHandle() { return PredictionHandle; } + +UGAAbilityBase::UGAAbilityBase(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + bReplicate = true; + bIsNameStable = false; +} + +void UGAAbilityBase::PostInitProperties() +{ + UpdateAssetRegistryInfo(); + Super::PostInitProperties(); +} + +void UGAAbilityBase::Serialize(FArchive& Ar) +{ + if (Ar.IsSaving()) + { + UpdateAssetRegistryInfo(); + } + + Super::Serialize(Ar); + + if (Ar.IsLoading()) + { + UpdateAssetRegistryInfo(); + } +} +#if WITH_EDITORONLY_DATA +void UGAAbilityBase::UpdateAssetBundleData() +{ + AssetBundleData.Reset(); + + // By default parse the metadata + if (UAssetManager::IsValid()) + { + UAssetManager::Get().InitializeAssetBundlesFromMetadata(this, AssetBundleData); + } +} + +void UGAAbilityBase::PreSave(const class ITargetPlatform* TargetPlatform) +{ + Super::PreSave(TargetPlatform); + + UpdateAssetBundleData(); + + if (UAssetManager::IsValid()) + { + // Bundles may have changed, refresh + UAssetManager::Get().RefreshAssetData(this); + } +} +#endif + +FPrimaryAssetId UGAAbilityBase::GetPrimaryAssetId() const +{ + //FName Name = GetFName(); + //FName clsNam = GetClass()->GetFName(); + FName dupa1 = FPackageName::GetShortFName(GetOutermost()->GetFName()); + //FName dupa2 = FPackageName::GetShortFName(GetFName()); + const UGAAbilityBase* A = this; + return FPrimaryAssetId(FPrimaryAssetType("Ability"), dupa1); + //if (HasAnyFlags(RF_ClassDefaultObject)) + { + UClass* SearchNativeClass = GetClass(); + + while (SearchNativeClass && !SearchNativeClass->HasAnyClassFlags(CLASS_Native | CLASS_Intrinsic)) + { + SearchNativeClass = SearchNativeClass->GetSuperClass(); + } + + if (SearchNativeClass && SearchNativeClass != GetClass()) + { + // If blueprint, return native class and asset name + + } + + // Native CDO, return nothing + return FPrimaryAssetId(); + } + + // Data assets use Class and ShortName by default, there's no inheritance so class works fine + //return FPrimaryAssetId(GetClass()->GetFName(), GetFName()); +} + +void UGAAbilityBase::PostLoad() +{ + Super::PostLoad(); + +#if WITH_EDITORONLY_DATA + FAssetBundleData OldData = AssetBundleData; + + UpdateAssetBundleData(); + + if (UAssetManager::IsValid() && OldData != AssetBundleData) + { + // Bundles changed, refresh + UAssetManager::Get().RefreshAssetData(this); + } +#endif +} +#if WITH_EDITOR +void UGAAbilityBase::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) +{ + Super::PostEditChangeProperty(PropertyChangedEvent); +} +#endif // WITH_EDITOR + +void UGAAbilityBase::UpdateAssetRegistryInfo() +{ + AbilityTagSearch = AbilityTag.GetTagName(); +} + +void UGAAbilityBase::InitAbility() +{ + //still want to initialize, as Spec is used in multiple places. + DefaultContext = UGABlueprintLibrary::MakeContext(this, POwner, AvatarActor, this, FHitResult(ForceInit)).GetRef(); + ActivationEffect.InitializeIfNotInitialized(POwner, this); + CooldownEffect.InitializeIfNotInitialized(POwner, this); + for (int32 Idx = 0; Idx < AttributeCost.Num(); Idx++) + { + AttributeCost[Idx].InitializeIfNotInitialized(POwner, this); + } + AttributeCostHandle.AddZeroed(AttributeCost.Num()); + + for (int32 Idx = 0; Idx < AbilityAttributeCost.Num(); Idx++) + { + AbilityAttributeCost[Idx].InitializeIfNotInitialized(POwner, this); + } + AbilityAttributeCostHandle.AddZeroed(AbilityAttributeCost.Num()); + if (AbilityComponent) + { + World = AbilityComponent->GetWorld(); + } + + if (!AbilityComponent) + { + AbilityComponent = GetAbilityComp(); + } + + if (GetAttributes()) + { + GetAttributes()->InitializeAttributes(GetAbilityComp()); + GetAttributes()->InitializeAttributesFromTable(); + } + ENetRole role = AbilityComponent->GetOwnerRole(); + ENetMode mode = AbilityComponent->GetOwner()->GetNetMode(); + + + { + FAFOnAttributeReady Delegate = FAFOnAttributeReady::CreateUObject(this, &UGAAbilityBase::OnAttributeSetReplicated); + AbilityComponent->RepAttributes.RegisterAttributeRepEvent(AbilityTag, Delegate); + } + + //AbilityComponent->RepAttributes.AttributeMap.Add(AbilityTag, Attributes); + if (role == ENetRole::ROLE_Authority || + mode == ENetMode::NM_Standalone) + { + if (AbilityComponent && GetAttributes()) + { + UGAAttributesBase* NewAttributes = AbilityComponent->AddAddtionalAttributes(AbilityTag, GetAttributes());; + SetAttributes(nullptr); + SetAttributes(NewAttributes); + } + } + + if (!OwnerCamera) + { + OwnerCamera = POwner->FindComponentByClass(); + } + + OnAbilityInited(); +} +void UGAAbilityBase::OnAttributeSetReplicated(class UGAAttributesBase* ReplicatedAttributes) +{ + SetAttributes(ReplicatedAttributes); + if (GetAttributes()) + { + GetAttributes()->InitializeAttributes(GetAbilityComp()); + GetAttributes()->InitializeAttributesFromTable(); + } +} + +void UGAAbilityBase::OnAbilityInited() +{ + +} +void UGAAbilityBase::OnNativeInputPressed(uint8 InputID, const FAFPredictionHandle& InPredictionHandle) +{ + { + //UE_LOG(AbilityFramework, Log, TEXT("OnNativeInputPressed in ability %s"), *GetName()); + PredictionHandle = InPredictionHandle; + OnInputPressed(InputID); + OnInputPressedDelegate.Broadcast(); + } +} + +void UGAAbilityBase::OnNativeInputReleased(uint8 InputID) +{ + { + UE_LOG(AbilityFramework, Log, TEXT("OnNativeInputReleased in ability %s"), *GetName()); + OnInputReleased(InputID); + OnInputReleasedDelegate.Broadcast(); + } +} + +void UGAAbilityBase::StartActivation(bool bApplyActivationEffect) +{ + if (!CanUseAbility()) + { + UE_LOG(AbilityFramework, Log, TEXT("Cannot use Ability: %s"), *GetName()); + return; + } + //AbilityComponent->ExecutingAbility = this; + AbilityState = EAFAbilityState::Activating; + NativeOnBeginAbilityActivation(bApplyActivationEffect); +} + +void UGAAbilityBase::NativeOnBeginAbilityActivation(bool bApplyActivationEffect) +{ + UE_LOG(AbilityFramework, Log, TEXT("Begin Executing Ability: %s"), *GetName()); + + if (OnConfirmCastingEndedDelegate.IsBound()) + { + OnConfirmCastingEndedDelegate.Broadcast(); + } + //ActivationInfo.SetActivationInfo(); + ApplyActivationEffect(bApplyActivationEffect); + OnActivate(); + OnActivateBeginDelegate.Broadcast(); + AbilityComponent->AppliedTags.AddTagContainer(ActivationAddedTags); + //OnAbilityExecuted(); +} + +void UGAAbilityBase::OnCooldownEffectExpired() +{ + UE_LOG(AFAbilities, Log, TEXT("Cooldown expired In Ability: %s"), *GetName()); +} +/* Functions for activation effect delegates */ +void UGAAbilityBase::NativeOnAbilityActivationFinish() +{ + UE_LOG(AbilityFramework, Log, TEXT("Ability Activation Effect Expired In Ability: %s"), *GetName()); + OnActivationFinished(); + OnActivationFinishedDelegate.Broadcast(); +} +void UGAAbilityBase::NativeOnAbilityActivationCancel() +{ + //OnAbilityExecutedNative(); + //this works under assumption that current state == activation state. + UE_LOG(AbilityFramework, Log, TEXT("Ability Activation Effect Removed In Ability: %s"), *GetName()); + //AbilityComponent->ExecutingAbility = nullptr; + OnConfirmDelegate.Clear(); + OnConfirmDelegate.RemoveAll(this); + + OnActivationCancel(); + //AbilityActivatedCounter++; +} +void UGAAbilityBase::OnActivationEffectPeriod() +{ + UE_LOG(AFAbilities, Log, TEXT("Ability Activation Effect Period In Ability: %s"), *GetName()); + + OnPeriod(); +} +void UGAAbilityBase::FinishAbility() +{ + UE_LOG(AFAbilities, Log, TEXT("FinishExecution in ability %s"), *GetName()); + OnAbilityFinished(); + NativeFinishAbility(); + AbilityState = EAFAbilityState::Waiting; + GetEffectsComponent()->AppliedTags.RemoveTagContainer(ActivationAddedTags); +} +void UGAAbilityBase::NativeFinishAbility() +{ + UE_LOG(AFAbilities, Log, TEXT("NativeFinishExecution in ability %s"), *GetName()); + AbilityComponent->ExecutingAbility = nullptr; + OnConfirmDelegate.Clear(); + OnConfirmDelegate.RemoveAll(this); + if (ActivationEffectHandle.Num() > 0 && !ActivationEffectHandle[0].IsValid()) + { + GetEffectsComponent()->RemoveEffect(ActivationEffect, DefaultContext, ActivationEffectHandle[0]); + ActivationEffectHandle.Reset(); + } + //remove effect. +} +/* Functions for activation effect delegates */ +void UGAAbilityBase::CancelActivation() +{ + NativeCancelActivation(); +} +void UGAAbilityBase::NativeCancelActivation() +{ + if (ActivationEffectHandle.Num() > 0 && !ActivationEffectHandle[0].IsValid()) + return; + + UAFAbilityComponent* AttrComp = DefaultContext.InstigatorComp.Get(); + AbilityComponent->ExecutingAbility = nullptr; + OnConfirmDelegate.Clear(); + OnConfirmDelegate.RemoveAll(this); + if (GetEffectsComponent()) + { + GetEffectsComponent()->RemoveEffect(ActivationEffect, DefaultContext, ActivationEffectHandle[0]); + AbilityState = EAFAbilityState::Waiting; + ActivationEffectHandle.Reset(); + } + OnActivationCancel(); +} + +bool UGAAbilityBase::IsWaitingForConfirm() +{ + if (OnConfirmDelegate.IsBound()) + return true; + else + return false; +} +void UGAAbilityBase::ConfirmAbility() +{ + if (OnConfirmDelegate.IsBound()) + OnConfirmDelegate.Broadcast(); + OnConfirmDelegate.Clear(); + OnConfirmDelegate.RemoveAll(this); +} + +bool UGAAbilityBase::ApplyCooldownEffect() +{ + if (!CooldownEffect.GetSpecData()) + { + return false; + } + FAFFunctionModifier Modifier; + + FSimpleDelegate PeriodDel = FSimpleDelegate::CreateUObject(this, &UGAAbilityBase::NativeOnCooldownEnd); + GetEffectsComponent()->AddEffectEvent(CooldownEffect.GetSpecData()->OnExpiredEvent, PeriodDel); + + CooldownEffectHandle = UGABlueprintLibrary::ApplyGameEffectToObject( + CooldownEffect + , this + , POwner + , this + , Modifier); + ENetMode nm = AbilityComponent->GetOwner()->GetNetMode(); + ENetRole role = AbilityComponent->GetOwnerRole(); + + if (role >= ENetRole::ROLE_Authority) + { + ClientSetCooldownHandle(CooldownEffectHandle[0]); + } + OnCooldownStart(); + + //CooldownEffectHandle.GetEffectRef().OnEffectExpired.AddUObject(this, &UGAAbilityBase::OnCooldownEnd); + return false; +} +void UGAAbilityBase::NativeOnCooldownEnd() +{ + //AbilityComponent->RemoveEffect(CooldownEffect, DefaultContext); + OnCooldownEnd(); + CooldownEffectHandle.Reset(); +} +void UGAAbilityBase::ClientSetCooldownHandle_Implementation(FGAEffectHandle InCooldownHandle) +{ + //CooldownEffectHandle = InCooldownHandle; +} +bool UGAAbilityBase::ApplyActivationEffect(bool bApplyActivationEffect) +{ + if (!ActivationEffect.GetSpecData()) + return false; + FHitResult Hit(ForceInit); + + UGAGameEffectSpec* Spec = ActivationEffect.GetClass().GetDefaultObject(); + float DurationCheck = Spec->Duration.GetFloatValue(DefaultContext); + float PeriodCheck = Spec->Period.GetFloatValue(DefaultContext); + if (DurationCheck > 0 || PeriodCheck > 0) + { + bApplyActivationEffect = true; + } + + if (bApplyActivationEffect) + { + FHitResult HitIn; + + FSimpleDelegate AppliedDel = FSimpleDelegate::CreateUObject(this, &UGAAbilityBase::NativeOnAbilityActivationFinish); + GetEffectsComponent()->AddEffectEvent(ActivationEffect.GetSpecData()->OnExpiredEvent, AppliedDel); + + FAFFunctionModifier Modifier; + ActivationEffectHandle = UGABlueprintLibrary::ApplyGameEffectToObject( + ActivationEffect + , this + , POwner + , this + , Modifier); + + //if(!ActivationEffectHandle.GetEffectRef().OnEffectExpired.) + // ActivationEffectHandle.GetEffectRef().OnEffectExpired.AddUObject(this, &UGAAbilityBase::NativeOnAbilityActivationFinish); + + + if (PeriodCheck > 0) + { + FSimpleDelegate PeriodDel = FSimpleDelegate::CreateUObject(this, &UGAAbilityBase::OnActivationEffectPeriod); + GetEffectsComponent()->AddEffectEvent(ActivationEffect.GetSpecData()->OnPeriodEvent, PeriodDel); + //if (!ActivationEffectHandle.GetEffectRef().OnEffectPeriod.IsBound()) + // ActivationEffectHandle.GetEffectRef().OnEffectPeriod.AddUObject(this, &UGAAbilityBase::OnActivationEffectPeriod); + } + } + else + { + NativeOnAbilityActivationFinish(); + } + return false; +} + +bool UGAAbilityBase::CanUseAbility() +{ + bool CanUse = true; + bool bIsOnCooldown = IsOnCooldown(); + bool bIsActivating = IsActivating(); + //if (!AbilityComponent->ExecutingAbility) + // UE_LOG(AbilityFramework, Log, TEXT("CanUseAbility AbilityComponent->ExecutingAbility is true")); + + CanUse = !bIsOnCooldown && !bIsActivating; + UE_LOG(AbilityFramework, Log, TEXT("CanUseAbility Ability, Cooldown: %s, Activating: %s \n"), bIsOnCooldown ? TEXT("true") : TEXT("false"), bIsActivating ? TEXT("true") : TEXT("false") ); + //now Lets check tags + if (CanUse) + { + if (GetEffectsComponent()->HasAll(ActivationRequiredTags)) + { + CanUse = true; + } + //blocking takes precedence. + if (GetEffectsComponent()->HasAny(ActivationBlockedTags)) + { + CanUse = false; + } + } + + return CanUse; +} +bool UGAAbilityBase::BP_CanUseAbility() +{ + return CanUseAbility(); +} +bool UGAAbilityBase::CanReleaseAbility() +{ + bool bCanUse = true; + /*if (AbilityComponent->ExecutingAbility == this) + { + bCanUse = true; + }*/ + if (IsOnCooldown()) + { + bCanUse = false; + UE_LOG(AbilityFramework, Log, TEXT("CanReleaseAbility can't release ability is on cooldown")); + } + return bCanUse; +} + +class UGAAttributesBase* UGAAbilityBase::GetAttributes() +{ + return Attributes; +} +UAFAbilityComponent* UGAAbilityBase::GetAbilityComp() +{ + IAFAbilityInterface* OwnerAttributes = Cast(POwner); + if (OwnerAttributes) + { + return OwnerAttributes->GetAbilityComp(); + } + return nullptr; +} + +UAFEffectsComponent* UGAAbilityBase::GetEffectsComponent() +{ + IAFAbilityInterface* OwnerAttributes = Cast(POwner); + if (OwnerAttributes) + { + return OwnerAttributes->GetEffectsComponent(); + } + return nullptr; +} +UAFEffectsComponent* UGAAbilityBase::NativeGetEffectsComponent() const +{ + IAFAbilityInterface* OwnerAttributes = Cast(POwner); + if (OwnerAttributes) + { + return OwnerAttributes->NativeGetEffectsComponent(); + } + return nullptr; +} +float UGAAbilityBase::GetAttributeValue(FGAAttribute AttributeIn) const +{ + return NativeGetAttributeValue(AttributeIn); +} +float UGAAbilityBase::NativeGetAttributeValue(const FGAAttribute AttributeIn) const +{ + return GetAttributes()->GetCurrentAttributeValue(AttributeIn); +} +float UGAAbilityBase::GetAttributeVal(FGAAttribute AttributeIn) const +{ + return GetAttributes()->GetCurrentAttributeValue(AttributeIn); +} + +bool UGAAbilityBase::ApplyAttributeCost() +{ + FAFFunctionModifier Modifier; + if (CheckAttributeCost()) + { + for (int32 Idx = 0; Idx < AttributeCost.Num(); Idx++) + { + AttributeCostHandle[Idx] = UGABlueprintLibrary::ApplyGameEffectToObject( + AttributeCost[Idx] + , POwner + , POwner + , this + , Modifier); + } + return true; + } + return false; +} +bool UGAAbilityBase::ApplyAbilityAttributeCost() +{ + //add checking if attribute goes below zero + //maybe let game specific code handle it.. + FAFFunctionModifier Modifier; + + if (CheckAbilityAttributeCost()) + { + for (int32 Idx = 0; Idx < AbilityAttributeCost.Num(); Idx++) + { + AbilityAttributeCostHandle[Idx] = UGABlueprintLibrary::ApplyGameEffectToObject( + AbilityAttributeCost[Idx] + , this + , POwner + , this + , Modifier); + } + return true; + } + return false; +} +bool UGAAbilityBase::BP_ApplyAttributeCost() +{ + return ApplyAttributeCost(); +} +bool UGAAbilityBase::BP_CheckAttributeCost() +{ + return CheckAttributeCost(); +} + +bool UGAAbilityBase::BP_ApplyAbilityAttributeCost() +{ + return ApplyAbilityAttributeCost(); +} +bool UGAAbilityBase::BP_CheckAbilityAttributeCost() +{ + return CheckAbilityAttributeCost(); +} +bool UGAAbilityBase::CheckAbilityAttributeCost() +{ + for (int32 Idx = 0; Idx < AbilityAttributeCost.Num(); Idx++) + { + float ModValue = AbilityAttributeCost[Idx].GetSpecData()->AtributeModifier.Magnitude.GetFloatValue(DefaultContext); + FGAAttribute Attribute = AbilityAttributeCost[Idx].GetSpecData()->AtributeModifier.Attribute; + float AttributeVal = GetAttributes()->GetFloatValue(Attribute); + if (ModValue > AttributeVal) + return false; + } + return true; +} +bool UGAAbilityBase::CheckAttributeCost() +{ + IAFAbilityInterface* Interface = Cast(POwner); + + for (int32 Idx = 0; Idx < AttributeCost.Num(); Idx++) + { + float ModValue = AttributeCost[Idx].GetSpecData()->AtributeModifier.Magnitude.GetFloatValue(DefaultContext); + FGAAttribute Attribute = AttributeCost[Idx].GetSpecData()->AtributeModifier.Attribute; + float AttributeVal = Interface->GetAttributes()->GetFloatValue(Attribute); + if (ModValue > AttributeVal) + return false; + } + return true; +} +bool UGAAbilityBase::IsOnCooldown() +{ + if (CooldownEffectHandle.Num() <= 0) + return false; + + bool bOnCooldown = false; + bOnCooldown = GetEffectsComponent()->IsEffectActive(CooldownEffectHandle[0]); + if (bOnCooldown) + { + OnNotifyOnCooldown.Broadcast(); + } + return bOnCooldown; //temp +} +bool UGAAbilityBase::IsActivating() +{ + if (ActivationEffectHandle.Num() <= 0) + return false; + + bool bAbilityActivating = false; + bool bHaveEffect = GetEffectsComponent()->IsEffectActive(ActivationEffectHandle[0]); + bool bInActivatingState = AbilityState == EAFAbilityState::Activating; + UE_LOG(AbilityFramework, Log, TEXT("IsActivating Ability, Effect: %s, State: %s \n"), bHaveEffect ? TEXT("true") : TEXT("false"), bInActivatingState ? TEXT("true") : TEXT("false")); + bAbilityActivating = bHaveEffect || bInActivatingState; + + return bAbilityActivating; //temp +} +bool UGAAbilityBase::BP_IsOnCooldown() +{ + return IsOnCooldown(); +} +void UGAAbilityBase::BP_ApplyCooldown() +{ + ApplyCooldownEffect(); +} + +float UGAAbilityBase::GetCurrentActivationTime() +{ + if (ActivationEffectHandle.Num() <= 0) + { + return 0; + } + + if (ActivationEffectHandle[0].IsValid()) + { + if (IAFAbilityInterface* Interface = DefaultContext.TargetInterface) + { + FGAEffect* Effect = Interface->GetEffectsComponent()->GetEffect(ActivationEffectHandle[0]); + if (Effect) + { + return Effect->GetCurrentDuration(); + } + } + //return ActivationEffectHandle.GetEffectPtr()->GetCurrentDuration(); + } + return 0; +} + +float UGAAbilityBase::CalculateAnimationSpeed(UAnimMontage* MontageIn) +{ + float ActivationTime = MontageIn->GetPlayLength(); + UGAGameEffectSpec* Spec = ActivationEffect.GetClass().GetDefaultObject(); + float DurationCheck = Spec->Duration.GetFloatValue(DefaultContext); + if (DurationCheck > 0) + { + ActivationTime = DurationCheck; + } + float Duration = MontageIn->GetPlayLength(); + + float PlaySpeed = Duration / ActivationTime; + return PlaySpeed; +} + + +bool UGAAbilityBase::IsNameStableForNetworking() const +{ + return bIsNameStable; +} + +void UGAAbilityBase::SetNetAddressable() +{ + bIsNameStable = true; +} + +class UWorld* UGAAbilityBase::GetWorld() const +{ + return World; +} +void UGAAbilityBase::PlayMontage(UAnimMontage* MontageIn, FName SectionName, float Speed) +{ + AbilityComponent->PlayMontage(MontageIn, SectionName, Speed); +} + +//replication +void UGAAbilityBase::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const +{ + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + //possibly can be infered upon replication. + //does other players need info about this ? + DOREPLIFETIME(UGAAbilityBase, POwner); + DOREPLIFETIME(UGAAbilityBase, PCOwner); + DOREPLIFETIME(UGAAbilityBase, AICOwner); + DOREPLIFETIME(UGAAbilityBase, AvatarActor); + //probabaly should be SKIP_Owner, and I'm not really sure if Multicast wouldn't be better. + +} +int32 UGAAbilityBase::GetFunctionCallspace(UFunction* Function, void* Parameters, FFrame* Stack) +{ + if (HasAnyFlags(RF_ClassDefaultObject)) + { + return FunctionCallspace::Local; + } + check(POwner != NULL); + return POwner->GetFunctionCallspace(Function, Parameters, Stack); +} +bool UGAAbilityBase::CallRemoteFunction(UFunction* Function, void* Parameters, FOutParmRec* OutParms, FFrame* Stack) +{ + check(!HasAnyFlags(RF_ClassDefaultObject)); + check(POwner != NULL); + + + UNetDriver* NetDriver = POwner->GetNetDriver(); + if (NetDriver) + { + NetDriver->ProcessRemoteFunction(POwner, Function, Parameters, OutParms, Stack, this); + return true; + } + + return false; +} + +void UGAAbilityBase::ExecuteAbilityInputPressedFromTag(FGameplayTag AbilityTagIn, FGameplayTag ActionName) +{ + //AbilityComponent->NativeInputPressed(ActionName); +} +void UGAAbilityBase::ExecuteAbilityInputReleasedFromTag(FGameplayTag AbilityTagIn, FGameplayTag ActionName) +{ + //AbilityComponent->NativeInputReleased(ActionName); +} + +bool UGAAbilityBase::HaveGameplayTag(AActor* Target, const FGameplayTag& Tag) +{ + bool bHaveTag = false; + if (IAFAbilityInterface* Interface = Cast(Target)) + { + if (UAFEffectsComponent* Comp = GetEffectsComponent()) + { + if (Comp->HasTag(Tag)) + { + bHaveTag = true; + } + } + } + return bHaveTag; +} +bool UGAAbilityBase::HaveAnyGameplayTag(AActor* Target, const FGameplayTagContainer& Tag) +{ + bool bHaveTag = false; + if (IAFAbilityInterface* Interface = Cast(Target)) + { + if (UAFEffectsComponent* Comp = GetEffectsComponent()) + { + if (Comp->HasAny(Tag)) + { + bHaveTag = true; + } + } + } + return bHaveTag; +} +/* Tracing Helpers Start */ +bool UGAAbilityBase::LineTraceSingleByChannel(const FVector Start, const FVector End, ETraceTypeQuery TraceChannel, bool bTraceComplex, FHitResult& OutHit) +{ + ECollisionChannel CollisionChannel = UEngineTypes::ConvertToCollisionChannel(TraceChannel); + static const FName LineTraceSingleName(TEXT("AbilityLineTraceSingle")); + FCollisionQueryParams Params(LineTraceSingleName, bTraceComplex); + + bool bHit = World->LineTraceSingleByChannel(OutHit, Start, End, CollisionChannel, Params); + return bHit; +} +bool UGAAbilityBase::LineTraceSingleByChannelFromCamera(float Range, ETraceTypeQuery TraceChannel, bool bTraceComplex, FHitResult& OutHit, + EDrawDebugTrace::Type DrawDebugType, bool bIgnoreSelf, FLinearColor TraceColor, FLinearColor TraceHitColor, float DrawTime) +{ + FVector Start = FVector::ZeroVector; + if (OwnerCamera) + { + Start = OwnerCamera->GetComponentLocation(); + } + else + { + FRotator UnusedRot; + POwner->GetActorEyesViewPoint(Start, UnusedRot); + } + FVector End = (POwner->GetBaseAimRotation().Vector() * Range) + Start; + ECollisionChannel CollisionChannel = UEngineTypes::ConvertToCollisionChannel(TraceChannel); + static const FName LineTraceSingleName(TEXT("AbilityLineTraceSingle")); + FCollisionQueryParams Params(LineTraceSingleName, bTraceComplex); + bool bHit = World->LineTraceSingleByChannel(OutHit, Start, End, CollisionChannel, Params); +#if ENABLE_DRAW_DEBUG + if (DrawDebugType != EDrawDebugTrace::None) + { + bool bPersistent = DrawDebugType == EDrawDebugTrace::Persistent; + float LifeTime = (DrawDebugType == EDrawDebugTrace::ForDuration) ? DrawTime : 0.f; + + // @fixme, draw line with thickness = 2.f? + if (bHit && OutHit.bBlockingHit) + { + // Red up to the blocking hit, green thereafter + ::DrawDebugLine(World, Start, OutHit.ImpactPoint, TraceColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugLine(World, OutHit.ImpactPoint, End, TraceHitColor.ToFColor(true), bPersistent, LifeTime); + ::DrawDebugPoint(World, OutHit.ImpactPoint, 16, TraceColor.ToFColor(true), bPersistent, LifeTime); + } + else + { + // no hit means all red + ::DrawDebugLine(World, Start, End, TraceColor.ToFColor(true), bPersistent, LifeTime); + } + } +#endif + return bHit; +} +bool UGAAbilityBase::LineTraceSingleByChannelFromSocket(FName SocketName, float Range, ETraceTypeQuery TraceChannel, bool bTraceComplex, FHitResult& OutHit, + EDrawDebugTrace::Type DrawDebugType, bool bIgnoreSelf, FLinearColor TraceColor, FLinearColor TraceHitColor, float DrawTime) +{ + return false; +} +bool UGAAbilityBase::LineTraceSingleByChannelCorrected(FName SocketName, float Range, ETraceTypeQuery TraceChannel, bool bTraceComplex, FHitResult& OutHit, + EDrawDebugTrace::Type DrawDebugType, bool bIgnoreSelf, FLinearColor TraceColor, FLinearColor TraceHitColor, float DrawTime) +{ + return false; +} +/* Tracing Helpers End */ + +//Helpers +float UGAAbilityBase::GetActivationRemainingTime() const +{ + if (ActivationEffectHandle.Num() <= 0) + return 0; + return NativeGetEffectsComponent()->GameEffectContainer.GetRemainingTime(ActivationEffectHandle[0]); +} +float UGAAbilityBase::GetActivationRemainingTimeNormalized() const +{ + if (ActivationEffectHandle.Num() <= 0) + return 0; + return NativeGetEffectsComponent()->GameEffectContainer.GetRemainingTimeNormalized(ActivationEffectHandle[0]); +} +float UGAAbilityBase::GetActivationCurrentTime() const +{ + if (ActivationEffectHandle.Num() <= 0) + return 0; + return NativeGetEffectsComponent()->GameEffectContainer.GetCurrentTime(ActivationEffectHandle[0]); +} +float UGAAbilityBase::GetActivationCurrentTimeNormalized() const +{ + if (ActivationEffectHandle.Num() <= 0) + return 0; + return NativeGetEffectsComponent()->GameEffectContainer.GetCurrentTimeNormalized(ActivationEffectHandle[0]); +} +float UGAAbilityBase::GetActivationEndTime() const +{ + if (ActivationEffectHandle.Num() <= 0) + return 0; + return NativeGetEffectsComponent()->GameEffectContainer.GetEndTime(ActivationEffectHandle[0]); +} +float UGAAbilityBase::BP_GetActivationRemainingTime() +{ + return GetActivationRemainingTime(); +} +float UGAAbilityBase::BP_GetActivationRemainingTimeNormalized() +{ + return GetActivationRemainingTimeNormalized(); +} +float UGAAbilityBase::BP_GetActivationCurrentTime() +{ + return GetActivationCurrentTime(); +} +float UGAAbilityBase::BP_GetActivationCurrentTimeNormalized() +{ + return GetActivationCurrentTimeNormalized(); +} +float UGAAbilityBase::BP_GetActivationEndTime() +{ + return GetActivationEndTime(); +} + + +float UGAAbilityBase::GetCooldownRemainingTime() const +{ + if (CooldownEffectHandle.Num() <= 0) + return 0; + return NativeGetEffectsComponent()->GameEffectContainer.GetRemainingTime(CooldownEffectHandle[0]); +} +float UGAAbilityBase::GetCooldownRemainingTimeNormalized() const +{ + if (CooldownEffectHandle.Num() <= 0) + return 0; + return NativeGetEffectsComponent()->GameEffectContainer.GetRemainingTimeNormalized(CooldownEffectHandle[0]); +} +float UGAAbilityBase::GetCooldownCurrentTime() const +{ + if (CooldownEffectHandle.Num() <= 0) + return 0; + return NativeGetEffectsComponent()->GameEffectContainer.GetCurrentTime(CooldownEffectHandle[0]); +} +float UGAAbilityBase::GetCooldownCurrentTimeNormalized() const +{ + if (CooldownEffectHandle.Num() <= 0) + return 0; + return NativeGetEffectsComponent()->GameEffectContainer.GetCurrentTimeNormalized(CooldownEffectHandle[0]); +} +float UGAAbilityBase::GetCooldownEndTime() const +{ + if (CooldownEffectHandle.Num() <= 0) + return 0; + return NativeGetEffectsComponent()->GameEffectContainer.GetEndTime(CooldownEffectHandle[0]); +} +float UGAAbilityBase::BP_GetCooldownRemainingTime() +{ + return GetCooldownRemainingTime(); +} +float UGAAbilityBase::BP_GetCooldownRemainingTimeNormalized() +{ + return GetCooldownRemainingTimeNormalized(); +} +float UGAAbilityBase::BP_GetCooldownCurrentTime() +{ + return GetCooldownCurrentTime(); +} +float UGAAbilityBase::BP_GetCooldownCurrentTimeNormalized() +{ + return GetCooldownCurrentTimeNormalized(); +} +float UGAAbilityBase::BP_GetCooldownEndTime() +{ + return GetCooldownEndTime(); +} + +AActor* UGAAbilityBase::BP_GetAvatar() +{ + return AvatarActor; +} + + +void UGAAbilityBase::OnLatentTaskAdded(FName InstanceName, class UAFTaskBase* TaskIn) +{ + if (!InstanceName.IsNone()) + { + AbilityTasks.Add(InstanceName, TaskIn); + } +}; +void UGAAbilityBase::AddReplicatedTask(class UAFTaskBase* TaskIn) +{ + AbilityComponent->ReplicatedTasks.Add(TaskIn); +} +void UGAAbilityBase::OnLatentTaskRemoved(class UAFTaskBase* TaskIn) +{ +}; + +void UGAAbilityBase::OnLatentTaskActivated(class UAFTaskBase* TaskIn) +{ +}; +void UGAAbilityBase::OnLatentTaskDeactivated(class UAFTaskBase* TaskIn) +{ +}; + +class UAFTaskBase* UGAAbilityBase::GetCachedLatentAction(FName TaskName) +{ + return AbilityTasks.FindRef(TaskName); +} +class UGAAbilityTask* UGAAbilityBase::GetAbilityTask(const FName& InName) +{ + UAFTaskBase* result = AbilityTasks.FindRef(InName); + return Cast(result); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/GAAbilityBlueprint.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/GAAbilityBlueprint.cpp new file mode 100644 index 0000000..71133ea --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/GAAbilityBlueprint.cpp @@ -0,0 +1,33 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFramework.h" +#include "GAAbilityBlueprint.h" + +////////////////////////////////////////////////////////////////////////// +// UGameplayAbilityBlueprint + +UGAAbilityBlueprint::UGAAbilityBlueprint(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +#if WITH_EDITOR + +/** Returns the most base gameplay ability blueprint for a given blueprint (if it is inherited from another ability blueprint, returning null if only native / non-ability BP classes are it's parent) */ +UGAAbilityBlueprint* UGAAbilityBlueprint::FindRootGameplayAbilityBlueprint(UGAAbilityBlueprint* DerivedBlueprint) +{ + UGAAbilityBlueprint* ParentBP = NULL; + + // Determine if there is a gameplay ability blueprint in the ancestry of this class + for (UClass* ParentClass = DerivedBlueprint->ParentClass; ParentClass != UObject::StaticClass(); ParentClass = ParentClass->GetSuperClass()) + { + if (UGAAbilityBlueprint* TestBP = Cast(ParentClass->ClassGeneratedBy)) + { + ParentBP = TestBP; + } + } + + return ParentBP; +} + +#endif diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/AFAbilityTask_SpawnProjectile.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/AFAbilityTask_SpawnProjectile.cpp new file mode 100644 index 0000000..dee0062 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/AFAbilityTask_SpawnProjectile.cpp @@ -0,0 +1,30 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAbilityTask_SpawnProjectile.h" + + + + +UAFAbilityTask_SpawnProjectile* UAFAbilityTask_SpawnProjectile::Ability_SpawnProjectile(UGAAbilityBase* WorldContextObject, + FName InTaskName, + FVector InStartLocation, + FVector InEndLocation, + float InLaunchSpeed, + float InOverrideGravityZ, + EAFPRojectileSpawnTraceOption InTraceOption, + float InCollisionRadius, + bool InbFavorHighArc, + bool InbDrawDebug) +{ + auto MyObj = NewAbilityTask(WorldContextObject, InTaskName); + MyObj->StartLocation = InStartLocation; + MyObj->EndLocation = InEndLocation; + MyObj->LaunchSpeed = InLaunchSpeed; + MyObj->OverrideGravityZ = InOverrideGravityZ; + MyObj->TraceOption = InTraceOption; + MyObj->CollisionRadius = InCollisionRadius; + MyObj->bFavorHighArc = InbFavorHighArc; + MyObj->bDrawDebug = InbDrawDebug; + return MyObj; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask.cpp new file mode 100644 index 0000000..190da1a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask.cpp @@ -0,0 +1,12 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "../../AbilityFramework.h" +#include "../GAAbilityBase.h" +#include "GAAbilityTask.h" + +UGAAbilityTask::UGAAbilityTask(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + bIsReplicated = false; + SetFlags(RF_StrongRefOnFrame); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_CreateObject.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_CreateObject.cpp new file mode 100644 index 0000000..c82011a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_CreateObject.cpp @@ -0,0 +1,64 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../../AbilityFramework.h" +#include "GAAbilityTask_CreateObject.h" + +UGAAbilityTask_CreateObject* UGAAbilityTask_CreateObject::CreateObject(UGAAbilityBase* WorldContextObject, + FName InTaskName, TSubclassOf Class, UObject* Outer) +{ + auto MyObj = NewAbilityTask(WorldContextObject); + //if(MyObj) + // MyObj->SpawnObject(WorldContextObject, InClass, Outer); + //MyObj->CachedTargetDataHandle = TargetData; + return MyObj; +} + +// --------------------------------------------------------------------------------------- + +bool UGAAbilityTask_CreateObject::BeginSpawningActor(UGAAbilityBase* WorldContextObject, + TSubclassOf Class, UObject*& SpawnedActor) +{ + //if (Ability.IsValid() && Ability.Get()->GetCurrentActorInfo()->IsNetAuthority()) + //{ + //UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject); + //if (World) + //{ + SpawnedActor = NewObject(WorldContextObject, Class); + //} + //} + + if (SpawnedActor == nullptr) + { + Failure.Broadcast(nullptr); + return false; + } + UE_LOG(AbilityFramework, Log, TEXT("Begin Spawning Actor in GAAbilityTask_SpawnActor")); + return true; +} + +void UGAAbilityTask_CreateObject::FinishSpawningActor(UGAAbilityBase* WorldContextObject, UObject* SpawnedActor) +{ + if (SpawnedActor) + { + FTransform SpawnTransform;// = AbilitySystemComponent->GetOwner()->GetTransform(); + + //if (FGameplayAbilityTargetData* LocationData = CachedTargetDataHandle.Get(0)) //Hardcode to use data 0. It's OK if data isn't useful/valid. + //{ + // //Set location. Rotation is unaffected. + // if (LocationData->HasHitResult()) + // { + // SpawnTransform.SetLocation(LocationData->GetHitResult()->Location); + // } + // else if (LocationData->HasEndPoint()) + // { + // SpawnTransform.SetLocation(LocationData->GetEndPoint()); + // } + //} + + //SpawnedActor->FinishSpawning(SpawnTransform); + + Success.Broadcast(SpawnedActor); + } + UE_LOG(AbilityFramework, Log, TEXT("Finish Spawning Actor in GAAbilityTask_SpawnActor")); + EndTask(); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_PlayMontage.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_PlayMontage.cpp new file mode 100644 index 0000000..3ab4e2e --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_PlayMontage.cpp @@ -0,0 +1,50 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../../AbilityFramework.h" +#include "../../AFAbilityComponent.h" +#include "GAAbilityTask_PlayMontage.h" + +UGAAbilityTask_PlayMontage* UGAAbilityTask_PlayMontage::AbilityPlayMontage(UGAAbilityBase* WorldContextObject, + FName InTaskName, UAnimMontage* MontageIn, FName SectionNameIn, float PlayRateIn, + bool bInUseActivationTime) +{ + auto MyObj = NewAbilityTask(WorldContextObject); + MyObj->Montage = MontageIn; + MyObj->SectionName = SectionNameIn; + MyObj->PlayRate = PlayRateIn; + MyObj->bUseActivationTime = bInUseActivationTime; + return MyObj; +} + +void UGAAbilityTask_PlayMontage::Activate() +{ + AbilityComponent->OnAbilityNotifyBegin.Unbind(); + AbilityComponent->OnAbilityNotifyTick.Unbind(); + AbilityComponent->OnAbilityNotifyEnd.Unbind(); + + AbilityComponent->OnAbilityNotifyBegin.BindUObject(this, &UGAAbilityTask_PlayMontage::BroadcastStartNotifyState); + AbilityComponent->OnAbilityNotifyTick.BindUObject(this, &UGAAbilityTask_PlayMontage::BroadcastTickNotifyState); + AbilityComponent->OnAbilityNotifyEnd.BindUObject(this, &UGAAbilityTask_PlayMontage::BroadcastEndNotifyState); + if (bUseActivationTime) + { + PlayRate = Ability->CalculateAnimationSpeed(Montage); + Ability->PlayMontage(Montage, SectionName, PlayRate); + } + else + { + Ability->PlayMontage(Montage, SectionName, PlayRate); + } +} + +void UGAAbilityTask_PlayMontage::BroadcastStartNotifyState(const FGameplayTag& InTag, const FName& InName) +{ + NotifyBegin.Broadcast(InTag, InName); +} +void UGAAbilityTask_PlayMontage::BroadcastEndNotifyState(const FGameplayTag& InTag, const FName& InName) +{ + NotifyTick.Broadcast(InTag, InName); +} +void UGAAbilityTask_PlayMontage::BroadcastTickNotifyState(const FGameplayTag& InTag, const FName& InName) +{ + NotifyEnd.Broadcast(InTag, InName); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_Repeat.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_Repeat.cpp new file mode 100644 index 0000000..1ee4cbb --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_Repeat.cpp @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../../AbilityFramework.h" +#include "GAAbilityTask_Repeat.h" + + + + +UGAAbilityTask_Repeat* UGAAbilityTask_Repeat::CreateRepeatTask(UGAAbilityBase* WorldContextObject, + FName InTaskName) +{ + auto MyObj = NewAbilityTask(WorldContextObject); + //MyObj->CachedTargetDataHandle = TargetData; + return MyObj; +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_SpawnActor.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_SpawnActor.cpp new file mode 100644 index 0000000..a075365 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_SpawnActor.cpp @@ -0,0 +1,70 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../../AbilityFramework.h" +#include "GAAbilityTask_SpawnActor.h" + + + + + +UGAAbilityTask_SpawnActor* UGAAbilityTask_SpawnActor::SpawnActor(UGAAbilityBase* WorldContextObject, + FName InTaskName, TSubclassOf InClass) +{ + auto MyObj = NewAbilityTask(WorldContextObject); + //MyObj->CachedTargetDataHandle = TargetData; + return MyObj; +} + +// --------------------------------------------------------------------------------------- +void UGAAbilityTask_SpawnActor::Activate() +{ + UE_LOG(AbilityFramework, Log, TEXT("TArget object spawned")); + //EndTask(); +} + +bool UGAAbilityTask_SpawnActor::BeginSpawningActor(UGAAbilityBase* WorldContextObject, TSubclassOf InClass, AActor*& SpawnedActor) +{ + //if (Ability.IsValid() && Ability.Get()->GetCurrentActorInfo()->IsNetAuthority()) + //{ + UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); + if (World) + { + SpawnedActor = World->SpawnActorDeferred(InClass, FTransform::Identity, NULL, NULL, ESpawnActorCollisionHandlingMethod::AlwaysSpawn); + } + //} + + if (SpawnedActor == nullptr) + { + Failure.Broadcast(nullptr); + return false; + } + UE_LOG(AbilityFramework, Log, TEXT("Begin Spawning Actor in GAAbilityTask_SpawnActor")); + return true; +} + +void UGAAbilityTask_SpawnActor::FinishSpawningActor(UGAAbilityBase* WorldContextObject, AActor* SpawnedActor) +{ + if (SpawnedActor) + { + FTransform SpawnTransform;// = AbilitySystemComponent->GetOwner()->GetTransform(); + + //if (FGameplayAbilityTargetData* LocationData = CachedTargetDataHandle.Get(0)) //Hardcode to use data 0. It's OK if data isn't useful/valid. + //{ + // //Set location. Rotation is unaffected. + // if (LocationData->HasHitResult()) + // { + // SpawnTransform.SetLocation(LocationData->GetHitResult()->Location); + // } + // else if (LocationData->HasEndPoint()) + // { + // SpawnTransform.SetLocation(LocationData->GetEndPoint()); + // } + //} + + SpawnedActor->FinishSpawning(SpawnTransform); + + Success.Broadcast(SpawnedActor); + } + UE_LOG(AbilityFramework, Log, TEXT("Finish Spawning Actor in GAAbilityTask_SpawnActor")); + //EndTask(); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_TargetData.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_TargetData.cpp new file mode 100644 index 0000000..9221e99 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_TargetData.cpp @@ -0,0 +1,154 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../../AbilityFramework.h" +#include "../GAAbilityBase.h" +#include "GAAbilityTask_TargetData.h" + + +UGAAbilityTask_TargetData* UGAAbilityTask_TargetData::CreateTargetDataTask(UGAAbilityBase* WorldContextObject, + FName InTaskName, + bool bDrawDebug, + bool bDrawCorrectedDebug, + bool bUseCorrectedTrace, + EGASConfirmType ConfirmTypeIn, + float Range) +{ + auto MyObj = NewAbilityTask(WorldContextObject); + + if (MyObj) + { + MyObj->Range = Range; + MyObj->ConfirmType = ConfirmTypeIn; + MyObj->bIsTickable = false; + MyObj->bDrawDebug = bDrawDebug; + MyObj->bDrawCorrectedDebug = bDrawCorrectedDebug; + MyObj->bUseCorrectedTrace = bUseCorrectedTrace; + } + return MyObj; +} + +void UGAAbilityTask_TargetData::Activate() +{ + switch (ConfirmType) + { + case EGASConfirmType::Instant: + { + FHitResult Hit = LineTrace(); + OnReceiveTargetData.Broadcast(Hit); + EndTask(); + break; + } + case EGASConfirmType::WaitForConfirm: + { + if (Ability.IsValid()) + { + if (!Ability->OnConfirmDelegate.IsBoundToObject(this)) + { + Ability->OnConfirmDelegate.AddUObject(this, &UGAAbilityTask_TargetData::OnConfirm); + bIsTickable = true; + } + if (!Ability->OnConfirmCastingEndedDelegate.IsBoundToObject(this)) + { + Ability->OnConfirmCastingEndedDelegate.AddUObject(this, &UGAAbilityTask_TargetData::OnCastEndedConfirm); + } + } + break; + } + } +} + +// --------------------------------------------------------------------------------------- + +void UGAAbilityTask_TargetData::OnConfirm() +{ + FHitResult Hit(ForceInit);// = LineTrace(); + OnConfirmed.Broadcast(Hit); + Ability->OnConfirmDelegate.RemoveAll(this); +} +void UGAAbilityTask_TargetData::OnCastEndedConfirm() +{ + FHitResult Hit = LineTrace(); + OnReceiveTargetData.Broadcast(Hit); + bIsTickable = false; + EndTask(); +} +void UGAAbilityTask_TargetData::Tick(float DeltaTime) +{ + //FHitResult HitOut = LineTrace(); +} + +FHitResult UGAAbilityTask_TargetData::LineTrace() +{ + FHitResult HitOut; + APlayerController* PC = Ability->PCOwner; + APawn* P = Ability->POwner; + UCameraComponent* Camera = Ability->OwnerCamera; + FVector TraceStart; + FRotator UnusedRot; + if (PC) + { + PC->PlayerCameraManager->GetCameraViewPoint(TraceStart, UnusedRot); +// TraceStart = Camera->GetComponentLocation(); + } + else + { + UnusedRot = P->GetBaseAimRotation(); + TraceStart = P->GetPawnViewLocation(); + } + + FVector TraceEnd = UnusedRot.Vector() * Range + TraceStart; + UWorld* World = GetWorld(); + FCollisionQueryParams ColParams; + ColParams.AddIgnoredActor(P); + FCollisionResponseParams ColResp; + World->LineTraceSingleByChannel(HitOut, TraceStart, TraceEnd, ECollisionChannel::ECC_WorldStatic, ColParams, ColResp); + if (HitOut.bBlockingHit) + { + FHitResult NewHit; + FVector Start = P->GetPawnViewLocation(); + FVector NewDir = (HitOut.Location - Start).GetSafeNormal(); + float Distance = FVector::Dist(Start, HitOut.Location); + FVector End = Start + (NewDir * Range); + World->LineTraceSingleByChannel(NewHit, Start, End, ECollisionChannel::ECC_WorldStatic, ColParams, ColResp); + + if (bDrawCorrectedDebug) + { + DrawDebugLine(GetWorld(), Start, End, FColor::Green, true, 2);// GetWorld()->DeltaTimeSeconds); + if (NewHit.bBlockingHit) + { + DrawDebugLine(GetWorld(), Start, NewHit.Location, FColor::Magenta, true, 2);//GetWorld()->DeltaTimeSeconds); + DrawDebugPoint(GetWorld(), NewHit.Location, 8, FColor::Magenta, true, 2);//GetWorld()->DeltaTimeSeconds); + } + } + } + else + { + FHitResult NewHit; + FVector Start = P->GetPawnViewLocation(); + FVector NewDir = (TraceEnd - Start).GetSafeNormal(); + float Distance = Range - FVector::Dist(TraceStart, Start); + FVector End = Start + (NewDir * Distance); + + World->LineTraceSingleByChannel(NewHit, Start, End, ECollisionChannel::ECC_WorldStatic, ColParams, ColResp); + + if (bDrawCorrectedDebug) + { + DrawDebugLine(GetWorld(), Start, End, FColor::Green, true, 2);//GetWorld()->DeltaTimeSeconds); + if (NewHit.bBlockingHit) + { + DrawDebugLine(GetWorld(), Start, NewHit.Location, FColor::Magenta, true, 2);//GetWorld()->DeltaTimeSeconds); + DrawDebugPoint(GetWorld(), NewHit.Location, 8, FColor::Magenta, true, 2);//GetWorld()->DeltaTimeSeconds); + } + } + } + if (bDrawDebug) + { + if (HitOut.bBlockingHit) + { + DrawDebugLine(GetWorld(), TraceStart, HitOut.ImpactPoint, FColor::Red, true, 2);//GetWorld()->DeltaTimeSeconds); + DrawDebugPoint(GetWorld(), HitOut.Location, 8, FColor::Red, true, 2);//GetWorld()->DeltaTimeSeconds); + } + DrawDebugLine(GetWorld(), TraceStart, TraceEnd, FColor::Green, true, 2);//GetWorld()->DeltaTimeSeconds); + } + return HitOut; +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_TargetDataCircle.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_TargetDataCircle.cpp new file mode 100644 index 0000000..1d539b4 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_TargetDataCircle.cpp @@ -0,0 +1,64 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../../AbilityFramework.h" +#include "../GAAbilityBase.h" +#include "GAAbilityTask_TargetDataCircle.h" + + +UGAAbilityTask_TargetDataCircle* UGAAbilityTask_TargetDataCircle::TargetCircleDataTask(UGAAbilityBase* WorldContextObject, + FName InTaskName, EGASConfirmType ConfirmTypeIn) +{ + auto MyObj = NewAbilityTask(WorldContextObject); + + if (MyObj) + { + MyObj->ConfirmType = ConfirmTypeIn; + } + return MyObj; +} + +void UGAAbilityTask_TargetDataCircle::Activate() +{ + switch (ConfirmType) + { + case EGASConfirmType::Instant: + { + + } + case EGASConfirmType::WaitForConfirm: + { + if (Ability.IsValid()) + { + if (!Ability->OnConfirmDelegate.IsBoundToObject(this)) + { + Ability->OnConfirmDelegate.AddUObject(this, &UGAAbilityTask_TargetDataCircle::OnConfirm); + } + } + } + } + //EndTask(); +} + +// --------------------------------------------------------------------------------------- + +//bool UGAAbilityTask_TargetDataCircle::BeginSpawningActor(UObject* WorldContextObject, UGASAbilityTargetingObject*& SpawnedActor) +//{ +// SpawnedActor = Class.GetDefaultObject();//NewObject(WorldContext +// return true; +//} +// +//void UGAAbilityTask_TargetDataCircle::FinishSpawningActor(UObject* WorldContextObject, UGASAbilityTargetingObject* SpawnedActor) +//{ +// if (SpawnedActor) +// { +// //Success.Broadcast(SpawnedActor); +// } +// UE_LOG(AbilityFramework, Log, TEXT("Finish Spawning Actor in GAAbilityTask_SpawnActor")); +// ReadyForActivation(); +//} + +void UGAAbilityTask_TargetDataCircle::OnConfirm() +{ + //TargetObj2->GetTarget(); + EndTask(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_TargetDataLineTrace.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_TargetDataLineTrace.cpp new file mode 100644 index 0000000..e1d2875 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_TargetDataLineTrace.cpp @@ -0,0 +1,261 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "Abilities/GAAbilityBase.h" +#include "GAAbilityTask_TargetDataLineTrace.h" + + +UGAAbilityTask_TargetDataLineTrace* UGAAbilityTask_TargetDataLineTrace::CreateTargetDataLineTrace(UGAAbilityBase* WorldContextObject + , FName InTaskName + , ETraceTypeQuery InTraceChannel + , USkeletalMeshComponent* InSocketComponent + , FName InSocketName + , bool bDrawDebug + , EAFConfirmType ConfirmTypeIn + , float Range) +{ + auto MyObj = NewAbilityTask(WorldContextObject, InTaskName); + + if (MyObj) + { + MyObj->TraceChannel = InTraceChannel; + MyObj->Range = Range; + MyObj->ConfirmType = ConfirmTypeIn; + MyObj->SocketComponent = InSocketComponent; + MyObj->SocketName = InSocketName; + MyObj->bIsTickable = false; + MyObj->bDrawDebug = bDrawDebug; + } + return MyObj; +} +UGAAbilityTask_TargetDataLineTrace::UGAAbilityTask_TargetDataLineTrace(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + bIsReplicated = true; +} +void UGAAbilityTask_TargetDataLineTrace::Activate() +{ + LocalHitResult.Reset(1, false); + FHitResult HitData; + switch (ConfirmType) + { + case EAFConfirmType::Instant: + { + + HitData = LineTrace(); + LocalHitResult = HitData; + //OnClient... Is called on both Client and server and is result of local simulation + //unconfirmed by server. This result might get overrided when data from server arrive to client + //it's good to spawn some cosmetic effects, but shouldn't be used to actually confirm hit result on client. + + //OnServer.. is confirmed by server that we got hit (or not), and should be used to show client confirmation + //for hits. + if (IsServerOrStandalone()) + { + //OnClientReceiveTargetData.Broadcast(HitData); + OnServerReceiveTargetData.Broadcast(HitData); + + } + else + { + OnClientUnconfirmedTargetData.Broadcast(HitData); + } + break; + } + case EAFConfirmType::WaitForConfirm: + { + if (Ability.IsValid()) + { + if (!Ability->OnConfirmDelegate.IsBoundToObject(this)) + { + Ability->OnConfirmDelegate.AddUObject(this, &UGAAbilityTask_TargetDataLineTrace::OnConfirm); + bIsTickable = true; + } + if (!Ability->OnConfirmCastingEndedDelegate.IsBoundToObject(this)) + { + Ability->OnConfirmCastingEndedDelegate.AddUObject(this, &UGAAbilityTask_TargetDataLineTrace::OnCastEndedConfirm); + } + } + break; + } + } + //if (HitData.IsValidBlockingHit()) + { + if (AbilityComponent->GetOwnerRole() < ROLE_Authority) + { + APlayerController* PC = Ability->PCOwner; + APawn* P = Ability->POwner; + + PC->PlayerState->RecalculateAvgPing(); + float ExactPing = PC->PlayerState->ExactPing; + + FAFLineTraceData TraceData; + TraceData.ExactPing = ExactPing; + TraceData.HitActor = HitData.GetActor(); + TraceData.HitLocation = HitData.Location; + ServerConfirmHitInfo(TraceData); + + } + } + if (AbilityComponent->GetOwnerRole() == ROLE_Authority) + { + EndTask(); + } + +} + +void UGAAbilityTask_TargetDataLineTrace::ServerConfirmHitInfo_Implementation(FAFLineTraceData TraceData) +{ + int test = 0; + UE_LOG(AbilityFramework, Log, TEXT("%s Server Confirm Hit"), *GetName()); + FAFLineTraceConfirmData ConfirmData; + ConfirmData.bConfirmed = true; + ConfirmData.HitActor = LocalHitResult.GetActor(); + ConfirmData.HitLocation = LocalHitResult.Location; + ClientConfirmHitInfo(ConfirmData); +} +bool UGAAbilityTask_TargetDataLineTrace::ServerConfirmHitInfo_Validate(FAFLineTraceData TraceData) +{ + return true; +} + +void UGAAbilityTask_TargetDataLineTrace::ClientConfirmHitInfo_Implementation(FAFLineTraceConfirmData ConfirmData) +{ + if (ConfirmData.bConfirmed) + { + UE_LOG(AbilityFramework, Log, TEXT("%s Client Hit Confirmed"), *GetName()); + OnClientReceiveTargetData.Broadcast(LocalHitResult); + } + else + { + UE_LOG(AbilityFramework, Log, TEXT("%s Client Hit Overrided"), *GetName()); + LocalHitResult.Actor = ConfirmData.HitActor; + LocalHitResult.Location = ConfirmData.HitLocation; + LocalHitResult.ImpactPoint = ConfirmData.HitLocation; + OnClientReceiveTargetData.Broadcast(LocalHitResult); + } + EndTask(); +} + +// --------------------------------------------------------------------------------------- + +void UGAAbilityTask_TargetDataLineTrace::OnConfirm() +{ + FHitResult Hit = LineTrace(); + //OnConfirmed.Broadcast(Hit); + + Ability->OnConfirmDelegate.RemoveAll(this); +} +void UGAAbilityTask_TargetDataLineTrace::OnCastEndedConfirm() +{ + FHitResult Hit = LineTrace(); + LocalHitResult = Hit; + //OnClient... Is called on both Client and server and is result of local simulation + //unconfirmed by server. This result might get overrided when data from server arrive to client + //it's good to spawn some cosmetic effects, but shouldn't be used to actually confirm hit result on client. + + //OnServer.. is confirmed by server that we got hit (or not), and should be used to show client confirmation + //for hits. + if (AbilityComponent->GetOwnerRole() < ROLE_Authority) + { + APlayerController* PC = Ability->PCOwner; + APawn* P = Ability->POwner; + + PC->PlayerState->RecalculateAvgPing(); + float ExactPing = PC->PlayerState->ExactPing; + + FAFLineTraceData TraceData; + TraceData.ExactPing = ExactPing; + TraceData.HitActor = Hit.GetActor(); + TraceData.HitLocation = Hit.Location; + ServerConfirmHitInfo(TraceData); + + } + + if (IsServerOrStandalone()) + { + //OnClientReceiveTargetData.Broadcast(HitData); + OnServerReceiveTargetData.Broadcast(Hit); + EndTask(); + } + else + { + OnClientUnconfirmedTargetData.Broadcast(Hit); + } + bIsTickable = false; + EndTask(); +} +void UGAAbilityTask_TargetDataLineTrace::Tick(float DeltaTime) +{ + //FHitResult HitOut = LineTrace(); +} + +FHitResult UGAAbilityTask_TargetDataLineTrace::LineTrace() +{ + FHitResult HitOut; + APlayerController* PC = Ability->PCOwner; + APawn* P = Ability->POwner; + + + UCameraComponent* Camera = Ability->OwnerCamera; + FVector TraceStart; + FRotator UnusedRot; + if (PC) + { + PC->PlayerCameraManager->GetCameraViewPoint(TraceStart, UnusedRot); +// TraceStart = Camera->GetComponentLocation(); + } + else + { + UnusedRot = P->GetBaseAimRotation(); + TraceStart = P->GetPawnViewLocation(); + } + + FVector TraceEnd = UnusedRot.Vector() * Range + TraceStart; + UWorld* World = GetWorld(); + FCollisionQueryParams ColParams; + ColParams.AddIgnoredActor(P); + FCollisionResponseParams ColResp; + ECollisionChannel CollisionChannel = UEngineTypes::ConvertToCollisionChannel(TraceChannel); + World->LineTraceSingleByChannel(HitOut, TraceStart, TraceEnd, CollisionChannel, ColParams, ColResp); + if (HitOut.bBlockingHit) + { + FHitResult NewHit; + FVector Start = SocketComponent->GetSocketLocation(SocketName); + FVector NewDir = (HitOut.Location - Start).GetSafeNormal(); + float Distance = FVector::Dist(Start, HitOut.Location); + FVector End = Start + (NewDir * Range); + World->LineTraceSingleByChannel(NewHit, Start, End, CollisionChannel, ColParams, ColResp); + UE_LOG(AbilityFramework, Log, TEXT("UGAAbilityTask_TargetDataLineTrace::LineTrace Corrected")); + if (bDrawDebug) + { + DrawDebugLine(GetWorld(), Start, End, FColor::Green, false, 1.0f); + if (NewHit.bBlockingHit) + { + DrawDebugLine(GetWorld(), Start, NewHit.Location, FColor::Magenta, false, 1.0f); + DrawDebugPoint(GetWorld(), NewHit.Location, 8, FColor::Magenta, false, 1.0f); + } + } + } + else + { + FHitResult NewHit; + FVector Start = SocketComponent->GetSocketLocation(SocketName); + FVector NewDir = (TraceEnd - Start).GetSafeNormal(); + float Distance = Range - FVector::Dist(TraceStart, Start); + FVector End = Start + (NewDir * Distance); + + World->LineTraceSingleByChannel(NewHit, Start, End, CollisionChannel, ColParams, ColResp); + UE_LOG(AbilityFramework, Log, TEXT("UGAAbilityTask_TargetDataLineTrace::LineTrace")); + if (bDrawDebug) + { + DrawDebugLine(GetWorld(), Start, End, FColor::Green, false, 1.0f); + if (NewHit.bBlockingHit) + { + DrawDebugLine(GetWorld(), Start, NewHit.Location, FColor::Magenta, false, 1.0f); + DrawDebugPoint(GetWorld(), NewHit.Location, 8, FColor::Magenta, false, 1.0f); + } + } + } + return HitOut; +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_WaitForConfirm.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_WaitForConfirm.cpp new file mode 100644 index 0000000..58e48ce --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_WaitForConfirm.cpp @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../../AbilityFramework.h" +#include "../GAAbilityBase.h" +#include "GAAbilityTask_WaitForConfirm.h" + + + + +UGAAbilityTask_WaitForConfirm* UGAAbilityTask_WaitForConfirm::CreateWaitConfirmTask(UGAAbilityBase* WorldContextObject, + FName InTaskName) +{ + auto MyObj = NewAbilityTask(WorldContextObject, InTaskName); + return MyObj; +} +void UGAAbilityTask_WaitForConfirm::Activate() +{ + if (AbilityComponent.IsValid() && Ability.IsValid()) + { + GetOuterUGAAbilityBase()->OnConfirmDelegate.AddUObject(this, &UGAAbilityTask_WaitForConfirm::OnConfirm); + } +} +void UGAAbilityTask_WaitForConfirm::Initialize() +{ + +} + +void UGAAbilityTask_WaitForConfirm::OnConfirm() +{ + Ability->OnConfirmDelegate.Clear(); + OnConfirmed.Broadcast(); + EndTask(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_WaitTargetData.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_WaitTargetData.cpp new file mode 100644 index 0000000..38f2151 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Abilities/Tasks/GAAbilityTask_WaitTargetData.cpp @@ -0,0 +1,84 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../../AbilityFramework.h" +#include "GAAbilityTask_WaitTargetData.h" + + +UGAAbilityTask_WaitTargetData::UGAAbilityTask_WaitTargetData(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + + +//UGAAbilityTask_WaitTargetData* UGAAbilityTask_WaitTargetData::WaitTargetData(UObject* WorldContextObject, +// FName InTaskName, TSubclassOf InClass, float InRange, ETraceTypeQuery InTraceChannel) +//{ +// auto MyObj = NewAbilityTask(WorldContextObject, "UGAAbilityTask_WaitTargetData"); +// MyObj->Range = InRange; +// MyObj->TraceChannel = InTraceChannel; +// return MyObj; +//} + +// --------------------------------------------------------------------------------------- +void UGAAbilityTask_WaitTargetData::Activate() +{ + UE_LOG(AbilityFramework, Log, TEXT("TArget object spawned")); + if (Ability.IsValid()) + { + if (!Ability->OnConfirmDelegate.IsBoundToObject(this)) + Ability->OnConfirmDelegate.AddUObject(this, &UGAAbilityTask_WaitTargetData::OnConfirm); + //Ability->ConfirmDelegate.CreateUObject(this, &UGAAbilityTask_WaitForConfirm::OnConfirm); + } +} + +//bool UGAAbilityTask_WaitTargetData::BeginSpawningActor(UObject* WorldContextObject, TSubclassOf Class, AGATargetingActor*& SpawnedActor) +//{ +// UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull); +// if (World) +// { +// SpawnedActor = World->SpawnActorDeferred(Class, FTransform::Identity, NULL, NULL, ESpawnActorCollisionHandlingMethod::AlwaysSpawn); +// } +// +// if (SpawnedActor == nullptr) +// { +// return false; +// } +// UE_LOG(AbilityFramework, Log, TEXT("Begin Spawning Actor in GAAbilityTask_SpawnActor")); +// return true; +//} +// +//void UGAAbilityTask_WaitTargetData::FinishSpawningActor(UObject* WorldContextObject, AGATargetingActor* SpawnedActor) +//{ +// if (SpawnedActor) +// { +// FTransform SpawnTransform; +// SpawnedActor->FinishSpawning(SpawnTransform); +// TargetActor = SpawnedActor; +// } +// ReadyForActivation(); +// UE_LOG(AbilityFramework, Log, TEXT("Finish Spawning Actor in GAAbilityTask_SpawnActor")); +//} +void UGAAbilityTask_WaitTargetData::TickTask(float DeltaSeconds, ELevelTick TickType, FGALatentFunctionTick& ThisTickFunction) +{ + //if (TargetActor && Ability.IsValid()) + //{ + // FHitResult OutHit; + // bool bHit = Ability->LineTraceSingleByChannelFromCamera(Range, TraceChannel, false, OutHit, + // EDrawDebugTrace::Type::None, true, FLinearColor::Green, FLinearColor::Red, 2); + // if (bHit) + // { + // TargetActor->SetActorLocation(OutHit.Location); + // } + // else + // { + // TargetActor->SetActorLocation(OutHit.TraceEnd); + // } + //} +} + +void UGAAbilityTask_WaitTargetData::OnConfirm() +{ + Ability->OnConfirmDelegate.Clear(); + OnConfirmed.Broadcast(); + EndTask(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AbilityFramework.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AbilityFramework.cpp new file mode 100644 index 0000000..a2e5e3e --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AbilityFramework.cpp @@ -0,0 +1,220 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "AbilityFramework.h" +#include "AFCueManager.h" +#include "Misc/CoreDelegates.h" +DEFINE_LOG_CATEGORY(AbilityFramework); +DEFINE_LOG_CATEGORY(GameAttributesGeneral); +DEFINE_LOG_CATEGORY(GameAttributes); +DEFINE_LOG_CATEGORY(GameAttributesEffects); + +DEFINE_LOG_CATEGORY(AFAttributes); +DEFINE_LOG_CATEGORY(AFEffects); +DEFINE_LOG_CATEGORY(AFAbilities); + +FAFEffectTimerManager* FAFEffectTimerManager::Instance = nullptr; + +DECLARE_CYCLE_STAT(TEXT("EffectTimer.Run"), STAT_EffectTimerRun, STATGROUP_EffectTimer); +FAFEffectTimer::FAFEffectTimer() +{ + +} +FAFEffectTimerWorker::FAFEffectTimerWorker() +{ + bActive = true; + Timers.Reset(); + Timers.SetNumZeroed(0); + InternalTime = FPlatformTime::ToSeconds64(FPlatformTime::Cycles64()); + for (int Idx = 0; Idx < 10000; Idx++) + { + float Duration = FMath::RandRange(15, 25); + AddTimer(Duration, 0.2); + } +} +FAFEffectTimerManager::FAFEffectTimerManager() +{ + TimerWorker = new FAFEffectTimerWorker(); + TimerThread = FRunnableThread::Create(TimerWorker, TEXT("EffectTimerThread"), 512*1024, TPri_Normal); + + check(TimerWorker != nullptr); +} +FAFEffectTimerManager::~FAFEffectTimerManager() +{ + //if (TimerThread) + //{ + // TimerThread->Kill(); + // delete TimerThread; + // TimerThread = nullptr; + //} +} +uint32 FAFEffectTimerWorker::Run() +{ + while (1) + { + SCOPE_CYCLE_COUNTER(STAT_EffectTimerRun); + InternalTime = FPlatformTime::ToSeconds64(FPlatformTime::Cycles64()); + //while (Timers.Num() > 0) + { +//#if UE_BUILD_DEVELOPTMENT || UE_BUILD_DEBUG + +//#endif // UE_BUILD_DEVELOPTMENT || UE_BUILD_DEBUG + + //for (FAFEffectTimer& Timer : Timers) + { + //auto It = Timers.CreateIterator(); + //for (; It; ++It) + //{ + + // if (It->bHavePeriod && (InternalTime > It->NextPeriodTime)) + // { + // double asdasd = It->ExpireTime - InternalTime; + // double FinalTime = InternalTime - It->StartTime; + // //UE_LOG(GameAttributesEffects, Log, TEXT("AsyncTimer Period TimeDifference: %f FinalTime: %f"), asdasd, FinalTime); + + // It->NextPeriodTime = InternalTime + It->PeriodTime; + // //It->PeriodDelegate.ExecuteIfBound(); + + // } + // if (It->bHaveDuration && (InternalTime > It->ExpireTime)) + // { + // double asdasd = It->ExpireTime - InternalTime; + // double FinalTime = InternalTime - It->StartTime; + // //UE_LOG(GameAttributesEffects, Log, TEXT("AsyncTimer Finish TimeDifference: %f FinalTime: %f"), asdasd, FinalTime); + // //It->ExpireDelegate.ExecuteIfBound(); + + // //FAFEffectTimer Out; + // //Timers.Remove(*It); + // //Timers.Shrink(); + // } + //} + for (FAFEffectTimer& Timer : Timers) + { + if (!Timer.bActive) + continue; + + if (Timer.bHavePeriod && (InternalTime > Timer.NextPeriodTime)) + { + double asdasd = Timer.ExpireTime - InternalTime; + double FinalTime = InternalTime - Timer.StartTime; + //UE_LOG(GameAttributesEffects, Log, TEXT("AsyncTimer Period TimeDifference: %f FinalTime: %f"), asdasd, FinalTime); + + Timer.NextPeriodTime = InternalTime + Timer.PeriodTime; + //Timer.PeriodDelegate.ExecuteIfBound(); + + } + if (Timer.bHaveDuration && (InternalTime > Timer.ExpireTime)) + { + double asdasd = Timer.ExpireTime - InternalTime; + double FinalTime = InternalTime - Timer.StartTime; + //UE_LOG(GameAttributesEffects, Log, TEXT("AsyncTimer Finish TimeDifference: %f FinalTime: %f"), asdasd, FinalTime); + //Timer.ExpireDelegate.ExecuteIfBound(); + //Timer.bActive = false; + //FAFEffectTimer Out; + //Timers.Remove(*It); + //Timers.Shrink(); + } + } + //UE_LOG(GameAttributesEffects, Log, TEXT("AsyncTimer TimeRemaining: %f"), asdasd); + //FAFEffectTimer& Top = Timers.HeapTop(); + + //if (Timer.bActive) + //{ + // if (Top.bHaveDuration && (InternalTime > Top.ExpireTime)) + // { + // double asdasd = Top.ExpireTime - InternalTime; + // double FinalTime = InternalTime - Top.StartTime; + // //UE_LOG(GameAttributesEffects, Log, TEXT("AsyncTimer Finish TimeDifference: %f FinalTime: %f"), asdasd, FinalTime); + // Top.ExpireDelegate.ExecuteIfBound(); + + // FAFEffectTimer Out; + // Timers.HeapPop(Out); + // Timers.Shrink(); + // } + //} + } + } + FPlatformProcess::Sleep(0.01); + } + return 0; +} +bool FAFEffectTimerWorker::Init() +{ + return true; +} +void FAFEffectTimerWorker::Stop() +{ + bActive = false; +} + +/** +* Exits the runnable object. +* +* Called in the context of the aggregating thread to perform any cleanup. +* @see Init, Run, Stop +*/ +void FAFEffectTimerWorker::Exit() +{ + //Timers.Empty(); + //bActive = false; +} + +FAFEffectTimeHandle FAFEffectTimerWorker::AddTimer(double InDuration, double InPeriod) +{ + FScopeLock lock(&CS); + //bActive = false; + FAFEffectTimer Timer; + Timer.Duration = InDuration; + Timer.PeriodTime = InPeriod; + Timer.bHaveDuration = InDuration <= 0 ? false : true; + Timer.bHavePeriod = InPeriod <= 0 ? false : true; + Timer.StartTime = InternalTime; // FPlatformTime::ToSeconds64(FPlatformTime::Cycles64());// InternalTime; + + Timer.ExpireTime = InternalTime + Timer.Duration; + Timer.NextPeriodTime = InternalTime + Timer.PeriodTime; + Timer.bActive = true; + Timers.Add(Timer); + int32 idx = Timers.Num() - 1; + //Timers.Push(Timer); + //Timers.Heapify(); + FAFEffectTimeHandle Handle; + Handle.Index = idx; + Timers[idx].Handle = Handle; + UE_LOG(GameAttributesEffects, Log, TEXT("AsyncTimer Start TimeDifference: %f"), (Timer.ExpireTime - InternalTime)); + + //since there is at least one timer, set timer manager to be active. + + bActive = true; + return Handle; +} + +FAFEffectTimeHandle FAFEffectTimerManager::AddTimer(double InDuration, double InPeriod) +{ + + return TimerWorker->AddTimer(InDuration, InPeriod); +} + +void FAbilityFramework::StartupModule() +{ +#if WITH_EDITOR + //FModuleManager::Get().LoadModule(TEXT("AbilityFrameworkEditor")); +#endif //WITH_EDITOR + //FAFEffectTimerManager::Get(); + // This code will execute after your module is loaded into memory (but after global variables are initialized, of course.) + + //initialize existing cues. + FCoreDelegates::OnFEngineLoopInitComplete.AddRaw(this, &FAbilityFramework::InitCues); +} + + +void FAbilityFramework::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +void FAbilityFramework::InitCues() +{ + UAFCueManager::Get(); +} + +IMPLEMENT_MODULE(FAbilityFramework, AbilityFramework) \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AnimNotify/AFAbilityNotifyState.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AnimNotify/AFAbilityNotifyState.cpp new file mode 100644 index 0000000..10e8534 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AnimNotify/AFAbilityNotifyState.cpp @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAbilityInterface.h" +#include "AFAbilityComponent.h" +#include "AFAbilityNotifyState.h" + + + + +void UAFAbilityNotifyState::NotifyBegin(class USkeletalMeshComponent * MeshComp, class UAnimSequenceBase * Animation, float TotalDuration) +{ + IAFAbilityInterface* IAbilities = Cast(MeshComp->GetOwner()); + if (IAbilities) + { + CachedAbilitiesComp = IAbilities->GetAbilityComp(); + CachedAbilitiesComp->OnAbilityNotifyBegin.ExecuteIfBound(Tag, Name); + } +} +void UAFAbilityNotifyState::NotifyTick(class USkeletalMeshComponent * MeshComp, class UAnimSequenceBase * Animation, float FrameDeltaTime) +{ + if (CachedAbilitiesComp) + { + CachedAbilitiesComp->OnAbilityNotifyTick.ExecuteIfBound(Tag, Name); + } +} +void UAFAbilityNotifyState::NotifyEnd(class USkeletalMeshComponent * MeshComp, class UAnimSequenceBase * Animation) +{ + if (CachedAbilitiesComp) + { + CachedAbilitiesComp->OnAbilityNotifyEnd.ExecuteIfBound(Tag, Name); + } +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/AnimNotify/AFAnimNotify.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AnimNotify/AFAnimNotify.cpp new file mode 100644 index 0000000..26e0f2d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/AnimNotify/AFAnimNotify.cpp @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAbilityComponent.h" +#include "AFAbilityInterface.h" +#include "AFAnimNotify.h" + + + + +void UAFAnimNotify::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) +{ + IAFAbilityInterface* IAbilities = Cast(MeshComp->GetOwner()); + if (!IAbilities) + return; + + UAFAbilityComponent* Comp = IAbilities->GetAbilityComp(); + Comp->OnAbilityNotifyBegin.ExecuteIfBound(Tag, Name); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributeBase.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributeBase.cpp new file mode 100644 index 0000000..5f2aef1 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributeBase.cpp @@ -0,0 +1,255 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFramework.h" +#include "GameplayTagContainer.h" +#include "../AFAbilityComponent.h" +#include "GAAttributesBase.h" +#include "../AFAbilityInterface.h" +#include "GAAttributeExtension.h" + +#include "GAAttributeBase.h" +DEFINE_STAT(STAT_CalculateBonus); +DEFINE_STAT(STAT_CurrentBonusByTag); +DEFINE_STAT(STAT_FinalBonusByTag); +//UGAAttributeBase::UGAAttributeBase(const FObjectInitializer& ObjectInitializer) +// : Super(ObjectInitializer) +//{ +// +//} +FAFAttributeBase::FAFAttributeBase() + : BaseBonusValue(0) + , CurrentValue(0) +{ + Modifiers.AddDefaulted(7); +}; +FAFAttributeBase::FAFAttributeBase(float BaseValueIn) + : BaseValue(BaseValueIn) + , BaseBonusValue(0) + , CurrentValue(BaseValue) + +{ + Modifiers.AddDefaulted(7); +}; + + +void FAFAttributeBase::InitializeAttribute(UAFAbilityComponent* InComponent, const FName InAttributeName) +{ + CurrentValue = BaseValue; + CalculateBonus(); + CurrentValue = GetFinalValue(); + Modifiers.Empty(); + Modifiers.AddDefaulted(7);// static_cast(EGAAttributeMod::Invalid)); + //Modifiers.AddDefaulted(static_cast(EGAAttributeMod::Invalid)); + AbilityComp = InComponent; + SelfName = FGAAttribute(InAttributeName); +} +void FAFAttributeBase::CopyFromOther(FAFAttributeBase* Other) +{ + if (!Other) + return; + + BaseValue = Other->BaseValue; + MinValue = Other->MinValue; + MaxValue = Other->MaxValue; + CurrentValue = Other->CurrentValue; + BaseBonusValue = Other->BaseBonusValue; + + CurrentValue = BaseValue; + CalculateBonus(); + CurrentValue = GetFinalValue(); +} +void FAFAttributeBase::CalculateBonus() +{ + SCOPE_CYCLE_COUNTER(STAT_CalculateBonus); + float AdditiveBonus = 0; + float SubtractBonus = 0; + float MultiplyBonus = 1; + float DivideBonus = 1; + //auto ModIt = Modifiers.CreateConstIterator(); + TMap& Additive = Modifiers[static_cast(EGAAttributeMod::Add)]; + TMap& Subtractive = Modifiers[static_cast(EGAAttributeMod::Subtract)]; + TMap& Multiplicative = Modifiers[static_cast(EGAAttributeMod::Multiply)]; + TMap& Divide = Modifiers[static_cast(EGAAttributeMod::Divide)]; + for (auto ModIt = Additive.CreateConstIterator(); ModIt; ++ModIt) + { + AdditiveBonus += ModIt->Value.Value; + } + for (auto ModIt = Subtractive.CreateConstIterator(); ModIt; ++ModIt) + { + SubtractBonus += ModIt->Value.Value; + } + for (auto ModIt = Multiplicative.CreateConstIterator(); ModIt; ++ModIt) + { + MultiplyBonus += ModIt->Value.Value; + } + for (auto ModIt = Divide.CreateConstIterator(); ModIt; ++ModIt) + { + DivideBonus += ModIt->Value.Value; + } + + float OldBonus = BaseBonusValue; + //calculate final bonus from modifiers values. + //we don't handle stacking here. It's checked and handled before effect is added. + BaseBonusValue = (AdditiveBonus - SubtractBonus); + BaseBonusValue = (BaseBonusValue * MultiplyBonus); + BaseBonusValue = (BaseBonusValue / DivideBonus); + //this is absolute maximum (not clamped right now). + float addValue = BaseBonusValue - OldBonus; + //reset to max = 200 + CurrentValue = CurrentValue + addValue; + /* + BaseValue = 200; + CurrentValue = 200; + BonusValue = 50; + CurrentValue = 200 + 50; + CurentValue == 250; + + Damage taken. + CurrentValue = 250 - 25; + CurrentValue == 225; + Bonus Ended - THERE IS NO SUBTRACTION ONLY FULL STATCK RECALCULATION; + Expected Result : 175; (225 - 50) + OldBonusValue = 50; + BonusValue = 0; + CurrentValue == 225; + BonusValue - OldBonusValue = -50; + CurrentValue = CurrentValue + (-50); ?? + + TwoBonuses 50 + 50; + CurrentValue = 300 - 25; + CurrentValue == 275; + Bonus Ended - THERE IS NO SUBTRACTION ONLY FULL STATCK RECALCULATION; + Expected Result : 225; (275 - 50) + OldBonusValue = 100; + BonusValue = 50; + CurrentValue == 225; + BonusValue - OldBonusValue = -50; + CurrentValue = CurrentValue + (-50); ?? + + Inverse Bonus is going to be Increased: + TwoBonuses 50 + 50; + CurrentValue = 300 - 25; + CurrentValue == 275; + Bonus Ended - THERE IS NO SUBTRACTION ONLY FULL STATCK RECALCULATION; + Expected Result : 325; (275 + 50) + OldBonusValue = 100; + new BonusValue = 150; (new bonus gives +50) + CurrentValue == 275; + BonusValue - OldBonusValue = 50; (150 - 100) = 50 + CurrentValue = CurrentValue + (50); ?? + */ +} + +bool FAFAttributeBase::CheckIfStronger(const FGAEffectMod& InMod) +{ + TMap& mods = Modifiers[static_cast(InMod.AttributeMod)]; + auto It = mods.CreateConstIterator(); + for (; It; ++It) + { + if (InMod > It->Value) + { + return true; + } + } + if (mods.Num() <= 0) + { + return true; + } + return false; +} +float FAFAttributeBase::Modify(const FGAEffectMod& ModIn, const FGAEffectHandle& HandleIn, + FGAEffectProperty& InProperty, const FGAEffectContext& InContext) +{ + //FString name = GetTypeName(); + if (ExtensionClass) + { + ExtensionClass.GetDefaultObject()->OnPreAttributeModify(AbilityComp, SelfName, CurrentValue); + + ExtensionClass.GetDefaultObject()->PreAttributeModify(InContext + , CurrentValue); + + + } + float returnValue = -1; + bool isPeriod = InProperty.GetPeriod() > 0; + bool IsDuration = InProperty.GetDuration() > 0; + + float PreValue = CurrentValue; + + if ( !InProperty.GetIsInstant()) + { + FGAModifier AttrMod(ModIn.AttributeMod, ModIn.Value, HandleIn); + AttrMod.Tags.AppendTags(InProperty.GetSpecData()->AttributeTags); + AddBonus(ModIn, HandleIn); + return ModIn.Value; + } + else + { + switch (ModIn.AttributeMod) + { + case EGAAttributeMod::Add: + { + float OldCurrentValue = CurrentValue; + UE_LOG(GameAttributes, Log, TEXT("FAFAttributeBase::Add:: OldCurrentValue: %f"), OldCurrentValue); + UE_LOG(GameAttributes, Log, TEXT("FAFAttributeBase::Add:: AddValue: %f"), ModIn.Value); + float Val = CurrentValue - (OldCurrentValue + ModIn.Value); + UE_LOG(GameAttributes, Log, TEXT("FAFAttributeBase::Add:: ActuallAddVal: %f"), Val); + CurrentValue -= Val; + CurrentValue = FMath::Clamp(CurrentValue, 0, GetFinalValue()); + UE_LOG(GameAttributes, Log, TEXT("FAFAttributeBase::Add:: CurrentValue: %f"), CurrentValue); + returnValue = CurrentValue; + break; + } + case EGAAttributeMod::Subtract: + { + float OldCurrentValue = CurrentValue; + UE_LOG(GameAttributes, Log, TEXT("FAFAttributeBase::Subtract:: OldCurrentValue: %f"), OldCurrentValue); + UE_LOG(GameAttributes, Log, TEXT("FAFAttributeBase::Subtract:: SubtractValue: %f"), ModIn.Value); + float Val = CurrentValue - (OldCurrentValue - ModIn.Value); + UE_LOG(GameAttributes, Log, TEXT("FAFAttributeBase::Subtract:: ActuallSubtractVal: %f"), Val); + CurrentValue -= Val; + CurrentValue = FMath::Clamp(CurrentValue, 0, GetFinalValue()); + UE_LOG(GameAttributes, Log, TEXT("FAFAttributeBase::Subtract:: CurrentValue: %f"), CurrentValue); + + returnValue = CurrentValue; + break; + } + case EGAAttributeMod::Multiply: + { + returnValue = -1; + break; + } + case EGAAttributeMod::Divide: + { + returnValue = -1; + break; + } + } + } + if (ExtensionClass) + { + ExtensionClass.GetDefaultObject()->OnPostAttributeModify(AbilityComp, SelfName, returnValue); + + ExtensionClass.GetDefaultObject()->PostAttributeModify( + InContext + , PreValue + , returnValue); + + } + return returnValue; +} + +void FAFAttributeBase::AddBonus(const FGAEffectMod& ModIn, const FGAEffectHandle& Handle) +{ + TMap& mods = Modifiers[static_cast(ModIn.AttributeMod)]; + FGAEffectMod& modsTemp = mods.FindOrAdd(Handle); + modsTemp = ModIn; + CalculateBonus(); +} +void FAFAttributeBase::RemoveBonus(const FGAEffectHandle& Handle, EGAAttributeMod InMod) +{ + TMap& mods = Modifiers[static_cast(InMod)]; + mods.Remove(Handle); + //Modifiers.Remove(Handle); + CalculateBonus(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributeExtension.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributeExtension.cpp new file mode 100644 index 0000000..f81bd71 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributeExtension.cpp @@ -0,0 +1,14 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../AbilityFramework.h" +#include "../AFAbilityComponent.h" +#include "GAAttributeExtension.h" + +void UGAAttributeExtension::OnPreAttributeModify(class UAFAbilityComponent* InComp, const FGAAttribute& Attribute, float InValue) +{ + InComp->NotifyOnPreAttributeModified(Attribute); +} +void UGAAttributeExtension::OnPostAttributeModify(class UAFAbilityComponent* InComp, const FGAAttribute& Attribute, float InValue) +{ + InComp->NotifyOnPostAttributeModified(Attribute); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributeGlobals.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributeGlobals.cpp new file mode 100644 index 0000000..de1a982 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributeGlobals.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../AbilityFramework.h" +#include "GAAttributeGlobals.h" + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributesBase.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributesBase.cpp new file mode 100644 index 0000000..fe29ab0 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributesBase.cpp @@ -0,0 +1,335 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFramework.h" +#include "../GAGlobalTypes.h" +#include "../AFAbilityComponent.h" +#include "Net/UnrealNetwork.h" +#include "GAAttributesBase.h" + +UGAAttributesBase::UGAAttributesBase(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + bNetAddressable = false; + LastAttributeProp = nullptr; + CachedFloatPropety = nullptr; +} +UGAAttributesBase::~UGAAttributesBase() +{ + LastAttributeProp = nullptr; //make sure we clear this pointer. + CachedFloatPropety = nullptr; +} +//void UGAAttributesBase::PostNetReceive() +//{ +// Super::PostNetReceive(); +//} +void UGAAttributesBase::InitializeAttributes(UAFAbilityComponent* InOwningAttributeComp) +{ + OwningAttributeComp = InOwningAttributeComp; + for (TFieldIterator StrIt(GetClass(), EFieldIteratorFlags::IncludeSuper); StrIt; ++StrIt) + { + FAFAttributeBase* attr = StrIt->ContainerPtrToValuePtr(this); + if (attr) + { + attr->InitializeAttribute(InOwningAttributeComp, StrIt->GetFName()); + TickableAttributes.Add(attr); + } + } + /* + Bind Delegates to map > For each attribute, so we don't store them inside attribute + but in this class. + */ + /*for (TFieldIterator PropIt(GetClass(), EFieldIteratorFlags::IncludeSuper); PropIt; ++PropIt) + { + int32 FoundIndex = -1; + FoundIndex = PropIt->GetName().Find("PostAttribute"); + FAFAttributeBase* attrPtr = GetAttribute(FGAAttribute(PropIt->GetFName())); + if (attrPtr) + { + return attrPtr->InitializeAttribute(); + } + }*/ + BP_InitializeAttributes(); +} + +void UGAAttributesBase::CopyFromOtherAttributes(UGAAttributesBase* Other) +{ + for (TFieldIterator StrIt(GetClass(), EFieldIteratorFlags::IncludeSuper); StrIt; ++StrIt) + { + FAFAttributeBase* ThisAttribute = StrIt->ContainerPtrToValuePtr(this); + FAFAttributeBase* OtherAttribute = Other->GetAttribute(FGAAttribute(StrIt->GetFName())); + + if (ThisAttribute && OtherAttribute) + { + ThisAttribute->CopyFromOther(OtherAttribute); + } + } +} + +void UGAAttributesBase::CopyFromStruct(UStruct* StructType, void* StructObject) +{ + for (TFieldIterator StrIt(StructType); StrIt; ++StrIt) + { + UProperty* Property = *StrIt; + if (UStructProperty* StructProp = Cast(Property)) + { + FAFAttributeBase* StructAttr = StructProp->ContainerPtrToValuePtr(StructObject); + UProperty* ThisProp = FindProperty(FGAAttribute(Property->GetFName())); + if (ThisProp) + { + FAFAttributeBase* ThisAttribute = ThisProp->ContainerPtrToValuePtr(this); + if (StructAttr && ThisAttribute) + { + ThisAttribute->CopyFromOther(StructAttr); + } + } + } + } +} + +void UGAAttributesBase::InitializeAttributesFromTable() +{ + if (!AttributeValues) + return; + + for (TFieldIterator StrIt(GetClass(), EFieldIteratorFlags::IncludeSuper); StrIt; ++StrIt) + { + FAFAttributeBase* attr = StrIt->ContainerPtrToValuePtr(this); + if (attr) + { + FName fieldName = StrIt->GetFName(); + FString OutString; + FAFAtributeRowData* row = AttributeValues->FindRow(fieldName, OutString); + if (row) + { + attr->SetBaseValue(row->BaseValue); + attr->SetMaxValue(row->MaxValue); + attr->SetMinValue(row->MinValue); + attr->SetCurrentValue(row->CurrentValue); + attr->SetExtensionClass(row->Extension); + attr->InitializeAttribute(OwningAttributeComp, StrIt->GetFName()); + } + //TickableAttributes.Add(attr); + } + } +} + +void UGAAttributesBase::Tick(float DeltaTime) +{ + for (FAFAttributeBase* Attribute : TickableAttributes) + { + } +} + + +UProperty* UGAAttributesBase::FindProperty(const FGAAttribute& AttributeIn) +{ + //if new attribute name is the same as last attribute name and pointer to last property + //is not null, then we just return last pointer instead of performing new search. + if ((AttributeIn.AttributeName == LastAttributeName) && LastAttributeProp) + return LastAttributeProp; + + LastAttributeName = AttributeIn.AttributeName; + LastAttributeProp = FindFieldChecked(this->GetClass(), LastAttributeName); + return LastAttributeProp; + return nullptr; +} +UStructProperty* UGAAttributesBase::GetStructAttribute(const FGAAttribute& Name) +{ + return FindField(this->GetClass(), Name.AttributeName); +} +FAFAttributeBase* UGAAttributesBase::GetAttribute(const FGAAttribute& Name) +{ + if (!Name.IsValid()) + { + UE_LOG(GameAttributesEffects, Log, TEXT("GetAttribute INVALID NAME")); + return nullptr; + } + UStructProperty* tempStruct = FindField(this->GetClass(), Name.AttributeName); + + FAFAttributeBase* attr = nullptr; + if (tempStruct) + { + attr = tempStruct->ContainerPtrToValuePtr(this); + return attr; + } + return attr; +} +void UGAAttributesBase::SetAttribute(const FGAAttribute& NameIn, UObject* NewVal) +{ + //UStructProperty* tempStruct = FindField(this->GetClass(), NameIn.AttributeName); +} +void UGAAttributesBase::SetAttributeAdditiveBonus(const FGAAttribute& NameIn, float NewValue) +{ + UStructProperty* tempStruct = FindField(this->GetClass(), NameIn.AttributeName); + UScriptStruct* scriptStruct = tempStruct->Struct; + + uint8* StructData = tempStruct->ContainerPtrToValuePtr(this); + + //omg figured it out! + //for (TFieldIterator It(scriptStruct); It; ++It) + //{ + // if (UProperty* Prop = *It) + // { + // if (Prop->GetFName() == "AdditiveBonus") + // { + // if (Prop->IsA(UFloatProperty::StaticClass())) + // { + // float testValue = NewValue; + // Cast(Prop)->SetPropertyValue_InContainer(StructData, testValue); + // break; + // } + // } + // } + //} +} + +float UGAAttributesBase::GetFinalAttributeValue(const FGAAttribute& Name) +{ + FAFAttributeBase* attrPtr = GetAttribute(Name); + if (attrPtr) + { + return attrPtr->GetFinalValue(); + } + return 0; +} +float UGAAttributesBase::GetCurrentAttributeValue(const FGAAttribute& Name) +{ + FAFAttributeBase* attrPtr = GetAttribute(Name); + if (attrPtr) + { + return attrPtr->GetCurrentValue(); + } + return 0; +} +float UGAAttributesBase::GetFloatValue(const FGAAttribute& AttributeIn) +{ + FAFAttributeBase* Attribute = GetAttribute(AttributeIn); + + if (!Attribute) + return 0; + return Attribute->GetCurrentValue(); +} + +float UGAAttributesBase::SetFloatValue(const FGAAttribute& AttributeIn, float ValueIn) +{ + if ((AttributeIn.AttributeName == LastAttributeName)) + { + if (CachedFloatPropety) + { + void* ValuePtr = CachedFloatPropety->ContainerPtrToValuePtr(this); + CachedFloatPropety->SetFloatingPointPropertyValue(ValuePtr, ValueIn); + return CachedFloatPropety->GetFloatingPointPropertyValue(ValuePtr); + } + } + //LastAttributeName = AttributeIn.AttributeName; + UNumericProperty* NumericProperty = CastChecked(FindProperty(AttributeIn)); + CachedFloatPropety = NumericProperty; + void* ValuePtr = CachedFloatPropety->ContainerPtrToValuePtr(this); + NumericProperty->SetFloatingPointPropertyValue(ValuePtr, ValueIn); + return CachedFloatPropety->GetFloatingPointPropertyValue(ValuePtr); + return 0; +} + +float UGAAttributesBase::AttributeOperation(const FGAAttribute& AttributeIn, float ValueIn, EGAAttributeMod Operation) +{ + switch (Operation) + { + case EGAAttributeMod::Add: + return AddAttributeFloat(GetFloatValue(AttributeIn), ValueIn); //don't want to set. + case EGAAttributeMod::Subtract: + return SubtractAttributeFloat(GetFloatValue(AttributeIn), ValueIn); + case EGAAttributeMod::Multiply: + return MultiplyAttributeFloat(GetFloatValue(AttributeIn), ValueIn); + case EGAAttributeMod::Divide: + return DivideAttributeFloat(GetFloatValue(AttributeIn), ValueIn); + case EGAAttributeMod::Set: + return SetFloatValue(AttributeIn, ValueIn); + default: + return 0; + } + return 0; +} + +float UGAAttributesBase::AddAttributeFloat(float ValueA, float ValueB) +{ + return ValueA + ValueB; +} +float UGAAttributesBase::SubtractAttributeFloat(float ValueA, float ValueB) +{ + return ValueA - ValueB; +} +float UGAAttributesBase::MultiplyAttributeFloat(float ValueA, float ValueB) +{ + return ValueA * ValueB; +} +float UGAAttributesBase::DivideAttributeFloat(float ValueA, float ValueB) +{ + return ValueA / ValueB; +} + +bool UGAAttributesBase::IsNameStableForNetworking() const +{ + /** + * IsNameStableForNetworking means an attribute set can be referred to its path name (relative to owning AActor*) over the network + * + * Attribute sets are net addressable if: + * -They are Default Subobjects (created in C++ constructor) + * -They were loaded directly from a package (placed in map actors) + * -They were explicitly set to bNetAddressable + */ + + return bNetAddressable;// || Super::IsNameStableForNetworking(); +} + + +void UGAAttributesBase::SetNetAddressable() +{ + bNetAddressable = true; +} +void UGAAttributesBase::ModifyAttribute(const FGAEffect& EffectIn) +{ + +} + +float UGAAttributesBase::ModifyAttribute(const FGAEffectMod& ModIn + , const FGAEffectHandle& HandleIn + , FGAEffectProperty& InProperty + , const FGAEffectContext& InContext) +{ + FAFAttributeBase* attr = nullptr; + UGAAttributesBase* atrObj = this; + + attr = GetAttribute(ModIn.Attribute); + float OutVal = -1; + if (attr) + { + OutVal = attr->Modify(ModIn, HandleIn, InProperty, InContext); + } + OnAttributeModified(ModIn, HandleIn); + return OutVal; +} + +void UGAAttributesBase::RemoveBonus(FGAAttribute AttributeIn, const FGAEffectHandle& HandleIn, EGAAttributeMod InMod) +{ + FAFAttributeBase* attr = nullptr; + + attr = GetAttribute(AttributeIn); + if (attr) + { + return attr->RemoveBonus(HandleIn, InMod); + } +} + +void UGAAttributesBase::OnAttributeModified(const FGAEffectMod& InMod, const FGAEffectHandle& InHandle) +{ + OwningAttributeComp->OnAttributeModified(InMod, InHandle, this); + FAFAttributeChangedData Data; + OwningAttributeComp->BroadcastAttributeChange(InMod.Attribute, Data); +} +void UGAAttributesBase::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const +{ + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + //possibly replicate it to everyone + //to allow prediction for UI. + DOREPLIFETIME(UGAAttributesBase, OwningAttributeComp); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributesBlueprintFunctionLibrary.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributesBlueprintFunctionLibrary.cpp new file mode 100644 index 0000000..a4fc7f1 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributesBlueprintFunctionLibrary.cpp @@ -0,0 +1,72 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFramework.h" + +#include "../AFAbilityInterface.h" +#include "GAAttributesBase.h" +#include "../AFAbilityComponent.h" +#include "GABlueprintLibrary.h" +#include "GAAttributesBlueprintFunctionLibrary.h" + + + +UGAAttributesBlueprintFunctionLibrary::UGAAttributesBlueprintFunctionLibrary(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + +} + +bool UGAAttributesBlueprintFunctionLibrary::EqualAttribute(const FGAAttribute& Compare, FGAAttribute Against) +{ + return Compare == Against; +} +FName UGAAttributesBlueprintFunctionLibrary::GetAttribute(FGAAttribute AttributeIn) +{ + return AttributeIn.AttributeName; +} +float UGAAttributesBlueprintFunctionLibrary::GetFinalAttributeValue(AActor* Target, FGAAttribute Name) +{ + IAFAbilityInterface* attributeInt = Cast(Target); + if (!attributeInt) + return 0; + if (!attributeInt->GetAttributes()) + return 0; + + return attributeInt->GetAttributes()->GetFinalAttributeValue(Name); +} +float UGAAttributesBlueprintFunctionLibrary::GetCurrentAttributeValue(AActor* Target, FGAAttribute Name) +{ + IAFAbilityInterface* attributeInt = Cast(Target); + if (!attributeInt) + return 0; + return attributeInt->GetAttributes()->GetCurrentAttributeValue(Name); +} +float UGAAttributesBlueprintFunctionLibrary::GetAttributeFloat(AActor* Target, FGAAttribute AttributeIn) +{ + IAFAbilityInterface* attributeInt = Cast(Target); + if (!attributeInt) + return 0; + + return attributeInt->GetAttributes()->GetFloatValue(AttributeIn); +} + +void UGAAttributesBlueprintFunctionLibrary::ExchangeAttributesValues( + APawn* Instigator + , UObject* Causer + , FAFPropertytHandle From + , FGAEffectHandle FromHandle + , UObject* FromTarget + , FAFPropertytHandle To + , FGAEffectHandle ToHandle + , UObject* ToTarget) +{ + IAFAbilityInterface* FromInterface = Cast(FromTarget); + IAFAbilityInterface* ToInterface = Cast(ToTarget); + + if (!FromInterface || !ToInterface) + return; + + FAFFunctionModifier ModF; + UGABlueprintLibrary::ApplyGameEffectToObject(From, FromTarget, Instigator, Causer, ModF); + UGABlueprintLibrary::ApplyGameEffectToObject(To, ToTarget, Instigator, Causer, ModF); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributesStats.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributesStats.cpp new file mode 100644 index 0000000..110fd10 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Attributes/GAAttributesStats.cpp @@ -0,0 +1,4 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFramework.h" +#include "GAAttributesStats.h" diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Cues/AFCueStaticBlueprint.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Cues/AFCueStaticBlueprint.cpp new file mode 100644 index 0000000..ee34def --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Cues/AFCueStaticBlueprint.cpp @@ -0,0 +1,8 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFCueStaticBlueprint.h" + + + + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Cues/AFCueStaticGeneratedClass.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Cues/AFCueStaticGeneratedClass.cpp new file mode 100644 index 0000000..13b398a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Cues/AFCueStaticGeneratedClass.cpp @@ -0,0 +1,8 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFCueStaticGeneratedClass.h" + + + + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueActor.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueActor.cpp new file mode 100644 index 0000000..2814c05 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueActor.cpp @@ -0,0 +1,162 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "MovieScene.h" +#include "GAEffectCueSequence.h" +#include "ActorSequencePlayer.h" +#include "AFCueActor.h" + +AAFCueActor::AAFCueActor(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + PrimaryActorTick.bCanEverTick = true; + PrimaryActorTick.bStartWithTickEnabled = true; + StartTime = 0; + EndTime = 5; + if (HasAnyFlags(RF_ClassDefaultObject) || GetArchetype() == GetDefault()) + { + Sequence = ObjectInitializer.CreateDefaultSubobject(this, "Sequence"); + Sequence->SetFlags(RF_Public | RF_Transactional); + SequencePlayer = ObjectInitializer.CreateDefaultSubobject(this, "SequencePlayer"); + } +} +void AAFCueActor::PostInitProperties() +{ + UpdateAssetRegistryInfo(); + Super::PostInitProperties(); +} + +void AAFCueActor::Serialize(FArchive& Ar) +{ + if (Ar.IsSaving()) + { + UpdateAssetRegistryInfo(); + } + + Super::Serialize(Ar); + + if (Ar.IsLoading()) + { + UpdateAssetRegistryInfo(); + } +} +#if WITH_EDITORONLY_DATA +void AAFCueActor::UpdateAssetBundleData() +{ + AssetBundleData.Reset(); + UpdateAssetRegistryInfo(); + + // By default parse the metadata + if (UAssetManager::IsValid()) + { + UAssetManager::Get().InitializeAssetBundlesFromMetadata(this, AssetBundleData); + } +} + +void AAFCueActor::PreSave(const class ITargetPlatform* TargetPlatform) +{ + Super::PreSave(TargetPlatform); + + UpdateAssetBundleData(); + + if (UAssetManager::IsValid()) + { + // Bundles may have changed, refresh + UAssetManager::Get().RefreshAssetData(this); + } +} +#endif +void AAFCueActor::PostLoad() +{ + Super::PostLoad(); + +#if WITH_EDITORONLY_DATA + FAssetBundleData OldData = AssetBundleData; + + UpdateAssetBundleData(); + + if (UAssetManager::IsValid() && OldData != AssetBundleData) + { + // Bundles changed, refresh + UAssetManager::Get().RefreshAssetData(this); + } +#endif +} +FPrimaryAssetId AAFCueActor::GetPrimaryAssetId() const +{ + FName dupa1 = FPackageName::GetShortFName(GetOutermost()->GetFName()); + + const AAFCueActor* A = this; + return FPrimaryAssetId(FPrimaryAssetType("ActorCue"), dupa1); + //if (HasAnyFlags(RF_ClassDefaultObject)) + { + UClass* SearchNativeClass = GetClass(); + + while (SearchNativeClass && !SearchNativeClass->HasAnyClassFlags(CLASS_Native | CLASS_Intrinsic)) + { + SearchNativeClass = SearchNativeClass->GetSuperClass(); + } + + if (SearchNativeClass && SearchNativeClass != GetClass()) + { + // If blueprint, return native class and asset name + + } + + // Native CDO, return nothing + return FPrimaryAssetId(); + } + + // Data assets use Class and ShortName by default, there's no inheritance so class works fine + //return FPrimaryAssetId(GetClass()->GetFName(), GetFName()); +} + +void AAFCueActor::SetAnimation(class UGAEffectCueSequence* InSequence) +{ + Sequence = InSequence; +} +// Called when the game starts or when spawned +void AAFCueActor::BeginPlay() +{ + if (!SequencePlayer) + { + SequencePlayer = NewObject(this, UActorSequencePlayer::StaticClass(), "SequencerPlayer"); + } + SequencePlayer->Initialize(Sequence, PlaybackSettings); + + Super::BeginPlay(); + //NativeBeginCue(); +} + +// Called every frame +void AAFCueActor::Tick( float DeltaTime ) +{ + Super::Tick( DeltaTime ); + if (SequencePlayer) + { + SequencePlayer->Update(DeltaTime); + } +} +void AAFCueActor::NativeBeginCue(AActor* InstigatorOut, AActor* TargetOut, UObject* Causer, + const FHitResult& HitInfo, const FGAEffectCueParams& CueParams) +{ + BeginCue(InstigatorOut, TargetOut, Causer, HitInfo); + if (!SequencePlayer) + { + SequencePlayer->Play(); + } +} + +void AAFCueActor::NativeOnExecuted() +{ + OnExecuted(); +} +void AAFCueActor::NativeOnRemoved() +{ + OnRemoved(); +} + +void AAFCueActor::UpdateAssetRegistryInfo() +{ + EffectCueTagSearch = CueTag.GetTagName(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueActorBlueprint.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueActorBlueprint.cpp new file mode 100644 index 0000000..b16fef9 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueActorBlueprint.cpp @@ -0,0 +1,33 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "AFCueActorBlueprint.h" + +////////////////////////////////////////////////////////////////////////// +// UGameplayAbilityBlueprint + +UAFCueActorBlueprint::UAFCueActorBlueprint(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +#if WITH_EDITOR + +/** Returns the most base gameplay ability blueprint for a given blueprint (if it is inherited from another ability blueprint, returning null if only native / non-ability BP classes are it's parent) */ +UAFCueActorBlueprint* UAFCueActorBlueprint::FindRootGameplayAbilityBlueprint(UAFCueActorBlueprint* DerivedBlueprint) +{ + UAFCueActorBlueprint* ParentBP = NULL; + + // Determine if there is a gameplay ability blueprint in the ancestry of this class + for (UClass* ParentClass = DerivedBlueprint->ParentClass; ParentClass != UObject::StaticClass(); ParentClass = ParentClass->GetSuperClass()) + { + if (UAFCueActorBlueprint* TestBP = Cast(ParentClass->ClassGeneratedBy)) + { + ParentBP = TestBP; + } + } + + return ParentBP; +} + +#endif \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueActorGeneratedClass.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueActorGeneratedClass.cpp new file mode 100644 index 0000000..f04cbf6 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueActorGeneratedClass.cpp @@ -0,0 +1,13 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "AFCueActorGeneratedClass.h" + +////////////////////////////////////////////////////////////////////////// +// UGameplayAbilityBlueprint + +UAFCueActorGeneratedClass::UAFCueActorGeneratedClass(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueStatic.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueStatic.cpp new file mode 100644 index 0000000..f6bc2d4 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFCueStatic.cpp @@ -0,0 +1,131 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" + +#include "Engine/AssetManager.h" + +#include "AFCueStatic.h" + + +UAFCueStatic::UAFCueStatic(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + +void UAFCueStatic::PostInitProperties() +{ + UpdateAssetRegistryInfo(); + Super::PostInitProperties(); +} + +void UAFCueStatic::Serialize(FArchive& Ar) +{ + if (Ar.IsSaving()) + { + UpdateAssetRegistryInfo(); + } + + Super::Serialize(Ar); + + if (Ar.IsLoading()) + { + UpdateAssetRegistryInfo(); + } +} +#if WITH_EDITORONLY_DATA +void UAFCueStatic::UpdateAssetBundleData() +{ + AssetBundleData.Reset(); + UpdateAssetRegistryInfo(); + + // By default parse the metadata + if (UAssetManager::IsValid()) + { + UAssetManager::Get().InitializeAssetBundlesFromMetadata(this, AssetBundleData); + } +} + +void UAFCueStatic::PreSave(const class ITargetPlatform* TargetPlatform) +{ + Super::PreSave(TargetPlatform); + + UpdateAssetBundleData(); + + if (UAssetManager::IsValid()) + { + // Bundles may have changed, refresh + UAssetManager::Get().RefreshAssetData(this); + } +} +#endif +void UAFCueStatic::PostLoad() +{ + Super::PostLoad(); + +#if WITH_EDITORONLY_DATA + FAssetBundleData OldData = AssetBundleData; + + UpdateAssetBundleData(); + + if (UAssetManager::IsValid() && OldData != AssetBundleData) + { + // Bundles changed, refresh + UAssetManager::Get().RefreshAssetData(this); + } +#endif +} +FPrimaryAssetId UAFCueStatic::GetPrimaryAssetId() const +{ + FName dupa1 = FPackageName::GetShortFName(GetOutermost()->GetFName()); + + const UAFCueStatic* A = this; + return FPrimaryAssetId(FPrimaryAssetType("StaticCue"), dupa1); + //if (HasAnyFlags(RF_ClassDefaultObject)) + { + UClass* SearchNativeClass = GetClass(); + + while (SearchNativeClass && !SearchNativeClass->HasAnyClassFlags(CLASS_Native | CLASS_Intrinsic)) + { + SearchNativeClass = SearchNativeClass->GetSuperClass(); + } + + if (SearchNativeClass && SearchNativeClass != GetClass()) + { + // If blueprint, return native class and asset name + + } + + // Native CDO, return nothing + return FPrimaryAssetId(); + } +} +void UAFCueStatic::UpdateAssetRegistryInfo() +{ + EffectCueTagSearch = CueTag.GetTagName(); +} + +bool UAFCueStatic::OnExecuted_Implementation(const FGAEffectCueParams& Hit) const +{ + return true; +} +void UAFCueStatic::OnActivate_Implementation(const FGAEffectCueParams& Hit) const +{ +} +void UAFCueStatic::OnExpire_Implementation(const FGAEffectCueParams& Hit) const +{ +} +void UAFCueStatic::OnRemoved_Implementation(const FGAEffectCueParams& Hit) const +{ +} + +UWorld* UAFCueStatic::GetWorld() const +{ + /*TIndirectArray WorldContexts = GEngine->GetWorldContexts(); + UWorld* World = nullptr; + for (const FWorldContext& Ctx : WorldContexts) + { + World = Ctx.World(); + }*/ + return nullptr; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectApplicationRequirement.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectApplicationRequirement.cpp new file mode 100644 index 0000000..a6e6ad6 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectApplicationRequirement.cpp @@ -0,0 +1,8 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFEffectApplicationRequirement.h" + + + + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectCustomApplication.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectCustomApplication.cpp new file mode 100644 index 0000000..8f04be7 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectCustomApplication.cpp @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "../AFAbilityComponent.h" +#include "AFEffectCustomApplication.h" + + + + +bool UAFEffectCustomApplication::ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + return true; +} + +void UAFEffectCustomApplication::ApplyExecute( + const FGAEffectHandle& InHandle + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + Params.GetContext().GetTargetEffectsComponent()->ExecuteEffect(InHandle, Params, Modifier); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectCustomStackingRule.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectCustomStackingRule.cpp new file mode 100644 index 0000000..bc4b54b --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectCustomStackingRule.cpp @@ -0,0 +1,14 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFEffectCustomStackingRule.h" + + + + +bool UAFEffectCustomStackingRule::CanStack(class UAFAbilityComponent* InComp, struct FGAEffectContainer* InContainer, + const FGAEffectHandle& InHandle) +{ + //InHandle.GetContext().TargetComp->ExecuteEffect(InHandle); + return true; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectSpecFunctionLibrary.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectSpecFunctionLibrary.cpp new file mode 100644 index 0000000..5d1704c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/AFEffectSpecFunctionLibrary.cpp @@ -0,0 +1,50 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFEffectSpecFunctionLibrary.h" + + + +void UAFEffectSpecFunctionLibrary::AppendOwnedTags(FAFEffectSpecHandle Spec, const FGameplayTagContainer& InTags) +{ + Spec.GetPtr()->OwnedTags.AppendTags(InTags); +} + +void UAFEffectSpecFunctionLibrary::CompareOwnedTags(FAFEffectSpecHandle Spec + , EAFTagContainerCompare Mode + , const FGameplayTagContainer& InTags + , EAFTagCompareResult& Result) +{ + switch (Mode) + { + case EAFTagContainerCompare::HasAny: + Spec.GetPtr()->OwnedTags.HasAny(InTags) ? Result = EAFTagCompareResult::Match : Result = EAFTagCompareResult::NoMatch; + break; + case EAFTagContainerCompare::HasAnyExact: + Spec.GetPtr()->OwnedTags.HasAnyExact(InTags) ? Result = EAFTagCompareResult::Match : Result = EAFTagCompareResult::NoMatch; + break; + case EAFTagContainerCompare::HasAll: + Spec.GetPtr()->OwnedTags.HasAll(InTags) ? Result = EAFTagCompareResult::Match : Result = EAFTagCompareResult::NoMatch; + break; + case EAFTagContainerCompare::HasAllExact: + Spec.GetPtr()->OwnedTags.HasAllExact(InTags) ? Result = EAFTagCompareResult::Match : Result = EAFTagCompareResult::NoMatch; + default: + break; + } +} + +void UAFEffectSpecFunctionLibrary::CompareOwnedTag(FAFEffectSpecHandle Spec + , EAFTagCompare Mode + , FGameplayTag InTag + , EAFTagCompareResult& Result) +{ + switch (Mode) + { + case EAFTagCompare::HasTag: + Spec.GetPtr()->OwnedTags.HasTag(InTag) ? Result = EAFTagCompareResult::Match : Result = EAFTagCompareResult::NoMatch; + break; + case EAFTagCompare::HasTagExact: + Spec.GetPtr()->OwnedTags.HasTagExact(InTag) ? Result = EAFTagCompareResult::Match : Result = EAFTagCompareResult::NoMatch; + break; + } +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/ApplicationRequirement/AFAttributeStongerOverride.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/ApplicationRequirement/AFAttributeStongerOverride.cpp new file mode 100644 index 0000000..95a6008 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/ApplicationRequirement/AFAttributeStongerOverride.cpp @@ -0,0 +1,39 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "../../Attributes/GAAttributeBase.h" +#include "../../AFAbilityInterface.h" +#include "AFAttributeStongerOverride.h" + + + + +bool UAFAttributeStongerOverride::CanApply( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FGAEffectHandle& InHandle + , struct FGAEffectContainer* InContainer) +{ + bool bCanApply = true; + FGAAttribute Attribute = Params.GetProperty().GetSpecData()->AtributeModifier.Attribute; + FAFAttributeBase* AttributePtr = Params.GetContext().TargetInterface->GetAttribute(Attribute); + FGAEffectProperty& InProperty = Params.GetProperty(); + + if (AttributePtr) + { + FGAEffectMod mod = FAFStatics::GetAttributeModifier(InProperty.GetAttributeModifier() + , InProperty.GetSpecData() + , Params.GetContext() + , InHandle); + + if (AttributePtr->CheckIfStronger(mod)) + { + bCanApply = true; + } + else + { + bCanApply = false; + } + } + return bCanApply; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/ApplicationRequirement/AFEffectAlreadyApplied.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/ApplicationRequirement/AFEffectAlreadyApplied.cpp new file mode 100644 index 0000000..9e44f37 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/ApplicationRequirement/AFEffectAlreadyApplied.cpp @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFEffectAlreadyApplied.h" + + + + +bool UAFEffectAlreadyApplied::CanApply( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FGAEffectHandle& InHandle + , struct FGAEffectContainer* InContainer) +{ + if (InContainer->ContainsEffectOfClass(Params.Property)) + { + return false; + } + return true; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAtributeDurationAdd.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAtributeDurationAdd.cpp new file mode 100644 index 0000000..a96c24c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAtributeDurationAdd.cpp @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "../GAGameEffect.h" +#include "AFEffectsComponent.h" +#include "AFAtributeDurationAdd.h" + + + + +bool UAFAtributeDurationAdd::ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + FTimerManager& DurationTimer = const_cast(Params).GetTargetTimerManager(); + + FTimerDelegate delDuration = FTimerDelegate::CreateUObject(Params.GetTargetEffectsComponent(), &UAFEffectsComponent::ExpireEffect, InHandle, Params); + DurationTimer.SetTimer(const_cast(EffectIn).DurationTimerHandle, delDuration, + Params.GetProperty().GetDuration(), false); + + return true; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAtributeDurationUnique.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAtributeDurationUnique.cpp new file mode 100644 index 0000000..d043d7a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAtributeDurationUnique.cpp @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "../GAGameEffect.h" +#include "AFEffectsComponent.h" +#include "AFAbilityInterface.h" +#include "AFAtributeDurationUnique.h" + + + + +bool UAFAtributeDurationUnique::ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + if (InContainer->IsEffectActive(Params.Property.SpecClass.SpecClass.Get())) + { + return false; + } + FTimerManager& DurationTimer = const_cast(Params).GetTargetTimerManager(); + + FTimerDelegate delDuration = FTimerDelegate::CreateUObject(Params.GetTargetEffectsComponent(), &UAFEffectsComponent::ExpireEffect, InHandle, Params); + DurationTimer.SetTimer(const_cast(EffectIn).DurationTimerHandle, delDuration, + Params.GetProperty().GetDuration(), false); + + return true; +} + +bool UAFAtributeDurationUnique::CanApply(class IAFAbilityInterface* Target, TSubclassOf EffectClass) +{ + if (!Target) + return false; + + return !Target->GetEffectsComponent()->IsEffectActive(EffectClass); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAttributeDurationInfinite.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAttributeDurationInfinite.cpp new file mode 100644 index 0000000..373b41c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAttributeDurationInfinite.cpp @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAttributeDurationInfinite.h" + + + + +bool UAFAttributeDurationInfinite::ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + return true; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAttributeDurationOverride.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAttributeDurationOverride.cpp new file mode 100644 index 0000000..02e6f6c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFAttributeDurationOverride.cpp @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "../GAGameEffect.h" +#include "AFEffectsComponent.h" +#include "AFAttributeDurationOverride.h" + + + + +bool UAFAttributeDurationOverride::ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + InContainer->RemoveEffect(Params.Property, Params.GetContext()); + + FTimerManager& DurationTimer = const_cast(Params).GetTargetTimerManager(); + + FTimerDelegate delDuration = FTimerDelegate::CreateUObject(Params.GetTargetEffectsComponent(), &UAFEffectsComponent::ExpireEffect, InHandle, Params); + DurationTimer.SetTimer(const_cast(EffectIn).DurationTimerHandle, delDuration, + Params.GetProperty().GetDuration(), false); + + return true; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationAdd.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationAdd.cpp new file mode 100644 index 0000000..a7bab63 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationAdd.cpp @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "../GAGameEffect.h" +#include "AFEffectsComponent.h" +#include "AFPeriodApplicationAdd.h" + + +bool UAFPeriodApplicationAdd::ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + FTimerManager& DurationTimer = const_cast(Params).GetTargetTimerManager(); + + FTimerDelegate delDuration = FTimerDelegate::CreateUObject(Params.GetTargetEffectsComponent(), &UAFEffectsComponent::ExpireEffect, InHandle, Params); + DurationTimer.SetTimer(const_cast(EffectIn).DurationTimerHandle, delDuration, + Params.GetProperty().GetDuration(), false); + + FTimerManager& PeriodTimer = const_cast(Params).GetTargetTimerManager(); + + FTimerDelegate PeriodDuration = FTimerDelegate::CreateUObject(Params.GetTargetEffectsComponent(), &UAFEffectsComponent::ExecuteEffect, InHandle, Params, Modifier); + PeriodTimer.SetTimer(const_cast(EffectIn).PeriodTimerHandle, PeriodDuration, + Params.GetProperty().GetPeriod(), true); + + //InContainer->AddEffect(InProperty, InHandle); + + return true; +} + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationExtend.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationExtend.cpp new file mode 100644 index 0000000..3d47b88 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationExtend.cpp @@ -0,0 +1,53 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "GAGlobalTypes.h" +#include "Effects/GAGameEffect.h" +#include "AFEffectsComponent.h" +#include "AFPeriodApplicationExtend.h" + + + + +bool UAFPeriodApplicationExtend::ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + TSet handles = InContainer->GetHandlesByClass(Params.GetProperty(), Params.GetContext()); + for (const FGAEffectHandle& handle : handles) + { + FGAEffect& ExtEffect = *InContainer->GetEffect(handle); + FGAEffect& Effect = const_cast(EffectIn); + + FGAEffectContext& ExtContext = const_cast(Params).GetContext(); + + FTimerManager& DurationTimer = const_cast(Params).GetTargetTimerManager(); + + float RemainingTime = DurationTimer.GetTimerRemaining(ExtEffect.DurationTimerHandle); + float NewDuration = RemainingTime + Effect.GetDurationTime(); + DurationTimer.ClearTimer(ExtEffect.DurationTimerHandle); + + FTimerDelegate delDuration = FTimerDelegate::CreateUObject(ExtContext.GetTargetEffectsComponent(), &UAFEffectsComponent::ExpireEffect, InHandle, Params); + DurationTimer.SetTimer(ExtEffect.DurationTimerHandle, delDuration, + NewDuration, false); + } + if (handles.Num() <= 0) + { + FGAEffect& Effect = const_cast(EffectIn);; + FTimerManager& DurationTimer = const_cast(Params).GetTargetTimerManager(); + + FTimerDelegate delDuration = FTimerDelegate::CreateUObject(Params.GetTargetEffectsComponent(), &UAFEffectsComponent::ExpireEffect, InHandle, Params); + DurationTimer.SetTimer(Effect.DurationTimerHandle, delDuration, + Params.GetProperty().GetDuration(), false); + + FTimerManager& PeriodTimer = const_cast(Params).GetTargetTimerManager(); + + FTimerDelegate PeriodDuration = FTimerDelegate::CreateUObject(Params.GetTargetEffectsComponent(), &UAFEffectsComponent::ExecuteEffect, InHandle, Params, Modifier); + PeriodTimer.SetTimer(Effect.PeriodTimerHandle, PeriodDuration, + Params.GetProperty().GetPeriod(), true); + } + return true; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationInfiniteAdd.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationInfiniteAdd.cpp new file mode 100644 index 0000000..7fc9e0a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationInfiniteAdd.cpp @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "../GAGameEffect.h" +#include "AFEffectsComponent.h" +#include "AFPeriodApplicationInfiniteAdd.h" + + +bool UAFPeriodApplicationInfiniteAdd::ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + FTimerManager& PeriodTimer = const_cast(Params).GetTargetTimerManager(); + + FTimerDelegate PeriodDuration = FTimerDelegate::CreateUObject(Params.GetTargetEffectsComponent(), &UAFEffectsComponent::ExecuteEffect, InHandle, Params, Modifier); + PeriodTimer.SetTimer(const_cast(EffectIn).PeriodTimerHandle, PeriodDuration, + Params.GetProperty().GetPeriod(), true); + + return true; +} + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationOverride.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationOverride.cpp new file mode 100644 index 0000000..255e753 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodApplicationOverride.cpp @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "../GAGameEffect.h" +#include "AFEffectsComponent.h" +#include "AFPeriodApplicationOverride.h" + + + + +bool UAFPeriodApplicationOverride::ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + + InContainer->RemoveEffect(Params.Property, Params.GetContext()); + + FTimerManager& DurationTimer = const_cast(Params).GetTargetTimerManager(); + + FTimerDelegate delDuration = FTimerDelegate::CreateUObject(Params.GetTargetEffectsComponent(), &UAFEffectsComponent::ExpireEffect, InHandle, Params); + DurationTimer.SetTimer(const_cast(EffectIn).DurationTimerHandle, delDuration, + Params.GetProperty().GetDuration(), false); + + FTimerManager& PeriodTimer = const_cast(Params).GetTargetTimerManager(); + + FTimerDelegate PeriodDuration = FTimerDelegate::CreateUObject(Params.GetTargetEffectsComponent(), &UAFEffectsComponent::ExecuteEffect, InHandle, Params, Modifier); + PeriodTimer.SetTimer(const_cast(EffectIn).PeriodTimerHandle, PeriodDuration, + Params.GetProperty().GetPeriod(), true); + + return true; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodicApplInfiniteOverride.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodicApplInfiniteOverride.cpp new file mode 100644 index 0000000..4585496 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/CustomApplications/AFPeriodicApplInfiniteOverride.cpp @@ -0,0 +1,8 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFPeriodicApplInfiniteOverride.h" + + + + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask.cpp new file mode 100644 index 0000000..d24b545 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask.cpp @@ -0,0 +1,8 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../../AbilityFramework.h" +#include "AFEffectTask.h" + + + + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_AppliedEffectEvent.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_AppliedEffectEvent.cpp new file mode 100644 index 0000000..df86500 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_AppliedEffectEvent.cpp @@ -0,0 +1,82 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAbilityInterface.h" +#include "AFEffectsComponent.h" +#include "AFEffectTask_AppliedEffectEvent.h" + + + + +UAFEffectTask_AppliedEffectEvent::UAFEffectTask_AppliedEffectEvent(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + +UAFEffectTask_AppliedEffectEvent* UAFEffectTask_AppliedEffectEvent::ListenAppliedEffectEvent(UGAEffectExtension* OwningExtension, FName TaskName, FGameplayTag Tag, AActor* OptionalExternalTarget, bool OnlyTriggerOnce) +{ + auto MyObj = NewEffectTask(OwningExtension, TaskName); + MyObj->Tag = Tag; + MyObj->SetExternalTarget(OptionalExternalTarget); + MyObj->OnlyTriggerOnce = OnlyTriggerOnce; + + return MyObj; +} + +void UAFEffectTask_AppliedEffectEvent::Activate() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + //(this, &UAFEffectTask_AppliedEffectEvent::GameplayEventCallback + FAFEventDelegate Delegate = FAFEventDelegate::CreateUObject(this, &UAFEffectTask_AppliedEffectEvent::GameplayEventCallback); + MyHandle = Delegate.GetHandle(); + ASC->AddAppliedEvent(Tag, Delegate); + } + + Super::Activate(); +} + +void UAFEffectTask_AppliedEffectEvent::GameplayEventCallback(FAFEventData Payload) +{ + //if (ShouldBroadcastAbilityTaskDelegates()) + { + OnEvent.Broadcast(Payload); + } + if (OnlyTriggerOnce) + { + EndTask(); + } +} +void UAFEffectTask_AppliedEffectEvent::OnTaskEnded() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + ASC->RemoveAppliedEvent(Tag, MyHandle); + } +} +void UAFEffectTask_AppliedEffectEvent::SetExternalTarget(AActor* Actor) +{ + if (Actor) + { + + if (IAFAbilityInterface* interface = Cast(Actor)) + { + UseExternalTarget = true; + OptionalExternalTarget = interface->GetEffectsComponent(); + } + + } +} + +UAFEffectsComponent* UAFEffectTask_AppliedEffectEvent::GetTargetASC() +{ + if (UseExternalTarget) + { + return OptionalExternalTarget; + } + + return EffectsComponent; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_AttributeChange.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_AttributeChange.cpp new file mode 100644 index 0000000..1e91f68 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_AttributeChange.cpp @@ -0,0 +1,70 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFEffectTask_AttributeChange.h" + + +UAFEffectTask_AttributeChange::UAFEffectTask_AttributeChange(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + +UAFEffectTask_AttributeChange* UAFEffectTask_AttributeChange::ListenAttributeChanged(UGAEffectExtension* OwningExtension, + FGAAttribute InAttribute, + AActor* OptionalExternalTarget, + bool OnlyTriggerOnce) +{ + auto MyObj = NewEffectTask(OwningExtension); + MyObj->Attribute = InAttribute; + MyObj->SetExternalTarget(OptionalExternalTarget); + MyObj->OnlyTriggerOnce = OnlyTriggerOnce; + + return MyObj; +} + +void UAFEffectTask_AttributeChange::Activate() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + // MyHandle = ASC->AttributeChanged.FindOrAdd(Attribute).AddUObject(this, &UAFEffectTask_AttributeChange::AttributeChangedCallback); + } + + Super::Activate(); +} + +void UAFEffectTask_AttributeChange::AttributeChangedCallback(FAFAttributeChangedData Payload) +{ + //if (ShouldBroadcastAbilityTaskDelegates()) + { + OnEvent.Broadcast(Payload); + } + if (OnlyTriggerOnce) + { + EndTask(); + } +} + +void UAFEffectTask_AttributeChange::SetExternalTarget(AActor* Actor) +{ + if (Actor) + { + if (IAFAbilityInterface* interface = Cast(Actor)) + { + UseExternalTarget = true; + OptionalExternalTarget = interface->GetEffectsComponent(); + } + + } +} + +UAFEffectsComponent* UAFEffectTask_AttributeChange::GetTargetASC() +{ + if (UseExternalTarget) + { + return OptionalExternalTarget; + } + + return EffectsComponent; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_EffectAppliedToSelf.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_EffectAppliedToSelf.cpp new file mode 100644 index 0000000..79bf78f --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_EffectAppliedToSelf.cpp @@ -0,0 +1,80 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAbilityInterface.h" +#include "AFEffectsComponent.h" +#include "AFEffectTask_EffectAppliedToSelf.h" + + + + +UAFEffectTask_EffectAppliedToSelf::UAFEffectTask_EffectAppliedToSelf(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + +UAFEffectTask_EffectAppliedToSelf* UAFEffectTask_EffectAppliedToSelf::ListenEffectAppliedToSelf(UGAEffectExtension* OwningExtension, FName TaskName, AActor* OptionalExternalTarget, bool OnlyTriggerOnce) +{ + auto MyObj = NewEffectTask(OwningExtension, TaskName); + MyObj->SetExternalTarget(OptionalExternalTarget); + MyObj->OnlyTriggerOnce = OnlyTriggerOnce; + + return MyObj; +} + +void UAFEffectTask_EffectAppliedToSelf::Activate() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + MyHandle = ASC->OnAppliedToSelf.AddUObject(this, &UAFEffectTask_EffectAppliedToSelf::GameplayEventCallback);//AddExecuteEvent(Tag, Delegate); + } + + Super::Activate(); +} + +void UAFEffectTask_EffectAppliedToSelf::GameplayEventCallback(FGAEffectContext Context + , FAFPropertytHandle Property + , FAFEffectSpec Spec) +{ + //if (ShouldBroadcastAbilityTaskDelegates()) + { + OnEvent.Broadcast(Context, Property, Spec); + } + if (OnlyTriggerOnce) + { + EndTask(); + } +} +void UAFEffectTask_EffectAppliedToSelf::OnTaskEnded() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + ASC->OnAppliedToSelf.Remove(MyHandle); + } +} +void UAFEffectTask_EffectAppliedToSelf::SetExternalTarget(AActor* Actor) +{ + if (Actor) + { + + if (IAFAbilityInterface* interface = Cast(Actor)) + { + UseExternalTarget = true; + OptionalExternalTarget = interface->GetEffectsComponent(); + } + + } +} + +UAFEffectsComponent* UAFEffectTask_EffectAppliedToSelf::GetTargetASC() +{ + if (UseExternalTarget) + { + return OptionalExternalTarget; + } + + return EffectsComponent; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_EffectAppliedToTarget.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_EffectAppliedToTarget.cpp new file mode 100644 index 0000000..b81e9f6 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_EffectAppliedToTarget.cpp @@ -0,0 +1,85 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAbilityInterface.h" +#include "AFEffectsComponent.h" +#include "AFEffectTask_EffectAppliedToTarget.h" + + + + +UAFEffectTask_EffectAppliedToTarget::UAFEffectTask_EffectAppliedToTarget(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + +UAFEffectTask_EffectAppliedToTarget* UAFEffectTask_EffectAppliedToTarget::ListenEffectAppliedToTarget(UGAEffectExtension* OwningExtension, FName TaskName, AActor* OptionalExternalTarget, bool OnlyTriggerOnce) +{ + auto MyObj = NewEffectTask(OwningExtension, TaskName); + MyObj->SetExternalTarget(OptionalExternalTarget); + MyObj->OnlyTriggerOnce = OnlyTriggerOnce; + + return MyObj; +} + +void UAFEffectTask_EffectAppliedToTarget::Activate() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + //(this, &UAFEffectTask_EffectAppliedToTarget::GameplayEventCallback + //FAFEventDelegate Delegate = FAFEventDelegate::CreateUObject(this, &UAFEffectTask_EffectAppliedToTarget::GameplayEventCallback); + //MyHandle = Delegate.GetHandle(); + MyHandle = ASC->OnAppliedToTarget.AddUObject(this, &UAFEffectTask_EffectAppliedToTarget::GameplayEventCallback);//AddExecuteEvent(Tag, Delegate); + } + + Super::Activate(); +} + +void UAFEffectTask_EffectAppliedToTarget::GameplayEventCallback(FGAEffectContext Context + , FAFPropertytHandle Property + , FAFEffectSpec Spec) +{ + //if (ShouldBroadcastAbilityTaskDelegates()) + { + OnEvent.Broadcast(Context, Property, Spec); + } + if (OnlyTriggerOnce) + { + EndTask(); + } +} + +void UAFEffectTask_EffectAppliedToTarget::OnTaskEnded() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + ASC->OnAppliedToTarget.Remove(MyHandle); + } +} + +void UAFEffectTask_EffectAppliedToTarget::SetExternalTarget(AActor* Actor) +{ + if (Actor) + { + + if (IAFAbilityInterface* interface = Cast(Actor)) + { + UseExternalTarget = true; + OptionalExternalTarget = interface->GetEffectsComponent(); + } + + } +} + +UAFEffectsComponent* UAFEffectTask_EffectAppliedToTarget::GetTargetASC() +{ + if (UseExternalTarget) + { + return OptionalExternalTarget; + } + + return EffectsComponent; +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_EffectEvent.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_EffectEvent.cpp new file mode 100644 index 0000000..c59cda4 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_EffectEvent.cpp @@ -0,0 +1,84 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "../../AFAbilityInterface.h" +#include "AFEffectsComponent.h" +#include "AFEffectTask_EffectEvent.h" + + + + +UAFEffectTask_EffectEvent::UAFEffectTask_EffectEvent(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + +UAFEffectTask_EffectEvent* UAFEffectTask_EffectEvent::ListenEffectEvent(UGAEffectExtension* OwningExtension, FName TaskName, FGameplayTag Tag, AActor* OptionalExternalTarget, bool OnlyTriggerOnce) +{ + auto MyObj = NewEffectTask(OwningExtension, TaskName); + MyObj->Tag = Tag; + MyObj->SetExternalTarget(OptionalExternalTarget); + MyObj->OnlyTriggerOnce = OnlyTriggerOnce; + + return MyObj; +} + +void UAFEffectTask_EffectEvent::Activate() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + //(this, &UAFEffectTask_EffectEvent::GameplayEventCallback + FAFEventDelegate Delegate = FAFEventDelegate::CreateUObject(this, &UAFEffectTask_EffectEvent::GameplayEventCallback); + MyHandle = Delegate.GetHandle(); + ASC->AddEvent(Tag, Delegate); + } + + Super::Activate(); +} + +void UAFEffectTask_EffectEvent::GameplayEventCallback(FAFEventData Payload) +{ + //if (ShouldBroadcastAbilityTaskDelegates()) + { + OnEvent.Broadcast(Payload); + } + if (OnlyTriggerOnce) + { + EndTask(); + } +} + +void UAFEffectTask_EffectEvent::OnTaskEnded() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + ASC->RemoveEvent(Tag, MyHandle); + } +} + +void UAFEffectTask_EffectEvent::SetExternalTarget(AActor* Actor) +{ + if (Actor) + { + + if (IAFAbilityInterface* interface = Cast(Actor)) + { + UseExternalTarget = true; + OptionalExternalTarget = interface->GetEffectsComponent(); + } + + } +} + +UAFEffectsComponent* UAFEffectTask_EffectEvent::GetTargetASC() +{ + if (UseExternalTarget) + { + return OptionalExternalTarget; + } + + return EffectsComponent; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_ExecutedEffectEvent.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_ExecutedEffectEvent.cpp new file mode 100644 index 0000000..cdeaaa0 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/EffectTasks/AFEffectTask_ExecutedEffectEvent.cpp @@ -0,0 +1,84 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "AFAbilityInterface.h" +#include "AFEffectsComponent.h" +#include "AFEffectTask_ExecutedEffectEvent.h" + + + + +UAFEffectTask_ExecutedEffectEvent::UAFEffectTask_ExecutedEffectEvent(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + +UAFEffectTask_ExecutedEffectEvent* UAFEffectTask_ExecutedEffectEvent::ListenExecutedEffectEvent(UGAEffectExtension* OwningExtension, FName TaskName, FGameplayTag Tag, AActor* OptionalExternalTarget, bool OnlyTriggerOnce) +{ + auto MyObj = NewEffectTask(OwningExtension, TaskName); + MyObj->Tag = Tag; + MyObj->SetExternalTarget(OptionalExternalTarget); + MyObj->OnlyTriggerOnce = OnlyTriggerOnce; + + return MyObj; +} + +void UAFEffectTask_ExecutedEffectEvent::Activate() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + //(this, &UAFEffectTask_ExecutedEffectEvent::GameplayEventCallback + FAFEventDelegate Delegate = FAFEventDelegate::CreateUObject(this, &UAFEffectTask_ExecutedEffectEvent::GameplayEventCallback); + MyHandle = Delegate.GetHandle(); + ASC->AddExecuteEvent(Tag, Delegate); + } + + Super::Activate(); +} + +void UAFEffectTask_ExecutedEffectEvent::GameplayEventCallback(FAFEventData Payload) +{ + //if (ShouldBroadcastAbilityTaskDelegates()) + { + OnEvent.Broadcast(Payload); + } + if (OnlyTriggerOnce) + { + EndTask(); + } +} + +void UAFEffectTask_ExecutedEffectEvent::OnTaskEnded() +{ + UAFEffectsComponent* ASC = GetTargetASC(); + if (ASC) + { + ASC->RemoveExecuteEvent(Tag, MyHandle); + } +} + +void UAFEffectTask_ExecutedEffectEvent::SetExternalTarget(AActor* Actor) +{ + if (Actor) + { + + if (IAFAbilityInterface* interface = Cast(Actor)) + { + UseExternalTarget = true; + OptionalExternalTarget = interface->GetEffectsComponent(); + } + + } +} + +UAFEffectsComponent* UAFEffectTask_ExecutedEffectEvent::GetTargetASC() +{ + if (UseExternalTarget) + { + return OptionalExternalTarget; + } + + return EffectsComponent; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GABlueprintLibrary.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GABlueprintLibrary.cpp new file mode 100644 index 0000000..be06b10 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GABlueprintLibrary.cpp @@ -0,0 +1,384 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "AFAbilityComponent.h" + + +#include "GABlueprintLibrary.h" + +#include "AFAbilityInterface.h" +#include "GAGameEffect.h" +#include "AFEffectCustomApplication.h" + +#include "GAEffectExtension.h" +#include "Engine/Engine.h" +#include "AFSimpleInterface.h" +#include "AFAttributeInterface.h" +#include "AFEffectsComponent.h" + +UGABlueprintLibrary::UGABlueprintLibrary(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + + +TArray UGABlueprintLibrary::ApplyGameEffectToObject( + UPARAM(Ref) FAFPropertytHandle& InEffect + , class UObject* Target + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier) +{ + TArray Targets; + Targets.Add(Target); + return ApplyEffectToObject(InEffect, Targets, Instigator, Causer, Modifier); +} + +TArray UGABlueprintLibrary::ApplyGameEffectToActor( + UPARAM(Ref) FAFPropertytHandle& InEffect + , class AActor* Target + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier) +{ + TArray Targets; + Targets.Add(Target); + return ApplyEffectToActor(InEffect, Targets, Instigator, Causer, Modifier); +} + +TArray UGABlueprintLibrary::ApplyGameEffectToLocation( + UPARAM(Ref) FAFPropertytHandle& InEffect + , const FHitResult& Target + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier) +{ + TArray Targets; + Targets.Add(Target); + return ApplyEffectFromHit(InEffect, Targets, Instigator, Causer, Modifier); +} + + +TArray UGABlueprintLibrary::ApplyGameEffectToObjects( + UPARAM(Ref) FAFPropertytHandle& InEffect + , TArray Targets + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier) +{ + return ApplyEffectToObject(InEffect, Targets, Instigator, Causer, Modifier); +} +TArray UGABlueprintLibrary::ApplyGameEffectToActors( + UPARAM(Ref) FAFPropertytHandle& InEffect + , TArray Targets + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier) +{ + return ApplyEffectToActor(InEffect, Targets, Instigator, Causer, Modifier); +} + +TArray UGABlueprintLibrary::ApplyGameEffectToTargets( + UPARAM(Ref) FAFPropertytHandle& InEffect + , const TArray& Targets + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier) +{ + return ApplyEffectFromHit(InEffect, Targets, Instigator, Causer, Modifier); +} + + +FString NetModeToString(ENetMode NetMode) +{ + switch (NetMode) + { + case ENetMode::NM_Client: + return FString("Client"); + case ENetMode::NM_DedicatedServer: + return FString("Server"); + case ENetMode::NM_ListenServer: + return FString("ListenServer"); + case ENetMode::NM_Standalone: + return FString("Standalone"); + } + + return FString("Invalid"); +} + +TArray UGABlueprintLibrary::ApplyEffect( + FAFPropertytHandle& InEffect + , TArray Targets + , class APawn* Instigator + , UObject* Causer + , const TArray& HitsIn + , const FAFFunctionModifier& Modifier) +{ + bool bCheckHits = Targets.Num() == HitsIn.Num(); + TArray Handles; + for (int32 Idx = 0; Idx < Targets.Num(); Idx++) + { + UObject* Target = Targets[Idx]; + FHitResult HitIn; + if (bCheckHits) + { + HitIn = HitsIn[Idx]; + } + + + ENetMode NetMode = GEngine->GetNetMode(Instigator->GetWorld()); + + UE_LOG(GameAttributesEffects, Error, TEXT("UGABlueprintLibrary::ApplyEffect START, NetMode %s"), *NetModeToString(NetMode)); + UE_LOG(GameAttributesEffects, Error, TEXT("-----")); + IAFAbilityInterface* Ability = Cast(Causer); + if (!Ability) + { + UE_LOG(GameAttributesEffects, Error, TEXT("UGABlueprintLibrary::ApplyEffect Effects must be applied trough Ability")); + return Handles; + } + + IAFAbilityInterface* TargetInterface = Cast(Target); + + + if (!InEffect.GetClass().GetDefaultObject()->Application.GetDefaultObject()->CanApply(TargetInterface, InEffect.GetClass())) + { + return Handles; + } + bool bReusedParams = false; + bool bPeriodicEffect = false; + + FAFEffectSpecHandle EffectSpecHandle; + FAFEffectParams Params(InEffect); + InEffect.InitializeIfNotInitialized(Instigator, Causer); + Params.Context = InEffect.GetPtr()->GetContextCopy(Target, HitIn); + + UAFEffectsComponent* Target2 = Params.Context.GetTargetEffectsComponent(); + + UGAGameEffectSpec* Spec = InEffect.GetSpecData(); + + if (!Target2->HaveEffectRquiredTags(Spec->ApplicationRequiredTags)) + { + return Handles; + } + if (Target2->DenyEffectApplication(Spec->DenyTags)) + { + return Handles; + } + + if ((InEffect.GetDuration() > 0 || InEffect.GetPeriod() > 0)) + { + bPeriodicEffect = true; + } + + if (!InEffect.IsInitialized()) + { + UE_LOG(GameAttributesEffects, Error, TEXT("Invalid Effect Spec")); + return Handles; + } + + + + UE_LOG(GameAttributesEffects, Log, TEXT("MakeOutgoingSpecObj: Created new Context: %s"), *Params.Context.ToString()); + + FGAEffect effect; + effect.World = Instigator->GetWorld(); + if (Ability) + { + effect.PredictionHandle = Ability->GetPredictionHandle(); + } + IAFAbilityInterface* InstigatorInterface = Cast(Instigator); + + + /*if (Params.EffectSpec.GetPtr()) + { + if (Params.EffectSpec.GetPtr()->GetContext().GetPtr()->Target.IsValid()) + { + UE_LOG(GameAttributesEffects, Log, TEXT(" Pre Spec Target: %s"), *Params.EffectSpec.GetPtr()->GetContext().GetPtr()->Target->GetName()); + } + }*/ + + Params.EffectSpec = InEffect.GetPtr()->GetSpecCopy(); + AddTagsToEffect(&Params.EffectSpec); + + Params.bRecreated = bReusedParams; + Params.bPeriodicEffect = bPeriodicEffect; + + FGAEffectHandle NewHandle = InstigatorInterface->ApplyEffectToTarget(effect, Params, Modifier); + Handles.Add(NewHandle); + UE_LOG(GameAttributesEffects, Error, TEXT("-----")); + UE_LOG(GameAttributesEffects, Error, TEXT("UGABlueprintLibrary::ApplyEffect END")); + + } + return Handles; +} + +TArray UGABlueprintLibrary::ApplyEffectFromHit( + FAFPropertytHandle& InEffect + , const TArray& Targets + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier) +{ + TArray ActorTargets; + for (const FHitResult& Hit : Targets) + { + ActorTargets.Add(Hit.GetActor()); + } + return ApplyEffect(InEffect, ActorTargets, Instigator, Causer, Targets, Modifier); +} + +TArray UGABlueprintLibrary::ApplyEffectToActor( + FAFPropertytHandle& InEffect + , TArray Target + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier) +{ + TArray Hits; + TArray ObjTargets; + for (AActor* A : Target) + { + ObjTargets.Add(A); + } + return ApplyEffect(InEffect, ObjTargets, Instigator, Causer, Hits, Modifier); +} + +TArray UGABlueprintLibrary::ApplyEffectToObject( + FAFPropertytHandle& InEffect + , TArray Target + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier) +{ + TArray Hits; + return ApplyEffect(InEffect, Target, Instigator, Causer, Hits, Modifier); +} + +FAFContextHandle UGABlueprintLibrary::MakeContext(class UObject* Target, class APawn* Instigator, + AActor* InAvatar, UObject* Causer, const FHitResult& HitIn) +{ + IAFAbilityInterface* targetAttr = Cast(Target); + IAFAbilityInterface* instiAttr = Cast(Instigator); + if (!targetAttr && !instiAttr) + { + UE_LOG(GameAttributesEffects, Error, TEXT("Target and Instigator does not implement IAFAbilityInterface interface")); + return FAFContextHandle(); + } + UAFAbilityComponent* targetComp = nullptr; + UAFAbilityComponent* instiComp = nullptr; + if (targetAttr) + { + targetComp = targetAttr->GetAbilityComp(); + } + if (instiAttr) + { + instiComp = instiAttr->GetAbilityComp(); + } + + FVector location = targetComp ? targetComp->GetOwner()->GetActorLocation() : FVector(HitIn.ImpactPoint.X, HitIn.ImpactPoint.Y, HitIn.ImpactPoint.Z); + FGAEffectContext* Context = new FGAEffectContext( + targetAttr ? targetAttr->GetAttributes() : nullptr + , instiAttr ? instiAttr->GetAttributes() : nullptr + , location + , Target + , Causer + , Instigator + , targetComp + , instiComp + , InAvatar); + + Context->HitResult = HitIn; + + FAFContextHandle Handle = FAFContextHandle::Generate(Context); + + return Handle; +} + +void UGABlueprintLibrary::AddTagsToEffect(FAFEffectSpec* EffectIn) +{ + if (EffectIn) + { + EffectIn->AddOwnedTags(EffectIn->GetSpec()->OwnedTags); + EffectIn->AddApplyTags(EffectIn->GetSpec()->ApplyTags); + } +} + +FGAEffectContext& UGABlueprintLibrary::GetContext(const FAFContextHandle& InHandle) +{ + return InHandle.GetRef(); +} + +UAFAbilityComponent* UGABlueprintLibrary::GetTargetComponent(const FGAEffectHandle& InHandle) +{ + return nullptr;// InHandle.GetContextRef().InstigatorComp.Get(); +} + +UAFAbilityComponent* UGABlueprintLibrary::GetInstigatorComponent(const FGAEffectHandle& InHandle) +{ + return nullptr;// InHandle.GetContextRef().TargetComp.Get(); +} + +void UGABlueprintLibrary::BroadcastEffectEvent(UObject* Target, FGameplayTag EventTag) +{ + IAFAbilityInterface* targetAttr = Cast(Target); + if (!targetAttr) + return; + + UAFAbilityComponent* TargetComp = targetAttr->GetAbilityComp(); + if (!TargetComp) + return; + + //FAFEventData EventData; + //TargetComp->NativeTriggerTagEvent(EventTag, EventData); +} +void UGABlueprintLibrary::CreateEffectSpec(UPARAM(Ref) FAFEffectSpecHandle& InOutSpec + , const FAFPropertytHandle& InEffect + , class UObject* Target + , class APawn* Instigator + , UObject* Causer) +{ + IAFAbilityInterface* TargetInterface = Cast(Target); + + FHitResult HitIn(ForceInit); + FAFContextHandle Context; + FAFEffectSpecHandle EffectSpecHandle; + Context = MakeContext(Target, Instigator, nullptr, Causer, HitIn); + + UE_LOG(GameAttributesEffects, Log, TEXT("MakeOutgoingSpecObj: Created new Context: %s"), *Context.GetRef().ToString()); + + FAFEffectSpec* EffectSpec = new FAFEffectSpec(Context, InEffect.GetClass()); + AddTagsToEffect(EffectSpec); + EffectSpecHandle = FAFEffectSpecHandle::Generate(EffectSpec); + + InOutSpec = EffectSpecHandle; +} +void UGABlueprintLibrary::ApplyEffectFromSpec(UPARAM(Ref) FAFPropertytHandle& InEffect, UPARAM(Ref) FAFEffectSpecHandle& InSpec) +{ + +} +void UGABlueprintLibrary::ModifyAttributeSimple( + UPARAM(Ref) FAFEffectSpecHandle& InSpec + , UObject* Target) +{ + if (!InSpec.IsValid()) + { + return; + } + + IAFAttributeInterface* Attr = Cast(Target); + IAFSimpleInterface* Simpl = Cast(Target); + + if (!Attr || !Simpl) + return; + + FGAEffectHandle Handle = FGAEffectHandle::GenerateHandle(); + + FGAEffect Effect = FGAEffect(InSpec.GetPtr(), Handle); + + FGAEffectMod Mod = InSpec.GetPtr()->GetModifier(); + + //Generate HAndle. + //Add to simple container. + //Modify Attribute +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GACustomCalculation.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GACustomCalculation.cpp new file mode 100644 index 0000000..2fa6e5d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GACustomCalculation.cpp @@ -0,0 +1,11 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFramework.h" +#include "../GAGlobalTypes.h" +#include "GACustomCalculation.h" + +UGACustomCalculation::UGACustomCalculation(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectBlueprint.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectBlueprint.cpp new file mode 100644 index 0000000..1edd0b9 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectBlueprint.cpp @@ -0,0 +1,33 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFramework.h" +#include "GAEffectBlueprint.h" + +////////////////////////////////////////////////////////////////////////// +// UGameplayAbilityBlueprint + +UGAEffectBlueprint::UGAEffectBlueprint(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +#if WITH_EDITOR + +/** Returns the most base gameplay ability blueprint for a given blueprint (if it is inherited from another ability blueprint, returning null if only native / non-ability BP classes are it's parent) */ +UGAEffectBlueprint* UGAEffectBlueprint::FindRootGameplayAbilityBlueprint(UGAEffectBlueprint* DerivedBlueprint) +{ + UGAEffectBlueprint* ParentBP = NULL; + + // Determine if there is a gameplay ability blueprint in the ancestry of this class + for (UClass* ParentClass = DerivedBlueprint->ParentClass; ParentClass != UObject::StaticClass(); ParentClass = ParentClass->GetSuperClass()) + { + if (UGAEffectBlueprint* TestBP = Cast(ParentClass->ClassGeneratedBy)) + { + ParentBP = TestBP; + } + } + + return ParentBP; +} + +#endif diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectCueGlobals.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectCueGlobals.cpp new file mode 100644 index 0000000..3f57b12 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectCueGlobals.cpp @@ -0,0 +1,51 @@ +#pragma once +#include "../AbilityFramework.h" +#include "../AFAbilityComponent.h" +#include "GAEffectCueGlobals.h" + +void FGACueContainer::AddCue(const FGAEffectHandle& HandleIn, const FGAEffectCueParams& CueParamsIn) +{ + //if (!CueIn) + //{ + // return; + //} + //UGAEffectCue* Cue = NewObject(OwningComponent.Get(), CueIn); + //Cues.Add(HandleIn, Cue); + //Cue->SetParameters(OwningComponent->GetOwner(), CueParamsIn); + //Cue->BeginCue(); +} +void FGACueContainer::AddCue(const FGAEffectHandle& HandleIn) +{ + //Cues.Add(HandleIn, CueIn); +} +class UGAEffectCue* FGACueContainer::GetCue(const FGAEffectHandle& HandleIn) +{ + //UGAEffectCue* Cue = nullptr; + //Cue = Cues.FindRef(HandleIn); + return nullptr; +} +void FGACueContainer::ExecuteCue(const FGAEffectHandle& HandleIn) +{ + //UGAEffectCue* Cue = GetCue(HandleIn); + //if (Cue) + //{ + // Cue->ExecuteCue(); + //} +} +void FGACueContainer::RemoveCue(const FGAEffectHandle& HandleIn) +{ + //UGAEffectCue* Cue; + //if (Cues.Num() > 0) + //{ + // Cues.RemoveAndCopyValue(HandleIn, Cue); + // if (Cue) + // { + // Cue->EndCue(); + // Cue->MarkPendingKill(); + // } + //} +} +void FGACueContainer::CueExpired(const FGAEffectHandle& HandleIn) +{ + +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectCueSequence.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectCueSequence.cpp new file mode 100644 index 0000000..1fc2476 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectCueSequence.cpp @@ -0,0 +1,130 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "../AbilityFramework.h" +#include "AFCueActor.h" +#include "MovieScene.h" +#include "MovieSceneCommonHelpers.h" +#include "Modules/ModuleManager.h" +#include "Engine/BlueprintGeneratedClass.h" +#include "Engine/Blueprint.h" +#include "GameFramework/Actor.h" +#include "Classes/Engine/SCS_Node.h" +#include "Classes/Engine/SimpleConstructionScript.h" +#include "Engine/Blueprint.h" +#include "UObject/Package.h" +#include "ActorSequenceObjectReference.h" +#include "GAEffectCueSequence.h" + + +#if WITH_EDITOR +UGAEffectCueSequence::FOnInitialize UGAEffectCueSequence::OnInitializeSequenceEvent; +#endif + +UGAEffectCueSequence::UGAEffectCueSequence(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) + , MovieScene(nullptr) +#if WITH_EDITOR + , bHasBeenInitialized(false) +#endif +{ + bParentContextsAreSignificant = true; + + MovieScene = ObjectInitializer.CreateDefaultSubobject(this, "MovieScene"); + MovieScene->SetFlags(RF_Transactional); +} + +void UGAEffectCueSequence::PostInitProperties() +{ +#if WITH_EDITOR && WITH_EDITORONLY_DATA + AAFCueActor* OwnerCue = Cast(GetOuter()); + if (!bHasBeenInitialized && !HasAnyFlags(RF_ClassDefaultObject) && OwnerCue && !OwnerCue->HasAnyFlags(RF_ClassDefaultObject)) + { + FGuid BindingID = MovieScene->AddPossessable(OwnerCue ? OwnerCue->GetActorLabel() : TEXT("Owner"), OwnerCue ? OwnerCue->GetClass() : AAFCueActor::StaticClass()); + //ObjectReferences.CreateBinding(BindingID, FActorSequenceObjectReference::CreateForContextActor()); + + OnInitializeSequenceEvent.Broadcast(this); + bHasBeenInitialized = true; + } +#endif + + Super::PostInitProperties(); +} +#if WITH_EDITOR +UGAEffectCueSequence* UGAEffectCueSequence::GetNullAnimation() +{ + static UGAEffectCueSequence* NullAnimation = nullptr; + + if (!NullAnimation) + { + NullAnimation = NewObject(GetTransientPackage(), NAME_None); + NullAnimation->AddToRoot(); + NullAnimation->MovieScene = NewObject(NullAnimation, FName("No Animation")); + NullAnimation->MovieScene->AddToRoot(); + } + + return NullAnimation; +} +#endif //WITH_EDITOR +FFrameNumber UGAEffectCueSequence::GetStartTime() const +{ + return MovieScene->GetPlaybackRange().GetLowerBoundValue(); +} + + +FFrameNumber UGAEffectCueSequence::GetEndTime() const +{ + return MovieScene->GetPlaybackRange().GetUpperBoundValue(); +} + + +/* UMovieSceneAnimation overrides +*****************************************************************************/ + + +void UGAEffectCueSequence::BindPossessableObject(const FGuid& ObjectId, UObject& PossessedObject, UObject* Context) +{ + AActor* ActorContext = CastChecked(Context); + + if (AActor* Actor = Cast(&PossessedObject)) + { + //ObjectReferences.CreateBinding(ObjectId, FActorSequenceObjectReference::CreateForActor(Actor, ActorContext)); + } +} + + +bool UGAEffectCueSequence::CanPossessObject(UObject& Object, UObject* InPlaybackContext) const +{ + AActor* ActorContext = CastChecked(InPlaybackContext); + + if (AActor* Actor = Cast(&Object)) + { + return Actor == InPlaybackContext || Actor->GetLevel() == ActorContext->GetLevel(); + } + return true; +} + +void UGAEffectCueSequence::LocateBoundObjects(const FGuid& ObjectId, UObject* Context, TArray>& OutObjects) const +{ + if (Context) + { + //ObjectReferences.ResolveBinding(ObjectId, CastChecked(Context), OutObjects); + } +} + + +UMovieScene* UGAEffectCueSequence::GetMovieScene() const +{ + return MovieScene; +} + + +UObject* UGAEffectCueSequence::GetParentObject(UObject* Object) const +{ + + return GetOuter(); +} + +void UGAEffectCueSequence::UnbindPossessableObjects(const FGuid& ObjectId) +{ + //ObjectReferences.RemoveBinding(ObjectId); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectExecution.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectExecution.cpp new file mode 100644 index 0000000..a28d5f9 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectExecution.cpp @@ -0,0 +1,27 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "GAGlobalTypes.h" +#include "Attributes/GAAttributeBase.h" +#include "AFAbilityComponent.h" +#include "Effects/GAGameEffect.h" +#include "AFAbilityInterface.h" +#include "GAEffectExecution.h" + +UGAEffectExecution::UGAEffectExecution(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + +} +void UGAEffectExecution::PreModifyAttribute(const FGAEffectHandle& HandleIn, FGAEffectMod& ModIn, const FGAEffectContext& Context) +{ + UE_LOG(GameAttributesEffects, Log, TEXT("Sample execution class implementation")); +} +void UGAEffectExecution::ExecuteEffect(const FGAEffectHandle& HandleIn, FGAEffectMod& ModIn, + const FAFEffectParams& Params, + const FAFFunctionModifier& Modifier) +{ + PreModifyAttribute(HandleIn, ModIn, Params.GetContext()); + const FGAEffectContext& Context = Params.GetContext(); + const_cast(Params).GetContext().TargetInterface->ModifyAttribute(ModIn, HandleIn, Params.GetProperty(), Context); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectExtension.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectExtension.cpp new file mode 100644 index 0000000..3e82610 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectExtension.cpp @@ -0,0 +1,104 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "AFEffectsComponent.h" +#include "Effects/EffectTasks/AFEffectTask.h" +#include "GAEffectExtension.h" + +UGAEffectExtension::UGAEffectExtension(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ +} +void UGAEffectExtension::SetParameters(const FGAEffectContext& ContextIn) +{ + Context = ContextIn; +} +void UGAEffectExtension::BeginEffect() +{ +} + +void UGAEffectExtension::NativeOnEffectApplied() +{ + OnEffectApplied(); +} +void UGAEffectExtension::NativeOnEffectExecuted() +{ + OnEffectExecuted(); +} +void UGAEffectExtension::NativeOnEffectExpired() +{ + OnEffectExpired(); + CleanupTasks(); +} +void UGAEffectExtension::NativeOnEffectRemoved() +{ + OnEffectRemoved(); + CleanupTasks(); +} + +void UGAEffectExtension::NativeOnEffectAppliedCDO() +{ + OnEffectAppliedCDO(); +} +void UGAEffectExtension::NativeOnEffectExecutedCDO() +{ + OnEffectExecutedCOD(); +} +void UGAEffectExtension::NativeOnEffectExpiredCDO() +{ + OnEffectExpiredCDO(); +} +void UGAEffectExtension::NativeOnEffectRemovedCDO() +{ + OnEffectRemovedCDO(); +} + +UWorld* UGAEffectExtension::GetWorld() const +{ + if (Context.Target.IsValid()) + return Context.Target->GetWorld(); + + return nullptr; +} + +void UGAEffectExtension::OnLatentTaskAdded(FName InstanceName, class UAFTaskBase* TaskIn) +{ + ActiveTasks.Add(TaskIn); + if (!InstanceName.IsNone()) + { + Tasks.Add(InstanceName, TaskIn); + } +}; +void UGAEffectExtension::AddReplicatedTask(class UAFTaskBase* TaskIn) +{ + //AbilityComponent->ReplicatedTasks.Add(TaskIn); +} +void UGAEffectExtension::OnLatentTaskRemoved(class UAFTaskBase* TaskIn) +{ +}; + +void UGAEffectExtension::OnLatentTaskActivated(class UAFTaskBase* TaskIn) +{ +}; +void UGAEffectExtension::OnLatentTaskDeactivated(class UAFTaskBase* TaskIn) +{ +}; + +class UAFTaskBase* UGAEffectExtension::GetCachedLatentAction(FName TaskName) +{ + return Tasks.FindRef(TaskName); +} + +void UGAEffectExtension::CleanupTasks() +{ + for (UAFTaskBase* Task : ActiveTasks) + { + Task->EndTask(); + } + + ActiveTasks.Reset(); + ActiveTasks.Shrink(); + + Tasks.Reset(); + Tasks.Shrink(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectField.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectField.cpp new file mode 100644 index 0000000..30e0213 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectField.cpp @@ -0,0 +1,48 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFramework.h" + +#include "../Abilities/GAAbilityBase.h" + +#include "GAEffectField.h" + +AGAEffectField::AGAEffectField(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + bReplicates = true; + SetReplicates(true); +} + +void AGAEffectField::InitializeField() +{ + //if (bIsFieldPersistent && AbilityInstigator) + //{ + + //} + //else if (!bIsFieldPersistent && AbilityInstigator) + //{ + // AbilityInstigator->OnAbilityCastEnd.AddUObject(this, &AGAEffectField::DestroyField); + //} + + //1. Automaticallt gather all collision componenets from blueprinted version. + // don't want to hardcode any kind of collision inside base class + // let designer decide what exactly he wants to do with it. + // but on other hand encapsulate this functionality so + // designer won't have to deal with binding/assiging events inside blueprint. + //2. Bind Events from them. +} + +void AGAEffectField::DestroyField() +{ + +} + +void AGAEffectField::OnAbilityExecuted_Implementation() +{ + +} + +void AGAEffectField::OnOtherFieldOverlap_Implementation() +{ + +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectGlobalTypes.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectGlobalTypes.cpp new file mode 100644 index 0000000..a099560 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAEffectGlobalTypes.cpp @@ -0,0 +1,143 @@ +#pragma once +#include "../AbilityFramework.h" +#include "../AFAbilityComponent.h" +#include "../Attributes/GAAttributeBase.h" +#include "GAEffectExecution.h" +#include "AFAbilityInterface.h" +#include "GAGameEffect.h" +#include "GACustomCalculation.h" + + + +float FGADirectModifier::GetValue() { return Value; } +float FGADirectModifier::GetValue() const { return Value; } +float FGAAttributeBasedModifier::GetValue(const FGAEffectContext& Context) +{ + FAFAttributeBase* attr = nullptr; + float Result = 0; + switch (Source) + { + case EGAAttributeSource::Instigator: + { + IAFAbilityInterface* AttrInt = Cast(Context.Instigator.Get()); + UGAAttributesBase* Attributes = AttrInt->GetAttributes(); + attr = Attributes->GetAttribute(Attribute); + //attr = Context.InstigatorComp->GetAttribute(Attribute); + break; + } + case EGAAttributeSource::Target: + { + IAFAbilityInterface* AttrInt = Cast(Context.Target.Get()); + UGAAttributesBase* Attributes = AttrInt->GetAttributes();// nullptr; + attr = Attributes->GetAttribute(Attribute);//Context.TargetComp->GetAttribute(Attribute); + break; + } + case EGAAttributeSource::Causer: + { + IAFAbilityInterface* AttrInt = Cast(Context.Causer.Get()); + UGAAttributesBase* Attributes = AttrInt->GetAttributes();// nullptr; + attr = Attributes->GetAttribute(Attribute);//Context.TargetComp->GetAttribute(Attribute); + break; + } + default: + return 0; + } + Result = (Coefficient * (PreMultiply + attr->GetFinalValue()) + PostMultiply) * PostCoefficient; + if (!bUseSecondaryAttribute) + return Result; + + return 0; +} +float FGAAttributeBasedModifier::GetValue(const FGAEffectContext& Context) const +{ + FAFAttributeBase* attr = nullptr; + float Result = 0; + + switch (Source) + { + case EGAAttributeSource::Instigator: + { + IAFAbilityInterface* AttrInt = Cast(Context.Instigator.Get()); + UGAAttributesBase* Attributes = AttrInt->GetAttributes(); + attr = Attributes->GetAttribute(Attribute); + //attr = Context.InstigatorComp->GetAttribute(Attribute); + break; + } + case EGAAttributeSource::Target: + { + IAFAbilityInterface* AttrInt = Cast(Context.Target.Get()); + UGAAttributesBase* Attributes = AttrInt->GetAttributes(); + attr = Attributes->GetAttribute(Attribute); + break; + } + case EGAAttributeSource::Causer: + { + IAFAbilityInterface* AttrInt = Cast(Context.Causer.Get()); + UGAAttributesBase* Attributes = AttrInt->GetAttributes();// nullptr; + attr = Attributes->GetAttribute(Attribute); + break; + } + default: + return 0; + } + Result = (Coefficient * (PreMultiply + attr->GetFinalValue()) + PostMultiply) * PostCoefficient; + if (!bUseSecondaryAttribute) + return Result; + + return 0; +} + +float FGACurveBasedModifier::GetValue(const FGAEffectContext& ContextIn) +{ + FAFAttributeBase* attr = nullptr; + float Result = 0; + switch (Source) + { + case EGAAttributeSource::Instigator: + attr = ContextIn.InstigatorComp->GetAttribute(Attribute); + break; + case EGAAttributeSource::Target: + attr = ContextIn.TargetComp->GetAttribute(Attribute); + break; + default: + return 0; + } + FString ContextString(TEXT("Evaluating modifier value.")); + Result = CurveTable.Eval(attr->GetFinalValue(), ContextString); + return Result; +} +float FGACurveBasedModifier::GetValue(const FGAEffectContext& ContextIn) const +{ + FAFAttributeBase* attr = nullptr; + float Result = 0; + switch (Source) + { + case EGAAttributeSource::Instigator: + attr = ContextIn.InstigatorComp->GetAttribute(Attribute); + break; + case EGAAttributeSource::Target: + attr = ContextIn.TargetComp->GetAttribute(Attribute); + break; + default: + return 0; + } + FString ContextString(TEXT("Evaluating modifier value.")); + Result = CurveTable.Eval(attr->GetFinalValue(), ContextString); + return Result; +} +float FGACustomCalculationModifier::GetValue(const FGAEffectContext& ContextIn) +{ + if (CustomCalculation) + { + return CustomCalculation->NativeCalculateMagnitude(ContextIn); + } + return 0; +} +float FGACustomCalculationModifier::GetValue(const FGAEffectContext& ContextIn) const +{ + if (CustomCalculation) + { + return CustomCalculation->NativeCalculateMagnitude(ContextIn); + } + return 0; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAGameEffect.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAGameEffect.cpp new file mode 100644 index 0000000..9c31b1f --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Effects/GAGameEffect.cpp @@ -0,0 +1,879 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "GameplayTagContainer.h" +#include "AFEffectsComponent.h" +#include "Attributes/GAAttributesBase.h" +#include "AFAbilityInterface.h" + +#include "GAEffectExecution.h" +#include "GAEffectExtension.h" +#include "GAGlobalTypes.h" + +#include "AFEffectApplicationRequirement.h" +#include "AFEffectCustomApplication.h" +#include "GAGameEffect.h" +#include "GABlueprintLibrary.h" + +DEFINE_STAT(STAT_GatherModifiers); + + +void FAFEffectSpec::OnApplied() const +{ + if (Extension.IsValid()) + { + Extension->NativeOnEffectApplied(); + } +} +void FAFEffectSpec::OnExpired() const +{ + if (Extension.IsValid()) + { + Extension->NativeOnEffectExpired(); + } +} +void FAFEffectSpec::OnRemoved() const +{ + if (Extension.IsValid()) + { + Extension->NativeOnEffectRemoved(); + } +} +void FAFEffectSpec::OnExecuted() const +{ + if (Extension.IsValid()) + { + Extension->NativeOnEffectExecuted(); + } +} +FAFEffectSpec::FAFEffectSpec(const FAFContextHandle& InContext, TSubclassOf InSpecClass) + : SpecClass(InSpecClass) +{ + Context = InContext; + Extension = nullptr; + SpecClass = InSpecClass; + OwnedTags.AppendTags(InSpecClass.GetDefaultObject()->OwnedTags); +} +void FAFEffectSpec::Instance() +{ + if (SpecClass.GetDefaultObject()->Extension) + { + Extension = NewObject(Context.GetPtr()->Target.Get(), SpecClass.GetDefaultObject()->Extension); + Extension->OwningComponent = Context.GetPtr()->TargetInterface->GetEffectsComponent(); + Extension->SourceComponent = Context.GetPtr()->InstigatorInterface->GetEffectsComponent(); + } +} +float FAFEffectSpec::GetFloatFromAttributeMagnitude( + const FGAMagnitude& AttributeIn + , const FGAEffectContext& InContext) const +{ + switch (AttributeIn.CalculationType) + { + case EGAMagnitudeCalculation::Direct: + { + return AttributeIn.DirectModifier.GetValue(); + } + case EGAMagnitudeCalculation::AttributeBased: + { + return AttributeIn.AttributeBased.GetValue(InContext); + } + case EGAMagnitudeCalculation::CurveBased: + { + return AttributeIn.CurveBased.GetValue(InContext); + } + case EGAMagnitudeCalculation::CustomCalculation: + { + return AttributeIn.Custom.GetValue(InContext); + } + default: + break; + } + + return 0; +} + +void FAFEffectSpec::OverrideAttributeModifier(float InValue) +{ + EffectMod.Value = InValue; +} +void FAFEffectSpec::CalculateAttributeModifier(const FGAEffectHandle& InHandle) +{ + FGAEffectContext& InContext = Context.GetRef(); + EffectMod = FAFStatics::GetAttributeModifier(SpecClass.GetDefaultObject()->AtributeModifier + , SpecClass.GetDefaultObject() + , InContext + , InHandle); +} + +float FAFEffectSpec::GetDuration(const FGAEffectContext& InContext) +{ + return GetFloatFromAttributeMagnitude(GetSpec()->Duration, InContext); +} +float FAFEffectSpec::GetPeriod(const FGAEffectContext& InContext) +{ + return GetFloatFromAttributeMagnitude(GetSpec()->Period, InContext); +} + +float FAFEffectSpec::GetDuration(const FGAEffectContext& InContext) const +{ + return GetFloatFromAttributeMagnitude(GetSpec()->Duration, InContext); +} +float FAFEffectSpec::GetPeriod(const FGAEffectContext& InContext) const +{ + return GetFloatFromAttributeMagnitude(GetSpec()->Period, InContext); +} + +FGAEffectProperty::FGAEffectProperty() + : ApplicationRequirement(nullptr) + , Application(nullptr) + , Execution(nullptr) + , Spec(nullptr) + , Duration(0) + , Period(0) + , bInstant(true) +{ + ApplicationRequirement = nullptr; + Application = nullptr; + Execution = nullptr; + Spec = nullptr; + Duration= 0; + Period = 0; +}; +FGAEffectProperty::FGAEffectProperty(TSubclassOf InClass) + : ApplicationRequirement(nullptr) + , Application(nullptr) + , Execution(nullptr) + , Spec(nullptr) + , Duration(0) + , Period(0) + , bInstant(true) +{ +}; +void FGAEffectProperty::PostScriptConstruct() +{ + ApplicationRequirement = nullptr; + Application = nullptr; + Execution = nullptr; + Spec = nullptr; + Duration = 0; + Period = 0; +} +void FGAEffectProperty::Initialize(TSubclassOf EffectClass) +{ + if (EffectClass) + { + Spec = EffectClass->GetDefaultObject(); + ApplicationRequirement = GetSpecData()->ApplicationRequirement.GetDefaultObject(); + Application = GetSpecData()->Application.GetDefaultObject(); + Execution = GetSpecData()->ExecutionType.GetDefaultObject(); + } +} +void FGAEffectProperty::InitializeIfNotInitialized( + class APawn* Instigator + , UObject* Causer + , TSubclassOf EffectClass + ) +{ + if (!IsInitialized()) + { + SpecClass = EffectClass; + + FGAEffectContext* Context = new FGAEffectContext(Instigator, Causer); + + EffectContext = FAFContextHandle::Generate(Context); + Initialize(EffectClass); + } + if (Spec.IsValid()) + { + Duration = GetSpecData()->Duration.GetFloatValue(EffectContext.GetRef()); + Period = GetSpecData()->Period.GetFloatValue(EffectContext.GetRef()); + + if ((Duration > 0) || (Period > 0)) + { + bInstant = false; + } + } +} +bool FGAEffectProperty::CanApply( + const struct FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& InParams + , const FGAEffectHandle& InHandle) +{ + return ApplicationRequirement->CanApply(EffectIn, InParams, InHandle, InContainer); +} +bool FGAEffectProperty::ApplyEffect( + const FGAEffectHandle& InHandle + , const struct FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& InParams + , const FAFFunctionModifier& Modifier) +{ + return Application->ApplyEffect(InHandle, EffectIn, InContainer, InParams, Modifier); +} +void FGAEffectProperty::ApplyExecute(const FGAEffectHandle& InHandle + , const FAFEffectParams& InParams + , const FAFFunctionModifier& Modifier) +{ + Application->ApplyExecute(InHandle, InParams, Modifier); +} + +void FGAEffectProperty::ExecuteEffect( + const FGAEffectHandle& HandleIn + , FGAEffectMod& ModIn + , const FAFEffectParams& InParams + , const FAFFunctionModifier& Modifier) +{ + Execution->ExecuteEffect(HandleIn, ModIn, InParams, Modifier); +} + +void FGAEffect::PreReplicatedRemove(const struct FGAEffectContainer& InArraySerializer) +{ + //const_cast(InArraySerializer).RemoveFromReplication(Handle, PredictionHandle); +} +void FGAEffect::PostReplicatedAdd(const struct FGAEffectContainer& InArraySerializer) +{ + World = InArraySerializer.OwningComponent->GetWorld(); + AppliedTime = World->TimeSeconds; + LastTickTime = World->TimeSeconds; + + + Handle = FGAEffectHandle::GenerateHandle(); + + //const_cast(InArraySerializer).ApplyFromReplication(Handle, PredictionHandle); +} +void FGAEffect::PostReplicatedChange(const struct FGAEffectContainer& InArraySerializer) +{ + +} +FGAEffect::FGAEffect(TSharedPtr InSpec, const FGAEffectHandle& InHandle) +{ + Handle = InHandle; +} +float FGAMagnitude::GetFloatValue(const FGAEffectContext& Context) +{ + switch (CalculationType) + { + case EGAMagnitudeCalculation::Direct: + { + return DirectModifier.GetValue(); + } + case EGAMagnitudeCalculation::AttributeBased: + { + return AttributeBased.GetValue(Context); + } + case EGAMagnitudeCalculation::CurveBased: + { + return CurveBased.GetValue(Context); + } + case EGAMagnitudeCalculation::CustomCalculation: + { + return Custom.GetValue(Context); + } + default: + return 0; + } + + return 0; +} + +float FAFStatics::GetFloatFromAttributeMagnitude(const FGAMagnitude& AttributeIn + , const FGAEffectContext& InContext + , const FGAEffectHandle& InHandle) +{ + switch (AttributeIn.CalculationType) + { + case EGAMagnitudeCalculation::Direct: + { + return AttributeIn.DirectModifier.GetValue(); + } + case EGAMagnitudeCalculation::AttributeBased: + { + return AttributeIn.AttributeBased.GetValue(InContext); + } + case EGAMagnitudeCalculation::CurveBased: + { + return AttributeIn.CurveBased.GetValue(InContext); + } + case EGAMagnitudeCalculation::CustomCalculation: + { + return AttributeIn.Custom.GetValue(InContext); + } + default: + break; + } + + return 0; +} +FGAEffectMod FAFStatics::GetAttributeModifier(FGAAttributeModifier& ModInfoIn + , class UGAGameEffectSpec* InSpec + , const FGAEffectContext& InContext + , const FGAEffectHandle& InHandle) +{ + FGAEffectMod ModOut; + if (InSpec) + { + switch (ModInfoIn.Magnitude.CalculationType) + { + case EGAMagnitudeCalculation::Direct: + { + return FGAEffectMod(ModInfoIn.Attribute, + ModInfoIn.Magnitude.DirectModifier.GetValue(), ModInfoIn.AttributeMod, InHandle, InSpec->AttributeTags); + } + case EGAMagnitudeCalculation::AttributeBased: + { + return FGAEffectMod(ModInfoIn.Attribute, + ModInfoIn.Magnitude.AttributeBased.GetValue(InContext), ModInfoIn.AttributeMod, InHandle, InSpec->AttributeTags); + + } + case EGAMagnitudeCalculation::CurveBased: + { + return FGAEffectMod(ModInfoIn.Attribute, + ModInfoIn.Magnitude.CurveBased.GetValue(InContext), ModInfoIn.AttributeMod, InHandle, InSpec->AttributeTags); + + } + case EGAMagnitudeCalculation::CustomCalculation: + { + return FGAEffectMod(ModInfoIn.Attribute, + ModInfoIn.Magnitude.Custom.GetValue(InContext), ModInfoIn.AttributeMod, InHandle, InSpec->AttributeTags); + + } + default: + break; + } + } + return ModOut; +} + +FGAEffect::~FGAEffect() +{ +} + + +float FGAEffect::GetDurationTime() const +{ + return Duration;// GetFloatFromAttributeMagnitude(GetEffect()->Duration); +} +float FGAEffect::GetPeriodTime() const +{ + return Period;// GetFloatFromAttributeMagnitude(GetEffect()->Period); +} + +float FGAEffect::GetCurrentDuration() const +{ + if (World) + { + float CurrentTime = World->TimeSeconds; + return CurrentTime - AppliedTime; + } + + return 0; +} +FTimerManager& FAFEffectParams::GetTargetTimerManager() +{ + return Context.TargetComp->GetWorld()->GetTimerManager(); +} +UAFEffectsComponent* FAFEffectParams::GetTargetEffectsComponent() +{ + return Context.GetTargetEffectsComponent(); +} +UAFEffectsComponent* FAFEffectParams::GetTargetEffectsComponent() const +{ + return Context.GetTargetEffectsComponent(); +} +void FGameCueContainer::AddCue(FGAEffectHandle EffectHandle, FGAEffectCueParams CueParams) +{ + /*if (!EffectCue) + { + return; + } + AActor* Instigator = EffectHandle.GetContext().Instigator.Get(); + UGAEffectCue* NewCue = NewObject(Instigator, EffectCue); + if (NewCue && Instigator) + { + NewCue->SetParameters(Instigator, CueParams); + NewCue->Context = EffectHandle.GetContext(); + NewCue->BeginCue(); + }*/ +} + +FGAEffectHandle FGAEffectContainer::ApplyEffect( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier) +{ + FGAEffectHandle Handle; + FGAEffectProperty& InProperty = Params.GetProperty(); + + bool bHasDuration = InProperty.GetDuration() > 0; + bool bHasPeriod = InProperty.GetPeriod() > 0; + + //InProperty.DataTest->ID++; + + ENetRole role = OwningComponent->GetOwnerRole(); + ENetMode mode = OwningComponent->GetOwner()->GetNetMode(); + + Handle = FGAEffectHandle::GenerateHandle(); + + if (InProperty.CanApply(EffectIn, this, Params, Handle)) + { + if(!Params.bPeriodicEffect) //instatnt effect. + { + const_cast(EffectIn).SetHandle(Handle); + if (InProperty.ApplyEffect(Handle, + EffectIn, this, Params)) + { + InProperty.ApplyExecute(Handle, Params, Modifier); + + // UE_LOG(GameAttributes, Log, TEXT("FGAEffectContainer::EffectApplied %s"), *HandleIn.GetEffectSpec()->GetName() ); + } + } + else + { + const_cast(EffectIn).SetHandle(Handle); + if (InProperty.ApplyEffect(Handle, + EffectIn, this, Params)) + { + const FAFEffectSpec& Spec = Params.GetSpec(); + const FGAEffectContext& Context = Params.GetContext(); + + const_cast(EffectIn).AppliedTime = OwningComponent->GetWorld()->TimeSeconds; + const_cast(EffectIn).LastTickTime = OwningComponent->GetWorld()->TimeSeconds; + const_cast(EffectIn).Duration = Spec.GetDuration(Context); + const_cast(EffectIn).Period = Spec.GetPeriod(Context); + MarkItemDirty(const_cast(EffectIn)); + int32 newItem = ActiveEffectInfos.Add(EffectIn); + MarkArrayDirty(); + AddEffect(Handle, const_cast(EffectIn).PredictionHandle, &ActiveEffectInfos[newItem], InProperty, Params); + + //InProperty.ApplyExecute(Handle, Params, Modifier); + //generate it only on client, and apply prediction key from client. + //if server replicates with valid key, then nothing happens. + //if not we try to rewind effect application. + //we probabaly don't need to unwind attribute changes, since next replication from + //server will overridem them anyway. + + bool bIsServer = GEngine->GetNetMode(OwningComponent->GetWorld()) == ENetMode::NM_DedicatedServer; + } + } + + } + //right place ? + Params.GetSpec().OnApplied(); + + FAFEventData EventData; + const FGameplayTagContainer& AppliedEvents = InProperty.GetSpecData()->AppliedEventTags; + for(const FGameplayTag& Event : AppliedEvents) + OwningComponent->TriggerAppliedEvent(Event, EventData); + + const FGAEffectContext& InContext = Params.GetContext(); + TArray& Effects = InProperty.GetSpecData()->IfHaveTagEffect.Effects; + for (FAFConditionalEffect& Effect : Effects) + { + if (Effect.RequiredTag.IsValid() + && InContext.GetTargetEffectsComponent()->HasTag(Effect.RequiredTag)) + { + //Hack. We need a way store handles for conditional effects. + FAFPropertytHandle PropertyNew(Effect.Effect); + FGAEffectHandle OtherHandle; + /*OtherHandle = UGABlueprintLibrary::ApplyEffect(PropertyNew + , OtherHandle + , InContext.Target.Get() + , InContext.Instigator.Get() + , InContext.Causer.Get() + , InContext.HitResult);*/ + } + } + + + return Handle; + +} + +TSet FGAEffectContainer::GetHandlesByClass(const FGAEffectProperty& InProperty +, const FGAEffectContext& InContext) +{ + TSet Handles; + UGAGameEffectSpec* Spec = InProperty.GetSpecData(); + EGAEffectAggregation Aggregation = Spec->EffectAggregation; + UClass* EffectClass = Spec->GetClass(); + + switch (Aggregation) + { + case EGAEffectAggregation::AggregateByInstigator: + { + UAFAbilityComponent* Instigator = InContext.InstigatorComp.Get(); + TMap>* EffectByClassMap = InstigatorEffectByClass.Find(Instigator); + //TSet* EffectByClass; + if (EffectByClassMap) + { + return EffectByClassMap->FindRef(EffectClass); + } + + break; + } + case EGAEffectAggregation::AggregateByTarget: + { + UAFAbilityComponent* Target = InContext.TargetComp.Get(); + TSet* TargetEffect = TargetEffectByClass.Find(EffectClass); + if (TargetEffect) + { + return *TargetEffect; + } + break; + } + default: + break; + } + return Handles; +} + +void FGAEffectContainer::AddEffect( + const FGAEffectHandle& InHandle + , const FAFPredictionHandle& InPredHandle + , FGAEffect* InEffect + , const FGAEffectProperty& InProperty + , const FAFEffectParams& Params + , bool bInfinite) +{ + HandleByPrediction.Add(InPredHandle, InHandle); + PredictionByHandle.Add(InHandle, InPredHandle); + PredictedEffectInfos.Add(InPredHandle, InEffect); + UGAGameEffectSpec* Spec = InProperty.GetSpecData(); + UClass* SpecClass = Spec->GetClass(); + const FGAEffectContext& Context = Params.GetContext(); + + TSet& Effects = EffectByAttribute.FindOrAdd(Spec->AtributeModifier.Attribute); + Effects.Add(InHandle); + + FObjectKey EffectKey(SpecClass); + TArray& LocalEffectClass = EffectByClass.FindOrAdd(EffectKey); + LocalEffectClass.Add(InHandle); + + switch (Spec->EffectAggregation) + { + case EGAEffectAggregation::AggregateByInstigator: + { + TMap>& InstEffectClass = InstigatorEffectByClass.FindOrAdd(Context.Instigator.Get()); + TSet& EffectClass2 = InstEffectClass.FindOrAdd(SpecClass); + EffectClass2.Add(InHandle); + break; + } + case EGAEffectAggregation::AggregateByTarget: + { + TSet& EffectClass = TargetEffectByClass.FindOrAdd(SpecClass); + EffectClass.Add(InHandle); + break; + } + } + + ActiveEffects.Add(InHandle, InEffect); + FGAEffectContainer* sss = this; + int dbg = 0; +} + +void FGAEffectContainer::RemoveEffectByHandle(const FGAEffectHandle& InHandle, const FGAEffectContext& InContext, const FAFPropertytHandle& InProperty) +{ + RemoveEffectInternal(InProperty, InContext, InHandle); +} + +TArray FGAEffectContainer::RemoveEffect(const FAFPropertytHandle& HandleIn, const FGAEffectContext& InContext, int32 Num) +{ + UGAGameEffectSpec* Spec = HandleIn.GetSpecData(); + EGAEffectAggregation Aggregation = Spec->EffectAggregation; + FObjectKey key(HandleIn.GetClass()); + TArray* handles = EffectByClass.Find(key);//GetHandlesByClass(HandleIn, InContext); + FGAEffectContainer* sss = this; + if (!handles) + return TArray(); + TArray copy = *handles; + + for (int32 idx = 0; idx < Num; idx++) + { + if (handles->IsValidIndex(0)) + { + FGAEffectHandle OutHandle = (*handles)[idx]; + RemoveEffectInternal(HandleIn, InContext, OutHandle); + } + } + + + + return copy; +} + +bool FGAEffectContainer::IsEffectActive(const FGAEffectHandle& HandleIn) +{ + if (ActiveEffects.Contains(HandleIn)) + { + return true; + } + return false; +} +bool FGAEffectContainer::IsEffectActive(const FGAEffectHandle& HandleIn) const +{ + if (ActiveEffects.Contains(HandleIn)) + { + return true; + } + return false; +} +bool FGAEffectContainer::ContainsEffectOfClass(const FAFPropertytHandle& InProperty) +{ + FObjectKey key(InProperty.GetClass()); + if (EffectByClass.Contains(key)) + { + return true; + } + return false; +} + +void FGAEffectContainer::ApplyFromReplication(const FGAEffectHandle& InHandle, const FAFPredictionHandle& InPredHandle, FGAEffect* InEffect) +{ + //AddEffect(InHandle, InPredHandle, InEffect); +} +void FGAEffectContainer::RemoveFromReplication(const FGAEffectHandle& InHandle, const FAFPredictionHandle& InPredHandle) +{ + //FGAEffect* Effect = ActiveEffects[InHandle]; + //APawn* Instigator = Effect->GetContext().Instigator.Get(); + //UObject* Target = Effect->GetContext().Target.Get(); + + //HandleByPrediction.Remove(InPredHandle); + //PredictionByHandle.Remove(InHandle); + //PredictedEffectInfos.Remove(InPredHandle); + + //FGAAttribute Attribute = Effect->GetEffect()->AtributeModifier.Attribute; + + //TSet* Effects = EffectByAttribute.Find(Attribute); + //if (Effects) + //{ + // Effects->Remove(InHandle); + // if (Effects->Num() == 0) + // { + // EffectByAttribute.Remove(Attribute); + // } + //} + + //FObjectKey EffectKey(Effect->GameEffectClass); + //TArray* EffectClass = EffectByClass.Find(EffectKey); + //if (EffectClass) + //{ + // EffectClass->Remove(InHandle); + // if (EffectClass->Num() == 0) + // { + // EffectByClass.Remove(EffectKey); + // } + //} + + //switch (Effect->GetEffect()->EffectAggregation) + //{ + //case EGAEffectAggregation::AggregateByInstigator: + //{ + // TMap>* InstEffectClass = InstigatorEffectByClass.Find(Instigator); + // if (InstEffectClass) + // { + // TSet* EffectClass2 = InstEffectClass->Find(Effect->GameEffectClass); + // if (EffectClass2) + // { + // EffectClass2->Remove(InHandle); + // if (EffectClass2->Num() == 0) + // { + // InstEffectClass->Remove(Effect->GameEffectClass); + // } + // } + // if (InstEffectClass->Num() == 0) + // { + // InstigatorEffectByClass.Remove(Instigator); + // } + // } + // + // break; + //} + //case EGAEffectAggregation::AggregateByTarget: + //{ + // TSet* EffectClass2 = TargetEffectByClass.Find(Effect->GameEffectClass); + // if (EffectClass2) + // { + // EffectClass2->Remove(InHandle); + // if (EffectClass2->Num() == 0) + // { + // TargetEffectByClass.Remove(Effect->GameEffectClass); + // } + // } + // break; + //} + //} +} +UWorld* FGAEffectContainer::GetWorld() const +{ + if (OwningComponent) + { + return OwningComponent->GetWorld(); + } + return nullptr; +} + +UGAGameEffectSpec::UGAGameEffectSpec() +{ + ExecutionType = UGAEffectExecution::StaticClass(); + ApplicationRequirement = UAFEffectApplicationRequirement::StaticClass(); + Application = UAFEffectCustomApplication::StaticClass(); +} + +float FGAEffectContainer::GetRemainingTime(const FGAEffectHandle& InHandle) const +{ + const FGAEffect* const * Effect = ActiveEffects.Find(InHandle); + if (Effect) + { + const FGAEffect* Ptr = *Effect; + float Duration = Ptr->GetDurationTime(); + return FMath::Clamp(Duration - Ptr->GetCurrentDuration(), 0, Duration); + } + return 0; +} +float FGAEffectContainer::GetRemainingTimeNormalized(const FGAEffectHandle& InHandle) const +{ + const FGAEffect* const * Effect = ActiveEffects.Find(InHandle); + if (Effect) + { + const FGAEffect* Ptr = *Effect; + float CurrentDuration = Ptr->GetCurrentDuration(); + float MaxDuration = Ptr->GetDurationTime(); + + float CurrentTime = ((CurrentDuration / MaxDuration) - 1) * (-1); + + return CurrentTime;// FMath::Clamp(CurrentTime, 1, 0); + } + return 0; +} +float FGAEffectContainer::GetCurrentTime(const FGAEffectHandle& InHandle) const +{ + const FGAEffect* const * Effect = ActiveEffects.Find(InHandle); + if (Effect) + { + const FGAEffect* Ptr = *Effect; + return Ptr->GetCurrentDuration(); + } + return 0; +} +float FGAEffectContainer::GetCurrentTimeNormalized(const FGAEffectHandle& InHandle) const +{ + const FGAEffect* const * Effect = ActiveEffects.Find(InHandle); + if (Effect) + { + const FGAEffect* Ptr = *Effect; + float CurrentDuration = Ptr->GetCurrentDuration(); + float MaxDuration = Ptr->GetDurationTime(); + return CurrentDuration * 1 / MaxDuration; + } + return 0; +} +float FGAEffectContainer::GetEndTime(const FGAEffectHandle& InHandle) const +{ + return 0; +} + +void FGAEffectContainer::RemoveEffectInternal(const FAFPropertytHandle& InProperty, const FGAEffectContext& InContext, const FGAEffectHandle& InHandle) +{ + FGAEffect* Effect = ActiveEffects[InHandle]; + UGAGameEffectSpec* Spec = InProperty.GetSpecData(); + UClass* SpecClass = Spec->GetClass(); + + FTimerManager& DurationTimer = InContext.TargetComp->GetWorld()->GetTimerManager(); + DurationTimer.ClearTimer(Effect->DurationTimerHandle); + DurationTimer.ClearTimer(Effect->PeriodTimerHandle); + + APawn* Instigator = InContext.Instigator.Get(); + UObject* ObjectTarget = InContext.Target.Get(); + FAFPredictionHandle PredHandle = PredictionByHandle[InHandle]; + + HandleByPrediction.Remove(PredHandle); + PredictionByHandle.Remove(InHandle); + PredictedEffectInfos.Remove(PredHandle); + + FGAAttribute Attribute = Spec->AtributeModifier.Attribute; + EGAAttributeMod AttributeMod = Spec->AtributeModifier.AttributeMod;; + + TSet* Effects = EffectByAttribute.Find(Spec->AtributeModifier.Attribute); + if (Effects) + { + IAFAbilityInterface* IntTarget = InContext.TargetInterface; + IntTarget->RemoveBonus(Attribute, InHandle, AttributeMod); + Effects->Remove(InHandle); + if (Effects->Num() == 0) + { + EffectByAttribute.Remove(Spec->AtributeModifier.Attribute); + } + } + + FObjectKey EffectKey(SpecClass); + TArray* EffectClass = EffectByClass.Find(EffectKey); + if (EffectClass) + { + EffectClass->Remove(InHandle); + if (EffectClass->Num() == 0) + { + EffectByClass.Remove(EffectKey); + } + } + + switch (Spec->EffectAggregation) + { + case EGAEffectAggregation::AggregateByInstigator: + { + TMap>* InstEffectClass = InstigatorEffectByClass.Find(Instigator); + if (InstEffectClass) + { + TSet* EffectClass2 = InstEffectClass->Find(SpecClass); + if (EffectClass2) + { + EffectClass2->Remove(InHandle); + if (EffectClass2->Num() == 0) + { + InstEffectClass->Remove(SpecClass); + } + } + if (InstEffectClass->Num() == 0) + { + InstigatorEffectByClass.Remove(Instigator); + } + } + + break; + } + case EGAEffectAggregation::AggregateByTarget: + { + TSet* EffectClass2 = TargetEffectByClass.Find(SpecClass); + if (EffectClass2) + { + EffectClass2->Remove(InHandle); + if (EffectClass2->Num() == 0) + { + TargetEffectByClass.Remove(SpecClass); + } + } + break; + } + } + ActiveEffects.Remove(InHandle); +} + +bool FGAEffectContainer::IsEffectActive(TSubclassOf EffectClass) +{ + FObjectKey EffectKey(EffectClass); + if (EffectByClass.Contains(EffectKey)) + { + return true; + } + return false; +} + +void FAFEffectContainerSimple::ApplyEffect(const FGAEffectHandle& InHandle + , const FGAEffect& InEffect) +{ + Effects.Add(InHandle, InEffect); +} +void FAFEffectContainerSimple::RemoveEffect(const FGAEffectHandle& InHandle) +{ + Effects.Remove(InHandle); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAGlobalTypes.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAGlobalTypes.cpp new file mode 100644 index 0000000..71cd769 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAGlobalTypes.cpp @@ -0,0 +1,371 @@ +#pragma once +#include "AbilityFramework.h" +#include "Effects/GAGameEffect.h" +#include "GAGlobalTypes.h" +#include "GameplayTagContainer.h" +#include "AFAbilityComponent.h" +#include "Attributes/GAAttributeBase.h" +#include "Effects/GAEffectExecution.h" +#include "AFAbilityInterface.h" +#include "Effects/GACustomCalculation.h" + +void AddLogDebugInfo(FString Text, UWorld* World) +{ + bool bIsServer = GEngine->GetNetMode(World) == ENetMode::NM_DedicatedServer; + UE_LOG(AbilityFramework, Log, TEXT("%s :: %s"), bIsServer ? TEXT("Server") : TEXT("Client"), *Text); +} + +FGAEffectContext::FGAEffectContext(TWeakObjectPtr TargetAttributesIn, TWeakObjectPtr InstigatorAttributesIn, + const FVector& TargetHitLocationIn, TWeakObjectPtr TargetIn, + TWeakObjectPtr CauserIn, TWeakObjectPtr InstigatorIn, + TWeakObjectPtr TargetCompIn, + TWeakObjectPtr InstigatorCompIn, + TWeakObjectPtr InAvatar) + : TargetHitLocation(TargetHitLocationIn), + TargetAttributes(TargetAttributesIn), + InstigatorAttributes(InstigatorAttributesIn), + Target(TargetIn), + Causer(CauserIn), + Instigator(InstigatorIn), + Avatar(InAvatar), + TargetComp(TargetCompIn), + InstigatorComp(InstigatorCompIn) +{ + TargetInterface = Cast(TargetIn.Get()); + InstigatorInterface = Cast(Instigator.Get()); + IAFAbilityInterface* CauserInterface = Cast(Causer.Get()); +} + + +FGAEffectContext::FGAEffectContext(APawn* InInstigator, UObject* InCauser) +{ + Instigator = InInstigator; + Causer = InCauser; + + IAFAbilityInterface* ABI = Cast(InInstigator); + InstigatorAttributes = ABI->GetAttributes(); + InstigatorComp = ABI->GetAbilityComp(); + InstigatorInterface = ABI; +} + +void FGAEffectContext::SetTarget(UObject* NewTarget, const FHitResult& InHit) +{ + HitResult = InHit; + IAFAbilityInterface* ATI = Cast(NewTarget); + if (!ATI) + { + TargetComp.Reset(); + Target.Reset(); + TargetInterface = nullptr; + TargetAttributes.Reset(); + return; + } + + TargetComp = ATI->GetAbilityComp(); + Target = NewTarget; + TargetInterface = ATI; + TargetAttributes = ATI->GetAttributes(); +} +FGAEffectHandle::FGAEffectHandle() + : Handle(0) +{ + Handle = 0; +} +FGAEffectHandle::FGAEffectHandle(uint32 HandleIn) + : Handle(HandleIn) +{ +} +void FGAEffectHandle::PostScriptConstruct() +{ + Handle = 0; +} +FGAEffectHandle::~FGAEffectHandle() +{ +} + +/* Executes effect trough provided execution class. */ + +FGAEffectHandle FGAEffectHandle::GenerateHandle() +{ + static int32 Handle; + Handle++; + return FGAEffectHandle(Handle); +} + +bool FGAEffectHandle::IsValid() const +{ + return (Handle > 0);// && EffectPtr->Context.IsValid(); +} +void FGAEffectHandle::Reset() +{ + Handle = 0; +} + +FAFPredictionHandle FAFPredictionHandle::GenerateClientHandle(UAFAbilityComponent* InComponent) +{ + if (InComponent->GetOwner()->GetNetMode() == ENetMode::NM_Client) + { + static uint32 Counter = 1; + Counter++; + FAFPredictionHandle Handle; + Handle.Handle = Counter; + return Handle; + } + return FAFPredictionHandle(); +} + +FGAHashedGameplayTagContainer::FGAHashedGameplayTagContainer(const FGameplayTagContainer& TagsIn) + : Tags(TagsIn) +{ + GenerateFNameKey(); +} +void FGAHashedGameplayTagContainer::GenerateFNameKey() +{ + FString RetString; + for (const FGameplayTag& tag : Tags) + { + RetString += TEXT("."); + RetString += tag.ToString(); + RetString += TEXT("."); + } + Key = *RetString; +} + +void FGAEffectContext::operator=(const FGAEffectContext& Other) +{ + HitResult = Other.HitResult; + TargetHitLocation = Other.TargetHitLocation; + TargetAttributes = Other.TargetAttributes; + InstigatorAttributes = Other.InstigatorAttributes; + Target = Other.Target; + Causer = Other.Causer; + Instigator = Other.Instigator; + Avatar = Other.Avatar; + TargetComp = Other.TargetComp; + InstigatorComp = Other.InstigatorComp; + TargetInterface = Other.TargetInterface; + InstigatorInterface = Other.InstigatorInterface; +} +FGAEffectContext::FGAEffectContext(const FGAEffectContext& Other) +{ + HitResult = Other.HitResult; + TargetHitLocation = Other.TargetHitLocation; + TargetAttributes = Other.TargetAttributes; + InstigatorAttributes = Other.InstigatorAttributes; + Target = Other.Target; + Causer = Other.Causer; + Instigator = Other.Instigator; + Avatar = Other.Avatar; + TargetComp = Other.TargetComp; + InstigatorComp = Other.InstigatorComp; + TargetInterface = Other.TargetInterface; + InstigatorInterface = Other.InstigatorInterface; +} +void FGAEffectContext::Reset() +{ + Target.Reset(); + Causer.Reset(); + Instigator.Reset(); + TargetComp.Reset(); + InstigatorComp.Reset(); + TargetInterface = nullptr; + InstigatorInterface = nullptr; +} +class UGAAttributesBase* FGAEffectContext::GetTargetAttributes() +{ + if (TargetAttributes.IsValid()) + return TargetAttributes.Get(); + else + return nullptr; +} +class UGAAttributesBase* FGAEffectContext::GetInstigatorAttributes() +{ + if(InstigatorComp.IsValid()) + return InstigatorComp->DefaultAttributes; + return nullptr; +} +class UGAAttributesBase* FGAEffectContext::GetCauserAttributes() +{ + IAFAbilityInterface* AttrInt = Cast(Causer.Get()); + if (AttrInt) + { + return AttrInt->GetAttributes(); + } + return nullptr; +} + +class UGAAttributesBase* FGAEffectContext::GetTargetAttributes() const +{ + if (TargetAttributes.IsValid()) + return TargetAttributes.Get(); + else + return nullptr; +} +class UGAAttributesBase* FGAEffectContext::GetInstigatorAttributes() const +{ + if (InstigatorComp.IsValid()) + return InstigatorComp->DefaultAttributes; + return nullptr; +} +class UGAAttributesBase* FGAEffectContext::GetCauserAttributes() const +{ + IAFAbilityInterface* AttrInt = Cast(Causer.Get()); + if (AttrInt) + { + return AttrInt->GetAttributes(); + } + return nullptr; +} + +class UAFEffectsComponent* FGAEffectContext::GetTargetEffectsComponent() +{ + IAFAbilityInterface* AttrInt = Cast(Target.Get()); + if (AttrInt) + { + return AttrInt->GetEffectsComponent(); + } + return nullptr; +} + +class UAFEffectsComponent* FGAEffectContext::GetTargetEffectsComponent() const +{ + IAFAbilityInterface* AttrInt = Cast(Target.Get()); + if (AttrInt) + { + return AttrInt->GetEffectsComponent(); + } + return nullptr; +} + +FGAEffectContext::~FGAEffectContext() +{ + Target.Reset(); + Causer.Reset(); + Instigator.Reset(); + TargetComp.Reset(); + InstigatorComp.Reset(); +} + +void FGACountedTagContainer::AddTag(const FGameplayTag& TagIn) +{ + int32& count = CountedTags.FindOrAdd(TagIn); + //if (count) + //{ + // *count += 1; + // return; + //} + count++; + //CountedTags.Add(TagIn, 1); + AllTags.AddTag(TagIn); +} +void FGACountedTagContainer::AddTagContainer(const FGameplayTagContainer& TagsIn) +{ + for (auto TagIt = TagsIn.CreateConstIterator(); TagIt; ++TagIt) + { + int32* count = CountedTags.Find(*TagIt); + if (count) + { + *count += 1; + } + else + { + CountedTags.Add(*TagIt, 1); + AllTags.AddTag(*TagIt); + } + } +} +void FGACountedTagContainer::RemoveTag(const FGameplayTag& TagIn) +{ + int32* count = CountedTags.Find(TagIn); + if (count) + { + *count -= 1; + if (*count <= 0) + { + CountedTags.Remove(TagIn); + AllTags.RemoveTag(TagIn); + } + } +} +void FGACountedTagContainer::RemoveTagContainer(const FGameplayTagContainer& TagsIn) +{ + for (auto TagIt = TagsIn.CreateConstIterator(); TagIt; ++TagIt) + { + int32* count = CountedTags.Find(*TagIt); + if (count) + { + *count -= 1; + } + if (*count <= 0) + { + CountedTags.Remove(*TagIt); + AllTags.RemoveTag(*TagIt); + } + } +} +bool FGACountedTagContainer::HasTag(const FGameplayTag& TagIn) +{ + return AllTags.HasTag(TagIn); +} +bool FGACountedTagContainer::HasTagExact(const FGameplayTag TagIn) +{ + return AllTags.HasTagExact(TagIn); +} +bool FGACountedTagContainer::HasAny(const FGameplayTagContainer& TagsIn) +{ + return AllTags.HasAny(TagsIn); +} +bool FGACountedTagContainer::HasAnyExact(const FGameplayTagContainer& TagsIn) +{ + return AllTags.HasAnyExact(TagsIn); +} +bool FGACountedTagContainer::HasAll(const FGameplayTagContainer& TagsIn) +{ + return AllTags.HasAll(TagsIn); +} +bool FGACountedTagContainer::HasAllExact(const FGameplayTagContainer& TagsIn) +{ + return AllTags.HasAllExact(TagsIn); +} + +bool FGACountedTagContainer::HasTag(const FGameplayTag& TagIn) const +{ + return AllTags.HasTag(TagIn); +} +bool FGACountedTagContainer::HasTagExact(const FGameplayTag TagIn) const +{ + return AllTags.HasTagExact(TagIn); +} +bool FGACountedTagContainer::HasAny(const FGameplayTagContainer& TagsIn) const +{ + return AllTags.HasAny(TagsIn); +} +bool FGACountedTagContainer::HasAnyExact(const FGameplayTagContainer& TagsIn) const +{ + return AllTags.HasAnyExact(TagsIn); +} +bool FGACountedTagContainer::HasAll(const FGameplayTagContainer& TagsIn) const +{ + return AllTags.HasAll(TagsIn); +} +bool FGACountedTagContainer::HasAllExact(const FGameplayTagContainer& TagsIn) const +{ + return AllTags.HasAllExact(TagsIn); +} + +FAFCueHandle FAFCueHandle::GenerateHandle() +{ + static uint32 HandleIndex = 0; + HandleIndex++; + + FAFCueHandle NewHandle(HandleIndex); + + return NewHandle; +} + +FGAEffectCueParams::FGAEffectCueParams(const FGAEffectContext& InContext, const struct FGAEffectProperty& InProperty) + : HitResult(InContext.HitResult) + , Instigator(InContext.Instigator) + , Causer(InContext.Causer) + , CueTags(InProperty.GetSpecData()->Cues.CueTags) +{}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAHelperTemplates.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAHelperTemplates.cpp new file mode 100644 index 0000000..0451e0e --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAHelperTemplates.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "GAHelperTemplates.h" + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAPhysicalMaterial.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAPhysicalMaterial.cpp new file mode 100644 index 0000000..05718f4 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAPhysicalMaterial.cpp @@ -0,0 +1,8 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "GAPhysicalMaterial.h" + + + + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAUIData.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAUIData.cpp new file mode 100644 index 0000000..6e90d29 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/GAUIData.cpp @@ -0,0 +1,8 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFramework.h" +#include "GAUIData.h" + + + + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/AFLatentInterface.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/AFLatentInterface.cpp new file mode 100644 index 0000000..abdf620 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/AFLatentInterface.cpp @@ -0,0 +1,8 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "AFLatentInterface.h" +UAFLatentInterface::UAFLatentInterface(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/AFTaskBase.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/AFTaskBase.cpp new file mode 100644 index 0000000..7b0fce9 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/AFTaskBase.cpp @@ -0,0 +1,100 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "AFLatentInterface.h" + +#include "AFTaskBase.h" + +void FGALatentFunctionTick::ExecuteTick(float DeltaTime, ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) +{ + if (Target && !Target->IsPendingKillOrUnreachable()) + { + FScopeCycleCounterUObject ActorScope(Target); + Target->TickTask(DeltaTime, TickType, *this); + } +} + +FString FGALatentFunctionTick::DiagnosticMessage() +{ + return Target->GetFullName() + TEXT("[TickAction]"); +} + +UAFTaskBase::UAFTaskBase(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + TickFunction.TickGroup = TG_PrePhysics; + // Default to no tick function, but if we set 'never ticks' to false (so there is a tick function) it is enabled by default + TickFunction.bCanEverTick = false; + TickFunction.bStartWithTickEnabled = true; + TickFunction.bAllowTickOnDedicatedServer = true; + TickFunction.bRunOnAnyThread = true; + + TickFunction.SetTickFunctionEnable(true); + SetFlags(RF_StrongRefOnFrame); + TaskState = EState::Waiting; +} + +void UAFTaskBase::Initialize() +{ + if (GetWorld()) + { + TickFunction.Target = this; + ULevel* level = GetWorld()->GetCurrentLevel(); + if (level) + { + TickFunction.RegisterTickFunction(level); + } + } +} + +void UAFTaskBase::ReadyForActivation() +{ + if (TaskOwner) + { + if (TaskState != EState::Active) + { + TaskState = EState::Active; + Activate(); + Cast(TaskOwner)->OnLatentTaskActivated(this); + } + + } + else + { + EndTask(); + } +} + +void UAFTaskBase::EndTask() +{ + if (TickFunction.bCanEverTick && TickFunction.IsTickFunctionRegistered()) + { + TickFunction.UnRegisterTickFunction(); + TickFunction.SetTickFunctionEnable(false); + } + OnTaskEnded(); + Cast(TaskOwner)->OnLatentTaskDeactivated(this); + TaskState = EState::Finished; + //MarkPendingKill(); +} +void UAFTaskBase::BeginDestroy() +{ + Super::BeginDestroy(); +} + +bool UAFTaskBase::IsNameStableForNetworking() const +{ + return false; +} +void UAFTaskBase::SetNetAddressable() +{ + +} +UWorld* UAFTaskBase::GetWorld() const +{ + if (TaskOwner) + { + return TaskOwner->GetWorld(); + } + return nullptr; +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/AFTaskManager.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/AFTaskManager.cpp new file mode 100644 index 0000000..10382b4 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/AFTaskManager.cpp @@ -0,0 +1,25 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "AFTaskManager.h" + +UAFTaskManager* UAFTaskManager::Instance = nullptr; + +UAFTaskManager::UAFTaskManager(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ +} + +UAFTaskManager* UAFTaskManager::Get() +{ + if (Instance) + { + return Instance; + } + else + { + Instance = NewObject(); + Instance->AddToRoot(); + return Instance; + } +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/GAWaitAction.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/GAWaitAction.cpp new file mode 100644 index 0000000..be34c49 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/LatentActions/GAWaitAction.cpp @@ -0,0 +1,51 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFramework.h" +#include "GAWaitAction.h" + +UGAWaitAction::UGAWaitAction(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + TickFunction.bCanEverTick = true; + TickFunction.bStartWithTickEnabled = true; + TickFunction.bAllowTickOnDedicatedServer = true; + TickFunction.bRunOnAnyThread = true; + SetFlags(RF_StrongRefOnFrame); +} + +UGAWaitAction* UGAWaitAction::NewGAWaitAction(UObject* InTaskOwner, float Time) +{ + UGAWaitAction* MyTask = nullptr;/*NewTask(InTaskOwner, InTaskOwner); + if (MyTask) + { + MyTask->Time = Time; + }*/ + return MyTask; +} + +void UGAWaitAction::Activate() +{ + OnInitialized.Broadcast(); + if (GEngine) + { + GEngine->AddOnScreenDebugMessage(0, 1, FColor::Red, FString("ObjectName: ") + GetName()); + } + if (TaskOwner && TaskOwner->GetWorld()) + { + UWorld* World = TaskOwner->GetWorld(); + TimeStarted = World->GetTimeSeconds(); + + // Use a dummy timer handle as we don't need to store it for later but we don't need to look for something to clear + FTimerHandle TimerHandle; + World->GetTimerManager().SetTimer(TimerHandle, this, &UGAWaitAction::OnTimeFinish, Time, false); + } +} +void UGAWaitAction::TickTask(float DeltaSeconds, ELevelTick TickType, FGALatentFunctionTick& ThisTickFunction) +{ + OnTick.Broadcast(); +}; +void UGAWaitAction::OnTimeFinish() +{ + OnFinish.Broadcast(); + EndTask(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Private/Mods/GAAttributeMod.cpp b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Mods/GAAttributeMod.cpp new file mode 100644 index 0000000..8069c17 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Private/Mods/GAAttributeMod.cpp @@ -0,0 +1,11 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFramework.h" +#include "GAGlobalTypes.h" +#include "GAAttributeMod.h" + +UGAAttributeMod::UGAAttributeMod(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ + +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAbilityComponent.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAbilityComponent.h new file mode 100644 index 0000000..4c128f5 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAbilityComponent.h @@ -0,0 +1,606 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "GameplayTags.h" +#include "AFAbilityTypes.h" + +#include "Attributes/GAAttributeBase.h" +#include "Attributes/GAAttributesBase.h" +#include "Effects/GAEffectCueGlobals.h" + +#include "Effects/GAGameEffect.h" +#include "GAGlobalTypes.h" + +#include "GameplayTagAssetInterface.h" + +#include "AssetRegistryModule.h" +#include "Engine/AssetManager.h" + +#include "AFAbilityComponent.generated.h" + +DECLARE_STATS_GROUP(TEXT("AttributeComponent"), STATGROUP_AttributeComponent, STATCAT_Advanced); +DECLARE_CYCLE_STAT_EXTERN(TEXT("AttributeComponentApplyEffect"), STAT_ApplyEffect, STATGROUP_AttributeComponent, ); +DECLARE_CYCLE_STAT_EXTERN(TEXT("AttributeComponentModifyAttribute"), STAT_ModifyAttribute, STATGROUP_AttributeComponent, ); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGAOnAttributeChanged); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGAOnAttributeModifed, const FAFAttributeChangedData&, Mod); + +DECLARE_MULTICAST_DELEGATE_OneParam(FGAGenericEffectDelegate, FGAEffectHandle); + + +DECLARE_MULTICAST_DELEGATE_OneParam(FAFAttributeChangedDelegate, FAFAttributeChangedData); + +DECLARE_DELEGATE_ThreeParams(FAFOnAbilityReady, FAFAbilitySpec, FAFAbilitySpecHandle, FAFAbilitySpecHandle); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAFOnAbilityAdded, const FGameplayTag&, AbilityTag); +DECLARE_DELEGATE(FAFGenericAttributeDelegate); + + +//UAFAssetManager* GetAssetManager() +//{ +// return Cast(UAssetManager::GetIfValid()); +//}; + +USTRUCT() +struct FGAModifiedAttributeData +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY() + TArray Mods; + UPROPERTY() + int32 ForceUpdate; + + FGAModifiedAttributeData() + : ForceUpdate(0) + {} +}; + +USTRUCT(BlueprintType) +struct FGAEffectUIData +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY(BlueprintReadOnly, Category = "UI") + float RemainingTime; + + FGAEffectUIData() + : RemainingTime(0) + {}; +}; +struct FGAContextSetup +{ +public: + UGAAttributesBase* IntigatorAttributes; + UGAAttributesBase* TargetAttributes; + UAFAbilityComponent* InstigatorComp; + UAFAbilityComponent* TargetComp; + + FGAContextSetup() + {}; + FGAContextSetup(UGAAttributesBase* IntigatorAttributesIn, UGAAttributesBase* TargetAttributesIn, + UAFAbilityComponent* InstigatorCompIn, UAFAbilityComponent* TargetCompIn) + : IntigatorAttributes(IntigatorAttributesIn), + TargetAttributes(TargetAttributesIn), + InstigatorComp(InstigatorCompIn), + TargetComp(TargetCompIn) + {}; +}; +DECLARE_MULTICAST_DELEGATE_TwoParams(FGASOnActiveAbilityAdded, int32, int32); +DECLARE_DELEGATE_TwoParams(FAFMontageGenericDelegate, const FGameplayTag&, const FName&); +/* TODO:: Implement fast serialization for structs. */ +/* TODO:: REmove all those structs for customization and replace it with something sane like tmap. */ +/**/ + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGASMontageRepData +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY() + UAnimMontage* CurrentMontage; + + UPROPERTY() + FName SectionName; + + UPROPERTY() + uint8 ForceRep; +}; + +USTRUCT() +struct FAFReplicatedAttributeItem : public FFastArraySerializerItem +{ + GENERATED_BODY() +public: + UPROPERTY() + FGameplayTag AttributeTag; + UPROPERTY() + UGAAttributesBase* Attributes; + + void PreReplicatedRemove(const struct FAFReplicatedAttributeContainer& InArraySerializer); + void PostReplicatedAdd(const struct FAFReplicatedAttributeContainer& InArraySerializer); + void PostReplicatedChange(const struct FAFReplicatedAttributeContainer& InArraySerializer); +}; + +DECLARE_DELEGATE_OneParam(FAFOnAttributeReady, class UGAAttributesBase*); + +USTRUCT() +struct FAFReplicatedAttributeContainer : public FFastArraySerializer +{ + GENERATED_BODY() +public: + UPROPERTY() + TArray Attributes; + + UPROPERTY() + TMap AttributeMap; + + + TMap AttributeReplicatedEvent; + + void RegisterAttributeRepEvent(const FGameplayTag& InTag, const FAFOnAttributeReady& InDelegate) + { + if (!AttributeReplicatedEvent.Contains(InTag)) + return; + + AttributeReplicatedEvent.Add(InTag, InDelegate); + } + + void OnAttributeReplicated(const FGameplayTag& InTag, UGAAttributesBase* InAttributes) const + { + if (const FAFOnAttributeReady* Delegate = AttributeReplicatedEvent.Find(InTag)) + { + Delegate->Execute(InAttributes); + //AttributeReplicatedEvent.Remove(InTag); + } + } + + UGAAttributesBase* Add(const FGameplayTag InTag, UGAAttributesBase* InAttributes, class UAFAbilityComponent* InOuter); + bool NetDeltaSerialize(FNetDeltaSerializeInfo & DeltaParms) + { + return FFastArraySerializer::FastArrayDeltaSerialize(Attributes, DeltaParms, *this); + } +}; + +template<> +struct TStructOpsTypeTraits< FAFReplicatedAttributeContainer > : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithNetDeltaSerializer = true, + }; +}; + + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFAbilityActionSet +{ + GENERATED_BODY() +public: + UPROPERTY() + TSoftClassPtr AbilityTag; + UPROPERTY() + TArray AbilityInputs; +}; + +UCLASS(hidecategories = (Object, LOD, Lighting, Transform, Sockets, TextureStreaming), editinlinenew, meta = (BlueprintSpawnableComponent)) +class ABILITYFRAMEWORK_API UAFAbilityComponent : public UActorComponent, public IGameplayTagAssetInterface +{ + GENERATED_BODY() + /* Attributes handling */ +public: + //Only for base testing and prototyping cue application. + //will be removed when Cue Manager will be more functional. + + //FAFEffectTimerManager EffectTimerManager; + + UPROPERTY(EditAnywhere, Category = "Test") + FGameplayTag TagTest; + /* + Set attribute which will be considered for indicating whether or not actor is dead. + */ + UPROPERTY(EditAnywhere, Category = "Config") + FGAAttribute DeathAttribute; + + UPROPERTY(EditAnywhere, Category = "Input Config") + TArray AbilityInputs; + + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer DefaultTags; + + UPROPERTY() + FGACountedTagContainer AppliedTags; + + UPROPERTY() + FGACountedTagContainer ImmunityTags; + + UFUNCTION() + void OnRep_ActiveEffects(); + + UPROPERTY(ReplicatedUsing = OnRep_ActiveCues) + FGameCueContainer ActiveCues; + UFUNCTION() + void OnRep_ActiveCues(); + /* + Could make it array. But realistically. How many times do you really need more, than one + attribute set for actor ? + + Of course array of attributes would allow to compose attributes from small discreete + attribute sets. On the other hand similiar funcionality can be achieved by using + inheritance. + + And I think that using inheritance in this case will be easier. + */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Instanced, Replicated) + class UGAAttributesBase* DefaultAttributes; + + //probabaly replace FGameplayTag with FObjectKey + TMap AdditionalAttributes; + + UPROPERTY(Replicated) + FAFReplicatedAttributeContainer RepAttributes; + + UPROPERTY(BlueprintAssignable, Category = "Game Attributes") + FGAOnAttributeModifed OnAttributeModifed; + UPROPERTY(BlueprintAssignable, Category = "Game Attributes") + FGAOnAttributeModifed ServerOnTargetAttributeModifed; + UPROPERTY(BlueprintAssignable, Category = "Game Attributes") + FGAOnAttributeModifed OnTargetAttributeModifed; + + TMap AttributeChanged; + + + void BroadcastAttributeChange(const FGAAttribute& InAttribute, + const FAFAttributeChangedData& InData); + + UFUNCTION() + void OnRep_GameEffectContainer(); + + template + T* GetAttributes() + { + return CastChecked(DefaultAttributes); + } + + template + T* GetAttributeSet(FGameplayTag InOwner) + { + UGAAttributesBase* AttributeSet = AdditionalAttributes.FindRef(InOwner); + return Cast(AttributeSet); + } + UGAAttributesBase* AddAddtionalAttributes(FGameplayTag InOwner, UGAAttributesBase* InAttributes) + { + if (!InAttributes) + return nullptr; + UGAAttributesBase* retVal = RepAttributes.Add(InOwner, InAttributes, this); + RepAttributes.MarkArrayDirty(); + + return retVal; + } + UFUNCTION(BlueprintCallable, Category = "Test") + void GetAttributeStructTest(FGAAttribute Name); + + /** UActorComponent Interface - Begin */ + virtual void BeginPlay() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void DestroyComponent(bool bPromoteChildren = false) override; + virtual void InitializeComponent() override; + virtual void UninitializeComponent() override; + virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + /* UActorComponent Interface - End **/ +public: + ///////////////////////////////////////////////// + //////////// ATTRIBUTES HANDLING + + /* + Two functions, They will allow to apply any static numerical mods from player who + initiated attribute change, and from player who will be affected by change. + + Mods will be appiled by small objects, and changed against tags. + For example there might be physical armor mod, which will apply changes only + to attributes tagged as Damage.Physical and only if you are reciving change, not causing it. + */ + + inline float GetFinalAttributeValue(const FGAAttribute& Name) + { + return DefaultAttributes->GetFinalAttributeValue(Name); + } + inline float GetCurrentAttributeValue(const FGAAttribute& Name) + { + return DefaultAttributes->GetCurrentAttributeValue(Name); + } + //////////// ATTRIBUTES HANDLING + ///////////////////////////////////////////////// + /* + Attribute replication. + */ + void OnAttributeModified(const FGAEffectMod& InMod, const FGAEffectHandle& InHandle, UGAAttributesBase* InAttributeSet); + //Helper functions: +public: + /* + IGameplayTagAssetInterface Start + */ + /** + * Get any owned gameplay tags on the asset + * + * @param OutTags [OUT] Set of tags on the asset + */ + UFUNCTION(BlueprintCallable, Category = GameplayTags) + virtual void GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const override; + + /* + IGameplayTagAssetInterface End + */ + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + class UGAAttributesBase* GetAttributes() { return DefaultAttributes; }; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + float GetAttributeValue(FGAAttribute AttributeIn) const { return DefaultAttributes->GetCurrentAttributeValue(AttributeIn); }; + + void ModifyAttribute(FGAEffectMod& ModIn + , const FGAEffectHandle& HandleIn + , FGAEffectProperty& InProperty + , const FGAEffectContext& InContext);// { DefaultAttributes->ModifyAttribute(ModIn, HandleIn); }; + void NotifyInstigatorTargetAttributeChanged(const FAFAttributeChangedData& InData, + const FGAEffectContext& InContext); + + UFUNCTION(Client, Unreliable) + void ClientNotifyAttributeModifier(const FAFAttributeChangedData& InData); + void ClientNotifyAttributeModifier_Implementation(const FAFAttributeChangedData& InData); + FAFAttributeBase* GetAttribute(FGAAttribute AttributeIn) { return DefaultAttributes->GetAttribute(AttributeIn); }; + void RemoveBonus(FGAAttribute AttributeIn, const FGAEffectHandle& HandleIn, EGAAttributeMod InMod) { DefaultAttributes->RemoveBonus(AttributeIn, HandleIn, InMod); }; + float NativeGetAttributeValue(const FGAAttribute AttributeIn) const { return 0; }; + +private: + class IAFAbilityInterface* AttributeInterface; + +public: + UAFAbilityComponent(const FObjectInitializer& ObjectInitializer); + + UFUNCTION() + void OnRep_InstancedAbilities(); + UPROPERTY(Replicated) + FAFAbilityContainer AbilityContainer; + UPROPERTY() + TArray AbilitiesRefs; + + UPROPERTY() + APlayerController* PCOwner; + + /* Ability which is currently being executed. */ + UPROPERTY(BlueprintReadOnly, Category = "Game Abilities") + class UGAAbilityBase* ExecutingAbility; + + + + /*UFUNCTION(NetMulticast, Reliable) + MulticastExecuteEffect()*/ + + + + + /* + True if player is currently casting/channeling/activating(?) + any ability. + */ + bool bIsAnyAbilityActive; + + //AbilityTag, Delegate + TMap OnAbilityReadyMap; + + void AddOnAbilityReadyDelegate(const FAFAbilitySpecHandle InAbilityPtr, FAFOnAbilityReady& InDelegate) + { + if(InDelegate.IsBound()) + OnAbilityReadyMap.Add(InAbilityPtr, InDelegate); + } + + void NotifyOnAbilityReady(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle) + { + if (FAFOnAbilityReady* Ready = OnAbilityReadyMap.Find(ClientHandle)) + { + Ready->ExecuteIfBound(Spec, ServerHandle, ClientHandle); + OnAbilityReadyMap.Remove(ClientHandle); + } + } + + TMap, FAFOnAbilityReady> OnAbilityInputReadyMap; + + void AddOnAbilityInputReadyDelegate(const TSoftClassPtr& InAbilityPtr, const FAFOnAbilityReady& InDelegate) + { + if(InDelegate.IsBound()) + OnAbilityInputReadyMap.Add(InAbilityPtr, InDelegate); + } + + void NotifyOnAbilityInputReady(const TSoftClassPtr& InAbilityPtr, FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle) + { + if (FAFOnAbilityReady* Ready = OnAbilityInputReadyMap.Find(InAbilityPtr)) + { + Ready->ExecuteIfBound(Spec, ServerHandle, ClientHandle); + OnAbilityInputReadyMap.Remove(InAbilityPtr); + } + } + + TMap> OnPreAttributeModifiedMap; + void AddOnPreAttributeModifiedDelegate(const FGAAttribute& InAttribute, const FAFGenericAttributeDelegate& InDelegate) + { + TArray& delegates = OnPreAttributeModifiedMap.FindOrAdd(InAttribute); + delegates.Add(InDelegate); + } + + void NotifyOnPreAttributeModified(const FGAAttribute& InAttribute) + { + if (TArray* Ready = OnPreAttributeModifiedMap.Find(InAttribute)) + { + for(const FAFGenericAttributeDelegate& delegate : *Ready) + delegate.ExecuteIfBound(); + } + } + + void RemoveOnPreAttributeModified(const FGAAttribute& InAttribute, const FAFGenericAttributeDelegate& Delegate) + { + if (TArray* Ready = OnPreAttributeModifiedMap.Find(InAttribute)) + { + //Ready->RemoveSingle(Delegate); + if (Ready->Num() <= 0) + { + OnPreAttributeModifiedMap.Remove(InAttribute); + } + } + } + + TMap> OnPostAttributeModifiedMap; + void AddOnPostAttributeModifiedDelegate(const FGAAttribute& InAttribute, const FAFGenericAttributeDelegate& InDelegate) + { + TArray& delegates = OnPostAttributeModifiedMap.FindOrAdd(InAttribute); + delegates.Add(InDelegate); + } + + void NotifyOnPostAttributeModified(const FGAAttribute& InAttribute) + { + if (TArray* Ready = OnPostAttributeModifiedMap.Find(InAttribute)) + { + for (const FAFGenericAttributeDelegate& delegate : *Ready) + delegate.ExecuteIfBound(); + } + } + + + + FAFOnAbilityReady OnAbilityReady; + + UPROPERTY(BlueprintAssignable, Category = "AbilityFramework") + FAFOnAbilityAdded OnAbilityAdded; + + FAFMontageGenericDelegate OnAbilityNotifyBegin; + FAFMontageGenericDelegate OnAbilityNotifyTick; + FAFMontageGenericDelegate OnAbilityNotifyEnd; + +private: + + + UPROPERTY(ReplicatedUsing=OnRep_PlayMontage) + FGASMontageRepData RepMontage; + UFUNCTION() + void OnRep_PlayMontage(); + +public: + UFUNCTION(BlueprintCallable, Category = "AbilityFramework") + void PlayMontage(UAnimMontage* MontageIn, FName SectionName, float Speed = 1); + UFUNCTION(NetMulticast, Unreliable) + void MulticastPlayMontage(UAnimMontage* MontageIn, FName SectionName, float Speed = 1); +public: + inline class UGAAbilityBase* GetGASAbility(int32 IndexIn) + { + return nullptr; + } + + TMap BlockedInput; + + + + void SetBlockedInput(const FGameplayTag& InActionName, bool bBlock); + + void BindInputs(class UInputComponent* InputComponent, FString BindEnum); + + TSoftClassPtr IsAbilityBoundToAction(const TSoftClassPtr& InAbilityPtr, const TArray& InInputTag); + +public: + /* Called when ability action has been binded on server. */ + UFUNCTION(Client, Reliable) + void ClientNotifyAbilityInputReady(const TSoftClassPtr& InAbilityPtr); + void ClientNotifyAbilityInputReady_Implementation(const TSoftClassPtr& InAbilityPtr); + + + + void BindAbilityToInputIDs(const FAFAbilitySpecHandle Handle, TArray InputIDs); + UFUNCTION(Server, Reliable, WithValidation) + void ServerBindAbilityToInputIDs(const FAFAbilitySpecHandle Handle, const TArray& InputIDs); + void ServerBindAbilityToInputIDs_Implementation(const FAFAbilitySpecHandle Handle, const TArray& InputIDs); + bool ServerBindAbilityToInputIDs_Validate(const FAFAbilitySpecHandle Handle, const TArray& InputIDs); + + void NativeInputPressed(uint8 InputID); +protected: + UFUNCTION(Server, Reliable, WithValidation) + void ServerNativeInputPressed(uint8 InputID, FAFPredictionHandle InPredictionHandle); + virtual void ServerNativeInputPressed_Implementation(uint8 InputID, FAFPredictionHandle InPredictionHandle); + virtual bool ServerNativeInputPressed_Validate(uint8 InputID, FAFPredictionHandle InPredictionHandle); + + +public: + void NativeInputReleased(uint8 InputID); +protected: + UFUNCTION(Server, Reliable, WithValidation) + void ServerNativeInputReleased(uint8 InputID); + virtual void ServerNativeInputReleased_Implementation(uint8 InputID); + virtual bool ServerNativeInputReleased_Validate(uint8 InputID); +public: + /* + Finds ability using asset registry and then gives it to component. + Only valid on server. + Does not check if component can or can't have given ability. + So it must be checked before this function is called. + */ + + UFUNCTION(BlueprintCallable, meta=(DisplayName = "Add Ability"), Category = "AbilityFramework|Ability Component") + void BP_AddAbility(TSoftClassPtr InAbility, + TArray InInputTag); + + /* + Adds new ability to this AbilityComponent. + Client handle is used to trigger ability related events on client which requested this function. + Please note that to find ability by handle you must refer to it trough server generated ability handle. + Which can be received by registering delegate trough: + @AddOnAbilityReadyDelegate + */ + void NativeAddAbility(TSoftClassPtr InAbility, const FAFAbilitySpecHandle ClientHandle); + + /* + Adds ability using existing instance of object. + Should only be called on authority or in standalone. + */ + void NativeAddAbilityFromObject(UGAAbilityBase* InAbility, const FAFAbilitySpecHandle ClientHandle); + + UFUNCTION(Server, Reliable, WithValidation) + void ServerNativeAddAbility(const FSoftObjectPath& InAbility, const FAFAbilitySpecHandle& ClientHandle); + void ServerNativeAddAbility_Implementation(const FSoftObjectPath& InAbility, const FAFAbilitySpecHandle& ClientHandle); + bool ServerNativeAddAbility_Validate(const FSoftObjectPath& InAbility, const FAFAbilitySpecHandle& ClientHandle); + + void OnFinishedLoad(TSoftClassPtr InAbility, const FAFAbilitySpecHandle Handle, const FAFAbilitySpecHandle ClientHandle); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Remove Ability"), Category = "AbilityFramework|Abilities") + void BP_RemoveAbility(TSoftClassPtr TagIn); + + void NativeRemoveAbility(const FAFAbilitySpecHandle InHandle); + UFUNCTION(Server, Reliable, WithValidation) + void ServerNativeRemoveAbility(const FAFAbilitySpecHandle& InHandle); + + void ServerNativeRemoveAbility_Implementation(const FAFAbilitySpecHandle& InHandle); + + bool ServerNativeRemoveAbility_Validate(const FAFAbilitySpecHandle& InHandle); + + //TODO: Make it procted + + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Get Ability By Handle"), Category = "AbilityFramework|Abilities") + UGAAbilityBase* BP_GetAbilityByHandle(FAFAbilitySpecHandle TagIn); + + + bool ReplicateSubobjects(class UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) override; + void GetSubobjectsWithStableNamesForNetworking(TArray& Objs) override; + + void NotifyOnAbilityAdded(const FGameplayTag& InAbilityTag); +protected: + void InitializeInstancedAbilities(); + + +public: + /* + Latent Tasks Handling + */ + + UPROPERTY(Replicated) + TArray ReplicatedTasks; +}; + + + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAbilityInterface.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAbilityInterface.h new file mode 100644 index 0000000..c60eeda --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAbilityInterface.h @@ -0,0 +1,74 @@ +#pragma once +#include "GAGlobalTypes.h" +#include "Effects/GAGameEffect.h" +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypes.h" +#include "AFAbilityComponent.h" +#include "AFAbilityInterface.generated.h" + + +struct FAFAttributeBase; +struct FGAEffectHandle; +UINTERFACE(Blueprintable, meta = (CannotImplementInterfaceInBlueprint)) +class ABILITYFRAMEWORK_API UAFAbilityInterface : public UInterface +{ + GENERATED_UINTERFACE_BODY() +}; + +class IAFAbilityInterface +{ + GENERATED_IINTERFACE_BODY() +public: + virtual FVector GetSocketLocation(FName SocketNameIn){ return FVector::ZeroVector; }; + + + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + virtual class UAFAbilityComponent* GetAbilityComp() = 0; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + virtual class UAFEffectsComponent* GetEffectsComponent() = 0; + + virtual class UAFEffectsComponent* NativeGetEffectsComponent() const = 0; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + virtual float GetAttributeValue(FGAAttribute AttributeIn) const { return 0; }; + + virtual void ModifyAttribute(FGAEffectMod& ModIn, const FGAEffectHandle& HandleIn, + struct FGAEffectProperty& InProperty, const FGAEffectContext& InContext) {}; + virtual FAFAttributeBase* GetAttribute(FGAAttribute AttributeIn) { return nullptr; }; + virtual void RemoveBonus(FGAAttribute AttributeIn, const FGAEffectHandle& HandleIn, EGAAttributeMod InMod) {}; + + virtual float NativeGetAttributeValue(const FGAAttribute AttributeIn) const { return 0; }; + + virtual void RemoveTagContainer(const FGameplayTagContainer& TagsIn) {}; + //override to allow gathering tags from causer + //those tags will be merged into effect owned tags. + virtual FGameplayTagContainer GetCauserTags() { return FGameplayTagContainer(); } + + virtual FAFPredictionHandle GetPredictionHandle() { return FAFPredictionHandle(); } + + + FGAEffectHandle ApplyEffectToTarget( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + virtual class UGAAttributesBase* GetAttributes() { return GetAbilityComp()->DefaultAttributes; }; + + template + T* GetAttributesTyped() + { + return Cast(GetAttributes()); + } + template + T* GetComponentTyped() + { + return Cast(GetAbilityComp()); + } + template + T* GetAttributeTyped(FGAAttribute InAttribute) + { + return static_cast(GetAttribute(InAttribute)); + } +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAbilityTypes.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAbilityTypes.h new file mode 100644 index 0000000..3cbdfd8 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAbilityTypes.h @@ -0,0 +1,123 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "Engine/NetSerialization.h" +#include "GameplayTags.h" +#include "AFAbilityTypes.generated.h" + +class UGAAbilityBase; + +USTRUCT(BlueprintType) +struct FAFAbilitySpecHandle +{ + GENERATED_BODY() + friend struct FAFAbilitySpec; +public: + UPROPERTY() + uint32 Handle; + + static FAFAbilitySpecHandle GenerateHandle() + { + static uint32 HandleID = 0; + HandleID++; + FAFAbilitySpecHandle Handle; + Handle.Handle = HandleID; + return Handle; + } +public: + bool IsValid() const + { + return Handle != 0; + } + bool operator==(const FAFAbilitySpecHandle& ROther) const + { + return Handle == ROther.Handle; + } + friend uint32 GetTypeHash(const FAFAbilitySpecHandle& InHandle) + { + return InHandle.Handle; + } +}; + + +/* + Handle is created on calling client and then send to server. If/when server instance ability and send back it to client + it will use exactly the same handle. +*/ +USTRUCT() +struct ABILITYFRAMEWORK_API FAFAbilitySpec : public FFastArraySerializerItem +{ + GENERATED_BODY() +public: + friend struct FAFAbilitySpecHandle; + UPROPERTY() + UGAAbilityBase* Ability; + UPROPERTY() + uint8 InputID; + /* Server generated handle that is valid on both client and server. Use it to find ability */ + UPROPERTY() + FAFAbilitySpecHandle Handle; + /* Client generated handle that is only used temporarily to fire events on owning client. */ + UPROPERTY() + FAFAbilitySpecHandle ClientHandle; + + void PreReplicatedRemove(const struct FAFAbilityContainer& InArraySerializer); + void PostReplicatedAdd(const struct FAFAbilityContainer& InArraySerializer); + void PostReplicatedChange(const struct FAFAbilityContainer& InArraySerializer); + + bool operator==(const FAFAbilitySpec& ROther) const + { + return Handle == ROther.Handle; + } + bool operator==(const FAFAbilitySpecHandle& ROther) const + { + return Handle == ROther; + } + friend uint32 GetTypeHash(const FAFAbilitySpec& InSpec) + { + return InSpec.Handle.Handle; + } +}; + +USTRUCT() +struct ABILITYFRAMEWORK_API FAFAbilityContainer : public FFastArraySerializer +{ + GENERATED_BODY() +public: + TWeakObjectPtr AbilitiesComp; + UPROPERTY() + TArray ActivatableAbilities; + + TMap SpecMap; + + TMap InputToAbilitySpec; + + UGAAbilityBase* AddAbility(TSubclassOf AbilityIn, const FAFAbilitySpecHandle Handle, const FAFAbilitySpecHandle ClientHandle); + + + void RemoveAbility(const FAFAbilitySpecHandle AbilityIn); + + UGAAbilityBase* GetAbility(FAFAbilitySpecHandle InAbiltyPtr); + + void HandleInputPressed(const uint8 InputID, const FAFPredictionHandle& InPredictionHandle); + void HandleInputReleased(const uint8 InputID); + + bool AbilityExists(FAFAbilitySpecHandle InAbiltyPtr) const + { + return SpecMap.Contains(InAbiltyPtr); + } + bool NetDeltaSerialize(FNetDeltaSerializeInfo & DeltaParms) + { + return FFastArraySerializer::FastArrayDeltaSerialize(ActivatableAbilities, DeltaParms, *this); + } + void BindAbilityToInputIDs(const FAFAbilitySpecHandle Handle, TArray InputIDs); +}; + +template<> +struct TStructOpsTypeTraits< FAFAbilityContainer > : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithNetDeltaSerializer = true, + }; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAttributeComponent.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAttributeComponent.h new file mode 100644 index 0000000..1140809 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAttributeComponent.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "AFAttributeComponent.generated.h" + + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class ABILITYFRAMEWORK_API UAFAttributeComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + // Sets default values for this component's properties + UAFAttributeComponent(); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAttributeInterface.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAttributeInterface.h new file mode 100644 index 0000000..9e24c00 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFAttributeInterface.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "AFAttributeInterface.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI) +class UAFAttributeInterface : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class ABILITYFRAMEWORK_API IAFAttributeInterface +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + + virtual void ModifyAttribute(const FGAEffectMod& InAttributeMod + , const FGAEffectHandle& InHandle) = 0; + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFBlueprintFunctionLibrary.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFBlueprintFunctionLibrary.h new file mode 100644 index 0000000..700bfb5 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFBlueprintFunctionLibrary.h @@ -0,0 +1,17 @@ +#pragma once +#include "GameplayTags.h" +#include "GameplayTagContainer.h" +#include "AFBlueprintFunctionLibrary.generated.h" +/* + Some static helper functions, to interact with Attribute system. +*/ +UCLASS() +class ABILITYFRAMEWORK_API UAFBlueprintFunctionLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities") + static void TriggerAbilityPressedByTag(UObject* Target, const FGameplayTag& AbilityTag, FGameplayTag ActionTag); + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities") + static void TriggerAbilityReleasedByTag(UObject* Target, const FGameplayTag& AbilityTag, FGameplayTag ActionTag); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFCueInterface.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFCueInterface.h new file mode 100644 index 0000000..26baa08 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFCueInterface.h @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "AFCueInterface.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI) +class UAFCueInterface : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class ABILITYFRAMEWORK_API IAFCueInterface +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFCueManager.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFCueManager.h new file mode 100644 index 0000000..4d4052d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFCueManager.h @@ -0,0 +1,130 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "GameplayTags.h" +#include "GAGlobalTypes.h" +#include "Effects/AFCueActor.h" +#include "AFCueManager.generated.h" + + +USTRUCT() +struct FAFCueData +{ + GENERATED_BODY() +public: + UPROPERTY() + FGameplayTag CueTag; + UPROPERTY() + FPrimaryAssetId AssetId; + UPROPERTY(Transient) + UClass* CueClass; + + FAFCueData() + : CueClass(nullptr) + {} +}; + +UENUM() +enum EAFCueEvent +{ + Activated, + Executed, + Expire, + Removed +}; + +struct FAFCueActorKey +{ + FObjectKey InstigatorKey; + FObjectKey TargetKey; + FGameplayTag CueTag; + struct Target {}; + struct Instigator {}; + + FAFCueActorKey(Instigator, UObject* InInstigator) + : InstigatorKey(FObjectKey(InInstigator)) + , TargetKey(FObjectKey()) + , CueTag(FGameplayTag()) + {} + + FAFCueActorKey(Target, UObject* InTarget) + : InstigatorKey(FObjectKey()) + , TargetKey(FObjectKey(InTarget)) + , CueTag(FGameplayTag()) + {} + + FAFCueActorKey(const FGameplayTag& Tag) + : InstigatorKey(FObjectKey()) + , TargetKey(FObjectKey()) + , CueTag(Tag) + {} + + FAFCueActorKey(UObject* InInstigator, UObject* InTarget, const FGameplayTag& Tag) + : InstigatorKey(FObjectKey(InInstigator)) + , TargetKey(FObjectKey(InTarget)) + , CueTag(Tag) + {} + + inline bool operator==(const FAFCueActorKey& Other) const + { + return InstigatorKey == Other.InstigatorKey + && TargetKey == Other.TargetKey + && CueTag == Other.CueTag; + } + +}; + +inline uint32 GetTypeHash(const FAFCueActorKey& Key) +{ + return GetTypeHash(Key.InstigatorKey) ^ + GetTypeHash(Key.TargetKey) ^ + GetTypeHash(Key.CueTag); +} + +/** + * + */ +UCLASS(config = Game) +class ABILITYFRAMEWORK_API UAFCueManager : public UObject +{ + GENERATED_BODY() +protected: + //UPROPERTY() + static UAFCueManager* ManagerInstance; + UWorld* CurrentWorld; + + UPROPERTY() + UObjectLibrary* StaticCues; + + TArray Cues; + TMap CuesMap; + + //Cues = Instigator+Target (optional) since Actor Cue might not have target (ie. Fire storm effect). + TMap InstancedCues; +public: + void Initialize(); +#if WITH_EDITOR + //handle clearing up cache when PIE mode is ending. + void HandleOnPIEEnd(bool InVal); +#endif //WITH_EDITOR + void HandlePreLoadMap(const FString& InMapName); + void HandlePostLoadMap(UWorld* InWorld); +public: + static UAFCueManager* Get(); + void HandleCue(const FGameplayTagContainer& Tags + , const FGAEffectCueParams& CueParams + , EAFCueEvent CueEvent); + + void HandleRemoveCue(const FGameplayTagContainer& Tags, + const FGAEffectCueParams& CueParams, FAFCueHandle InHandle); +protected: + void OnFinishedLoad(int32 Idx + , FPrimaryAssetId InPrimaryAssetId + , FGAEffectCueParams CueParams + , EAFCueEvent CueEvent); + + void HandleCueEvent(UClass* InCueClass, const FGAEffectCueParams& InCueParams, EAFCueEvent CueEvent); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFEffectsComponent.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFEffectsComponent.h new file mode 100644 index 0000000..6a63c3d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFEffectsComponent.h @@ -0,0 +1,225 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "GameplayTags.h" +#include "GameplayTagAssetInterface.h" + +#include "Attributes/GAAttributeBase.h" +#include "Attributes/GAAttributesBase.h" +#include "Effects/GAEffectCueGlobals.h" +#include "Effects/GAGameEffect.h" +#include "GAGlobalTypes.h" + +#include "AFEffectsComponent.generated.h" + +DECLARE_DELEGATE(FAFEffectEvent); +DECLARE_DELEGATE_OneParam(FAFEventDelegate, FAFEventData); + +DECLARE_MULTICAST_DELEGATE_ThreeParams(FAFApplicationDelegate, FGAEffectContext, FAFPropertytHandle, FAFEffectSpec); + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class ABILITYFRAMEWORK_API UAFEffectsComponent : public UActorComponent +{ + GENERATED_BODY() +private: + friend class UGAAbilityBase; + friend class IAFAbilityInterface; + friend class UAFAbilityComponent; + friend class UAFEffectTask_EffectEvent; + +private: + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer DefaultTags; + + UPROPERTY(Replicated) + FGACountedTagContainer AppliedTags; + + UPROPERTY(Replicated) + FGACountedTagContainer ImmunityTags; + + UPROPERTY(ReplicatedUsing = OnRep_GameEffectContainer) + FGAEffectContainer GameEffectContainer; + + TMap OnEffectApplyToTarget; + TMap OnEffectApplyToSelf; + TMap> EffectEvents; + + TMap EffectToCue; + + TMap OnEffectEvent; + + TMap> AppliedEvents; + TMap> ExecutedEvents; +public: + FAFApplicationDelegate OnAppliedToTarget; + FAFApplicationDelegate OnAppliedToSelf; + FAFApplicationDelegate OnEffectExecuted; +public: + // Sets default values for this component's properties + UAFEffectsComponent(const FObjectInitializer& ObjectInitializer); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + + /** UActorComponent Interface - Begin */ + virtual void InitializeComponent() override; + /* UActorComponent Interface - End **/ + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + +protected: + + /* + * @call Order: + * Previous Function: UAFAbilityComponent::ApplyEffectToTarget + * Next Function: FGAEffectContainer::ApplyEffect + * Apply target to Me. Try to apply effect to container and launch Events in: + * TMap OnEffectEvent - event is called before application; + * TMap OnEffectApplyToSelf - event is called before application; + * + * @param EffectIn& - Effect to apply + * @param InProperty - cached effect information + * @param InContext - Context about effect application. Target, instigator, causer. + * @param Modifier - optional modifier which can be applied to effect. + * @return Handle to Effect; + */ + FGAEffectHandle ApplyEffectToSelf( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + /* + * @call Order: + * Previous Function: UGABlueprintLibrary::ApplyEffect + * Next Function: UAFAbilityComponent::ApplyEffectToSelf + * Apply effect to target provided inside Context. + * Try launch events: + * TMap OnEffectApplyToTarget - event is called before application + * + * @param EffectIn& - Effect to apply + * @param InProperty - cached effect information + * @param InContext - Context about effect application. Target, instigator, causer. + * @param Modifier - optional modifier which can be applied to effect. + * @return Handle to Effect; + */ + FGAEffectHandle ApplyEffectToTarget( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + +public: + /* Have to to copy handle around, because timer delegates do not support references. */ + void ExecuteEffect(FGAEffectHandle HandleIn + , FAFEffectParams Params + , FAFFunctionModifier Modifier); + + virtual void PostExecuteEffect(); + /* ExpireEffect is used to remove existing effect naturally when their time expires. */ +public: + void ExpireEffect(FGAEffectHandle HandleIn + , FAFEffectParams Params); + +protected: + UFUNCTION(Client, Reliable) + void ClientExpireEffect(FAFPredictionHandle PredictionHandle); + void ClientExpireEffect_Implementation(FAFPredictionHandle PredictionHandle); + + /* RemoveEffect is used to remove effect by force. */ + void RemoveEffect(const FAFPropertytHandle& InProperty + , const FGAEffectContext& InContext + , const FGAEffectHandle& InHandle); + void InternalRemoveEffect(const FAFPropertytHandle& InProperty, const FGAEffectContext& InContext); + + void AddEffectEvent(const FGameplayTag& InEventTag, const FSimpleDelegate& InEvent); + void ExecuteEffectEvent(const FGameplayTag& InEventTag); + void RemoveEffectEvent(const FGameplayTag& InEventTag); + bool IsEffectActive(const FGAEffectHandle& InHandle) const; + +public: + void AddEvent(const FGameplayTag& EventTag, FAFEventDelegate& EventDelegate); + void RemoveEvent(const FGameplayTag& EventTag, const FDelegateHandle& EventDelegate); + TArray& GetTagEvent(FGameplayTag TagIn); + void NativeTriggerTagEvent(FGameplayTag TagIn, const FAFEventData& InEventData); + + void AddAppliedEvent(const FGameplayTag& EventTag, FAFEventDelegate& EventDelegate); + void RemoveAppliedEvent(const FGameplayTag& EventTag, const FDelegateHandle& EventDelegate); + void TriggerAppliedEvent(FGameplayTag TagIn, const FAFEventData& InEventData); + + + void AddExecuteEvent(const FGameplayTag& EventTag, FAFEventDelegate& EventDelegate); + void RemoveExecuteEvent(const FGameplayTag& EventTag, const FDelegateHandle& EventDelegate); + void TriggerExecuteEvent(FGameplayTag TagIn, const FAFEventData& InEventData); + +public: + bool DenyEffectApplication(const FGameplayTagContainer& InTags); + bool HaveEffectRquiredTags(const FGameplayTagContainer& InTags); +protected: + /* + + */ + UFUNCTION(NetMulticast, Unreliable) + void MulticastApplyEffectCue(FGAEffectCueParams CueParams, FAFCueHandle InHandle); + virtual void MulticastApplyEffectCue_Implementation(FGAEffectCueParams CueParams, FAFCueHandle InHandle); + + UFUNCTION(NetMulticast, Unreliable) + void MulticastExecuteEffectCue(TSubclassOf EffectSpec, FGAEffectCueParams CueParams); + void MulticastExecuteEffectCue_Implementation(TSubclassOf EffectSpec, FGAEffectCueParams CueParams); + + UFUNCTION(NetMulticast, Unreliable) + void MulticastRemoveEffectCue(FGAEffectCueParams CueParams, FAFCueHandle InHandle); + void MulticastRemoveEffectCue_Implementation(FGAEffectCueParams CueParams, FAFCueHandle InHandle); + + UFUNCTION(NetMulticast, Unreliable) + void MulticastUpdateDurationCue(FGAEffectHandle EffectHandle, float NewDurationIn); + void MulticastUpdateDurationCue_Implementation(FGAEffectHandle EffectHandle, float NewDurationIn); + + UFUNCTION(NetMulticast, Unreliable) + void MulticastUpdatePeriodCue(FGAEffectHandle EffectHandle, float NewPeriodIn); + void MulticastUpdatePeriodCue_Implementation(FGAEffectHandle EffectHandle, float NewPeriodIn); + + UFUNCTION(NetMulticast, Unreliable) + void MulticastUpdateTimersCue(FGAEffectHandle EffectHandle, float NewDurationIn, float NewPeriodIn); + void MulticastUpdateTimersCue_Implementation(FGAEffectHandle EffectHandle, float NewDurationIn, float NewPeriodIn); + + UFUNCTION(NetMulticast, Unreliable) + void MulticastExtendDurationCue(FGAEffectHandle EffectHandle, float NewDurationIn); + void MulticastExtendDurationCue_Implementation(FGAEffectHandle EffectHandle, float NewDurationIn); +public: + FGAEffect* GetEffect(const FGAEffectHandle& InHandle); + + /* Counted Tag Container Wrapper Start */ + inline void AddTag(const FGameplayTag& TagIn) { AppliedTags.AddTag(TagIn); }; + inline void AddTagContainer(const FGameplayTagContainer& TagsIn) { AppliedTags.AddTagContainer(TagsIn); }; + inline void RemoveTag(const FGameplayTag& TagIn) { AppliedTags.RemoveTag(TagIn); }; + inline void RemoveTagContainer(const FGameplayTagContainer& TagsIn) { AppliedTags.RemoveTagContainer(TagsIn); }; + inline bool HasTag(const FGameplayTag& TagIn) const { return AppliedTags.HasTag(TagIn); } + inline bool HasTagExact(const FGameplayTag TagIn) const { return AppliedTags.HasTagExact(TagIn); }; + inline bool HasAny(const FGameplayTagContainer& TagsIn) const { return AppliedTags.HasAny(TagsIn); }; + inline bool HasAnyExact(const FGameplayTagContainer& TagsIn) const { return AppliedTags.HasAnyExact(TagsIn); }; + inline bool HasAll(const FGameplayTagContainer& TagsIn) const { return AppliedTags.HasAll(TagsIn); }; + inline bool HasAllExact(const FGameplayTagContainer& TagsIn) const { return AppliedTags.HasAllExact(TagsIn); }; + inline int32 GetTagCount(const FGameplayTag& TagIn) const { return AppliedTags.GetTagCount(TagIn); } + /* Counted Tag Container Wrapper Start */ + + + /* Game Effect Container WRAPPER */ + bool IsEffectActive(TSubclassOf EffectClass) + { + return GameEffectContainer.IsEffectActive(EffectClass); + } + + /* Game Effect Container WRAPPER */ + + /*Network Functions - BEGIN */ +protected: + UFUNCTION() + void OnRep_GameEffectContainer(); + + /*Network Functions - END */ +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFSimpleInterface.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFSimpleInterface.h new file mode 100644 index 0000000..94768fe --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AFSimpleInterface.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "AFSimpleInterface.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI) +class UAFSimpleInterface : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class ABILITYFRAMEWORK_API IAFSimpleInterface +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + + virtual void ApplyEffect(const FGAEffectHandle& InHandle + , const FGAEffect& InEffect) = 0; +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityActivationSpec.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityActivationSpec.h new file mode 100644 index 0000000..d9d6bfb --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityActivationSpec.h @@ -0,0 +1,21 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/GAGameEffect.h" +#include "AFAbilityActivationSpec.generated.h" + +/** + * + */ +UCLASS(Blueprintable, BlueprintType, Abstract) +class ABILITYFRAMEWORK_API UAFAbilityActivationSpec : public UGAGameEffectSpec +{ + GENERATED_BODY() + +public: + UAFAbilityActivationSpec(); + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityCooldownSpec.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityCooldownSpec.h new file mode 100644 index 0000000..238e495 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityCooldownSpec.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/GAGameEffect.h" +#include "AFAbilityCooldownSpec.generated.h" + +/** + * + */ +UCLASS(Blueprintable, BlueprintType, Abstract) +class ABILITYFRAMEWORK_API UAFAbilityCooldownSpec : public UGAGameEffectSpec +{ + GENERATED_BODY() +public: + UAFAbilityCooldownSpec(); + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityInfiniteDurationSpec.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityInfiniteDurationSpec.h new file mode 100644 index 0000000..89b59a2 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityInfiniteDurationSpec.h @@ -0,0 +1,21 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/GAGameEffect.h" +#include "AFAbilityInfiniteDurationSpec.generated.h" + +/** + * + */ +UCLASS(Blueprintable, BlueprintType, Abstract) +class ABILITYFRAMEWORK_API UAFAbilityInfiniteDurationSpec : public UGAGameEffectSpec +{ + GENERATED_BODY() +public: + UAFAbilityInfiniteDurationSpec(); + + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityPeriodSpec.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityPeriodSpec.h new file mode 100644 index 0000000..7c6f1eb --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityPeriodSpec.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/GAGameEffect.h" +#include "AFAbilityPeriodSpec.generated.h" + +/** + * + */ +UCLASS(Blueprintable, BlueprintType, Abstract) +class ABILITYFRAMEWORK_API UAFAbilityPeriodSpec : public UGAGameEffectSpec +{ + GENERATED_BODY() +public: + UAFAbilityPeriodSpec(); + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityPeriodicInfiniteSpec.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityPeriodicInfiniteSpec.h new file mode 100644 index 0000000..57158e4 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/AFAbilityPeriodicInfiniteSpec.h @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/GAGameEffect.h" +#include "AFAbilityPeriodicInfiniteSpec.generated.h" + +/** + * + */ +UCLASS(Blueprintable, BlueprintType, Abstract) +class ABILITYFRAMEWORK_API UAFAbilityPeriodicInfiniteSpec : public UGAGameEffectSpec +{ + GENERATED_BODY() +public: + UAFAbilityPeriodicInfiniteSpec(); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/GAAbilityBase.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/GAAbilityBase.h new file mode 100644 index 0000000..0bf50a4 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/GAAbilityBase.h @@ -0,0 +1,631 @@ +#pragma once +#include "GAGlobalTypes.h" +#include "Effects/GAGameEffect.h" +#include "GameplayTasksComponent.h" +#include "GameplayTask.h" +#include "GameplayTaskOwnerInterface.h" +#include "Attributes/GAAttributesBase.h" +#include "AFAbilityInterface.h" +#include "AFAbilityActivationSpec.h" +#include "AssetBundleData.h" +#include "SubclassOf.h" +#include "LatentActions/AFLatentInterface.h" + +#include "GAAbilityBase.generated.h" + +/* + TODO:: + 1. Add virtual functions, for default behaviours inside ability. + And figure out some clever names for them. Functions like: + ExecuteAbility() + Possibly default input functions. + The interface for it, is not yet fully determined. + It would be best if the functions and names of them, made sense.. For both AI and player + pawns. + 2. Add linked abilities. I'm not 100% sure if it really should be default functionality, + but the idea is that after first ability is executed, it will automatically set next, ability + for execution in chain, and so on, until last ability. Last ability will, simply back to first. + This can be implement as very simple linked list (though I'm not sure about nice BP workflow), + at ability level, OR it can be implemented at component level as queue. + But, from game design perspective implementation on ability level makes more sense. + + Moar TODO: (idk, if the above is still relevelant). + 1. Add simple tracing directly inside ability. Aside from targeting tasks. + + 2. Add caching for effects, so we don;'t create new ones every time, just reference handle. +*/ +/* + Base class for abilities. It will only implement few generic virtual functions, needed by all + abilities. + + Ability is what actor can do, not nessesarly, how actor will go about doing it. + For example we can have jump ability, which is nothing else, than object encapsulating, + access jump function inside Movement Component. + + This way you can give actors, certain abilities, which they can then used based on + some critera (for example defined in Blackboard and Behaviour tree), and if it is + possible for actor to perform ability, he will do it (though, one must be careful to + give abilities, which can be performed by actors, an ordinary actor, can't jump). + + More complicated abilities, can be actions in their own right. Like spells. + + Abilities are using state machine, combined with effects, to perform actions, like + casting, channeling etc. + It needs to be better explained on how each state makes use of effect parameters (Duration, Period). +*/ +DECLARE_MULTICAST_DELEGATE(FGASSimpleAbilityDynamicDelegate); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGASGenericAbilityDelegate); + +USTRUCT() +struct FGAActiationInfo +{ + GENERATED_USTRUCT_BODY(); + + UPROPERTY() + float TimeStamp; + UPROPERTY() + float Duration; + UPROPERTY() + float Period; + UPROPERTY() + bool bApplyActivationEffect; + + inline void SetActivationInfo(float TimeStampIn, float DurationIn, float PeriodIn, + bool bApplyActivationEffectIn) + { + TimeStamp = TimeStampIn; + Duration = DurationIn; + Period = PeriodIn; + bApplyActivationEffect = bApplyActivationEffectIn; + //always increment to make sure it is replicated. + ForceReplication++; + } + + UPROPERTY() + int8 ForceReplication; +}; + +enum EAFAbilityState +{ + Waiting, + Activating +}; + +UCLASS(BlueprintType, Blueprintable) +class ABILITYFRAMEWORK_API UGAAbilityBase : public UObject, public IAFAbilityInterface, public IAFLatentInterface +{ + GENERATED_BODY() +public: + + /* + Since each ability is instanced per owner, and cannot be activated multiple times (ie, to run in background), + we can assume that PredictionHandle will always be unique per activation. + */ + FAFPredictionHandle PredictionHandle; + /* By default all abilities are considered to be replicated. */ + UPROPERTY(EditAnywhere, Category = "Replication") + bool bReplicate; + + bool bIsNameStable; + + //possibly map TMap ? + UPROPERTY(Transient) + TSet ActiveTasks; + /* List of tasks, this ability have. */ + UPROPERTY(Transient) + TMap AbilityTasks; + + /* + Delegate is used to confirm ability execution. + After confirming ability will proceed to activation state and either casts instatly or start + casting effect. + */ + FGASSimpleAbilityDynamicDelegate OnConfirmDelegate; + /* + Delegate which is called after ability is confirmed and then cast time ended. + */ + FGASSimpleAbilityDynamicDelegate OnConfirmCastingEndedDelegate; + FSimpleDelegate ConfirmDelegate; + + /* Attributes specific to ability. */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Instanced, Category = "AbilityFramework|Abilities") + UGAAttributesBase* Attributes; + + UPROPERTY(Transient) + class UWorld* World; + /* + Replicated to everyone because we will need it, to determine cosmetic stuff on clients. + */ + /* + */ + UPROPERTY(BlueprintReadOnly, Replicated, BlueprintReadOnly, Category = "AbilityFramework|Abilities", Transient) + APawn* POwner; + UPROPERTY(BlueprintReadOnly, Replicated, Category = "AbilityFramework|Abilities", Transient) + APlayerController* PCOwner; + UPROPERTY(BlueprintReadOnly, Replicated, Category = "AbilityFramework|Abilities", Transient) + class AAIController* AICOwner; + UPROPERTY(BlueprintReadOnly, Category = "AbilityFramework|Abilities", Transient) + class UAFAbilityComponent* AbilityComponent; + + /* + Physical reprsentation of ability in game world. It might be sword, gun, or character. + What differs it from pawn or controller is that Avatar is actually used by ability to perform actions. + + It will need some common interfaces for getting data out. + */ + UPROPERTY(BlueprintReadOnly, Replicated, Category = "AbilityFramework|Abilities", Transient) + class AActor* AvatarActor; + + UPROPERTY(BlueprintReadOnly, Category = "AbilityFramework|Abilities", Transient) + UCameraComponent* OwnerCamera; + + FGAEffectContext DefaultContext; + + /* + Tags applied to instigator of this ability, for duration of cooldown. + Duration of this effect equals cooldown of ability. + */ + UPROPERTY(EditAnywhere, meta=(AllowedClass="AFAbilityCooldownSpec"), Category = "Config") + FAFPropertytHandle CooldownEffect; + TArray CooldownEffectHandle; + /* + Tags applied to the time of activation ability. + Only applies to abilities, which are not instant (for now). + Though even instant abilities have animation time, + they probabaly never apply activation tags, since + main usecase for those tags is to make other abilities + being able to interrupt them. + All abilities with casting/channeling time use it. + + Add Periodic Effect ? (For abilities with period). + */ + UPROPERTY(EditAnywhere, meta = (AllowedClass = "AFAbilityActivationSpec,AFAbilityPeriodSpec,AFAbilityInfiniteDurationSpec,AFAbilityPeriodicInfiniteSpec"), Category = "Config") + FAFPropertytHandle ActivationEffect; + TArray ActivationEffectHandle; + + /* + These attributes will be reduced by specified amount when ability is activated. + Attribute cost from Ability Owner attributes + */ + UPROPERTY(EditAnywhere, Category = "Config") + TArray AttributeCost; + TArray> AttributeCostHandle; + /* + Attribute cost from ability own attributes + */ + UPROPERTY(EditAnywhere, Category = "Config") + TArray AbilityAttributeCost; + TArray> AbilityAttributeCostHandle; + + UPROPERTY(AssetRegistrySearchable) + FName AbilityTagSearch; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Tags") + FGameplayTag AbilityTag; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Tags") + FGameplayTagContainer OwnedTags; + /* + These tags are added to owner while ability is activating (or channeled). + */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Tags") + FGameplayTagContainer ActivationAddedTags; + /* + These tags must be present on onwer to activate this ability. + */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Tags") + FGameplayTagContainer ActivationRequiredTags; + /* + If any of these tags is present ability activation is blocked. + */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Tags") + FGameplayTagContainer ActivationBlockedTags; + +public: //because I'm to lazy to write all those friend states.. + UFUNCTION() + void OnActivationEffectPeriod(); + + /* Replication counters for above events. */ + + + UPROPERTY(BlueprintAssignable) + FGASGenericAbilityDelegate OnInputPressedDelegate; + UPROPERTY(BlueprintAssignable) + FGASGenericAbilityDelegate OnInputReleasedDelegate; + UPROPERTY(BlueprintAssignable) + FGASGenericAbilityDelegate OnActivateBeginDelegate; + UPROPERTY(BlueprintAssignable) + FGASGenericAbilityDelegate OnActivationFinishedDelegate; + + UPROPERTY(BlueprintAssignable) + FGASGenericAbilityDelegate OnNotifyOnCooldown; + + /* Stub, I think replicating montage directly from ability will be better, as abilities are replicated regardless. */ + UPROPERTY(Transient) + UAnimMontage* RepMontage; +protected: + EAFAbilityState AbilityState; + +public: + UGAAbilityBase(const FObjectInitializer& ObjectInitializer); + + virtual void PostInitProperties() override; + + virtual void Serialize(FArchive& Ar) override; + // UObject interface + virtual FPrimaryAssetId GetPrimaryAssetId() const override; + virtual void PostLoad() override; + +#if WITH_EDITORONLY_DATA + /** This scans the class for AssetBundles metadata on asset properties and initializes the AssetBundleData with InitializeAssetBundlesFromMetadata */ + virtual void UpdateAssetBundleData(); + + /** Updates AssetBundleData */ + virtual void PreSave(const class ITargetPlatform* TargetPlatform) override; + +protected: + /** Asset Bundle data computed at save time. In cooked builds this is accessible from AssetRegistry */ + UPROPERTY() + FAssetBundleData AssetBundleData; +#endif +public: +#if WITH_EDITOR + virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; +#endif // WITH_EDITOR + + void UpdateAssetRegistryInfo(); + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities") + void PlayMontage(UAnimMontage* MontageIn, FName SectionName, float Speed = 1); + + void InitAbility(); +public: + UFUNCTION() + void OnAttributeSetReplicated(class UGAAttributesBase* ReplicatedAttributes); + //called on both server and client after InitAbility(); + virtual void OnAbilityInited(); + + /* + Called on server and client, after ability has been bound to some input. + */ + virtual void OnAbilityInputReady() {}; + + /* + * @call Order: + * Previous Function: FGASAbilityContainer::HandleInputPressed + * Next Function: UGAAbilityBase::OnInputPressed + * + * Called on both Client and Server. + * + * @param ActionName - Name of action which tirggered this ability + * @param InPredictionHandle - Prediction Handle Generate By Client + */ + void OnNativeInputPressed(uint8 InputID, const FAFPredictionHandle& InPredictionHandle); + /* + * @call Order: + * Previous Function: UGAAbilityBase::OnNativeInputPressed + * Next Function: Multiple Choices. Next function is usually called from within Ability Blueprint + * Default Choices: + * UGAAbilityBase::StartActivation + * UGAAbilityBase::CanUseAbility + * Custom Function + * + * Called on both Client and Server. + * + * @param ActionName - Name of action which tirggered this ability + */ + UFUNCTION(BlueprintImplementableEvent, Category = "AbilityFramework|Abilities") + void OnInputPressed(uint8 InputID); + + void OnNativeInputReleased(uint8 InputID); + UFUNCTION(BlueprintImplementableEvent, Category = "AbilityFramework|Abilities") + void OnInputReleased(uint8 InputID); + + + + + void NativeOnAbilityConfirmed(); + + + + /* + * @call Order: + * Previous Function: UGAAbilityBase::StartActivation + * Next Function: (Blueprint) UGAAbilityBase::FinishAbility + * + * Called on both Client and Server to indicate that ability is finished. + */ + UFUNCTION(BlueprintImplementableEvent, Category = "AbilityFramework|Abilities") + void OnActivationFinished(); + + /* + * @call Order: + * Previous Function: (Blueprint) UGAAbilityBase::OnInputPressed + * Next Function: UGAAbilityBase::NativeOnBeginAbilityActivation + * + * Called on both Client and Server. + * + * @param bApplyActivationEffect - Should apply activation effect to Owner. + */ + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities") + void StartActivation(bool bApplyActivationEffect); + + /* + * @call Order: + * Previous Function: UGAAbilityBase::StartActivation + * Next Function: UGAAbilityBase::ApplyActivationEffect + * Next Function: (Blueprint) UGAAbilityBase::OnActivate + * + * Called on both Client and Server. + * + * @param bApplyActivationEffect - Should apply activation effect to Owner. + */ + virtual void NativeOnBeginAbilityActivation(bool bApplyActivationEffect); + + /* + * @call Order: + * Previous Function: UGAAbilityBase::NativeOnBeginAbilityActivation - + * called when activation effect finishes (or immedietly, if there was no activation effect applied). + * Next Function: (Blueprint) Custom Functions + * Next Function: (Blueprint) UGAAbilityBase::FinishAbility - must be called at some point + * finish ability. + * + * Called on both Client and Server. + */ + UFUNCTION(BlueprintImplementableEvent, Category = "AbilityFramework|Abilities") + void OnActivate(); + + /* Event called when ability activation has been canceled. */ + UFUNCTION(BlueprintImplementableEvent, Category = "AbilityFramework|Abilities") + void OnActivationCancel(); + /* + * @call Order: + * Previous Function: Called if Periodic effect has been applied and is active. Otherwise inactive. + * called when activation effect finishes (or immedietly, if there was no activation effect applied). + * Next Function: (Blueprint) Custom Functions + * + * Called on both Client and Server. + */ + UFUNCTION(BlueprintImplementableEvent, Category = "AbilityFramework|Abilities") + void OnPeriod(); + + + + UFUNCTION(BlueprintImplementableEvent, Category = "AbilityFramework|Abilities") + void OnCooldownStart(); + UFUNCTION(BlueprintImplementableEvent, Category = "AbilityFramework|Abilities") + void OnCooldownEnd(); + + void NativeOnCooldownEnd(); + + UFUNCTION() + void OnCooldownEffectExpired(); + UFUNCTION() + void NativeOnAbilityActivationFinish(); + UFUNCTION() + void NativeOnAbilityActivationCancel(); + + /* + * @call Order: + * Previous Function: UGAAbilityBase::NativeOnBeginAbilityActivation - + * called when activation effect finishes (or immedietly, if there was no activation effect applied). + * Next Function: (Blueprint) Custom Functions + * Next Function: (Blueprint) UGAAbilityBase::FinishAbility - must be called at some point + * finish ability. + * + * Called to finish ability and start clean up. + */ + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities") + void FinishAbility(); + /* + * @call Order: + * Previous Function: UGAAbilityBase::FinishAbility + * Next Function: (Blueprint) UGAAbilityBase::OnAbilityFinished + * + * Called to finish ability and start clean up. + */ + void NativeFinishAbility(); + + /* + * @call Order: + * Previous Function: UGAAbilityBase::NativeFinishAbility + * Next Function: (Blueprint) Custom Functions + * + * Called when ability is finished. + */ + UFUNCTION(BlueprintImplementableEvent, Category = "AbilityFramework|Abilities") + void OnAbilityFinished(); + /* + Stop effect activation and remove activation effect. + */ + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities") + void CancelActivation(); + void NativeCancelActivation(); + + bool IsWaitingForConfirm(); + void ConfirmAbility(); + + bool CanUseAbility(); + bool CanReleaseAbility(); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "Can Use Ability"), Category = "AbilityFramework|Abilities") + bool BP_CanUseAbility(); + + virtual void SetAttributes(UGAAttributesBase* InAttributes) + { + Attributes = InAttributes; + } + virtual class UGAAttributesBase* GetAttributes() const + { + return Attributes; + } + /** IAFAbilityInterface Begin */ + virtual class UGAAttributesBase* GetAttributes() override; + virtual class UAFAbilityComponent* GetAbilityComp() override; + virtual class UAFEffectsComponent* GetEffectsComponent() override; + virtual class UAFEffectsComponent* NativeGetEffectsComponent() const override; + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities|Attributes") + virtual float GetAttributeValue(FGAAttribute AttributeIn) const override; + virtual float NativeGetAttributeValue(const FGAAttribute AttributeIn) const override; + virtual FAFAttributeBase* GetAttribute(FGAAttribute AttributeIn) override { return Attributes->GetAttribute(AttributeIn); }; + virtual void RemoveBonus(FGAAttribute AttributeIn, const FGAEffectHandle& HandleIn, EGAAttributeMod InMod) override { Attributes->RemoveBonus(AttributeIn, HandleIn, InMod); }; + virtual void ModifyAttribute(FGAEffectMod& ModIn, const FGAEffectHandle& HandleIn + , FGAEffectProperty& InProperty + , const FGAEffectContext& InContext) override + { + if (!Attributes) + { + UE_LOG(AFAbilities, Log, TEXT("ModifyAttribute Ability Attributes INVALID")); + return; + } + Attributes->ModifyAttribute(ModIn, HandleIn, InProperty, InContext); + }; + virtual FAFPredictionHandle GetPredictionHandle() override; + /* IAFAbilityInterface End **/ + UFUNCTION(BlueprintPure, Category = "AbilityFramework|Abilities|Attributes") + virtual float GetAttributeVal(FGAAttribute AttributeIn) const; + +public: //protected ? + bool ApplyCooldownEffect(); + UFUNCTION(Client, Reliable) + void ClientSetCooldownHandle(FGAEffectHandle InCooldownHandle); + void ClientSetCooldownHandle_Implementation(FGAEffectHandle InCooldownHandle); + + bool ApplyActivationEffect(bool bApplyActivationEffect); + bool ApplyAttributeCost(); + bool ApplyAbilityAttributeCost(); + bool CheckAbilityAttributeCost(); + bool CheckAttributeCost(); + bool IsOnCooldown(); + bool IsActivating(); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Is On Cooldown"), Category = "AbilityFramework|Abilities") + bool BP_IsOnCooldown(); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Apply Cooldown"), Category = "AbilityFramework|Abilities") + void BP_ApplyCooldown(); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Apply Attribute Cost"), Category = "AbilityFramework|Abilities") + bool BP_ApplyAttributeCost(); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Check Attribute Cost"), Category = "AbilityFramework|Abilities") + bool BP_CheckAttributeCost(); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Apply Ability Attribute Cost"), Category = "AbilityFramework|Abilities") + bool BP_ApplyAbilityAttributeCost(); + + UFUNCTION(BlueprintCallable, meta = (DisplayName = "Check Ability Attribute Cost"), Category = "AbilityFramework|Abilities") + bool BP_CheckAbilityAttributeCost(); + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities") + float GetCurrentActivationTime(); + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities") + float CalculateAnimationSpeed(UAnimMontage* MontageIn); + + /* Replication */ + bool IsNameStableForNetworking() const override; + + bool IsSupportedForNetworking() const override + { + return bReplicate; + } + void SetNetAddressable(); + +public: + int32 GetFunctionCallspace(UFunction* Function, void* Parameters, FFrame* Stack) override; + virtual bool CallRemoteFunction(UFunction* Function, void* Parameters, FOutParmRec* OutParms, FFrame* Stack) override; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities") + void ExecuteAbilityInputPressedFromTag(FGameplayTag AbilityTagIn, FGameplayTag ActionName); + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities") + void ExecuteAbilityInputReleasedFromTag(FGameplayTag AbilityTagIn, FGameplayTag ActionName); + + virtual class UWorld* GetWorld() const override; + + inline void AddAbilityTask(FName InName, class UAFTaskBase* InTask) + { + if (!AbilityTasks.Contains(InName)) + { + AbilityTasks.Add(InName, InTask); + } + } + class UGAAbilityTask* GetAbilityTask(const FName& InName); + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities|Tags") + bool HaveGameplayTag(AActor* Target, const FGameplayTag& Tag); + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities|Tags") + bool HaveAnyGameplayTag(AActor* Target, const FGameplayTagContainer& Tag); + + /* Tracing Helpers Start */ + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities|Tracing") + bool LineTraceSingleByChannel(const FVector Start, const FVector End, ETraceTypeQuery TraceChannel, bool bTraceComplex, FHitResult& OutHit); + /* Traces location from owner camera position if no camera available traces from eyes */ + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities|Tracing") + bool LineTraceSingleByChannelFromCamera(float Range, ETraceTypeQuery TraceChannel, bool bTraceComplex, FHitResult& OutHit, + EDrawDebugTrace::Type DrawDebugType, bool bIgnoreSelf, FLinearColor TraceColor, FLinearColor TraceHitColor, float DrawTime); + /* Traces from ability avatar socket. */ + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities|Tracing") + bool LineTraceSingleByChannelFromSocket(FName SocketName, float Range, ETraceTypeQuery TraceChannel, bool bTraceComplex, FHitResult& OutHit, + EDrawDebugTrace::Type DrawDebugType, bool bIgnoreSelf, FLinearColor TraceColor, FLinearColor TraceHitColor, float DrawTime); + /* Make first trace from camera location and then second trace from avatar socket in direction of first trace. */ + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Abilities|Tracing") + bool LineTraceSingleByChannelCorrected(FName SocketName, float Range, ETraceTypeQuery TraceChannel, bool bTraceComplex, FHitResult& OutHit, + EDrawDebugTrace::Type DrawDebugType, bool bIgnoreSelf, FLinearColor TraceColor, FLinearColor TraceHitColor, float DrawTime); + /* Tracing Helpers End */ + + + //Helpers + float GetActivationRemainingTime() const; + float GetActivationRemainingTimeNormalized() const; + float GetActivationCurrentTime() const; + float GetActivationCurrentTimeNormalized() const; + float GetActivationEndTime() const; + + UFUNCTION(BlueprintPure, DisplayName = "GetActivationRemainingTime", Category = "AbilityFramework|Abilities|Helpers") + float BP_GetActivationRemainingTime(); + UFUNCTION(BlueprintPure, DisplayName = "GetActivationRemainingTimeNormalized", Category = "AbilityFramework|Abilities|Helpers") + float BP_GetActivationRemainingTimeNormalized(); + UFUNCTION(BlueprintPure, DisplayName = "GetActivationCurrentTime", Category = "AbilityFramework|Abilities|Helpers") + float BP_GetActivationCurrentTime(); + UFUNCTION(BlueprintPure, DisplayName = "GetActivationCurrentTimeNormalized", Category = "AbilityFramework|Abilities|Helpers") + float BP_GetActivationCurrentTimeNormalized(); + UFUNCTION(BlueprintPure, DisplayName = "GetActivationEndTime", Category = "AbilityFramework|Abilities|Helpers") + float BP_GetActivationEndTime(); + + + float GetCooldownRemainingTime() const; + float GetCooldownRemainingTimeNormalized() const; + float GetCooldownCurrentTime() const; + float GetCooldownCurrentTimeNormalized() const; + float GetCooldownEndTime() const; + + UFUNCTION(BlueprintPure, DisplayName = "GetCooldownRemainingTime", Category = "AbilityFramework|Abilities|Helpers") + float BP_GetCooldownRemainingTime(); + UFUNCTION(BlueprintPure, DisplayName = "GetCooldownRemainingTimeNormalized", Category = "AbilityFramework|Abilities|Helpers") + float BP_GetCooldownRemainingTimeNormalized(); + UFUNCTION(BlueprintPure, DisplayName = "GetCooldownCurrentTime", Category = "AbilityFramework|Abilities|Helpers") + float BP_GetCooldownCurrentTime(); + UFUNCTION(BlueprintPure, DisplayName = "GetCooldownCurrentTimeNormalized", Category = "AbilityFramework|Abilities|Helpers") + float BP_GetCooldownCurrentTimeNormalized(); + UFUNCTION(BlueprintPure, DisplayName = "GetCooldownEndTime", Category = "AbilityFramework|Abilities|Helpers") + float BP_GetCooldownEndTime(); + + UFUNCTION(BlueprintCallable, DisplayName = "Get Avatar", Category = "AbilityFramework|Abilities|Helpers") + AActor* BP_GetAvatar(); + + virtual void OnAvatarReady() {}; + + + /* IAFLatentInterface */ + virtual void OnLatentTaskAdded(FName InstanceName, class UAFTaskBase* TaskIn); + virtual void AddReplicatedTask(class UAFTaskBase* TaskIn); + virtual void OnLatentTaskRemoved(class UAFTaskBase* TaskIn); + + virtual void OnLatentTaskActivated(class UAFTaskBase* TaskIn); + virtual void OnLatentTaskDeactivated(class UAFTaskBase* TaskIn); + + virtual class UAFTaskBase* GetCachedLatentAction(FName TaskName); + /* IAFLatentInterface */ +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/GAAbilityBlueprint.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/GAAbilityBlueprint.h new file mode 100644 index 0000000..e1c6fef --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/GAAbilityBlueprint.h @@ -0,0 +1,31 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Engine/Blueprint.h" +#include "GAAbilityBlueprint.generated.h" + +/** + * Game Ability Blueprint + */ + +UCLASS(BlueprintType) +class ABILITYFRAMEWORK_API UGAAbilityBlueprint : public UBlueprint +{ + GENERATED_UCLASS_BODY() + +#if WITH_EDITOR + + // UBlueprint interface + virtual bool SupportedByDefaultBlueprintFactory() const override + { + return false; + } + // End of UBlueprint interface + + /** Returns the most base gameplay ability blueprint for a given blueprint (if it is inherited from another ability blueprint, returning null if only native / non-ability BP classes are it's parent) */ + static UGAAbilityBlueprint* FindRootGameplayAbilityBlueprint(UGAAbilityBlueprint* DerivedBlueprint); + +#endif +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/AFAbilityTask_SpawnProjectile.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/AFAbilityTask_SpawnProjectile.h new file mode 100644 index 0000000..5d3e7ae --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/AFAbilityTask_SpawnProjectile.h @@ -0,0 +1,58 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Abilities/Tasks/GAAbilityTask.h" +#include "AFAbilityTask_SpawnProjectile.generated.h" + +UENUM() +enum class EAFPRojectileSpawnTraceOption : uint8 +{ + DoNotTrace, + TraceFullPath, + OnlyTraceWhileAscending, +}; + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FAFOnPRojectileSpawned); + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFAbilityTask_SpawnProjectile : public UGAAbilityTask +{ + GENERATED_BODY() +public: + UPROPERTY() + FVector StartLocation; + UPROPERTY() + FVector EndLocation; + UPROPERTY() + float LaunchSpeed; + UPROPERTY() + float OverrideGravityZ; + UPROPERTY() + EAFPRojectileSpawnTraceOption TraceOption; + UPROPERTY() + float CollisionRadius; + UPROPERTY() + bool bFavorHighArc; + UPROPERTY() + bool bDrawDebug; + + UPROPERTY(BlueprintAssignable) + FAFOnPRojectileSpawned Played; +public: + static UAFAbilityTask_SpawnProjectile* Ability_SpawnProjectile(UGAAbilityBase* WorldContextObject, + FName InTaskName, + FVector InStartLocation, + FVector InEndLocation, + float InLaunchSpeed, + float InOverrideGravityZ, + EAFPRojectileSpawnTraceOption InTraceOption, + float InCollisionRadius, + bool InbFavorHighArc, + bool InbDrawDebug); + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask.h new file mode 100644 index 0000000..b989524 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask.h @@ -0,0 +1,95 @@ +#pragma once +#include "GameplayTask.h" +#include "GAAbilityBase.h" +#include "AFAbilityComponent.h" + +#include "LatentActions/AFTaskBase.h" + +#include "GAAbilityTask.generated.h" +/* + AbilityActions are generic (preferably C++) defined actions, which then can be added to ability and + the should be activated from ability. + Then can perform tasks, like spawn tagetting helpers (splines, circles), spawn actors, + gather targeting data etc. + + Should they be activated automatically after ability is initialized, (it'e ability enterted in + active state, which means it's ready to be fired and display helpers, but did not yet received input, + or should designer in blueprint decide when to launch actions ?). +*/ + +UCLASS(BlueprintType, Blueprintable, Within=GAAbilityBase) +class ABILITYFRAMEWORK_API UGAAbilityTask : public UAFTaskBase +{ + GENERATED_BODY() + friend struct FAFAbilityTaskMessageTick; +public: + uint8 bIsReplicated : 1; + /* Ability owning this task */ + TWeakObjectPtr Ability; + /* Ability owning this task */ + TWeakObjectPtr AbilityComponent; +public: + + template + static T* NewAbilityTask(UGAAbilityBase* WorldContextObject, FName InTaskName = FName(), FName InstanceName = FName()) + { + check(WorldContextObject); + + T* MyObj = nullptr; + UGAAbilityBase* ThisAbility = CastChecked(WorldContextObject); + MyObj = NewTask(WorldContextObject, WorldContextObject, InTaskName); + + MyObj->Ability = ThisAbility; + MyObj->AbilityComponent = ThisAbility->AbilityComponent; + + return MyObj; + } + UGAAbilityTask(const FObjectInitializer& ObjectInitializer); + bool IsReplicated() + { + return bIsReplicated; + } + +protected: + bool IsClient() + { + APawn* POwner = Ability->POwner; + if (POwner->GetNetMode() == ENetMode::NM_Client) + { + return true; + } + return false; + } + + bool IsServer() + { + APawn* POwner = Ability->POwner; + if (POwner->GetNetMode() == ENetMode::NM_DedicatedServer + || POwner->GetNetMode() == ENetMode::NM_ListenServer) + { + return true; + } + return false; + } + bool IsServerOrStandalone() + { + APawn* POwner = Ability->POwner; + if (POwner->GetNetMode() == ENetMode::NM_DedicatedServer + || POwner->GetNetMode() == ENetMode::NM_ListenServer + || POwner->GetNetMode() == ENetMode::NM_Standalone) + { + return true; + } + return false; + } + + bool IsAuthority() + { + APawn* POwner = Ability->POwner; + if (POwner->Role >= ENetRole::ROLE_Authority) + { + return true; + } + return false; + } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_CreateObject.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_CreateObject.h new file mode 100644 index 0000000..3fbdd2c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_CreateObject.h @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GAAbilityTask.h" +#include "GAAbilityTask_CreateObject.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGASSpawnObjectDelegate, class UObject*, SpawnedObject); + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UGAAbilityTask_CreateObject : public UGAAbilityTask +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintAssignable) + FGASSpawnObjectDelegate Success; + UPROPERTY(BlueprintAssignable) + FGASSpawnObjectDelegate Failure; + + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + static UGAAbilityTask_CreateObject* CreateObject(UGAAbilityBase* WorldContextObject, + FName InTaskName, TSubclassOf Class, UObject* Outer); + + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + bool BeginSpawningActor(UGAAbilityBase* WorldContextObject, TSubclassOf Class, class UObject*& SpawnedActor); + + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + void FinishSpawningActor(UGAAbilityBase* WorldContextObject, class UObject* SpawnedActor); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_PlayMontage.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_PlayMontage.h new file mode 100644 index 0000000..1c33398 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_PlayMontage.h @@ -0,0 +1,45 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GAAbilityTask.h" +#include "AFAbilityTypes.h" +#include "GAAbilityTask_PlayMontage.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FGASGenericMontageDelegate, FGameplayTag, Tag, FName, NotifyName); + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UGAAbilityTask_PlayMontage : public UGAAbilityTask +{ + GENERATED_BODY() + +public: + UPROPERTY(BlueprintReadOnly, meta = (ExposeOnSpawn = true)) + UAnimMontage* Montage; + FName SectionName; + float PlayRate; + bool bUseActivationTime; + + UPROPERTY(BlueprintAssignable) + FGASGenericMontageDelegate Played; + UPROPERTY(BlueprintAssignable) + FGASGenericMontageDelegate NotifyBegin; + UPROPERTY(BlueprintAssignable) + FGASGenericMontageDelegate NotifyTick; + UPROPERTY(BlueprintAssignable) + FGASGenericMontageDelegate NotifyEnd; + + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + static UGAAbilityTask_PlayMontage* AbilityPlayMontage(UGAAbilityBase* WorldContextObject, + FName InTaskName, UAnimMontage* MontageIn, FName SectionNameIn, float PlayRateIn, + bool bInUseActivationTime); + + virtual void Activate() override; + + void BroadcastStartNotifyState(const FGameplayTag& InTag, const FName& InName); + void BroadcastEndNotifyState(const FGameplayTag& InTag, const FName& InName); + void BroadcastTickNotifyState(const FGameplayTag& InTag, const FName& InName); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_Repeat.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_Repeat.h new file mode 100644 index 0000000..914bf6a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_Repeat.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GAAbilityTask.h" +#include "GAAbilityTask_Repeat.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGASOnTaskRepeated); + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UGAAbilityTask_Repeat : public UGAAbilityTask +{ + GENERATED_BODY() + + UPROPERTY(BlueprintAssignable) + FGASOnTaskRepeated OnTaskRepeated; + + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + static UGAAbilityTask_Repeat* CreateRepeatTask(UGAAbilityBase* WorldContextObject, + FName InTaskName); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_SpawnActor.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_SpawnActor.h new file mode 100644 index 0000000..af30e2f --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_SpawnActor.h @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GAAbilityTask.h" +#include "GAAbilityTask_SpawnActor.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGASSpawnActorDelegate, AActor*, SpawnedActor); + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UGAAbilityTask_SpawnActor : public UGAAbilityTask +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintAssignable) + FGASSpawnActorDelegate Success; + UPROPERTY(BlueprintAssignable) + FGASSpawnActorDelegate Failure; + + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + static UGAAbilityTask_SpawnActor* SpawnActor(UGAAbilityBase* WorldContextObject, + FName InTaskName, TSubclassOf Class); + + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + bool BeginSpawningActor(UGAAbilityBase* WorldContextObject, TSubclassOf Class, AActor*& SpawnedActor); + + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + void FinishSpawningActor(UGAAbilityBase* WorldContextObject, AActor* SpawnedActor); + + virtual void Activate() override; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_TargetData.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_TargetData.h new file mode 100644 index 0000000..2546286 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_TargetData.h @@ -0,0 +1,64 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GAAbilityTask.h" +#include "GAAbilityTask_TargetData.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGASOnReceiveTargetData, const FHitResult&, HitResult); + +UENUM() +enum class EGASConfirmType : uint8 +{ + Instant, + WaitForConfirm +}; + + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UGAAbilityTask_TargetData : public UGAAbilityTask, public FTickableGameObject +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintAssignable) + FGASOnReceiveTargetData OnConfirmed; + UPROPERTY(BlueprintAssignable) + FGASOnReceiveTargetData OnReceiveTargetData; + + EGASConfirmType ConfirmType; + + float Range; + bool bIsTickable; + bool bDrawDebug; + bool bDrawCorrectedDebug; + bool bUseCorrectedTrace; +public: + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + static UGAAbilityTask_TargetData* CreateTargetDataTask(UGAAbilityBase* WorldContextObject, + FName InTaskName, + bool bDrawDebug, + bool bDrawCorrectedDebug, + bool bUseCorrectedTrace, + EGASConfirmType ConfirmTypeIn, + float Range); + + virtual void Activate() override; + + UFUNCTION() + virtual void OnConfirm(); + + UFUNCTION() + void OnCastEndedConfirm(); + + /* FTickableGameObject Begin */ + virtual void Tick(float DeltaTime) override; + virtual bool IsTickable() const override { return bIsTickable; } + virtual TStatId GetStatId() const override { RETURN_QUICK_DECLARE_CYCLE_STAT(UGAAbilityTask_TargetData, STATGROUP_Tickables); }; + /* FTickableGameObject End */ + +protected: + FHitResult LineTrace(); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_TargetDataCircle.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_TargetDataCircle.h new file mode 100644 index 0000000..f8f162b --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_TargetDataCircle.h @@ -0,0 +1,39 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GAAbilityTask.h" +#include "GAAbilityTask_TargetData.h" +#include "GAAbilityTask_TargetDataCircle.generated.h" + +//DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGASOnReceiveTargetData, const FHitResult&, HitResult); + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UGAAbilityTask_TargetDataCircle : public UGAAbilityTask_TargetData +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintAssignable) + FGASOnReceiveTargetData OnReceiveTargetDataCircle; + + EGASConfirmType ConfirmType; + +public: + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + static UGAAbilityTask_TargetDataCircle* TargetCircleDataTask(UGAAbilityBase* WorldContextObject, + FName InTaskName, EGASConfirmType ConfirmTypeIn); + + virtual void Activate() override; + + //UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + // bool BeginSpawningActor(UObject* WorldContextObject, class UGASAbilityTargetingObject*& SpawnedActor); + + //UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + // void FinishSpawningActor(UObject* WorldContextObject, class UGASAbilityTargetingObject* SpawnedActor); + // + + virtual void OnConfirm() override; +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_TargetDataLineTrace.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_TargetDataLineTrace.h new file mode 100644 index 0000000..4e317fc --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_TargetDataLineTrace.h @@ -0,0 +1,107 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GAAbilityTask.h" +#include "Components/SkeletalMeshComponent.h" +#include "GAAbilityTask_TargetDataLineTrace.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAFOnTargetReceived, const FHitResult&, HitResult); + +UENUM() +enum class EAFConfirmType : uint8 +{ + Instant, + WaitForConfirm +}; + +USTRUCT() +struct FAFLineTraceData +{ + GENERATED_BODY() + UPROPERTY() + float ExactPing; + UPROPERTY() + AActor* HitActor; + UPROPERTY() + FVector HitLocation; +}; +USTRUCT() +struct FAFLineTraceConfirmData +{ + GENERATED_BODY() + + UPROPERTY() + uint8 bConfirmed : 1; + UPROPERTY() + AActor* HitActor; + UPROPERTY() + FVector HitLocation; +}; +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UGAAbilityTask_TargetDataLineTrace : public UGAAbilityTask, public FTickableGameObject +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintAssignable) + FAFOnTargetReceived OnClientReceiveTargetData; + + UPROPERTY(BlueprintAssignable) + FAFOnTargetReceived OnClientUnconfirmedTargetData; + + UPROPERTY(BlueprintAssignable) + FAFOnTargetReceived OnServerReceiveTargetData; + + ETraceTypeQuery TraceChannel; + USkeletalMeshComponent* SocketComponent; + FName SocketName; + EAFConfirmType ConfirmType; + + float Range; + bool bIsTickable; + bool bDrawDebug; + + //Result of trace from either server or client simulation + FHitResult LocalHitResult; +public: + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + static UGAAbilityTask_TargetDataLineTrace* CreateTargetDataLineTrace(UGAAbilityBase* WorldContextObject + , FName InTaskName + , ETraceTypeQuery InTraceChannel + , USkeletalMeshComponent* InSocketComponent + , FName InSocketName + , bool bDrawDebug + , EAFConfirmType ConfirmTypeIn + , float Range); + + UGAAbilityTask_TargetDataLineTrace(const FObjectInitializer& ObjectInitializer); + + virtual void Activate() override; + + UFUNCTION(Server, Reliable, WithValidation) + void ServerConfirmHitInfo(FAFLineTraceData TraceData); + void ServerConfirmHitInfo_Implementation(FAFLineTraceData TraceData); + bool ServerConfirmHitInfo_Validate(FAFLineTraceData TraceData); + + UFUNCTION(Client, Reliable) + void ClientConfirmHitInfo(FAFLineTraceConfirmData ConfirmData); + void ClientConfirmHitInfo_Implementation(FAFLineTraceConfirmData ConfirmData); + + UFUNCTION() + void OnConfirm(); + + UFUNCTION() + void OnCastEndedConfirm(); + + /* FTickableGameObject Begin */ + virtual void Tick(float DeltaTime) override; + virtual bool IsTickable() const override { return bIsTickable; } + virtual TStatId GetStatId() const override { RETURN_QUICK_DECLARE_CYCLE_STAT(UGAAbilityTask_TargetData, STATGROUP_Tickables); }; + /* FTickableGameObject End */ + +protected: + FHitResult LineTrace(); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_WaitForConfirm.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_WaitForConfirm.h new file mode 100644 index 0000000..e81c18a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_WaitForConfirm.h @@ -0,0 +1,30 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GAAbilityTask.h" +#include "GAAbilityTask_WaitForConfirm.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGASOnConfirmed); + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UGAAbilityTask_WaitForConfirm : public UGAAbilityTask +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintAssignable) + FGASOnConfirmed OnConfirmed; + + UFUNCTION(BlueprintCallable, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", BlueprintInternalUseOnly = "true"), Category = "AbilityFramework|Abilities|Tasks") + static UGAAbilityTask_WaitForConfirm* CreateWaitConfirmTask(UGAAbilityBase* WorldContextObject, + FName InTaskName); + + virtual void Activate() override; + virtual void Initialize() override; + + UFUNCTION() + void OnConfirm(); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_WaitTargetData.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_WaitTargetData.h new file mode 100644 index 0000000..d50f96e --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Abilities/Tasks/GAAbilityTask_WaitTargetData.h @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GAAbilityTask.h" +#include "GAAbilityTask_WaitTargetData.generated.h" +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGASOnTargetingTaskConfimred); + +/** + * + */ +UCLASS(meta = (ExposedAsyncProxy)) +class ABILITYFRAMEWORK_API UGAAbilityTask_WaitTargetData : public UGAAbilityTask +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintAssignable) + FGASOnTargetingTaskConfimred OnConfirmed; + + UPROPERTY() + float Range; + ETraceTypeQuery TraceChannel; + + virtual void Activate() override; + + virtual void TickTask(float DeltaSeconds, ELevelTick TickType, FGALatentFunctionTick& ThisTickFunction) override; + + + UFUNCTION() + void OnConfirm(); + +public: + UGAAbilityTask_WaitTargetData(const FObjectInitializer& ObjectInitializer); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AbilityFramework.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AbilityFramework.h new file mode 100644 index 0000000..888d139 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AbilityFramework.h @@ -0,0 +1,154 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#pragma once +#include "Engine.h" +#include "IAbilityFramework.h" +#include "InputCoreTypes.h" + +#include "Runtime/UMG/Public/UMG.h" +#include "Runtime/UMG/Public/UMGStyle.h" +#include "Runtime/UMG/Public/Slate/SObjectWidget.h" +#include "Runtime/UMG/Public/IUMGModule.h" +#include "Runtime/UMG/Public/Blueprint/UserWidget.h" +//#include "GameTrace.h" + +enum class EAFEffectTimerStatus : uint8 +{ + Pending, + Active, + Executing, + Paused +}; + +struct FAFEffectTimeHandle +{ + int32 Index; + bool operator==(const FAFEffectTimeHandle& Other) const + { + return Index == Other.Index; + } +}; + +struct FAFEffectTimer +{ + double StartTime; //when started + double ExpireTime; + double NextPeriodTime; + double PeriodTime; + double Duration; //how often timer is executed + + bool bHaveDuration; //does it loop + bool bHavePeriod; + bool bActive; + + EAFEffectTimerStatus Status; + + FSimpleDelegate ExpireDelegate; + FSimpleDelegate PeriodDelegate; + + FAFEffectTimeHandle Handle; + + FAFEffectTimer(); + + bool operator<(const FAFEffectTimer& Other) const + { + return ExpireTime < Other.ExpireTime; + } + bool operator==(const FAFEffectTimer& Other) const + { + return Handle == Other.Handle; + } +}; + +DECLARE_STATS_GROUP(TEXT("EffectTimer"), STATGROUP_EffectTimer, STATCAT_Advanced); +class FAFEffectTimerWorker : public FRunnable +{ + FCriticalSection CS; + TArray Timers; + TArray ActiveTimers; + UWorld* World; + double InternalTime; + bool bActive; +public: + FAFEffectTimerWorker(); + virtual bool Init() override; + + /** + * Runs the runnable object. + * + * This is where all per object thread work is done. This is only called if the initialization was successful. + * + * @return The exit code of the runnable object + * @see Init, Stop, Exit + */ + virtual uint32 Run() override; + + /** + * Stops the runnable object. + * + * This is called if a thread is requested to terminate early. + * @see Init, Run, Exit + */ + virtual void Stop() override; + + /** + * Exits the runnable object. + * + * Called in the context of the aggregating thread to perform any cleanup. + * @see Init, Run, Stop + */ + virtual void Exit() override; + + FAFEffectTimeHandle AddTimer(double InDuration, double InPeriod); +}; + +class FAFEffectTimerManager +{ + FRunnableThread* TimerThread; + FAFEffectTimerWorker* TimerWorker; + + +public: + static FAFEffectTimerManager* Instance; + static FAFEffectTimerManager* Get() + { + //static FAFEffectTimerManager Obj;// = nullptr; + //return Obj; + if (!Instance) + Instance = new FAFEffectTimerManager(); + + return Instance; + + } + + FAFEffectTimerManager(); + + ~FAFEffectTimerManager(); + + void TickTimer(float InDeltaTime); + FAFEffectTimeHandle AddTimer(double InDuration, double InPeriod); +}; + +class FAbilityFramework : public IAbilityFramework +{ + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; + + void InitCues(); +}; + + +DECLARE_LOG_CATEGORY_EXTERN(AbilityFramework, Log, All); + +DECLARE_LOG_CATEGORY_EXTERN(GameAttributesGeneral, Log, All); + +DECLARE_LOG_CATEGORY_EXTERN(GameAttributes, Log, All); + +DECLARE_LOG_CATEGORY_EXTERN(GameAttributesEffects, Log, All); + + + +DECLARE_LOG_CATEGORY_EXTERN(AFAttributes, Log, All); +DECLARE_LOG_CATEGORY_EXTERN(AFEffects, Log, All); +DECLARE_LOG_CATEGORY_EXTERN(AFAbilities, Log, All); \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AnimNotify/AFAbilityNotifyState.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AnimNotify/AFAbilityNotifyState.h new file mode 100644 index 0000000..d2a949a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AnimNotify/AFAbilityNotifyState.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "Animation/AnimNotifies/AnimNotifyState.h" +#include "GameplayTags.h" +#include "AFAbilityNotifyState.generated.h" + +/** + * + */ +UCLASS(meta = (DisplayName = "Ability Notify State")) +class ABILITYFRAMEWORK_API UAFAbilityNotifyState : public UAnimNotifyState +{ + GENERATED_BODY() +protected: + UPROPERTY(EditAnywhere) + FGameplayTag Tag; + UPROPERTY(EditAnywhere) + FName Name; + UPROPERTY() + class UAFAbilityComponent* CachedAbilitiesComp; +public: + virtual void NotifyBegin(class USkeletalMeshComponent * MeshComp, class UAnimSequenceBase * Animation, float TotalDuration) override; + virtual void NotifyTick(class USkeletalMeshComponent * MeshComp, class UAnimSequenceBase * Animation, float FrameDeltaTime) override; + virtual void NotifyEnd(class USkeletalMeshComponent * MeshComp, class UAnimSequenceBase * Animation) override; + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/AnimNotify/AFAnimNotify.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AnimNotify/AFAnimNotify.h new file mode 100644 index 0000000..b6e0390 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/AnimNotify/AFAnimNotify.h @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "Animation/AnimNotifies/AnimNotify.h" +#include "GameplayTags.h" +#include "AFAnimNotify.generated.h" + +/** + * + */ +UCLASS(meta=(DisplayName = "Ability Notify")) +class ABILITYFRAMEWORK_API UAFAnimNotify : public UAnimNotify +{ + GENERATED_BODY() + + virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override; + + UPROPERTY(EditAnywhere) + FGameplayTag Tag; + UPROPERTY(EditAnywhere) + FName Name; +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributeBase.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributeBase.h new file mode 100644 index 0000000..274dbde --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributeBase.h @@ -0,0 +1,172 @@ +#pragma once +#include "../GAGlobalTypes.h" +#include "./Effects/GAGameEffect.h" +#include "../Effects/GAEffectGlobalTypes.h" + +// Messaging +//#include "Messaging.h" + +#include "GAAttributeBase.generated.h" + +DECLARE_MULTICAST_DELEGATE(FGAGenericAttributeDelegate); + +DECLARE_STATS_GROUP(TEXT("Attribute"), STATGROUP_Attribute, STATCAT_Advanced); +DECLARE_CYCLE_STAT_EXTERN(TEXT("CalculateBonus"), STAT_CalculateBonus, STATGROUP_Attribute, ); +DECLARE_CYCLE_STAT_EXTERN(TEXT("CurrentBonusByTag"), STAT_CurrentBonusByTag, STATGROUP_Attribute, ); +DECLARE_CYCLE_STAT_EXTERN(TEXT("FinalBonusByTag"), STAT_FinalBonusByTag, STATGROUP_Attribute, ); + + +struct QueuedAttributeMods +{ +public: + FGAEffectHandle Handle; + FGAEffectMod Mod; + + void operator=(const QueuedAttributeMods& Other) + { + Handle = Other.Handle; + Mod = Other.Mod; + } +}; + +//wrapper for multi-precision attribute. +//works like any numeric type, but depending on preprocessor flag it can int16,in32, float or double. + +typedef int16 AttributeReal; + +struct FNumericAttribute +{ + AttributeReal Value; +}; + +class UAFAbilityComponent; +/* + I probabaly should chaange attribute to use int's instead of floats. Stable, accurate and + I can still have decimal values with them. +*/ +/* + Base data structure describing Attribute: + 1. Base Value - the base value attribute has been initialized with. + 2. Current value - current value of attribute. + 3. Bonuses value. + 4. One bonus value (if need be attribute can take care of calculating it's own bonus value). + + As for now it's made to in mind to use it as meta attribute. Meta attributes, have always + 0 value and are used to change other attributes. Like Damage is used to subtract health. + LifeSteal is used to transfer health from target to instigator etc. + + We could extend attributes, to also support tags, so their bonus can be recalculated, + based on on tags requiremnts from effect asking for this particular attribute. +*/ +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFAttributeBase +{ + GENERATED_BODY() +public: + + UPROPERTY(NotReplicated) + class UAFAbilityComponent* AbilityComp; + UPROPERTY(NotReplicated) + FGAAttribute SelfName; + + UPROPERTY(EditAnywhere, SaveGame) + float BaseValue; + /* + Bonus Value applied to BaseValue of Attribute. It should never be directly modified outside of AbilityFramework. + */ + UPROPERTY(SaveGame) + float BaseBonusValue; + + UPROPERTY(EditAnywhere, SaveGame) + float MinValue; + + UPROPERTY(EditAnywhere, SaveGame) + float MaxValue; + /* + Bonus to the MaxValue. + */ + UPROPERTY(SaveGame) + float BonusMaxValue; + + UPROPERTY(SaveGame) + float CurrentValue; + + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Value") + TSubclassOf ExtensionClass; + + //Considering amount of bonuses TArray might be better than TMap, for cache coherency. + TArray> Modifiers; + FAFAttributeBase(); + FAFAttributeBase(float BaseValueIn); + void InitializeAttribute(UAFAbilityComponent* InComponent, const FName InAttributeName); + void CopyFromOther(FAFAttributeBase* Other); + /* You should never use those tree function to set attributes. + Only use them for testing/debugging and setting initial values for attributes. */ + inline void SetBaseValue(float ValueIn) { BaseValue = ValueIn; } + inline void SetMinValue(float ValueIn) { MinValue = ValueIn; } + inline void SetMaxValue(float ValueIn) { MaxValue = ValueIn; } + //used internally. NEver call it directly. + inline void SetCurrentValue(float ValueIn) { CurrentValue = ValueIn; } + + /* + Gets current absolute maximum of value of the attribute. + BaseValue + BonusValue, clamped by MaxValue. + */ + inline float GetFinalValue() + { + return FMath::Clamp(BaseValue + BaseBonusValue, MinValue, MaxValue); + }; + inline float GetCurrentValue() { return CurrentValue; }; + void CalculateBonus(); + bool CheckIfStronger(const FGAEffectMod& InMod); + float Modify(const FGAEffectMod& ModIn, const FGAEffectHandle& HandleIn, FGAEffectProperty& InProperty, const FGAEffectContext& InContext); + void AddBonus(const FGAEffectMod& ModIn, const FGAEffectHandle& Handle); + void RemoveBonus(const FGAEffectHandle& Handle, EGAAttributeMod InMod); + void SetExtensionClass(TSubclassOf InExtensionClass) { ExtensionClass = InExtensionClass; }; +}; +template<> +struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithCopy = false + }; +}; +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAModifiedAttribute +{ + GENERATED_USTRUCT_BODY() +public: + /** + * Always increment it, to make sure it will replicate. + */ + UPROPERTY() + int8 ReplicationCounter; + + /** + * Attribute we have modified. + */ + UPROPERTY() + FGAAttribute Attribute; + + /** + * Final value by which we modified attribute. + */ + UPROPERTY(BlueprintReadOnly, Category = "UI") + float ModifiedByValue; + + /** + * Final tags appiled by this change. + */ + UPROPERTY() + FGameplayTagContainer Tags; + + UPROPERTY(BlueprintReadOnly, Category = "UI") + FVector TargetLocation; //change to vector, we need only position. + UPROPERTY(BlueprintReadOnly, Category = "UI") + FVector InstigatorLocation; + + UPROPERTY() + TWeakObjectPtr Causer; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributeExtension.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributeExtension.h new file mode 100644 index 0000000..69cd535 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributeExtension.h @@ -0,0 +1,30 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "UObject/NoExportTypes.h" +#include "../GAGlobalTypes.h" +#include "GAAttributeExtension.generated.h" + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UGAAttributeExtension : public UObject +{ + GENERATED_BODY() +public: + UPROPERTY() + FGAAttribute Attribute; + + void OnPreAttributeModify(class UAFAbilityComponent* InComp, const FGAAttribute& Attribute, float InValue); + void OnPostAttributeModify(class UAFAbilityComponent* InComp, const FGAAttribute& Attribute, float InValue); + + virtual void PreAttributeModify(const FGAEffectContext& InContext, float PreValue) {}; + virtual void PostAttributeModify(const FGAEffectContext& InContext, float PreValue, float PostValue) {}; + + virtual float CalculateBonusValueByTags(const FGAIndividualMods& Mods) { return 0; } + virtual float CalculateCurentValue() { return 0; } + virtual bool CanModifyAttribute() { return true; } + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributeGlobals.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributeGlobals.h new file mode 100644 index 0000000..e82dfdf --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributeGlobals.h @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "Engine/NetSerialization.h" +#include "GameplayTags.h" +#include "GAAttributeGlobals.generated.h" +/** + * + */ + +USTRUCT() +struct FDumbStruct +{ + GENERATED_BODY() +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributesBase.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributesBase.h new file mode 100644 index 0000000..6181b02 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributesBase.h @@ -0,0 +1,160 @@ +#pragma once +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "UObject/Object.h" +#include "UObject/Class.h" +#include "Templates/SubclassOf.h" +#include "UObject/UnrealType.h" +#include "UObject/CoreNet.h" +#include "../Effects/GAGameEffect.h" +#include "../GAGlobalTypes.h" +#include "GAAttributeBase.h" +#include "GAAttributesBase.generated.h" + +/* + What I need. + Easy way to create Targeted modifications. + For Example, we have ability Fireball, which have cast time 3s, and recharge time 5 seconds. + Targeted modification, will only affect this one ability! + + So we want attribute which will decrease recharge time of this ability by 2 seconds (or decrease recharge time by 25% + or increase recharge speed). How to do it ? + + Path of least resistance is to create special object, which will be instanced, which will listen for abilities + which are activated, and you can cast to your particular ability (or check for tags), and just modify it's + properties directly. + + Second way, (??) would be to create small objects, contained within array (structs), which would do the same thing. + Except they would only be able to catch something like ability activation by tag. They wouldn't know, what kind of + properties are on ability. + + The ability in this case would be needed to be treated as source of incoming attribute, and that object would check + for this attribute and modify it. + Well kind of. + + The same problems exist for any kind of abilities more broad (like Hex), more narrow (only Necromancer Hex), + or for weapons (we want to increase fire rate, if you have equiped machine gun). + + Though on the very base level attribute system have no idea, what kind of properties you might have on + your machine gun. + + + This bring us to the core issue. How to create system like Traits/Feats/Talents, which can contain + myriads of possible combinations of those tree systems. We would need to mix some instanced/non-instanced UObjects + along with plain structs. Which is probabaly going to be total mess. +*/ +UCLASS(BlueprintType, Blueprintable, DefaultToInstanced, EditInlineNew) +class ABILITYFRAMEWORK_API UGAAttributesBase : public UObject +{ + GENERATED_BODY() +public: + + UPROPERTY(EditAnywhere, BlueprintReadOnly, meta=(ExposeOnSpawn)) + UDataTable* AttributeValues; + UGAAttributesBase(const FObjectInitializer& ObjectInitializer); + ~UGAAttributesBase(); + //virtual void PostNetReceive() override; + virtual void InitializeAttributes(UAFAbilityComponent* InOwningAttributeComp); + void CopyFromOtherAttributes(UGAAttributesBase* Other); + + /* + Copy attributes from arbitrary struct. + Struct must be composed from FAFAttributeBase (or it's derivative) fields. + */ + void CopyFromStruct(UStruct* StructType, void* StructObject); + void InitializeAttributesFromTable(); + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "Initialize Attributes")) + bool BP_InitializeAttributes(); + /* + Updates attributes. + @param AttributeIn - attribute which changed value. + + You can use this function to update other attributes (for example derived ones), + based on the primary attribute, if the primary attribute (AttributeIn), changed. + + I have yet to fully figure out how do I want it to work. But one thing for certain is + that it must be fully functional from within blueprint. + */ + UPROPERTY(Replicated) + class UAFAbilityComponent* OwningAttributeComp; +protected: + UProperty* FindProperty(const FGAAttribute& AttributeIn); + +public: + /* + Ticked called from owning component. + */ + virtual void Tick(float DeltaTime);// {}; + /* + Helper C++ functions. Shouldn't ever be exposed or called from blueprint. Also never + try to override them. + + probabaly could also add support for int32 values. + */ + UStructProperty* GetStructAttribute(const FGAAttribute& Name); + /* + Gets pointer to compelx attribute. + */ + FAFAttributeBase* GetAttribute(const FGAAttribute& Name); + /* + Deprecated. I'm going to remove it, since it does not work as intended! + */ + void SetAttribute(const FGAAttribute& NameIn, UObject* NewVal); + + void SetAttributeAdditiveBonus(const FGAAttribute& NameIn, float NewValue); + + /* + Gets value from complex attribute (FAFAttributeBase). + */ + float GetFinalAttributeValue(const FGAAttribute& Name); + float GetCurrentAttributeValue(const FGAAttribute& Name); + + float GetFloatValue(const FGAAttribute& AttributeIn); + float SetFloatValue(const FGAAttribute& AttributeIn, float ValueIn); + float AttributeOperation(const FGAAttribute& AttributeIn, float ValueIn, EGAAttributeMod Operation); + + bool IsNameStableForNetworking() const override; + + bool IsSupportedForNetworking() const override + { + return true; + } + void SetNetAddressable(); + + void ModifyAttribute(const FGAEffect& EffectIn); + float ModifyAttribute(const FGAEffectMod& ModIn + , const FGAEffectHandle& HandleIn + , FGAEffectProperty& InProperty + , const FGAEffectContext& InContext); + void RemoveBonus(FGAAttribute AttributeIn, const FGAEffectHandle& HandleIn, EGAAttributeMod InMod); +protected: + bool bNetAddressable; + +private: + TArray TickableAttributes; + UProperty* LastAttributeProp; + FName LastAttributeName; + // cached numeric property. WEll we probabaly don't need UProperty cache then.. + UNumericProperty* CachedFloatPropety; + + float AddAttributeFloat(float ValueA, float ValueB); + float SubtractAttributeFloat(float ValueA, float ValueB); + float MultiplyAttributeFloat(float ValueA, float ValueB); + float DivideAttributeFloat(float ValueA, float ValueB); + + void OnAttributeModified(const FGAEffectMod& InMod, const FGAEffectHandle& InHandle); +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFAttributesProperty +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere) + TSubclassOf Attributes; + /* + If set, any values in Attributes will be overriden by table. + */ + UPROPERTY(EditAnywhere, BlueprintReadOnly) + UDataTable* AttributeValues; +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributesBlueprintFunctionLibrary.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributesBlueprintFunctionLibrary.h new file mode 100644 index 0000000..6a9cf15 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributesBlueprintFunctionLibrary.h @@ -0,0 +1,58 @@ +#pragma once +#include "../GAGlobalTypes.h" +#include "GAGameEffect.h" +#include "GAAttributesBlueprintFunctionLibrary.generated.h" +/* + Some static helper functions, to interact with Attribute system. +*/ +UCLASS() +class ABILITYFRAMEWORK_API UGAAttributesBlueprintFunctionLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_UCLASS_BODY() +public: + UFUNCTION(BlueprintPure, meta=(DisplayName="Equal"), Category = "AbilityFramework|Attributes") + static bool EqualAttribute(const FGAAttribute& Compare, FGAAttribute Against); + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + static FName GetAttribute(FGAAttribute AttributeIn); + + UFUNCTION(BlueprintPure, Category = "AbilityFramework|Attributes") + static float GetFinalAttributeValue(AActor* Target, FGAAttribute Name); + + UFUNCTION(BlueprintPure, Category = "AbilityFramework|Attributes") + static float GetCurrentAttributeValue(AActor* Target, FGAAttribute Name); + + /** + * Takes actor, and return value of specified attribute. + * + * @param Target - Actrom from which take attribute + * @param AttributeIn - Attribute from which we want to get value + * + * @return value of attribute from actor. + */ + UFUNCTION(BlueprintPure, Category = "AbilityFramework|Attributes") + static float GetAttributeFloat(AActor* Target, FGAAttribute AttributeIn); + /** + * Subtracts value specified by From effect + * and adds it by effect specified by To. + * + * @param Instigator - Who Insigated effects. + * @param Causer - Who Caused Effects + * @param From - effect which will subtract Value + * @param FromTarget - from whose attributes value will be subtracted + * @param To - Effect specifing where attribute should be added. + * @param ToTarget - Target to which attributes will be added. + * + * @return value of attribute from actor. + */ + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + static void ExchangeAttributesValues( + APawn* Instigator + , UObject* Causer + , FAFPropertytHandle From + , FGAEffectHandle FromHandle + , UObject* FromTarget + , FAFPropertytHandle To + , FGAEffectHandle ToHandle + , UObject* ToTarget); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributesStats.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributesStats.h new file mode 100644 index 0000000..3f59c93 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Attributes/GAAttributesStats.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Cues/AFCueStaticBlueprint.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Cues/AFCueStaticBlueprint.h new file mode 100644 index 0000000..8c4107b --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Cues/AFCueStaticBlueprint.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/Blueprint.h" +#include "AFCueStaticBlueprint.generated.h" + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFCueStaticBlueprint : public UBlueprint +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Cues/AFCueStaticGeneratedClass.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Cues/AFCueStaticGeneratedClass.h new file mode 100644 index 0000000..acf4b4d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Cues/AFCueStaticGeneratedClass.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/BlueprintGeneratedClass.h" +#include "AFCueStaticGeneratedClass.generated.h" + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFCueStaticGeneratedClass : public UBlueprintGeneratedClass +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueActor.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueActor.h new file mode 100644 index 0000000..8ca29c0 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueActor.h @@ -0,0 +1,85 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GameFramework/Actor.h" +#include "MovieSceneSequencePlayer.h" +#include "GAGlobalTypes.h" +#include "GameplayTags.h" +#include "AssetBundleData.h" +#include "Engine/AssetManager.h" +#include "AFCueActor.generated.h" +class UActorSequencePlayer; +UCLASS() +class ABILITYFRAMEWORK_API AAFCueActor : public AActor +{ + GENERATED_BODY() +protected: + UPROPERTY(EditAnywhere, Category = "Cue") + FGameplayTag CueTag; + UPROPERTY(AssetRegistrySearchable) + FName EffectCueTagSearch; + UPROPERTY() + FAssetBundleData AssetBundleData; +public: + // Sets default values for this actor's properties + AAFCueActor(const FObjectInitializer& ObjectInitializer); + void PostInitProperties() override; + + void Serialize(FArchive& Ar) override; + +#if WITH_EDITORONLY_DATA + void UpdateAssetBundleData(); + void PreSave(const class ITargetPlatform* TargetPlatform) override; +#endif //WITH_EDITORONLY_DATA + void PostLoad() override; + FPrimaryAssetId GetPrimaryAssetId() const override; + // Called when the game starts or when spawned + virtual void BeginPlay() override; + + // Called every frame + virtual void Tick( float DeltaSeconds ) override; + + + UFUNCTION(BlueprintImplementableEvent) + void BeginCue(AActor* InstigatorOut, AActor* TargetOut, UObject* Causer, + const FHitResult& HitInfo); + + UFUNCTION(BlueprintImplementableEvent) + void OnExecuted(); + + UFUNCTION(BlueprintImplementableEvent) + void OnExpired(); + + UFUNCTION(BlueprintImplementableEvent) + void OnRemoved(); + + void NativeBeginCue(AActor* InstigatorOut, AActor* TargetOut, UObject* Causer, + const FHitResult& HitInfo, const FGAEffectCueParams& CueParams); + + void NativeOnExecuted(); + void NativeOnRemoved(); + UPROPERTY() + float Duration; + UPROPERTY() + float Period; + + void SetAnimation(class UGAEffectCueSequence* InSequence); + UPROPERTY() + double StartTime; + UPROPERTY() + double EndTime; + /** Animation being played */ + UPROPERTY(EditAnywhere, Instanced, Export, Category = Animation) + UGAEffectCueSequence* Sequence; + UPROPERTY(transient, BlueprintReadOnly, Category = Animation) + UActorSequencePlayer* SequencePlayer; + + UPROPERTY(EditAnywhere, Category = "Playback", meta = (ShowOnlyInnerProperties)) + FMovieSceneSequencePlaybackSettings PlaybackSettings; + + FTimerHandle PeriodTimer; + +protected: + void UpdateAssetRegistryInfo(); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueActorBlueprint.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueActorBlueprint.h new file mode 100644 index 0000000..e850f2c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueActorBlueprint.h @@ -0,0 +1,32 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Engine/Blueprint.h" +#include "AFCueActorBlueprint.generated.h" + +/** + * Game Effect Blueprint + */ + +UCLASS(BlueprintType) +class ABILITYFRAMEWORK_API UAFCueActorBlueprint : public UBlueprint +{ + GENERATED_UCLASS_BODY() +UPROPERTY() + class UGAEffectCueSequence* Animation; +#if WITH_EDITOR + + // UBlueprint interface + virtual bool SupportedByDefaultBlueprintFactory() const override + { + return false; + } + // End of UBlueprint interface + + /** Returns the most base gameplay ability blueprint for a given blueprint (if it is inherited from another ability blueprint, returning null if only native / non-ability BP classes are it's parent) */ + static UAFCueActorBlueprint* FindRootGameplayAbilityBlueprint(UAFCueActorBlueprint* DerivedBlueprint); + +#endif +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueActorGeneratedClass.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueActorGeneratedClass.h new file mode 100644 index 0000000..4ae2d26 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueActorGeneratedClass.h @@ -0,0 +1,17 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Engine/BlueprintGeneratedClass.h" +#include "AFCueActorGeneratedClass.generated.h" + +/** + * Game Effect Blueprint + */ + +UCLASS(BlueprintType) +class ABILITYFRAMEWORK_API UAFCueActorGeneratedClass : public UBlueprintGeneratedClass +{ + GENERATED_UCLASS_BODY() +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueStatic.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueStatic.h new file mode 100644 index 0000000..8fbd33f --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFCueStatic.h @@ -0,0 +1,61 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameplayTags.h" +#include "AssetBundleData.h" +#include "UObject/NoExportTypes.h" +#include "GAGlobalTypes.h" +#include "AFCueStatic.generated.h" + +/** + * An Non instanced Cue, where only CDO is used to execute it. + * They cannot have state or modify any external state. + */ +UCLASS(BlueprintType, Blueprintable, meta=(ShowWorldContextPin)) +class ABILITYFRAMEWORK_API UAFCueStatic : public UObject +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Category = "Cue") + FGameplayTag CueTag; + UPROPERTY(AssetRegistrySearchable) + FName EffectCueTagSearch; + UPROPERTY() + FAssetBundleData AssetBundleData; +public: + // Sets default values for this actor's properties + UAFCueStatic(const FObjectInitializer& ObjectInitializer); + void PostInitProperties() override; + + void Serialize(FArchive& Ar) override; + +#if WITH_EDITORONLY_DATA + void UpdateAssetBundleData(); + void PreSave(const class ITargetPlatform* TargetPlatform) override; +#endif //WITH_EDITORONLY_DATA + void PostLoad() override; + FPrimaryAssetId GetPrimaryAssetId() const override; +protected: + void UpdateAssetRegistryInfo(); + +public: + UFUNCTION(BlueprintNativeEvent, Category = "Ability Framework|Cues") + bool OnExecuted(const FGAEffectCueParams& Hit); + virtual bool OnExecuted_Implementation(const FGAEffectCueParams& Hit) const; + + UFUNCTION(BlueprintNativeEvent, Category = "Ability Framework|Cues") + void OnActivate(const FGAEffectCueParams& Hit) const; + virtual void OnActivate_Implementation(const FGAEffectCueParams& Hit) const; + + UFUNCTION(BlueprintNativeEvent, Category = "Ability Framework|Cues") + void OnExpire(const FGAEffectCueParams& Hit) const; + virtual void OnExpire_Implementation(const FGAEffectCueParams& Hit) const; + + UFUNCTION(BlueprintNativeEvent, Category = "Ability Framework|Cues") + void OnRemoved(const FGAEffectCueParams& Hit) const; + virtual void OnRemoved_Implementation(const FGAEffectCueParams& Hit) const; + + UWorld* GetWorld() const override; +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectApplicationRequirement.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectApplicationRequirement.h new file mode 100644 index 0000000..3225e76 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectApplicationRequirement.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "../GAGlobalTypes.h" +#include "GAGameEffect.h" +#include "AFEffectApplicationRequirement.generated.h" + +/** + * Default requirment always passes. + */ +UCLASS(meta=(DisplayName = "No Requirement")) +class ABILITYFRAMEWORK_API UAFEffectApplicationRequirement : public UObject +{ + GENERATED_BODY() + +public: + virtual bool CanApply( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FGAEffectHandle& InHandle + , struct FGAEffectContainer* InContainer) + { + return true; + } + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectCustomApplication.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectCustomApplication.h new file mode 100644 index 0000000..24fd308 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectCustomApplication.h @@ -0,0 +1,44 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "../GAGlobalTypes.h" +#include "GAGameEffect.h" +#include "AFEffectCustomApplication.generated.h" + +/** + * Default application used for instant effects. + */ +UCLASS(meta = (DisplayName = "Default Application")) +class ABILITYFRAMEWORK_API UAFEffectCustomApplication : public UObject +{ + GENERATED_BODY() +public: + virtual bool ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + virtual void ApplyExecute( + const FGAEffectHandle& InHandle + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + virtual bool CanApply(class IAFAbilityInterface* Target, TSubclassOf EffectClass) + { + return true; + } + + virtual bool ShowPeriod() + { + return false; + } + virtual bool ShowDuration() + { + return false; + } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectCustomStackingRule.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectCustomStackingRule.h new file mode 100644 index 0000000..ba364d2 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectCustomStackingRule.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "../GAGlobalTypes.h" +#include "AFEffectCustomStackingRule.generated.h" + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFEffectCustomStackingRule : public UObject +{ + GENERATED_BODY() + +public: + virtual bool CanStack(class UAFAbilityComponent* InComp, struct FGAEffectContainer* InContainer, + const FGAEffectHandle& InHandle); + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectSpecFunctionLibrary.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectSpecFunctionLibrary.h new file mode 100644 index 0000000..7a9aa21 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/AFEffectSpecFunctionLibrary.h @@ -0,0 +1,57 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Effects/GAGameEffect.h" +#include "AFEffectSpecFunctionLibrary.generated.h" +UENUM(BlueprintType) +enum class EAFTagCompareResult : uint8 +{ + Match, + NoMatch, +}; +UENUM() +enum class EAFTagContainerCompare : uint8 +{ + HasAny, + HasAnyExact, + HasAll, + HasAllExact, +}; + +UENUM() +enum class EAFTagCompare : uint8 +{ + HasTag, + HasTagExact +}; + + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFEffectSpecFunctionLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects|Spec") + static void AppendOwnedTags(FAFEffectSpecHandle Spec, const FGameplayTagContainer& InTags); + + + UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Result"), Category = "AbilityFramework|Effects|Spec") + static void CompareOwnedTags(FAFEffectSpecHandle Spec + , EAFTagContainerCompare Mode + , const FGameplayTagContainer& InTags + , EAFTagCompareResult& Result); + + + UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Result"), Category = "AbilityFramework|Effects|Spec") + static void CompareOwnedTag(FAFEffectSpecHandle Spec + , EAFTagCompare Mode + , FGameplayTag InTag + , EAFTagCompareResult& Result); + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/ApplicationRequirement/AFAttributeStongerOverride.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/ApplicationRequirement/AFAttributeStongerOverride.h new file mode 100644 index 0000000..f2e18f5 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/ApplicationRequirement/AFAttributeStongerOverride.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectApplicationRequirement.h" +#include "AFAttributeStongerOverride.generated.h" + +/** + * USe only with Duration Based application. + * Effect will be applied if the attribute modifier is stronger than the current one on Attribute. + */ +UCLASS(BlueprintType, meta = (DisplayName = "Attribute Stronger")) +class ABILITYFRAMEWORK_API UAFAttributeStongerOverride : public UAFEffectApplicationRequirement +{ + GENERATED_BODY() +public: + virtual bool CanApply( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FGAEffectHandle& InHandle + , struct FGAEffectContainer* InContainer) override; + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/ApplicationRequirement/AFEffectAlreadyApplied.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/ApplicationRequirement/AFEffectAlreadyApplied.h new file mode 100644 index 0000000..13b21b5 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/ApplicationRequirement/AFEffectAlreadyApplied.h @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectApplicationRequirement.h" +#include "AFEffectAlreadyApplied.generated.h" + +/** + * If effect of the same type is already applied, it will be skipped. + */ +UCLASS(meta = (DisplayName = "Only One Of Type")) +class ABILITYFRAMEWORK_API UAFEffectAlreadyApplied : public UAFEffectApplicationRequirement +{ + GENERATED_BODY() +public: + virtual bool CanApply( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FGAEffectHandle& InHandle + , struct FGAEffectContainer* InContainer) override; + + + + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAtributeDurationAdd.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAtributeDurationAdd.h new file mode 100644 index 0000000..04eca4b --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAtributeDurationAdd.h @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFAtributeDurationAdd.generated.h" + +/** + * Adds New duration Effect. + */ +UCLASS(meta = (DisplayName = "Duration Add")) +class ABILITYFRAMEWORK_API UAFAtributeDurationAdd : public UAFEffectCustomApplication +{ + GENERATED_BODY() +public: + virtual bool ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + virtual bool ShowPeriod() override + { + return false; + } + virtual bool ShowDuration() override + { + return true; + } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAtributeDurationUnique.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAtributeDurationUnique.h new file mode 100644 index 0000000..be69075 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAtributeDurationUnique.h @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFAtributeDurationUnique.generated.h" + +/** + * Adds New Unique duration Effect. If effect of the same class is already applied to target, new effect will be ignored. + */ +UCLASS(meta = (DisplayName = "Duration Add Unique")) +class ABILITYFRAMEWORK_API UAFAtributeDurationUnique : public UAFEffectCustomApplication +{ + GENERATED_BODY() +public: + virtual bool ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + virtual bool CanApply(class IAFAbilityInterface* Target, TSubclassOf EffectClass) override; + + virtual bool ShowPeriod() override + { + return false; + } + virtual bool ShowDuration() override + { + return true; + } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAttributeDurationInfinite.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAttributeDurationInfinite.h new file mode 100644 index 0000000..7707eda --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAttributeDurationInfinite.h @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFAttributeDurationInfinite.generated.h" + +/** + * Adds infinite duration effect. + */ +UCLASS(meta = (DisplayName = "Duration Infinite Add")) +class ABILITYFRAMEWORK_API UAFAttributeDurationInfinite : public UAFEffectCustomApplication +{ + GENERATED_BODY() +public: + virtual bool ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + virtual bool ShowPeriod() override + { + return false; + } + virtual bool ShowDuration() override + { + return false; + } + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAttributeDurationOverride.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAttributeDurationOverride.h new file mode 100644 index 0000000..158d374 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFAttributeDurationOverride.h @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFAttributeDurationOverride.generated.h" + +/** + * If effect of the same class is already applied it will be removed, and new one will be applied. + */ +UCLASS(meta = (DisplayName = "Duration Override")) +class ABILITYFRAMEWORK_API UAFAttributeDurationOverride : public UAFEffectCustomApplication +{ + GENERATED_BODY() +public: + virtual bool ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + + virtual bool ShowPeriod() override + { + return false; + } + virtual bool ShowDuration() override + { + return true; + } + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationAdd.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationAdd.h new file mode 100644 index 0000000..00a1e2a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationAdd.h @@ -0,0 +1,39 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFPeriodApplicationAdd.generated.h" + +/** + * Adds new periodic effect. + */ +UCLASS(meta = (DisplayName = "Periodic Add")) +class ABILITYFRAMEWORK_API UAFPeriodApplicationAdd : public UAFEffectCustomApplication +{ + GENERATED_BODY() +public: + bool ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()) override; + + virtual void ExecuteEffect( + const FGAEffectHandle& InHandle + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()) + {}; + + virtual bool ShowPeriod() override + { + return true; + } + virtual bool ShowDuration() override + { + return true; + } + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationExtend.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationExtend.h new file mode 100644 index 0000000..e5efa4e --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationExtend.h @@ -0,0 +1,39 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFPeriodApplicationExtend.generated.h" + +/** + * If periodic effect of the same class already exists it duration will be extended. If not new effect + * will be applied. + */ +UCLASS(meta = (DisplayName = "Periodic Extend")) +class ABILITYFRAMEWORK_API UAFPeriodApplicationExtend : public UAFEffectCustomApplication +{ + GENERATED_BODY() + +public: + virtual bool ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + virtual void ExecuteEffect( + const FGAEffectHandle& InHandle + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()) + {}; + virtual bool ShowPeriod() override + { + return true; + } + virtual bool ShowDuration() override + { + return true; + } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationInfiniteAdd.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationInfiniteAdd.h new file mode 100644 index 0000000..745850a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationInfiniteAdd.h @@ -0,0 +1,39 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFPeriodApplicationInfiniteAdd.generated.h" + +/** + * Periodic effect will be applied for infinite amount of time. + */ +UCLASS(meta = (DisplayName = "Periodic Infinite Add")) +class ABILITYFRAMEWORK_API UAFPeriodApplicationInfiniteAdd : public UAFEffectCustomApplication +{ + GENERATED_BODY() +public: + virtual bool ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + virtual void ExecuteEffect( + const FGAEffectHandle& InHandle + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()) + {}; + + virtual bool ShowPeriod() override + { + return true; + } + virtual bool ShowDuration() override + { + return false; + } + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationOverride.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationOverride.h new file mode 100644 index 0000000..6f7e271 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodApplicationOverride.h @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFPeriodApplicationOverride.generated.h" + +/** + * If effect of the same class already exist it will be removed and new effect will be appllied. + */ +UCLASS(meta = (DisplayName = "Periodic Override")) +class ABILITYFRAMEWORK_API UAFPeriodApplicationOverride : public UAFEffectCustomApplication +{ + GENERATED_BODY() +public: + virtual bool ApplyEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + virtual void ExecuteEffect( + const FGAEffectHandle& InHandle + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()) + {}; + virtual bool ShowPeriod() override + { + return true; + } + virtual bool ShowDuration() override + { + return true; + } + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodicApplInfiniteOverride.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodicApplInfiniteOverride.h new file mode 100644 index 0000000..8d613d5 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/CustomApplications/AFPeriodicApplInfiniteOverride.h @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFPeriodicApplInfiniteOverride.generated.h" + +/** + * Adds infinite periodic effect. If effect of the same class already exists, it will be removed first. + */ +UCLASS(meta=(DisplayName = "Periodic Infinite Override")) +class ABILITYFRAMEWORK_API UAFPeriodicApplInfiniteOverride : public UAFEffectCustomApplication +{ + GENERATED_BODY() + + + virtual void ExecuteEffect( + const FGAEffectHandle& InHandle + , const FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()) + {}; + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask.h new file mode 100644 index 0000000..67a5429 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask.h @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "LatentActions/AFTaskBase.h" +#include "GAEffectExtension.h" +#include "GAGlobalTypes.h" +#include "AFAbilityComponent.h" +#include "AFEffectTask.generated.h" + +/** + * + */ +UCLASS(BlueprintType, meta = (ExposedAsyncProxy = "true") ) +class ABILITYFRAMEWORK_API UAFEffectTask : public UAFTaskBase +{ + GENERATED_BODY() +public: + UPROPERTY() + class UGAEffectExtension* Effect; + UPROPERTY() + class UAFEffectsComponent* EffectsComponent; + +public: + template + static T* NewEffectTask(UGAEffectExtension* WorldContextObject, FName InTaskName = FName(), FName InstanceName = FName()) + { + T* MyObj = nullptr; + UGAEffectExtension* EffectExtension = WorldContextObject; + MyObj = NewTask(WorldContextObject, WorldContextObject, InTaskName); + + MyObj->Effect = EffectExtension; + MyObj->EffectsComponent = EffectExtension->OwningComponent; + + return MyObj; + } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_AppliedEffectEvent.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_AppliedEffectEvent.h new file mode 100644 index 0000000..3393112 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_AppliedEffectEvent.h @@ -0,0 +1,49 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/EffectTasks/AFEffectTask.h" +#include "../../GAGlobalTypes.h" +#include "AFEffectTask_AppliedEffectEvent.generated.h" + + + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFEffectTask_AppliedEffectEvent : public UAFEffectTask +{ + GENERATED_BODY() +public: + DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAFEffectEventDelegate, FAFEventData, Payload); + UPROPERTY(BlueprintAssignable) + FAFEffectEventDelegate OnEvent; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects|Tasks", meta = (HidePin = "OwningExtension", DefaultToSelf = "OwningExtension", BlueprintInternalUseOnly = "TRUE")) + static UAFEffectTask_AppliedEffectEvent* ListenAppliedEffectEvent(UGAEffectExtension* OwningExtension, FName TaskName, FGameplayTag EventTag, AActor* OptionalExternalTarget = nullptr, bool OnlyTriggerOnce = false); + + UAFEffectTask_AppliedEffectEvent(const FObjectInitializer& ObjectInitializer); + + void SetExternalTarget(AActor* Actor); + + class UAFEffectsComponent* GetTargetASC(); + + virtual void Activate() override; + + virtual void GameplayEventCallback(FAFEventData Payload); + + virtual void OnTaskEnded() override; + + FGameplayTag Tag; + + UPROPERTY() + UAFEffectsComponent* OptionalExternalTarget; + + bool UseExternalTarget; + bool OnlyTriggerOnce; + + FDelegateHandle MyHandle; + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_AttributeChange.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_AttributeChange.h new file mode 100644 index 0000000..1952d19 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_AttributeChange.h @@ -0,0 +1,50 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/EffectTasks/AFEffectTask.h" +#include "AFEffectTask_AttributeChange.generated.h" +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAFTaskAttributeChangedDelegate, FAFAttributeChangedData, Payload); + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFEffectTask_AttributeChange : public UAFEffectTask +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintAssignable) + FAFTaskAttributeChangedDelegate OnEvent; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects|Tasks", meta = (HidePin = "OwningExtension", DefaultToSelf = "OwningExtension", BlueprintInternalUseOnly = "TRUE")) + static UAFEffectTask_AttributeChange* ListenAttributeChanged(UGAEffectExtension* OwningExtension, + FGAAttribute InAttribute, + AActor* OptionalExternalTarget = nullptr, + bool OnlyTriggerOnce = false); + + UAFEffectTask_AttributeChange(const FObjectInitializer& ObjectInitializer); + + void SetExternalTarget(AActor* Actor); + + class UAFEffectsComponent* GetTargetASC(); + + virtual void Activate() override; + + void AttributeChangedCallback(FAFAttributeChangedData Payload); + + FGAAttribute Attribute; + + UPROPERTY() + UAFEffectsComponent* OptionalExternalTarget; + + bool UseExternalTarget; + bool OnlyTriggerOnce; + + FDelegateHandle MyHandle; + + + + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_EffectAppliedToSelf.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_EffectAppliedToSelf.h new file mode 100644 index 0000000..8cb571e --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_EffectAppliedToSelf.h @@ -0,0 +1,50 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/EffectTasks/AFEffectTask.h" +#include "Effects/GAGameEffect.h" +#include "GAGlobalTypes.h" +#include "AFEffectTask_EffectAppliedToSelf.generated.h" + + + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFEffectTask_EffectAppliedToSelf : public UAFEffectTask +{ + GENERATED_BODY() +public: + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FAFEffectEventDelegate, FGAEffectContext, Context, FAFPropertytHandle, Property, FAFEffectSpec, Spec); + UPROPERTY(BlueprintAssignable) + FAFEffectEventDelegate OnEvent; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects|Tasks", meta = (HidePin = "OwningExtension", DefaultToSelf = "OwningExtension", BlueprintInternalUseOnly = "TRUE")) + static UAFEffectTask_EffectAppliedToSelf* ListenEffectAppliedToSelf(UGAEffectExtension* OwningExtension, FName TaskName, AActor* OptionalExternalTarget = nullptr, bool OnlyTriggerOnce = false); + + UAFEffectTask_EffectAppliedToSelf(const FObjectInitializer& ObjectInitializer); + + void SetExternalTarget(AActor* Actor); + + class UAFEffectsComponent* GetTargetASC(); + + virtual void Activate() override; + + virtual void GameplayEventCallback(FGAEffectContext Context + , FAFPropertytHandle Property + , FAFEffectSpec Spec); + + virtual void OnTaskEnded() override; + + UPROPERTY() + UAFEffectsComponent* OptionalExternalTarget; + + bool UseExternalTarget; + bool OnlyTriggerOnce; + + FDelegateHandle MyHandle; + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_EffectAppliedToTarget.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_EffectAppliedToTarget.h new file mode 100644 index 0000000..31fb999 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_EffectAppliedToTarget.h @@ -0,0 +1,50 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/EffectTasks/AFEffectTask.h" +#include "Effects/GAGameEffect.h" +#include "GAGlobalTypes.h" +#include "AFEffectTask_EffectAppliedToTarget.generated.h" + + + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFEffectTask_EffectAppliedToTarget : public UAFEffectTask +{ + GENERATED_BODY() +public: + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FAFEffectEventDelegate, FGAEffectContext, Context, FAFPropertytHandle, Property, FAFEffectSpec, Spec); + UPROPERTY(BlueprintAssignable) + FAFEffectEventDelegate OnEvent; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects|Tasks", meta = (HidePin = "OwningExtension", DefaultToSelf = "OwningExtension", BlueprintInternalUseOnly = "TRUE")) + static UAFEffectTask_EffectAppliedToTarget* ListenEffectAppliedToTarget(UGAEffectExtension* OwningExtension, FName TaskName, AActor* OptionalExternalTarget = nullptr, bool OnlyTriggerOnce = false); + + UAFEffectTask_EffectAppliedToTarget(const FObjectInitializer& ObjectInitializer); + + void SetExternalTarget(AActor* Actor); + + class UAFEffectsComponent* GetTargetASC(); + + virtual void Activate() override; + + virtual void GameplayEventCallback(FGAEffectContext Context + , FAFPropertytHandle Property + , FAFEffectSpec Spec); + + virtual void OnTaskEnded() override; + + UPROPERTY() + UAFEffectsComponent* OptionalExternalTarget; + + bool UseExternalTarget; + bool OnlyTriggerOnce; + + FDelegateHandle MyHandle; + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_EffectEvent.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_EffectEvent.h new file mode 100644 index 0000000..52f79d4 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_EffectEvent.h @@ -0,0 +1,48 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/EffectTasks/AFEffectTask.h" +#include "../../GAGlobalTypes.h" +#include "AFEffectTask_EffectEvent.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAFEffectEventDelegate, FAFEventData, Payload); + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFEffectTask_EffectEvent : public UAFEffectTask +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintAssignable) + FAFEffectEventDelegate OnEvent; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects|Tasks", meta = (HidePin = "OwningExtension", DefaultToSelf = "OwningExtension", BlueprintInternalUseOnly = "TRUE")) + static UAFEffectTask_EffectEvent* ListenEffectEvent(UGAEffectExtension* OwningExtension, FName TaskName, FGameplayTag EventTag, AActor* OptionalExternalTarget = nullptr, bool OnlyTriggerOnce = false); + + UAFEffectTask_EffectEvent(const FObjectInitializer& ObjectInitializer); + + void SetExternalTarget(AActor* Actor); + + class UAFEffectsComponent* GetTargetASC(); + + virtual void Activate() override; + + virtual void GameplayEventCallback(FAFEventData Payload); + + virtual void OnTaskEnded() override; + + FGameplayTag Tag; + + UPROPERTY() + UAFEffectsComponent* OptionalExternalTarget; + + bool UseExternalTarget; + bool OnlyTriggerOnce; + + FDelegateHandle MyHandle; + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_ExecutedEffectEvent.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_ExecutedEffectEvent.h new file mode 100644 index 0000000..c4253e3 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/EffectTasks/AFEffectTask_ExecutedEffectEvent.h @@ -0,0 +1,49 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/EffectTasks/AFEffectTask.h" +#include "../../GAGlobalTypes.h" +#include "AFEffectTask_ExecutedEffectEvent.generated.h" + + + +/** + * + */ +UCLASS() +class ABILITYFRAMEWORK_API UAFEffectTask_ExecutedEffectEvent : public UAFEffectTask +{ + GENERATED_BODY() +public: + DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAFEffectEventDelegate, FAFEventData, Payload); + UPROPERTY(BlueprintAssignable) + FAFEffectEventDelegate OnEvent; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects|Tasks", meta = (HidePin = "OwningExtension", DefaultToSelf = "OwningExtension", BlueprintInternalUseOnly = "TRUE")) + static UAFEffectTask_ExecutedEffectEvent* ListenExecutedEffectEvent(UGAEffectExtension* OwningExtension, FName TaskName, FGameplayTag EventTag, AActor* OptionalExternalTarget = nullptr, bool OnlyTriggerOnce = false); + + UAFEffectTask_ExecutedEffectEvent(const FObjectInitializer& ObjectInitializer); + + void SetExternalTarget(AActor* Actor); + + class UAFEffectsComponent* GetTargetASC(); + + virtual void Activate() override; + + virtual void GameplayEventCallback(FAFEventData Payload); + + virtual void OnTaskEnded() override; + + FGameplayTag Tag; + + UPROPERTY() + UAFEffectsComponent* OptionalExternalTarget; + + bool UseExternalTarget; + bool OnlyTriggerOnce; + + FDelegateHandle MyHandle; + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GABlueprintLibrary.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GABlueprintLibrary.h new file mode 100644 index 0000000..8285465 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GABlueprintLibrary.h @@ -0,0 +1,143 @@ +#pragma once +#include "Effects/GAGameEffect.h" +#include "GAGlobalTypes.h" +#include "Attributes/GAAttributeBase.h" +#include "GAEffectGlobalTypes.h" +#include "GABlueprintLibrary.generated.h" + +UCLASS(BlueprintType, Blueprintable) +class ABILITYFRAMEWORK_API UGABlueprintLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_UCLASS_BODY() +public: + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects") + static TArray ApplyGameEffectToObject( + UPARAM(Ref) FAFPropertytHandle& InEffect + , class UObject* Target + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier); + + /* + Makes outgoing effect spec and assign handle to it. + If valid handle is provided it will instead reuse existing effect spec from handle, + and just change context of effect. + */ + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects") + static TArray ApplyGameEffectToActor( + UPARAM(Ref) FAFPropertytHandle& InEffect + , class AActor* Target + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier); + + /* + Makes outgoing effect spec and assign handle to it. + If valid handle is provided it will instead reuse existing effect spec from handle, + and just change context of effect. + */ + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects") + static TArray ApplyGameEffectToLocation( + UPARAM(Ref) FAFPropertytHandle& InEffect + , const FHitResult& Target + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier); + + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects") + static TArray ApplyGameEffectToObjects( + UPARAM(Ref) FAFPropertytHandle& InEffect + , TArray Targets + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier); + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects") + static TArray ApplyGameEffectToActors( + UPARAM(Ref) FAFPropertytHandle& InEffect + , TArray Targets + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier); + + /* + Makes outgoing effect spec and assign handle to it. + If valid handle is provided it will instead reuse existing effect spec from handle, + and just change context of effect. + */ + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects") + static TArray ApplyGameEffectToTargets( + UPARAM(Ref) FAFPropertytHandle& InEffect + , const TArray& Targets + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier); + + + static TArray ApplyEffect( + FAFPropertytHandle& InEffect + , TArray Targets + , class APawn* Instigator + , UObject* Causer + , const TArray& HitsIn + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + static TArray ApplyEffectFromHit( + FAFPropertytHandle& InEffect + , const TArray& Targets + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier); + + static TArray ApplyEffectToActor( + FAFPropertytHandle& InEffect + , TArray Targets + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier); + + static TArray ApplyEffectToObject( + FAFPropertytHandle& InEffect + , TArray Targets + , class APawn* Instigator + , UObject* Causer + , const FAFFunctionModifier& Modifier); + /* + Create Effect but does not apply it. + */ + + static FAFContextHandle MakeContext(class UObject* Target, class APawn* Instigator, AActor* InAvatar, + UObject* Causer, const FHitResult& HitIn); + static void AddTagsToEffect(FAFEffectSpec* EffectIn); + + UFUNCTION(BlueprintPure, Category = "AbilityFramework|Effects") + static FGAEffectContext& GetContext(const FAFContextHandle& InHandle); + + UFUNCTION(BlueprintPure, Category = "AbilityFramework|Effects") + static UAFAbilityComponent* GetTargetComponent(const FGAEffectHandle& InHandle); + + UFUNCTION(BlueprintPure, Category = "AbilityFramework|Effects") + static UAFAbilityComponent* GetInstigatorComponent(const FGAEffectHandle& InHandle); + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects") + static void BroadcastEffectEvent(UObject* Target, FGameplayTag EventTag); + + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects") + static void CreateEffectSpec(UPARAM(Ref) FAFEffectSpecHandle& InOutSpec + , const FAFPropertytHandle& InEffect + , class UObject* Target + , class APawn* Instigator + , UObject* Causer); + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects") + static void ApplyEffectFromSpec(UPARAM(Ref) FAFPropertytHandle& InEffect, UPARAM(Ref) FAFEffectSpecHandle& InSpec); + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Effects") + static void ModifyAttributeSimple( + UPARAM(Ref) FAFEffectSpecHandle& InSpec + , UObject* Target); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GACustomCalculation.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GACustomCalculation.h new file mode 100644 index 0000000..265264d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GACustomCalculation.h @@ -0,0 +1,30 @@ +#pragma once +#include "../GAGlobalTypes.h" +#include "../GAHelperTemplates.h" +#include "../Attributes/GAAttributeBase.h" +#include "GAGameEffect.h" +#include "GACustomCalculation.generated.h" + +/* + Simple base class for custom magnitude calculation. + You can implement here any kind of formula, taking arbitrary information, for calculations. + + Object is instanced inside effect spec, so you can add custom properties set up, as per + effect spec base. + + Please refrain from making super complicated things, which calculate everything, it's + generally not purpose of this class, but if you really want.. (;. +*/ +UCLASS(BlueprintType, Blueprintable, EditInLineNew) +class ABILITYFRAMEWORK_API UGACustomCalculation : public UObject +{ + GENERATED_BODY() +public: + UGACustomCalculation(const FObjectInitializer& ObjectInitializer); + + //UFUNCTION(BlueprintNativeEvent, Category = "Attributes") + // float CalculateMagnitude(const FGAEffectContext& ContextIn); + + + virtual float NativeCalculateMagnitude(const FGAEffectContext& ContextIn) { return 0; } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectBlueprint.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectBlueprint.h new file mode 100644 index 0000000..953751b --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectBlueprint.h @@ -0,0 +1,31 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Engine/Blueprint.h" +#include "GAEffectBlueprint.generated.h" + +/** + * Game Effect Blueprint + */ + +UCLASS(BlueprintType) +class ABILITYFRAMEWORK_API UGAEffectBlueprint : public UBlueprint +{ + GENERATED_UCLASS_BODY() + +#if WITH_EDITOR + + // UBlueprint interface + virtual bool SupportedByDefaultBlueprintFactory() const override + { + return false; + } + // End of UBlueprint interface + + /** Returns the most base gameplay ability blueprint for a given blueprint (if it is inherited from another ability blueprint, returning null if only native / non-ability BP classes are it's parent) */ + static UGAEffectBlueprint* FindRootGameplayAbilityBlueprint(UGAEffectBlueprint* DerivedBlueprint); + +#endif +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectCueGlobals.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectCueGlobals.h new file mode 100644 index 0000000..bed97a4 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectCueGlobals.h @@ -0,0 +1,26 @@ +#pragma once +#include "GameplayTagContainer.h" +#include "../GAGlobalTypes.h" +#include "GAGameEffect.h" +#include "GAEffectCueGlobals.generated.h" + +USTRUCT() +struct FGACueContainer +{ + GENERATED_USTRUCT_BODY() +public: + TWeakObjectPtr OwningComponent; + + void AddCue(const FGAEffectHandle& HandleIn, const FGAEffectCueParams& CueParamsIn); + + void AddCue(const FGAEffectHandle& HandleIn); + + /* Return cue. Might return null so always check it first! */ + class UGAEffectCue* GetCue(const FGAEffectHandle& HandleIn); + + void ExecuteCue(const FGAEffectHandle& HandleIn); + + void RemoveCue(const FGAEffectHandle& HandleIn); + + void CueExpired(const FGAEffectHandle& HandleIn); +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectCueSequence.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectCueSequence.h new file mode 100644 index 0000000..c61235f --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectCueSequence.h @@ -0,0 +1,69 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "GameFramework/Actor.h" +#include "MovieSceneSequence.h" +#include "MovieScene.h" +#include "LazyObjectPtr.h" +#include "ActorSequence.h" +#include "FrameNumber.h" +#include "GAEffectCueSequence.generated.h" + +UCLASS(BlueprintType, DefaultToInstanced) +class ABILITYFRAMEWORK_API UGAEffectCueSequence : public UMovieSceneSequence +{ + GENERATED_BODY() + +public: + UPROPERTY(Instanced) + UMovieScene* MovieScene; +private: + /** Collection of object references. */ + //UPROPERTY() + // FActorSequenceObjectReferenceMap ObjectReferences; + +#if WITH_EDITORONLY_DATA +private: + bool bHasBeenInitialized; +#endif +public: + // Sets default values for this actor's properties + UGAEffectCueSequence(const FObjectInitializer& ObjectInitializer); + virtual void PostInitProperties() override; +#if WITH_EDITOR + /** + * Get a placeholder animation. + * + * @return Placeholder animation. + */ + static UGAEffectCueSequence* GetNullAnimation(); + + /** Event that is fired to initialize default state for a sequence */ + DECLARE_EVENT_OneParam(UGAEffectCueSequence, FOnInitialize, UGAEffectCueSequence*) + static FOnInitialize OnInitializeSequenceEvent; +public: + static FOnInitialize& OnInitializeSequence() { return OnInitializeSequenceEvent; } + + +#endif +public: + inline UMovieScene* GetMovieScene() { return MovieScene; } + UFUNCTION(BlueprintCallable, Category = "Animation") + FFrameNumber GetStartTime() const; + + /** + * Get the end time of this animation. + * + * @return End time in seconds. + * @see GetStartTime + */ + UFUNCTION(BlueprintCallable, Category = "Animation") + FFrameNumber GetEndTime() const; + virtual void BindPossessableObject(const FGuid& ObjectId, UObject& PossessedObject, UObject* Context) override; + virtual bool CanPossessObject(UObject& Object, UObject* InPlaybackContext) const override; + virtual UMovieScene* GetMovieScene() const override; + virtual UObject* GetParentObject(UObject* Object) const override; + virtual void UnbindPossessableObjects(const FGuid& ObjectId) override; + virtual void LocateBoundObjects(const FGuid& ObjectId, UObject* Context, TArray>& OutObjects) const override; +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectExecution.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectExecution.h new file mode 100644 index 0000000..6b94d56 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectExecution.h @@ -0,0 +1,22 @@ +#pragma once +#include "../GAGlobalTypes.h" +#include "../Attributes/GAAttributeBase.h" +#include "GAGameEffect.h" +#include "GAEffectGlobalTypes.h" +#include "GAEffectExecution.generated.h" + +/* + +*/ +UCLASS(BlueprintType, Blueprintable, EditInLineNew) +class ABILITYFRAMEWORK_API UGAEffectExecution : public UObject +{ + GENERATED_BODY() +public: + UGAEffectExecution(const FObjectInitializer& ObjectInitializer); + + virtual void PreModifyAttribute(const FGAEffectHandle& HandleIn, FGAEffectMod& ModIn, const FGAEffectContext& Context); + virtual void ExecuteEffect(const FGAEffectHandle& HandleIn, FGAEffectMod& ModIn, + const FAFEffectParams& Params, + const FAFFunctionModifier& Modifier = FAFFunctionModifier()); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectExtension.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectExtension.h new file mode 100644 index 0000000..65a33bd --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectExtension.h @@ -0,0 +1,95 @@ +#pragma once +#include "GameplayTagContainer.h" +#include "GAGlobalTypes.h" +#include "GAGameEffect.h" + +#include "LatentActions/AFLatentInterface.h" +#include "GAEffectExtension.generated.h" +/* + Instanced effect with active event graph, where you can bind events + on application. +*/ +UCLASS(BlueprintType, Blueprintable, EditInLineNew) +class ABILITYFRAMEWORK_API UGAEffectExtension : public UObject, public IAFLatentInterface //this interface is not needed, but NewTask is expting those functions. +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintReadOnly, Category = "Context") + FGAEffectContext Context; + + /*Component which actually owns this Effect (Effect Target) */ + UPROPERTY() + class UAFEffectsComponent* OwningComponent; + + /* Component from this effect has originated (Effect Instigator) */ + UPROPERTY() + class UAFEffectsComponent* SourceComponent; + + UPROPERTY() + class AActor* Avatar; + + UPROPERTY() + TSet ActiveTasks; + + UPROPERTY() + TMap Tasks; + +public: + UGAEffectExtension(const FObjectInitializer& ObjectInitializer); + void SetParameters(const FGAEffectContext& ContextIn); + void BeginEffect(); + + /* + This event is always executed once upon application. + */ + UFUNCTION(BlueprintImplementableEvent, Category = "Event Graph") + void OnEffectApplied(); + UFUNCTION(BlueprintImplementableEvent, Category = "Event Graph") + void OnEffectExecuted(); + /* + Event executed when effet naturally expires. + */ + UFUNCTION(BlueprintImplementableEvent, Category = "Event Graph") + void OnEffectExpired(); + /* + Event executed when this effect is removed by force. + */ + UFUNCTION(BlueprintImplementableEvent, Category = "Event Graph") + void OnEffectRemoved(); + + void NativeOnEffectApplied(); + void NativeOnEffectExecuted(); + void NativeOnEffectExpired(); + void NativeOnEffectRemoved(); + + void NativeOnEffectAppliedCDO(); + void NativeOnEffectExecutedCDO(); + void NativeOnEffectExpiredCDO(); + void NativeOnEffectRemovedCDO(); + + + UFUNCTION(BlueprintImplementableEvent, Category = "Event Graph") + void OnEffectAppliedCDO() const; + UFUNCTION(BlueprintImplementableEvent, Category = "Event Graph") + void OnEffectExecutedCOD() const; + UFUNCTION(BlueprintImplementableEvent, Category = "Event Graph") + void OnEffectExpiredCDO() const; + UFUNCTION(BlueprintImplementableEvent, Category = "Event Graph") + void OnEffectRemovedCDO() const; + + virtual UWorld* GetWorld() const override; + + /* IAFLatentInterface */ + virtual void OnLatentTaskAdded(FName InstanceName, class UAFTaskBase* TaskIn); + virtual void AddReplicatedTask(class UAFTaskBase* TaskIn); + virtual void OnLatentTaskRemoved(class UAFTaskBase* TaskIn); + + virtual void OnLatentTaskActivated(class UAFTaskBase* TaskIn); + virtual void OnLatentTaskDeactivated(class UAFTaskBase* TaskIn); + + virtual class UAFTaskBase* GetCachedLatentAction(FName TaskName); + /* IAFLatentInterface */ + +protected: + void CleanupTasks(); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectField.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectField.h new file mode 100644 index 0000000..6c02bb4 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectField.h @@ -0,0 +1,60 @@ +#pragma once +#include "GAEffectField.generated.h" + +/* + Base class for effect field. + These fields might exist in two states: + 1. As long as ability is channeled. + 2. They are persistent on their own, which means that ability only create them once + and from create tim they might exist set amount of time (including indefinetly), or + until they are manually removed or destroyed. + + Main use cases: + 1. Createing persistent level effects (fire wall, oil puddle, wall of ice etc). + 2. Spawning other actors (rain of meteors, other pawns). + + Possible functionaltity: + 1. Interacting with other fields (Wind field can extinguish fire field). + 2. Interacting with other direct damage/attribute changes (fire damage, can + ignite oil field, creating fire field). + Not sure about this. I would probabaly need to implement this functionality down the line in + GameSystem Module, or add GameAttributes dependency here. + + Fields are only created on server, and then replicated back to clients. + + Need custom K2 Node to properly spawn this actor!. Default SpawnActorFromClass is + not sufficient. +*/ + +UCLASS(BlueprintType, Blueprintable, DefaultToInstanced) +class ABILITYFRAMEWORK_API AGAEffectField : public AActor +{ + GENERATED_UCLASS_BODY() +public: + /** + * If false, field will exist only as long as ability is channeled. + * Otherwise specific life time. + */ + UPROPERTY(BlueprintReadOnly, meta=(ExposeOnSpawn), Category = "Config") + bool bIsFieldPersistent; + + /** + * How long this field will live in world ? + * Only applicable if bIsFieldPersistent = true; + */ + UPROPERTY(BlueprintReadOnly, meta = (ExposeOnSpawn), Category = "Config") + float Lifetime; + + //UPROPERTY(BlueprintReadOnly, Category = "Owner") + //class AGASAbility* AbilityInstigator; + + void InitializeField(); + + void DestroyField(); + + UFUNCTION(BlueprintNativeEvent, Category = "Ability Field") + void OnAbilityExecuted(); + + UFUNCTION(BlueprintNativeEvent, Category = "Ability Field") + void OnOtherFieldOverlap(); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectGlobalTypes.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectGlobalTypes.h new file mode 100644 index 0000000..0b2fc2c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAEffectGlobalTypes.h @@ -0,0 +1,155 @@ +#pragma once +#include "../AbilityFramework.h" +#include "../Attributes/GAAttributeGlobals.h" +#include "GameplayTagContainer.h" +#include "../GAGlobalTypes.h" +#include "GAEffectGlobalTypes.generated.h" + + +USTRUCT(BlueprintType) +struct FAFFunctionModifier +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY() + float Additive; + UPROPERTY() + float Subtract; + UPROPERTY() + float Multiply; + UPROPERTY() + float Divide; + + FAFFunctionModifier() + {}; +}; + +/* +Base concept behind those attributes calculations (not sure if these are any good solutions +/performance firendly but: +1. Prefer getting values directly of attributes (GetBaseValue(), GetFinalValue(), GetBonus() etc), +as attributes can track their own state, we don't need any sophisticated way to access them and calculate bonuses). +2. Prefer simple and direct formulas (either evaluate from CurveTable, just plain add, Multiply various numbers, +or get value directly). +3. This system is not inteded, to calculate absolute final value on effect, before that effect is applied. +It will calculate absolute maximum value from the informations it have access to. +Further modifications like increasing specific damage type value, or reducing damage by value, are done +on AttributeComponent, by implementing approperiate functions, or by existing effects, which happen to intercept +incoming effect. +This might change in future though. But even if, I still prefer the magnitude calculations to be simple, +and we will add needed buffs/debuffs as we progress trough execution chain. +4. All calculations are linear. +*/ +//EGAMagnitudeCalculation::Direct +USTRUCT(BlueprintType) +struct FGADirectModifier +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY(EditAnywhere) + float Value; + + float GetValue(); + float GetValue() const; +}; +//EGAMagnitudeCalculation::AttributeBased +USTRUCT(BlueprintType) +struct FGAAttributeBasedModifier +{ + /* + We also need to add concept of backing attributes, + though I'm not sure how I want to handle them at this point. + */ + GENERATED_USTRUCT_BODY() +public: + /* + Source of Attribute for this calculation. + */ + UPROPERTY(EditAnywhere) + EGAAttributeSource Source; + /* + Name of attribute Used for calculation. + */ + UPROPERTY(EditAnywhere) + FGAAttribute Attribute; + + UPROPERTY(EditAnywhere, meta = (FixedIncrement = "0.01")) + float Coefficient; + UPROPERTY(EditAnywhere, meta = (FixedIncrement = "0.01")) + float PreMultiply; + UPROPERTY(EditAnywhere, meta = (FixedIncrement = "0.01")) + float PostMultiply; + UPROPERTY(EditAnywhere, meta = (FixedIncrement = "0.01")) + float PostCoefficient; + /* + Should we use secondary attribute for this ecalculation ? + */ + UPROPERTY(EditAnywhere) + bool bUseSecondaryAttribute; + /* + Source for secondary attribute + */ + UPROPERTY(EditAnywhere) + EGAAttributeSource SecondarySource; + /* + Name of secondary attribute used in calculation. + */ + UPROPERTY(EditAnywhere) + FGAAttribute SecondaryAttribute; + + FGAAttributeBasedModifier() + : Source(EGAAttributeSource::Instigator), + Coefficient(1), + PreMultiply(0), + PostMultiply(0), + PostCoefficient(1), + bUseSecondaryAttribute(false) + {} + + float GetValue(const FGAEffectContext& Context); + float GetValue(const FGAEffectContext& Context) const; +}; +//EGAMagnitudeCalculation::CurveBased +USTRUCT(BlueprintType) +struct FGACurveBasedModifier +{ + GENERATED_USTRUCT_BODY() +public: + /* + Source of Attribute for this calculation. + */ + UPROPERTY(EditAnywhere) + EGAAttributeSource Source; + /* + Name of attribute from which we will take XValue for Curve + */ + UPROPERTY(EditAnywhere) + FGAAttribute Attribute; + /* + Curve and row from which we will take YValue. + */ + UPROPERTY(EditAnywhere) + FCurveTableRowHandle CurveTable; + + float GetValue(const FGAEffectContext& ContextIn); + float GetValue(const FGAEffectContext& ContextIn) const; +}; +//EGAMagnitudeCalculation::CustomCalculation +USTRUCT(BlueprintType) +struct FGACustomCalculationModifier +{ + GENERATED_USTRUCT_BODY() +public: + /* + Instanced, so we can setup custom properties this class might provide, per effect spec. + */ + UPROPERTY(EditAnywhere, Instanced) + class UGACustomCalculation* CustomCalculation; + + FGACustomCalculationModifier() + : CustomCalculation(nullptr) + {}; + + float GetValue(const FGAEffectContext& ContextIn); + float GetValue(const FGAEffectContext& ContextIn) const; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAGameEffect.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAGameEffect.h new file mode 100644 index 0000000..52a95e1 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Effects/GAGameEffect.h @@ -0,0 +1,1297 @@ +#pragma once +//#include "GAGlobalTypes.h" +#include "GAEffectGlobalTypes.h" +#include "GameplayTagContainer.h" +#include "UObject/ObjectMacros.h" +#include "UObject/GCObject.h" +#include "GAGameEffect.generated.h" + +DECLARE_STATS_GROUP(TEXT("GameEffect"), STATGROUP_GameEffect, STATCAT_Advanced); +DECLARE_CYCLE_STAT_EXTERN(TEXT("GatherModifiers"), STAT_GatherModifiers, STATGROUP_GameEffect, ); + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAMagnitude +{ + GENERATED_USTRUCT_BODY() +public: + /* + Type of calculation we want to perform for this Magnitude. + */ + UPROPERTY(EditAnywhere) + EGAMagnitudeCalculation CalculationType; + + UPROPERTY(EditAnywhere) + FGADirectModifier DirectModifier; + /* + Simple calculation based on attribute: + (Coefficient * (PreMultiply + AttributeValue) + PostMultiply) * PostCoefficient + + There is no any magic manipulation, it straight off pull attribute from selected source, + and make this operation on it. + */ + UPROPERTY(EditAnywhere) + FGAAttributeBasedModifier AttributeBased; + /* + Get value from selected CurveTable, based on selected attribute value. + */ + UPROPERTY(EditAnywhere) + FGACurveBasedModifier CurveBased; + /* + Provide custom calculation class. + */ + UPROPERTY(EditAnywhere) + FGACustomCalculationModifier Custom; + + float GetFloatValue(const FGAEffectContext& Context); +}; +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAAttributeModifier +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY(EditAnywhere, Category = "Instant Spec") + FGAAttribute Attribute; + + UPROPERTY(EditAnywhere, Category = "Instant Spec") + EGAAttributeMod AttributeMod; + + /* + Who will be target of this attribute change. + Instigator - pawn which applied effect (regardless of to whom). + Target - targeted pawn (regardless of who applied). + */ + UPROPERTY(EditAnywhere) + EGAModifierTarget ModifierTarget; + /* + How modifier will be executed on target. + */ + //UPROPERTY(EditAnywhere, Category = "Execution Type") + // TSubclassOf ExecutionType; + + /* + Modifier value applied to attribute + */ + UPROPERTY(EditAnywhere) + FGAMagnitude Magnitude; +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFAttributeModifierContainer +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere) + TArray Modifiers; +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFCueContainer +{ + GENERATED_BODY() +public: + /* Cues to apply */ + UPROPERTY(EditAnywhere) + FGameplayTagContainer CueTags; +}; + +USTRUCT(BlueprintType) +struct FAFConditionalEffect +{ + GENERATED_BODY() + /* If target have this tag apply specified effects */ + UPROPERTY(EditAnywhere) + FGameplayTag RequiredTag; + UPROPERTY(EditAnywhere) + TSubclassOf Effect; +}; +USTRUCT(BlueprintType) +struct FAFConditionalEffectContainer +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere) + TArray Effects; +}; + +UENUM(BlueprintType) +enum class EAFExtensionType : uint8 +{ + NonInstanced UMETA(ToolTip = "Effect CDO will be used. Canno carry any state. You usually should use this if effect is instant or applied very often"), + Instanced UMETA(ToolTip = "Effect Extension will be instanced per effect application, these can have state and Tasks") + +}; + +/* + Base effect class. You can derive your own specialized classes from it + with preset customizations and values. You should never directly inherit blueprints from it. +*/ +UCLASS(Blueprintable, BlueprintType, Abstract, DefaultToInstanced, EditInlineNew) +class ABILITYFRAMEWORK_API UGAGameEffectSpec : public UObject +{ + GENERATED_BODY() +public: + /* + Replicate effect back to clients ? + */ + UPROPERTY(EditAnywhere, Category = "Network") + bool bReplicate; + + /* + Individual Tag descrbing effect type. + ie. Condition.Burning + */ + UPROPERTY(EditAnywhere, Category = "Effect Info") + FGameplayTag EffectTag; + + UPROPERTY(EditAnywhere, meta=(UseDisplayName), Category = "Effect Info") + TSubclassOf ApplicationRequirement; + /* + How effect should stack. Only relevelant for periodic effects + and modifiers applied on period. + */ + UPROPERTY(EditAnywhere, meta = (UseDisplayName), Category = "Effect Info") + TSubclassOf Application; + + UPROPERTY(EditAnywhere, Category = "Stacking") + int32 MaxStacks; + + /* + Who should aggregate this effect. Relevelant for stacking type + and by this only relevelant for periodic effects. + */ + UPROPERTY(EditAnywhere, Category = "Stacking") + EGAEffectAggregation EffectAggregation; + + /* Total duration of effect (if applicable) */ + UPROPERTY(EditAnywhere, Category = "Duration") + FGAMagnitude Duration; + /* Duration of single period. */ + UPROPERTY(EditAnywhere, Category = "Period") + FGAMagnitude Period; + /* Total duration of effect (if applicable) */ + UPROPERTY(EditAnywhere, Category = "Duration") + float MaxStackedDuration; + + /* IF true, effect will tick instantly upon application. */ + UPROPERTY(EditAnywhere, Category = "Duration") + bool bTickOnApplication; + UPROPERTY(EditAnywhere, Category = "Duration") + bool bExecuteOnApplication; + + + /* + Modifier applied to attribute + */ + UPROPERTY(EditAnywhere, Category = "Attribute Modifiers") + FGAAttributeModifier AtributeModifier; + UPROPERTY(EditAnywhere, Category = "Attribute Modifiers") + FAFAttributeModifierContainer Modifiers; + + UPROPERTY(EditAnywhere, Category = "Execution Type") + TSubclassOf ExecutionType; + + + UPROPERTY(EditAnywhere, Category = "Extension") + EAFExtensionType ExtensionInstancingPolicy; + UPROPERTY(EditAnywhere, Category = "Extension") + TSubclassOf Extension; + + /* Cues to apply by this effect. */ + UPROPERTY(EditAnywhere, Category = "Cues") + FAFCueContainer Cues; + /* + Effects applied when this effect is applied. + These effects will be applied with the same context and the same target as + effect, which stores them. + */ + UPROPERTY(EditAnywhere, Category = "Linked Effects") + TArray> OnAppliedEffects; + + /* Effects applied when this effect expire*/ + UPROPERTY(EditAnywhere, Category = "Linked Effects") + TArray> OnExpiredEffects; + + /* Effects applied when this effect is removed. */ + UPROPERTY(EditAnywhere, Category = "Linked Effects") + TArray> OnRemovedEffects; + + UPROPERTY(EditAnywhere, Category = "Event Tags") + FGameplayTag OnExpiredEvent; + UPROPERTY(EditAnywhere, Category = "Event Tags") + FGameplayTag OnPeriodEvent; + UPROPERTY(EditAnywhere, Category = "Event Tags") + FGameplayTag OnRemovedEvent; + + + UPROPERTY(EditAnywhere, Category = "Event Application Tags") + FGameplayTag OnEffectApplyToTargetEvent; + UPROPERTY(EditAnywhere, Category = "Event Application Tags") + FGameplayTag OnEffectApplyToSelfEvent; + + /* + Effects applied only when certain criteria are met. + Just dumbed here it needs it's own structure that will actually alow to setup those conditions. + */ + UPROPERTY(EditAnywhere, Category = "Linked Effects") + FAFConditionalEffectContainer IfHaveTagEffect; + + + /* Remove effects with these tags. */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer RemoveEffectWithTags; + + /* + Tags descrbing what this effect does. + */ + /* Tags I own and I don't apply. New tags can be added here as the effect is applied. */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer OwnedTags; + + /* Tags owned by this effect and not applied. Describe the type of this effect. */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer EffectTags; + + /* + When effect is appied trigger events with these tags. + */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer AppliedEventTags; + /* + When effect is executed trigger events with these tags. + */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer ExecuteEventTags; + + /* + Tags applied to attribute when effect is applying non-instant effect. + Owned tags of another effect are checked against these tags to calculate + modifier. + Also it's checked when tag is applied to determine effect stacking, + when stacking is set to Override or StrongerOverride. + + Use only single tag here, with proper hierarchy. + Using multiple tags should be reserved only for special cases. + */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer AttributeTags; + + /* If Target have any of these tags, effect will not be applied. */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer DenyTags; + + /* Tags, required for this effect to be applied. If these tags are not present, effect will be ignored. */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer ApplicationRequiredTags; + + /* Applied immunity tags. */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer AppliedImmunityTags; + + /* Tags, which are applied to Target when effect is Duration/Periodic based. */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer ApplyTags; + + /* If any of these tags are present on Effect Target, it will not be executed */ + UPROPERTY(EditAnywhere, Category = "Tags") + FGameplayTagContainer ExecutionDenyTags; +public: + UGAGameEffectSpec(); +}; +/* + Base effect class to extend from when creating effect blueprints. +*/ +UCLASS(Blueprintable, BlueprintType, Abstract) +class ABILITYFRAMEWORK_API UAFEffectSpecBase : public UGAGameEffectSpec +{ + GENERATED_BODY() +public: +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAEffectClass +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Category = "Effect") + TSubclassOf SpecClass; + + FGAEffectClass() + {} + FGAEffectClass(TSubclassOf InClass) + : SpecClass(InClass) + {} + + void Reset() + { + SpecClass = nullptr; + } + const bool operator==(const FGAEffectClass& Other) const + { + return SpecClass == Other.SpecClass; + } + const bool operator==(const TSubclassOf& OtherClass) const + { + return SpecClass == OtherClass; + } + void operator=(const FGAEffectClass& Other) + { + SpecClass = Other.SpecClass; + } + void operator=(const TSubclassOf& Other) + { + SpecClass = Other; + } + void operator=(UGAGameEffectSpec* Other) + { + SpecClass = Other->GetClass(); + } +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFContextHandle +{ + GENERATED_BODY() +private: + TSharedPtr DataPtr; + uint32 ID; +public: + static FAFContextHandle Generate(FGAEffectContext* InContext) + { + static uint32 id = 0; + id++; + + TSharedPtr PropPtr = MakeShareable(InContext); + FAFContextHandle Handle(PropPtr, id); + + return Handle; + } + + FAFContextHandle() + : ID(0) + {}; +protected: + FAFContextHandle(TSharedPtr InProperty, uint32 InID) + : DataPtr(InProperty) + , ID(InID) + {}; + +public: + bool IsValid() + { + return DataPtr.IsValid(); + } + bool IsValid() const + { + return DataPtr.IsValid(); + } + FGAEffectContext& GetRef() + { + return DataPtr.ToSharedRef().Get(); + } + FGAEffectContext& GetRef() const + { + return DataPtr.ToSharedRef().Get(); + } + FGAEffectContext* GetPtr() + { + return DataPtr.Get(); + } + FGAEffectContext* GetPtr() const + { + return DataPtr.Get(); + } + + void SetTarget(UObject* NewTarget, const FHitResult& InHit) + { + DataPtr->SetTarget(NewTarget, InHit); + } + + bool operator==(const FAFContextHandle& Other) const + { + return ID == Other.ID; + } + + bool operator==(const FObjectKey& Other) const + { + return *DataPtr.Get() == Other; + } + bool operator==(UObject* Other) const + { + return *DataPtr.Get() == Other; + } + + friend uint32 GetTypeHash(const FAFContextHandle& InHandle) + { + return InHandle.ID; + } +}; + +template<> +struct TStructOpsTypeTraits< FAFContextHandle > : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithCopy = true, + }; +}; + +/* + Dervied from GCObject because Extension property has been garbage collected. Even with UPROPERTY() and non-GC outer. +*/ + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFEffectSpec // : public FGCObject +{ + GENERATED_BODY() +private: + FAFContextHandle Context; + UPROPERTY() + TWeakObjectPtr Extension; //week ptr ? + + TSubclassOf SpecClass; + + FGAEffectMod EffectMod; +public: + + FGameplayTagContainer OwnedTags; + FGameplayTagContainer ApplyTags; + FGameplayTagContainer RequiredTags; + +public: + FAFEffectSpec() + : Extension(nullptr) + {} + + FAFEffectSpec(const FAFContextHandle& InContext, TSubclassOf InSpecClass); + + void OnApplied() const; + void OnExpired() const; + void OnRemoved() const; + void OnExecuted() const; + FAFContextHandle GetContext() + { + return Context; + } + FGAEffectMod GetModifier() + { + return EffectMod; + } + + inline void SetContext(const FAFContextHandle& InContext) { Context = InContext; } + + void AddOwnedTags(const FGameplayTagContainer& InTags) + { + OwnedTags.AppendTags(InTags); + } + void AddApplyTags(const FGameplayTagContainer& InTags) + { + ApplyTags.AppendTags(InTags); + } + + UGAGameEffectSpec* GetSpec() + { + return SpecClass.GetDefaultObject(); + } + UGAGameEffectSpec* GetSpec() const + { + return SpecClass.GetDefaultObject(); + } + + float GetFloatFromAttributeMagnitude( + const FGAMagnitude& AttributeIn + , const FGAEffectContext& InContext) const; + + void OverrideAttributeModifier(float InValue); + void CalculateAttributeModifier(const FGAEffectHandle& InHandle); + + float GetDuration(const FGAEffectContext& InContext); + float GetPeriod(const FGAEffectContext& InContext); + + float GetDuration(const FGAEffectContext& InContext) const; + float GetPeriod(const FGAEffectContext& InContext) const; + + const TSubclassOf& GetEffectClass() + { + return SpecClass; + } + + void Instance(); + + //virtual void AddReferencedObjects(FReferenceCollector& Collector) override + //{ + // Collector.AddReferencedObject(Extension, Context.GetPtr()->Target.Get()); + //} + +}; +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFEffectSpecHandle +{ + GENERATED_BODY() +public: + TSharedPtr SpecPtr; + uint32 ID; + +public: + static FAFEffectSpecHandle Generate(FAFEffectSpec* Effect) + { + static uint32 id = 0; + id++; + + TSharedPtr PropPtr = MakeShareable(Effect); + FAFEffectSpecHandle Handle(PropPtr, id); + + return Handle; + } + + FAFEffectSpecHandle() + : ID(0) + {} + FAFEffectSpecHandle(TSharedPtr Ptr, uint32 InID) + : SpecPtr(Ptr) + , ID(InID) + {} + + bool IsValid() + { + return SpecPtr.IsValid(); + } + void Reset() + { + SpecPtr.Reset(); + ID = 0; + } + TSharedPtr GetPtr() + { + return SpecPtr; + } + FAFEffectSpec& GetRef() + { + return SpecPtr.ToSharedRef().Get(); + } + FAFEffectSpec& GetRef() const + { + return SpecPtr.ToSharedRef().Get(); + } + FGAEffectMod GetModifier() + { + return SpecPtr->GetModifier(); + } + void OverrideAttributeModifier(float InValue) + { + SpecPtr->OverrideAttributeModifier(InValue); + } + void CalculateAttributeModifier(const FGAEffectHandle& InHandlet) + { + SpecPtr->CalculateAttributeModifier(InHandlet); + } + inline void SetContext(const FAFContextHandle& InContext) { SpecPtr->SetContext(InContext); } +}; +template<> +struct TStructOpsTypeTraits< FAFEffectSpecHandle > : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithCopy = true, + }; +}; + + + +/* + Container for: + 1. Effect handles applied from this property, sorted per target. + 2. Their contexts (each effect have it's own context). + 3. Targets affected by effect from this container (and which effect). + + Also contains hard pointers to base classes/assets used by effect (Execution, Application, Specification). +*/ + +struct FAFEffectParams; + +struct ABILITYFRAMEWORK_API FGAEffectProperty +{ +protected: + + TWeakObjectPtr ApplicationRequirement; + TWeakObjectPtr Application; + TWeakObjectPtr Execution; + TWeakObjectPtr Spec; + TSubclassOf SpecClass; + FAFPredictionHandle PredictionHandle; + + float Duration; + float Period; + bool bInstant; + /* + Handle to effect created from SpecClass + This handle is only created and kept for instant effects, + so we don't create new object every time instant effect is created + as potentially there can be quite a lot of allocations. + */ + /* + Holds handle to duration/infinite effects. Since there can be multiple effects active on multiple targets. + + */ + + FAFContextHandle EffectContext; + FAFEffectSpecHandle EffectSpec; + //add chaing or not ? + //struct Aggregator + //{ + // FAFContextHandle InstantContext; + // FAFEffectSpecHandle InstantEffectSpec; + // FGAEffectHandle Handle; + //}; + + //TArray AppliedEffects; + +public: + FGAEffectProperty(); + + FGAEffectProperty(TSubclassOf InClass); + void PostScriptConstruct(); + + UGAGameEffectSpec* GetSpecData() { return Spec.Get(); } + UGAGameEffectSpec* GetSpecData() const { return Spec.Get(); } + + bool CanApply( + const struct FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& InParams + , const FGAEffectHandle& InHandle); + + bool ApplyEffect(const FGAEffectHandle& InHandle + , const struct FGAEffect& EffectIn + , struct FGAEffectContainer* InContainer + , const FAFEffectParams& InParams + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + void ApplyExecute(const FGAEffectHandle& InHandle + , const FAFEffectParams& InParams + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + void ExecuteEffect(const FGAEffectHandle& HandleIn + , FGAEffectMod& ModIn + , const FAFEffectParams& InParams + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + + /* Get or create Effect Spec. The Effect spec is created once per EffectProperty and then returned by value. */ + FAFEffectSpec GetSpecCopy() + { + if (EffectSpec.IsValid()) + { + FAFEffectSpec* Ptr = EffectSpec.GetPtr().Get(); + Ptr->Instance(); + return *Ptr; + } + else + { + FAFEffectSpec* LocalSpec = new FAFEffectSpec(EffectContext, SpecClass); + LocalSpec->Instance(); + EffectSpec = FAFEffectSpecHandle::Generate(LocalSpec); + return *LocalSpec; + } + } + + FGAEffectContext GetContextCopy(UObject* Target, const FHitResult& InHit) + { + if (EffectContext.IsValid()) + { + EffectContext.SetTarget(Target, InHit); + return *EffectContext.GetPtr(); + } + else + { + return FGAEffectContext(); + } + } + + //intentionally non const. + //FGAEffectHandle& GetHandleRef() { return Handle; } + //void SetHandle(const FGAEffectHandle& InHandle) { Handle = InHandle; }; + void OnEffectRemoved(UObject* InTarget, const FGAEffectHandle& InHandle) {} + + void Initialize(TSubclassOf EffectClass); + void InitializeIfNotInitialized( + class APawn* Instigator + , UObject* Causer + , TSubclassOf EffectClass); + + bool GetIsInstant() const + { + return bInstant; + } + inline float GetPeriod() const + { + return Period; + } + inline float GetDuration() const + { + return Duration; + } + + void SetPredictionHandle(const FAFPredictionHandle& InHandle) + { + PredictionHandle = InHandle; + } + + FAFPredictionHandle GetPredictionHandle() + { + return PredictionHandle; + } + + FGAAttributeModifier& GetAttributeModifier() + { + return Spec->AtributeModifier; + } + + + const bool IsInitialized() const + { + return ApplicationRequirement.IsValid() && Application.IsValid() && Execution.IsValid() && Spec.IsValid(); + } + +}; +template<> +struct TStructOpsTypeTraits< FGAEffectProperty > : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithCopy = true, + WithPostScriptConstruct = true, + }; +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFPropertytHandle +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Category = "Effect") + FGAEffectClass SpecClass; + + TSharedPtr DataPtr; + //TSharedRef Test; + + uint32 ID; +public: + FAFPropertytHandle() + : ID(0) + { + if (!DataPtr.IsValid()) + { + DataPtr = MakeShareable(new FGAEffectProperty()); + } + }; + + void Reset() + { + SpecClass.Reset(); + DataPtr.Reset(); + ID = 0; + } + + FAFPropertytHandle(TSubclassOf InSpecClass) + : ID(0) + { + SpecClass = InSpecClass; + if (!DataPtr.IsValid()) + { + DataPtr = MakeShareable(new FGAEffectProperty()); + } + }; + + FAFPropertytHandle(const FAFPropertytHandle& Other) + { + SpecClass = Other.SpecClass; + DataPtr = Other.DataPtr; + }; + + + + void PostScriptConstruct() + { + if (SpecClass.SpecClass) + { + + } + } + + TSubclassOf GetClass() const { return SpecClass.SpecClass; } + const TSubclassOf& GetClassRef() { return SpecClass.SpecClass; } +public: + + void InitializeIfNotInitialized( + class APawn* Instigator + , UObject* Causer) + { + DataPtr->InitializeIfNotInitialized(Instigator, Causer, SpecClass.SpecClass); + } + + FAFEffectSpec GetSpecCopy() + { + return DataPtr->GetSpecCopy(); + } + + FGAEffectProperty & GetRef() + { + return DataPtr.ToSharedRef().Get(); + } + FGAEffectProperty& GetRef() const + { + return DataPtr.ToSharedRef().Get(); + } + FGAEffectProperty* GetPtr() const + { + return DataPtr.Get(); + } + + FObjectKey GetClassKey() const + { + return FObjectKey(GetClass()); + } + inline float GetPeriod() const + { + return DataPtr->GetPeriod(); + } + inline float GetDuration() const + { + return DataPtr->GetDuration(); + } + + UGAGameEffectSpec* GetSpecData() + { + return DataPtr->GetSpecData(); + } + UGAGameEffectSpec* GetSpecData() const + { + return DataPtr->GetSpecData(); + } + + const bool IsInitialized() const + { + return DataPtr->IsInitialized(); + } + const bool IsValid() const + { + return SpecClass.SpecClass ? true : false; + } + const bool operator==(const FAFPropertytHandle& Other) const + { + return SpecClass == Other.SpecClass; + } + const bool operator==(const TSubclassOf& OtherClass) const + { + return SpecClass == OtherClass; + } + FAFPropertytHandle& operator=(const FAFPropertytHandle& Rhs) + { + if (this == &Rhs) + return *this; + DataPtr = Rhs.DataPtr; + SpecClass = Rhs.SpecClass; + return *this; + } + void operator=(const TSubclassOf& Other) + { + SpecClass = Other; + } + void operator=(UGAGameEffectSpec* Other) + { + SpecClass = Other->GetClass(); + } +}; + +template<> +struct TStructOpsTypeTraits< FAFPropertytHandle > : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithCopy = true, + WithPostScriptConstruct = true, + }; +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFEffectParams +{ + GENERATED_BODY() + //make this private and allow assign only trough constructr. + FGAEffectContext Context; + FAFPropertytHandle Property; + FAFEffectSpec EffectSpec; + bool bRecreated; + bool bPeriodicEffect; +public: + FAFEffectParams() + {}; + FAFEffectParams(FAFPropertytHandle InProperty) + : Property(InProperty) + , bRecreated(false) + {}; + + FGAEffectContext& GetContext() + { + return Context; + } + const FGAEffectContext& GetContext() const + { + return Context; + } + + FGAEffectProperty& GetProperty() const + { + return Property.GetRef(); + } + + FAFEffectSpec& GetSpec() + { + return EffectSpec; + } + const FAFEffectSpec& GetSpec() const + { + return EffectSpec; + } + FTimerManager& GetTargetTimerManager(); + + UAFEffectsComponent* GetTargetEffectsComponent(); + UAFEffectsComponent* GetTargetEffectsComponent() const; + +}; + + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFEventData +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintReadOnly) + FGAEffectContext ContextHandle; + UPROPERTY(BlueprintReadOnly) + FAFEffectSpec SpecHandle; + UPROPERTY(BlueprintReadOnly) + FAFPropertytHandle PropertyHandle; + + FAFEventData() + {}; + + FAFEventData(FGAEffectContext InContextHandle + , FAFEffectSpec InSpecHandle + , FAFPropertytHandle InPropertyHandle + ) + : ContextHandle(InContextHandle) + , SpecHandle(InSpecHandle) + , PropertyHandle(InPropertyHandle) + {}; + + FAFEventData(const FAFEffectParams& EffectParams) + : ContextHandle(EffectParams.Context) + , SpecHandle(EffectParams.EffectSpec) + , PropertyHandle(EffectParams.Property) + {}; + +}; + +struct ABILITYFRAMEWORK_API FAFStatics +{ + static float GetFloatFromAttributeMagnitude(const FGAMagnitude& AttributeIn + , const FGAEffectContext& InContext + , const FGAEffectHandle& InHandle); + static FGAEffectMod GetAttributeModifier(FGAAttributeModifier& ModInfoIn + , class UGAGameEffectSpec* InSpec, + const FGAEffectContext& InContext, + const FGAEffectHandle& InHandle); +}; + +/* + Calculcated magnitudes, captured attributes and tags, set duration. + Final effect which then is used to apply custom calculations and attribute changes. +*/ +DECLARE_MULTICAST_DELEGATE_OneParam(FAFEffectMulicastDelegate, const FGAEffectHandle&); +UENUM() +enum class ERepInfoType : uint8 +{ + LocallyPredicted, + RemotePredicted, + Server +}; + +USTRUCT() +struct ABILITYFRAMEWORK_API FGAEffect : public FFastArraySerializerItem//, TSharedFromThis +{ + GENERATED_BODY() + + FGAEffectHandle Handle; + UPROPERTY() + FAFPredictionHandle PredictionHandle; + + mutable FTimerHandle PeriodTimerHandle; + mutable FTimerHandle DurationTimerHandle; + + UWorld* World; + +public: + float AppliedTime; + float LastTickTime; + float Period; + float Duration; +public: + void PreReplicatedRemove(const struct FGAEffectContainer& InArraySerializer); + void PostReplicatedAdd(const struct FGAEffectContainer& InArraySerializer); + void PostReplicatedChange(const struct FGAEffectContainer& InArraySerializer); + + inline void SetHandle(const FGAEffectHandle& InHandle) + { + Handle = InHandle; + } + + float GetDurationTime() const; + float GetPeriodTime() const; + float GetCurrentDuration() const; + //float GetFloatFromAttributeMagnitude(const FGAMagnitude& AttributeIn) const; + + FGAEffect() + {} + + FGAEffect(TSharedPtr InSpec, const FGAEffectHandle& InHandle); + + ~FGAEffect(); + + + bool operator==(const FGAEffect& Other) const + { + return Handle == Other.Handle; + } +}; + +/* + Minimum replicated info about applied info, so we don't replicate full effect if not needed. + Also provide callbacks for cues assigned to this Effect, so they can be predictevly, + executed on clients. + + Add replication optimization. +*/ + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAEffectAttributeModifier +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY(EditAnywhere) + FGAAttribute Attribute; + UPROPERTY(EditAnywhere) + float Value; +}; +USTRUCT(BlueprintType) +struct FGAEffectDuration +{ + GENERATED_USTRUCT_BODY() +public: + /* + -1 infinite duration, 0-no duration >0 - set duration + */ + UPROPERTY(EditAnywhere, Category = "Duration") + float Duration; + /* + <=0 - no period >0 - set period + */ + UPROPERTY(EditAnywhere, Category = "Duration") + float Period; + /* + If PeriodNum > 0 and Period > 0, then duration of + effect is PeriodNum * Period + */ + UPROPERTY(EditAnywhere, Category = "Duration") + float PeriodNum; +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAInstigatorInstancedEffectContainer +{ + GENERATED_USTRUCT_BODY() + + UPROPERTY() + TArray Effects; +}; + + +USTRUCT() +struct ABILITYFRAMEWORK_API FGAGameCue +{ + GENERATED_BODY() + + + //Handle to effect, which spawned this cue. + UPROPERTY() + FGAEffectHandle EffectHandle; +}; + +USTRUCT() +struct ABILITYFRAMEWORK_API FGameCueContainer +{ + GENERATED_USTRUCT_BODY() + + TWeakObjectPtr OwningComp; +public: + void AddCue(FGAEffectHandle EffectHandle, FGAEffectCueParams CueParams); +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAEffectContainer : public FFastArraySerializer +{ + GENERATED_BODY() +public: + UPROPERTY() + TArray ActiveEffectInfos; + + UPROPERTY() + TMap HandleByPrediction; + + UPROPERTY() + TMap PredictionByHandle; + + + TMap PredictedEffectInfos; + + + TMap> EffectByAttribute; + + + TMap> EffectByClass; + + TMap ActiveEffects; + /* + Contains effects with infinite duration. + Infinite effects are considred to be special case, where they can only be self spplied + and must be manually removed. + */ + UPROPERTY() + TSet InfiniteEffects; + + //not really sure if we really need set.\ + // it could be usefull, for effects which stack in add. + /* + UObject* - Instigator + FName = Effect class name + FGAEffectHandle = handle to effect of class. + */ + + TMap>> InstigatorEffectByClass; + + /* + FName = Effect class name + FGAEffectHandle = handle to effect of class. + */ + + TMap> TargetEffectByClass; + + //Conditonally applied effects. Only duration/periodic. + //TMap ConditionalEffects; + + UPROPERTY(NotReplicated) + class UAFEffectsComponent* OwningComponent; +public: + + /* + * @call Order: + * Previous Function: UAFAbilityComponent::ApplyEffectToSelf + * Next Function: InProperty.Application->ApplyEffect(); + * FGAEffectContainer::ApplyReplicationInfo() + * + * Apply target to Me. Try to apply effect to container and launch Events in: + * TMap OnEffectEvent - event is called before application; + * TMap OnEffectApplyToSelf - event is called before application; + * + * @param EffectIn* - Effect to apply + * @param InProperty - cached effect information + * @param InContext - Context about effect application. Target, instigator, causer. + * @param Modifier - optional modifier which can be applied to effect. + * @return Handle to Effect @ UAFAbilityComponent::ApplyEffectToSelf + */ + FGAEffectHandle ApplyEffect( + const FGAEffect& EffectIn + , const FAFEffectParams& Params + , const FAFFunctionModifier& Modifier = FAFFunctionModifier()); + + /* Removesgiven number of effects of the same type. If Num == 0 Removes all effects */ + TArray RemoveEffect(const FAFPropertytHandle& HandleIn, const FGAEffectContext& InContext, int32 Num = 1); + /* Removesgiven number of effects of the same type. If Num == 0 Removes all effects */ + void RemoveEffectByHandle(const FGAEffectHandle& InHandle, const FGAEffectContext& InContext, const FAFPropertytHandle& InProperty); + + inline int32 GetEffectsNum() const { return ActiveEffectInfos.Num(); }; + + TSet GetHandlesByClass(const FGAEffectProperty& InProperty, + const FGAEffectContext& InContext); + + void AddEffect( + const FGAEffectHandle& InHandle + , const FAFPredictionHandle& InPredHandle + , FGAEffect* InEffect + , const FGAEffectProperty& InProperty + , const FAFEffectParams& Params + , bool bInfinite = false); + + //modifiers + void ApplyEffectsFromMods() {}; + void DoesQualify() {}; + bool IsEffectActive(const FGAEffectHandle& HandleIn); + bool IsEffectActive(const FGAEffectHandle& HandleIn) const; + bool ContainsEffectOfClass(const FAFPropertytHandle& InProperty); + + void ApplyFromReplication(const FGAEffectHandle& InHandle, const FAFPredictionHandle& InPredHandle, FGAEffect* InEffect); + void RemoveFromReplication(const FGAEffectHandle& InHandle, const FAFPredictionHandle& InPredHandle); + + bool NetDeltaSerialize(FNetDeltaSerializeInfo & DeltaParms) + { + //return FastArrayDeltaSerialize(ActiveEffectInfos, DeltaParms, *this); + return FFastArraySerializer::FastArrayDeltaSerialize(ActiveEffectInfos, DeltaParms, *this); + } + + UWorld* GetWorld() const; + + ///Helpers + float GetRemainingTime(const FGAEffectHandle& InHandle) const; + float GetRemainingTimeNormalized(const FGAEffectHandle& InHandle) const; + /* Get Current effect ime clamped to max duration */ + float GetCurrentTime(const FGAEffectHandle& InHandle) const; + float GetCurrentTimeNormalized(const FGAEffectHandle& InHandle) const; + float GetEndTime(const FGAEffectHandle& InHandle) const; + + FGAEffect* GetEffect(const FGAEffectHandle& InHandle) + { + return ActiveEffects[InHandle]; + } + bool IsEffectActive(TSubclassOf EffectClass); +private: + void RemoveEffectInternal(const FAFPropertytHandle& InProperty, const FGAEffectContext& InContext, const FGAEffectHandle& InHandle); +}; +template<> +struct TStructOpsTypeTraits< FGAEffectContainer > : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithNetDeltaSerializer = true, + WithCopy = false + }; +}; + + +/* +Simplified effect container, which do not support effect replication. +*/ +USTRUCT() +struct ABILITYFRAMEWORK_API FAFEffectContainerSimple +{ + GENERATED_BODY() +protected: + UPROPERTY(Transient) + TMap Effects; + +public: + void ApplyEffect(const FGAEffectHandle& InHandle + , const FGAEffect& InEffect); + + void RemoveEffect(const FGAEffectHandle& InHandle); + +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAGlobalTypes.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAGlobalTypes.h new file mode 100644 index 0000000..21e20a3 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAGlobalTypes.h @@ -0,0 +1,798 @@ +#pragma once +#include "AbilityFramework.h" +#include "GameplayTagsModule.h" +#include "GameplayTagContainer.h" +//#include "Messaging.h" +#include "GAGlobalTypes.generated.h" + +void AddLogDebugInfo(FString Text, UWorld* World); + +/* + Explanation of tags from Fred K, on forums: + https://forums.unrealengine.com/showthread.php?57988-GameplayAbilities-questions&p=220315#post220315 + Here are some examples to illustrate the possible results. Let's assume that our + tag container contains exactly one tag, "A.B.C". + + HasTag("A.B.C", Explicit, Explicit) returns true. + HasTag("A.B", Explicit, Explicit) returns false. + HasTag("A.B.C.D", Explicit, Explicit) returns false. + HasTag("E.B.C", Explicit, Explicit) returns false. + HasTag("A.B.C", IncludeParentTags, IncludeParentTags) returns true. + HasTag("A.B", IncludeParentTags, IncludeParentTags) returns true. + HasTag("A.B.C.D", IncludeParentTags, IncludeParentTags) returns true. + HasTag("E.B.C", IncludeParentTags, IncludeParentTags) returns false. + HasTag("A.B.C", IncludeParentTags, Explicit) returns true. + HasTag("A.B", IncludeParentTags, Explicit) returns true. + HasTag("A.B.C.D", IncludeParentTags, Explicit) returns false. + HasTag("E.B.C", IncludeParentTags, Explicit) returns false. + HasTag("A.B.C", Explicit, IncludeParentTags) returns true. + HasTag("A.B", Explicit, IncludeParentTags) returns false. + HasTag("A.B.C.D", Explicit, IncludeParentTags) returns true. + HasTag("E.B.C", Explicit, IncludeParentTags) returns false. +*/ + +/* + I seriosuly need to clean this shit up. +*/ +/* + TODO:: I probabaly need to change it to normal enum. + So I can use it as array indexes. +*/ +UENUM() +enum class EGAAttributeMod : int32 +{ + Add = 0, //Value = Value + X + Subtract = 1, //Value = Value - X + Multiply = 2, //Value = Value * X + Divide = 3,//Value = Value * X - ok its's not really divide. + Set = 4, //Value = X + PercentageAdd = 5, + PercentageSubtract = 6, + Invalid = 7 +}; + +UENUM() +enum class EGAAttributeSource : uint8 +{ + Instigator, + Target, + Causer, + Ability +}; + +UENUM() +enum class EGAModifierTarget : uint8 +{ + Instigator, + Target +}; + +UENUM() +enum class EGAAttributeValue : uint8 +{ + Base, + Current, + Final, + Bonus +}; + +UENUM() +enum class EGAEffectType : uint8 +{ + Instant = 0, + Duration = 1, + Infinite = 2, +}; + +/* + + StrongetOverride - Does not check for effect type/tags. It will just check if modified + attribute, is already modified, and if incoming effect is stronger it will override + all modifiers affecting this attribute, and remove all weaker ones. + + Override - does not check if it is stronger/weaker, it will simply override any existing modifiers + and effects with the same name. + + Duration - Will add duration to existing effect of EXACTLY the same type. + + Intensity - Undefined. It will either add new effects to stack, + or it will simply sum modifiers, from all effects of the same types, for the same attributes + and refresh duration to the latest applied effect. + + Add - no checks, simply add new effect to stack. +*/ +UENUM() +enum class EGAEffectStacking : uint8 +{ + Add = 0, + Duration = 1, + Override = 2, //override existing effect of the same type, and all other effects which have override the same attribute and have same AttributeTags + Intensity = 3, + //will add duration to existing effect + //will simply add new effect +}; + +UENUM() +enum class EGAMagnitudeCalculation : uint8 +{ + Direct, //straight float value, no calculations. + AttributeBased, //calculate based on attribute Attribute * RestOfEquationToBeDecided + CurveBased, //Takes value of attribute, and then gets value from curve based on this attribute. + CustomCalculation,//uses custom object to calculate magnitude. + Invalid +}; + + +/* +Rules for where we should aggregate effects. +Concept might look bit muddy at first look, but it is actually very simple. + +Let's say we have additive effect which modify Health by 50 points, and effect which modify health by 100. +We want, to only the highest one, affect target (positive bonus). Regardless of who applied this effect. + +To do it we need to tell this effect, that it should be aggregated by target and set effect stacking rule to +HighestOverride. + +Now say we have effect which reduce Health by 30 points, and second which reduce by 20 points. +We might want negative effects from diffrent source to stack. +To do this we need to aggregate those effects by Instigator. +And then we can decide how those effects will stack within single Instigator. +*/ +UENUM() +enum class EGAEffectAggregation : uint8 +{ + /* + Effect will be stacked/aggregated by Instigator who applied it. + Checking for stacking rules will be done only against other effects from the same Instigator. + */ + AggregateByInstigator, + /* + Effects will be stacked/aggregated by Target. + Checking for stacking rules, will be done only for effects, with the same target. + */ + AggregateByTarget +}; + +USTRUCT() +struct FAFAtributeRowData : public FTableRowBase +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, BlueprintReadOnly) + float BaseValue; + UPROPERTY(EditAnywhere, BlueprintReadOnly) + float MinValue; + UPROPERTY(EditAnywhere, BlueprintReadOnly) + float MaxValue; + UPROPERTY(EditAnywhere, BlueprintReadOnly) + float CurrentValue; + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TSubclassOf Extension; +}; + + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAEffectContext +{ + GENERATED_USTRUCT_BODY() +public: + /* + Just copy entire hit result struct. + */ + UPROPERTY(BlueprintReadOnly, Category = "Spec") + FHitResult HitResult; + /** + * Where exactly we hit target. + */ + UPROPERTY(BlueprintReadOnly, Category = "Spec") + FVector TargetHitLocation; + + UPROPERTY(BlueprintReadOnly, Category = "Spec") + TWeakObjectPtr TargetAttributes; + + UPROPERTY(BlueprintReadOnly, Category = "Spec") + TWeakObjectPtr InstigatorAttributes; + + /** + * Direct Reference to TargetActor (I will possibly remove FHitResult Target! + */ + UPROPERTY(BlueprintReadOnly, Category = "Spec") + TWeakObjectPtr Target; + /** + * Object which caused this effect. Might be ability, weapon, projectile etc. + */ + UPROPERTY(BlueprintReadOnly, Category = "Spec") + TWeakObjectPtr Causer; + /** + * Pawn, which originally instigated effect (an owned AttributeComponent). + */ + UPROPERTY(BlueprintReadOnly, Category = "Spec") + TWeakObjectPtr Instigator; + + UPROPERTY(BlueprintReadOnly, Category = "Spec") + TWeakObjectPtr Avatar; + /** + * Attribute component of Target. + */ + UPROPERTY(BlueprintReadOnly, Category = "Spec") + TWeakObjectPtr TargetComp; + /** + * Attribute component of Intigator + */ + UPROPERTY(BlueprintReadOnly, Category = "Spec") + TWeakObjectPtr InstigatorComp; + + class IAFAbilityInterface* TargetInterface; + class IAFAbilityInterface* InstigatorInterface; + + void SetTarget(UObject* NewTarget, const FHitResult& InHit); + template + inline T* GetTarget() + { + return Cast(Target); + } + + inline bool IsValid() const + { + /*if (Target.IsValid() && Causer.IsValid() && Instigator.IsValid() && TargetComp.IsValid() && InstigatorComp.IsValid()) + return true;*/ + if (Causer.IsValid() && Instigator.IsValid() && InstigatorComp.IsValid() && TargetInterface) + return true; + //UE_LOG(GameAttributesEffects, Error, TEXT("Effect Context Is Not Valid")); + return false; + } + + inline FString ToString() + { + if (!IsValid()) + { + //UE_LOG(GameAttributesEffects, Error, TEXT("Effect Context Is Not Valid")); + return FString("Context Is not valid"); + } + FString ret; + ret = "TargetHitLocation: "; + ret += TargetHitLocation.ToString(); + ret += "\n"; + ret += "Target: "; + ret += Target->GetName(); + ret += "\n"; + ret += "Causer: "; + ret += Causer->GetName(); + ret += "\n"; + ret += "Instigator: "; + ret += Instigator->GetName(); + ret += "\n"; + ret += "TargetComp: "; + return ret; + } + + bool operator==(UObject* Other) const + { + return FObjectKey(Target.Get()) == FObjectKey(Other); + } + + bool operator==(const FObjectKey& Other) const + { + return FObjectKey(Target.Get()) == Other; + } + + void Reset(); + + class UGAAttributesBase* GetTargetAttributes(); + class UGAAttributesBase* GetInstigatorAttributes(); + class UGAAttributesBase* GetCauserAttributes(); + + class UGAAttributesBase* GetTargetAttributes() const; + class UGAAttributesBase* GetInstigatorAttributes() const; + class UGAAttributesBase* GetCauserAttributes() const; + + class UAFEffectsComponent* GetTargetEffectsComponent(); + class UAFEffectsComponent* GetTargetEffectsComponent() const; + void operator=(const FGAEffectContext& Other); + FGAEffectContext() + {} + + FGAEffectContext(const FGAEffectContext& Other); + + FGAEffectContext(APawn* InInstigator, UObject* InCauser); + + FGAEffectContext(TWeakObjectPtr TargetAttributesIn, TWeakObjectPtr InstigatorAttributesIn, + const FVector& TargetHitLocationIn, TWeakObjectPtr TargetIn, + TWeakObjectPtr CauserIn, TWeakObjectPtr InstigatorIn, + TWeakObjectPtr TargetCompIn, + TWeakObjectPtr InstigatorCompIn, + TWeakObjectPtr InAvatar); + + ~FGAEffectContext(); +}; + + +struct FGAEffect; +class UGAGameEffectSpec; +struct FGAEffectMod; +struct FGAAttribute; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAEffectHandle +{ + GENERATED_BODY() +protected: + //just to be safe we don't run out of numbers.. + UPROPERTY(VisibleAnywhere, Transient) + int32 Handle; //Fname Guid ? +public: + int32 GetHandle() const + { + return Handle; + } + static FGAEffectHandle GenerateHandle(); + bool operator==(const FGAEffectHandle& Other) const + { + return Handle == Other.Handle; + } + bool operator!=(const FGAEffectHandle& Other) const + { + return Handle != Other.Handle; + } + + //FGAEffectHandle& operator=(const FGAEffectHandle& Other) + //{ + // Handle = Other.Handle; + // EffectPtr = Other.EffectPtr; + // return *this; + //} + + void Reset(); + bool IsValid() const; + friend uint32 GetTypeHash(const FGAEffectHandle& InHandle) + { + return InHandle.Handle; + } + + FGAEffectHandle(); + + FGAEffectHandle(uint32 HandleIn); + void PostScriptConstruct(); +public: + ~FGAEffectHandle(); +}; +// +template<> +struct TStructOpsTypeTraits< FGAEffectHandle > : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithPostScriptConstruct = true, + }; +}; + +USTRUCT() +struct ABILITYFRAMEWORK_API FAFPredictionHandle +{ + GENERATED_BODY() +public: + //ID of current handle. + UPROPERTY() + uint32 Handle; + UPROPERTY() + FGAEffectHandle EffectHandle; + + uint64 Timestamp; + + static FAFPredictionHandle GenerateClientHandle(UAFAbilityComponent* InComponent); + /* + Was prediction successful ? + If true nothing happens on client (might interpolate to result from server). + If false, server will override client predicted results. + */ + UPROPERTY() + bool bPredictionValid; + + + bool IsValid() const + { + return true; + } + + const bool operator==(const FAFPredictionHandle& Other) const + { + return Handle == Other.Handle; + } + friend uint32 GetTypeHash(const FAFPredictionHandle& InHandle) + { + return InHandle.Handle; + } +}; + +DECLARE_MULTICAST_DELEGATE(FGAGenericDelegate); + +struct ABILITYFRAMEWORK_API EnumToString +{ + static FString GetStatckingAsString(EGAEffectStacking Stacking) + { + switch (Stacking) + { + case EGAEffectStacking::Override: + return FString("Override"); + case EGAEffectStacking::Intensity: + return FString("Intensity"); + case EGAEffectStacking::Duration: + return FString("Duration"); + case EGAEffectStacking::Add: + return FString("Add"); + } + return FString(""); + } +}; + +/* + Special struct, which allows to use FGameplayTagContainer as key, for TSet and TMap. + Bear in mind slower inserts/remove, but allow for complex keys. +*/ +struct ABILITYFRAMEWORK_API FGAHashedGameplayTagContainer +{ +public: + FGameplayTagContainer Tags; + +private: + FName Key; + void GenerateFNameKey(); + +public: + FGAHashedGameplayTagContainer() + {}; + FGAHashedGameplayTagContainer(const FGameplayTagContainer& TagsIn); + + friend uint32 GetTypeHash(const FGAHashedGameplayTagContainer& InHandle) + { + return ::GetTypeHash(InHandle.Key); + } +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAIndividualMods +{ + GENERATED_BODY() +public: + UPROPERTY() + float Additive; + UPROPERTY() + float Subtractive; + UPROPERTY() + float Multiplicative; + UPROPERTY() + float Divide; + UPROPERTY() + float PercentageAdd; + UPROPERTY() + float PercentageSubtract; + + FGAIndividualMods() + : Additive(0.0f), + Subtractive(0.0f), + Multiplicative(0.0f), + Divide(0.0f), + PercentageAdd(0.0f), + PercentageSubtract(0.0f) + {}; + FGAIndividualMods(float AdditiveIn, + float SubtractiveIn, + float MultiplicativeIn, + float DivideIn, + float PercentageAddIn, + float PercentageSubtractIn + ) + : Additive(AdditiveIn), + Subtractive(SubtractiveIn), + Multiplicative(MultiplicativeIn), + Divide(DivideIn), + PercentageAdd(PercentageAddIn), + PercentageSubtract(PercentageSubtractIn) + {} +}; +/** +* Struct representing single attribute. Needed for Pin customization. +* What we really need is to use this struct for making "complex" attributes. +* Which means attributes, which needs to track their own state. +* Bonuses applied to them, types of bonues, and who applied those bonuses +* so we can properly remove them, get them, track them, and controll order +* in which theyare added. +* we will two have attributes types. Staless (transient), auxiallry attttributes +* and staefull attributes, which are going to track their state. +*/ +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAAttribute +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY(EditAnywhere, BlueprintReadOnly) + FName AttributeName; + + inline bool operator== (const FGAAttribute& OtherAttribute) const + { + return (OtherAttribute.AttributeName == AttributeName); + } + + inline bool operator!= (const FGAAttribute& OtherAttribute) const + { + return (OtherAttribute.AttributeName != AttributeName); + } + + inline bool IsValid() const + { + return !AttributeName.IsNone(); + } + + inline FString ToString() + { + return AttributeName.ToString(); + } + + FGAAttribute() + { + AttributeName = NAME_None; + }; + FGAAttribute(const FName& AttributeNameIn) + { + AttributeName = AttributeNameIn; + }; + friend uint32 GetTypeHash(const FGAAttribute& InAttribute) + { + return GetTypeHash(InAttribute.AttributeName); + } + //FGAAttribute(const FString& AttributeNameIn) + //{ + // AttributeName = *AttributeNameIn; + //}; +}; + +/* Final calculcated mod from effect, which can be modified by Calculation object. */ +USTRUCT() +struct ABILITYFRAMEWORK_API FGAEffectMod +{ + GENERATED_BODY() +public: + FGAAttribute Attribute; + UPROPERTY() + float Value; + EGAAttributeMod AttributeMod; + struct FGAEffectHandle Handle; + FGameplayTagContainer AttributeTags; + /* + Spec from which this mod has been derived. + Used to do not copy to much heavy data around. + */ + inline bool CompareMods(const FGAEffectMod& OtherMod) const + { + return AttributeMod == OtherMod.AttributeMod; + } + inline bool HasAllTags(const FGameplayTagContainer& TagsIn) const + { + return AttributeTags.HasAll(TagsIn); + } + inline bool HasAllTagsExact(const FGAEffectMod& OtherMod) const + { + return AttributeTags.HasAllExact(OtherMod.AttributeTags); + } + inline bool HasAllTagsExact(const FGameplayTagContainer& TagsIn) const + { + return AttributeTags.HasAllExact(TagsIn); + } + inline bool HasAllTagsIncludingChildren(const FGameplayTagContainer& TagsIn) const + { + return TagsIn.HasAll(AttributeTags); + } + const bool operator==(const FGAEffectMod& Other) const + { + return Value == Other.Value && AttributeMod == Other.AttributeMod; + } + const bool operator!=(const FGAEffectMod& Other) const + { + return Value != Other.Value && AttributeMod == Other.AttributeMod; + } + + const bool operator>(const FGAEffectMod& Other) const + { + return Value > Other.Value && AttributeMod == Other.AttributeMod; + } + + const bool operator<(const FGAEffectMod& Other) const + { + return Value < Other.Value && AttributeMod == Other.AttributeMod; + } + const bool operator>=(const FGAEffectMod& Other) const + { + return Value >= Other.Value && AttributeMod == Other.AttributeMod; + } + + const bool operator<=(const FGAEffectMod& Other) const + { + return Value <= Other.Value && AttributeMod == Other.AttributeMod; + } + + + FGAEffectMod() + : Attribute(NAME_None), + Value(0), + AttributeMod(EGAAttributeMod::Invalid) + {}; + + FGAEffectMod(const FGAAttribute& AttributeIn, float ValueIn, + EGAAttributeMod AttributeModIn, FGAEffectHandle HandleIn, FGameplayTagContainer AttributeTagsIn) + : Attribute(AttributeIn), + Value(ValueIn), + AttributeMod(AttributeModIn), + Handle(HandleIn), + AttributeTags(AttributeTagsIn) + { + }; +}; + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FAFAttributeChangedData +{ + GENERATED_BODY() +public: + UPROPERTY() + FGAEffectMod Mod; + + UPROPERTY() + TWeakObjectPtr Target; + UPROPERTY() + FVector Location; + + UPROPERTY() + float NewValue; +}; + +/* +Struct representing final modifier applied to attribute. +*/ +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAModifier +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY() + EGAAttributeMod AttributeMod; + UPROPERTY() + float Value; + + FGameplayTagContainer Tags; + /* + Weak pointer to effect, which added this modifier. + Useful because, while effect exist it have lots of useful informations. + */ + struct FGAEffectHandle Handle; + + FGAModifier() + {}; + FGAModifier(EGAAttributeMod ModIn, float ValueIn) + : AttributeMod(ModIn), + Value(ValueIn) + {}; + FGAModifier(EGAAttributeMod ModIn, float ValueIn, FGAEffectHandle HandleIn) + : AttributeMod(ModIn), + Value(ValueIn), + Handle(HandleIn) + {}; + + FGAModifier(const FGAEffectMod& ModIn) + : AttributeMod(ModIn.AttributeMod), + Value(ModIn.Value), + Handle(ModIn.Handle) + {}; +}; + +USTRUCT() +struct ABILITYFRAMEWORK_API FGACountedTagContainer +{ + GENERATED_USTRUCT_BODY() +protected: + /* + Here we will store counted GamaplayTags. + If tag is already in map, we just incremement count. + */ + TMap CountedTags; + + /* + Here we store all currently posesd tags. + It is equivalent of CountedTags, except this does not track count of tags, but we need it + to have something against which we can perform queries. + */ +public: + UPROPERTY() + FGameplayTagContainer AllTags; +public: + + inline FGameplayTagContainer GetTags() { return AllTags; }; + + void AddTag(const FGameplayTag& TagIn); + void AddTagContainer(const FGameplayTagContainer& TagsIn); + void RemoveTag(const FGameplayTag& TagIn); + void RemoveTagContainer(const FGameplayTagContainer& TagsIn); + + bool HasTag(const FGameplayTag& TagIn); + bool HasTagExact(const FGameplayTag TagIn); + bool HasAny(const FGameplayTagContainer& TagsIn); + bool HasAnyExact(const FGameplayTagContainer& TagsIn); + bool HasAll(const FGameplayTagContainer& TagsIn); + bool HasAllExact(const FGameplayTagContainer& TagsIn); + + bool HasTag(const FGameplayTag& TagIn) const; + bool HasTagExact(const FGameplayTag TagIn) const; + bool HasAny(const FGameplayTagContainer& TagsIn) const; + bool HasAnyExact(const FGameplayTagContainer& TagsIn) const; + bool HasAll(const FGameplayTagContainer& TagsIn) const; + bool HasAllExact(const FGameplayTagContainer& TagsIn) const; + + inline FGameplayTagContainer& GetAllTags() + { + return AllTags; + } + + inline int32 GetTagCount(const FGameplayTag& TagIn) const + { + return CountedTags.FindRef(TagIn); + } +}; + + +USTRUCT(BlueprintType) +struct ABILITYFRAMEWORK_API FGAEffectCueParams +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY(BlueprintReadOnly, Category = "Gameplay Cue") + FHitResult HitResult; + + /** Instigator actor, the actor that owns the ability system component */ + UPROPERTY(BlueprintReadWrite, Category = "Gameplay Cue") + TWeakObjectPtr Instigator; + + /** The physical actor that actually did the damage, can be a weapon or projectile */ + UPROPERTY(BlueprintReadWrite, Category = "Gameplay Cue") + TWeakObjectPtr Causer; + + UPROPERTY(BlueprintReadOnly) + FGameplayTagContainer CueTags; + + FGAEffectCueParams() + {}; + FGAEffectCueParams(const FHitResult& InHitResult, AActor* InstigatorIn, UObject* CauserIn) + : HitResult(InHitResult), + Instigator(InstigatorIn), + Causer(CauserIn) + {}; + FGAEffectCueParams(const FGAEffectContext& InContext, const struct FGAEffectProperty& InProperty); + //bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess); +}; + +USTRUCT() +struct ABILITYFRAMEWORK_API FAFCueHandle +{ + GENERATED_BODY(); +private: + UPROPERTY() + uint32 Handle; + + FAFCueHandle(uint32 InHandle) + : Handle(InHandle) + {} +public: + FAFCueHandle() + : Handle(0) + {} + + static FAFCueHandle GenerateHandle(); + + bool operator==(const FAFCueHandle Other) const + { + return Handle == Other.Handle; + } + + friend uint32 GetTypeHash(const FAFCueHandle& InHandle) + { + return InHandle.Handle; + } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAHelperTemplates.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAHelperTemplates.h new file mode 100644 index 0000000..34b2f98 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAHelperTemplates.h @@ -0,0 +1,59 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "Engine/NetSerialization.h" +#include "GameplayTags.h" +#include "AFAbilityComponent.h" +#include "GAHelperTemplates.generated.h" + +USTRUCT(BlueprintType) +struct FGAAttributeSource +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere) + EGAAttributeSource Source; + /* Class which is source for attribute set. */ + UPROPERTY(EditAnywhere)//, meta = (MustImplement = "IGAAbilities")) + FGameplayTag AttributeSource; +}; + +USTRUCT(BlueprintType) +struct FGAAttributeCapture +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere) + FGAAttributeSource Source; + + UPROPERTY(EditAnywhere) + FGameplayTagContainer RequiredTags; + UPROPERTY(EditAnywhere) + FGameplayTagContainer DenyTags; + + template + T* GetAttributeSet(const FGAEffectContext& ContextIn) + { + UAFAbilityComponent* TargetComp = ContextIn.TargetComp.Get(); + UAFAbilityComponent* InstigatorComp = ContextIn.InstigatorComp.Get(); + T* AttributeSet = nullptr; + switch (Source.Source) + { + case EGAAttributeSource::Causer: + { + break; + } + case EGAAttributeSource::Target: + { + AttributeSet = TargetComp->GetAttributeSet(Source.AttributeSource); + break; + } + case EGAAttributeSource::Instigator: + { + AttributeSet = InstigatorComp->GetAttributeSet(Source.AttributeSource); + break; + } + } + return AttributeSet; + } +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAPhysicalMaterial.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAPhysicalMaterial.h new file mode 100644 index 0000000..429f1bd --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAPhysicalMaterial.h @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "PhysicalMaterials/PhysicalMaterial.h" +#include "GAPhysicalMaterial.generated.h" + +/** + * + */ +UCLASS(Blueprintable) +class ABILITYFRAMEWORK_API UGAPhysicalMaterial : public UPhysicalMaterial +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Category = "Fx") + UParticleEmitter* SurfaceHitFX; + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAUIData.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAUIData.h new file mode 100644 index 0000000..bc6d205 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/GAUIData.h @@ -0,0 +1,16 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "Object.h" +#include "GAUIData.generated.h" + +/** + * Base class for UI data for effect. + * Do not instance it. Just use CDO, to get data from it. + */ +UCLASS() +class ABILITYFRAMEWORK_API UGAUIData : public UObject +{ + GENERATED_BODY() +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/IAbilityFramework.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/IAbilityFramework.h new file mode 100644 index 0000000..8ff3a17 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/IAbilityFramework.h @@ -0,0 +1,37 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "Modules/ModuleManager.h" + + +/** + * The public interface to this module. In most cases, this interface is only public to sibling modules + * within this plugin. + */ +class IAbilityFramework : public IModuleInterface +{ + +public: + /** + * Singleton-like access to this module's interface. This is just for convenience! + * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. + * + * @return Returns singleton instance, loading the module on demand if needed + */ + static inline IAbilityFramework& Get() + { + return FModuleManager::LoadModuleChecked< IAbilityFramework >( "AbilityFramework" ); + } + + /** + * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. + * + * @return True if the module is loaded and ready to use + */ + static inline bool IsAvailable() + { + return FModuleManager::Get().IsModuleLoaded( "AbilityFramework" ); + } +}; + diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/AFLatentInterface.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/AFLatentInterface.h new file mode 100644 index 0000000..0ce54c8 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/AFLatentInterface.h @@ -0,0 +1,25 @@ +#pragma once +#include "AFLatentInterface.generated.h" + + +struct FAFAttributeBase; +struct FGAEffectHandle; +UINTERFACE(Blueprintable, meta = (CannotImplementInterfaceInBlueprint)) +class ABILITYFRAMEWORK_API UAFLatentInterface : public UInterface +{ + GENERATED_UINTERFACE_BODY() +}; + +class IAFLatentInterface +{ + GENERATED_IINTERFACE_BODY() +public: + virtual void OnLatentTaskAdded(FName InstanceName, class UAFTaskBase* TaskIn) = 0; + virtual void AddReplicatedTask(class UAFTaskBase* TaskIn) = 0; + virtual void OnLatentTaskRemoved(class UAFTaskBase* TaskIn) = 0; + + virtual void OnLatentTaskActivated(class UAFTaskBase* TaskIn) = 0; + virtual void OnLatentTaskDeactivated(class UAFTaskBase* TaskIn) = 0; + + virtual class UAFTaskBase* GetCachedLatentAction(FName TaskName) = 0; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/AFTaskBase.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/AFTaskBase.h new file mode 100644 index 0000000..ab9d327 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/AFTaskBase.h @@ -0,0 +1,103 @@ +#pragma once +#include "CoreMinimal.h" +#include "Engine/EngineBaseTypes.h" +#include "AFLatentInterface.h" + +#include "AFTaskBase.generated.h" + +struct FGALatentFunctionTick: public FTickFunction +{ + /** AActor that is the target of this tick **/ + class UAFTaskBase* Target; + + /** + * Abstract function actually execute the tick. + * @param DeltaTime - frame time to advance, in seconds + * @param TickType - kind of tick for this frame + * @param CurrentThread - thread we are executing on, useful to pass along as new tasks are created + * @param MyCompletionGraphEvent - completion event for this task. Useful for holding the completetion of this task until certain child tasks are complete. + **/ + virtual void ExecuteTick(float DeltaTime, ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) override; + /** Abstract function to describe this tick. Used to print messages about illegal cycles in the dependency graph **/ + virtual FString DiagnosticMessage() override; +}; + +UCLASS(meta = (ExposedAsyncProxy = "true")) +class ABILITYFRAMEWORK_API UAFTaskBase : public UObject +{ + GENERATED_BODY() + //never access internals of these classes directly. Use messages instead. +protected: + enum class EState : uint8 + { + Waiting, + Active, + Finished + }; + + EState TaskState; + bool bReplicated; + + UPROPERTY() + UObject* TaskOwner; + friend struct FGALatentFunctionTick; + FGALatentFunctionTick TickFunction; + + UAFTaskBase(const FObjectInitializer& ObjectInitializer); + virtual UWorld* GetWorld() const override; + + //virtual void Tick(float DeltaSecondsIn); + virtual void TickTask(float DeltaSeconds, ELevelTick TickType, FGALatentFunctionTick& ThisTickFunction) {}; + virtual void Initialize(); +public: + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"), Category = "Latent Action") + virtual void ReadyForActivation(); + virtual void EndTask(); +protected: + virtual void Activate() {}; + + virtual void BeginDestroy() override; + virtual void OnTaskEnded() {}; +public: + /* Replication */ + bool IsNameStableForNetworking() const override; + + bool IsSupportedForNetworking() const override + { + return bReplicated; + } + void SetNetAddressable(); + +protected: + + //use template to avoid using interface + template + static TaskType* NewTask(UObject* WorldContextObject, OwnerType* InTaskOwner, FName InstanceName = FName()) + { + TaskType* MyObj = nullptr; + + if (!InstanceName.IsNone()) + { + MyObj = Cast(InTaskOwner->GetCachedLatentAction(InstanceName)); + if (!MyObj) + { + MyObj = NewObject(WorldContextObject); + + InTaskOwner->OnLatentTaskAdded(InstanceName, MyObj); + } + } + else + { + MyObj = NewObject(WorldContextObject); + + InTaskOwner->OnLatentTaskAdded(InstanceName, MyObj); + } + if (MyObj->bReplicated) + { + InTaskOwner->AddReplicatedTask(MyObj); + } + MyObj->TaskOwner = InTaskOwner; + + return MyObj; + } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/AFTaskManager.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/AFTaskManager.h new file mode 100644 index 0000000..8a39299 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/AFTaskManager.h @@ -0,0 +1,17 @@ +#pragma once +#include "CoreMinimal.h" +#include "Engine/EngineBaseTypes.h" + +#include "AFTaskManager.generated.h" + +UCLASS() +class ABILITYFRAMEWORK_API UAFTaskManager : public UObject +{ + GENERATED_BODY() + + static UAFTaskManager* Instance; + +public: + UAFTaskManager(const FObjectInitializer& ObjectInitializer); + static UAFTaskManager* Get(); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/GAWaitAction.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/GAWaitAction.h new file mode 100644 index 0000000..af68fc7 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/LatentActions/GAWaitAction.h @@ -0,0 +1,42 @@ +#pragma once +#include "AFTaskBase.h" +#include "GAWaitAction.generated.h" +/* + AbilityActions are generic (preferably C++) defined actions, which then can be added to ability and + the should be activated from ability. + Then can perform tasks, like spawn tagetting helpers (splines, circles), spawn actors, + gather targeting data etc. + + Should they be activated automatically after ability is initialized, (it'e ability enterted in + active state, which means it's ready to be fired and display helpers, but did not yet received input, + or should designer in blueprint decide when to launch actions ?). +*/ +UCLASS(meta = (ExposedAsyncProxy = "true") ) +class ABILITYFRAMEWORK_API UGAWaitAction : public UAFTaskBase +{ + GENERATED_BODY() + +public: + UGAWaitAction(const FObjectInitializer& ObjectInitializer); + float Time; + float TimeStarted; + + DECLARE_DYNAMIC_MULTICAST_DELEGATE(FGAWaitActionDelegate); + UPROPERTY(BlueprintAssignable) + FGAWaitActionDelegate OnInitialized; + UPROPERTY(BlueprintAssignable) + FGAWaitActionDelegate OnFinish; + + UPROPERTY(BlueprintAssignable) + FGAWaitActionDelegate OnTick; + + //virtual void Tick(float DeltaSecondsIn); + + virtual void Activate() override; + virtual void TickTask(float DeltaSeconds, ELevelTick TickType, FGALatentFunctionTick& ThisTickFunction) override; + UFUNCTION(BlueprintCallable, Category = "Latent Actions", meta = (AdvancedDisplay = "InTaskOwner, Priority", DefaultToSelf = "InTaskOwner", BlueprintInternalUseOnly = "TRUE")) + static UGAWaitAction* NewGAWaitAction(UObject* InTaskOwner, float Time); + + void OnTimeFinish(); + +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFramework/Public/Mods/GAAttributeMod.h b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Mods/GAAttributeMod.h new file mode 100644 index 0000000..1363965 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFramework/Public/Mods/GAAttributeMod.h @@ -0,0 +1,32 @@ +#pragma once +#include "GAGlobalTypes.h" +#include "GameplayTagContainer.h" +#include "GAAttributeMod.generated.h" +/* + Using this class you can perform actions, when change to attribute is instigated. + Outcoming are modifiers appiled by instigator. + Incoming are modifiers appiled by target. + + Common applications are generic mods like damage reduction by armor or other attribute. + Increasing damage. + + Fireing other actions, when certain critera has been meet. + + This system is actually similiar to Effects from GameEffectSystem module. + + The main difference is that, attribute mods, cannot be appiled by other objects. You can add or remove + them on runtime, by providing set of classes, that can be added to component and the constructed. + + But you can't apply those mods by means like weapons or abilities. + They are always passive (as they are listening for events), they are always infinite + (their duration is for the entire lifetime of pawn/controller/game) + and they can't affect other attribute mods. They can only affect attributes, and trigger actions + based on them. This might include launching effects. + + As per usual using GameplayTags is recommened for defining behaviour. +*/ +UCLASS(BlueprintType, Blueprintable, DefaultToInstanced, EditInlineNew) +class ABILITYFRAMEWORK_API UGAAttributeMod : public UObject +{ + GENERATED_UCLASS_BODY() +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/AbilityFrameworkEditor.Build.cs b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/AbilityFrameworkEditor.Build.cs new file mode 100644 index 0000000..341096a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/AbilityFrameworkEditor.Build.cs @@ -0,0 +1,83 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +using UnrealBuildTool; +using System.IO; +namespace UnrealBuildTool.Rules +{ + public class AbilityFrameworkEditor : ModuleRules + { + public AbilityFrameworkEditor(ReadOnlyTargetRules Target) : base(Target) + { + var EngineDir = Path.GetFullPath(Target.RelativeEnginePath); + + PrivateIncludePaths.AddRange( + new string[] { + "AbilityFrameworkEditor/Private", + Path.Combine(EngineDir, @"Source/Editor/GraphEditor/Private"), + Path.Combine(EngineDir, @"Source/Editor/Kismet/Private"), + Path.Combine(EngineDir, @"Source/Editor/PropertyEditor/Private"), + Path.Combine(EngineDir, @"Source/Developer/AssetTools/Private"), + // ... add other private include paths required here ... + } + ); + PrivateIncludePathModuleNames.AddRange( + new string[] { + "UnrealEd", + "AssetTools", + "PropertyEditor", + "MovieScene", + "MovieSceneTools", + "MovieSceneTracks", + "Sequencer", + "ActorSequence" + }); + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "Engine", + "CoreUObject", + "AssetTools", + "UnrealEd", + "BlueprintGraph", + "GraphEditor", + "PropertyEditor", + "SlateCore", + "Slate", + "EditorStyle", + "Kismet", + "KismetCompiler", + "AssetTools", + "MainFrame", + "InputCore", + "AbilityFramework", + "MovieScene", + "MovieSceneTools", + "MovieSceneTracks", + "Sequencer", + "ActorSequence" + // ... add other public dependencies that you statically link with here ... + } + ); + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "Core", + "Engine", + "CoreUObject", + "AssetTools", + "UnrealEd", + "PropertyEditor", + // ... add private dependencies that you statically link with here ... + } + ); + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } + } +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityActionSpecDetails.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityActionSpecDetails.cpp new file mode 100644 index 0000000..02f483d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityActionSpecDetails.cpp @@ -0,0 +1,75 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" + +#include "STextCombobox.h" +#include "STreeView.h" + +#include "Abilities/AFAbilityActivationSpec.h" +#include "AFAbilityActionSpecDetails.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFEffectCustomizationCommon.h" +TSharedRef FAFAbilityActivationSpecDetails::MakeInstance() +{ + return MakeShareable(new FAFAbilityActivationSpecDetails); +} + +void FAFAbilityActivationSpecDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) +{ + MyDetailLayout = &DetailLayout; + + TArray> Objects; + DetailLayout.GetObjectsBeingCustomized(Objects); + + ApplicationTypeHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Application), UGAGameEffectSpec::StaticClass()); + UpdateEffectTypeyDelegate = FSimpleDelegate::CreateSP(this, &FAFAbilityActivationSpecDetails::OnDurationPolicyChange); + ApplicationTypeHandle->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + + for (TWeakObjectPtr obj : Objects) + { + if (UAFAbilityActivationSpec* Spec = Cast(obj.Get())) + { + bIsDuration = Spec->Application.GetDefaultObject()->ShowDuration(); + bIsPeriodic = Spec->Application.GetDefaultObject()->ShowPeriod(); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ApplicationRequirement"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Application"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "EffectAggregation"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "MaxStackedDuration"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "MaxStacks"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "bTickOnApplication"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "bExecuteOnApplication"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Extension"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnAppliedEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnExpiredEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnRemovedEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ConditonalEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "RemoveEffectWithTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AtributeModifier"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Modifiers"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedEventTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ExecuteEventTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AttributeTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "DenyTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedImmunityTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "RequiredTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ExecutionRequiredTags"); + + DurationProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Duration), UGAGameEffectSpec::StaticClass()); + PeriodProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Period), UGAGameEffectSpec::StaticClass()); + + DetailLayout.HideProperty(DurationProperty); + DetailLayout.HideProperty(PeriodProperty); + DurationCalcTypeProp = DurationProperty->GetChildHandle("CalculationType"); + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, DurationProperty, "Duration"); + DurationCalcTypeProp->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + } + } +} +void FAFAbilityActivationSpecDetails::OnDurationPolicyChange() +{ + MyDetailLayout->ForceRefreshDetails(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityActionSpecDetails.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityActionSpecDetails.h new file mode 100644 index 0000000..75a6c49 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityActionSpecDetails.h @@ -0,0 +1,31 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypesEditor.h" + +#include "IDetailCustomization.h" +#include "PropertyHandle.h" + +class FAFAbilityActivationSpecDetails : public IDetailCustomization +{ + +protected: + bool bIsDuration; + bool bIsPeriodic; + TSharedPtr ApplicationTypeHandle; +public: + /** Makes a new instance of this detail layout class for a specific detail view requesting it */ + static TSharedRef MakeInstance(); + +private: + TSharedPtr MyProperty; + TSharedPtr DurationProperty; + TSharedPtr PeriodProperty; + TSharedPtr DurationCalcTypeProp; + IDetailLayoutBuilder* MyDetailLayout; + FSimpleDelegate UpdateEffectTypeyDelegate; + /** IDetailCustomization interface */ + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override; + + void OnDurationPolicyChange(); +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityCooldownSpecDetails.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityCooldownSpecDetails.cpp new file mode 100644 index 0000000..217ee21 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityCooldownSpecDetails.cpp @@ -0,0 +1,75 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" + +#include "STextCombobox.h" +#include "STreeView.h" + +#include "Abilities/AFAbilityCooldownSpec.h" +#include "AFAbilityCooldownSpecDetails.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFEffectCustomizationCommon.h" +TSharedRef FAFAbilityCooldownSpecDetails::MakeInstance() +{ + return MakeShareable(new FAFAbilityCooldownSpecDetails); +} + +void FAFAbilityCooldownSpecDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) +{ + MyDetailLayout = &DetailLayout; + + TArray> Objects; + DetailLayout.GetObjectsBeingCustomized(Objects); + + ApplicationTypeHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Application), UGAGameEffectSpec::StaticClass()); + FSimpleDelegate UpdateEffectTypeyDelegate = FSimpleDelegate::CreateSP(this, &FAFAbilityCooldownSpecDetails::OnDurationPolicyChange); + ApplicationTypeHandle->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + + for (TWeakObjectPtr obj : Objects) + { + if (UAFAbilityCooldownSpec* Spec = Cast(obj.Get())) + { + bIsDuration = Spec->Application.GetDefaultObject()->ShowDuration(); + bIsPeriodic = Spec->Application.GetDefaultObject()->ShowPeriod(); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ApplicationRequirement"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Application"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "EffectAggregation"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "MaxStackedDuration"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "MaxStacks"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "bTickOnApplication"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "bExecuteOnApplication"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Extension"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnAppliedEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnExpiredEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnRemovedEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ConditonalEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "RemoveEffectWithTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AtributeModifier"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Modifiers"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedEventTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ExecuteEventTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AttributeTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "DenyTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedImmunityTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "RequiredTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ExecutionRequiredTags"); + + DurationProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Duration), UGAGameEffectSpec::StaticClass()); + PeriodProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Period), UGAGameEffectSpec::StaticClass()); + + DetailLayout.HideProperty(DurationProperty); + DetailLayout.HideProperty(PeriodProperty); + DurationCalcTypeProp = DurationProperty->GetChildHandle("CalculationType"); + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, DurationProperty, "Duration"); + DurationCalcTypeProp->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + } + } +} +void FAFAbilityCooldownSpecDetails::OnDurationPolicyChange() +{ + MyDetailLayout->ForceRefreshDetails(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityCooldownSpecDetails.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityCooldownSpecDetails.h new file mode 100644 index 0000000..be653a3 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityCooldownSpecDetails.h @@ -0,0 +1,30 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypesEditor.h" + +#include "IDetailCustomization.h" +#include "PropertyHandle.h" + +class FAFAbilityCooldownSpecDetails : public IDetailCustomization +{ + +protected: + bool bIsDuration; + bool bIsPeriodic; + TSharedPtr ApplicationTypeHandle; +public: + /** Makes a new instance of this detail layout class for a specific detail view requesting it */ + static TSharedRef MakeInstance(); + +private: + TSharedPtr MyProperty; + TSharedPtr DurationProperty; + TSharedPtr PeriodProperty; + TSharedPtr DurationCalcTypeProp; + IDetailLayoutBuilder* MyDetailLayout; + /** IDetailCustomization interface */ + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override; + + void OnDurationPolicyChange(); +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfiniteDurationSpecDetails.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfiniteDurationSpecDetails.cpp new file mode 100644 index 0000000..d99ea2b --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfiniteDurationSpecDetails.cpp @@ -0,0 +1,83 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" + +#include "STextCombobox.h" +#include "STreeView.h" + +#include "Abilities/AFAbilityInfiniteDurationSpec.h" +#include "AFAbilityInfiniteDurationSpecDetails.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFEffectCustomizationCommon.h" +TSharedRef FAFAbilityInfiniteDurationSpecDetails::MakeInstance() +{ + return MakeShareable(new FAFAbilityInfiniteDurationSpecDetails); +} + +void FAFAbilityInfiniteDurationSpecDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) +{ + MyDetailLayout = &DetailLayout; + + TArray> Objects; + DetailLayout.GetObjectsBeingCustomized(Objects); + + ApplicationTypeHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Application), UGAGameEffectSpec::StaticClass()); + FSimpleDelegate UpdateEffectTypeyDelegate = FSimpleDelegate::CreateSP(this, &FAFAbilityInfiniteDurationSpecDetails::OnDurationPolicyChange); + ApplicationTypeHandle->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + + for (TWeakObjectPtr obj : Objects) + { + if (UAFAbilityInfiniteDurationSpec* Spec = Cast(obj.Get())) + { + bIsDuration = Spec->Application.GetDefaultObject()->ShowDuration(); + bIsPeriodic = Spec->Application.GetDefaultObject()->ShowPeriod(); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ApplicationRequirement"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Application"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "EffectAggregation"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "MaxStackedDuration"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "MaxStacks"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "bTickOnApplication"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "bExecuteOnApplication"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Extension"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnAppliedEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnExpiredEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnRemovedEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ConditonalEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "RemoveEffectWithTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AtributeModifier"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Modifiers"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedEventTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ExecuteEventTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AttributeTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "DenyTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedImmunityTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "RequiredTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ExecutionRequiredTags"); + + DurationProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Duration), UGAGameEffectSpec::StaticClass()); + PeriodProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Period), UGAGameEffectSpec::StaticClass()); + DetailLayout.HideCategory("Duration"); + DetailLayout.HideCategory("Period"); + + DetailLayout.HideProperty(DurationProperty); + DetailLayout.HideProperty(PeriodProperty); + DurationCalcTypeProp = DurationProperty->GetChildHandle("CalculationType"); + PeriodCalcTypeProp = PeriodProperty->GetChildHandle("CalculationType"); + + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, DurationProperty, "Duration"); + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, PeriodProperty, "Period"); + + DurationCalcTypeProp->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + PeriodCalcTypeProp->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + } + } +} +void FAFAbilityInfiniteDurationSpecDetails::OnDurationPolicyChange() +{ + MyDetailLayout->ForceRefreshDetails(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfiniteDurationSpecDetails.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfiniteDurationSpecDetails.h new file mode 100644 index 0000000..c1b4218 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfiniteDurationSpecDetails.h @@ -0,0 +1,31 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypesEditor.h" + +#include "IDetailCustomization.h" +#include "PropertyHandle.h" + +class FAFAbilityInfiniteDurationSpecDetails : public IDetailCustomization +{ + +protected: + bool bIsDuration; + bool bIsPeriodic; + TSharedPtr ApplicationTypeHandle; +public: + /** Makes a new instance of this detail layout class for a specific detail view requesting it */ + static TSharedRef MakeInstance(); + +private: + TSharedPtr MyProperty; + TSharedPtr DurationProperty; + TSharedPtr PeriodProperty; + TSharedPtr DurationCalcTypeProp; + TSharedPtr PeriodCalcTypeProp; + IDetailLayoutBuilder* MyDetailLayout; + /** IDetailCustomization interface */ + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override; + + void OnDurationPolicyChange(); +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfinitePeriodSpecDetails.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfinitePeriodSpecDetails.cpp new file mode 100644 index 0000000..38f91d2 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfinitePeriodSpecDetails.cpp @@ -0,0 +1,83 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" + +#include "STextCombobox.h" +#include "STreeView.h" + +#include "Abilities/AFAbilityPeriodicInfiniteSpec.h" +#include "AFAbilityInfinitePeriodSpecDetails.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFEffectCustomizationCommon.h" +TSharedRef FAFAbilityInfinitePeriodSpecDetails::MakeInstance() +{ + return MakeShareable(new FAFAbilityInfinitePeriodSpecDetails); +} + +void FAFAbilityInfinitePeriodSpecDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) +{ + MyDetailLayout = &DetailLayout; + + TArray> Objects; + DetailLayout.GetObjectsBeingCustomized(Objects); + + ApplicationTypeHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Application), UGAGameEffectSpec::StaticClass()); + FSimpleDelegate UpdateEffectTypeyDelegate = FSimpleDelegate::CreateSP(this, &FAFAbilityInfinitePeriodSpecDetails::OnDurationPolicyChange); + ApplicationTypeHandle->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + + for (TWeakObjectPtr obj : Objects) + { + if (UAFAbilityPeriodicInfiniteSpec* Spec = Cast(obj.Get())) + { + bIsDuration = Spec->Application.GetDefaultObject()->ShowDuration(); + bIsPeriodic = Spec->Application.GetDefaultObject()->ShowPeriod(); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ApplicationRequirement"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Application"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "EffectAggregation"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "MaxStackedDuration"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "MaxStacks"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "bTickOnApplication"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "bExecuteOnApplication"); + + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Extension"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnAppliedEffects"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnExpiredEffects"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnRemovedEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ConditonalEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "RemoveEffectWithTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AtributeModifier"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Modifiers"); + + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedEventTags"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ExecuteEventTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AttributeTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "DenyTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedImmunityTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "RequiredTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ExecutionRequiredTags"); + + DetailLayout.HideCategory("Duration"); + + DurationProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Duration), UGAGameEffectSpec::StaticClass()); + PeriodProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Period), UGAGameEffectSpec::StaticClass()); + + DetailLayout.HideProperty(DurationProperty); + DetailLayout.HideProperty(PeriodProperty); + DurationCalcTypeProp = DurationProperty->GetChildHandle("CalculationType"); + PeriodCalcTypeProp = PeriodProperty->GetChildHandle("CalculationType"); + + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, DurationProperty, "Duration"); + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, PeriodProperty, "Period"); + + DurationCalcTypeProp->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + PeriodCalcTypeProp->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + } + } +} +void FAFAbilityInfinitePeriodSpecDetails::OnDurationPolicyChange() +{ + MyDetailLayout->ForceRefreshDetails(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfinitePeriodSpecDetails.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfinitePeriodSpecDetails.h new file mode 100644 index 0000000..bdffbdd --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityInfinitePeriodSpecDetails.h @@ -0,0 +1,31 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypesEditor.h" + +#include "IDetailCustomization.h" +#include "PropertyHandle.h" + +class FAFAbilityInfinitePeriodSpecDetails : public IDetailCustomization +{ + +protected: + bool bIsDuration; + bool bIsPeriodic; + TSharedPtr ApplicationTypeHandle; +public: + /** Makes a new instance of this detail layout class for a specific detail view requesting it */ + static TSharedRef MakeInstance(); + +private: + TSharedPtr MyProperty; + TSharedPtr DurationProperty; + TSharedPtr PeriodProperty; + TSharedPtr DurationCalcTypeProp; + TSharedPtr PeriodCalcTypeProp; + IDetailLayoutBuilder* MyDetailLayout; + /** IDetailCustomization interface */ + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override; + + void OnDurationPolicyChange(); +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityPeriodSpecDetails.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityPeriodSpecDetails.cpp new file mode 100644 index 0000000..8fe5b22 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityPeriodSpecDetails.cpp @@ -0,0 +1,81 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" + +#include "STextCombobox.h" +#include "STreeView.h" + +#include "Abilities/AFAbilityPeriodSpec.h" +#include "AFAbilityPeriodSpecDetails.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFEffectCustomizationCommon.h" +TSharedRef FAFAbilityPeriodSpecDetails::MakeInstance() +{ + return MakeShareable(new FAFAbilityPeriodSpecDetails); +} + +void FAFAbilityPeriodSpecDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) +{ + MyDetailLayout = &DetailLayout; + + TArray> Objects; + DetailLayout.GetObjectsBeingCustomized(Objects); + + ApplicationTypeHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Application), UGAGameEffectSpec::StaticClass()); + FSimpleDelegate UpdateEffectTypeyDelegate = FSimpleDelegate::CreateSP(this, &FAFAbilityPeriodSpecDetails::OnDurationPolicyChange); + ApplicationTypeHandle->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + + for (TWeakObjectPtr obj : Objects) + { + if (UAFAbilityPeriodSpec* Spec = Cast(obj.Get())) + { + bIsDuration = Spec->Application.GetDefaultObject()->ShowDuration(); + bIsPeriodic = Spec->Application.GetDefaultObject()->ShowPeriod(); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ApplicationRequirement"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Application"); + + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "EffectAggregation"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "MaxStackedDuration"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "MaxStacks"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "bTickOnApplication"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "bExecuteOnApplication"); + + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Extension"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnAppliedEffects"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnExpiredEffects"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnRemovedEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ConditonalEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "RemoveEffectWithTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AtributeModifier"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "Modifiers"); + + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedEventTags"); + //FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ExecuteEventTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AttributeTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "DenyTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedImmunityTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "RequiredTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ExecutionRequiredTags"); + + DurationProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Duration), UGAGameEffectSpec::StaticClass()); + PeriodProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Period), UGAGameEffectSpec::StaticClass()); + + DetailLayout.HideProperty(DurationProperty); + DetailLayout.HideProperty(PeriodProperty); + DurationCalcTypeProp = DurationProperty->GetChildHandle("CalculationType"); + PeriodCalcTypeProp = PeriodProperty->GetChildHandle("CalculationType"); + + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, DurationProperty, "Duration"); + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, PeriodProperty, "Period"); + + DurationCalcTypeProp->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + PeriodCalcTypeProp->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + } + } +} +void FAFAbilityPeriodSpecDetails::OnDurationPolicyChange() +{ + MyDetailLayout->ForceRefreshDetails(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityPeriodSpecDetails.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityPeriodSpecDetails.h new file mode 100644 index 0000000..b5e4527 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFAbilityPeriodSpecDetails.h @@ -0,0 +1,31 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypesEditor.h" + +#include "IDetailCustomization.h" +#include "PropertyHandle.h" + +class FAFAbilityPeriodSpecDetails : public IDetailCustomization +{ + +protected: + bool bIsDuration; + bool bIsPeriodic; + TSharedPtr ApplicationTypeHandle; +public: + /** Makes a new instance of this detail layout class for a specific detail view requesting it */ + static TSharedRef MakeInstance(); + +private: + TSharedPtr MyProperty; + TSharedPtr DurationProperty; + TSharedPtr PeriodProperty; + TSharedPtr DurationCalcTypeProp; + TSharedPtr PeriodCalcTypeProp; + IDetailLayoutBuilder* MyDetailLayout; + /** IDetailCustomization interface */ + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override; + + void OnDurationPolicyChange(); +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEK2Node_AsyncEffectTaskCall.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEK2Node_AsyncEffectTaskCall.cpp new file mode 100644 index 0000000..f0898d5 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEK2Node_AsyncEffectTaskCall.cpp @@ -0,0 +1,79 @@ + +#include "AbilityFrameworkEditor.h" +#include "Kismet/KismetMathLibrary.h" +#include "Kismet/KismetArrayLibrary.h" +#include "LatentActions/AFTaskBase.h" +#include "Effects/EffectTasks/AFEffectTask.h" +#include "Effects/GAEffectExtension.h" +#include "KismetCompiler.h" +#include "BlueprintEditorUtils.h" +#include "AFEK2Node_AsyncEffectTaskCall.h" +#include "K2Node_EnumLiteral.h" +#include "BlueprintFunctionNodeSpawner.h" +#include "BlueprintActionDatabaseRegistrar.h" + +#define LOCTEXT_NAMESPACE "K2Node" + +UAFEK2Node_AsyncEffectTaskCall::UAFEK2Node_AsyncEffectTaskCall(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + ProxyActivateFunctionName = GET_FUNCTION_NAME_CHECKED(UAFTaskBase, ReadyForActivation); +} + +bool UAFEK2Node_AsyncEffectTaskCall::IsCompatibleWithGraph(UEdGraph const* TargetGraph) const +{ + bool bIsCompatible = false; + + EGraphType GraphType = TargetGraph->GetSchema()->GetGraphType(TargetGraph); + bool const bAllowLatentFuncs = (GraphType == GT_Ubergraph || GraphType == GT_Macro); + + if (bAllowLatentFuncs) + { + UBlueprint* MyBlueprint = FBlueprintEditorUtils::FindBlueprintForGraph(TargetGraph); + if (MyBlueprint && MyBlueprint->GeneratedClass) + { + if (MyBlueprint->GeneratedClass->IsChildOf(UGAEffectExtension::StaticClass())) + { + bIsCompatible = true; + } + } + } + return bIsCompatible; +} + + +void UAFEK2Node_AsyncEffectTaskCall::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const +{ + //UK2Node_BaseAsyncTask::GetMenuActions(ActionRegistrar); + struct GetMenuActions_Utils + { + static void SetNodeFunc(UEdGraphNode* NewNode, bool /*bIsTemplateNode*/, TWeakObjectPtr FunctionPtr) + { + UAFEK2Node_AsyncEffectTaskCall* AsyncTaskNode = CastChecked(NewNode); + if (FunctionPtr.IsValid()) + { + UFunction* Func = FunctionPtr.Get(); + UObjectProperty* ReturnProp = CastChecked(Func->GetReturnProperty()); + + AsyncTaskNode->ProxyFactoryFunctionName = Func->GetFName(); + AsyncTaskNode->ProxyFactoryClass = Func->GetOuterUClass(); + AsyncTaskNode->ProxyClass = ReturnProp->PropertyClass; + } + } + }; + + UClass* NodeClass = GetClass(); + //FBlueprintActionDatabaseRegistrar::FMakeFuncSpawnerDelegate::CreateUObject(this, &UGAEK2Node_LatentAbilityTaskCall::CreateNodeSpawner); + ActionRegistrar.RegisterClassFactoryActions(FBlueprintActionDatabaseRegistrar::FMakeFuncSpawnerDelegate::CreateLambda([NodeClass](const UFunction* FactoryFunc)->UBlueprintNodeSpawner* + { + UBlueprintNodeSpawner* NodeSpawner = UBlueprintFunctionNodeSpawner::Create(FactoryFunc); + check(NodeSpawner != nullptr); + NodeSpawner->NodeClass = NodeClass; + + TWeakObjectPtr FunctionPtr = const_cast(FactoryFunc); + NodeSpawner->CustomizeNodeDelegate = UBlueprintNodeSpawner::FCustomizeNodeDelegate::CreateStatic(GetMenuActions_Utils::SetNodeFunc, FunctionPtr); + return NodeSpawner; + })); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEK2Node_AsyncEffectTaskCall.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEK2Node_AsyncEffectTaskCall.h new file mode 100644 index 0000000..d9c7d0f --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEK2Node_AsyncEffectTaskCall.h @@ -0,0 +1,20 @@ + +#pragma once +#include "EdGraph/EdGraphPin.h" +#include "EdGraphSchema_K2.h" +#include "K2Node_BaseAsyncTask.h" +#include "AFEK2Node_AsyncEffectTaskCall.generated.h" + +UCLASS() +class UAFEK2Node_AsyncEffectTaskCall : public UK2Node_BaseAsyncTask +{ + GENERATED_BODY() + +public: + UAFEK2Node_AsyncEffectTaskCall(const FObjectInitializer& ObjectInitializer); + + // UEdGraphNode interface + virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const override; + virtual bool IsCompatibleWithGraph(UEdGraph const* TargetGraph) const override; + // End of UEdGraphNode interface +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEffectCustomizationCommon.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEffectCustomizationCommon.cpp new file mode 100644 index 0000000..ea1ff60 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEffectCustomizationCommon.cpp @@ -0,0 +1,111 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AbilityFrameworkEditor.h" +#include "Effects/GAGameEffect.h" +#include "DetailLayoutBuilder.h" +#include "DetailCategoryBuilder.h" +#include "IDetailGroup.h" +#include "AFEffectCustomizationCommon.h" + +FAFEffectCustomizationCommon::FAFEffectCustomizationCommon() +{ +} + +FAFEffectCustomizationCommon::~FAFEffectCustomizationCommon() +{ +} +void FAFEffectCustomizationCommon::CreateMagnitudeLayout(IDetailLayoutBuilder& DetailLayout, + TSharedPtr& InProperty, FName InCategory) +{ + IDetailCategoryBuilder& DurationCategory = DetailLayout.EditCategory(InCategory); + + TSharedPtr DurationCalcTypeProp = InProperty->GetChildHandle("CalculationType"); + + uint8 CalcType = 0; + DurationCalcTypeProp->GetValue(CalcType); + + TSharedPtr DirectModifier = InProperty->GetChildHandle("DirectModifier"); + TSharedPtr AttributeBased = InProperty->GetChildHandle("AttributeBased"); + TSharedPtr CurveBased = InProperty->GetChildHandle("CurveBased"); + TSharedPtr Custom = InProperty->GetChildHandle("Custom"); + + DurationCategory.AddProperty(DurationCalcTypeProp.ToSharedRef()); + switch (CalcType) + { + case 0: //Direct + { + DetailLayout.HideProperty(DirectModifier); + DetailLayout.HideProperty(AttributeBased); + DetailLayout.HideProperty(CurveBased); + DetailLayout.HideProperty(Custom); + + TSharedPtr Value = DirectModifier->GetChildHandle("Value"); + DurationCategory.AddProperty(Value.ToSharedRef()); + //DetailGroup. + break; + } + case 1: //AttributeBased + { + DetailLayout.HideProperty(DirectModifier); + DetailLayout.HideProperty(AttributeBased); + DetailLayout.HideProperty(CurveBased); + DetailLayout.HideProperty(Custom); + + TSharedPtr Source = AttributeBased->GetChildHandle("Source"); + TSharedPtr Attribute = AttributeBased->GetChildHandle("Attribute"); + TSharedPtr Coefficient = AttributeBased->GetChildHandle("Coefficient"); + TSharedPtr PreMultiply = AttributeBased->GetChildHandle("PreMultiply"); + TSharedPtr PostMultiply = AttributeBased->GetChildHandle("PostMultiply"); + TSharedPtr PostCoefficient = AttributeBased->GetChildHandle("PostCoefficient"); + TSharedPtr bUseSecondaryAttribute = AttributeBased->GetChildHandle("bUseSecondaryAttribute"); + TSharedPtr SecondarySource = AttributeBased->GetChildHandle("SecondarySource"); + TSharedPtr SecondaryAttribute = AttributeBased->GetChildHandle("SecondaryAttribute"); + + DurationCategory.AddProperty(Source.ToSharedRef()); + DurationCategory.AddProperty(Attribute.ToSharedRef()); + DurationCategory.AddProperty(Coefficient.ToSharedRef()); + DurationCategory.AddProperty(PreMultiply.ToSharedRef()); + DurationCategory.AddProperty(PostMultiply.ToSharedRef()); + DurationCategory.AddProperty(PostCoefficient.ToSharedRef()); + DurationCategory.AddProperty(bUseSecondaryAttribute.ToSharedRef()); + DurationCategory.AddProperty(SecondarySource.ToSharedRef()); + DurationCategory.AddProperty(SecondaryAttribute.ToSharedRef()); + + break; + } + case 2: //CurveBased + { + DetailLayout.HideProperty(AttributeBased); + DetailLayout.HideProperty(DirectModifier); + DetailLayout.HideProperty(CurveBased); + DetailLayout.HideProperty(Custom); + + TSharedPtr Source = CurveBased->GetChildHandle("Source"); + TSharedPtr Attribute = CurveBased->GetChildHandle("Attribute"); + TSharedPtr CurveTable = CurveBased->GetChildHandle("CurveTable"); + + DurationCategory.AddProperty(Source.ToSharedRef()); + DurationCategory.AddProperty(Attribute.ToSharedRef()); + DurationCategory.AddProperty(CurveTable.ToSharedRef()); + break; + } + case 3: //CustomCalculation + { + DetailLayout.HideProperty(AttributeBased); + DetailLayout.HideProperty(CurveBased); + DetailLayout.HideProperty(DirectModifier); + DetailLayout.HideProperty(Custom); + + TSharedPtr CustomCalculation = Custom->GetChildHandle("CustomCalculation"); + DurationCategory.AddProperty(CustomCalculation.ToSharedRef()); + break; + } + } +} +void FAFEffectCustomizationCommon::HideProperty(IDetailLayoutBuilder& DetailLayout, FName InName) +{ + UProperty* prop = UGAGameEffectSpec::StaticClass()->FindPropertyByName(InName); + + TSharedPtr Property = DetailLayout.GetProperty(InName, UGAGameEffectSpec::StaticClass()); + DetailLayout.HideProperty(Property); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEffectCustomizationCommon.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEffectCustomizationCommon.h new file mode 100644 index 0000000..2c495a7 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AFEffectCustomizationCommon.h @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "IDetailCustomization.h" +#include "PropertyHandle.h" +/** + * + */ +class ABILITYFRAMEWORKEDITOR_API FAFEffectCustomizationCommon +{ +public: + FAFEffectCustomizationCommon(); + ~FAFEffectCustomizationCommon(); + static void CreateMagnitudeLayout(IDetailLayoutBuilder& DetailLayout, + TSharedPtr& InProperty, FName InCategory); + static void HideProperty(IDetailLayoutBuilder& DetailLayout, FName InName); +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/AssetTypeActions_GAAbilityBlueprint.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/AssetTypeActions_GAAbilityBlueprint.cpp new file mode 100644 index 0000000..0e2b42a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/AssetTypeActions_GAAbilityBlueprint.cpp @@ -0,0 +1,57 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#include "../AbilityFrameworkEditor.h" +#include "AssetTypeActions_GAAbilityBlueprint.h" +#include "Misc/MessageDialog.h" +#include "Kismet2/BlueprintEditorUtils.h" +#include "GAAbilityEditor.h" +#include "Abilities/GAAbilityBlueprint.h" +#include "Abilities/GAAbilityBase.h" +#include "GAAbilityBlueprintFactory.h" + +#define LOCTEXT_NAMESPACE "AssetTypeActions" + +FText FAssetTypeActions_GAAbilityBlueprint::GetName() const +{ + return FText::FromString("Ability"); +} +UClass* FAssetTypeActions_GAAbilityBlueprint::GetSupportedClass() const +{ + return UGAAbilityBlueprint::StaticClass(); +} + +void FAssetTypeActions_GAAbilityBlueprint::OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor) +{ + EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone; + + for (auto ObjIt = InObjects.CreateConstIterator(); ObjIt; ++ObjIt) + { + auto Blueprint = Cast(*ObjIt); + if (Blueprint && Blueprint->SkeletonGeneratedClass && Blueprint->GeneratedClass) + { + TSharedRef< FGAAbilityEditor > NewEditor(new FGAAbilityEditor()); + + TArray Blueprints; + Blueprints.Add(Blueprint); + + NewEditor->InitAbilitiesEditor(Mode, EditWithinLevelEditor, Blueprints, ShouldUseDataOnlyEditor(Blueprint)); + } + else + { + FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Ability Blueprint could not be loaded because it derives from an invalid class. Check to make sure the parent class for this blueprint hasn't been removed!")); + } + } +} + +bool FAssetTypeActions_GAAbilityBlueprint::ShouldUseDataOnlyEditor(const UBlueprint* Blueprint) const +{ + return false; +} + +UFactory* FAssetTypeActions_GAAbilityBlueprint::GetFactoryForBlueprintType(UBlueprint* InBlueprint) const +{ + UGAAbilityBlueprintFactory* AbilityBlueprintFactory = NewObject(); + AbilityBlueprintFactory->ParentClass = TSubclassOf(*InBlueprint->GeneratedClass); + return AbilityBlueprintFactory; +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/AssetTypeActions_GAAbilityBlueprint.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/AssetTypeActions_GAAbilityBlueprint.h new file mode 100644 index 0000000..78b71c1 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/AssetTypeActions_GAAbilityBlueprint.h @@ -0,0 +1,27 @@ +#pragma once +#include "CoreMinimal.h" +#include "Toolkits/IToolkitHost.h" +#include "AssetTypeCategories.h" +//#include "Developer/AssetTools/Private/AssetTypeActions/AssetTypeActions_ClassTypeBase.h" +#include "Developer/AssetTools/Public/AssetTypeActions/AssetTypeActions_Blueprint.h" + +class UFactory; + +class FAssetTypeActions_GAAbilityBlueprint : public FAssetTypeActions_Blueprint +{ +public: + // IAssetTypeActions Implementation + virtual FText GetName() const override; + virtual FColor GetTypeColor() const override { return FColor(0, 96, 128); } + virtual UClass* GetSupportedClass() const override; + virtual void OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor = TSharedPtr()) override; + virtual uint32 GetCategories() override { return EAssetTypeCategories::Gameplay; } + // End IAssetTypeActions Implementation + + // FAssetTypeActions_Blueprint interface + virtual UFactory* GetFactoryForBlueprintType(UBlueprint* InBlueprint) const override; + +private: + /** Returns true if the blueprint is data only */ + bool ShouldUseDataOnlyEditor(const UBlueprint* Blueprint) const; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityBlueprintFactory.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityBlueprintFactory.cpp new file mode 100644 index 0000000..3493cac --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityBlueprintFactory.cpp @@ -0,0 +1,334 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +#include "../AbilityFrameworkEditor.h" +#include "GAAbilityBlueprintFactory.h" +#include "InputCoreTypes.h" +#include "UObject/Interface.h" +#include "Layout/Visibility.h" +#include "Input/Reply.h" +#include "Widgets/SWidget.h" +#include "Widgets/DeclarativeSyntaxSupport.h" +#include "Misc/MessageDialog.h" +#include "Modules/ModuleManager.h" +#include "Effects/GAGameEffect.h" +#include "Widgets/SCompoundWidget.h" +#include "Widgets/SBoxPanel.h" +#include "Widgets/SWindow.h" +#include "Widgets/Layout/SBorder.h" +#include "Widgets/Text/STextBlock.h" +#include "Widgets/Layout/SBox.h" +#include "Widgets/Layout/SUniformGridPanel.h" +#include "Widgets/Input/SButton.h" +#include "EditorStyleSet.h" +#include "Editor.h" +#include "EdGraphSchema_K2.h" + +#include "ClassViewerModule.h" +#include "Kismet2/BlueprintEditorUtils.h" +#include "Engine/BlueprintGeneratedClass.h" +#include "Kismet2/KismetEditorUtilities.h" +#include "BlueprintEditorSettings.h" + +#include "Abilities/GAAbilityBlueprint.h" +#include "Abilities/GAAbilityBase.h" +#include "GAAbilityGraph.h" +#include "GAAbilityGraphSchema.h" + +#include "ClassViewerFilter.h" + +#include "SlateOptMacros.h" + +// ------------------------------------------------------------------------------ +// Dialog to configure creation properties +// ------------------------------------------------------------------------------ +BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION + +class SAbilityBlueprintCreateDialog : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SAbilityBlueprintCreateDialog){} + + SLATE_END_ARGS() + + /** Constructs this widget with InArgs */ + void Construct(const FArguments& InArgs) + { + bOkClicked = false; + ParentClass = UGAAbilityBase::StaticClass(); + + ChildSlot + [ + SNew(SBorder) + .Visibility(EVisibility::Visible) + .BorderImage(FEditorStyle::GetBrush("Menu.Background")) + [ + SNew(SBox) + .Visibility(EVisibility::Visible) + .WidthOverride(500.0f) + [ + SNew(SVerticalBox) + + SVerticalBox::Slot() + .FillHeight(1) + [ + SNew(SBorder) + .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) + .Content() + [ + SAssignNew(ParentClassContainer, SVerticalBox) + ] + ] + + // Ok/Cancel buttons + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(HAlign_Right) + .VAlign(VAlign_Bottom) + .Padding(8) + [ + SNew(SUniformGridPanel) + .SlotPadding(FEditorStyle::GetMargin("StandardDialog.SlotPadding")) + .MinDesiredSlotWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth")) + .MinDesiredSlotHeight(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotHeight")) + + SUniformGridPanel::Slot(0, 0) + [ + SNew(SButton) + .HAlign(HAlign_Center) + .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + .OnClicked(this, &SAbilityBlueprintCreateDialog::OkClicked) + .Text(FText::FromString("OK")) + ] + + SUniformGridPanel::Slot(1, 0) + [ + SNew(SButton) + .HAlign(HAlign_Center) + .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + .OnClicked(this, &SAbilityBlueprintCreateDialog::CancelClicked) + .Text(FText::FromString("Cancel")) + ] + ] + ] + ] + ]; + + MakeParentClassPicker(); + } + + /** Sets properties for the supplied AbilitiesBlueprintFactory */ + bool ConfigureProperties(TWeakObjectPtr InAbilitiesBlueprintFactory) + { + AbilitiesBlueprintFactory = InAbilitiesBlueprintFactory; + + TSharedRef Window = SNew(SWindow) + .Title(FText::FromString("Create Ability Blueprint")) + .ClientSize(FVector2D(400, 700)) + .SupportsMinimize(false).SupportsMaximize(false) + [ + AsShared() + ]; + + PickerWindow = Window; + + GEditor->EditorAddModalWindow(Window); + AbilitiesBlueprintFactory.Reset(); + + return bOkClicked; + } + +private: + class FAbilityBlueprintParentFilter : public IClassViewerFilter + { + public: + /** All children of these classes will be included unless filtered out by another setting. */ + TSet< const UClass* > AllowedChildrenOfClasses; + + FAbilityBlueprintParentFilter() {} + + virtual bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InClass) != EFilterReturn::Failed; + } + + virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef< const IUnloadedBlueprintData > InUnloadedClassData, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InUnloadedClassData) != EFilterReturn::Failed; + } + }; + + /** Creates the combo menu for the parent class */ + void MakeParentClassPicker() + { + // Load the classviewer module to display a class picker + FClassViewerModule& ClassViewerModule = FModuleManager::LoadModuleChecked("ClassViewer"); + + // Fill in options + FClassViewerInitializationOptions Options; + Options.Mode = EClassViewerMode::ClassPicker; + + // Only allow parenting to base blueprints. + Options.bIsBlueprintBaseOnly = true; + + TSharedPtr Filter = MakeShareable(new FAbilityBlueprintParentFilter); + + // All child child classes of UGameplayAbility are valid. + Filter->AllowedChildrenOfClasses.Add(UGAAbilityBase::StaticClass()); + Options.ClassFilter = Filter; + + ParentClassContainer->ClearChildren(); + ParentClassContainer->AddSlot() + .AutoHeight() + [ + SNew(STextBlock) + .Text(FText::FromString("Parent Class:")) + .ShadowOffset(FVector2D(1.0f, 1.0f)) + ]; + + ParentClassContainer->AddSlot() + [ + ClassViewerModule.CreateClassViewer(Options, FOnClassPicked::CreateSP(this, &SAbilityBlueprintCreateDialog::OnClassPicked)) + ]; + } + + /** Handler for when a parent class is selected */ + void OnClassPicked(UClass* ChosenClass) + { + ParentClass = ChosenClass; + } + + /** Handler for when ok is clicked */ + FReply OkClicked() + { + if (AbilitiesBlueprintFactory.IsValid()) + { + AbilitiesBlueprintFactory->BlueprintType = BPTYPE_Normal; + AbilitiesBlueprintFactory->ParentClass = ParentClass.Get(); + } + + CloseDialog(true); + + return FReply::Handled(); + } + + void CloseDialog(bool bWasPicked = false) + { + bOkClicked = bWasPicked; + if (PickerWindow.IsValid()) + { + PickerWindow.Pin()->RequestDestroyWindow(); + } + } + + /** Handler for when cancel is clicked */ + FReply CancelClicked() + { + CloseDialog(); + return FReply::Handled(); + } + + FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) + { + if (InKeyEvent.GetKey() == EKeys::Escape) + { + CloseDialog(); + return FReply::Handled(); + } + return SWidget::OnKeyDown(MyGeometry, InKeyEvent); + } + +private: + /** The factory for which we are setting up properties */ + TWeakObjectPtr AbilitiesBlueprintFactory; + + /** A pointer to the window that is asking the user to select a parent class */ + TWeakPtr PickerWindow; + + /** The container for the Parent Class picker */ + TSharedPtr ParentClassContainer; + + /** The selected class */ + TWeakObjectPtr ParentClass; + + /** True if Ok was clicked */ + bool bOkClicked; +}; + +END_SLATE_FUNCTION_BUILD_OPTIMIZATION + +/*------------------------------------------------------------------------------ + UAbilitiesBlueprintFactory implementation. +------------------------------------------------------------------------------*/ + +UGAAbilityBlueprintFactory::UGAAbilityBlueprintFactory(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + bCreateNew = true; + bEditAfterNew = true; + SupportedClass = UGAAbilityBlueprint::StaticClass(); + ParentClass = UGAAbilityBase::StaticClass(); +} + +bool UGAAbilityBlueprintFactory::ConfigureProperties() +{ + TSharedRef Dialog = SNew(SAbilityBlueprintCreateDialog); + return Dialog->ConfigureProperties(this); +}; + +UObject* UGAAbilityBlueprintFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) +{ + // Make sure we are trying to factory a gameplay ability blueprint, then create and init one + check(Class->IsChildOf(UGAAbilityBlueprint::StaticClass())); + + // If they selected an interface, force the parent class to be UInterface + if (BlueprintType == BPTYPE_Interface) + { + ParentClass = UInterface::StaticClass(); + } + + if ( ( ParentClass == NULL ) || !FKismetEditorUtilities::CanCreateBlueprintOfClass(ParentClass) || !ParentClass->IsChildOf(UGAAbilityBase::StaticClass()) ) + { + FFormatNamedArguments Args; + Args.Add( TEXT("ClassName"), (ParentClass != NULL) ? FText::FromString( ParentClass->GetName() ) : FText::FromString("Null") ); + FMessageDialog::Open( EAppMsgType::Ok, FText::Format( FText::FromString("Cannot create a Ability Blueprint based on the class '{ClassName}'."), Args ) ); + return NULL; + } + else + { + UGAAbilityBlueprint* NewBP = CastChecked(FKismetEditorUtilities::CreateBlueprint(ParentClass, InParent, Name, BlueprintType, UGAAbilityBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass(), CallingContext)); + + if (NewBP) + { + UGAAbilityBlueprint* AbilityBP = UGAAbilityBlueprint::FindRootGameplayAbilityBlueprint(NewBP); + if (AbilityBP == NULL) + { + const UEdGraphSchema_K2* K2Schema = GetDefault(); +#if WITH_EDITORONLY_DATA + // Only allow a gameplay ability graph if there isn't one in a parent blueprint + UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(NewBP, TEXT("Ability Graph"), UGAAbilityGraph::StaticClass(), UGAAbilityGraphSchema::StaticClass()); + + if (NewBP->UbergraphPages.Num()) + { + FBlueprintEditorUtils::RemoveGraphs(NewBP, NewBP->UbergraphPages); + } + + FBlueprintEditorUtils::AddUbergraphPage(NewBP, NewGraph); + NewBP->LastEditedDocuments.Add(NewGraph); + NewGraph->bAllowDeletion = false; +#endif + UBlueprintEditorSettings* Settings = GetMutableDefault(); + if(Settings && Settings->bSpawnDefaultBlueprintNodes) + { + int32 NodePositionY = 0; + //FKismetEditorUtilities::AddDefaultEventNode(NewBP, NewGraph, FName(TEXT("K2_ActivateAbility")), UGAAbilityBase::StaticClass(), NodePositionY); + //FKismetEditorUtilities::AddDefaultEventNode(NewBP, NewGraph, FName(TEXT("K2_OnEndAbility")), UGAAbilityBase::StaticClass(), NodePositionY); + } + } + } + + return NewBP; + } +} + +UObject* UGAAbilityBlueprintFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) +{ + return FactoryCreateNew(Class, InParent, Name, Flags, Context, Warn, NAME_None); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityBlueprintFactory.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityBlueprintFactory.h new file mode 100644 index 0000000..ec61b23 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityBlueprintFactory.h @@ -0,0 +1,32 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Templates/SubclassOf.h" +#include "Engine/Blueprint.h" +#include "Factories/Factory.h" +#include "AssetTypeCategories.h" +#include "GAAbilityBlueprintFactory.generated.h" + +UCLASS(HideCategories=Object, MinimalAPI) +class UGAAbilityBlueprintFactory : public UFactory +{ + GENERATED_UCLASS_BODY() + + // The type of blueprint that will be created + UPROPERTY(EditAnywhere, Category=GameplayAbilitiesBlueprintFactory) + TEnumAsByte BlueprintType; + + // The parent class of the created blueprint + UPROPERTY(EditAnywhere, Category=GameplayAbilitiesBlueprintFactory) + TSubclassOf ParentClass; + + //~ Begin UFactory Interface + virtual bool ConfigureProperties() override; + virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) override; + virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override; + + //~ Begin UFactory Interface +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityEditor.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityEditor.cpp new file mode 100644 index 0000000..ef34e13 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityEditor.cpp @@ -0,0 +1,142 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +#include "../AbilityFrameworkEditor.h" +#include "GAAbilityEditor.h" +#include "EditorReimportHandler.h" + +#if WITH_EDITOR +#include "Editor.h" +#endif +#include "ISequencerModule.h" +#include "Editor/UnrealEd/Private/Toolkits/SStandaloneAssetEditorToolkitHost.h" +#include "Toolkits/ToolkitManager.h" +#include "Toolkits/GlobalEditorCommonCommands.h" + +#include "Abilities/GAAbilityBlueprint.h" +#include "GAAbilityBlueprintFactory.h" +#include "GAAbilityGraphSchema.h" +#include "Kismet2/BlueprintEditorUtils.h" + +#define LOCTEXT_NAMESPACE "FGAAbilityEditor" + + +///////////////////////////////////////////////////// +// FGameplayAbilitiesEditor + +FGAAbilityEditor::FGAAbilityEditor() +{ + +} + +FGAAbilityEditor::~FGAAbilityEditor() +{ + FEditorDelegates::OnAssetPostImport.RemoveAll(this); + FReimportManager::Instance()->OnPostReimport().RemoveAll(this); + + // NOTE: Any tabs that we still have hanging out when destroyed will be cleaned up by FBaseToolkit's destructor +} +void FGAAbilityEditor::InitAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr& InitToolkitHost, const FName AppIdentifier, const TSharedRef& StandaloneDefaultLayout, const bool bCreateDefaultStandaloneMenu, const bool bCreateDefaultToolbar, const TArray& ObjectsToEdit, const bool bInIsToolbarFocusable) +{ + FAssetEditorToolkit::InitAssetEditor(Mode, InitToolkitHost, AppIdentifier, StandaloneDefaultLayout, bCreateDefaultStandaloneMenu, bCreateDefaultToolbar, ObjectsToEdit, bInIsToolbarFocusable); +} +void FGAAbilityEditor::InitAbilitiesEditor(const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, const TArray& InBlueprints, bool bShouldOpenInDefaultsMode) +{ + InitBlueprintEditor(Mode, InitToolkitHost, InBlueprints, bShouldOpenInDefaultsMode); + + for (auto Blueprint : InBlueprints) + { + EnsureAbilityBlueprintIsUpToDate(Blueprint); + } +} + +void FGAAbilityEditor::EnsureAbilityBlueprintIsUpToDate(UBlueprint* Blueprint) +{ +#if WITH_EDITORONLY_DATA + int32 Count = Blueprint->UbergraphPages.Num(); + for (auto Graph : Blueprint->UbergraphPages) + { + // remove the default event graph, if it exists, from existing Gameplay Ability Blueprints + if (Graph->GetName() == "EventGraph" && Graph->Nodes.Num() == 0) + { + check(!Graph->Schema->GetClass()->IsChildOf(UGAAbilityGraphSchema::StaticClass())); + FBlueprintEditorUtils::RemoveGraph(Blueprint, Graph); + break; + } + } +#endif +} +bool FGAAbilityEditor::IsBlueprintEditor() const +{ + return true; +} +// FRED_TODO: don't merge this back +// FName FGameplayAbilitiesEditor::GetToolkitContextFName() const +// { +// return GetToolkitFName(); +// } + +FName FGAAbilityEditor::GetToolkitFName() const +{ + return FName("GameAbilityEditor"); +} + +FText FGAAbilityEditor::GetBaseToolkitName() const +{ + return FText::FromString("Game Ability Editor"); +} + +FText FGAAbilityEditor::GetToolkitName() const +{ + const TArray& EditingObjs = GetEditingObjects(); + + check(EditingObjs.Num() > 0); + + FFormatNamedArguments Args; + + const UObject* EditingObject = EditingObjs[0]; + + const bool bDirtyState = EditingObject->GetOutermost()->IsDirty(); + + Args.Add(TEXT("ObjectName"), FText::FromString(EditingObject->GetName())); + Args.Add(TEXT("DirtyState"), bDirtyState ? FText::FromString(TEXT("*")) : FText::GetEmpty()); + return FText::Format(FText::FromString("{ObjectName}{DirtyState}"), Args); +} + +FText FGAAbilityEditor::GetToolkitToolTipText() const +{ + const UObject* EditingObject = GetEditingObject(); + + check (EditingObject != NULL); + + return FAssetEditorToolkit::GetToolTipTextForObject(EditingObject); +} + +FString FGAAbilityEditor::GetWorldCentricTabPrefix() const +{ + return TEXT("AbilityEditor"); +} + +FLinearColor FGAAbilityEditor::GetWorldCentricTabColorScale() const +{ + return FLinearColor::White; +} + +UBlueprint* FGAAbilityEditor::GetBlueprintObj() const +{ + const TArray& EditingObjs = GetEditingObjects(); + for (int32 i = 0; i < EditingObjs.Num(); ++i) + { + if (EditingObjs[i]->IsA()) + { + return (UBlueprint*)EditingObjs[i]; + } + } + return nullptr; +} + +FString FGAAbilityEditor::GetDocumentationLink() const +{ + return FBlueprintEditor::GetDocumentationLink(); // todo: point this at the correct documentation +} + +#undef LOCTEXT_NAMESPACE + diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityEditor.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityEditor.h new file mode 100644 index 0000000..cfd9ffa --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityEditor.h @@ -0,0 +1,64 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Framework/Commands/UICommandList.h" +#include "Framework/MultiBox/MultiBoxExtender.h" +#include "GraphEditor.h" +#include "ISequencer.h" +#include "Editor/Kismet/Public/BlueprintEditor.h" + +////////////////////////////////////////////////////////////////////////// +// FGameplayAbilitiesEditor + +/** + * Gameplay abilities asset editor (extends Blueprint editor) + */ +class FGAAbilityEditor : public FBlueprintEditor +{ +public: + virtual void InitAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr& InitToolkitHost, const FName AppIdentifier, const TSharedRef& StandaloneDefaultLayout, const bool bCreateDefaultStandaloneMenu, const bool bCreateDefaultToolbar, const TArray& ObjectsToEdit, const bool bInIsToolbarFocusable = false) override; + /** + * Edits the specified gameplay ability asset(s) + * + * @param Mode Asset editing mode for this editor (standalone or world-centric) + * @param InitToolkitHost When Mode is WorldCentric, this is the level editor instance to spawn this editor within + * @param InBlueprints The blueprints to edit + * @param bShouldOpenInDefaultsMode If true, the editor will open in defaults editing mode + */ + + void InitAbilitiesEditor(const EToolkitMode::Type Mode, const TSharedPtr& InitToolkitHost, const TArray& InBlueprints, bool bShouldOpenInDefaultsMode); + +private: + /** + * Updates existing gameplay ability blueprints to make sure that they are up to date + * + * @param Blueprint The blueprint to be updated + */ + void EnsureAbilityBlueprintIsUpToDate(UBlueprint* Blueprint); + +public: + FGAAbilityEditor(); + + virtual ~FGAAbilityEditor(); + +public: + // IToolkit interface + // FRED_TODO: don't merge this back +// virtual FName GetToolkitContextFName() const override; + virtual FName GetToolkitFName() const override; + virtual FText GetBaseToolkitName() const override; + virtual FText GetToolkitName() const override; + virtual FText GetToolkitToolTipText() const override; + virtual FString GetWorldCentricTabPrefix() const override; + virtual FLinearColor GetWorldCentricTabColorScale() const override; + virtual bool IsBlueprintEditor() const override; + // End of IToolkit interface + + /** @return the documentation location for this editor */ + virtual FString GetDocumentationLink() const override; + + /** Returns a pointer to the Blueprint object we are currently editing, as long as we are editing exactly one */ + virtual UBlueprint* GetBlueprintObj() const override; +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraph.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraph.cpp new file mode 100644 index 0000000..da482a3 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraph.cpp @@ -0,0 +1,16 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFrameworkEditor.h" +#include "GAAbilityGraph.h" + +#define LOCTEXT_NAMESPACE "GameplayAbilityGraph" + +///////////////////////////////////////////////////// +// UGameplayAbilityGraph + +UGAAbilityGraph::UGAAbilityGraph(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraph.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraph.h new file mode 100644 index 0000000..dcc6890 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraph.h @@ -0,0 +1,15 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "EdGraph/EdGraph.h" +#include "GAAbilityGraph.generated.h" + +UCLASS(MinimalAPI) +class UGAAbilityGraph : public UEdGraph +{ + GENERATED_UCLASS_BODY() +}; + diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraphSchema.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraphSchema.cpp new file mode 100644 index 0000000..f51d3ff --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraphSchema.cpp @@ -0,0 +1,22 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFrameworkEditor.h" +#include "GAAbilityGraphSchema.h" +#include "EdGraphSchema_K2_Actions.h" +#include "Effects/GAGameEffect.h" +#include "Kismet2/BlueprintEditorUtils.h" + +UGAAbilityGraphSchema::UGAAbilityGraphSchema(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ +} + +UK2Node_VariableGet* UGAAbilityGraphSchema::SpawnVariableGetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const +{ + return Super::SpawnVariableGetNode(GraphPosition, ParentGraph, VariableName, Source); +} + +UK2Node_VariableSet* UGAAbilityGraphSchema::SpawnVariableSetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const +{ + return Super::SpawnVariableSetNode(GraphPosition, ParentGraph, VariableName, Source); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraphSchema.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraphSchema.h new file mode 100644 index 0000000..1c099f8 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityEditor/GAAbilityGraphSchema.h @@ -0,0 +1,38 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "EdGraphSchema_K2.h" +#include "GAAbilityGraphSchema.generated.h" + +UCLASS(MinimalAPI) +class UGAAbilityGraphSchema : public UEdGraphSchema_K2 +{ + GENERATED_UCLASS_BODY() + + /** + * Creates a new variable getter node and adds it to ParentGraph + * + * @param GraphPosition The location of the new node inside the graph + * @param ParentGraph The graph to spawn the new node in + * @param VariableName The name of the variable + * @param Source The source of the variable + * @return A pointer to the newly spawned node + */ + virtual class UK2Node_VariableGet* SpawnVariableGetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const override; + + /** + * Creates a new variable setter node and adds it to ParentGraph + * + * @param GraphPosition The location of the new node inside the graph + * @param ParentGraph The graph to spawn the new node in + * @param VariableName The name of the variable + * @param Source The source of the variable + * @return A pointer to the newly spawned node + */ + virtual class UK2Node_VariableSet* SpawnVariableSetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const override; + + virtual bool ShouldAlwaysPurgeOnModification() const override { return true; } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityFrameworkEditor.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityFrameworkEditor.cpp new file mode 100644 index 0000000..fade3e1 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityFrameworkEditor.cpp @@ -0,0 +1,164 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "AbilityFrameworkEditor.h" +#include "GAAttributePin.h" +#include "Attributes/GAAttributeGlobals.h" +#include "Effects/AFCueActor.h" +#include "GAAttributePanelGraphPinFactory.h" +#include "GAAttributeDetailCustomization.h" + +#include "GAEffectDetails.h" +//#include "GAEffectSpecStructCustomization.h" +#include "GAEffectPropertyStructCustomization.h" +#include "AFAbilityActionSpecDetails.h" +#include "AFAbilityPeriodSpecDetails.h" +#include "AFAbilityCooldownSpecDetails.h" +#include "AFAbilityInfiniteDurationSpecDetails.h" +#include "AFAbilityInfinitePeriodSpecDetails.h" + +#include "EffectEditor/AssetTypeActions_GAEffectBlueprint.h" +#include "AbilityEditor/AssetTypeActions_GAAbilityBlueprint.h" +#include "EffectCueEditor/AssetTypeActions_AFCueActorBlueprint.h" +#include "CueStatic/AssetTypeActions_AFCueStaticBlueprint.h" +#include "EffectCueEditor/AFEffectCueDetails.h" + + + +#include "AFCueManager.h" + +TSet FAbilityFrameworkEditor::EffectClasses = TSet(); +/** Shared class type that ensures safe binding to RegisterBlueprintEditorTab through an SP binding without interfering with module ownership semantics */ +FEffectCueequenceEditorTabBinding::FEffectCueequenceEditorTabBinding() +{ + FBlueprintEditorModule& BlueprintEditorModule = FModuleManager::LoadModuleChecked("Kismet"); + BlueprintEditorTabSpawnerHandle = BlueprintEditorModule.OnRegisterTabsForEditor().AddRaw(this, &FEffectCueequenceEditorTabBinding::RegisterBlueprintEditorTab); + BlueprintEditorLayoutExtensionHandle = BlueprintEditorModule.OnRegisterLayoutExtensions().AddRaw(this, &FEffectCueequenceEditorTabBinding::RegisterBlueprintEditorLayout); +} + +void FEffectCueequenceEditorTabBinding::RegisterBlueprintEditorLayout(FLayoutExtender& Extender) +{ + Extender.ExtendLayout(FBlueprintEditorTabs::CompilerResultsID, ELayoutExtensionPosition::Before, FTabManager::FTab(FName("EmbeddedEffectCueSequenceID"), ETabState::ClosedTab)); +} + +void FEffectCueequenceEditorTabBinding::RegisterBlueprintEditorTab(FWorkflowAllowedTabSet& TabFactories, FName InModeName, TSharedPtr BlueprintEditor) +{ + TabFactories.RegisterFactory(MakeShared(BlueprintEditor)); +} + +FEffectCueequenceEditorTabBinding::~FEffectCueequenceEditorTabBinding() +{ + FBlueprintEditorModule* BlueprintEditorModule = FModuleManager::GetModulePtr("Kismet"); + if (BlueprintEditorModule) + { + BlueprintEditorModule->OnRegisterTabsForEditor().Remove(BlueprintEditorTabSpawnerHandle); + BlueprintEditorModule->OnRegisterLayoutExtensions().Remove(BlueprintEditorLayoutExtensionHandle); + } +} + + +void FAbilityFrameworkEditor::RegisterAssetTypeAction(IAssetTools& AssetTools, TSharedRef Action) +{ + AssetTools.RegisterAssetTypeActions(Action); + CreatedAssetTypeActions.Add(Action); +} +void FAbilityFrameworkEditor::OnInitializeSequence(UGAEffectCueSequence* Sequence) +{ + auto* ProjectSettings = GetDefault(); + AAFCueActor* Cue = Cast(Sequence->GetOuter()); + + + if (Cue) + { + TRange Frames(static_cast(Cue->StartTime), static_cast(Cue->EndTime)); + Sequence->GetMovieScene()->SetPlaybackRange(Frames, true); + } + else + { + TRange Frames; + Sequence->GetMovieScene()->SetPlaybackRange(Frames, true); + } +} + /** IModuleInterface implementation */ +void FAbilityFrameworkEditor::StartupModule() +{ + if(GEditor) + BlueprintEditorTabBinding = MakeShared(); + + + + FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked("PropertyEditor"); + PropertyModule.RegisterCustomPropertyTypeLayout("GAAttribute", FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FGAAttributeDetailCustomization::MakeInstance)); + //PropertyModule.RegisterCustomPropertyTypeLayout("GAEffectProperty", FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FGAEffectPropertyStructCustomization::MakeInstance)); + PropertyModule.RegisterCustomPropertyTypeLayout("AFPropertytHandle", FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FGAEffectPropertyStructCustomization::MakeInstance)); + + TSharedPtr GAAttributePanelGraphPinFactory = MakeShareable(new FGAAttributePanelGraphPinFactory()); + FEdGraphUtilities::RegisterVisualPinFactory(GAAttributePanelGraphPinFactory); + + PropertyModule.RegisterCustomClassLayout("AFEffectSpecBase", FOnGetDetailCustomizationInstance::CreateStatic(&FGAEffectDetails::MakeInstance)); + PropertyModule.RegisterCustomClassLayout("AFAbilityActivationSpec", FOnGetDetailCustomizationInstance::CreateStatic(&FAFAbilityActivationSpecDetails::MakeInstance)); + PropertyModule.RegisterCustomClassLayout("AFAbilityPeriodSpec", FOnGetDetailCustomizationInstance::CreateStatic(&FAFAbilityPeriodSpecDetails::MakeInstance)); + PropertyModule.RegisterCustomClassLayout("AFAbilityCooldownSpec", FOnGetDetailCustomizationInstance::CreateStatic(&FAFAbilityCooldownSpecDetails::MakeInstance)); + PropertyModule.RegisterCustomClassLayout("AFAbilityPeriodicInfiniteSpec", FOnGetDetailCustomizationInstance::CreateStatic(&FAFAbilityInfinitePeriodSpecDetails::MakeInstance)); + PropertyModule.RegisterCustomClassLayout("AFAbilityInfiniteDurationSpec", FOnGetDetailCustomizationInstance::CreateStatic(&FAFAbilityInfiniteDurationSpecDetails::MakeInstance)); + + PropertyModule.RegisterCustomClassLayout("GAEffectCue", FOnGetDetailCustomizationInstance::CreateStatic(&FAFEffectCueDetails::MakeInstance)); + + IAssetTools& AssetTools = FModuleManager::LoadModuleChecked("AssetTools").Get(); + TSharedRef GABAction = MakeShareable(new FAssetTypeActions_GAEffectBlueprint()); + RegisterAssetTypeAction(AssetTools, GABAction); + TSharedRef GAAbilityAction = MakeShareable(new FAssetTypeActions_GAAbilityBlueprint()); + RegisterAssetTypeAction(AssetTools, GAAbilityAction); + TSharedRef GAEffectCueAction = MakeShareable(new FAssetTypeActions_AFCueActorBlueprint()); + RegisterAssetTypeAction(AssetTools, GAEffectCueAction); + //AssetTypeActions_AFCueStaticBlueprint + TSharedRef AFStaticCueAction = MakeShareable(new FAssetTypeActions_AFCueStaticBlueprint()); + RegisterAssetTypeAction(AssetTools, AFStaticCueAction); + //BlueprintEditorTabBinding = MakeShared(); + OnInitializeSequenceHandle = UGAEffectCueSequence::OnInitializeSequence().AddStatic(FAbilityFrameworkEditor::OnInitializeSequence); +} +void FAbilityFrameworkEditor::ShutdownModule() +{ + BlueprintEditorTabBinding = nullptr; + FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked("PropertyEditor"); + PropertyModule.UnregisterCustomClassLayout("AFEffectSpecBase"); + PropertyModule.UnregisterCustomClassLayout("AFAbilityActivationSpec"); + PropertyModule.UnregisterCustomClassLayout("AFAbilityPeriodSpec"); + PropertyModule.UnregisterCustomClassLayout("AFAbilityCooldownSpec"); + PropertyModule.UnregisterCustomClassLayout("AFAbilityPeriodicInfiniteSpec"); + PropertyModule.UnregisterCustomClassLayout("AFAbilityInfiniteDurationSpec"); + + PropertyModule.UnregisterCustomPropertyTypeLayout("GAAttribute"); + //PropertyModule.UnregisterCustomPropertyTypeLayout("GAEffectProperty"); + PropertyModule.UnregisterCustomPropertyTypeLayout("AFPropertytHandle"); + + UGAEffectCueSequence::OnInitializeSequence().Remove(OnInitializeSequenceHandle); + BlueprintEditorTabBinding = nullptr; + if (FModuleManager::Get().IsModuleLoaded("AssetTools")) + { + IAssetTools& AssetToolsModule = FModuleManager::GetModuleChecked("AssetTools").Get(); + for (auto& AssetTypeAction : CreatedAssetTypeActions) + { + if (AssetTypeAction.IsValid()) + { + AssetToolsModule.UnregisterAssetTypeActions(AssetTypeAction.ToSharedRef()); + } + } + } +} + +IMPLEMENT_GAME_MODULE(FAbilityFrameworkEditor, AbilityFrameworkEditor); + + +//void FGameAttributesEditor::StartupModule() +//{ +// +//} +// +// +//void FGameAttributesEditor::ShutdownModule() +//{ +// +//} + + + diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityFrameworkEditor.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityFrameworkEditor.h new file mode 100644 index 0000000..5a235e7 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/AbilityFrameworkEditor.h @@ -0,0 +1,60 @@ +#pragma once +#include "Engine.h" +#include "AbilityFramework.h" +#include "Effects/GAGameEffect.h" +#include "GAGlobalTypes.h" +#include "EditorStyle.h" +#include "Effects/GAEffectCueSequence.h" +#include "EffectCueEditor/GAEffectCueEditor.h" + +#include "UnrealEd.h" +#include "AssetToolsModule.h" +#include "IAssetTypeActions.h" + +#include "BlueprintEditorModule.h" +#include "BlueprintEditorTabs.h" +#include "LayoutExtender.h" +#include "LevelEditor.h" +#include "MovieSceneToolsProjectSettings.h" +#include "PropertyEditorModule.h" +#include "Styling/SlateStyle.h" +#include "WorkflowTabManager.h" +#include "Modules/ModuleManager.h" +#include "Widgets/Docking/SDockTab.h" + +#include "ISettingsModule.h" + +#include "IAbilityFrameworkEditor.h" +class FEffectCueequenceEditorTabBinding + : public TSharedFromThis +{ +public: + + FEffectCueequenceEditorTabBinding(); + + void RegisterBlueprintEditorLayout(FLayoutExtender& Extender); + + void RegisterBlueprintEditorTab(FWorkflowAllowedTabSet& TabFactories, FName InModeName, TSharedPtr BlueprintEditor); + ~FEffectCueequenceEditorTabBinding(); + +private: + + /** Delegate binding handle for FBlueprintEditorModule::OnRegisterTabsForEditor */ + FDelegateHandle BlueprintEditorTabSpawnerHandle, BlueprintEditorLayoutExtensionHandle; +}; +//add static list of registered custom derived effcts. Will be used to specify, from which classes +//new effect blueprints can be created, and which classes are allowed to pick (if not specified +//in metaData. +class FAbilityFrameworkEditor : public IAbilityFrameworkEditor +{ + TArray< TSharedPtr > CreatedAssetTypeActions; + TSharedPtr BlueprintEditorTabBinding; + FDelegateHandle OnInitializeSequenceHandle; + static TSet EffectClasses; + + void RegisterAssetTypeAction(IAssetTools& AssetTools, TSharedRef Action); + static void OnInitializeSequence(UGAEffectCueSequence* Sequence); + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AFCueStaticBlueprintFactory.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AFCueStaticBlueprintFactory.cpp new file mode 100644 index 0000000..2e308bc --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AFCueStaticBlueprintFactory.cpp @@ -0,0 +1,334 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +#include "AbilityFrameworkEditor.h" +#include "AFCueStaticBlueprintFactory.h" + +#include "InputCoreTypes.h" +#include "UObject/Interface.h" +#include "Layout/Visibility.h" +#include "Input/Reply.h" +#include "Widgets/SWidget.h" +#include "Widgets/DeclarativeSyntaxSupport.h" +#include "Misc/MessageDialog.h" +#include "Modules/ModuleManager.h" +#include "Widgets/SCompoundWidget.h" +#include "Widgets/SBoxPanel.h" +#include "Widgets/SWindow.h" +#include "Widgets/Layout/SBorder.h" +#include "Widgets/Text/STextBlock.h" +#include "Widgets/Layout/SBox.h" +#include "Widgets/Layout/SUniformGridPanel.h" +#include "Widgets/Input/SButton.h" +#include "EditorStyleSet.h" +#include "Editor.h" +#include "EdGraphSchema_K2.h" + +#include "ClassViewerModule.h" +#include "Kismet2/BlueprintEditorUtils.h" +#include "Engine/BlueprintGeneratedClass.h" +#include "Kismet2/KismetEditorUtilities.h" +#include "BlueprintEditorSettings.h" + +#include "Cues/AFCueStaticBlueprint.h" +#include "Cues/AFCueStaticGeneratedClass.h" + +#include "ClassViewerFilter.h" + +#include "Effects/AFCueStatic.h" + +#include "SlateOptMacros.h" + +// ------------------------------------------------------------------------------ +// Dialog to configure creation properties +// ------------------------------------------------------------------------------ +BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION + +class SEffectCueBlueprintCreateDialog : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SEffectCueBlueprintCreateDialog){} + + SLATE_END_ARGS() + + /** Constructs this widget with InArgs */ + void Construct(const FArguments& InArgs) + { + bOkClicked = false; + ParentClass = UAFCueStatic::StaticClass(); + + ChildSlot + [ + SNew(SBorder) + .Visibility(EVisibility::Visible) + .BorderImage(FEditorStyle::GetBrush("Menu.Background")) + [ + SNew(SBox) + .Visibility(EVisibility::Visible) + .WidthOverride(500.0f) + [ + SNew(SVerticalBox) + + SVerticalBox::Slot() + .FillHeight(1) + [ + SNew(SBorder) + .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) + .Content() + [ + SAssignNew(ParentClassContainer, SVerticalBox) + ] + ] + + // Ok/Cancel buttons + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(HAlign_Right) + .VAlign(VAlign_Bottom) + .Padding(8) + [ + SNew(SUniformGridPanel) + .SlotPadding(FEditorStyle::GetMargin("StandardDialog.SlotPadding")) + .MinDesiredSlotWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth")) + .MinDesiredSlotHeight(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotHeight")) + + SUniformGridPanel::Slot(0, 0) + [ + SNew(SButton) + .HAlign(HAlign_Center) + .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + .OnClicked(this, &SEffectCueBlueprintCreateDialog::OkClicked) + .Text(FText::FromString("OK")) + ] + + SUniformGridPanel::Slot(1, 0) + [ + SNew(SButton) + .HAlign(HAlign_Center) + .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + .OnClicked(this, &SEffectCueBlueprintCreateDialog::CancelClicked) + .Text(FText::FromString("Cancel")) + ] + ] + ] + ] + ]; + + MakeParentClassPicker(); + } + + /** Sets properties for the supplied AbilitiesBlueprintFactory */ + bool ConfigureProperties(TWeakObjectPtr InEffectCueBlueprintFactory) + { + EffectCueBlueprintFactory = InEffectCueBlueprintFactory; + + TSharedRef Window = SNew(SWindow) + .Title(FText::FromString("Create Ability Blueprint")) + .ClientSize(FVector2D(400, 700)) + .SupportsMinimize(false).SupportsMaximize(false) + [ + AsShared() + ]; + + PickerWindow = Window; + + GEditor->EditorAddModalWindow(Window); + EffectCueBlueprintFactory.Reset(); + + return bOkClicked; + } + +private: + class FEffectCueBlueprintParentFilter : public IClassViewerFilter + { + public: + /** All children of these classes will be included unless filtered out by another setting. */ + TSet< const UClass* > AllowedChildrenOfClasses; + + FEffectCueBlueprintParentFilter() {} + + virtual bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InClass) != EFilterReturn::Failed; + } + + virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef< const IUnloadedBlueprintData > InUnloadedClassData, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InUnloadedClassData) != EFilterReturn::Failed; + } + }; + + /** Creates the combo menu for the parent class */ + void MakeParentClassPicker() + { + // Load the classviewer module to display a class picker + FClassViewerModule& ClassViewerModule = FModuleManager::LoadModuleChecked("ClassViewer"); + + // Fill in options + FClassViewerInitializationOptions Options; + Options.Mode = EClassViewerMode::ClassPicker; + + // Only allow parenting to base blueprints. + Options.bIsBlueprintBaseOnly = true; + + TSharedPtr Filter = MakeShareable(new FEffectCueBlueprintParentFilter); + + // All child child classes of UGameplayAbility are valid. + Filter->AllowedChildrenOfClasses.Add(AAFCueActor::StaticClass()); + Options.ClassFilter = Filter; + + ParentClassContainer->ClearChildren(); + ParentClassContainer->AddSlot() + .AutoHeight() + [ + SNew(STextBlock) + .Text(FText::FromString("Parent Class:")) + .ShadowOffset(FVector2D(1.0f, 1.0f)) + ]; + + ParentClassContainer->AddSlot() + [ + ClassViewerModule.CreateClassViewer(Options, FOnClassPicked::CreateSP(this, &SEffectCueBlueprintCreateDialog::OnClassPicked)) + ]; + } + + /** Handler for when a parent class is selected */ + void OnClassPicked(UClass* ChosenClass) + { + ParentClass = ChosenClass; + } + + /** Handler for when ok is clicked */ + FReply OkClicked() + { + if (EffectCueBlueprintFactory.IsValid()) + { + EffectCueBlueprintFactory->BlueprintType = BPTYPE_Normal; + EffectCueBlueprintFactory->ParentClass = ParentClass.Get(); + } + + CloseDialog(true); + + return FReply::Handled(); + } + + void CloseDialog(bool bWasPicked = false) + { + bOkClicked = bWasPicked; + if (PickerWindow.IsValid()) + { + PickerWindow.Pin()->RequestDestroyWindow(); + } + } + + /** Handler for when cancel is clicked */ + FReply CancelClicked() + { + CloseDialog(); + return FReply::Handled(); + } + + FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) + { + if (InKeyEvent.GetKey() == EKeys::Escape) + { + CloseDialog(); + return FReply::Handled(); + } + return SWidget::OnKeyDown(MyGeometry, InKeyEvent); + } + +private: + /** The factory for which we are setting up properties */ + TWeakObjectPtr EffectCueBlueprintFactory; + + /** A pointer to the window that is asking the user to select a parent class */ + TWeakPtr PickerWindow; + + /** The container for the Parent Class picker */ + TSharedPtr ParentClassContainer; + + /** The selected class */ + TWeakObjectPtr ParentClass; + + /** True if Ok was clicked */ + bool bOkClicked; +}; + +END_SLATE_FUNCTION_BUILD_OPTIMIZATION + +/*------------------------------------------------------------------------------ + UAbilitiesBlueprintFactory implementation. +------------------------------------------------------------------------------*/ + +UAFCueStaticBlueprintFactory::UAFCueStaticBlueprintFactory(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + bCreateNew = true; + bEditAfterNew = true; + SupportedClass = UAFCueStaticBlueprint::StaticClass(); + ParentClass = UAFCueStatic::StaticClass(); +} + +bool UAFCueStaticBlueprintFactory::ConfigureProperties() +{ + TSharedRef Dialog = SNew(SEffectCueBlueprintCreateDialog); + return Dialog->ConfigureProperties(this); +}; + +UObject* UAFCueStaticBlueprintFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) +{ + // Make sure we are trying to factory a gameplay ability blueprint, then create and init one + check(Class->IsChildOf(UAFCueStaticBlueprint::StaticClass())); + + // If they selected an interface, force the parent class to be UInterface + if (BlueprintType == BPTYPE_Interface) + { + ParentClass = UInterface::StaticClass(); + } + + if ( ( ParentClass == NULL ) || !FKismetEditorUtilities::CanCreateBlueprintOfClass(ParentClass) || !ParentClass->IsChildOf(AAFCueActor::StaticClass()) ) + { + FFormatNamedArguments Args; + Args.Add( TEXT("ClassName"), (ParentClass != NULL) ? FText::FromString( ParentClass->GetName() ) : FText::FromString("Null") ); + FMessageDialog::Open( EAppMsgType::Ok, FText::Format( FText::FromString("Cannot create a Ability Blueprint based on the class '{ClassName}'."), Args ) ); + return NULL; + } + else + { + UAFCueStaticBlueprint* NewBP = CastChecked(FKismetEditorUtilities::CreateBlueprint(ParentClass, InParent, Name, BlueprintType, UAFCueStaticBlueprint::StaticClass(), UAFCueStaticGeneratedClass::StaticClass(), CallingContext)); + + if (NewBP) + { +// UAFCueStaticBlueprint* AbilityBP = UAFCueActorBlueprint::FindRootGameplayAbilityBlueprint(NewBP); +// if (AbilityBP == NULL) +// { +// const UEdGraphSchema_K2* K2Schema = GetDefault(); +// +// // Only allow a gameplay ability graph if there isn't one in a parent blueprint +// UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(NewBP, TEXT("Ability Graph"), UGAEffectCueGraph::StaticClass(), UGAEffectCueGraphSchema::StaticClass()); +//#if WITH_EDITORONLY_DATA +// if (NewBP->UbergraphPages.Num()) +// { +// FBlueprintEditorUtils::RemoveGraphs(NewBP, NewBP->UbergraphPages); +// } +//#endif +// FBlueprintEditorUtils::AddUbergraphPage(NewBP, NewGraph); +// NewBP->LastEditedDocuments.Add(NewGraph); +// NewGraph->bAllowDeletion = false; +// +// UBlueprintEditorSettings* Settings = GetMutableDefault(); +// if(Settings && Settings->bSpawnDefaultBlueprintNodes) +// { +// int32 NodePositionY = 0; +// //FKismetEditorUtilities::AddDefaultEventNode(NewBP, NewGraph, FName(TEXT("K2_ActivateAbility")), UGAAbilityBase::StaticClass(), NodePositionY); +// //FKismetEditorUtilities::AddDefaultEventNode(NewBP, NewGraph, FName(TEXT("K2_OnEndAbility")), UGAAbilityBase::StaticClass(), NodePositionY); +// } +// } + } + + return NewBP; + } +} + +UObject* UAFCueStaticBlueprintFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) +{ + return FactoryCreateNew(Class, InParent, Name, Flags, Context, Warn, NAME_None); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AFCueStaticBlueprintFactory.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AFCueStaticBlueprintFactory.h new file mode 100644 index 0000000..4150463 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AFCueStaticBlueprintFactory.h @@ -0,0 +1,32 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Templates/SubclassOf.h" +#include "Engine/Blueprint.h" +#include "Factories/Factory.h" +#include "AssetTypeCategories.h" +#include "AFCueStaticBlueprintFactory.generated.h" + +UCLASS(HideCategories=Object, MinimalAPI) +class UAFCueStaticBlueprintFactory : public UFactory +{ + GENERATED_UCLASS_BODY() + + // The type of blueprint that will be created + UPROPERTY(EditAnywhere, Category=GameplayAbilitiesBlueprintFactory) + TEnumAsByte BlueprintType; + + // The parent class of the created blueprint + UPROPERTY(EditAnywhere, Category=GameplayAbilitiesBlueprintFactory) + TSubclassOf ParentClass; + + //~ Begin UFactory Interface + virtual bool ConfigureProperties() override; + virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) override; + virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override; + + //~ Begin UFactory Interface +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AssetTypeActions_AFCueStaticBlueprint.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AssetTypeActions_AFCueStaticBlueprint.cpp new file mode 100644 index 0000000..65f7cb7 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AssetTypeActions_AFCueStaticBlueprint.cpp @@ -0,0 +1,59 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#include "AbilityFrameworkEditor.h" +#include "AssetTypeActions_AFCueStaticBlueprint.h" +#include "Misc/MessageDialog.h" +#include "Kismet2/BlueprintEditorUtils.h" +#include "BlueprintEditor.h" +//#include "GAEffectCueEditor.h" +#include "Cues/AFCueStaticBlueprint.h" + +#include "Effects/AFCueStatic.h" +#include "CueStatic/AFCueStaticBlueprintFactory.h" + +#define LOCTEXT_NAMESPACE "AssetTypeActions" + +FText FAssetTypeActions_AFCueStaticBlueprint::GetName() const +{ + return FText::FromString("Cue Static"); +} +UClass* FAssetTypeActions_AFCueStaticBlueprint::GetSupportedClass() const +{ + return UAFCueStaticBlueprint::StaticClass(); +} + +void FAssetTypeActions_AFCueStaticBlueprint::OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor) +{ + EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone; + + for (auto ObjIt = InObjects.CreateConstIterator(); ObjIt; ++ObjIt) + { + auto Blueprint = Cast(*ObjIt); + if (Blueprint && Blueprint->SkeletonGeneratedClass && Blueprint->GeneratedClass) + { + TSharedRef< FBlueprintEditor > NewEditor(new FBlueprintEditor()); + + TArray Blueprints; + Blueprints.Add(Blueprint); + + NewEditor->InitBlueprintEditor(Mode, EditWithinLevelEditor, Blueprints, false); + } + else + { + FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Ability Blueprint could not be loaded because it derives from an invalid class. Check to make sure the parent class for this blueprint hasn't been removed!")); + } + } +} + +bool FAssetTypeActions_AFCueStaticBlueprint::ShouldUseDataOnlyEditor(const UBlueprint* Blueprint) const +{ + return false; +} + +UFactory* FAssetTypeActions_AFCueStaticBlueprint::GetFactoryForBlueprintType(UBlueprint* InBlueprint) const +{ + UAFCueStaticBlueprintFactory* EffectCueBlueprintFactory = NewObject(); + EffectCueBlueprintFactory->ParentClass = TSubclassOf(*InBlueprint->GeneratedClass); + return EffectCueBlueprintFactory; +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AssetTypeActions_AFCueStaticBlueprint.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AssetTypeActions_AFCueStaticBlueprint.h new file mode 100644 index 0000000..40ef9ae --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CueStatic/AssetTypeActions_AFCueStaticBlueprint.h @@ -0,0 +1,26 @@ +#pragma once +#include "CoreMinimal.h" +#include "Toolkits/IToolkitHost.h" +#include "AssetTypeCategories.h" +#include "Developer/AssetTools/Public/AssetTypeActions/AssetTypeActions_Blueprint.h" + +class UFactory; + +class FAssetTypeActions_AFCueStaticBlueprint : public FAssetTypeActions_Blueprint +{ +public: + // IAssetTypeActions Implementation + virtual FText GetName() const override; + virtual FColor GetTypeColor() const override { return FColor(0, 96, 128); } + virtual UClass* GetSupportedClass() const override; + virtual void OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor = TSharedPtr()) override; + virtual uint32 GetCategories() override { return EAssetTypeCategories::Gameplay; } + // End IAssetTypeActions Implementation + + // FAssetTypeActions_Blueprint interface + virtual UFactory* GetFactoryForBlueprintType(UBlueprint* InBlueprint) const override; + +private: + /** Returns true if the blueprint is data only */ + bool ShouldUseDataOnlyEditor(const UBlueprint* Blueprint) const; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CurveTable/GACurveTableDetailCustomization.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CurveTable/GACurveTableDetailCustomization.cpp new file mode 100644 index 0000000..5840655 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CurveTable/GACurveTableDetailCustomization.cpp @@ -0,0 +1,28 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" + +#include "STextCombobox.h" +#include "STreeView.h" + +#include "GACurveTableDetailCustomization.h" + +TSharedRef FGACurveTableDetailCustomization::MakeInstance() +{ + return MakeShareable(new FGACurveTableDetailCustomization); +} + +FGACurveTableDetailCustomization::~FGACurveTableDetailCustomization() +{ + +} + +void FGACurveTableDetailCustomization::CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) +{ + +} +void FGACurveTableDetailCustomization::CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) +{ + +} diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CurveTable/GACurveTableDetailCustomization.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CurveTable/GACurveTableDetailCustomization.h new file mode 100644 index 0000000..2b09d86 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/CurveTable/GACurveTableDetailCustomization.h @@ -0,0 +1,23 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "../GAGlobalTypesEditor.h" + +#include "IPropertyTypeCustomization.h" +#include "PropertyHandle.h" + +class FGACurveTableDetailCustomization : public IPropertyTypeCustomization +{ +public: + static TSharedRef MakeInstance(); + /** + * Destructor + */ + virtual ~FGACurveTableDetailCustomization(); + + /** IPropertyTypeCustomization interface */ + virtual void CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; + virtual void CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; + + + +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFCueActorBlueprintFactory.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFCueActorBlueprintFactory.cpp new file mode 100644 index 0000000..2951ef1 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFCueActorBlueprintFactory.cpp @@ -0,0 +1,334 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +#include "AbilityFrameworkEditor.h" +#include "AFCueActorBlueprintFactory.h" +#include "InputCoreTypes.h" +#include "UObject/Interface.h" +#include "Layout/Visibility.h" +#include "Input/Reply.h" +#include "Widgets/SWidget.h" +#include "Widgets/DeclarativeSyntaxSupport.h" +#include "Misc/MessageDialog.h" +#include "Modules/ModuleManager.h" +#include "Effects/GAGameEffect.h" +#include "Widgets/SCompoundWidget.h" +#include "Widgets/SBoxPanel.h" +#include "Widgets/SWindow.h" +#include "Widgets/Layout/SBorder.h" +#include "Widgets/Text/STextBlock.h" +#include "Widgets/Layout/SBox.h" +#include "Widgets/Layout/SUniformGridPanel.h" +#include "Widgets/Input/SButton.h" +#include "EditorStyleSet.h" +#include "Editor.h" +#include "EdGraphSchema_K2.h" + +#include "ClassViewerModule.h" +#include "Kismet2/BlueprintEditorUtils.h" +#include "Engine/BlueprintGeneratedClass.h" +#include "Kismet2/KismetEditorUtilities.h" +#include "BlueprintEditorSettings.h" + +#include "Effects/AFCueActorBlueprint.h" +#include "Effects/AFCueActor.h" +#include "GAEffectCueGraph.h" +#include "GAEffectCueGraphSchema.h" + +#include "ClassViewerFilter.h" + +#include "SlateOptMacros.h" + +// ------------------------------------------------------------------------------ +// Dialog to configure creation properties +// ------------------------------------------------------------------------------ +BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION + +class SCueStaticBlueprintCreateDialog : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SCueStaticBlueprintCreateDialog){} + + SLATE_END_ARGS() + + /** Constructs this widget with InArgs */ + void Construct(const FArguments& InArgs) + { + bOkClicked = false; + ParentClass = AAFCueActor::StaticClass(); + + ChildSlot + [ + SNew(SBorder) + .Visibility(EVisibility::Visible) + .BorderImage(FEditorStyle::GetBrush("Menu.Background")) + [ + SNew(SBox) + .Visibility(EVisibility::Visible) + .WidthOverride(500.0f) + [ + SNew(SVerticalBox) + + SVerticalBox::Slot() + .FillHeight(1) + [ + SNew(SBorder) + .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) + .Content() + [ + SAssignNew(ParentClassContainer, SVerticalBox) + ] + ] + + // Ok/Cancel buttons + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(HAlign_Right) + .VAlign(VAlign_Bottom) + .Padding(8) + [ + SNew(SUniformGridPanel) + .SlotPadding(FEditorStyle::GetMargin("StandardDialog.SlotPadding")) + .MinDesiredSlotWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth")) + .MinDesiredSlotHeight(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotHeight")) + + SUniformGridPanel::Slot(0, 0) + [ + SNew(SButton) + .HAlign(HAlign_Center) + .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + .OnClicked(this, &SCueStaticBlueprintCreateDialog::OkClicked) + .Text(FText::FromString("OK")) + ] + + SUniformGridPanel::Slot(1, 0) + [ + SNew(SButton) + .HAlign(HAlign_Center) + .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + .OnClicked(this, &SCueStaticBlueprintCreateDialog::CancelClicked) + .Text(FText::FromString("Cancel")) + ] + ] + ] + ] + ]; + + MakeParentClassPicker(); + } + + /** Sets properties for the supplied AbilitiesBlueprintFactory */ + bool ConfigureProperties(TWeakObjectPtr InEffectCueBlueprintFactory) + { + EffectCueBlueprintFactory = InEffectCueBlueprintFactory; + + TSharedRef Window = SNew(SWindow) + .Title(FText::FromString("Create Ability Blueprint")) + .ClientSize(FVector2D(400, 700)) + .SupportsMinimize(false).SupportsMaximize(false) + [ + AsShared() + ]; + + PickerWindow = Window; + + GEditor->EditorAddModalWindow(Window); + EffectCueBlueprintFactory.Reset(); + + return bOkClicked; + } + +private: + class FEffectCueBlueprintParentFilter : public IClassViewerFilter + { + public: + /** All children of these classes will be included unless filtered out by another setting. */ + TSet< const UClass* > AllowedChildrenOfClasses; + + FEffectCueBlueprintParentFilter() {} + + virtual bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InClass) != EFilterReturn::Failed; + } + + virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef< const IUnloadedBlueprintData > InUnloadedClassData, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InUnloadedClassData) != EFilterReturn::Failed; + } + }; + + /** Creates the combo menu for the parent class */ + void MakeParentClassPicker() + { + // Load the classviewer module to display a class picker + FClassViewerModule& ClassViewerModule = FModuleManager::LoadModuleChecked("ClassViewer"); + + // Fill in options + FClassViewerInitializationOptions Options; + Options.Mode = EClassViewerMode::ClassPicker; + + // Only allow parenting to base blueprints. + Options.bIsBlueprintBaseOnly = true; + + TSharedPtr Filter = MakeShareable(new FEffectCueBlueprintParentFilter); + + // All child child classes of UGameplayAbility are valid. + Filter->AllowedChildrenOfClasses.Add(AAFCueActor::StaticClass()); + Options.ClassFilter = Filter; + + ParentClassContainer->ClearChildren(); + ParentClassContainer->AddSlot() + .AutoHeight() + [ + SNew(STextBlock) + .Text(FText::FromString("Parent Class:")) + .ShadowOffset(FVector2D(1.0f, 1.0f)) + ]; + + ParentClassContainer->AddSlot() + [ + ClassViewerModule.CreateClassViewer(Options, FOnClassPicked::CreateSP(this, &SCueStaticBlueprintCreateDialog::OnClassPicked)) + ]; + } + + /** Handler for when a parent class is selected */ + void OnClassPicked(UClass* ChosenClass) + { + ParentClass = ChosenClass; + } + + /** Handler for when ok is clicked */ + FReply OkClicked() + { + if (EffectCueBlueprintFactory.IsValid()) + { + EffectCueBlueprintFactory->BlueprintType = BPTYPE_Normal; + EffectCueBlueprintFactory->ParentClass = ParentClass.Get(); + } + + CloseDialog(true); + + return FReply::Handled(); + } + + void CloseDialog(bool bWasPicked = false) + { + bOkClicked = bWasPicked; + if (PickerWindow.IsValid()) + { + PickerWindow.Pin()->RequestDestroyWindow(); + } + } + + /** Handler for when cancel is clicked */ + FReply CancelClicked() + { + CloseDialog(); + return FReply::Handled(); + } + + FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) + { + if (InKeyEvent.GetKey() == EKeys::Escape) + { + CloseDialog(); + return FReply::Handled(); + } + return SWidget::OnKeyDown(MyGeometry, InKeyEvent); + } + +private: + /** The factory for which we are setting up properties */ + TWeakObjectPtr EffectCueBlueprintFactory; + + /** A pointer to the window that is asking the user to select a parent class */ + TWeakPtr PickerWindow; + + /** The container for the Parent Class picker */ + TSharedPtr ParentClassContainer; + + /** The selected class */ + TWeakObjectPtr ParentClass; + + /** True if Ok was clicked */ + bool bOkClicked; +}; + +END_SLATE_FUNCTION_BUILD_OPTIMIZATION + +/*------------------------------------------------------------------------------ + UAbilitiesBlueprintFactory implementation. +------------------------------------------------------------------------------*/ + +UAFCueActorBlueprintFactory::UAFCueActorBlueprintFactory(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + bCreateNew = true; + bEditAfterNew = true; + SupportedClass = UAFCueActorBlueprint::StaticClass(); + ParentClass = AAFCueActor::StaticClass(); +} + +bool UAFCueActorBlueprintFactory::ConfigureProperties() +{ + TSharedRef Dialog = SNew(SCueStaticBlueprintCreateDialog); + return Dialog->ConfigureProperties(this); +}; + +UObject* UAFCueActorBlueprintFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) +{ + // Make sure we are trying to factory a gameplay ability blueprint, then create and init one + check(Class->IsChildOf(UAFCueActorBlueprint::StaticClass())); + + // If they selected an interface, force the parent class to be UInterface + if (BlueprintType == BPTYPE_Interface) + { + ParentClass = UInterface::StaticClass(); + } + + if ( ( ParentClass == NULL ) || !FKismetEditorUtilities::CanCreateBlueprintOfClass(ParentClass) || !ParentClass->IsChildOf(AAFCueActor::StaticClass()) ) + { + FFormatNamedArguments Args; + Args.Add( TEXT("ClassName"), (ParentClass != NULL) ? FText::FromString( ParentClass->GetName() ) : FText::FromString("Null") ); + FMessageDialog::Open( EAppMsgType::Ok, FText::Format( FText::FromString("Cannot create a Ability Blueprint based on the class '{ClassName}'."), Args ) ); + return NULL; + } + else + { + UAFCueActorBlueprint* NewBP = CastChecked(FKismetEditorUtilities::CreateBlueprint(ParentClass, InParent, Name, BlueprintType, UAFCueActorBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass(), CallingContext)); + + if (NewBP) + { + UAFCueActorBlueprint* AbilityBP = UAFCueActorBlueprint::FindRootGameplayAbilityBlueprint(NewBP); + if (AbilityBP == NULL) + { + const UEdGraphSchema_K2* K2Schema = GetDefault(); + + // Only allow a gameplay ability graph if there isn't one in a parent blueprint + UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(NewBP, TEXT("Ability Graph"), UGAEffectCueGraph::StaticClass(), UGAEffectCueGraphSchema::StaticClass()); +#if WITH_EDITORONLY_DATA + if (NewBP->UbergraphPages.Num()) + { + FBlueprintEditorUtils::RemoveGraphs(NewBP, NewBP->UbergraphPages); + } +#endif + FBlueprintEditorUtils::AddUbergraphPage(NewBP, NewGraph); + NewBP->LastEditedDocuments.Add(NewGraph); + NewGraph->bAllowDeletion = false; + + UBlueprintEditorSettings* Settings = GetMutableDefault(); + if(Settings && Settings->bSpawnDefaultBlueprintNodes) + { + int32 NodePositionY = 0; + //FKismetEditorUtilities::AddDefaultEventNode(NewBP, NewGraph, FName(TEXT("K2_ActivateAbility")), UGAAbilityBase::StaticClass(), NodePositionY); + //FKismetEditorUtilities::AddDefaultEventNode(NewBP, NewGraph, FName(TEXT("K2_OnEndAbility")), UGAAbilityBase::StaticClass(), NodePositionY); + } + } + } + + return NewBP; + } +} + +UObject* UAFCueActorBlueprintFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) +{ + return FactoryCreateNew(Class, InParent, Name, Flags, Context, Warn, NAME_None); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFCueActorBlueprintFactory.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFCueActorBlueprintFactory.h new file mode 100644 index 0000000..a8b46d3 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFCueActorBlueprintFactory.h @@ -0,0 +1,32 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Templates/SubclassOf.h" +#include "Engine/Blueprint.h" +#include "Factories/Factory.h" +#include "AssetTypeCategories.h" +#include "AFCueActorBlueprintFactory.generated.h" + +UCLASS(HideCategories=Object, MinimalAPI) +class UAFCueActorBlueprintFactory : public UFactory +{ + GENERATED_UCLASS_BODY() + + // The type of blueprint that will be created + UPROPERTY(EditAnywhere, Category=GameplayAbilitiesBlueprintFactory) + TEnumAsByte BlueprintType; + + // The parent class of the created blueprint + UPROPERTY(EditAnywhere, Category=GameplayAbilitiesBlueprintFactory) + TSubclassOf ParentClass; + + //~ Begin UFactory Interface + virtual bool ConfigureProperties() override; + virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) override; + virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override; + + //~ Begin UFactory Interface +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFEffectCueDetails.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFEffectCueDetails.cpp new file mode 100644 index 0000000..fcb61a3 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFEffectCueDetails.cpp @@ -0,0 +1,353 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" + +#include "STextCombobox.h" +#include "STreeView.h" + +#include "Effects/AFCueActor.h" +#include "Effects/GAEffectCueSequence.h" +#include "EditorReimportHandler.h" +#include "MovieScene.h" +#include "Tracks/MovieScenePropertyTrack.h" +#if WITH_EDITOR +#include "Editor.h" +#endif +#include "ISequencerModule.h" +#include "LevelEditorSequencerIntegration.h" +#include "SSCSEditor.h" +#include "SlateIconFinder.h" +#include "BlueprintEditorUtils.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "Framework/Application/SlateApplication.h" + +#include "AFEffectCueDetails.h" + +class SEffectCueSequenceEditorWidget + : public SCompoundWidget +{ +private: + TWeakObjectPtr WeakSequence; + AAFCueActor* EffectCue; + TWeakPtr WeakBlueprintEditor; + + TSharedPtr Content; + TSharedPtr Sequencer; + FDelegateHandle OnBlueprintPreCompileHandle; + FDelegateHandle OnObjectSavedHandle; + FDelegateHandle OnSequenceChangedHandle; + FDelegateHandle OnBlueprintCompileHandle; + FDelegateHandle OnBlueprintReinstancedHandle; +public: + + SLATE_BEGIN_ARGS(SEffectCueSequenceEditorWidget) {} + SLATE_END_ARGS(); + + void Construct(const FArguments&, TWeakPtr InBlueprintEditor) + { + OnBlueprintPreCompileHandle = GEditor->OnBlueprintPreCompile().AddSP(this, &SEffectCueSequenceEditorWidget::OnBlueprintPreCompile); + OnObjectSavedHandle = FCoreUObjectDelegates::OnObjectSaved.AddSP(this, &SEffectCueSequenceEditorWidget::OnObjectPreSave); + OnBlueprintCompileHandle = GEditor->OnBlueprintCompiled().AddSP(this, &SEffectCueSequenceEditorWidget::OnBlueprintCompiled); + OnBlueprintReinstancedHandle = GEditor->OnBlueprintReinstanced().AddSP(this, &SEffectCueSequenceEditorWidget::OnBlueprintReinstanced); + + WeakBlueprintEditor = InBlueprintEditor; + + ChildSlot + [ + SAssignNew(Content, SBox) + .MinDesiredHeight(200) + ]; + } + void OnBlueprintCompiled() + { + TSharedPtr BlueprintEditor = WeakBlueprintEditor.Pin(); + UBlueprint* bp = BlueprintEditor->GetBlueprintObj(); + float dupa = 0; + } + void OnBlueprintReinstanced() + { + float dupa = 0; + } + ~SEffectCueSequenceEditorWidget() + { + if (Sequencer.IsValid()) + { + Sequencer->Close(); + Sequencer = nullptr; + } + + GEditor->OnBlueprintPreCompile().Remove(OnBlueprintPreCompileHandle); + GEditor->OnBlueprintCompiled().Remove(OnBlueprintCompileHandle); + GEditor->OnBlueprintReinstanced().Remove(OnBlueprintReinstancedHandle); + FCoreUObjectDelegates::OnObjectSaved.Remove(OnObjectSavedHandle); + } + void OnObjectPreSave(UObject* InObject) + { + TSharedPtr BlueprintEditor = WeakBlueprintEditor.Pin(); + if (Sequencer.IsValid() && BlueprintEditor.IsValid() && InObject && InObject == BlueprintEditor->GetBlueprintObj()) + { + Sequencer->RestorePreAnimatedState(); + } + } + + void OnBlueprintPreCompile(UBlueprint* InBlueprint) + { + TSharedPtr BlueprintEditor = WeakBlueprintEditor.Pin(); + if (Sequencer.IsValid() && BlueprintEditor.IsValid() && InBlueprint && InBlueprint == BlueprintEditor->GetBlueprintObj()) + { + Sequencer->RestorePreAnimatedState(); + } + } + void OnSequenceChanged() + { + UGAEffectCueSequence* ActorSequence = WeakSequence.Get(); + /*UBlueprint* Blueprint = ActorSequence ? ActorSequence->GetParentBlueprint() : nullptr; + + if (Blueprint) + { + FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint); + }*/ + } + void OnSequencerReceivedFocus() + { + if (Sequencer.IsValid()) + { + FLevelEditorSequencerIntegration::Get().OnSequencerReceivedFocus(Sequencer.ToSharedRef()); + } + } + UObject* GetPlaybackContext() const + { + UGAEffectCueSequence* LocalActorSequence = WeakSequence.Get(); + if (LocalActorSequence) + { + if (AActor* Actor = LocalActorSequence->GetTypedOuter()) + { + return Actor; + } + else if (UBlueprintGeneratedClass* GeneratedClass = LocalActorSequence->GetTypedOuter()) + { + return GeneratedClass->SimpleConstructionScript->GetComponentEditorActorInstance(); + } + } + + return nullptr; + } + + TArray GetEventContexts() const + { + TArray Contexts; + if (auto* Context = GetPlaybackContext()) + { + Contexts.Add(Context); + } + return Contexts; + } + AActor* GetPreviewActor() const + { + TSharedPtr BlueprintEditor = WeakBlueprintEditor.Pin(); + if (BlueprintEditor.IsValid()) + { + return BlueprintEditor->GetPreviewActor(); + } + if (UGAEffectCueSequence* Sequence = WeakSequence.Get()) + { + return Sequence->GetTypedOuter(); + } + return nullptr; + } + void OnSelectionUpdated(TSharedPtr SelectedNode) + { + if (SelectedNode->GetNodeType() != FSCSEditorTreeNode::ComponentNode) + { + return; + } + + UActorComponent* EditingComponent = nullptr; + + TSharedPtr BlueprintEditor = WeakBlueprintEditor.Pin(); + if (BlueprintEditor.IsValid()) + { + UBlueprint* Blueprint = BlueprintEditor->GetBlueprintObj(); + if (Blueprint) + { + EditingComponent = SelectedNode->GetEditableComponentTemplate(Blueprint); + } + } + else if (AActor* Actor = GetPreviewActor()) + { + EditingComponent = SelectedNode->FindComponentInstanceInActor(Actor); + } + + if (EditingComponent) + { + const FScopedTransaction Transaction(FText::FromString("Add component to Sequencer")); + Sequencer->GetHandleToObject(EditingComponent, true); + } + + FSlateApplication::Get().DismissAllMenus(); + } + void AddPossessComponentMenuExtensions(FMenuBuilder& MenuBuilder) + { + AActor* Actor = GetPreviewActor(); + if (!Actor) + { + return; + } + + Sequencer->State.ClearObjectCaches(*Sequencer); + TSet AllBoundObjects; + if (UGAEffectCueSequence* Sequence = WeakSequence.Get()) + { + AllBoundObjects.Add(Sequence->GetTypedOuter()); + //return Sequence->GetTypedOuter(); + } + UMovieScene* MovieScene = Sequencer->GetFocusedMovieSceneSequence()->GetMovieScene(); + for (int32 Index = 0; Index < MovieScene->GetPossessableCount(); ++Index) + { + FMovieScenePossessable& Possessable = MovieScene->GetPossessable(Index); + for (TWeakObjectPtr<> WeakObject : Sequencer->FindBoundObjects(Possessable.GetGuid(), Sequencer->GetFocusedTemplateID())) + { + if (UObject* Object = WeakObject.Get()) + { + AllBoundObjects.Add(Object); + } + } + } + + bool bIdent = false; + /*MenuBuilder.AddWidget( + SNew(SComponentSelectionTree, Actor) + .IsInEditMode(WeakBlueprintEditor.Pin().IsValid()) + .OnComponentSelected(this, &SEffectCueSequenceEditorWidget::OnSelectionUpdated) + .IsComponentValid_Lambda( + [AllBoundObjects](UActorComponent* Component) + { + return !AllBoundObjects.Contains(Component); + } + ) + , FText(), !bIdent + );*/ + } + void SetActorSequence(UGAEffectCueSequence* NewSequence, AAFCueActor* InEffectCue) + { + if (UGAEffectCueSequence* OldSequence = WeakSequence.Get()) + { + if (OnSequenceChangedHandle.IsValid()) + { + OldSequence->OnSignatureChanged().Remove(OnSequenceChangedHandle); + } + } + EffectCue = InEffectCue; + WeakSequence = NewSequence; + + if (NewSequence) + { + OnSequenceChangedHandle = NewSequence->OnSignatureChanged().AddSP(this, &SEffectCueSequenceEditorWidget::OnSequenceChanged); + } + + // If we already have a sequencer open, just assign the sequence + if (Sequencer.IsValid() && NewSequence) + { + if (Sequencer->GetRootMovieSceneSequence() != NewSequence) + { + Sequencer->ResetToNewRootSequence(*NewSequence); + } + return; + } + + // If we're setting the sequence to none, destroy sequencer + if (!NewSequence) + { + //Content->SetContent(SNew(STextBlock).Text(LOCTEXT("NothingSelected", "Select a sequence"))); + return; + } + + // We need to initialize a new sequencer instance + FSequencerInitParams SequencerInitParams; + { + TWeakObjectPtr LocalWeakSequence = NewSequence; + + SequencerInitParams.RootSequence = NewSequence; + SequencerInitParams.EventContexts = TAttribute>(this, &SEffectCueSequenceEditorWidget::GetEventContexts); + SequencerInitParams.PlaybackContext = TAttribute(this, &SEffectCueSequenceEditorWidget::GetPlaybackContext); + + TSharedRef AddMenuExtender = MakeShareable(new FExtender); + + AddMenuExtender->AddMenuExtension("AddTracks", EExtensionHook::Before, nullptr, + FMenuExtensionDelegate::CreateLambda([=](FMenuBuilder& MenuBuilder) { + + MenuBuilder.AddSubMenu( + FText::FromString("Component"), + FText::FromString("Add a binding to one of this actor's components and allow it to be animated by Sequencer"), + FNewMenuDelegate::CreateRaw(this, &SEffectCueSequenceEditorWidget::AddPossessComponentMenuExtensions), + false /*bInOpenSubMenuOnClick*/, + FSlateIcon()//"LevelSequenceEditorStyle", "LevelSequenceEditor.PossessNewActor") + ); + + }) + ); + + SequencerInitParams.ViewParams.bReadOnly = false;// !WeakBlueprintEditor.IsValid() && !NewSequence->IsEditable(); + SequencerInitParams.bEditWithinLevelEditor = false; + SequencerInitParams.ViewParams.AddMenuExtender = AddMenuExtender; + SequencerInitParams.ViewParams.UniqueName = "EffectCueActorSequenceEditor"; + SequencerInitParams.ViewParams.OnReceivedFocus.BindRaw(this, &SEffectCueSequenceEditorWidget::OnSequencerReceivedFocus); + } + + Sequencer = FModuleManager::LoadModuleChecked("Sequencer").CreateSequencer(SequencerInitParams); + Content->SetContent(Sequencer->GetSequencerWidget()); + } +}; + + + +FEffectCueSequenceEditorSummoner::FEffectCueSequenceEditorSummoner(TSharedPtr BlueprintEditor) + : FWorkflowTabFactory("EmbeddedEffectCueSequenceID", BlueprintEditor) + , WeakBlueprintEditor(BlueprintEditor) +{ + bIsSingleton = true; + + TabLabel = FText::FromString("Cue Sequencer"); +} + +TSharedRef FEffectCueSequenceEditorSummoner::CreateTabBody(const FWorkflowTabSpawnInfo& Info) const +{ + return SNew(SEffectCueSequenceEditorWidget, WeakBlueprintEditor); +} + +TSharedRef FAFEffectCueDetails::MakeInstance() +{ + return MakeShareable(new FAFEffectCueDetails); +} + +void FAFEffectCueDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) +{ + const IDetailsView* DetailsView = DetailLayout.GetDetailsView(); + if (DetailsView) + { + TSharedPtr HostTabManager = DetailsView->GetHostTabManager(); + TArray> Objects; + DetailLayout.GetObjectsBeingCustomized(Objects); + AAFCueActor* EffectCue = Cast(Objects[0].Get()); + + if (HostTabManager.IsValid() && HostTabManager->CanSpawnTab("EmbeddedEffectCueSequenceID")) + { + TSharedPtr ExistingTab = HostTabManager->FindExistingLiveTab(FName("EmbeddedEffectCueSequenceID")); + if (ExistingTab.IsValid()) + { + //EffectCue->StaticClass()->GetDefaultObject()->Sequence + + //auto SequencerWidget = StaticCastSharedRef(ExistingTab->GetContent()); + StaticCastSharedRef(ExistingTab->GetContent())->SetActorSequence(EffectCue->StaticClass()->GetDefaultObject()->Sequence, EffectCue); + //bIsExternalTabAlreadyOpened = ThisSequence && SequencerWidget->GetSequence() == ThisSequence; + return; + } + //EffectCue->Sequence + if (!Tab.IsValid()) + Tab = HostTabManager->InvokeTab(FName("EmbeddedEffectCueSequenceID")); + //Tab->SetContent(Sequencer->GetSequencerWidget()); + StaticCastSharedRef(Tab->GetContent())->SetActorSequence(EffectCue->StaticClass()->GetDefaultObject()->Sequence, EffectCue); + } + } +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFEffectCueDetails.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFEffectCueDetails.h new file mode 100644 index 0000000..611e2aa --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AFEffectCueDetails.h @@ -0,0 +1,36 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypesEditor.h" + +#include "IDetailCustomization.h" +#include "PropertyHandle.h" + +#include "GraphEditor.h" +#include "ISequencer.h" +#include "Effects/GAEffectCueSequence.h" +#include "Editor/Kismet/Public/BlueprintEditor.h" +#include "WorkflowTabFactory.h" + +struct FEffectCueSequenceEditorSummoner + : public FWorkflowTabFactory +{ + FEffectCueSequenceEditorSummoner(TSharedPtr BlueprintEditor); + + virtual TSharedRef CreateTabBody(const FWorkflowTabSpawnInfo& Info) const override; + /*virtual TSharedRef SpawnTab(const FWorkflowTabSpawnInfo& Info) const override;*/ +protected: + TWeakPtr WeakBlueprintEditor; +}; +class FAFEffectCueDetails : public IDetailCustomization +{ +protected: + TSharedPtr Sequencer; + FDelegateHandle OnBlueprintPreCompileHandle; + TSharedPtr Tab; +public: + /** Makes a new instance of this detail layout class for a specific detail view requesting it */ + static TSharedRef MakeInstance(); + /** IDetailCustomization interface */ + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AssetTypeActions_AFCueActorBlueprint.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AssetTypeActions_AFCueActorBlueprint.cpp new file mode 100644 index 0000000..8df946c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AssetTypeActions_AFCueActorBlueprint.cpp @@ -0,0 +1,57 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#include "AbilityFrameworkEditor.h" +#include "AssetTypeActions_AFCueStaticBlueprint.h" +#include "Misc/MessageDialog.h" +#include "Kismet2/BlueprintEditorUtils.h" +#include "GAEffectCueEditor.h" +#include "AFCueActorBlueprint.h" +#include "Effects/AFCueActor.h" +#include "AFCueActorBlueprintFactory.h" + +#define LOCTEXT_NAMESPACE "AssetTypeActions" + +FText FAssetTypeActions_AFCueActorBlueprint::GetName() const +{ + return FText::FromString("Cue Actor"); +} +UClass* FAssetTypeActions_AFCueActorBlueprint::GetSupportedClass() const +{ + return UAFCueActorBlueprint::StaticClass(); +} + +void FAssetTypeActions_AFCueActorBlueprint::OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor) +{ + EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone; + + for (auto ObjIt = InObjects.CreateConstIterator(); ObjIt; ++ObjIt) + { + auto Blueprint = Cast(*ObjIt); + if (Blueprint && Blueprint->SkeletonGeneratedClass && Blueprint->GeneratedClass) + { + TSharedRef< FGAEffectCueEditor > NewEditor(new FGAEffectCueEditor()); + + TArray Blueprints; + Blueprints.Add(Blueprint); + + NewEditor->InitEffectCueEditor(Mode, EditWithinLevelEditor, Blueprints, ShouldUseDataOnlyEditor(Blueprint)); + } + else + { + FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Ability Blueprint could not be loaded because it derives from an invalid class. Check to make sure the parent class for this blueprint hasn't been removed!")); + } + } +} + +bool FAssetTypeActions_AFCueActorBlueprint::ShouldUseDataOnlyEditor(const UBlueprint* Blueprint) const +{ + return false; +} + +UFactory* FAssetTypeActions_AFCueActorBlueprint::GetFactoryForBlueprintType(UBlueprint* InBlueprint) const +{ + UAFCueActorBlueprintFactory* EffectCueBlueprintFactory = NewObject(); + EffectCueBlueprintFactory->ParentClass = TSubclassOf(*InBlueprint->GeneratedClass); + return EffectCueBlueprintFactory; +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AssetTypeActions_AFCueActorBlueprint.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AssetTypeActions_AFCueActorBlueprint.h new file mode 100644 index 0000000..d4d1445 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/AssetTypeActions_AFCueActorBlueprint.h @@ -0,0 +1,27 @@ +#pragma once +#include "CoreMinimal.h" +#include "Toolkits/IToolkitHost.h" +#include "AssetTypeCategories.h" + +#include "Developer/AssetTools/Public/AssetTypeActions/AssetTypeActions_Blueprint.h" + +class UFactory; + +class FAssetTypeActions_AFCueActorBlueprint : public FAssetTypeActions_Blueprint +{ +public: + // IAssetTypeActions Implementation + virtual FText GetName() const override; + virtual FColor GetTypeColor() const override { return FColor(0, 96, 128); } + virtual UClass* GetSupportedClass() const override; + virtual void OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor = TSharedPtr()) override; + virtual uint32 GetCategories() override { return EAssetTypeCategories::Gameplay; } + // End IAssetTypeActions Implementation + + // FAssetTypeActions_Blueprint interface + virtual UFactory* GetFactoryForBlueprintType(UBlueprint* InBlueprint) const override; + +private: + /** Returns true if the blueprint is data only */ + bool ShouldUseDataOnlyEditor(const UBlueprint* Blueprint) const; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueEditor.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueEditor.cpp new file mode 100644 index 0000000..18496a2 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueEditor.cpp @@ -0,0 +1,210 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +#include "../AbilityFrameworkEditor.h" +#include "Effects/AFCueActor.h" +#include "GAEffectCueEditor.h" +#include "Effects/GAEffectCueSequence.h" +#include "EditorReimportHandler.h" +#include "MovieScene.h" +#include "Tracks/MovieScenePropertyTrack.h" +#if WITH_EDITOR +#include "Editor.h" +#endif +#include "ISequencerModule.h" +#include "Editor/UnrealEd/Private/Toolkits/SStandaloneAssetEditorToolkitHost.h" +#include "Toolkits/ToolkitManager.h" +#include "Toolkits/GlobalEditorCommonCommands.h" + +#include "AFCueActorBlueprint.h" +#include "AFCueActorBlueprintFactory.h" +#include "GAEffectCueGraphSchema.h" +#include "Kismet2/BlueprintEditorUtils.h" +#include "SDockTab.h" +#include "BlueprintEditorTabs.h" +#include "LayoutExtender.h" +#include "BlueprintEditorModes.h" +#include "BlueprintEditorTabs.h" + +#define LOCTEXT_NAMESPACE "FGAEffectCueEditor" + + +//TSharedRef FEffectCueSequenceEditorSummoner::SpawnTab(const FWorkflowTabSpawnInfo& Info) const +//{ +// TSharedRef Tab = FWorkflowTabFactory::SpawnTab(Info); +// +// TSharedPtr BlueprintEditorPtr = StaticCastSharedPtr(HostingApp.Pin()); +// BlueprintEditorPtr->GetInspector()->SetOwnerTab(Tab); +// +// BlueprintEditorPtr->GetInspector()->GetPropertyView()->SetHostTabManager(Info.TabManager); +// +// return Tab; +//} + +///////////////////////////////////////////////////// +// FGameplayAbilitiesEditor + +FGAEffectCueEditor::FGAEffectCueEditor() +{ + EditedCue = nullptr; + FBlueprintEditorModule& BlueprintEditorModule = FModuleManager::LoadModuleChecked("Kismet"); + BlueprintEditorTabSpawnerHandle = BlueprintEditorModule.OnRegisterTabsForEditor().AddRaw(this, &FGAEffectCueEditor::RegisterBlueprintEditorTab); + BlueprintEditorLayoutExtensionHandle = BlueprintEditorModule.OnRegisterLayoutExtensions().AddRaw(this, &FGAEffectCueEditor::RegisterBlueprintEditorLayout); +} + +void FGAEffectCueEditor::RegisterBlueprintEditorLayout(FLayoutExtender& Extender) +{ + //Extender.ExtendLayout(FBlueprintEditorTabs::CompilerResultsID, ELayoutExtensionPosition::Before, FTabManager::FTab(FName("EmbeddedEffectCueSequenceID"), ETabState::ClosedTab)); +} + +void FGAEffectCueEditor::RegisterBlueprintEditorTab(FWorkflowAllowedTabSet& TabFactories, FName InModeName, TSharedPtr BlueprintEditor) +{ + //TabFactories.RegisterFactory(MakeShared(BlueprintEditor)); +} +TArray FGAEffectCueEditor::GetAnimationEventContexts() const +{ + TArray EventContexts; + return EventContexts; +} + +void FGAEffectCueEditor::OnSequenceChanged() +{ + UBlueprint* Blueprint = GetBlueprintObj(); + + if (Blueprint) + { + FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint); + } +} +void FGAEffectCueEditor::OnMovieSceneDataChanged() +{ +} +void FGAEffectCueEditor::ChangeViewedAnimation(UGAEffectCueSequence& InAnimationToView) +{ +} +FGAEffectCueEditor::~FGAEffectCueEditor() +{ + FEditorDelegates::OnAssetPostImport.RemoveAll(this); + FReimportManager::Instance()->OnPostReimport().RemoveAll(this); + FBlueprintEditorModule* BlueprintEditorModule = &FModuleManager::LoadModuleChecked("Kismet"); + BlueprintEditorModule->OnRegisterTabsForEditor().Remove(BlueprintEditorTabSpawnerHandle); + BlueprintEditorModule->OnRegisterLayoutExtensions().Remove(BlueprintEditorLayoutExtensionHandle); + BlueprintEditorTabSpawnerHandle.Reset(); + BlueprintEditorLayoutExtensionHandle.Reset(); + TabManager.Pin()->UnregisterTabSpawner(FName("EmbeddedEffectCueSequenceID")); + // NOTE: Any tabs that we still have hanging out when destroyed will be cleaned up by FBaseToolkit's destructor +} + +void FGAEffectCueEditor::RegisterTabSpawners(const TSharedRef& InTabManager) +{ + TabManager = InTabManager; + FBlueprintEditor::RegisterTabSpawners(InTabManager); +} +void FGAEffectCueEditor::UnregisterTabSpawners(const TSharedRef& InTabManager) +{ + FAssetEditorToolkit::RegisterTabSpawners(InTabManager); +} + +void FGAEffectCueEditor::InitAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr& InitToolkitHost, const FName AppIdentifier, const TSharedRef& StandaloneDefaultLayout, const bool bCreateDefaultStandaloneMenu, const bool bCreateDefaultToolbar, const TArray& ObjectsToEdit, const bool bInIsToolbarFocusable) +{ + + FAssetEditorToolkit::InitAssetEditor(Mode, InitToolkitHost, AppIdentifier, StandaloneDefaultLayout, bCreateDefaultStandaloneMenu, bCreateDefaultToolbar, ObjectsToEdit, bInIsToolbarFocusable); +} +void FGAEffectCueEditor::InitEffectCueEditor(const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, const TArray& InBlueprints, bool bShouldOpenInDefaultsMode) +{ + InitBlueprintEditor(Mode, InitToolkitHost, InBlueprints, bShouldOpenInDefaultsMode); + UBlueprint* BP = InBlueprints[0]; + EditedCue = BP->GeneratedClass->GetDefaultObject(); + CueClass = BP->GeneratedClass; + + for (auto Blueprint : InBlueprints) + { + EnsureAbilityBlueprintIsUpToDate(Blueprint); + } +} + +void FGAEffectCueEditor::EnsureAbilityBlueprintIsUpToDate(UBlueprint* Blueprint) +{ +#if WITH_EDITORONLY_DATA + int32 Count = Blueprint->UbergraphPages.Num(); + for (auto Graph : Blueprint->UbergraphPages) + { + // remove the default event graph, if it exists, from existing Gameplay Ability Blueprints + if (Graph->GetName() == "EventGraph" && Graph->Nodes.Num() == 0) + { + check(!Graph->Schema->GetClass()->IsChildOf(UGAEffectCueGraphSchema::StaticClass())); + FBlueprintEditorUtils::RemoveGraph(Blueprint, Graph); + break; + } + } +#endif +} +bool FGAEffectCueEditor::IsBlueprintEditor() const +{ + return true; +} + +FName FGAEffectCueEditor::GetToolkitFName() const +{ + return FName("EffectCueEditor"); +} + +FText FGAEffectCueEditor::GetBaseToolkitName() const +{ + return FText::FromString("Game Effect Cue"); +} + +FText FGAEffectCueEditor::GetToolkitName() const +{ + const TArray& EditingObjs = GetEditingObjects(); + + check(EditingObjs.Num() > 0); + + FFormatNamedArguments Args; + + const UObject* EditingObject = EditingObjs[0]; + + const bool bDirtyState = EditingObject->GetOutermost()->IsDirty(); + + Args.Add(TEXT("ObjectName"), FText::FromString(EditingObject->GetName())); + Args.Add(TEXT("DirtyState"), bDirtyState ? FText::FromString(TEXT("*")) : FText::GetEmpty()); + return FText::Format(FText::FromString("{ObjectName}{DirtyState}"), Args); +} + +FText FGAEffectCueEditor::GetToolkitToolTipText() const +{ + const UObject* EditingObject = GetEditingObject(); + + check (EditingObject != NULL); + + return FAssetEditorToolkit::GetToolTipTextForObject(EditingObject); +} + +FString FGAEffectCueEditor::GetWorldCentricTabPrefix() const +{ + return TEXT("EffectCueEditor"); +} + +FLinearColor FGAEffectCueEditor::GetWorldCentricTabColorScale() const +{ + return FLinearColor::White; +} + +UBlueprint* FGAEffectCueEditor::GetBlueprintObj() const +{ + const TArray& EditingObjs = GetEditingObjects(); + for (int32 i = 0; i < EditingObjs.Num(); ++i) + { + if (EditingObjs[i]->IsA()) + { + return (UBlueprint*)EditingObjs[i]; + } + } + return nullptr; +} + +FString FGAEffectCueEditor::GetDocumentationLink() const +{ + return FBlueprintEditor::GetDocumentationLink(); // todo: point this at the correct documentation +} + +#undef LOCTEXT_NAMESPACE + diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueEditor.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueEditor.h new file mode 100644 index 0000000..1babf1d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueEditor.h @@ -0,0 +1,79 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Framework/Commands/UICommandList.h" +#include "Framework/MultiBox/MultiBoxExtender.h" +#include "GraphEditor.h" +#include "ISequencer.h" +#include "Effects/GAEffectCueSequence.h" +#include "Editor/Kismet/Public/BlueprintEditor.h" +#include "WorkflowTabFactory.h" +////////////////////////////////////////////////////////////////////////// +// FGameplayAbilitiesEditor +class UGAEffectCueSequence; +/** + * Gameplay abilities asset editor (extends Blueprint editor) + */ + +class FGAEffectCueEditor : public FBlueprintEditor +{ + TWeakPtr TabManager; + FDelegateHandle OnSequenceChangedHandle; + + TArray GetAnimationEventContexts() const; + FDelegateHandle BlueprintEditorTabSpawnerHandle, BlueprintEditorLayoutExtensionHandle; + class AAFCueActor* EditedCue; + TSubclassOf CueClass; + TWeakObjectPtr EditedSequence; + void ChangeViewedAnimation(UGAEffectCueSequence& InAnimationToView); + void OnMovieSceneDataChanged(); + void OnSequenceChanged(); + void RegisterBlueprintEditorLayout(FLayoutExtender& Extender); + void RegisterBlueprintEditorTab(FWorkflowAllowedTabSet& TabFactories, FName InModeName, TSharedPtr BlueprintEditor); +public: + virtual void InitAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr& InitToolkitHost, const FName AppIdentifier, const TSharedRef& StandaloneDefaultLayout, const bool bCreateDefaultStandaloneMenu, const bool bCreateDefaultToolbar, const TArray& ObjectsToEdit, const bool bInIsToolbarFocusable = false) override; + /** + * Edits the specified gameplay ability asset(s) + * + * @param Mode Asset editing mode for this editor (standalone or world-centric) + * @param InitToolkitHost When Mode is WorldCentric, this is the level editor instance to spawn this editor within + * @param InBlueprints The blueprints to edit + * @param bShouldOpenInDefaultsMode If true, the editor will open in defaults editing mode + */ + + void InitEffectCueEditor(const EToolkitMode::Type Mode, const TSharedPtr& InitToolkitHost, const TArray& InBlueprints, bool bShouldOpenInDefaultsMode); +private: + /** + * Updates existing gameplay ability blueprints to make sure that they are up to date + * + * @param Blueprint The blueprint to be updated + */ + void EnsureAbilityBlueprintIsUpToDate(UBlueprint* Blueprint); + +public: + FGAEffectCueEditor(); + + virtual ~FGAEffectCueEditor(); + +public: + // IToolkit interface + // FRED_TODO: don't merge this back + virtual void RegisterTabSpawners(const TSharedRef& InTabManager) override; + virtual void UnregisterTabSpawners(const TSharedRef& InTabManager) override; + virtual FName GetToolkitFName() const override; + virtual FText GetBaseToolkitName() const override; + virtual FText GetToolkitName() const override; + virtual FText GetToolkitToolTipText() const override; + virtual FString GetWorldCentricTabPrefix() const override; + virtual FLinearColor GetWorldCentricTabColorScale() const override; + virtual bool IsBlueprintEditor() const override; + // End of IToolkit interface + + /** @return the documentation location for this editor */ + virtual FString GetDocumentationLink() const override; + + /** Returns a pointer to the Blueprint object we are currently editing, as long as we are editing exactly one */ + virtual UBlueprint* GetBlueprintObj() const override; +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraph.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraph.cpp new file mode 100644 index 0000000..1487984 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraph.cpp @@ -0,0 +1,16 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFrameworkEditor.h" +#include "GAEffectCueGraph.h" + +#define LOCTEXT_NAMESPACE "GameplayAbilityGraph" + +///////////////////////////////////////////////////// +// UGameplayAbilityGraph + +UGAEffectCueGraph::UGAEffectCueGraph(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraph.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraph.h new file mode 100644 index 0000000..5a3bfe0 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraph.h @@ -0,0 +1,15 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "EdGraph/EdGraph.h" +#include "GAEffectCueGraph.generated.h" + +UCLASS(MinimalAPI) +class UGAEffectCueGraph : public UEdGraph +{ + GENERATED_UCLASS_BODY() +}; + diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraphSchema.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraphSchema.cpp new file mode 100644 index 0000000..bae2670 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraphSchema.cpp @@ -0,0 +1,22 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFrameworkEditor.h" +#include "GAEffectCueGraphSchema.h" +#include "EdGraphSchema_K2_Actions.h" +#include "Effects/GAGameEffect.h" +#include "Kismet2/BlueprintEditorUtils.h" + +UGAEffectCueGraphSchema::UGAEffectCueGraphSchema(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ +} + +UK2Node_VariableGet* UGAEffectCueGraphSchema::SpawnVariableGetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const +{ + return Super::SpawnVariableGetNode(GraphPosition, ParentGraph, VariableName, Source); +} + +UK2Node_VariableSet* UGAEffectCueGraphSchema::SpawnVariableSetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const +{ + return Super::SpawnVariableSetNode(GraphPosition, ParentGraph, VariableName, Source); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraphSchema.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraphSchema.h new file mode 100644 index 0000000..1f9b8cc --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectCueEditor/GAEffectCueGraphSchema.h @@ -0,0 +1,38 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "EdGraphSchema_K2.h" +#include "GAEffectCueGraphSchema.generated.h" + +UCLASS(MinimalAPI) +class UGAEffectCueGraphSchema : public UEdGraphSchema_K2 +{ + GENERATED_UCLASS_BODY() + + /** + * Creates a new variable getter node and adds it to ParentGraph + * + * @param GraphPosition The location of the new node inside the graph + * @param ParentGraph The graph to spawn the new node in + * @param VariableName The name of the variable + * @param Source The source of the variable + * @return A pointer to the newly spawned node + */ + virtual class UK2Node_VariableGet* SpawnVariableGetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const override; + + /** + * Creates a new variable setter node and adds it to ParentGraph + * + * @param GraphPosition The location of the new node inside the graph + * @param ParentGraph The graph to spawn the new node in + * @param VariableName The name of the variable + * @param Source The source of the variable + * @return A pointer to the newly spawned node + */ + virtual class UK2Node_VariableSet* SpawnVariableSetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const override; + + virtual bool ShouldAlwaysPurgeOnModification() const override { return true; } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/AssetTypeActions_GAEffectBlueprint.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/AssetTypeActions_GAEffectBlueprint.cpp new file mode 100644 index 0000000..44ef642 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/AssetTypeActions_GAEffectBlueprint.cpp @@ -0,0 +1,57 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#include "../AbilityFrameworkEditor.h" +#include "AssetTypeActions_GAEffectBlueprint.h" +#include "Misc/MessageDialog.h" +#include "Kismet2/BlueprintEditorUtils.h" +#include "GAEffectEditor.h" +#include "Effects/GAEffectBlueprint.h" +#include "Effects/GAGameEffect.h" +#include "GAEffectBlueprintFactory.h" + +#define LOCTEXT_NAMESPACE "AssetTypeActions" + +FText FAssetTypeActions_GAEffectBlueprint::GetName() const +{ + return FText::FromString("Effect Data"); +} +UClass* FAssetTypeActions_GAEffectBlueprint::GetSupportedClass() const +{ + return UGAEffectBlueprint::StaticClass(); +} + +void FAssetTypeActions_GAEffectBlueprint::OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor) +{ + EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone; + + for (auto ObjIt = InObjects.CreateConstIterator(); ObjIt; ++ObjIt) + { + auto Blueprint = Cast(*ObjIt); + if (Blueprint && Blueprint->SkeletonGeneratedClass && Blueprint->GeneratedClass) + { + TSharedRef< FGAEffectEditor > NewEditor(new FGAEffectEditor()); + + TArray Blueprints; + Blueprints.Add(Blueprint); + + NewEditor->InitEffectEditor(Mode, EditWithinLevelEditor, Blueprints, ShouldUseDataOnlyEditor(Blueprint)); + } + else + { + FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Gameplay Ability Blueprint could not be loaded because it derives from an invalid class. Check to make sure the parent class for this blueprint hasn't been removed!")); + } + } +} + +bool FAssetTypeActions_GAEffectBlueprint::ShouldUseDataOnlyEditor(const UBlueprint* Blueprint) const +{ + return true; +} + +UFactory* FAssetTypeActions_GAEffectBlueprint::GetFactoryForBlueprintType(UBlueprint* InBlueprint) const +{ + UGAEffectBlueprintFactory* EffectBlueprintFactory = NewObject(); + EffectBlueprintFactory->ParentClass = TSubclassOf(*InBlueprint->GeneratedClass); + return EffectBlueprintFactory; +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/AssetTypeActions_GAEffectBlueprint.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/AssetTypeActions_GAEffectBlueprint.h new file mode 100644 index 0000000..ad3cabd --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/AssetTypeActions_GAEffectBlueprint.h @@ -0,0 +1,27 @@ +#pragma once +#include "CoreMinimal.h" +#include "Toolkits/IToolkitHost.h" +#include "AssetTypeCategories.h" +//#include "Developer/AssetTools/Private/AssetTypeActions/AssetTypeActions_ClassTypeBase.h" +#include "Developer/AssetTools/Public/AssetTypeActions/AssetTypeActions_Blueprint.h" + +class UFactory; + +class FAssetTypeActions_GAEffectBlueprint : public FAssetTypeActions_Blueprint +{ +public: + // IAssetTypeActions Implementation + virtual FText GetName() const override; + virtual FColor GetTypeColor() const override { return FColor(0, 96, 128); } + virtual UClass* GetSupportedClass() const override; + virtual void OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor = TSharedPtr()) override; + virtual uint32 GetCategories() override { return EAssetTypeCategories::Gameplay; } + // End IAssetTypeActions Implementation + + // FAssetTypeActions_Blueprint interface + virtual UFactory* GetFactoryForBlueprintType(UBlueprint* InBlueprint) const override; + +private: + /** Returns true if the blueprint is data only */ + bool ShouldUseDataOnlyEditor(const UBlueprint* Blueprint) const; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectBlueprintFactory.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectBlueprintFactory.cpp new file mode 100644 index 0000000..c84d883 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectBlueprintFactory.cpp @@ -0,0 +1,347 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +#include "../AbilityFrameworkEditor.h" +#include "GAEffectBlueprintFactory.h" +#include "InputCoreTypes.h" +#include "UObject/Interface.h" +#include "Layout/Visibility.h" +#include "Input/Reply.h" +#include "Widgets/SWidget.h" +#include "Widgets/DeclarativeSyntaxSupport.h" +#include "Misc/MessageDialog.h" +#include "Modules/ModuleManager.h" +#include "Effects/GAGameEffect.h" +#include "Widgets/SCompoundWidget.h" +#include "Widgets/SBoxPanel.h" +#include "Widgets/SWindow.h" +#include "Widgets/Layout/SBorder.h" +#include "Widgets/Text/STextBlock.h" +#include "Widgets/Layout/SBox.h" +#include "Widgets/Layout/SUniformGridPanel.h" +#include "Widgets/Input/SButton.h" +#include "EditorStyleSet.h" +#include "Editor.h" +#include "EdGraphSchema_K2.h" + +#include "ClassViewerModule.h" +#include "Kismet2/BlueprintEditorUtils.h" +#include "Engine/BlueprintGeneratedClass.h" +#include "Kismet2/KismetEditorUtilities.h" +#include "BlueprintEditorSettings.h" + +#include "Effects/GAEffectBlueprint.h" +#include "GAEffectGraph.h" +#include "GAEffectGraphSchema.h" +#include "Abilities/AFAbilityActivationSpec.h" +#include "Abilities/AFAbilityCooldownSpec.h" +#include "Abilities/AFAbilityPeriodSpec.h" +#include "Abilities/AFAbilityInfiniteDurationSpec.h" + +#include "ClassViewerFilter.h" + +#include "SlateOptMacros.h" + +#define LOCTEXT_NAMESPACE "UEffectBlueprintFactory" + + +// ------------------------------------------------------------------------------ +// Dialog to configure creation properties +// ------------------------------------------------------------------------------ +BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION + +class SEffectBlueprintCreateDialog : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SEffectBlueprintCreateDialog){} + + SLATE_END_ARGS() + + /** Constructs this widget with InArgs */ + void Construct(const FArguments& InArgs) + { + bOkClicked = false; + ParentClass = UGAGameEffectSpec::StaticClass(); + + ChildSlot + [ + SNew(SBorder) + .Visibility(EVisibility::Visible) + .BorderImage(FEditorStyle::GetBrush("Menu.Background")) + [ + SNew(SBox) + .Visibility(EVisibility::Visible) + .WidthOverride(500.0f) + [ + SNew(SVerticalBox) + + SVerticalBox::Slot() + .FillHeight(1) + [ + SNew(SBorder) + .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) + .Content() + [ + SAssignNew(ParentClassContainer, SVerticalBox) + ] + ] + + // Ok/Cancel buttons + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(HAlign_Right) + .VAlign(VAlign_Bottom) + .Padding(8) + [ + SNew(SUniformGridPanel) + .SlotPadding(FEditorStyle::GetMargin("StandardDialog.SlotPadding")) + .MinDesiredSlotWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth")) + .MinDesiredSlotHeight(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotHeight")) + + SUniformGridPanel::Slot(0, 0) + [ + SNew(SButton) + .HAlign(HAlign_Center) + .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + .OnClicked(this, &SEffectBlueprintCreateDialog::OkClicked) + .Text(FText::FromString("OK")) + ] + + SUniformGridPanel::Slot(1, 0) + [ + SNew(SButton) + .HAlign(HAlign_Center) + .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + .OnClicked(this, &SEffectBlueprintCreateDialog::CancelClicked) + .Text(FText::FromString("Cancel")) + ] + ] + ] + ] + ]; + + MakeParentClassPicker(); + } + + /** Sets properties for the supplied EffectBlueprintFactory */ + bool ConfigureProperties(TWeakObjectPtr InEffectlueprintFactory) + { + EffectBlueprintFactory = InEffectlueprintFactory; + + TSharedRef Window = SNew(SWindow) + .Title(FText::FromString("Create Game Effect Blueprint")) + .ClientSize(FVector2D(400, 700)) + .SupportsMinimize(false).SupportsMaximize(false) + [ + AsShared() + ]; + + PickerWindow = Window; + + GEditor->EditorAddModalWindow(Window); + EffectBlueprintFactory.Reset(); + + return bOkClicked; + } + +private: + class FEffectBlueprintParentFilter : public IClassViewerFilter + { + public: + /** All children of these classes will be included unless filtered out by another setting. */ + TSet< const UClass* > AllowedChildrenOfClasses; + + FEffectBlueprintParentFilter() {} + + virtual bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InClass) != EFilterReturn::Failed; + } + + virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef< const IUnloadedBlueprintData > InUnloadedClassData, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InUnloadedClassData) != EFilterReturn::Failed; + } + }; + + /** Creates the combo menu for the parent class */ + void MakeParentClassPicker() + { + // Load the classviewer module to display a class picker + FClassViewerModule& ClassViewerModule = FModuleManager::LoadModuleChecked("ClassViewer"); + + // Fill in options + FClassViewerInitializationOptions Options; + Options.Mode = EClassViewerMode::ClassPicker; + + // Only allow parenting to base blueprints. + Options.bIsBlueprintBaseOnly = true; + + TSharedPtr Filter = MakeShareable(new FEffectBlueprintParentFilter); + + // All child child classes of UGameplayAbility are valid. + Filter->AllowedChildrenOfClasses.Add(UAFEffectSpecBase::StaticClass()); + Filter->AllowedChildrenOfClasses.Add(UAFAbilityActivationSpec::StaticClass()); + Filter->AllowedChildrenOfClasses.Add(UAFAbilityCooldownSpec::StaticClass()); + Filter->AllowedChildrenOfClasses.Add(UAFAbilityPeriodSpec::StaticClass()); + Filter->AllowedChildrenOfClasses.Add(UAFAbilityInfiniteDurationSpec::StaticClass()); + + Options.ClassFilter = Filter; + + ParentClassContainer->ClearChildren(); + ParentClassContainer->AddSlot() + .AutoHeight() + [ + SNew(STextBlock) + .Text(FText::FromString("Parent Class:")) + .ShadowOffset(FVector2D(1.0f, 1.0f)) + ]; + + ParentClassContainer->AddSlot() + [ + ClassViewerModule.CreateClassViewer(Options, FOnClassPicked::CreateSP(this, &SEffectBlueprintCreateDialog::OnClassPicked)) + ]; + } + + /** Handler for when a parent class is selected */ + void OnClassPicked(UClass* ChosenClass) + { + ParentClass = ChosenClass; + } + + /** Handler for when ok is clicked */ + FReply OkClicked() + { + if (EffectBlueprintFactory.IsValid()) + { + EffectBlueprintFactory->BlueprintType = BPTYPE_Normal; + EffectBlueprintFactory->ParentClass = ParentClass.Get(); + } + + CloseDialog(true); + + return FReply::Handled(); + } + + void CloseDialog(bool bWasPicked = false) + { + bOkClicked = bWasPicked; + if (PickerWindow.IsValid()) + { + PickerWindow.Pin()->RequestDestroyWindow(); + } + } + + /** Handler for when cancel is clicked */ + FReply CancelClicked() + { + CloseDialog(); + return FReply::Handled(); + } + + FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) + { + if (InKeyEvent.GetKey() == EKeys::Escape) + { + CloseDialog(); + return FReply::Handled(); + } + return SWidget::OnKeyDown(MyGeometry, InKeyEvent); + } + +private: + /** The factory for which we are setting up properties */ + TWeakObjectPtr EffectBlueprintFactory; + + /** A pointer to the window that is asking the user to select a parent class */ + TWeakPtr PickerWindow; + + /** The container for the Parent Class picker */ + TSharedPtr ParentClassContainer; + + /** The selected class */ + TWeakObjectPtr ParentClass; + + /** True if Ok was clicked */ + bool bOkClicked; +}; + +END_SLATE_FUNCTION_BUILD_OPTIMIZATION + +/*------------------------------------------------------------------------------ + UEffectBlueprintFactory implementation. +------------------------------------------------------------------------------*/ + +UGAEffectBlueprintFactory::UGAEffectBlueprintFactory(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + bCreateNew = true; + bEditAfterNew = true; + SupportedClass = UGAEffectBlueprint::StaticClass(); + ParentClass = UGAGameEffectSpec::StaticClass(); +} + +bool UGAEffectBlueprintFactory::ConfigureProperties() +{ + TSharedRef Dialog = SNew(SEffectBlueprintCreateDialog); + return Dialog->ConfigureProperties(this); +}; + +UObject* UGAEffectBlueprintFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) +{ + // Make sure we are trying to factory a gameplay ability blueprint, then create and init one + check(Class->IsChildOf(UGAEffectBlueprint::StaticClass())); + + // If they selected an interface, force the parent class to be UInterface + if (BlueprintType == BPTYPE_Interface) + { + ParentClass = UInterface::StaticClass(); + } + + if ( ( ParentClass == NULL ) || !FKismetEditorUtilities::CanCreateBlueprintOfClass(ParentClass) || !ParentClass->IsChildOf(UGAGameEffectSpec::StaticClass()) ) + { + FFormatNamedArguments Args; + Args.Add( TEXT("ClassName"), (ParentClass != NULL) ? FText::FromString( ParentClass->GetName() ) : LOCTEXT("Null", "(null)") ); + FMessageDialog::Open( EAppMsgType::Ok, FText::Format( FText::FromString("Cannot create a Effect Blueprint based on the class '{ClassName}'."), Args ) ); + return NULL; + } + else + { + UGAEffectBlueprint* NewBP = CastChecked(FKismetEditorUtilities::CreateBlueprint(ParentClass, InParent, Name, BlueprintType, UGAEffectBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass(), CallingContext)); + + if (NewBP) + { + UGAEffectBlueprint* AbilityBP = UGAEffectBlueprint::FindRootGameplayAbilityBlueprint(NewBP); + if (AbilityBP == NULL) + { + const UEdGraphSchema_K2* K2Schema = GetDefault(); + + // Only allow a gameplay ability graph if there isn't one in a parent blueprint + //UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(NewBP, TEXT("Not Used Effect Graph"), UGAEffectGraph::StaticClass(), UGAEffectGraphSchema::StaticClass()); +#if WITH_EDITORONLY_DATA + if (NewBP->UbergraphPages.Num()) + { + FBlueprintEditorUtils::RemoveGraphs(NewBP, NewBP->UbergraphPages); + } +#endif + //FBlueprintEditorUtils::AddUbergraphPage(NewBP, NewGraph); + //NewBP->LastEditedDocuments.Add(NewGraph); + //NewGraph->bAllowDeletion = false; + + UBlueprintEditorSettings* Settings = GetMutableDefault(); + if(Settings && Settings->bSpawnDefaultBlueprintNodes) + { + int32 NodePositionY = 0; + //FKismetEditorUtilities::AddDefaultEventNode(NewBP, NewGraph, FName(TEXT("K2_ActivateAbility")), UGAGameEffectSpec::StaticClass(), NodePositionY); + //FKismetEditorUtilities::AddDefaultEventNode(NewBP, NewGraph, FName(TEXT("K2_OnEndAbility")), UGAGameEffectSpec::StaticClass(), NodePositionY); + } + } + } + + return NewBP; + } +} + +UObject* UGAEffectBlueprintFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) +{ + return FactoryCreateNew(Class, InParent, Name, Flags, Context, Warn, NAME_None); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectBlueprintFactory.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectBlueprintFactory.h new file mode 100644 index 0000000..8a9b850 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectBlueprintFactory.h @@ -0,0 +1,32 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Templates/SubclassOf.h" +#include "Engine/Blueprint.h" +#include "Factories/Factory.h" +#include "AssetTypeCategories.h" +#include "GAEffectBlueprintFactory.generated.h" + +UCLASS(HideCategories=Object, MinimalAPI) +class UGAEffectBlueprintFactory : public UFactory +{ + GENERATED_UCLASS_BODY() + + // The type of blueprint that will be created + UPROPERTY(EditAnywhere, Category=GameplayAbilitiesBlueprintFactory) + TEnumAsByte BlueprintType; + + // The parent class of the created blueprint + UPROPERTY(EditAnywhere, Category=GameplayAbilitiesBlueprintFactory) + TSubclassOf ParentClass; + + //~ Begin UFactory Interface + virtual bool ConfigureProperties() override; + virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) override; + virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override; + + //~ Begin UFactory Interface +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectEditor.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectEditor.cpp new file mode 100644 index 0000000..5559a8d --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectEditor.cpp @@ -0,0 +1,124 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +#include "../AbilityFrameworkEditor.h" +#include "GAEffectEditor.h" +#include "EditorReimportHandler.h" + +#if WITH_EDITOR +#include "Editor.h" +#endif +//Editor\UnrealEd\Public\Toolkits\ToolkitManager.h +//\Editor\UnrealEd\Private\Toolkits\SStandaloneAssetEditorToolkitHost.h +#include "Editor/UnrealEd/Private/Toolkits/SStandaloneAssetEditorToolkitHost.h" +#include "Toolkits/ToolkitManager.h" +//#include "Toolkits/AssetEditorCommonCommands.h" +#include "Toolkits/GlobalEditorCommonCommands.h" + +#include "Effects/GAEffectBlueprint.h" +#include "GAEffectBlueprintFactory.h" +#include "GAEffectGraphSchema.h" +#include "Kismet2/BlueprintEditorUtils.h" + +#define LOCTEXT_NAMESPACE "FGAEffectEditor" + + +///////////////////////////////////////////////////// +// FGameplayAbilitiesEditor + +FGAEffectEditor::FGAEffectEditor() +{ + // todo: Do we need to register a callback for when properties are changed? + //bCreateMenuExtenders = true; + //bCreateDefaultStandaloneMenu = false; + //bCreateDefaultToolbar = false; +} + +FGAEffectEditor::~FGAEffectEditor() +{ + FEditorDelegates::OnAssetPostImport.RemoveAll(this); + FReimportManager::Instance()->OnPostReimport().RemoveAll(this); + + // NOTE: Any tabs that we still have hanging out when destroyed will be cleaned up by FBaseToolkit's destructor +} +void FGAEffectEditor::InitAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr& InitToolkitHost, const FName AppIdentifier, const TSharedRef& StandaloneDefaultLayout, const bool bCreateDefaultStandaloneMenu, const bool bCreateDefaultToolbar, const TArray& ObjectsToEdit, const bool bInIsToolbarFocusable) +{ + FAssetEditorToolkit::InitAssetEditor(Mode, InitToolkitHost, AppIdentifier, StandaloneDefaultLayout, true, true, ObjectsToEdit, true); +} +void FGAEffectEditor::InitEffectEditor(const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, const TArray& InBlueprints, bool bShouldOpenInDefaultsMode) +{ + InitBlueprintEditor(Mode, InitToolkitHost, InBlueprints, bShouldOpenInDefaultsMode); + RemoveAllToolbarWidgets(); +} + + +// FRED_TODO: don't merge this back +// FName FGameplayAbilitiesEditor::GetToolkitContextFName() const +// { +// return GetToolkitFName(); +// } + +FName FGAEffectEditor::GetToolkitFName() const +{ + return FName("GameEffectEditor"); +} + +FText FGAEffectEditor::GetBaseToolkitName() const +{ + return FText::FromString("Game Effect Editor"); +} + +FText FGAEffectEditor::GetToolkitName() const +{ + const TArray& EditingObjs = GetEditingObjects(); + + check(EditingObjs.Num() > 0); + + FFormatNamedArguments Args; + + const UObject* EditingObject = EditingObjs[0]; + + const bool bDirtyState = EditingObject->GetOutermost()->IsDirty(); + + Args.Add(TEXT("ObjectName"), FText::FromString(EditingObject->GetName())); + Args.Add(TEXT("DirtyState"), bDirtyState ? FText::FromString(TEXT("*")) : FText::GetEmpty()); + return FText::Format(LOCTEXT("GameplayAbilitiesToolkitName", "{ObjectName}{DirtyState}"), Args); +} + +FText FGAEffectEditor::GetToolkitToolTipText() const +{ + const UObject* EditingObject = GetEditingObject(); + + check(EditingObject != NULL); + + return FAssetEditorToolkit::GetToolTipTextForObject(EditingObject); +} + +FString FGAEffectEditor::GetWorldCentricTabPrefix() const +{ + return TEXT("EffectEditor"); +} + +FLinearColor FGAEffectEditor::GetWorldCentricTabColorScale() const +{ + return FLinearColor::White; +} + +UBlueprint* FGAEffectEditor::GetBlueprintObj() const +{ + const TArray& EditingObjs = GetEditingObjects(); + for (int32 i = 0; i < EditingObjs.Num(); ++i) + { + if (EditingObjs[i]->IsA()) + { + return (UBlueprint*)EditingObjs[i]; + } + } + return nullptr; +} + +FString FGAEffectEditor::GetDocumentationLink() const +{ + return FBlueprintEditor::GetDocumentationLink(); // todo: point this at the correct documentation +} + +#undef LOCTEXT_NAMESPACE + diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectEditor.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectEditor.h new file mode 100644 index 0000000..e0dd625 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectEditor.h @@ -0,0 +1,53 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Editor/Kismet/Public/BlueprintEditor.h" + +////////////////////////////////////////////////////////////////////////// +// FGameplayAbilitiesEditor + +/** + * Gameplay abilities asset editor (extends Blueprint editor) + */ +class FGAEffectEditor : public FBlueprintEditor +{ +public: + virtual void InitAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr& InitToolkitHost, const FName AppIdentifier, const TSharedRef& StandaloneDefaultLayout, const bool bCreateDefaultStandaloneMenu, const bool bCreateDefaultToolbar, const TArray& ObjectsToEdit, const bool bInIsToolbarFocusable = false) override; + /** + * Edits the specified gameplay ability asset(s) + * + * @param Mode Asset editing mode for this editor (standalone or world-centric) + * @param InitToolkitHost When Mode is WorldCentric, this is the level editor instance to spawn this editor within + * @param InBlueprints The blueprints to edit + * @param bShouldOpenInDefaultsMode If true, the editor will open in defaults editing mode + */ + + void InitEffectEditor(const EToolkitMode::Type Mode, const TSharedPtr& InitToolkitHost, const TArray& InBlueprints, bool bShouldOpenInDefaultsMode); +public: + FGAEffectEditor(); + + virtual ~FGAEffectEditor(); + +public: + // IToolkit interface + // FRED_TODO: don't merge this back +// virtual FName GetToolkitContextFName() const override; + virtual FName GetToolkitFName() const override; + virtual FText GetBaseToolkitName() const override; + virtual FText GetToolkitName() const override; + virtual FText GetToolkitToolTipText() const override; + virtual FString GetWorldCentricTabPrefix() const override; + virtual FLinearColor GetWorldCentricTabColorScale() const override; + virtual bool IsAssetEditor() const override { return true; } + virtual bool IsBlueprintEditor() const override { return false; }; + virtual void PostRegenerateMenusAndToolbars() override { RemoveAllToolbarWidgets(); }; + // End of IToolkit interface + + /** @return the documentation location for this editor */ + virtual FString GetDocumentationLink() const override; + + /** Returns a pointer to the Blueprint object we are currently editing, as long as we are editing exactly one */ + virtual UBlueprint* GetBlueprintObj() const override; +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraph.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraph.cpp new file mode 100644 index 0000000..a802167 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraph.cpp @@ -0,0 +1,16 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFrameworkEditor.h" +#include "GAEffectGraph.h" + +#define LOCTEXT_NAMESPACE "GameplayAbilityGraph" + +///////////////////////////////////////////////////// +// UGameplayAbilityGraph + +UGAEffectGraph::UGAEffectGraph(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraph.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraph.h new file mode 100644 index 0000000..3492fc2 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraph.h @@ -0,0 +1,15 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "EdGraph/EdGraph.h" +#include "GAEffectGraph.generated.h" + +UCLASS(MinimalAPI) +class UGAEffectGraph : public UEdGraph +{ + GENERATED_UCLASS_BODY() +}; + diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraphSchema.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraphSchema.cpp new file mode 100644 index 0000000..1404740 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraphSchema.cpp @@ -0,0 +1,22 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "../AbilityFrameworkEditor.h" +#include "GAEffectGraphSchema.h" +#include "EdGraphSchema_K2_Actions.h" +#include "Effects/GAGameEffect.h" +#include "Kismet2/BlueprintEditorUtils.h" + +UGAEffectGraphSchema::UGAEffectGraphSchema(const FObjectInitializer& ObjectInitializer) +: Super(ObjectInitializer) +{ +} + +UK2Node_VariableGet* UGAEffectGraphSchema::SpawnVariableGetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const +{ + return Super::SpawnVariableGetNode(GraphPosition, ParentGraph, VariableName, Source); +} + +UK2Node_VariableSet* UGAEffectGraphSchema::SpawnVariableSetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const +{ + return Super::SpawnVariableSetNode(GraphPosition, ParentGraph, VariableName, Source); +} diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraphSchema.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraphSchema.h new file mode 100644 index 0000000..d435fae --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/EffectEditor/GAEffectGraphSchema.h @@ -0,0 +1,38 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "EdGraphSchema_K2.h" +#include "GAEffectGraphSchema.generated.h" + +UCLASS(MinimalAPI) +class UGAEffectGraphSchema : public UEdGraphSchema_K2 +{ + GENERATED_UCLASS_BODY() + + /** + * Creates a new variable getter node and adds it to ParentGraph + * + * @param GraphPosition The location of the new node inside the graph + * @param ParentGraph The graph to spawn the new node in + * @param VariableName The name of the variable + * @param Source The source of the variable + * @return A pointer to the newly spawned node + */ + virtual class UK2Node_VariableGet* SpawnVariableGetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const override; + + /** + * Creates a new variable setter node and adds it to ParentGraph + * + * @param GraphPosition The location of the new node inside the graph + * @param ParentGraph The graph to spawn the new node in + * @param VariableName The name of the variable + * @param Source The source of the variable + * @return A pointer to the newly spawned node + */ + virtual class UK2Node_VariableSet* SpawnVariableSetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const override; + + virtual bool ShouldAlwaysPurgeOnModification() const override { return true; } +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributeDetailCustomization.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributeDetailCustomization.cpp new file mode 100644 index 0000000..81cbfa0 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributeDetailCustomization.cpp @@ -0,0 +1,90 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" + +#include "STextCombobox.h" +#include "STreeView.h" + +#include "SGAAttributeWidget.h" + +#include "GAAttributeDetailCustomization.h" + +TSharedRef FGAAttributeDetailCustomization::MakeInstance() +{ + return MakeShareable(new FGAAttributeDetailCustomization); +} + +FGAAttributeDetailCustomization::~FGAAttributeDetailCustomization() +{ + +} + +void FGAAttributeDetailCustomization::CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) +{ + SocketNameHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FGAAttribute, AttributeName)); + check(SocketNameHandle.IsValid()); + + HeaderRow + .NameContent() + [ + InStructPropertyHandle->CreatePropertyNameWidget() + ] + .ValueContent() + .MaxDesiredWidth(512) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .AutoWidth() + .VAlign(VAlign_Center) + [ + SNew(SComboButton) + .OnGetMenuContent(this, &FGAAttributeDetailCustomization::GetSocketTree) + .ContentPadding(FMargin(0.4)) + .ButtonContent() + [ + SNew(STextBlock) + .Margin(FMargin(0.6)) + .Text(this, &FGAAttributeDetailCustomization::GetAttributeName) + ] + ] + ]; +} +void FGAAttributeDetailCustomization::CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) +{ + +} + +FText FGAAttributeDetailCustomization::GetAttributeName() const +{ + FName attributeName; + if (SocketNameHandle.IsValid()) + { + SocketNameHandle->GetValue(attributeName); + return FText::FromName(attributeName); + } + return FText::FromName(attributeName); +} + +TSharedRef FGAAttributeDetailCustomization::GetSocketTree() +{ + return SNew(SVerticalBox) + + SVerticalBox::Slot() + .AutoHeight() + .MaxHeight(400) + [ + SNew(SGAAttributeWidget) + .OnAttributeSelectedIn(this, &FGAAttributeDetailCustomization::SetSocketName) + ]; +} + +void FGAAttributeDetailCustomization::SetSocketName(FString AttributeNameIn) +{ + FName name; + FName nameToSet = *AttributeNameIn; + SocketNameHandle->GetValue(name); + if (name != nameToSet) + { + SocketNameHandle->SetValue(nameToSet); + } +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributeDetailCustomization.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributeDetailCustomization.h new file mode 100644 index 0000000..7b28395 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributeDetailCustomization.h @@ -0,0 +1,33 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypesEditor.h" + +#include "IPropertyTypeCustomization.h" +#include "PropertyHandle.h" + +class FGAAttributeDetailCustomization : public IPropertyTypeCustomization +{ +public: + static TSharedRef MakeInstance(); + /** + * Destructor + */ + virtual ~FGAAttributeDetailCustomization(); + + /** IPropertyTypeCustomization interface */ + virtual void CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; + virtual void CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; + + +protected: + /** Cached Property Handle */ + TSharedPtr SocketNameHandle; + + /** Used with Combobox, show up socket tree widget. */ + TSharedRef GetSocketTree(); + + FText GetAttributeName() const; + + void SetSocketName(FString AttributeNameIn); +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePanelGraphPinFactory.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePanelGraphPinFactory.cpp new file mode 100644 index 0000000..347b0d0 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePanelGraphPinFactory.cpp @@ -0,0 +1,16 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" + + + +//TSharedPtr FGAAttributePanelGraphPinFactory::CreatePin(class UEdGraphPin* InPin) const +//{ +// const UEdGraphSchema_K2* K2Schema = GetDefault(); +// if (InPin->PinType.PinCategory == K2Schema->PC_Struct) +// //&& InPin->PinType.PinSubCategoryObject == FGAAttribute::StaticStruct()) +// { +// +// } +// return nullptr; +//} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePanelGraphPinFactory.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePanelGraphPinFactory.h new file mode 100644 index 0000000..047dc24 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePanelGraphPinFactory.h @@ -0,0 +1,23 @@ +#pragma once +#include "SlateBasics.h" +#include "Attributes/GAAttributeGlobals.h" +#include "EdGraph/EdGraphPin.h" +#include "EdGraph/EdGraphSchema.h" +#include "EdGraphSchema_K2.h" +#include "GAAttributePanelGraphPinFactory.h" +#include "GAAttributePin.h" +#include "EdGraphUtilities.h" + +class FGAAttributePanelGraphPinFactory : public FGraphPanelPinFactory +{ + virtual TSharedPtr CreatePin(class UEdGraphPin* InPin) const override + { + const UEdGraphSchema_K2* K2Schema = GetDefault(); + if (InPin->PinType.PinCategory == K2Schema->PC_Struct + && InPin->PinType.PinSubCategoryObject == FGAAttribute::StaticStruct()) + { + return SNew(SGAAttributePin, InPin); + } + return nullptr; + } +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePin.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePin.cpp new file mode 100644 index 0000000..51b9723 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePin.cpp @@ -0,0 +1,105 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" + +#include "KismetEditorUtilities.h" + +#include "STextComboBox.h" +#include "EdGraph/EdGraphPin.h" +#include "EdGraph/EdGraphSchema.h" + +#include "Effects/GAGameEffect.h" +#include "GAGlobalTypes.h" +#include "Attributes/GAAttributesBase.h" +#include "SGAAttributeWidget.h" +#include "GAAttributePin.h" + +void SGAAttributePin::Construct(const FArguments& InArgs, UEdGraphPin* InGraphPinObj) +{ + AttributesList.Empty(); + + SelectedAttribute = InGraphPinObj->GetDefaultAsString(); + SelectedAttribute.RemoveFromStart("(AttributeName=\""); + SelectedAttribute.RemoveFromEnd("\")"); + + for (TObjectIterator ClassIt; ClassIt; ++ClassIt) + { + UClass* Class = *ClassIt; + if (Class->IsChildOf(UGAAttributesBase::StaticClass()) + && !FKismetEditorUtilities::IsClassABlueprintSkeleton(Class)) + { + for (TFieldIterator PropertyIt(Class, EFieldIteratorFlags::ExcludeSuper); PropertyIt; ++PropertyIt) + { + UProperty* Prop = *PropertyIt; + //I need array within array, one for list of attributes, and one for class names. + TSharedPtr attribute = MakeShareable(new FString(Prop->GetName())); + AttributesList.Add(attribute); + } + } + } + SGraphPin::Construct(SGraphPin::FArguments(), InGraphPinObj); +} +TSharedRef SGAAttributePin::GetDefaultValueWidget() +{ + //AttributesList.Empty(); + return SNew(SVerticalBox) + + SVerticalBox::Slot() + .AutoHeight() + [ + SAssignNew(AttributeComboButton, SComboButton) + .OnGetMenuContent(this, &SGAAttributePin::GetAttributesMenu) + .ButtonContent() + [ + SNew(STextBlock) + .Text(this, &SGAAttributePin::GetSelectedAttributeText) + ] + ]; + //return SNew(STextComboBox) + // .OptionsSource(&AttributesList) + // .OnSelectionChanged(this, &SGAAttributePin::OnAttributeSelected); + //return AttributeComboButton.ToSharedRef(); + +} + +TSharedRef SGAAttributePin::GetAttributesMenu() +{ + return SNew(SVerticalBox) + + SVerticalBox::Slot() + .AutoHeight() + .MaxHeight(400) + [ + SNew(SGAAttributeWidget) + .OnAttributeSelectedIn(this, &SGAAttributePin::OnAttributeSelected) + ]; +} + +FText SGAAttributePin::GetSelectedAttributeText() const +{ + return FText::FromString(SelectedAttribute); +} +void SGAAttributePin::OnAttributeSelected(FString ItemSelected) +{ + SelectedAttribute = ItemSelected; + //FString CurrentValue = GraphPinObj->GetDefaultAsString(); + FString CurrentDefaultValue = GraphPinObj->GetDefaultAsString(); + FString attribute = ItemSelected; + if (CurrentDefaultValue.IsEmpty()) + { + CurrentDefaultValue = FString(TEXT("()")); + } + FString AttributeString = TEXT("("); + if (!attribute.IsEmpty()) + { + AttributeString += TEXT("AttributeName=\""); + AttributeString += attribute; + AttributeString += TEXT("\""); + } + AttributeString += TEXT(")"); + + if (!CurrentDefaultValue.Equals(AttributeString)) + { + GraphPinObj->GetSchema()->TrySetDefaultValue(*GraphPinObj, AttributeString); + } + + //if () +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePin.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePin.h new file mode 100644 index 0000000..74aeb68 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAAttributePin.h @@ -0,0 +1,27 @@ +#pragma once +#include "SlateBasics.h" +#include "SGraphPin.h" + +class SGAAttributePin : public SGraphPin +{ +public: + SLATE_BEGIN_ARGS(SGAAttributePin) {} + SLATE_END_ARGS() + +public: + void Construct(const FArguments& InArgs, UEdGraphPin* InGraphPinObj); + + virtual TSharedRef GetDefaultValueWidget() override; + void OnAttributeSelected(FString ItemSelected); +private: + TArray> AttributesList; + + TSharedPtr AttributeComboButton; + + TSharedRef GetAttributesMenu(); + + FText GetSelectedAttributeText() const; + + FString SelectedAttribute; + +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAbilityTaskCall.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAbilityTaskCall.cpp new file mode 100644 index 0000000..1784ae6 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAbilityTaskCall.cpp @@ -0,0 +1,79 @@ + +#include "AbilityFrameworkEditor.h" +#include "Kismet/KismetMathLibrary.h" +#include "Kismet/KismetArrayLibrary.h" +#include "GameplayTask.h" +#include "Abilities/Tasks/GAAbilityTask.h" +#include "Abilities/GAAbilityBase.h" +#include "KismetCompiler.h" +#include "BlueprintEditorUtils.h" +#include "GAEK2Node_LatentAbilityTaskCall.h" +#include "K2Node_EnumLiteral.h" +#include "BlueprintFunctionNodeSpawner.h" +#include "BlueprintActionDatabaseRegistrar.h" + +#define LOCTEXT_NAMESPACE "K2Node" + +UGAEK2Node_LatentAbilityTaskCall::UGAEK2Node_LatentAbilityTaskCall(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + ProxyActivateFunctionName = GET_FUNCTION_NAME_CHECKED(UAFTaskBase, ReadyForActivation); +} + +bool UGAEK2Node_LatentAbilityTaskCall::IsCompatibleWithGraph(UEdGraph const* TargetGraph) const +{ + bool bIsCompatible = false; + + EGraphType GraphType = TargetGraph->GetSchema()->GetGraphType(TargetGraph); + bool const bAllowLatentFuncs = (GraphType == GT_Ubergraph || GraphType == GT_Macro); + + if (bAllowLatentFuncs) + { + UBlueprint* MyBlueprint = FBlueprintEditorUtils::FindBlueprintForGraph(TargetGraph); + if (MyBlueprint && MyBlueprint->GeneratedClass) + { + if (MyBlueprint->GeneratedClass->IsChildOf(UGAAbilityBase::StaticClass())) + { + bIsCompatible = true; + } + } + } + return bIsCompatible; +} + + +void UGAEK2Node_LatentAbilityTaskCall::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const +{ + //UK2Node_BaseAsyncTask::GetMenuActions(ActionRegistrar); + struct GetMenuActions_Utils + { + static void SetNodeFunc(UEdGraphNode* NewNode, bool /*bIsTemplateNode*/, TWeakObjectPtr FunctionPtr) + { + UGAEK2Node_LatentAbilityTaskCall* AsyncTaskNode = CastChecked(NewNode); + if (FunctionPtr.IsValid()) + { + UFunction* Func = FunctionPtr.Get(); + UObjectProperty* ReturnProp = CastChecked(Func->GetReturnProperty()); + + AsyncTaskNode->ProxyFactoryFunctionName = Func->GetFName(); + AsyncTaskNode->ProxyFactoryClass = Func->GetOuterUClass(); + AsyncTaskNode->ProxyClass = ReturnProp->PropertyClass; + } + } + }; + + UClass* NodeClass = GetClass(); + //FBlueprintActionDatabaseRegistrar::FMakeFuncSpawnerDelegate::CreateUObject(this, &UGAEK2Node_LatentAbilityTaskCall::CreateNodeSpawner); + ActionRegistrar.RegisterClassFactoryActions(FBlueprintActionDatabaseRegistrar::FMakeFuncSpawnerDelegate::CreateLambda([NodeClass](const UFunction* FactoryFunc)->UBlueprintNodeSpawner* + { + UBlueprintNodeSpawner* NodeSpawner = UBlueprintFunctionNodeSpawner::Create(FactoryFunc); + check(NodeSpawner != nullptr); + NodeSpawner->NodeClass = NodeClass; + + TWeakObjectPtr FunctionPtr = const_cast(FactoryFunc); + NodeSpawner->CustomizeNodeDelegate = UBlueprintNodeSpawner::FCustomizeNodeDelegate::CreateStatic(GetMenuActions_Utils::SetNodeFunc, FunctionPtr); + return NodeSpawner; + })); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAbilityTaskCall.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAbilityTaskCall.h new file mode 100644 index 0000000..e81d718 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAbilityTaskCall.h @@ -0,0 +1,20 @@ + +#pragma once +#include "EdGraph/EdGraphPin.h" +#include "EdGraphSchema_K2.h" +#include "K2Node_BaseAsyncTask.h" +#include "GAEK2Node_LatentAbilityTaskCall.generated.h" + +UCLASS() +class UGAEK2Node_LatentAbilityTaskCall : public UK2Node_BaseAsyncTask//UK2Node_LatentGameplayTaskCall +{ + GENERATED_BODY() + +public: + UGAEK2Node_LatentAbilityTaskCall(const FObjectInitializer& ObjectInitializer); + + // UEdGraphNode interface + virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const override; + virtual bool IsCompatibleWithGraph(UEdGraph const* TargetGraph) const override; + // End of UEdGraphNode interface +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAction.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAction.cpp new file mode 100644 index 0000000..a5c474a --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAction.cpp @@ -0,0 +1,76 @@ + +#include "AbilityFrameworkEditor.h" +#include "Kismet/KismetMathLibrary.h" +#include "Kismet/KismetArrayLibrary.h" +#include "KismetCompiler.h" +#include "BlueprintEditorUtils.h" +#include "GAEK2Node_LatentAction.h" +#include "K2Node_EnumLiteral.h" +#include "BlueprintFunctionNodeSpawner.h" +#include "BlueprintActionDatabaseRegistrar.h" +#include "LatentActions/AFTaskBase.h" +#define LOCTEXT_NAMESPACE "K2Node" + +UGAEK2Node_LatentAction::UGAEK2Node_LatentAction(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + ProxyActivateFunctionName = GET_FUNCTION_NAME_CHECKED(UAFTaskBase, ReadyForActivation); +} + +bool UGAEK2Node_LatentAction::IsCompatibleWithGraph(UEdGraph const* TargetGraph) const +{ + bool bIsCompatible = true; + + //EGraphType GraphType = TargetGraph->GetSchema()->GetGraphType(TargetGraph); + //bool const bAllowLatentFuncs = (GraphType == GT_Ubergraph || GraphType == GT_Macro); + + //if (bAllowLatentFuncs) + //{ + // UBlueprint* MyBlueprint = FBlueprintEditorUtils::FindBlueprintForGraph(TargetGraph); + // if (MyBlueprint && MyBlueprint->GeneratedClass) + // { + // if (MyBlueprint->GeneratedClass->IsChildOf(UGAAbilityBase::StaticClass())) + // { + // bIsCompatible = true; + // } + // } + //} + return bIsCompatible; +} + + +void UGAEK2Node_LatentAction::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const +{ + //UK2Node_BaseAsyncTask::GetMenuActions(ActionRegistrar); + struct GetMenuActions_Utils + { + static void SetNodeFunc(UEdGraphNode* NewNode, bool /*bIsTemplateNode*/, TWeakObjectPtr FunctionPtr) + { + UGAEK2Node_LatentAction* AsyncTaskNode = CastChecked(NewNode); + if (FunctionPtr.IsValid()) + { + UFunction* Func = FunctionPtr.Get(); + UObjectProperty* ReturnProp = CastChecked(Func->GetReturnProperty()); + + AsyncTaskNode->ProxyFactoryFunctionName = Func->GetFName(); + AsyncTaskNode->ProxyFactoryClass = Func->GetOuterUClass(); + AsyncTaskNode->ProxyClass = ReturnProp->PropertyClass; + } + } + }; + + UClass* NodeClass = GetClass(); + //FBlueprintActionDatabaseRegistrar::FMakeFuncSpawnerDelegate::CreateUObject(this, &UGAEK2Node_LatentAbilityTaskCall::CreateNodeSpawner); + ActionRegistrar.RegisterClassFactoryActions(FBlueprintActionDatabaseRegistrar::FMakeFuncSpawnerDelegate::CreateLambda([NodeClass](const UFunction* FactoryFunc)->UBlueprintNodeSpawner* + { + UBlueprintNodeSpawner* NodeSpawner = UBlueprintFunctionNodeSpawner::Create(FactoryFunc); + check(NodeSpawner != nullptr); + NodeSpawner->NodeClass = NodeClass; + + TWeakObjectPtr FunctionPtr = const_cast(FactoryFunc); + NodeSpawner->CustomizeNodeDelegate = UBlueprintNodeSpawner::FCustomizeNodeDelegate::CreateStatic(GetMenuActions_Utils::SetNodeFunc, FunctionPtr); + return NodeSpawner; + })); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAction.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAction.h new file mode 100644 index 0000000..5e88133 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEK2Node_LatentAction.h @@ -0,0 +1,19 @@ + +#pragma once +#include "EdGraph/EdGraphPin.h" +#include "EdGraphSchema_K2.h" +#include "K2Node_BaseAsyncTask.h" +#include "GAEK2Node_LatentAction.generated.h" + +UCLASS() +class UGAEK2Node_LatentAction : public UK2Node_BaseAsyncTask +{ + GENERATED_BODY() + +public: + UGAEK2Node_LatentAction(const FObjectInitializer& ObjectInitializer); + + // UEdGraphNode interface + virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const override; + virtual bool IsCompatibleWithGraph(UEdGraph const* TargetGraph) const override; +}; diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectClassStructWidget.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectClassStructWidget.cpp new file mode 100644 index 0000000..2eedb36 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectClassStructWidget.cpp @@ -0,0 +1,856 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "IDetailsView.h" +#include "PropertyEditorModule.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" +#include "Editor/PropertyEditor/Private/IDetailsViewPrivate.h" +#include "Editor/PropertyEditor/Private/SDetailsViewBase.h" +#include "Editor/PropertyEditor/Private/SDetailsView.h" + +#include "STextCombobox.h" +#include "STreeView.h" +#include "SButton.h" +#include "STextBlock.h" + +#include "ClassViewerModule.h" +#include "ClassViewerFilter.h" + +#include "EditorClassUtils.h" +#include "IAssetTools.h" +#include "AssetRegistryModule.h" +#include "Dialogs/DlgPickAssetPath.h" +#include "AssetToolsModule.h" +#include "KismetCompilerModule.h" +#include "Kismet2/KismetEditorUtilities.h" +#include "Kismet2/CompilerResultsLog.h" +#include "EffectEditor/GAEffectEditor.h" +#include "SMyBlueprint.h" +#include "SKismetInspector.h" + +#include "SGAAttributeWidget.h" +#include "Effects/GAGameEffect.h" +#include "Effects/GAEffectBlueprint.h" +#include "EffectEditor/GAEffectBlueprintFactory.h" +#include "GAEffectClassStructWidget.h" +#include "GAEffectDetails.h" +#include "AFAbilityActionSpecDetails.h" +#include "AFAbilityPeriodSpecDetails.h" +#include "AFAbilityCooldownSpecDetails.h" +#include "Abilities/AFAbilityActivationSpec.h" +#include "Abilities/AFAbilityPeriodSpec.h" +#include "Abilities/AFAbilityCooldownSpec.h" + +class SEffectCreateDialog : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SEffectCreateDialog) {} + SLATE_ARGUMENT(TSet, MetaClass); + SLATE_END_ARGS() + + /** Constructs this widget with InArgs */ + void Construct(const FArguments& InArgs) + { + bOkClicked = false; + ParentClass = UGAGameEffectSpec::StaticClass(); + MetaClass = InArgs._MetaClass; + ChildSlot + [ + SNew(SBorder) + .Visibility(EVisibility::Visible) + .BorderImage(FEditorStyle::GetBrush("Menu.Background")) + [ + SNew(SBox) + .Visibility(EVisibility::Visible) + .WidthOverride(500.0f) + [ + SNew(SVerticalBox) + + SVerticalBox::Slot() + .FillHeight(1) + [ + SNew(SBorder) + .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) + .Content() + [ + SAssignNew(ParentClassContainer, SVerticalBox) + ] + ] + + // Ok/Cancel buttons + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(HAlign_Right) + .VAlign(VAlign_Bottom) + .Padding(8) + [ + SNew(SUniformGridPanel) + .SlotPadding(FEditorStyle::GetMargin("StandardDialog.SlotPadding")) + .MinDesiredSlotWidth(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotWidth")) + .MinDesiredSlotHeight(FEditorStyle::GetFloat("StandardDialog.MinDesiredSlotHeight")) + + SUniformGridPanel::Slot(0, 0) + [ + SNew(SButton) + .HAlign(HAlign_Center) + .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + .OnClicked(this, &SEffectCreateDialog::OkClicked) + .Text(FText::FromString("OK")) + ] + + SUniformGridPanel::Slot(1, 0) + [ + SNew(SButton) + .HAlign(HAlign_Center) + .ContentPadding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + .OnClicked(this, &SEffectCreateDialog::CancelClicked) + .Text(FText::FromString("Cancel")) + ] + ] + ] + ] + ]; + + MakeParentClassPicker(); + } + + /** Sets properties for the supplied GameplayAbilitiesBlueprintFactory */ + bool ConfigureProperties(FGAEffectClassStructWidget* InGameplayAbilitiesBlueprintFactory) + { + GameplayAbilitiesBlueprintFactory = InGameplayAbilitiesBlueprintFactory; + + TSharedRef Window = SNew(SWindow) + .Title(FText::FromString("Create Game Effect Blueprint")) + .ClientSize(FVector2D(400, 700)) + .SupportsMinimize(false).SupportsMaximize(false) + [ + AsShared() + ]; + + PickerWindow = Window; + + GEditor->EditorAddModalWindow(Window); + GameplayAbilitiesBlueprintFactory = nullptr; + + return bOkClicked; + } + +private: + class FGameplayAbilityBlueprintParentFilter : public IClassViewerFilter + { + public: + /** All children of these classes will be included unless filtered out by another setting. */ + TSet< const UClass* > AllowedChildrenOfClasses; + + FGameplayAbilityBlueprintParentFilter() {} + + virtual bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InClass) != EFilterReturn::Failed; + } + + virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef< const IUnloadedBlueprintData > InUnloadedClassData, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InUnloadedClassData) != EFilterReturn::Failed; + } + }; + + /** Creates the combo menu for the parent class */ + void MakeParentClassPicker() + { + // Load the classviewer module to display a class picker + FClassViewerModule& ClassViewerModule = FModuleManager::LoadModuleChecked("ClassViewer"); + + // Fill in options + FClassViewerInitializationOptions Options; + Options.Mode = EClassViewerMode::ClassPicker; + Options.bShowDisplayNames = true; + // Only allow parenting to base blueprints. + Options.bIsBlueprintBaseOnly = true; + + TSharedPtr Filter = MakeShareable(new FGameplayAbilityBlueprintParentFilter); + + // All child child classes of UGameplayAbility are valid. + Filter->AllowedChildrenOfClasses = MetaClass; + Options.ClassFilter = Filter; + + ParentClassContainer->ClearChildren(); + ParentClassContainer->AddSlot() + .AutoHeight() + [ + SNew(STextBlock) + .Text(FText::FromString("Parent Class:")) + .ShadowOffset(FVector2D(1.0f, 1.0f)) + ]; + + ParentClassContainer->AddSlot() + [ + ClassViewerModule.CreateClassViewer(Options, FOnClassPicked::CreateSP(this, &SEffectCreateDialog::OnClassPicked)) + ]; + } + + /** Handler for when a parent class is selected */ + void OnClassPicked(UClass* ChosenClass) + { + ParentClass = ChosenClass; + } + + /** Handler for when ok is clicked */ + FReply OkClicked() + { + if (GameplayAbilitiesBlueprintFactory) + { + GameplayAbilitiesBlueprintFactory->ParentClass = ParentClass.Get(); + } + + CloseDialog(true); + + return FReply::Handled(); + } + + void CloseDialog(bool bWasPicked = false) + { + bOkClicked = bWasPicked; + if (PickerWindow.IsValid()) + { + PickerWindow.Pin()->RequestDestroyWindow(); + } + } + + /** Handler for when cancel is clicked */ + FReply CancelClicked() + { + CloseDialog(); + return FReply::Handled(); + } + + FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) + { + if (InKeyEvent.GetKey() == EKeys::Escape) + { + CloseDialog(); + return FReply::Handled(); + } + return SWidget::OnKeyDown(MyGeometry, InKeyEvent); + } + +private: + /** The factory for which we are setting up properties */ + FGAEffectClassStructWidget* GameplayAbilitiesBlueprintFactory; + + /** A pointer to the window that is asking the user to select a parent class */ + TWeakPtr PickerWindow; + + /** The container for the Parent Class picker */ + TSharedPtr ParentClassContainer; + + /** The selected class */ + TWeakObjectPtr ParentClass; + + TSet MetaClass; + + /** True if Ok was clicked */ + bool bOkClicked; +}; +class FPropertyEditorClassFilter : public IClassViewerFilter +{ +public: + /** The meta class for the property that classes must be a child-of. */ + const UClass* ClassPropertyMetaClass; + + /** The interface that must be implemented. */ + const UClass* InterfaceThatMustBeImplemented; + + /** Whether or not abstract classes are allowed. */ + bool bAllowAbstract; + + bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + bool bMatchesFlags = !InClass->HasAnyClassFlags(CLASS_Hidden | CLASS_HideDropDown | CLASS_Deprecated) && + (bAllowAbstract || !InClass->HasAnyClassFlags(CLASS_Abstract)); + + if (bMatchesFlags && InClass->IsChildOf(ClassPropertyMetaClass) + && (!InterfaceThatMustBeImplemented || InClass->ImplementsInterface(InterfaceThatMustBeImplemented))) + { + return true; + } + + return false; + } + + virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef< const IUnloadedBlueprintData > InClass, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + bool bMatchesFlags = !InClass->HasAnyClassFlags(CLASS_Hidden | CLASS_HideDropDown | CLASS_Deprecated) && + (bAllowAbstract || !InClass->HasAnyClassFlags(CLASS_Abstract)); + + if (bMatchesFlags && InClass->IsChildOf(ClassPropertyMetaClass) + && (!InterfaceThatMustBeImplemented || InClass->ImplementsInterface(InterfaceThatMustBeImplemented))) + { + return true; + } + + return false; + } +}; + +FGAEffectClassStructWidget::~FGAEffectClassStructWidget() +{ + +} + +TSharedRef FGAEffectClassStructWidget::CreateEffectClassWidget(UObject* OwnerObject) +{ + OuterObject = OwnerObject; + //TAttribute EffectName;// (); + //EffectName.Create(TAttribute::FGetter::CreateRaw(this, &FGAEffectClassStructWidget::GetClassName)); + return SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .AutoWidth() + [ + SAssignNew(ComboButton, SComboButton) + .OnGetMenuContent(this, &FGAEffectClassStructWidget::GenerateClassPicker) + .ContentPadding(FMargin(2.0f, 2.0f)) + .ToolTipText(this, &FGAEffectClassStructWidget::GetDisplayValueAsString) + .ButtonContent() + [ + SNew(STextBlock) + .Text(this, &FGAEffectClassStructWidget::GetDisplayValueAsString) + //.Font(InArgs._Font) + ] + ] + +SHorizontalBox::Slot() + .AutoWidth() + [ + MakeNewBlueprintButton() + ] + +SHorizontalBox::Slot() + .AutoWidth() + [ + SNew(SButton) + .OnClicked(this, &FGAEffectClassStructWidget::OnEditButtonClicked) + [ + SNew(STextBlock) + .Text(FText::FromString("Edit")) + ] + ]; +} + +FText FGAEffectClassStructWidget::GetClassName() const +{ + if (StructPropertyHandle.IsValid()) + { + return StructPropertyHandle->GetPropertyDisplayName(); + } + return FText::FromString("No Effect Selected"); +} +static FString GetClassDisplayName(const UObject* Object) +{ + const UClass* Class = Cast(Object); + if (Class != NULL) + { + UBlueprint* BP = UBlueprint::GetBlueprintFromClass(Class); + if (BP != NULL) + { + return BP->GetName(); + } + } + return (Object) ? Object->GetName() : "None"; +} +FText FGAEffectClassStructWidget::GetDisplayValueAsString() const +{ + static bool bIsReentrant = false; + + // Guard against re-entrancy which can happen if the delegate executed below (SelectedClass.Get()) forces a slow task dialog to open, thus causing this to lose context and regain focus later starting the loop over again + if (!bIsReentrant) + { + TGuardValue(bIsReentrant, true); + if (EffectPropertyHandle.IsValid()) + { + UObject* ObjectValue = NULL; + FPropertyAccess::Result Result = EffectPropertyHandle->GetValue(ObjectValue); + + if (Result == FPropertyAccess::Success && ObjectValue != NULL) + { + return FText::FromString(GetClassDisplayName(ObjectValue)); + } + + return FText::FromString("None"); + } + + return FText::FromString("None"); + } + else + { + return FText::FromString("None"); + } + +} +UClass* FGAEffectClassStructWidget::GetClassFromString(const FString& ClassName) +{ + if (ClassName.IsEmpty() || ClassName == "None") + { + return nullptr; + } + + UClass* Class = FindObject(ANY_PACKAGE, *ClassName); + if (!Class) + { + Class = LoadObject(nullptr, *ClassName); + } + return Class; +} +TSharedRef FGAEffectClassStructWidget::GenerateClassPicker() +{ + FClassViewerInitializationOptions Options; + Options.bShowUnloadedBlueprints = true; + Options.bShowNoneOption = true; + + if (EffectPropertyHandle.IsValid()) + { + Options.PropertyHandle = EffectPropertyHandle; + } + + + class FGameplayAbilityBlueprintParentFilter : public IClassViewerFilter + { + public: + /** All children of these classes will be included unless filtered out by another setting. */ + TSet< const UClass* > AllowedChildrenOfClasses; + bool bAllowAbstract; + FGameplayAbilityBlueprintParentFilter() {} + + virtual bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + if (!bAllowAbstract) + { + return !InClass->HasAnyClassFlags(CLASS_Abstract) && InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InClass) != EFilterReturn::Failed; + } + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InClass) != EFilterReturn::Failed; + } + + virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef< const IUnloadedBlueprintData > InUnloadedClassData, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs) override + { + // If it appears on the allowed child-of classes list (or there is nothing on that list) + return InFilterFuncs->IfInChildOfClassesSet(AllowedChildrenOfClasses, InUnloadedClassData) != EFilterReturn::Failed; + } + }; + TSharedPtr ClassFilter = MakeShareable(new FGameplayAbilityBlueprintParentFilter); + + TSet MetaClass; + TSharedPtr EffectPropertyHandleLocal = StructPropertyHandle->GetParentHandle(); + if (EffectPropertyHandleLocal.IsValid()) + { + FString ClassName = EffectPropertyHandleLocal->GetMetaData("AllowedClass"); + TArray ClassNames; + //ClassName.Pars + ClassName.ParseIntoArray(ClassNames, TEXT(",")); + if (ClassNames.Num() > 0) + { + for (const FString& name : ClassNames) + { + UClass* temp = GetClassFromString(name); + if (temp) + { + MetaClass.Add(temp); + } + } + } + else + { + MetaClass.Add(UGAGameEffectSpec::StaticClass()); + } + } + ClassFilter->AllowedChildrenOfClasses = MetaClass; + Options.ClassFilter = ClassFilter; + //ClassFilter->ClassPropertyMetaClass = MetaClass; + //ClassFilter->InterfaceThatMustBeImplemented = nullptr;// UInterface::StaticClass(); + ClassFilter->bAllowAbstract = false; + Options.bIsBlueprintBaseOnly = true; + Options.bIsPlaceableOnly = false; + Options.DisplayMode = EClassViewerDisplayMode::TreeView;// : EClassViewerDisplayMode::ListView; + Options.bAllowViewOptions = true; + Options.bShowDisplayNames = true; + + FOnClassPicked OnPicked(FOnClassPicked::CreateRaw(this, &FGAEffectClassStructWidget::OnClassPicked)); + + return SNew(SBox) + .WidthOverride(280) + [ + SNew(SVerticalBox) + + SVerticalBox::Slot() + .AutoHeight() + .MaxHeight(500) + [ + FModuleManager::LoadModuleChecked("ClassViewer").CreateClassViewer(Options, OnPicked) + ] + ]; +} + +void FGAEffectClassStructWidget::OnClassPicked(UClass* InClass) +{ + if (!InClass) + { + SendToObjects(TEXT("None")); + } + else + { + SendToObjects(InClass->GetPathName()); + } + + ComboButton->SetIsOpen(false); +} + +void FGAEffectClassStructWidget::SendToObjects(const FString& NewValue) +{ + if (EffectPropertyHandle.IsValid()) + { + EffectPropertyHandle->SetValueFromFormattedString(NewValue); + } + else + { + UClass* NewClass = FindObject(ANY_PACKAGE, *NewValue); + if (!NewClass) + { + NewClass = LoadObject(nullptr, *NewValue); + } + //OnSetClass.Execute(NewClass); + } +} + +TSharedRef FGAEffectClassStructWidget::MakeNewBlueprintButton() +{ + return + SNew(SButton) + .Text(FText::FromString("New Blueprint")) + //.ToolTipText(OptionalToolTipText.Get().IsEmpty() ? LOCTEXT("NewBlueprintButtonToolTipText", "Create New Blueprint") : OptionalToolTipText) + .OnClicked(this, &FGAEffectClassStructWidget::MakeNewBlueprint) + .IsEnabled(true) + .IsFocusable(false) + .ButtonColorAndOpacity(FSlateColor::UseForeground()) + [ + SNew(SImage) + .Image(FEditorStyle::GetBrush("PropertyWindow.Button_CreateNewBlueprint")) + ]; +} + +FReply FGAEffectClassStructWidget::MakeNewBlueprint() +{ + TSet MetaClass; + TSharedPtr EffectPropertyHandleLocal = StructPropertyHandle->GetParentHandle(); + FString ClassName = EffectPropertyHandleLocal->GetMetaData("AllowedClass"); + TArray ClassNames; + //ClassName.Pars + ClassName.ParseIntoArray(ClassNames, TEXT(",")); + if (ClassNames.Num() > 0) + { + for (const FString& name : ClassNames) + { + UClass* temp = GetClassFromString(name); + if (temp) + { + MetaClass.Add(temp); + } + } + } + else + { + MetaClass.Add(UAFEffectSpecBase::StaticClass()); + } + TSharedRef Dialog = SNew(SEffectCreateDialog).MetaClass(MetaClass); + Dialog->ConfigureProperties(this); + if (ParentClass) + { + check(FKismetEditorUtilities::CanCreateBlueprintOfClass(UGAGameEffectSpec::StaticClass())); + + // Pre-generate a unique asset name to fill out the path picker dialog with. + FString OuterName; + FString OuterName2; + + if (StructPropertyHandle.IsValid()) + { + UProperty* prop = StructPropertyHandle->GetProperty(); + OuterName = prop->GetOuter()->GetName(); + OuterName = prop->GetPathName(); + OuterName = StructPropertyHandle->GeneratePathToProperty(); + } + + + UPackage* OuterMost = OuterObject->GetOutermost(); + FString AssetName = OuterObject->GetName(); + FString Path = OuterMost->GetFullName(); + FJsonSerializableArray OutArray; + Path = Path.RightChop(7); + Path.ParseIntoArrayWS(OutArray, TEXT("/")); + FString OutAsset = OutArray[OutArray.Num() - 1]; + OutArray.RemoveAt(OutArray.Num() - 1); + // OutArray.RemoveAt(0); + FString OutPath = "/"; + for (const FString& str : OutArray) + { + OutPath += str; + OutPath += "/"; + } + OutPath += FString::Printf(TEXT("E_%s_"), *OutAsset); + + FString NewNameSuggestion = "";// FString::Printf(TEXT("E_%s_"), *OutAsset); + UClass* BlueprintClass = UGAGameEffectSpec::StaticClass(); + UClass* BlueprintGeneratedClass = UGAEffectBlueprint::StaticClass(); + + IKismetCompilerInterface& KismetCompilerModule = FModuleManager::LoadModuleChecked("KismetCompiler"); + KismetCompilerModule.GetBlueprintTypesForClass(UGAGameEffectSpec::StaticClass(), BlueprintClass, BlueprintGeneratedClass); + + FString PackageName = OutPath + NewNameSuggestion; + FString OutPackageName; + FString Name; + FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked("AssetTools"); + AssetToolsModule.Get().CreateUniqueAssetName(PackageName, NewNameSuggestion, OutPackageName, Name); + + + + TSharedPtr PickAssetPathWidget = + SNew(SDlgPickAssetPath) + .Title(FText::FromString("Create New Effect")) + .DefaultAssetPath(FText::FromString(OutPath)); + UBlueprint* Blueprint = nullptr; + if (EAppReturnType::Ok == PickAssetPathWidget->ShowModal()) + { + // Get the full name of where we want to create the physics asset. + FString UserPackageName = PickAssetPathWidget->GetFullAssetPath().ToString(); + FName BPName(*FPackageName::GetLongPackageAssetName(UserPackageName)); + + // Check if the user inputed a valid asset name, if they did not, give it the generated default name + if (BPName == NAME_None) + { + // Use the defaults that were already generated. + UserPackageName = PackageName; + BPName = *Name; + } + + // Then find/create it. + UPackage* Package = CreatePackage(NULL, *UserPackageName); + check(Package); + + // Create and init a new Blueprint + Blueprint = FKismetEditorUtilities::CreateBlueprint(ParentClass, Package, BPName, BPTYPE_Normal, UGAEffectBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass(), FName("LevelEditorActions")); + if (Blueprint) + { + // Notify the asset registry + FAssetRegistryModule::AssetCreated(Blueprint); + + // Mark the package dirty... + Package->MarkPackageDirty(); + } + } + if (Blueprint != NULL && Blueprint->GeneratedClass ) + { + UGAEffectBlueprint* eff = Cast(Blueprint); + if (eff) + { + EffectPropertyHandle->SetValueFromFormattedString(eff->GeneratedClass->GetPathName()); + + FAssetEditorManager::Get().OpenEditorForAsset(eff); + return FReply::Handled(); + } + } + } + return FReply::Unhandled(); +} + +FReply FGAEffectClassStructWidget::OnEditButtonClicked() +{ + if (EffectEditorWindow.IsValid()) + { + //EffectEditorWindow->RequestDestroyWindow(); + EffectEditorWindow->DestroyWindowImmediately(); + EffectEditorWindow.Reset(); + // already open, just show it + //EffectEditorWindow->BringToFront(true); + } + + { + UObject* OutVal = nullptr; + UGAEffectBlueprint* Blueprint = nullptr; + UProperty* Prop; + UBlueprintGeneratedClass* Class = nullptr; + if (EffectPropertyHandle.IsValid()) + { + EffectPropertyHandle->GetValue(OutVal); + EffectPropertyHandle->CreatePropertyValueWidget(); + Prop = EffectPropertyHandle->GetProperty(); + + if (OutVal) + { + Class = Cast(OutVal); + if (Class && Class->ClassGeneratedBy && Class->ClassGeneratedBy->IsA(UGAEffectBlueprint::StaticClass())) + { + Blueprint = Cast(Class->ClassGeneratedBy); + } + } + } + + FDetailsViewArgs Args; + Args.bHideSelectionTip = true; + Args.bLockable = false; + FPropertyEditorModule& PropertyEditorModule = FModuleManager::GetModuleChecked("PropertyEditor"); + TSharedRef DetailView = PropertyEditorModule.CreateDetailView(Args); + TArray InObjects; + if (Blueprint) + { + EditedBlueprint = Blueprint; + if (Blueprint->ParentClass && Blueprint->ParentClass->IsChildOf(UAFAbilityActivationSpec::StaticClass())) + { + DetailView->RegisterInstancedCustomPropertyLayout(UAFAbilityActivationSpec::StaticClass(), FOnGetDetailCustomizationInstance::CreateStatic(&FAFAbilityActivationSpecDetails::MakeInstance)); + } + else if (Blueprint->ParentClass && Blueprint->ParentClass->IsChildOf(UAFAbilityPeriodSpec::StaticClass())) + { + DetailView->RegisterInstancedCustomPropertyLayout(UAFAbilityPeriodSpec::StaticClass(), FOnGetDetailCustomizationInstance::CreateStatic(&FAFAbilityPeriodSpecDetails::MakeInstance)); + } + else if (Blueprint->ParentClass && Blueprint->ParentClass->IsChildOf(UAFAbilityCooldownSpec::StaticClass())) + { + DetailView->RegisterInstancedCustomPropertyLayout(UAFAbilityCooldownSpec::StaticClass(), FOnGetDetailCustomizationInstance::CreateStatic(&FAFAbilityCooldownSpecDetails::MakeInstance)); + } + else if (Blueprint->ParentClass && Blueprint->ParentClass->IsChildOf(UGAGameEffectSpec::StaticClass())) + { + // DetailView->UnregisterInstancedCustomPropertyLayout(UGAGameEffectSpec::StaticClass()); + // DetailView->RegisterInstancedCustomPropertyLayout(UGAGameEffectSpec::StaticClass(), FOnGetDetailCustomizationInstance::CreateStatic(&FGAEffectDetails::MakeInstance)); + } + } + if(!Class) + { + return FReply::Unhandled(); + } + if (!Class->ClassDefaultObject) + { + return FReply::Unhandled(); + } + //DetailView->RegisterInstancedCustomPropertyLayout(UGAGameEffectSpec::StaticClass(), FOnGetDetailCustomizationInstance::CreateStatic(&FGAEffectDetails::MakeInstance)); + InObjects.Add(Class->ClassDefaultObject); + DetailView->SetObjects(InObjects); + FString WindowTitle = "Effect Editor: "; + WindowTitle += Blueprint->GetName(); + EffectEditorWindow = SNew(SWindow) + .Title(FText::FromString(WindowTitle)) + .HasCloseButton(true) + .ClientSize(FVector2D(600, 400)); + EffectEditorWindow->SetContent( + SNew(SBorder) + .BorderImage(FEditorStyle::GetBrush(TEXT("PropertyWindow.WindowBorder"))) + [ + SNew(SVerticalBox) + +SVerticalBox::Slot() + .AutoHeight() + .MaxHeight(24.0f) + [ + SNew(SHorizontalBox) + +SHorizontalBox::Slot() + [ + SNew(SButton) + .OnClicked(this, &FGAEffectClassStructWidget::OnSaveButtonClicked) + [ + SNew(STextBlock) + .Text(FText::FromString("Save")) + ] + ] + + SHorizontalBox::Slot() + [ + SNew(SButton) + .OnClicked(this, &FGAEffectClassStructWidget::OnSaveCloseButtonClicked) + [ + SNew(STextBlock) + .Text(FText::FromString("Save/Close")) + ] + ] + + SHorizontalBox::Slot() + [ + SNew(SButton) + .OnClicked(this, &FGAEffectClassStructWidget::OnCloseButtonClicked) + .IsEnabled(true) + .IsFocusable(false) + [ + SNew(STextBlock) + .Text(FText::FromString("Close")) + ] + ] + ] + +SVerticalBox::Slot() + .FillHeight(1) + [ + DetailView + ] + ] + ); + + if (FGlobalTabmanager::Get()->GetRootWindow().IsValid()) + { + FSlateApplication::Get().AddWindowAsNativeChild(EffectEditorWindow.ToSharedRef(), FGlobalTabmanager::Get()->GetRootWindow().ToSharedRef()); + } + else + { + FSlateApplication::Get().AddWindow(EffectEditorWindow.ToSharedRef()); + } + } + + return FReply::Handled(); +} +FReply FGAEffectClassStructWidget::OnSaveButtonClicked() +{ + if (EditedBlueprint) + { + FCompilerResultsLog LogResults; + LogResults.BeginEvent(TEXT("Compile")); + LogResults.bLogDetailedResults = false; + LogResults.EventDisplayThresholdMs = 0.1; + EBlueprintCompileOptions CompileOptions = EBlueprintCompileOptions::None; + CompileOptions |= EBlueprintCompileOptions::SaveIntermediateProducts; + + FKismetEditorUtilities::CompileBlueprint(EditedBlueprint, CompileOptions, &LogResults); + TArray PackagesToSave; + check((EditedBlueprint != nullptr) && EditedBlueprint->IsAsset()); + PackagesToSave.Add(EditedBlueprint->GetOutermost()); + + FEditorFileUtils::PromptForCheckoutAndSave(PackagesToSave, true, /*bPromptToSave=*/ false); + //EditedBlueprint = nullptr; + } + return FReply::Unhandled(); +} +FReply FGAEffectClassStructWidget::OnSaveCloseButtonClicked() +{ + if (EditedBlueprint) + { + FCompilerResultsLog LogResults; + LogResults.BeginEvent(TEXT("Compile")); + LogResults.bLogDetailedResults = false; + LogResults.EventDisplayThresholdMs = 0.1; + EBlueprintCompileOptions CompileOptions = EBlueprintCompileOptions::None; + CompileOptions |= EBlueprintCompileOptions::SaveIntermediateProducts; + + FKismetEditorUtilities::CompileBlueprint(EditedBlueprint, CompileOptions, &LogResults); + TArray PackagesToSave; + check((EditedBlueprint != nullptr) && EditedBlueprint->IsAsset()); + PackagesToSave.Add(EditedBlueprint->GetOutermost()); + + FEditorFileUtils::PromptForCheckoutAndSave(PackagesToSave, true, /*bPromptToSave=*/ false); + + EditedBlueprint = nullptr; + + if (EffectEditorWindow.IsValid()) + { + EffectEditorWindow->RequestDestroyWindow(); + EffectEditorWindow = nullptr; + + return FReply::Handled(); + } + } + + return FReply::Unhandled(); +} +FReply FGAEffectClassStructWidget::OnCloseButtonClicked() +{ + if (EffectEditorWindow.IsValid()) + { + EffectEditorWindow->RequestDestroyWindow(); + EffectEditorWindow = nullptr; + return FReply::Handled(); + } + return FReply::Unhandled(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectClassStructWidget.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectClassStructWidget.h new file mode 100644 index 0000000..f7e557f --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectClassStructWidget.h @@ -0,0 +1,58 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypesEditor.h" + +#include "IPropertyTypeCustomization.h" +#include "PropertyHandle.h" + +class FGAEffectClassStructWidget : public TSharedFromThis +{ +protected: + /* Handle to FGAEffectClass*/ + TSharedPtr StructPropertyHandle; + + /* Handle to TSubclassOf SpecClass */ + TSharedPtr EffectPropertyHandle; + + TSharedPtr ComboButton; + + TSharedPtr EffectEditorWindow; + UBlueprint* EditedBlueprint; + UObject* OuterObject; +public: + FGAEffectClassStructWidget() {}; + FGAEffectClassStructWidget(TSharedPtr InStructPropertyHandle, + TSharedPtr InEffectPropertyHandle) + : StructPropertyHandle(InStructPropertyHandle), + EffectPropertyHandle(InEffectPropertyHandle) + {}; + + TSubclassOf ParentClass; + TSharedRef CreateEffectClassWidget(UObject* OwnerObject); + void SetHandles(TSharedPtr InStructPropertyHandle, + TSharedPtr InEffectPropertyHandle) + { + StructPropertyHandle = InStructPropertyHandle; + EffectPropertyHandle = InEffectPropertyHandle; + } + + /** + * Destructor + */ + virtual ~FGAEffectClassStructWidget(); + + FText GetClassName() const; + FText GetDisplayValueAsString() const; + UClass* GetClassFromString(const FString& ClassName); + TSharedRef GenerateClassPicker(); + void OnClassPicked(UClass* InClass); + void SendToObjects(const FString& NewValue); + //FReply OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent); + TSharedRef MakeNewBlueprintButton(); + FReply MakeNewBlueprint(); + FReply OnEditButtonClicked(); + FReply OnSaveButtonClicked(); + FReply OnSaveCloseButtonClicked(); + FReply OnCloseButtonClicked(); +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectDetails.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectDetails.cpp new file mode 100644 index 0000000..b96e65c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectDetails.cpp @@ -0,0 +1,112 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" + +#include "STextCombobox.h" +#include "STreeView.h" + +#include "Effects/GAGameEffect.h" +#include "GAEffectDetails.h" +#include "Effects/AFEffectCustomApplication.h" +#include "AFEffectCustomizationCommon.h" +#include "Abilities/AFAbilityActivationSpec.h" +#include "Abilities/AFAbilityPeriodSpec.h" +#include "Abilities/AFAbilityCooldownSpec.h" +TSharedRef FGAEffectDetails::MakeInstance() +{ + return MakeShareable(new FGAEffectDetails); +} + +void FGAEffectDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) +{ + MyDetailLayout = &DetailLayout; + + TArray> Objects; + DetailLayout.GetObjectsBeingCustomized(Objects); + + ApplicationTypeHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Application), UGAGameEffectSpec::StaticClass()); + UpdateEffectTypeyDelegate = FSimpleDelegate::CreateSP(this, &FGAEffectDetails::OnDurationPolicyChange); + ApplicationTypeHandle->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + + DurationHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Duration), UGAGameEffectSpec::StaticClass()); + PeriodHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, Period), UGAGameEffectSpec::StaticClass()); + DurationHandle->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + PeriodHandle->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + + DurationCalcTypeHandle = DurationHandle->GetChildHandle("CalculationType"); + PeriodCalcTypeHandle = PeriodHandle->GetChildHandle("CalculationType"); + + DurationCalcTypeHandle->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + PeriodCalcTypeHandle->SetOnPropertyValueChanged(UpdateEffectTypeyDelegate); + + for (TWeakObjectPtr obj : Objects) + { + if (UAFEffectSpecBase* Spec = Cast(obj.Get())) + { + /*if (!Spec->IsA(UAFAbilityActivationSpec::StaticClass()) + && !Spec->IsA(UAFAbilityPeriodSpec::StaticClass()) + && !Spec->IsA(UAFAbilityCooldownSpec::StaticClass()) + )*/ + { + bIsDuration = Spec->Application.GetDefaultObject()->ShowDuration(); + bIsPeriodic = Spec->Application.GetDefaultObject()->ShowPeriod(); + + if (bIsPeriodic && bIsDuration) + { + DetailLayout.HideProperty(PeriodHandle); + DetailLayout.HideProperty(DurationHandle); + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, DurationHandle, "Duration"); + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, PeriodHandle, "Period"); + } + else if (!bIsPeriodic && bIsDuration) + { + TSharedPtr MaxStacksProp = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, MaxStacks), UGAGameEffectSpec::StaticClass()); + TSharedPtr MaxStackedDurationHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, MaxStackedDuration), UGAGameEffectSpec::StaticClass()); + + DetailLayout.HideProperty(MaxStacksProp); + DetailLayout.HideProperty(PeriodHandle); + DetailLayout.HideProperty(DurationHandle); + DetailLayout.HideProperty(MaxStackedDurationHandle); + + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, DurationHandle, "Duration"); + } + else if (bIsPeriodic && !bIsDuration) + { + TSharedPtr MaxStacksProp = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, MaxStacks), UGAGameEffectSpec::StaticClass()); + TSharedPtr MaxStackedDurationHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, MaxStackedDuration), UGAGameEffectSpec::StaticClass()); + + DetailLayout.HideProperty(MaxStacksProp); + DetailLayout.HideProperty(DurationHandle); + DetailLayout.HideProperty(PeriodHandle); + DetailLayout.HideProperty(MaxStackedDurationHandle); + + FAFEffectCustomizationCommon::CreateMagnitudeLayout(DetailLayout, PeriodHandle, "Period"); + } + else if (!bIsPeriodic && !bIsDuration) + { + TSharedPtr MaxStacksProp = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, MaxStacks), UGAGameEffectSpec::StaticClass()); + TSharedPtr MaxStackedDurationHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UGAGameEffectSpec, MaxStackedDuration), UGAGameEffectSpec::StaticClass()); + + DetailLayout.HideProperty(MaxStacksProp); + DetailLayout.HideProperty(DurationHandle); + DetailLayout.HideProperty(PeriodHandle); + DetailLayout.HideProperty(MaxStackedDurationHandle); + DetailLayout.HideCategory("Duration"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "EffectAggregation"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnExpiredEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "OnRemovedEffects"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AttributeTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "AppliedImmunityTags"); + FAFEffectCustomizationCommon::HideProperty(DetailLayout, "ApplyTags"); + + } + } + } + } +} +void FGAEffectDetails::OnDurationPolicyChange() +{ + if(MyDetailLayout) + MyDetailLayout->ForceRefreshDetails(); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectDetails.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectDetails.h new file mode 100644 index 0000000..8280469 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectDetails.h @@ -0,0 +1,32 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypesEditor.h" + +#include "IDetailCustomization.h" +#include "PropertyHandle.h" + +class FGAEffectDetails : public IDetailCustomization +{ + +protected: + bool bIsDuration; + bool bIsPeriodic; + TSharedPtr ApplicationTypeHandle; +public: + /** Makes a new instance of this detail layout class for a specific detail view requesting it */ + static TSharedRef MakeInstance(); + +private: + TSharedPtr MyProperty; + TSharedPtr DurationHandle; + TSharedPtr PeriodHandle; + TSharedPtr DurationCalcTypeHandle; + TSharedPtr PeriodCalcTypeHandle; + IDetailLayoutBuilder* MyDetailLayout; + FSimpleDelegate UpdateEffectTypeyDelegate; + /** IDetailCustomization interface */ + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override; + + void OnDurationPolicyChange(); +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectPropertyStructCustomization.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectPropertyStructCustomization.cpp new file mode 100644 index 0000000..a10c616 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectPropertyStructCustomization.cpp @@ -0,0 +1,96 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#include "AbilityFrameworkEditor.h" +#include "IDetailsView.h" +#include "PropertyEditorModule.h" +#include "Editor/PropertyEditor/Public/PropertyEditing.h" +#include "Editor/PropertyEditor/Private/IDetailsViewPrivate.h" +#include "Editor/PropertyEditor/Private/SDetailsViewBase.h" +#include "Editor/PropertyEditor/Private/SDetailsView.h" +//D:\Unreal\UnrealEngine-Master\Engine\Source\Editor\PropertyEditor\Private\SDetailsView.h +#include "STextCombobox.h" +#include "STreeView.h" +#include "SButton.h" +#include "STextBlock.h" + +#include "ClassViewerModule.h" +#include "ClassViewerFilter.h" + +#include "EditorClassUtils.h" +#include "IAssetTools.h" +#include "AssetRegistryModule.h" +#include "Dialogs/DlgPickAssetPath.h" +#include "AssetToolsModule.h" +#include "KismetCompilerModule.h" +#include "Kismet2/KismetEditorUtilities.h" +#include "EffectEditor/GAEffectEditor.h" +#include "SMyBlueprint.h" +#include "SKismetInspector.h" + +#include "SGAAttributeWidget.h" +#include "Effects/GAGameEffect.h" +#include "Effects/GAEffectBlueprint.h" +#include "EffectEditor/GAEffectBlueprintFactory.h" +#include "GAEffectPropertyStructCustomization.h" +#include "GAEffectDetails.h" + +TSharedRef FGAEffectPropertyStructCustomization::MakeInstance() +{ + return MakeShareable(new FGAEffectPropertyStructCustomization); +} + +FGAEffectPropertyStructCustomization::~FGAEffectPropertyStructCustomization() +{ + +} + +void FGAEffectPropertyStructCustomization::CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) +{ + const TArray>& objs = StructCustomizationUtils.GetPropertyUtilities()->GetSelectedObjects(); + UObject* Owner = nullptr; + if (objs.Num() > 0) + { + Owner = objs[0].Get(); + } + StructPropertyHandle = InStructPropertyHandle; + TAttribute EffectName;// (); + EffectName.Create(TAttribute::FGetter::CreateRaw(this, &FGAEffectPropertyStructCustomization::GetClassName)); + /*SNew(SVerticalBox) + + SVerticalBox::Slot() + [ + SNew(STextBlock) + .Text(EffectName) + ]*/ + EffectPropertyHandle = InStructPropertyHandle->GetChildHandle(TEXT("SpecClass")); //struct + TSharedPtr ClassInStruct = EffectPropertyHandle->GetChildHandle(TEXT("SpecClass")); + EffectClassWidget = MakeShareable(new FGAEffectClassStructWidget()); + EffectClassWidget->SetHandles(EffectPropertyHandle, ClassInStruct); + + HeaderRow + .NameContent() + [ + InStructPropertyHandle->CreatePropertyNameWidget() + ] + .ValueContent() + .HAlign(HAlign_Fill) + [ + SNew(SHorizontalBox) + +SHorizontalBox::Slot() + .AutoWidth() + [ + EffectClassWidget->CreateEffectClassWidget(Owner) + ] + ]; +} +void FGAEffectPropertyStructCustomization::CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) +{ + +} +FText FGAEffectPropertyStructCustomization::GetClassName() const +{ + if (StructPropertyHandle.IsValid()) + { + return StructPropertyHandle->GetPropertyDisplayName(); + } + return FText::FromString("No Effect Selected"); +} \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectPropertyStructCustomization.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectPropertyStructCustomization.h new file mode 100644 index 0000000..4ed717c --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAEffectPropertyStructCustomization.h @@ -0,0 +1,28 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "Attributes/GAAttributeGlobals.h" +#include "GAGlobalTypesEditor.h" + +#include "IPropertyTypeCustomization.h" +#include "PropertyHandle.h" + +#include "GAEffectClassStructWidget.h" +class FGAEffectPropertyStructCustomization : public IPropertyTypeCustomization +{ +protected: + TSharedPtr StructPropertyHandle; + TSharedPtr EffectPropertyHandle; + TSharedPtr EffectClassWidget; +public: + static TSharedRef MakeInstance(); + /** + * Destructor + */ + virtual ~FGAEffectPropertyStructCustomization(); + + /** IPropertyTypeCustomization interface */ + virtual void CustomizeHeader(TSharedRef InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; + virtual void CustomizeChildren(TSharedRef InStructPropertyHandle, IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; + + FText GetClassName() const; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAGlobalTypesEditor.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAGlobalTypesEditor.h new file mode 100644 index 0000000..3f87d07 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/GAGlobalTypesEditor.h @@ -0,0 +1,35 @@ + +#pragma once + +#include "GAGlobalTypesEditor.generated.h" + +USTRUCT() +struct FGAAttributeNode +{ + GENERATED_USTRUCT_BODY() +public: + //Name of current node, like class, category, attribute etc. + FString NodeName; + + FString ParentClassName; + + //current attribute for this node); + FString Attribute; + + TWeakPtr ParentNode; + + TArray > ChildNodes; + + /* + List of attributes containe within selected class (ParentClassName) + */ + TArray AttributeNames; + TArray CategoryNames; + FGAAttributeNode() {}; + ~FGAAttributeNode() + { + ParentClassName.Empty(); + Attribute.Empty(); + AttributeNames.Empty(); + }; +}; \ No newline at end of file diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/IAbilityFrameworkEditor.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/IAbilityFrameworkEditor.h new file mode 100644 index 0000000..6b825c2 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/IAbilityFrameworkEditor.h @@ -0,0 +1,36 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. + +#pragma once +#include "ModuleManager.h" + + +/** + * The public interface to this module. In most cases, this interface is only public to sibling modules + * within this plugin. + */ +class IAbilityFrameworkEditor : public IModuleInterface +{ +public: + + /** + * Singleton-like access to this module's interface. This is just for convenience! + * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. + * + * @return Returns singleton instance, loading the module on demand if needed + */ + static inline IAbilityFrameworkEditor& Get() + { + return FModuleManager::LoadModuleChecked< IAbilityFrameworkEditor >("AbilityFrameworkEditor"); + } + + /** + * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. + * + * @return True if the module is loaded and ready to use + */ + static inline bool IsAvailable() + { + return FModuleManager::Get().IsModuleLoaded( "AbilityFrameworkEditor" ); + } +}; + diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/SGAAttributeWidget.cpp b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/SGAAttributeWidget.cpp new file mode 100644 index 0000000..95453df --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/SGAAttributeWidget.cpp @@ -0,0 +1,151 @@ +// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +#pragma once +#include "AbilityFrameworkEditor.h" + +#include "KismetEditorUtilities.h" + +#include "STextComboBox.h" +#include "STreeView.h" +#include "GAGlobalTypesEditor.h" + +#include "Attributes/GAAttributesBase.h" +#include "SGAAttributeWidget.h" + +void SGAAttributeWidget::Construct(const FArguments& InArgs) +{ + AttributesList.Empty(); + AttributesNodes.Empty(); + OnAttributeSelected = InArgs._OnAttributeSelectedIn; + + /* + Intended look: + ClassName + --CategoryName + ----AttributeName + + Or: + ClassName + --CategoryName + ----AttributeType + ------AttributeName + + + search. We really need search! + */ + for (TObjectIterator ClassIt; ClassIt; ++ClassIt) + { + UClass* Class = *ClassIt; + if (Class->IsChildOf(UGAAttributesBase::StaticClass()) + && !FKismetEditorUtilities::IsClassABlueprintSkeleton(Class)) + { + FString className = Class->GetName(); + if (!className.Contains(TEXT("REINST_"))) + { + TSharedPtr classRootNode = MakeShareable(new FGAAttributeNode()); + classRootNode->Attribute = className; + //first let's find root of tree, which is class name + classRootNode->NodeName = className; + FString Category; + //now let's categories as childs + for (TFieldIterator PropertyIt(Class, EFieldIteratorFlags::ExcludeSuper); PropertyIt; ++PropertyIt) + { + UProperty* Prop = *PropertyIt; + Category = Prop->GetMetaData("Category"); + + //check if we already have this category added.. + bool bFoundExistingCategory = false; + if (!Category.IsEmpty()) + { + for (TSharedPtr childNode : classRootNode->ChildNodes) + { + if (childNode->NodeName == Category) + { + bFoundExistingCategory = true; + TSharedPtr attrNode = MakeShareable(new FGAAttributeNode()); + attrNode->NodeName = Prop->GetName(); + attrNode->ParentNode = childNode; + childNode->ChildNodes.Add(attrNode); + } + } + if (!bFoundExistingCategory) + { + TSharedPtr categoryNode = MakeShareable(new FGAAttributeNode()); + categoryNode->NodeName = Category; + categoryNode->ParentNode = classRootNode; + classRootNode->ChildNodes.Add(categoryNode); + + TSharedPtr attrNode = MakeShareable(new FGAAttributeNode()); + attrNode->NodeName = Prop->GetName(); + attrNode->ParentNode = categoryNode; + categoryNode->ChildNodes.Add(attrNode); + } + } + } + AttributesNodes.Add(classRootNode); + } + } + } + + ChildSlot + [ + SAssignNew(AttributeTreeWidget, STreeView>) + .OnSelectionChanged(this, &SGAAttributeWidget::OnItemSelected) + .TreeItemsSource(&AttributesNodes) + .OnGenerateRow(this, &SGAAttributeWidget::OnGenerateRow) + .OnGetChildren(this, &SGAAttributeWidget::OnGetChildren) + .OnExpansionChanged(this, &SGAAttributeWidget::OnExpansionChanged) + .SelectionMode(ESelectionMode::Single) + ]; +} +SGAAttributeWidget::~SGAAttributeWidget() +{ + AttributesNodes.Empty(); +} + +void SGAAttributeWidget::OnItemSelected(TSharedPtr SelectedItem, ESelectInfo::Type SelectInfo) +{ + if (SelectedItem.IsValid()) + { + if (OnAttributeSelected.IsBound()) + { + OnAttributeSelected.Execute(SelectedItem->NodeName); + } + } +} + +TSharedRef SGAAttributeWidget::OnGenerateRow(TSharedPtr InItem, const TSharedRef& OwnerTable) +{ + return SNew(STableRow< TSharedPtr >, OwnerTable) + [ + SNew(STextBlock) + .Text(FText::FromString(InItem->NodeName)) + ]; +} + +void SGAAttributeWidget::OnGetChildren(TSharedPtr InItem, TArray< TSharedPtr >& OutChildren) +{ + TArray> Children; + + TArray> Children2; + + for (const FString& attribute : InItem->AttributeNames) + { + TSharedPtr attrNode = MakeShareable(new FGAAttributeNode()); + attrNode->Attribute = attribute; + Children.Add(attrNode); + } + + for (TSharedPtr childs : InItem->ChildNodes) + { + Children2.Add(childs); + } + + OutChildren += Children2; +} + + +void SGAAttributeWidget::OnExpansionChanged(TSharedPtr InItem, bool bIsExpanded) +{ + +} + + diff --git a/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/SGAAttributeWidget.h b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/SGAAttributeWidget.h new file mode 100644 index 0000000..9ff94f5 --- /dev/null +++ b/Plugins/AbilityFramework/Source/AbilityFrameworkEditor/Public/SGAAttributeWidget.h @@ -0,0 +1,64 @@ + +#pragma once + +#include "SlateBasics.h" +#include "GAGlobalTypesEditor.h" + +DECLARE_DELEGATE_OneParam(FGAOnAttributeSelected, FString); + +class FAFAttributeNode +{ + FString NodeName; + + FString Attribute; + + TWeakPtr ParentNode; + + TArray > ChildNodes; +}; + +class FAFAttributeTree +{ + +}; + +class SGAAttributeWidget : public SCompoundWidget +{ + SLATE_BEGIN_ARGS(SGAAttributeWidget) + {} + SLATE_EVENT(FGAOnAttributeSelected, OnAttributeSelectedIn) + SLATE_END_ARGS(); + + void Construct(const FArguments& InArgs); + ~SGAAttributeWidget(); +private: + TArray> AttributesList; + + TArray > AttributesNodes; + + TSharedPtr > > AttributeTreeWidget; + + FGAOnAttributeSelected OnAttributeSelected; + + void OnItemSelected(TSharedPtr SelectedItem, ESelectInfo::Type SelectInfo); + /** + * Generate a row widget for the specified item node and table + * + * @param InItem Tag node to generate a row widget for + * @param OwnerTable Table that owns the row + * + * @return Generated row widget for the item node + */ + TSharedRef OnGenerateRow(TSharedPtr InItem, const TSharedRef& OwnerTable); + + /** + * Get children nodes of the specified node + * + * @param InItem Node to get children of + * @param OutChildren [OUT] Array of children nodes, if any + */ + void OnGetChildren(TSharedPtr InItem, TArray< TSharedPtr >& OutChildren); + + + void OnExpansionChanged(TSharedPtr InItem, bool bIsExpanded); +}; \ No newline at end of file diff --git a/Plugins/DraggableWindow/DraggableWindow.uplugin b/Plugins/DraggableWindow/DraggableWindow.uplugin new file mode 100644 index 0000000..3b1b4c9 --- /dev/null +++ b/Plugins/DraggableWindow/DraggableWindow.uplugin @@ -0,0 +1,23 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "DraggableWindow", + "Description": "", + "Category": "Other", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "DraggableWindow", + "Type": "Developer", + "LoadingPhase": "Default" + } + ] +} \ No newline at end of file diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/DraggableWindow.Build.cs b/Plugins/DraggableWindow/Source/DraggableWindow/DraggableWindow.Build.cs new file mode 100644 index 0000000..4396c51 --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/DraggableWindow.Build.cs @@ -0,0 +1,54 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class DraggableWindow : ModuleRules +{ + public DraggableWindow(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "DraggableWindow/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "Core", + "CoreUObject", + "Engine", + "InputCore", + "Slate", + "SlateCore", + "UMG" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + if (Target.Type == TargetRules.TargetType.Editor) + { + PublicDependencyModuleNames.AddRange(new string[] { "UnrealEd", "PropertyEditor" }); + } + } +} diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWBPFunctionLibrary.cpp b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWBPFunctionLibrary.cpp new file mode 100644 index 0000000..48e6f7b --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWBPFunctionLibrary.cpp @@ -0,0 +1,14 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "DWBPFunctionLibrary.h" +#include "DWManager.h" + + +FDWWWindowHandle UDWBPFunctionLibrary::CreateWindow(const FString& WindowName) +{ + return FDWManager::Get().CreateWindow(WindowName); +} +FDWWWindowHandle UDWBPFunctionLibrary::CreateWindowWithContent(UUserWidget* InWindowContent, const FString& WindowName) +{ + return FDWManager::Get().CreateWindow(InWindowContent->TakeWidget(), WindowName); +} \ No newline at end of file diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWBPFunctionLibrary.h b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWBPFunctionLibrary.h new file mode 100644 index 0000000..1914c37 --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWBPFunctionLibrary.h @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "UserWidget.h" +#include "DWTypes.h" + +#include "DWBPFunctionLibrary.generated.h" + +/** + * + */ +UCLASS() +class DRAGGABLEWINDOW_API UDWBPFunctionLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, Category = "Draggable Window") + static FDWWWindowHandle CreateWindow(const FString& WindowName); + + UFUNCTION(BlueprintCallable, Category = "Draggable Window") + static FDWWWindowHandle CreateWindowWithContent(UUserWidget* InWindowContent, const FString& WindowName); +}; diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWManager.cpp b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWManager.cpp new file mode 100644 index 0000000..bf1b797 --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWManager.cpp @@ -0,0 +1,72 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "DWManager.h" +#include "EngineGlobals.h" +#include "Engine/Engine.h" +#include "Engine/GameViewportClient.h" + +FDWManager* FDWManager::Instance = nullptr; +void FDWManager::Init() +{ + Desktop = SNew(SDraggableDesktopWidget).Visibility(EVisibility::SelfHitTestInvisible); + GEngine->GameViewport->AddViewportWidgetContent(Desktop.ToSharedRef(), 2000); +} +void FDWManager::CleanUp() +{ + Desktop->Clean(); + Desktop.Reset(); + WindowHandles.Empty(); + WindowHandles.Shrink(); +} +void FDWManager::RemoveWindow(const FDWWWindowHandle& InHandle) +{ + Desktop->RemoveWindow(InHandle.Window.Pin()); + WindowHandles.Remove(InHandle); +} +FDWManager& FDWManager::Get() +{ + if (!Instance) + { + Instance = new FDWManager(); + Instance->Init(); + } + return *Instance; +} +#if WITH_EDITORONLY_DATA +void FDWManager::PIEDestroy() +{ + if (Instance) + { + Instance->CleanUp(); + delete Instance; + Instance = nullptr; + } +} +#endif //WITH_EDITORONLY_DATA +FDWManager::FDWManager() +{ +} + +FDWManager::~FDWManager() +{ +} + +FDWWWindowHandle FDWManager::CreateWindow(const FString& WindowName) +{ + TSharedPtr NewWindow = SNew(SDraggableWindowWidget); + return AddWindow(NewWindow, WindowName); +} +FDWWWindowHandle FDWManager::CreateWindow(TSharedPtr InWindowContent, const FString& WindowName) +{ + + TSharedPtr NewWindow = SNew(SDraggableWindowWidget); + NewWindow->AddContent(InWindowContent); + return AddWindow(NewWindow, WindowName); +} +FDWWWindowHandle FDWManager::AddWindow(TSharedPtr InWindowWidget, const FString& WindowName) +{ + FDWWWindowHandle Handle = Desktop->AddWindow(InWindowWidget); + WindowHandles.Add(Handle); + WindowsByName.Add(FName(*WindowName), Handle); + return Handle; +} \ No newline at end of file diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWManager.h b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWManager.h new file mode 100644 index 0000000..046d245 --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWManager.h @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SDraggableWindowWidget.h" + +/** + * + */ +class DRAGGABLEWINDOW_API FDWManager +{ +public: + friend class SDraggableWindowWidget; + friend class SDraggableDesktopWidget; +private: + static FDWManager* Instance; + TSharedPtr Desktop; + TSet WindowHandles; + //name of window, window handle + TMap WindowsByName; + void Init(); + void CleanUp(); + void RemoveWindow(const FDWWWindowHandle& InHandle); + FDWManager(); + +public: + static FDWManager& Get(); +#if WITH_EDITORONLY_DATA + static void PIEDestroy(); +#endif //WITH_EDITORONLY_DATA + ~FDWManager(); + + FDWWWindowHandle CreateWindow(const FString& WindowName); + FDWWWindowHandle CreateWindow(TSharedPtr InWindowContent, const FString& WindowName); + FDWWWindowHandle AddWindow(TSharedPtr InWindowWidget, const FString& WindowName); +}; +typedef FDWManager FDraggableWindowManager; \ No newline at end of file diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWTypes.cpp b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWTypes.cpp new file mode 100644 index 0000000..3fe94f4 --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWTypes.cpp @@ -0,0 +1,3 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "DWTypes.h" \ No newline at end of file diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWTypes.h b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWTypes.h new file mode 100644 index 0000000..d5e8c26 --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DWTypes.h @@ -0,0 +1,41 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "DWTypes.generated.h" + +USTRUCT(BlueprintType) +struct FDWWWindowHandle +{ + GENERATED_BODY() + TWeakPtr Window; +protected: + uint32 Handle; +public: + FDWWWindowHandle() + {}; + FDWWWindowHandle(uint32 InHandle) + : Handle(InHandle) + { + + } + + ~FDWWWindowHandle() + { + Handle = 0; + Window.Reset(); + } + + static FDWWWindowHandle Make(TSharedPtr InWindow); + + friend uint32 GetTypeHash(const FDWWWindowHandle& InHandle) + { + return InHandle.Handle; + } + + const bool operator==(const FDWWWindowHandle& InHandle) const + { + return Handle == InHandle.Handle; + } +}; \ No newline at end of file diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/Public/DraggableWindow.cpp b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DraggableWindow.cpp new file mode 100644 index 0000000..e401549 --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DraggableWindow.cpp @@ -0,0 +1,33 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "DraggableWindow.h" +#include "DWManager.h" +#if WITH_EDITORONLY_DATA +#include "Editor.H" +#endif +#define LOCTEXT_NAMESPACE "FDraggableWindowModule" + +void FDraggableWindowModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module + +#if WITH_EDITORONLY_DATA + FEditorDelegates::EndPIE.AddRaw(this, &FDraggableWindowModule::HandlePIEEnd); +#endif //WITH_EDITORONLY_DATA + +} + +void FDraggableWindowModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} +#if WITH_EDITORONLY_DATA +void FDraggableWindowModule::HandlePIEEnd(bool InVal) +{ + FDWManager::PIEDestroy(); +} +#endif +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FDraggableWindowModule, DraggableWindow) \ No newline at end of file diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/Public/DraggableWindow.h b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DraggableWindow.h new file mode 100644 index 0000000..106e834 --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/Public/DraggableWindow.h @@ -0,0 +1,21 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "Engine.h" +#include "CoreMinimal.h" +#include "ModuleManager.h" + + + +class FDraggableWindowModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +#if WITH_EDITORONLY_DATA + void HandlePIEEnd(bool InVal); +#endif +}; \ No newline at end of file diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/Public/SDraggableWindowWidget.cpp b/Plugins/DraggableWindow/Source/DraggableWindow/Public/SDraggableWindowWidget.cpp new file mode 100644 index 0000000..a930314 --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/Public/SDraggableWindowWidget.cpp @@ -0,0 +1,706 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SDraggableWindowWidget.h" +#include "SlateOptMacros.h" + +#include "Slate.h" +#include "SlateCore.h" +#include "SBorder.h" +#include "Widgets/Layout/SGridPanel.h" +#include "Widgets/Layout/SBackgroundBlur.h" +#include "DWManager.h" +#include "EngineGlobals.h" +#include "Engine/Engine.h" +#include "Engine/GameViewportClient.h" +#include "SceneViewport.h" + +DECLARE_CYCLE_STAT(TEXT("DraggebleWindow.Tick"), STAT_DraggebleWindowTick, STATGROUP_DraggebleWindow); + +FDWWWindowHandle FDWWWindowHandle::Make(TSharedPtr InWindow) +{ + static uint32 NewHandle = 0; + NewHandle++; + FDWWWindowHandle Handle(NewHandle); + Handle.Window = InWindow; + InWindow->SetHandle(Handle); + return Handle; +} +void SDraggableDesktopWidget::Clean() +{ + for (TSharedPtr& Window : Windows) + { + Window.Reset(); + } + Windows.Empty(); + Windows.Shrink(); +} +BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION +void SDraggableDesktopWidget::Construct(const FArguments& InArgs) +{ + SetVisibility(EVisibility::SelfHitTestInvisible); + Container = SNew(SOverlay).Visibility(EVisibility::SelfHitTestInvisible); + ChildSlot + [ + Container.ToSharedRef() + ]; +} +END_SLATE_FUNCTION_BUILD_OPTIMIZATION + +FDWWWindowHandle SDraggableDesktopWidget::AddWindow(TSharedPtr InWindow) +{ + if (!Container.IsValid()) + return FDWWWindowHandle(); + + Container->AddSlot() + .HAlign(EHorizontalAlignment::HAlign_Left) + .VAlign(EVerticalAlignment::VAlign_Top) + [ + InWindow.ToSharedRef() + ]; + + FDWWWindowHandle Handle = FDWWWindowHandle::Make(InWindow); + Windows.Add(InWindow); + return Handle; +} + +void SDraggableDesktopWidget::RemoveWindow(TSharedPtr InWindow) +{ + Container->RemoveSlot(InWindow.ToSharedRef()); + Windows.Remove(InWindow); + InWindow.Reset(); +} + +void SWindowBox::Construct(const FArguments& InArgs) +{ + WidthOverride = InArgs._WidthOverride.Get(); + HeightOverride = InArgs._HeightOverride.Get(); + + ChildSlot + .HAlign(EHorizontalAlignment::HAlign_Fill) + .VAlign(EVerticalAlignment::VAlign_Fill) + [ + InArgs._Content.Widget + ]; +} +void SWindowBox::SetWidthOverride(float InWidthOverride) +{ + if (WidthOverride != InWidthOverride) + { + WidthOverride = InWidthOverride; + + Invalidate(EInvalidateWidget::Layout); + } +} + +void SWindowBox::SetHeightOverride(float InHeightOverride) +{ + if (HeightOverride != InHeightOverride) + { + HeightOverride = InHeightOverride; + + Invalidate(EInvalidateWidget::Layout); + } +} +void SWindowBox::OnArrangeChildren(const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren) const +{ + const EVisibility& MyCurrentVisibility = this->GetVisibility(); + if (ArrangedChildren.Accepts(MyCurrentVisibility)) + { + const FMargin SlotPadding(ChildSlot.SlotPadding.Get()); + bool bAlignChildren = true; + + AlignmentArrangeResult XAlignmentResult(0, 0); + AlignmentArrangeResult YAlignmentResult(0, 0); + + if (bAlignChildren) + { + XAlignmentResult = AlignChild(AllottedGeometry.GetLocalSize().X, ChildSlot, SlotPadding); + YAlignmentResult = AlignChild(AllottedGeometry.GetLocalSize().Y, ChildSlot, SlotPadding); + } + + const float AlignedSizeX = XAlignmentResult.Size; + const float AlignedSizeY = YAlignmentResult.Size; + + ArrangedChildren.AddWidget( + AllottedGeometry.MakeChild( + ChildSlot.GetWidget(), + FVector2D(XAlignmentResult.Offset, YAlignmentResult.Offset), + FVector2D(AlignedSizeX, AlignedSizeY) + ) + ); + } +} +FChildren* SWindowBox::GetChildren() +{ + return &ChildSlot; +} +FVector2D SWindowBox::ComputeDesiredSize(float) const +{ + EVisibility ChildVisibility = ChildSlot.GetWidget()->GetVisibility(); + + if (ChildVisibility != EVisibility::Collapsed) + { + // If the user specified a fixed width or height, those values override the Box's content. + + const float CurrentWidthOverride = WidthOverride; + const float CurrentHeightOverride = HeightOverride; + + + return FVector2D(CurrentWidthOverride, CurrentHeightOverride); + } + + return FVector2D::ZeroVector; +} +BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION +void SDraggableWindowWidget::Construct(const FArguments& InArgs) +{ + CurrentSize = FVector2D(1, 1); + ResizingState = EDDWState::NoResize; + bDestroyOnClose = true; + SetVisibility(EVisibility::SelfHitTestInvisible); + FSimpleDelegate OnPressedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnPressed); + FSimpleDelegate OnReleasedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnReleased); + TAttribute posAttr = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &SDraggableWindowWidget::GetPosition)); + + + FSimpleDelegate OnHorizontalPressedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnHorizontalResizePressed); + FSimpleDelegate OnHorizontalReleasedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnHorizontalResizeReleased); + FSimpleDelegate OnHorizontalLeftPressedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnHorizontalResizeLeftPressed); + FSimpleDelegate OnHorizontalLeftReleasedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnHorizontalResizeLeftReleased); + + FSimpleDelegate OnVerticalTopPressedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnVerticalTopResizePressed); + FSimpleDelegate OnVerticalTopReleasedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnVerticalTopResizeReleased); + FSimpleDelegate OnVerticalBottomPressedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnVerticalBottomResizePressed); + FSimpleDelegate OnVerticalBottomReleasedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnVerticalBottomResizeReleased); + + FSimpleDelegate OnBottomRightPressedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnBottomRightResizePressed); + FSimpleDelegate OnBottomRightReleasedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnBottomRightResizeReleased); + + FSimpleDelegate OnBottomLeftPressedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnBottomLeftResizePressed); + FSimpleDelegate OnBottomLeftReleasedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnBottomLeftResizeReleased); + + FSimpleDelegate OnTopRightPressedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnTopRightResizePressed); + FSimpleDelegate OnTopRightReleasedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnTopRightResizeReleased); + + FSimpleDelegate OnTopLeftPressedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnTopLeftResizePressed); + FSimpleDelegate OnTopLeftReleasedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnTopLeftResizeReleased); + + + FSimpleDelegate OnCloseButtonPressedDel = FSimpleDelegate::CreateSP(this, &SDraggableWindowWidget::OnCloseButtonPressed); + + CurrentHeight = 200; + CurrentWidth = 200; + + FSlateBrush brush; + brush.DrawAs = ESlateBrushDrawType::Type::NoDrawType; + ButtonStyle.Normal = brush; + ButtonStyle.Hovered = brush; + ButtonStyle.Pressed = brush; + ButtonStyle.Disabled = brush; + BackgroundColor = FSlateColor(FLinearColor(0, 0, 0, 1)); + ChildSlot + [ + SNew(SCanvas) + + SCanvas::Slot() + .HAlign(EHorizontalAlignment::HAlign_Left) + .VAlign(EVerticalAlignment::VAlign_Top) + .Position(posAttr) + //.Size(sizeAttr) + [ + SNew(SGridPanel) + + +SGridPanel::Slot(0, 0) + [ + SNew(SBox) + .HeightOverride(3) + .WidthOverride(3) + [ + SNew(SButton) + .ButtonStyle(&ButtonStyle) + .OnPressed(OnTopLeftPressedDel) + .OnReleased(OnTopLeftReleasedDel) + .Cursor(EMouseCursor::ResizeSouthEast) + ] + ] + + SGridPanel::Slot(1 ,0) + [ + SNew(SBox) + .HeightOverride(3) + [ + SNew(SButton) + .ButtonStyle(&ButtonStyle) + .OnPressed(OnVerticalTopPressedDel) + .OnReleased(OnVerticalTopReleasedDel) + .Cursor(EMouseCursor::ResizeUpDown) + + ] + ] + + SGridPanel::Slot(2, 0) + [ + SNew(SBox) + .HeightOverride(3) + .WidthOverride(3) + [ + SNew(SButton) + .ButtonStyle(&ButtonStyle) + .OnPressed(OnTopRightPressedDel) + .OnReleased(OnTopRightReleasedDel) + .Cursor(EMouseCursor::ResizeSouthWest) + ] + ] + + SGridPanel::Slot(0, 1) + [ + SNew(SBox) + .WidthOverride(3) + [ + SNew(SButton) + .ButtonStyle(&ButtonStyle) + .OnPressed(OnHorizontalLeftPressedDel) + .OnReleased(OnHorizontalLeftReleasedDel) + .Cursor(EMouseCursor::ResizeLeftRight) + ] + ] + + SGridPanel::Slot(1, 1) + .HAlign(EHorizontalAlignment::HAlign_Fill) + .VAlign(EVerticalAlignment::VAlign_Fill) + [ + SAssignNew(WindowBox, SWindowBox) + .Visibility(EVisibility::SelfHitTestInvisible) + //.HeightOverride(heightAttr) + //.WidthOverride(widthAttr) + [ + SNew(SVerticalBox) + .Visibility(EVisibility::SelfHitTestInvisible) + + SVerticalBox::Slot() + .AutoHeight() + .MaxHeight(24) + [ + SNew(SOverlay) + + SOverlay::Slot() + [ + SNew(SBackgroundBlur) + .BlurRadius(4) + .BlurStrength(16) + .Visibility(EVisibility::SelfHitTestInvisible) + ] + + SOverlay::Slot() + [ + SAssignNew(WindowBar, SButton) + .OnPressed(OnPressedDel) + .OnReleased(OnReleasedDel) + .VAlign(EVerticalAlignment::VAlign_Center) + .HAlign(EHorizontalAlignment::HAlign_Right) + .ContentPadding(FMargin(0)) + .ButtonStyle(&ButtonStyle) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .FillWidth(0.8f) + .AutoWidth() + [ + SNew(STextBlock) + .Visibility(EVisibility::SelfHitTestInvisible) + .Text(FText::FromString("Window Title")) + ] + + SHorizontalBox::Slot() + [ + SNew(SButton) + .OnPressed(OnCloseButtonPressedDel) + [ + SNew(STextBlock) + .Text(FText::FromString("X")) + ] + ] + ] + ] + + ] + + SVerticalBox::Slot() + .HAlign(EHorizontalAlignment::HAlign_Fill) + .VAlign(EVerticalAlignment::VAlign_Fill) + .FillHeight(1.0f) + [ + SNew(SBox) + .HAlign(EHorizontalAlignment::HAlign_Fill) + .VAlign(EVerticalAlignment::VAlign_Fill) + [ + SNew(SOverlay) + + SOverlay::Slot() + [ + SNew(SBackgroundBlur) + .BlurRadius(4) + .BlurStrength(8) + .Visibility(EVisibility::SelfHitTestInvisible) + ] + +SOverlay::Slot() + [ + SAssignNew(Content, SOverlay) + .Visibility(EVisibility::SelfHitTestInvisible) + ] + + ] + ] + ] + + ] + + SGridPanel::Slot(2, 1) + [ + SNew(SBox) + .WidthOverride(3) + [ + SNew(SButton) + .ButtonStyle(&ButtonStyle) + .OnPressed(OnHorizontalPressedDel) + .OnReleased(OnHorizontalReleasedDel) + .Cursor(EMouseCursor::ResizeLeftRight) + ] + ] + + SGridPanel::Slot(0, 2) + [ + SNew(SBox) + .HeightOverride(3) + .WidthOverride(3) + [ + SNew(SButton) + .ButtonStyle(&ButtonStyle) + .OnPressed(OnBottomLeftPressedDel) + .OnReleased(OnBottomLeftReleasedDel) + .Cursor(EMouseCursor::ResizeSouthWest) + ] + ] + + SGridPanel::Slot(1, 2) + [ + SNew(SBox) + .HeightOverride(3) + [ + SNew(SButton) + .ButtonStyle(&ButtonStyle) + .OnPressed(OnVerticalBottomPressedDel) + .OnReleased(OnVerticalBottomReleasedDel) + .Cursor(EMouseCursor::ResizeUpDown) + ] + ] + + SGridPanel::Slot(2, 2) + [ + SNew(SBox) + .HeightOverride(3) + .WidthOverride(3) + [ + SNew(SButton) + .ButtonStyle(&ButtonStyle) + .OnPressed(OnBottomRightPressedDel) + .OnReleased(OnBottomRightReleasedDel) + .Cursor(EMouseCursor::ResizeSouthEast) + ] + ] + ] + ]; + WindowBox->SetHeightOverride(CurrentHeight); + WindowBox->SetWidthOverride(CurrentWidth); +} +END_SLATE_FUNCTION_BUILD_OPTIMIZATION +SDraggableWindowWidget::~SDraggableWindowWidget() +{ +} +FVector2D SDraggableWindowWidget::ComputeDesiredSize(float) const +{ + return SCompoundWidget::ComputeDesiredSize(1); +} +void SDraggableWindowWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) +{ + SCOPE_CYCLE_COUNTER(STAT_DraggebleWindowTick); + SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime); + + FVector2D LastPosition = AllottedGeometry.AbsoluteToLocal(FSlateApplicationBase::Get().GetLastCursorPos()); + + FVector2D CurrentPosition = AllottedGeometry.AbsoluteToLocal(FSlateApplicationBase::Get().GetCursorPos()); + + float dist = FVector2D::Distance(CurrentPosition, LastPosition); + + switch (ResizingState) + { + case EDDWState::Dragging: + { + FVector2D AbsPos = FSlateApplicationBase::Get().GetCursorPos(); + + CurrentPosition = CurrentPosition - DragPosition; + AbsPosition = AbsPos - AbsDragPosition; + + FVector2D WindowPosition = GEngine->GameViewport->GetWindow()->GetPositionInScreen(); + FVector2D WindowSize = GEngine->GameViewport->GetWindow()->GetSizeInScreen() - 8; + + const float ApplicationScale = FSlateApplication::Get().GetApplicationScale(); + FVector2D AbsSize = AllottedGeometry.LocalToAbsolute(FVector2D(CurrentWidth, CurrentHeight)); + FVector2D GeomAbs = AllottedGeometry.GetAbsolutePosition(); + FVector2D localSize = WindowSize + WindowPosition; + CurrentCursorPosition = CurrentPosition; + if (CurrentPosition.X <= 0) + { + CurrentCursorPosition.X = 0; + } + if (CurrentPosition.Y <= 0) + { + CurrentCursorPosition.Y = 0; + } + if ((AbsPos.X + ((AbsSize.X - AbsDragPosition.X) * ApplicationScale)) >= localSize.X) + { + FVector2D localSize2 = AllottedGeometry.AbsoluteToLocal(WindowSize + WindowPosition); + CurrentCursorPosition.X = localSize2.X - CurrentWidth; + } + if ((AbsPos.Y + ((AbsSize.Y - AbsDragPosition.Y) * ApplicationScale)) >= localSize.Y) + { + FVector2D localSize2 = AllottedGeometry.AbsoluteToLocal(WindowSize + WindowPosition); + CurrentCursorPosition.Y = localSize2.Y - CurrentHeight; + } + break; + } + case EDDWState::HorizontalRight: + { + float CurrentXX = 0; + if (dist != 0) + { + CurrentXX = CurrentPosition.X - (CurrentCursorPosition.X + CurrentWidth); + } + CurrentWidth = CurrentWidth + CurrentXX; + WindowBox->SetWidthOverride(CurrentWidth); + break; + } + case EDDWState::HorizontalLeft: + { + float CurrentXX = 0; + if (dist != 0) + { + CurrentXX = CurrentCursorPosition.X - CurrentPosition.X; + } + + CurrentCursorPosition.X -= CurrentXX; + CurrentWidth = CurrentWidth + CurrentXX; + WindowBox->SetWidthOverride(CurrentWidth); + break; + } + case EDDWState::VerticalTop: + { + float CurrentXX = 0; + float CurrentY = 0; + if (dist != 0) + { + CurrentXX = CurrentCursorPosition.Y - CurrentPosition.Y; + + } + CurrentCursorPosition.Y -= CurrentXX; + CurrentHeight = CurrentHeight + CurrentXX; + WindowBox->SetHeightOverride(CurrentHeight); + break; + } + case EDDWState::VerticalBottom: + { + float CurrentY = 0; + if (dist != 0) + { + CurrentY = CurrentPosition.Y - (CurrentCursorPosition.Y + CurrentHeight); + } + + CurrentHeight = CurrentHeight + CurrentY; + WindowBox->SetHeightOverride(CurrentHeight); + break; + } + case EDDWState::DiagonalBottomRight: + { + float CurrentXX = 0; + float CurrentY = 0; + if (dist != 0) + { + CurrentXX = CurrentPosition.X - (CurrentCursorPosition.X + CurrentWidth); + CurrentY = CurrentPosition.Y - (CurrentCursorPosition.Y + CurrentHeight); + } + CurrentWidth = CurrentWidth + CurrentXX; + CurrentHeight = CurrentHeight + CurrentY; + WindowBox->SetHeightOverride(CurrentHeight); + WindowBox->SetWidthOverride(CurrentWidth); + break; + } + case EDDWState::DiagonalBottomLeft: + { + float CurrentXX = 0; + float CurrentY = 0; + if (dist != 0) + { + CurrentXX = CurrentCursorPosition.X - CurrentPosition.X; + CurrentY = CurrentPosition.Y - (CurrentCursorPosition.Y + CurrentHeight); + } + CurrentCursorPosition.X -= CurrentXX; + CurrentWidth = CurrentWidth + CurrentXX; + CurrentHeight = CurrentHeight + CurrentY; + WindowBox->SetHeightOverride(CurrentHeight); + WindowBox->SetWidthOverride(CurrentWidth); + break; + } + case EDDWState::DiagonalTopRight: + { + float CurrentXX = 0; + float CurrentY = 0; + if (dist != 0) + { + CurrentY = CurrentCursorPosition.Y - CurrentPosition.Y; + CurrentXX = CurrentPosition.X - (CurrentCursorPosition.X + CurrentWidth); + } + CurrentCursorPosition.Y -= CurrentY; + + CurrentHeight = CurrentHeight + CurrentY; + CurrentWidth = CurrentWidth + CurrentXX; + WindowBox->SetHeightOverride(CurrentHeight); + WindowBox->SetWidthOverride(CurrentWidth); + break; + } + case EDDWState::DiagonalTopLeft: + { + float CurrentXX = 0; + float CurrentY = 0; + if (dist != 0) + { + CurrentY = CurrentCursorPosition.Y - CurrentPosition.Y; + CurrentXX = CurrentCursorPosition.X - CurrentPosition.X; + } + CurrentCursorPosition.Y -= CurrentY; + CurrentCursorPosition.X -= CurrentXX; + CurrentHeight = CurrentHeight + CurrentY; + CurrentWidth = CurrentWidth + CurrentXX; + WindowBox->SetHeightOverride(CurrentHeight); + WindowBox->SetWidthOverride(CurrentWidth); + break; + } + case EDDWState::NoResize: + { break; + } + default: + break; + } +} +void SDraggableWindowWidget::AddContent(TSharedPtr InWidget) +{ + Content->AddSlot() + .HAlign(EHorizontalAlignment::HAlign_Fill) + .VAlign(EVerticalAlignment::VAlign_Fill) + [ + InWidget.ToSharedRef() + ]; +} +void SDraggableWindowWidget::SetHandle(const FDWWWindowHandle& InHandle) +{ + Handle = InHandle; +} +void SDraggableWindowWidget::OnCloseButtonPressed() +{ + if(bDestroyOnClose) + FDWManager::Get().RemoveWindow(Handle); + else + { + SetVisibility(EVisibility::Collapsed); + } +} +void SDraggableWindowWidget::OnPressed() +{ + FGeometry geom = GetCachedGeometry(); + FVector2D CurrentPosAbs = FSlateApplicationBase::Get().GetLastCursorPos(); + FVector2D CurrentPosition = geom.AbsoluteToLocal(CurrentPosAbs); + //UE_LOG(LogTemp, Warning, TEXT("SDraggableWindowWidget::OnPressed Pre DragPosition X: %f Y: %f"), DragPosition.X, DragPosition.Y); + DragPosition = CurrentPosition - CurrentCursorPosition; + AbsDragPosition = CurrentPosAbs - AbsPosition; + + //UE_LOG(LogTemp, Warning, TEXT("SDraggableWindowWidget::OnPressed CurrentPosition X: %f Y: %f"), CurrentPosition.X, CurrentPosition.Y); + //UE_LOG(LogTemp, Warning, TEXT("SDraggableWindowWidget::OnPressed CurrentCursorPosition X: %f Y: %f"), CurrentCursorPosition.X, CurrentCursorPosition.Y); + //UE_LOG(LogTemp, Warning, TEXT("SDraggableWindowWidget::OnPressed DragPosition X: %f Y: %f"), DragPosition.X, DragPosition.Y); + ResizingState = EDDWState::Dragging; +} +void SDraggableWindowWidget::OnReleased() +{ + ResizingState = EDDWState::NoResize; +} + +void SDraggableWindowWidget::OnHorizontalResizePressed() +{ + ResizingState = EDDWState::HorizontalRight; +} +void SDraggableWindowWidget::OnHorizontalResizeReleased() +{ + ResizingState = EDDWState::NoResize; +} +void SDraggableWindowWidget::OnHorizontalResizeLeftPressed() +{ + ResizingState = EDDWState::HorizontalLeft; +} +void SDraggableWindowWidget::OnHorizontalResizeLeftReleased() +{ + ResizingState = EDDWState::NoResize; +} + +void SDraggableWindowWidget::OnVerticalTopResizePressed() +{ + ResizingState = EDDWState::VerticalTop; +} +void SDraggableWindowWidget::OnVerticalTopResizeReleased() +{ + ResizingState = EDDWState::NoResize; +} +void SDraggableWindowWidget::OnVerticalBottomResizePressed() +{ + ResizingState = EDDWState::VerticalBottom; +} +void SDraggableWindowWidget::OnVerticalBottomResizeReleased() +{ + ResizingState = EDDWState::NoResize; +} + +void SDraggableWindowWidget::OnDirectionalResizePressed() +{ +} + +void SDraggableWindowWidget::OnDirectionalResizeReleased() +{ +} + +void SDraggableWindowWidget::OnBottomRightResizePressed() +{ + ResizingState = EDDWState::DiagonalBottomRight; +} +void SDraggableWindowWidget::OnBottomRightResizeReleased() +{ + ResizingState = EDDWState::NoResize; +} + +void SDraggableWindowWidget::OnBottomLeftResizePressed() +{ + ResizingState = EDDWState::DiagonalBottomLeft; +} +void SDraggableWindowWidget::OnBottomLeftResizeReleased() +{ + ResizingState = EDDWState::NoResize; +} + +void SDraggableWindowWidget::OnTopRightResizePressed() +{ + ResizingState = EDDWState::DiagonalTopRight; +} +void SDraggableWindowWidget::OnTopRightResizeReleased() +{ + ResizingState = EDDWState::NoResize; +} + +void SDraggableWindowWidget::OnTopLeftResizePressed() +{ + ResizingState = EDDWState::DiagonalTopLeft; +} +void SDraggableWindowWidget::OnTopLeftResizeReleased() +{ + ResizingState = EDDWState::NoResize; +} + +FVector2D SDraggableWindowWidget::GetPosition() const +{ + return CurrentCursorPosition; +} + +FText SDraggableWindowWidget::GetTitle() const +{ + return WindowTitle; +} \ No newline at end of file diff --git a/Plugins/DraggableWindow/Source/DraggableWindow/Public/SDraggableWindowWidget.h b/Plugins/DraggableWindow/Source/DraggableWindow/Public/SDraggableWindowWidget.h new file mode 100644 index 0000000..13e96bc --- /dev/null +++ b/Plugins/DraggableWindow/Source/DraggableWindow/Public/SDraggableWindowWidget.h @@ -0,0 +1,195 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Input/Events.h" +#include "Widgets/SCompoundWidget.h" +#include "SlateCore.h" +#include "Styling/SlateTypes.h" +#include "SOverlay.h" +#include "SGridPanel.h" +#include "SBox.h" +#include "SBorder.h" +#include "SButton.h" +#include "SConstraintCanvas.h" +#include "DWTypes.h" + +DECLARE_STATS_GROUP(TEXT("DraggebleWindow"), STATGROUP_DraggebleWindow, STATCAT_Advanced); + +enum class EDDWState : uint8 +{ + Dragging = 0, + HorizontalRight = 1, + HorizontalLeft = 2, + VerticalTop = 3, + VerticalBottom = 4, + DiagonalBottomRight = 5, + DiagonalBottomLeft = 6, + DiagonalTopRight = 7, + DiagonalTopLeft = 8, + + NoResize +}; +class DRAGGABLEWINDOW_API SDraggableDesktopWidget : public SCompoundWidget +{ + + SLATE_BEGIN_ARGS(SDraggableDesktopWidget) {} + SLATE_END_ARGS() +public: + friend class FDWManager; + friend class SDraggableWindowWidget; + /** Constructs this widget with InArgs */ + void Construct(const FArguments& InArgs); +protected: + TArray> Windows; + TSharedPtr Container; + void Clean(); + FDWWWindowHandle AddWindow(TSharedPtr InWindow); + void RemoveWindow(TSharedPtr InWindow); +}; + +class SWindowBox : public SPanel +{ +public: + class FBoxSlot : public TSupportsOneChildMixin, public TSupportsContentAlignmentMixin, public TSupportsContentPaddingMixin + { + public: + FBoxSlot(SWidget* InOwner) + : TSupportsOneChildMixin(nullptr) + , TSupportsContentAlignmentMixin(HAlign_Fill, VAlign_Fill) + { + } + }; + SLATE_BEGIN_ARGS(SWindowBox) + : _Content() + , _WidthOverride() + , _HeightOverride() + { + _Visibility = EVisibility::SelfHitTestInvisible; + } + SLATE_DEFAULT_SLOT(FArguments, Content) + /** When specified, ignore the content's desired size and report the WidthOverride as the Box's desired width. */ + SLATE_ATTRIBUTE(float, WidthOverride) + + /** When specified, ignore the content's desired size and report the HeightOverride as the Box's desired height. */ + SLATE_ATTRIBUTE(float, HeightOverride) + SLATE_END_ARGS() +private: + /** When specified, ignore the content's desired size and report the.WidthOverride as the Box's desired width. */ + float WidthOverride; + + /** When specified, ignore the content's desired size and report the.HeightOverride as the Box's desired height. */ + float HeightOverride; +protected: + + FBoxSlot ChildSlot; +public: + SWindowBox() + : ChildSlot(this) + {} + void Construct(const FArguments& InArgs); + /** See WidthOverride attribute */ + void SetWidthOverride(float InWidthOverride); + + /** See HeightOverride attribute */ + void SetHeightOverride(float InHeightOverride); +protected: + /** + * Panels arrange their children in a space described by the AllottedGeometry parameter. The results of the arrangement + * should be returned by appending a FArrangedWidget pair for every child widget. See StackPanel for an example + * + * @param AllottedGeometry The geometry allotted for this widget by its parent. + * @param ArrangedChildren The array to which to add the WidgetGeometries that represent the arranged children. + */ + virtual void OnArrangeChildren(const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren) const override; + // Begin SWidget overrides. + virtual FVector2D ComputeDesiredSize(float) const override; + + /** + * All widgets must provide a way to access their children in a layout-agnostic way. + * Panels store their children in Slots, which creates a dilemma. Most panels + * can store their children in a TPanelChildren, where the Slot class + * provides layout information about the child it stores. In that case + * GetChildren should simply return the TPanelChildren. See StackPanel for an example. + */ + virtual FChildren* GetChildren() override; +}; + +/** + * Check IF cursor is moving during resizing. + */ +class DRAGGABLEWINDOW_API SDraggableWindowWidget : public SCompoundWidget +{ + SLATE_BEGIN_ARGS(SDraggableWindowWidget){} + SLATE_ATTRIBUTE(bool, HideOnClose) + SLATE_END_ARGS() +public: + friend struct FDWWWindowHandle; + friend class SDraggableDesktopWidget; + friend class FDWManager; + bool bDestroyOnClose; +protected: + EDDWState ResizingState; + + FVector2D CurrentSize; + FVector2D CurrentCursorPosition; + FVector2D DragPosition; + FVector2D AbsPosition; + FVector2D AbsDragPosition; + + TSharedPtr Content; + TSharedPtr WindowBox; + float CurrentHeight; + float CurrentWidth; + FButtonStyle ButtonStyle; + TAttribute BackgroundColor; + TSharedPtr WindowBar; + FDWWWindowHandle Handle; + + FText WindowTitle; +public: + /** Constructs this widget with InArgs */ + void Construct(const FArguments& InArgs); + ~SDraggableWindowWidget(); +protected: + virtual FVector2D ComputeDesiredSize(float) const override; + virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; + + void AddContent(TSharedPtr InWidget); + + void SetHandle(const FDWWWindowHandle& InHandle); + void OnCloseButtonPressed(); + + void OnPressed(); + void OnReleased(); + + void OnHorizontalResizePressed(); + void OnHorizontalResizeReleased(); + void OnHorizontalResizeLeftPressed(); + void OnHorizontalResizeLeftReleased(); + + void OnVerticalTopResizePressed(); + void OnVerticalTopResizeReleased(); + void OnVerticalBottomResizePressed(); + void OnVerticalBottomResizeReleased(); + + void OnDirectionalResizePressed(); + void OnDirectionalResizeReleased(); + + void OnBottomRightResizePressed(); + void OnBottomRightResizeReleased(); + + void OnBottomLeftResizePressed(); + void OnBottomLeftResizeReleased(); + + void OnTopRightResizePressed(); + void OnTopRightResizeReleased(); + + void OnTopLeftResizePressed(); + void OnTopLeftResizeReleased(); + + FVector2D GetPosition() const; + + FText GetTitle() const; +}; diff --git a/Plugins/InventoryFramework/InventoryFramework.uplugin b/Plugins/InventoryFramework/InventoryFramework.uplugin new file mode 100644 index 0000000..a36617d --- /dev/null +++ b/Plugins/InventoryFramework/InventoryFramework.uplugin @@ -0,0 +1,29 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "InventoryFramework", + "Description": "", + "Category": "Gameplay", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": true, + "Installed": false, + "Modules": [ + { + "Name": "InventoryFramework", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ], + "Plugins": [ + { + "Name": "JsonUObject", + "Enabled": true + } + ] +} \ No newline at end of file diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/InventoryFramework.Build.cs b/Plugins/InventoryFramework/Source/InventoryFramework/InventoryFramework.Build.cs new file mode 100644 index 0000000..702f45e --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/InventoryFramework.Build.cs @@ -0,0 +1,50 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class InventoryFramework : ModuleRules +{ + public InventoryFramework(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "InventoryFramework/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "Json", + "JsonUtilities", + "JsonUObject" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFEquipmentComponent.cpp b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFEquipmentComponent.cpp new file mode 100644 index 0000000..d99a042 --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFEquipmentComponent.cpp @@ -0,0 +1,132 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "IFEquipmentComponent.h" +#include "IFInventoryComponent.h" + +// Sets default values for this component's properties +UIFEquipmentComponent::UIFEquipmentComponent() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = true; + + // ... +} + + +// Called when the game starts +void UIFEquipmentComponent::BeginPlay() +{ + uint8 Counter = 0; + for (uint8 Idx = 0; Idx < MaxSlots; Idx++) + { + FIFItemData NewItem; + NewItem.Item = nullptr; + NewItem.Index = Idx; + Counter++; + EquipmentItems.Add(NewItem); + } + Super::BeginPlay(); + + // ... + +} + + +// Called every frame +void UIFEquipmentComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // ... +} + +void UIFEquipmentComponent::AddItemFromInventory(class UIFInventoryComponent* Source, uint8 SourceIndex, uint8 EquipmentIndex) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + UIFItemBase* Item = Source->GetItem(SourceIndex); + OnClientPreItemAdded(Item, EquipmentIndex); + ServerAddItemFromInventory(Source, SourceIndex, EquipmentIndex); + } + else + { + UIFItemBase* Item = Source->GetItem(SourceIndex); + if (!Item) + return; + + EquipmentItems[EquipmentIndex].Item = DuplicateObject(Item, this); + + OnItemAdded(EquipmentItems[EquipmentIndex].Item, EquipmentIndex); + EquipmentItems[EquipmentIndex].Item->OnServerItemAddedEquipment(EquipmentItems[EquipmentIndex].Index); + + OnItemAddedEvent.Broadcast(EquipmentIndex, EquipmentIndex, EquipmentItems[EquipmentIndex].Item); + + } +} +void UIFEquipmentComponent::ServerAddItemFromInventory_Implementation(class UIFInventoryComponent* Source, uint8 SourceIndex, uint8 EquipmentIndex) +{ + UIFItemBase* Item = Source->GetItem(SourceIndex); + if (!Item) + return; + + EquipmentItems[EquipmentIndex].Item = DuplicateObject(Item, this); + OnServerItemAdded(EquipmentItems[EquipmentIndex].Item, EquipmentIndex); + EquipmentItems[EquipmentIndex].Item->OnServerItemAddedEquipment(EquipmentItems[EquipmentIndex].Index); + ClientAddItemFromInventory(Source, SourceIndex, EquipmentIndex); + OnItemAddedEvent.Broadcast(EquipmentIndex, EquipmentIndex, EquipmentItems[EquipmentIndex].Item); + +} +bool UIFEquipmentComponent::ServerAddItemFromInventory_Validate(class UIFInventoryComponent* Source, uint8 SourceIndex, uint8 EquipmentIndex) +{ + return true; +} +void UIFEquipmentComponent::ClientAddItemFromInventory_Implementation(class UIFInventoryComponent* Source, uint8 SourceIndex, uint8 EquipmentIndex) +{ + UIFItemBase* Item = Source->GetItem(SourceIndex); + if (!Item) + return; + + EquipmentItems[EquipmentIndex].Item = DuplicateObject(Item, this); + EquipmentItems[EquipmentIndex].Item->OnItemAddedEquipment(EquipmentItems[EquipmentIndex].Index); + OnItemAdded(EquipmentItems[EquipmentIndex].Item, EquipmentIndex); + OnItemAddedEvent.Broadcast(EquipmentIndex, EquipmentIndex, EquipmentItems[EquipmentIndex].Item); + Source->RemoveItem(SourceIndex); +} + + +void UIFEquipmentComponent::RemoveFromEquipment(uint8 EquipmentIndex) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + ServerRemoveFromEquipment(EquipmentIndex); + return; + } +} + +void UIFEquipmentComponent::ServerRemoveFromEquipment_Implementation(uint8 EquipmentIndex) +{ + EquipmentItems[EquipmentIndex].Item->OnServerItemRemovedEquipment(EquipmentItems[EquipmentIndex].Index); + if (EquipmentItems[EquipmentIndex].Item) + { + EquipmentItems[EquipmentIndex].Item->MarkPendingKill(); + } + EquipmentItems[EquipmentIndex].Item = nullptr; + ClientRemoveFromEquipment(EquipmentIndex); + OnServerItemRemoved(EquipmentIndex); +} +bool UIFEquipmentComponent::ServerRemoveFromEquipment_Validate(uint8 EquipmentIndex) +{ + return true; +} + +void UIFEquipmentComponent::ClientRemoveFromEquipment_Implementation(uint8 EquipmentIndex) +{ + EquipmentItems[EquipmentIndex].Item->OnItemRemovedEquipment(EquipmentItems[EquipmentIndex].Index); + if (EquipmentItems[EquipmentIndex].Item) + { + EquipmentItems[EquipmentIndex].Item->MarkPendingKill(); + } + EquipmentItems[EquipmentIndex].Item = nullptr; + OnItemRemoved(EquipmentIndex); +} \ No newline at end of file diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFInventoryComponent.cpp b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFInventoryComponent.cpp new file mode 100644 index 0000000..5310b43 --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFInventoryComponent.cpp @@ -0,0 +1,500 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "IFInventoryComponent.h" + +#include "GameFramework/Actor.h" +#include "Engine/AssetManager.h" + +#include "JsonUOSerialize.h" + +#include "JsonObjectConverter.h" + +#include "IFItemBase.h" +#include "IFItemActorBase.h" +#include "IFInventoryInterface.h" +#include "IFEquipmentComponent.h" +#include "Net/UnrealNetwork.h" +#include "Engine/ActorChannel.h" + + + +DEFINE_LOG_CATEGORY(IFLog); + + +// Sets default values for this component's properties +UIFInventoryComponent::UIFInventoryComponent() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = true; + bWantsInitializeComponent = true; + bAutoActivate = true; + bAutoRegister = true; + + MaxSlots = 8; + AvailableSlots = 8; + // ... +} + +void UIFInventoryComponent::InitializeComponent() +{ + Super::InitializeComponent(); +} + +// Called when the game starts +void UIFInventoryComponent::BeginPlay() +{ + Super::BeginPlay(); + uint8 Counter = 0; + for (uint8 Idx = 0; Idx < MaxSlots; Idx++) + { + FIFItemData NewItem; + NewItem.Item = nullptr; + NewItem.Index = Idx; + Counter++; + InventoryItems.Add(NewItem); + } + FakeBackend.SetNumZeroed(MaxSlots); + /* + Further steps + 2. Load Properties from external data source (JSON); + */ + // ... + +} + +// Called every frame +void UIFInventoryComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // ... +} + +TArray UIFInventoryComponent::GetLocalItemIdxs(TSubclassOf ItemClass) +{ + TArray Idxs; + for (uint8 Idx = 0; Idx < InventoryItems.Num(); Idx++) + { + if (InventoryItems[Idx].Item && InventoryItems[Idx].Item->IsA(ItemClass)) + { + Idxs.Add(Idx); + } + } + + return Idxs; + //return Inventory.GetLocalItemIdxs(ItemClass); +} + +bool UIFInventoryComponent::AcceptItem(UIFItemBase* Item, uint8 InLocaLIndex) +{ + bool bAccept = false; + + if (AcceptedClasses.Num() == 0) + { + bAccept = true; + } + else + { + for (TSubclassOf& ItemClass : AcceptedClasses) + { + bAccept = false; + if (Item->IsA(ItemClass)) + { + bAccept = true; + break; //no reason to check further. + } + } + } + + if (bAccept) + { + if (AcceptedSlotClasses.Num() == 0) + { + bAccept = true; + } + else + { + FIFSlotAcceptedClasses AC = AcceptedSlotClasses[InLocaLIndex]; + if (AC.AcceptedClasses.Num() == 0) + { + bAccept = true; + } + else + { + for (TSubclassOf& ItemClass : AC.AcceptedClasses) + { + bAccept = false; + if (Item->IsA(ItemClass)) + { + bAccept = true; + break; //no reason to check further. + } + } + } + } + + } + return bAccept; +} + +void UIFInventoryComponent::MoveItemInInventory(uint8 NewLocalPostion, uint8 OldLocalPositin) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + return; + } + + const FIFItemData& NewSlot = GetSlot(NewLocalPostion); + const FIFItemData& OldSlot = GetSlot(OldLocalPositin); +} + +void UIFInventoryComponent::ServerMoveItemInInventory_Implementation(uint8 NewNetPostion, uint8 OldNetPositin) +{ +} +bool UIFInventoryComponent::ServerMoveItemInInventory_Validate(uint8 NewNetPostion, uint8 OldNetPositin) +{ + return true; +} + +void UIFInventoryComponent::AddAllItemsFromActor(class AIFItemActorBase* Source) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + ServerAddAllItemsFromActor(Source); + return; + } + TArray> Items = Source->GetAllItems(); + Source->OnItemPicked(); + for (const TSoftClassPtr Item : Items) + { + FStreamableManager& Manager = UAssetManager::GetStreamableManager(); + + FStreamableDelegate Delegate = FStreamableDelegate::CreateUObject(this, &UIFInventoryComponent::OnItemLoadedFreeSlot, Item); + + Manager.RequestAsyncLoad(Item.ToSoftObjectPath(), Delegate); + } +} +void UIFInventoryComponent::ServerAddAllItemsFromActor_Implementation(class AIFItemActorBase* Source) +{ + TArray> Items = Source->GetAllItems(); + for (const TSoftClassPtr Item : Items) + { + FStreamableManager& Manager = UAssetManager::GetStreamableManager(); + + FStreamableDelegate Delegate = FStreamableDelegate::CreateUObject(this, &UIFInventoryComponent::OnItemLoadedFreeSlot, Item); + + Manager.RequestAsyncLoad(Item.ToSoftObjectPath(), Delegate); + } + Source->OnItemPicked(); +} +bool UIFInventoryComponent::ServerAddAllItemsFromActor_Validate(class AIFItemActorBase* Sourcex) +{ + return true; +} + + + +void UIFInventoryComponent::AddItemFromClass(TSoftClassPtr Item, uint8 InLocalIndex) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + return; + } +} +void UIFInventoryComponent::BP_AddAllItemsFromActor(class AIFItemActorBase* Source) +{ + AddAllItemsFromActor(Source); +} + + +void UIFInventoryComponent::ServerAddItemFromClass_Implementation(FSoftObjectPath Item, uint8 InNetIndex) +{ + FStreamableManager& Manager = UAssetManager::GetStreamableManager(); + TSoftClassPtr It(Item); + FStreamableDelegate Delegate = FStreamableDelegate::CreateUObject(this, &UIFInventoryComponent::OnItemLoaded, It, InNetIndex); + + UE_LOG(LogTemp, Warning, TEXT("ServerAddItemFromClass_Implementation %s"), *Item.ToString()); + Manager.RequestAsyncLoad(Item, Delegate); +} +bool UIFInventoryComponent::ServerAddItemFromClass_Validate(FSoftObjectPath Item, uint8 InNetIndex) +{ + return true; +} +void UIFInventoryComponent::BP_AddItemFromClass(TSoftClassPtr Item, uint8 InLocalIndex) +{ + AddItemFromClass(Item, InLocalIndex); +} + + +void UIFInventoryComponent::AddItemFromEquipment(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex) +{ + +} + +void UIFInventoryComponent::ServerAddItemFromEquipment_Implementation(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex) +{ + +} +bool UIFInventoryComponent::ServerAddItemFromEquipment_Validate(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex) +{ + return true; +} +void UIFInventoryComponent::ClientAddItemFromEquipment_Implementation(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex) +{ + +} + +void UIFInventoryComponent::AddItemFromEquipmentAnySlot(class UIFEquipmentComponent* Source, uint8 SourceIndex) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + UIFItemBase* Item = Source->GetItem(SourceIndex); + if (!Item) + return; + ServerAddItemFromEquipmentAnySlot(Source, SourceIndex); + return; + } +} +void UIFInventoryComponent::ServerAddItemFromEquipmentAnySlot_Implementation(class UIFEquipmentComponent* Source, uint8 SourceIndex) +{ + UIFItemBase* Item = Source->GetItem(SourceIndex); + if (!Item) + return; + + uint8 FreeSlot = 0; + for (uint8 Idx = 0; Idx < InventoryItems.Num(); Idx++) + { + if (InventoryItems[Idx].Item == nullptr) + { + FreeSlot = Idx; + break; + } + } + + InventoryItems[FreeSlot].Item = DuplicateObject(Item, this); + + InventoryItems[FreeSlot].Item->OnServerItemAdded(FreeSlot); + + OnServerItemAdded(InventoryItems[FreeSlot].Item, FreeSlot); + ClientAddItemFromEquipmentAnySlot(Source, SourceIndex, FreeSlot); + + TSharedPtr Obj = ItemToJson(&InventoryItems[FreeSlot]); + SendToBackend(Obj, FreeSlot); +} +bool UIFInventoryComponent::ServerAddItemFromEquipmentAnySlot_Validate(class UIFEquipmentComponent* Source, uint8 SourceIndex) +{ + return true; +} +void UIFInventoryComponent::ClientAddItemFromEquipmentAnySlot_Implementation(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex) +{ + UIFItemBase* Item = Source->GetItem(SourceIndex); + + InventoryItems[InventoryIndex].Item = DuplicateObject(Item, this); + + InventoryItems[InventoryIndex].Item->OnItemAdded(InventoryIndex); + OnItemAdded(InventoryItems[InventoryIndex].Item, InventoryIndex); + + Source->RemoveFromEquipment(SourceIndex); +} + +void UIFInventoryComponent::AddItemAnySlot(class UIFItemBase* Source) +{ + if (!Source) + return; + + uint8 FreeSlot = 0; + for (uint8 Idx = 0; Idx < InventoryItems.Num(); Idx++) + { + if (InventoryItems[Idx].Item == nullptr) + { + FreeSlot = Idx; + break; + } + } + + InventoryItems[FreeSlot].Item = DuplicateObject(Source, this); + Source->MarkPendingKill(); + + TSharedPtr Obj = ItemToJson(&InventoryItems[FreeSlot]); + SendToBackend(Obj, FreeSlot); + + FString OutputString = JsonItemToString(Obj); + + InventoryItems[FreeSlot].Item->OnServerItemAdded(FreeSlot); + OnServerItemAdded(InventoryItems[FreeSlot].Item, FreeSlot); + + ClientAddAnySlot(OutputString, FreeSlot); +} +void UIFInventoryComponent::ClientAddAnySlot_Implementation(const FString& JsonData, uint8 InventoryIndex) +{ + FIFItemData Item = JsonToItem(JsonData); + + if (Item.Item) + { + InventoryItems[InventoryIndex] = Item; + OnItemAddedEvent.Broadcast(InventoryIndex, InventoryIndex, Item.Item); + OnItemUpdatedEvent.Broadcast(InventoryIndex, InventoryIndex, Item.Item); + InventoryItems[Item.Index].Item->OnItemAdded(Item.Index); + OnItemAdded(InventoryItems[Item.Index].Item, Item.Index); + } +} + +void UIFInventoryComponent::RemoveItem(uint8 InIndex) +{ + if(GetOwnerRole() < ENetRole::ROLE_Authority) + { + ServerRemoveItem(InIndex); + return; + } + //remove from backend + OnItemRemoved(InventoryItems[InIndex].Item, InIndex); + if (InventoryItems[InIndex].Item) + InventoryItems[InIndex].Item->MarkPendingKill(); + + InventoryItems[InIndex].Item = nullptr; + ClientRemoveItem(InIndex); +} +void UIFInventoryComponent::ServerRemoveItem_Implementation(uint8 InIndex) +{ + OnServerItemRemoved(InventoryItems[InIndex].Item, InIndex); + InventoryItems[InIndex].Item->OnServerItemRemoved(InIndex); + if (InventoryItems[InIndex].Item) + InventoryItems[InIndex].Item->MarkPendingKill(); + + InventoryItems[InIndex].Item = nullptr; + + ClientRemoveItem(InIndex); +} +bool UIFInventoryComponent::ServerRemoveItem_Validate(uint8 InIndex) +{ + return true; +} +void UIFInventoryComponent::ClientRemoveItem_Implementation(uint8 InIndex) +{ + InventoryItems[InIndex].Item->OnItemRemoved(InIndex); + OnItemRemoved(InventoryItems[InIndex].Item, InIndex); + if (InventoryItems[InIndex].Item) + InventoryItems[InIndex].Item->MarkPendingKill(); + + InventoryItems[InIndex].Item = nullptr; + +} +void UIFInventoryComponent::OnItemLoadedFreeSlot(TSoftClassPtr InItem) +{ + + uint8 FreeIndex = 0; + + for (uint8 Idx = 0; Idx < InventoryItems.Num(); Idx++) + { + if (!InventoryItems[Idx].Item) + { + FreeIndex = Idx; + break; + } + } + AddItem(InItem, FreeIndex); +} +void UIFInventoryComponent::OnItemLoaded(TSoftClassPtr InItem, uint8 InNetIndex) +{ + AddItem(InItem, InNetIndex); +} + +void UIFInventoryComponent::ClientSendJsonData_Implementation(const FString& Data) +{ + FIFItemData Item = JsonToItem(Data); + Item.Item->ClientPostItemDeserializeFromJson(); + if (Item.Item) + { + Item.Item->OnItemAdded(Item.Index); + + InventoryItems[Item.Index] = Item; + OnItemAddedEvent.Broadcast(Item.Index, Item.Index, Item.Item); + OnItemUpdatedEvent.Broadcast(Item.Index, Item.Index, Item.Item); + + OnItemAdded(InventoryItems[Item.Index].Item, Item.Index); + } +} + +void UIFInventoryComponent::AddItem(TSoftClassPtr InItem, uint8 ItemIndex) +{ + TSubclassOf ItemClass = InItem.Get(); + FIFItemData Item; + Item.Index = ItemIndex; + Item.Item = NewObject(this, ItemClass); + Item.Item->OnServerItemLoaded(); + + InventoryItems[Item.Index] = Item; + InventoryItems[Item.Index].Item->OnServerItemAdded(Item.Index); + OnServerItemAdded(InventoryItems[Item.Index].Item, Item.Index); + + TSharedPtr Obj = ItemToJson(&InventoryItems[Item.Index]); + SendToBackend(Obj, Item.Index); + + FString OutputString = JsonItemToString(Obj); + + UE_LOG(IFLog, Log, TEXT("ItemLoaded %s "), *OutputString); + ClientSendJsonData(OutputString); + + FStreamableManager& Manager = UAssetManager::GetStreamableManager(); + Manager.Unload(InItem.ToSoftObjectPath()); +} + +TSharedPtr UIFInventoryComponent::ItemToJson(FIFItemData* Item) +{ + typedef TJsonWriter< TCHAR, TPrettyJsonPrintPolicy > FPrettyJsonStringWriter; + typedef TJsonWriterFactory< TCHAR, TPrettyJsonPrintPolicy > FPrettyJsonStringWriterFactory; + + TSharedPtr Obj = MakeShareable(new FJsonObject()); + TSharedPtr UObj = MakeShareable(new FJsonObject()); + if (Item->Item) + { + Item->Item->PreItemSerializeToJson(); + FJsonUOSerialize::UObjectToJsonObject(Item->Item->GetClass(), Item->Item, UObj.ToSharedRef()); + //UObj = Item->Item->SaveToJson(); + } + Obj->Values.Add(FString("index"), MakeShareable(new FJsonValueNumber(Item->Index))); + Obj->Values.Add(FString("item"), MakeShareable(new FJsonValueObject(UObj))); + FakeBackend[Item->Index] = Obj; + + return Obj; +} +FString UIFInventoryComponent::JsonItemToString(TSharedPtr Object) +{ + typedef TJsonWriter< TCHAR, TPrettyJsonPrintPolicy > FPrettyJsonStringWriter; + typedef TJsonWriterFactory< TCHAR, TPrettyJsonPrintPolicy > FPrettyJsonStringWriterFactory; + + FString OutputString; + TSharedRef< FPrettyJsonStringWriter > Writer = FPrettyJsonStringWriterFactory::Create(&OutputString); + check(FJsonSerializer::Serialize(Object.ToSharedRef(), Writer)); + + return OutputString; +} +void UIFInventoryComponent::SendToBackend(TSharedPtr JsonObj, int32 Idx) +{ + FakeBackend[Idx] = JsonObj; +} + +FIFItemData UIFInventoryComponent::JsonToItem(const FString& JsonString) +{ + TSharedRef< TJsonReader<> > Reader = TJsonReaderFactory<>::Create(JsonString); + + TSharedPtr Object = MakeShareable(new FJsonObject()); + + bool bSuccessful = FJsonSerializer::Deserialize(Reader, Object); + + TSharedPtr itemField = Object->GetObjectField("item"); + FString objClassStr = itemField->GetStringField("objectClass"); + int32 idx = Object->GetIntegerField("index"); + + FSoftClassPath path(objClassStr); + + UClass* itemCls = Cast(path.TryLoad()); + UObject* OutObj = nullptr; + FIFJsonSerializer::JsonObjectToUObject(itemField, OutObj, this); + FIFItemData Item; + Item.Index = idx; + Item.Item = Cast(OutObj); + + return Item; +} \ No newline at end of file diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFInventoryInterface.cpp b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFInventoryInterface.cpp new file mode 100644 index 0000000..7846e17 --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFInventoryInterface.cpp @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "IFInventoryInterface.h" + + +// Add default functionality here for any IIFInventoryInterface functions that are not pure virtual. diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFItemActorBase.cpp b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFItemActorBase.cpp new file mode 100644 index 0000000..9401e9d --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFItemActorBase.cpp @@ -0,0 +1,41 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "IFItemActorBase.h" +#include "IFInventoryComponent.h" + +// Sets default values +AIFItemActorBase::AIFItemActorBase() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + bReplicates = true; +} + +// Called when the game starts or when spawned +void AIFItemActorBase::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void AIFItemActorBase::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + +TArray> AIFItemActorBase::GetAllItems() +{ + Destroy(); + return Items; +} + +void AIFItemActorBase::GiveAllItemsToInstigator(class UIFInventoryComponent* Inventory) +{ + Inventory->AddAllItemsFromActor(this); +} +void AIFItemActorBase::BP_GiveAllItemsToInstigator(class UIFInventoryComponent* Inventory) +{ + GiveAllItemsToInstigator(Inventory); +} \ No newline at end of file diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFItemBase.cpp b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFItemBase.cpp new file mode 100644 index 0000000..01d12e1 --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFItemBase.cpp @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "IFItemBase.h" + +#include "Engine/NetDriver.h" +#include "GameFramework/Actor.h" +#include "IFInventoryComponent.h" + +bool UIFItemBase::CallRemoteFunction(UFunction* Function, void* Parameters, FOutParmRec* OutParms, FFrame* Stack) +{ + check(!HasAnyFlags(RF_ClassDefaultObject)); + check(GetOuter() != NULL); + + UIFInventoryComponent* Owner = CastChecked(GetOuter()); + UNetDriver* NetDriver = Owner->GetOwner()->GetNetDriver(); + if (NetDriver) + { + NetDriver->ProcessRemoteFunction(Owner->GetOwner(), Function, Parameters, OutParms, Stack, this); + return true; + } + + return false; +} + diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFTypes.cpp b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFTypes.cpp new file mode 100644 index 0000000..0f425c7 --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Private/IFTypes.cpp @@ -0,0 +1,473 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "IFTypes.h" +#include "JsonObjectConverter.h" + + +bool FIFJsonSerializer::ConvertScalarJsonValueToUProperty(TSharedPtr JsonValue, UProperty* Property, void* OutValue) +{ + if (UEnumProperty* EnumProperty = Cast(Property)) + { + if (JsonValue->Type == EJson::String) + { + // see if we were passed a string for the enum + const UEnum* Enum = EnumProperty->GetEnum(); + check(Enum); + FString StrValue = JsonValue->AsString(); + int64 IntValue = Enum->GetValueByName(FName(*StrValue)); + if (IntValue == INDEX_NONE) + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Unable import enum %s from string value %s for property %s"), *Enum->CppType, *StrValue, *Property->GetNameCPP()); + return false; + } + EnumProperty->GetUnderlyingProperty()->SetIntPropertyValue(OutValue, IntValue); + } + else + { + // AsNumber will log an error for completely inappropriate types (then give us a default) + EnumProperty->GetUnderlyingProperty()->SetIntPropertyValue(OutValue, (int64)JsonValue->AsNumber()); + } + } + else if (UNumericProperty *NumericProperty = Cast(Property)) + { + if (NumericProperty->IsEnum() && JsonValue->Type == EJson::String) + { + // see if we were passed a string for the enum + const UEnum* Enum = NumericProperty->GetIntPropertyEnum(); + check(Enum); // should be assured by IsEnum() + FString StrValue = JsonValue->AsString(); + int64 IntValue = Enum->GetValueByName(FName(*StrValue)); + if (IntValue == INDEX_NONE) + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Unable import enum %s from string value %s for property %s"), *Enum->CppType, *StrValue, *Property->GetNameCPP()); + return false; + } + NumericProperty->SetIntPropertyValue(OutValue, IntValue); + } + else if (NumericProperty->IsFloatingPoint()) + { + // AsNumber will log an error for completely inappropriate types (then give us a default) + NumericProperty->SetFloatingPointPropertyValue(OutValue, JsonValue->AsNumber()); + } + else if (NumericProperty->IsInteger()) + { + if (JsonValue->Type == EJson::String) + { + // parse string -> int64 ourselves so we don't lose any precision going through AsNumber (aka double) + NumericProperty->SetIntPropertyValue(OutValue, FCString::Atoi64(*JsonValue->AsString())); + } + else + { + // AsNumber will log an error for completely inappropriate types (then give us a default) + NumericProperty->SetIntPropertyValue(OutValue, (int64)JsonValue->AsNumber()); + } + } + else + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Unable to set numeric property type %s for property %s"), *Property->GetClass()->GetName(), *Property->GetNameCPP()); + return false; + } + } + else if (UBoolProperty *BoolProperty = Cast(Property)) + { + // AsBool will log an error for completely inappropriate types (then give us a default) + BoolProperty->SetPropertyValue(OutValue, JsonValue->AsBool()); + } + else if (UStrProperty *StringProperty = Cast(Property)) + { + // AsString will log an error for completely inappropriate types (then give us a default) + StringProperty->SetPropertyValue(OutValue, JsonValue->AsString()); + } + else if (UArrayProperty *ArrayProperty = Cast(Property)) + { + if (JsonValue->Type == EJson::Array) + { + TArray< TSharedPtr > ArrayValue = JsonValue->AsArray(); + int32 ArrLen = ArrayValue.Num(); + + // make the output array size match + FScriptArrayHelper Helper(ArrayProperty, OutValue); + Helper.Resize(ArrLen); + + // set the property values + for (int32 i = 0; i& ArrayValueItem = ArrayValue[i]; + if (ArrayValueItem.IsValid() && !ArrayValueItem->IsNull()) + { + if (!JsonValueToUProperty(ArrayValueItem, ArrayProperty->Inner, Helper.GetRawPtr(i))) + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Unable to deserialize array element [%d] for property %s"), i, *Property->GetNameCPP()); + return false; + } + } + } + } + else + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Attempted to import TArray from non-array JSON key for property %s"), *Property->GetNameCPP()); + return false; + } + } + else if (UMapProperty* MapProperty = Cast(Property)) + { + if (JsonValue->Type == EJson::Object) + { + TSharedPtr ObjectValue = JsonValue->AsObject(); + + FScriptMapHelper Helper(MapProperty, OutValue); + + // set the property values + for (const auto& Entry : ObjectValue->Values) + { + if (Entry.Value.IsValid() && !Entry.Value->IsNull()) + { + int32 NewIndex = Helper.AddDefaultValue_Invalid_NeedsRehash(); + + TSharedPtr TempKeyValue = MakeShareable(new FJsonValueString(Entry.Key)); + + const bool bKeySuccess = JsonValueToUProperty(TempKeyValue, MapProperty->KeyProp, Helper.GetKeyPtr(NewIndex)); + const bool bValueSuccess = JsonValueToUProperty(Entry.Value, MapProperty->ValueProp, Helper.GetValuePtr(NewIndex)); + + if (!(bKeySuccess && bValueSuccess)) + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Unable to deserialize map element [key: %s] for property %s"), *Entry.Key, *Property->GetNameCPP()); + return false; + } + } + } + + Helper.Rehash(); + } + else + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Attempted to import TMap from non-object JSON key for property %s"), *Property->GetNameCPP()); + return false; + } + } + else if (USetProperty* SetProperty = Cast(Property)) + { + if (JsonValue->Type == EJson::Array) + { + TArray< TSharedPtr > ArrayValue = JsonValue->AsArray(); + int32 ArrLen = ArrayValue.Num(); + + FScriptSetHelper Helper(SetProperty, OutValue); + + // set the property values + for (int32 i = 0; i < ArrLen; ++i) + { + const TSharedPtr& ArrayValueItem = ArrayValue[i]; + if (ArrayValueItem.IsValid() && !ArrayValueItem->IsNull()) + { + int32 NewIndex = Helper.AddDefaultValue_Invalid_NeedsRehash(); + if (!JsonValueToUProperty(ArrayValueItem, SetProperty->ElementProp, Helper.GetElementPtr(NewIndex))) + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Unable to deserialize set element [%d] for property %s"), i, *Property->GetNameCPP()); + return false; + } + } + } + + Helper.Rehash(); + } + else + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Attempted to import TSet from non-array JSON key for property %s"), *Property->GetNameCPP()); + return false; + } + } + else if (UTextProperty* TextProperty = Cast(Property)) + { + if (JsonValue->Type == EJson::String) + { + // assume this string is already localized, so import as invariant + TextProperty->SetPropertyValue(OutValue, FText::FromString(JsonValue->AsString())); + } + else if (JsonValue->Type == EJson::Object) + { + TSharedPtr Obj = JsonValue->AsObject(); + check(Obj.IsValid()); // should not fail if Type == EJson::Object + + // import the subvalue as a culture invariant string + FText Text; + if (!FJsonObjectConverter::GetTextFromObject(Obj.ToSharedRef(), Text)) + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Attempted to import FText from JSON object with invalid keys for property %s"), *Property->GetNameCPP()); + return false; + } + TextProperty->SetPropertyValue(OutValue, Text); + } + else + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Attempted to import FText from JSON that was neither string nor object for property %s"), *Property->GetNameCPP()); + return false; + } + } + else if (UStructProperty *StructProperty = Cast(Property)) + { + static const FName NAME_DateTime(TEXT("DateTime")); + static const FName NAME_Color(TEXT("Color")); + static const FName NAME_LinearColor(TEXT("LinearColor")); + if (JsonValue->Type == EJson::Object) + { + TSharedPtr Obj = JsonValue->AsObject(); + check(Obj.IsValid()); // should not fail if Type == EJson::Object + if (!JsonObjectToUStruct(Obj.ToSharedRef(), StructProperty->Struct, OutValue)) + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - FJsonObjectConverter::JsonObjectToUStruct failed for property %s"), *Property->GetNameCPP()); + return false; + } + } + else if (JsonValue->Type == EJson::String && StructProperty->Struct->GetFName() == NAME_LinearColor) + { + FLinearColor& ColorOut = *(FLinearColor*)OutValue; + FString ColorString = JsonValue->AsString(); + + FColor IntermediateColor; + IntermediateColor = FColor::FromHex(ColorString); + + ColorOut = IntermediateColor; + } + else if (JsonValue->Type == EJson::String && StructProperty->Struct->GetFName() == NAME_Color) + { + FColor& ColorOut = *(FColor*)OutValue; + FString ColorString = JsonValue->AsString(); + + ColorOut = FColor::FromHex(ColorString); + } + else if (JsonValue->Type == EJson::String && StructProperty->Struct->GetFName() == NAME_DateTime) + { + FString DateString = JsonValue->AsString(); + FDateTime& DateTimeOut = *(FDateTime*)OutValue; + if (DateString == TEXT("min")) + { + // min representable value for our date struct. Actual date may vary by platform (this is used for sorting) + DateTimeOut = FDateTime::MinValue(); + } + else if (DateString == TEXT("max")) + { + // max representable value for our date struct. Actual date may vary by platform (this is used for sorting) + DateTimeOut = FDateTime::MaxValue(); + } + else if (DateString == TEXT("now")) + { + // this value's not really meaningful from json serialization (since we don't know timezone) but handle it anyway since we're handling the other keywords + DateTimeOut = FDateTime::UtcNow(); + } + else if (FDateTime::ParseIso8601(*DateString, DateTimeOut)) + { + // ok + } + else if (FDateTime::Parse(DateString, DateTimeOut)) + { + // ok + } + else + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Unable to import FDateTime for property %s"), *Property->GetNameCPP()); + return false; + } + } + else if (JsonValue->Type == EJson::String && StructProperty->Struct->GetCppStructOps() && StructProperty->Struct->GetCppStructOps()->HasImportTextItem()) + { + UScriptStruct::ICppStructOps* TheCppStructOps = StructProperty->Struct->GetCppStructOps(); + + FString ImportTextString = JsonValue->AsString(); + const TCHAR* ImportTextPtr = *ImportTextString; + if (!TheCppStructOps->ImportTextItem(ImportTextPtr, OutValue, PPF_None, nullptr, (FOutputDevice*)GWarn)) + { + // Fall back to trying the tagged property approach if custom ImportTextItem couldn't get it done + Property->ImportText(ImportTextPtr, OutValue, PPF_None, nullptr); + } + } + else if (JsonValue->Type == EJson::String) + { + FString ImportTextString = JsonValue->AsString(); + const TCHAR* ImportTextPtr = *ImportTextString; + Property->ImportText(ImportTextPtr, OutValue, PPF_None, nullptr); + } + else + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Attempted to import UStruct from non-object JSON key for property %s"), *Property->GetNameCPP()); + return false; + } + } + else + { + // Default to expect a string for everything else + if (Property->ImportText(*JsonValue->AsString(), OutValue, 0, NULL) == NULL) + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Unable import property type %s from string value for property %s"), *Property->GetClass()->GetName(), *Property->GetNameCPP()); + return false; + } + } + + return true; +} + +bool FIFJsonSerializer::JsonValueToUProperty(TSharedPtr JsonValue, UProperty* Property, void* OutValue) +{ + if (!JsonValue.IsValid()) + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Invalid value JSON key")); + return false; + } + + bool bArrayOrSetProperty = Property->IsA() || Property->IsA(); + bool bJsonArray = JsonValue->Type == EJson::Array; + + if (!bJsonArray) + { + if (bArrayOrSetProperty) + { + UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Attempted to import TArray from non-array JSON key")); + return false; + } + + if (Property->ArrayDim != 1) + { + UE_LOG(LogJson, Warning, TEXT("Ignoring excess properties when deserializing %s"), *Property->GetName()); + } + + return ConvertScalarJsonValueToUProperty(JsonValue, Property, OutValue); + } + + // In practice, the ArrayDim == 1 check ought to be redundant, since nested arrays of UPropertys are not supported + if (bArrayOrSetProperty && Property->ArrayDim == 1) + { + // Read into TArray + return ConvertScalarJsonValueToUProperty(JsonValue, Property, OutValue); + } + + // We're deserializing a JSON array + const auto& ArrayValue = JsonValue->AsArray(); + if (Property->ArrayDim < ArrayValue.Num()) + { + UE_LOG(LogJson, Warning, TEXT("Ignoring excess properties when deserializing %s"), *Property->GetName()); + } + + // Read into native array + int ItemsToRead = FMath::Clamp(ArrayValue.Num(), 0, Property->ArrayDim); + for (int Index = 0; Index != ItemsToRead; ++Index) + { + if (!ConvertScalarJsonValueToUProperty(ArrayValue[Index], Property, (char*)OutValue + Index * Property->ElementSize)) + { + return false; + } + } + return true; +} + +bool FIFJsonSerializer::JsonAttributesToUObject(const TMap< FString, TSharedPtr >& JsonAttributes, const UStruct* StructDefinition, void* OutStruct) +{ + // iterate over the struct properties + for (TFieldIterator PropIt(StructDefinition); PropIt; ++PropIt) + { + UProperty* Property = *PropIt; + FString PropertyName = Property->GetName(); + + // find a json value matching this property name + TSharedPtr JsonValue; + for (auto It = JsonAttributes.CreateConstIterator(); It; ++It) + { + // use case insensitive search sincd FName may change caseing strangely on us + if (PropertyName.Equals(It.Key(), ESearchCase::IgnoreCase)) + { + JsonValue = It.Value(); + break; + } + } + if (!JsonValue.IsValid() || JsonValue->IsNull()) + { + // we allow values to not be found since this mirrors the typical UObject mantra that all the fields are optional when deserializing + continue; + } + + void* Value = Property->ContainerPtrToValuePtr(OutStruct); + if (!JsonValueToUProperty(JsonValue, Property, Value)) + { + UE_LOG(LogJson, Error, TEXT("JsonObjectToUStruct - Unable to parse %s.%s from JSON"), *StructDefinition->GetName(), *PropertyName); + return false; + } + } + + return true; +} + +bool FIFJsonSerializer::JsonObjectToUStruct(const TSharedRef& JsonObject, const UStruct* StructDefinition, void* OutStruct) +{ + return JsonAttributesToUObject(JsonObject->Values, StructDefinition, OutStruct); +} + +void FIFJsonSerializer::JsonObjectToUObject(TSharedPtr Object, UObject*& OutObject, UObject* Outer) +{ + FString objClassStr = Object->GetStringField("objectClass"); + + FSoftClassPath path(objClassStr); + + UClass* itemCls = Cast(path.TryLoad()); + if (itemCls) + { + OutObject = NewObject(Outer, itemCls); + for (TFieldIterator PropIt(itemCls); PropIt; ++PropIt) + { + UProperty* Property = *PropIt; + FString PropertyName = Property->GetName(); + TSharedPtr JsonValue; + for (auto It = Object->Values.CreateConstIterator(); It; ++It) + { + // use case insensitive search sincd FName may change caseing strangely on us + if (PropertyName.Equals(It.Key(), ESearchCase::IgnoreCase)) + { + JsonValue = It.Value(); + break; + } + } + if (!JsonValue.IsValid()) + continue; + + if(UObjectProperty* ObjectProp = Cast(Property)) + { + const TSharedPtr* Obj; + JsonValue->TryGetObject(Obj); + + if (Obj) + { + TSharedPtr Objj = *Obj; + + //TSharedPtr itemField = Objj->GetObjectField("item"); + FString objClassStr2 = Objj->GetStringField("objectClass"); + if (objClassStr2.Len() > 0) + { + FSoftClassPath pathLocal(objClassStr2); + UClass* itemClsLocal = Cast(pathLocal.TryLoad()); + UObject* Out = nullptr; + JsonObjectToUObject(Objj, Out, OutObject); + ObjectProp->SetObjectPropertyValue_InContainer(OutObject, Out); + } + } + } + else if(UStructProperty* StructProp = Cast(Property)) + { + void* Value = StructProp->ContainerPtrToValuePtr(OutObject); + if (!JsonValue->AsObject()) + continue; + + JsonAttributesToUObject(JsonValue->AsObject()->Values, StructProp->Struct, Value); + } + else + { + void* Value = Property->ContainerPtrToValuePtr(OutObject); + ConvertScalarJsonValueToUProperty(JsonValue, Property, Value); + } + } + } +} +IFTypes::IFTypes() +{ +} + +IFTypes::~IFTypes() +{ +} diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Private/InventoryFramework.cpp b/Plugins/InventoryFramework/Source/InventoryFramework/Private/InventoryFramework.cpp new file mode 100644 index 0000000..365f1d3 --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Private/InventoryFramework.cpp @@ -0,0 +1,22 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "InventoryFramework.h" + + + +#define LOCTEXT_NAMESPACE "FInventoryFrameworkModule" + +void FInventoryFrameworkModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FInventoryFrameworkModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FInventoryFrameworkModule, InventoryFramework) \ No newline at end of file diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFEquipmentComponent.h b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFEquipmentComponent.h new file mode 100644 index 0000000..f16fb4a --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFEquipmentComponent.h @@ -0,0 +1,104 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "IFTypes.h" +#include "IFItemBase.h" +#include "IFEquipmentComponent.generated.h" + + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class INVENTORYFRAMEWORK_API UIFEquipmentComponent : public UActorComponent +{ + GENERATED_BODY() +protected: + UPROPERTY() + TArray EquipmentItems; + + + UPROPERTY(EditAnywhere, Category = "Inventory") + uint8 MaxSlots; + + /* + Currently available slots (must be smaller or equal to max slots); + */ + UPROPERTY(EditAnywhere, Category = "Inventory") + uint8 AvailableSlots; + + FIFItemEvent OnItemAddedEvent; + FIFItemEvent OnItemUpdatedEvent; + FIFItemEvent OnItemRemovedEvent; + +public: + // Sets default values for this component's properties + UIFEquipmentComponent(); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + inline UIFItemBase* GetItem(uint8 InLocalIndex) + { + return EquipmentItems[InLocalIndex].Item; + //return Inventory.Items[InLocalIndex].Item; + } + template + T* GetItem(uint8 InLocalIndex) + { + if (EquipmentItems.IsValidIndex(InLocalIndex)) + { + return Cast(EquipmentItems[InLocalIndex].Item); + } + else + { + return nullptr; + } + //return Cast(Inventory.Items[InLocalIndex].Item); + } + + void AddItemFromInventory(class UIFInventoryComponent* Source, uint8 SourceIndex, uint8 EquipmentIndex); + UFUNCTION(Server, Reliable, WithValidation) + void ServerAddItemFromInventory(class UIFInventoryComponent* Source, uint8 SourceIndex, uint8 EquipmentIndex); + void ServerAddItemFromInventory_Implementation(class UIFInventoryComponent* Source, uint8 SourceIndex, uint8 EquipmentIndex); + bool ServerAddItemFromInventory_Validate(class UIFInventoryComponent* Source, uint8 SourceIndex, uint8 EquipmentIndex); + /* + Confirm that change can be made and do the same change on client. + We do not predict inventory modifications. Clients MUST wait for server to make changes and send confirmation back. + */ + UFUNCTION(Client, Reliable) + void ClientAddItemFromInventory(class UIFInventoryComponent* Source, uint8 SourceIndex, uint8 EquipmentIndex); + void ClientAddItemFromInventory_Implementation(class UIFInventoryComponent* Source, uint8 SourceIndex, uint8 EquipmentIndex); + + void RemoveFromEquipment(uint8 EquipmentIndex); + UFUNCTION(Server, Reliable, WithValidation) + void ServerRemoveFromEquipment(uint8 EquipmentIndex); + void ServerRemoveFromEquipment_Implementation(uint8 EquipmentIndex); + bool ServerRemoveFromEquipment_Validate(uint8 EquipmentIndex); + UFUNCTION(Client, Reliable) + void ClientRemoveFromEquipment(uint8 EquipmentIndex); + void ClientRemoveFromEquipment_Implementation(uint8 EquipmentIndex); + + /* + Called on client, before request to server is send to add item to Equipment component. + Not called in standalone. + */ + virtual void OnClientPreItemAdded(UIFItemBase* Item, uint8 Index) {}; + virtual void OnItemAdded(UIFItemBase* Item, uint8 Index) {}; + virtual void OnItemChanged(UIFItemBase* Item, uint8 Index) {}; + virtual void OnItemRemoved(uint8 Index) {}; + + //called only on server. + virtual void OnServerItemAdded(UIFItemBase* Item, uint8 LocalIndex) {}; + virtual void OnServerItemChanged(UIFItemBase* Item, uint8 LocalIndex) {}; + virtual void OnServerItemRemoved(uint8 LocalIndex) {}; + + inline FIFItemEvent& GetOnItemAdded() { return OnItemAddedEvent; } + inline FIFItemEvent& GetOnItemUpdated() { return OnItemUpdatedEvent; } + inline FIFItemEvent& GetOnItemRemoved() { return OnItemRemovedEvent; } +}; diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFInventoryComponent.h b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFInventoryComponent.h new file mode 100644 index 0000000..c9069f6 --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFInventoryComponent.h @@ -0,0 +1,243 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + +#include "Components/ActorComponent.h" +#include "IFTypes.h" +#include "IFItemBase.h" +#include "IFInventoryComponent.generated.h" + +//NetIndex, LocalIndex + +DECLARE_LOG_CATEGORY_EXTERN(IFLog, Log, All); + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class INVENTORYFRAMEWORK_API UIFInventoryComponent : public UActorComponent +{ + GENERATED_BODY() + friend struct FIFItemContainer; + friend struct FIFItemData; +protected: + + FIFItemEvent OnItemAddedEvent; + FIFItemEvent OnItemUpdatedEvent; + FIFItemEvent OnItemRemovedEvent; + FIFOnInventoryChanged OnInventoryChanged; + + /* Array faking an database backend (where data is stored as json like DynamoDB, GameSparks, CosmosDB, MongoDB */ + TArray> FakeBackend; + + /* Key is deserialized from Json and it stored in backend. */ + //UPROPERTY() + // TMap InventoryItems; + + + UPROPERTY() + TArray InventoryItems; + /* + Which items this inventory accept. + */ + UPROPERTY(EditAnywhere, Category = "Inventory") + TArray> AcceptedClasses; + + /* + Which items slot will accept. + + Order is Equvalent to slot order on server. + */ + UPROPERTY(EditAnywhere, Category = "Inventory") + TArray AcceptedSlotClasses; + + UPROPERTY(EditAnywhere, Category = "Inventory") + uint8 MaxSlots; + + /* + Currently available slots (must be smaller or equal to max slots); + */ + UPROPERTY(EditAnywhere, Category = "Inventory") + uint8 AvailableSlots; + + /* Called when all alots are created */ + FSimpleMulticastDelegate OnInventoryReady; + +public: + // Sets default values for this component's properties + UIFInventoryComponent(); + +protected: + virtual void InitializeComponent() override;; + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + void InitializeInventory(); + + inline FIFItemEvent& GetOnItemAdded() { return OnItemAddedEvent; } + inline FIFItemEvent& GetOnItemUpdated() { return OnItemUpdatedEvent; } + inline FIFItemEvent& GetOnItemRemoved() { return OnItemRemovedEvent; } + + inline uint8 GetMaxSlots() + { + return MaxSlots; + } + + inline const FIFItemData& GetSlot(uint8 Idx) + { + return InventoryItems[Idx];; + } + + inline UIFItemBase* GetItem(uint8 InLocalIndex) + { + return InventoryItems[InLocalIndex].Item; + //return Inventory.Items[InLocalIndex].Item; + } + template + T* GetItem(uint8 InLocalIndex) + { + return Cast(InventoryItems[InLocalIndex].Item); + //return Cast(Inventory.Items[InLocalIndex].Item); + } + + TArray GetLocalItemIdxs(TSubclassOf ItemClass); + + template + TArray GetItems(TSubclassOf ItemClass) + { + TArray Items; + TArray Idxs; + for (uint8 Idx = 0; Idx < InventoryItems.Num(); Idx++) + { + if (InventoryItems[Idx].Item && InventoryItems[Idx].Item->IsA(ItemClass)) + { + Items.Add(Cast(InventoryItems[Idx].Item)); + } + } + + return Items; + //return Inventory.GetItems(ItemClass); + } + + /* + Check if item can be droped/added to this inventory/slot. + First check if inventory accepts, If it passes it will check slot. + */ + bool AcceptItem(UIFItemBase* Item, uint8 InLocaLIndex); + /* + Move item from old position to new position. + If there was already item in new position it will be swapped with the moved item; + */ + void MoveItemInInventory(uint8 NewLocalPostion, uint8 OldLocalPositin); + + UFUNCTION(Server, Reliable, WithValidation) + void ServerMoveItemInInventory(uint8 NewNetPostion, uint8 OldNetPositin); + void ServerMoveItemInInventory_Implementation(uint8 NewNetPostion, uint8 OldNetPositin); + bool ServerMoveItemInInventory_Validate(uint8 NewNetPostion, uint8 OldNetPositin); + /* + Adds new item at slot specified slot + Source - Droped item from which we will transfer item + SourceIndex - Index + */ + void AddAllItemsFromActor(class AIFItemActorBase* Source); + + UFUNCTION(Server, Reliable, WithValidation) + void ServerAddAllItemsFromActor(class AIFItemActorBase* Source); + void ServerAddAllItemsFromActor_Implementation(class AIFItemActorBase* Source); + bool ServerAddAllItemsFromActor_Validate(class AIFItemActorBase* Source); + UFUNCTION(BlueprintCallable, Category = "InventoryFramework") + void BP_AddAllItemsFromActor(class AIFItemActorBase* Source); + + /* Adds item from class. Realistically you should never call it on client. */ + void AddItemFromClass(TSoftClassPtr Item, uint8 InLocalIndex); + + UFUNCTION(Server, Reliable, WithValidation) + void ServerAddItemFromClass(const FSoftObjectPath& Item, uint8 InLocalIndex); + + void ServerAddItemFromClass_Implementation(FSoftObjectPath Item, uint8 InNetIndex); + bool ServerAddItemFromClass_Validate(FSoftObjectPath Item, uint8 InNetIndex); + UFUNCTION(BlueprintCallable, Category = "InventoryFramework") + void BP_AddItemFromClass(TSoftClassPtr Item, uint8 InLocalIndex); + + + void AddItemFromEquipment(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex); + UFUNCTION(Server, Reliable, WithValidation) + void ServerAddItemFromEquipment(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex); + void ServerAddItemFromEquipment_Implementation(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex); + bool ServerAddItemFromEquipment_Validate(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex); + /* + Confirm that change can be made and do the same change on client. + We do not predict inventory modifications. Clients MUST wait for server to make changes and send confirmation back. + */ + UFUNCTION(Client, Reliable) + void ClientAddItemFromEquipment(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex); + void ClientAddItemFromEquipment_Implementation(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex); + + void AddItemFromEquipmentAnySlot(class UIFEquipmentComponent* Source, uint8 SourceIndex); + UFUNCTION(Server, Reliable, WithValidation) + void ServerAddItemFromEquipmentAnySlot(class UIFEquipmentComponent* Source, uint8 SourceIndex); + void ServerAddItemFromEquipmentAnySlot_Implementation(class UIFEquipmentComponent* Source, uint8 SourceIndex); + bool ServerAddItemFromEquipmentAnySlot_Validate(class UIFEquipmentComponent* Source, uint8 SourceIndex); + /* + Confirm that change can be made and do the same change on client. + We do not predict inventory modifications. Clients MUST wait for server to make changes and send confirmation back. + */ + UFUNCTION(Client, Reliable) + void ClientAddItemFromEquipmentAnySlot(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex); + void ClientAddItemFromEquipmentAnySlot_Implementation(class UIFEquipmentComponent* Source, uint8 SourceIndex, uint8 InventoryIndex); + + + //never call on clients. + void AddItemAnySlot(class UIFItemBase* Source); + /* + Confirm that change can be made and do the same change on client. + We do not predict inventory modifications. Clients MUST wait for server to make changes and send confirmation back. + */ + UFUNCTION(Client, Reliable) + void ClientAddAnySlot(const FString& JsonData, uint8 InventoryIndex); + void ClientAddAnySlot_Implementation(const FString& JsonData, uint8 InventoryIndex); + + + virtual void OnItemAdded(UIFItemBase* Item, uint8 LocalIndex) {}; + virtual void OnItemChanged(UIFItemBase* Item, uint8 LocalIndex) {}; + virtual void OnItemRemoved(UIFItemBase* Item, uint8 LocalIndex) {}; + + //these function are called on server. + virtual void OnServerItemAdded(UIFItemBase* Item, uint8 LocalIndex) {}; + virtual void OnServerItemChanged(UIFItemBase* Item, uint8 LocalIndex) {}; + virtual void OnServerItemRemoved(UIFItemBase* Item, uint8 LocalIndex) {}; + + void RemoveItem(uint8 InIndex); + UFUNCTION(Server, Reliable, WithValidation) + void ServerRemoveItem(uint8 InIndex); + void ServerRemoveItem_Implementation(uint8 InIndex); + bool ServerRemoveItem_Validate(uint8 InIndex); + UFUNCTION(Client, Reliable) + void ClientRemoveItem(uint8 Index); + void ClientRemoveItem_Implementation(uint8 InIndex); + + + UFUNCTION() + void OnItemLoadedFreeSlot(TSoftClassPtr InItem); + + UFUNCTION() + void OnItemLoaded(TSoftClassPtr InItem, uint8 InNetIndex); + + FSimpleMulticastDelegate& GetOnInventoryRead(); + + + UFUNCTION(Client, Reliable) + void ClientSendJsonData(const FString& Data); + void ClientSendJsonData_Implementation(const FString& Data); + + protected: + void AddItem(TSoftClassPtr InItem, uint8 ItemIndex); + TSharedPtr ItemToJson(FIFItemData* Item); + FString JsonItemToString(TSharedPtr Object); + void SendToBackend(TSharedPtr JsonObj, int32 Idx); + + FIFItemData JsonToItem(const FString& JsonString); +}; diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFInventoryInterface.h b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFInventoryInterface.h new file mode 100644 index 0000000..3d7e9eb --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFInventoryInterface.h @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "IFInventoryInterface.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI) +class UIFInventoryInterface : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class INVENTORYFRAMEWORK_API IIFInventoryInterface +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + + virtual void OnInventoryReplicated(class UIFInventoryComponent* Inventory) = 0; +}; diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFItemActorBase.h b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFItemActorBase.h new file mode 100644 index 0000000..ea167bc --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFItemActorBase.h @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "IFItemActorBase.generated.h" + +UCLASS() +class INVENTORYFRAMEWORK_API AIFItemActorBase : public AActor +{ + GENERATED_BODY() + friend class UIFInventoryComponent; +protected: + //temp + UPROPERTY(EditAnywhere, Category = "Loot") + TArray> Items; +public: + // Sets default values for this actor's properties + AIFItemActorBase(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + virtual void OnItemPicked() {}; +protected: + + TArray> GetAllItems(); + + void GiveAllItemsToInstigator(class UIFInventoryComponent* Inventory); + UFUNCTION(BlueprintCallable, Category = "InventoryFramework") + void BP_GiveAllItemsToInstigator(class UIFInventoryComponent* Inventory); +}; diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFItemBase.h b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFItemBase.h new file mode 100644 index 0000000..09cb1ab --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFItemBase.h @@ -0,0 +1,110 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "UObject/NoExportTypes.h" +#include "IFItemBase.generated.h" + + +/** + * + */ +UCLASS(Blueprintable, BlueprintType) +class INVENTORYFRAMEWORK_API UIFItemBase : public UObject +{ + GENERATED_BODY() +public: + + //Possibly just one index, if we are going to bypass unreal replication + //and just send items as json from server and then decode them and insert in map. + UPROPERTY() + uint8 LocalIndex; + UPROPERTY() + uint8 NetIndex; + + bool IsNameStableForNetworking() const override + { + return false; + } + + bool IsSupportedForNetworking() const override + { + return true; + } + + bool CallRemoteFunction(UFunction* Function, void* Parameters, FOutParmRec* OutParms, FFrame* Stack) override; + + /* + Called just fater NewObject<> On server or in standalone. + */ + virtual void OnServerItemLoaded() {}; + + /* + Called after item has been added to inventory. + */ + virtual void OnItemAdded(uint8 InIndex) {}; + /* + Called when item changed slots within THE SAME inventory; + */ + virtual void OnItemChanged(uint8 InIndex) {}; + /* + Called after item has been removed from inventory; + */ + virtual void OnItemRemoved(uint8 InIndex) {}; + + /* + Called after item has been added to inventory. + Called on server or in standalone game. + */ + virtual void OnServerItemAdded(uint8 InIndex) {}; + /* + Called when item changed slots within THE SAME inventory. + Called on server or in standalone game. + */ + virtual void OnServerItemChanged(uint8 InIndex) {}; + /* + Called after item has been removed from inventory. + Called on server or in standalone game. + */ + virtual void OnServerItemRemoved(uint8 InIndex) {}; + + + + /* + Called after item has been added to Equipment. + */ + virtual void OnItemAddedEquipment(uint8 InIndex) {}; + /* + Called when item changed slots within THE SAME Equipment; + */ + virtual void OnItemChangedEquipment(uint8 InIndex) {}; + /* + Called after item has been removed from Equipment; + */ + virtual void OnItemRemovedEquipment(uint8 InIndex) {}; + + /* + Called after item has been added to Equipment. + Called on server or in standalone game. + */ + virtual void OnServerItemAddedEquipment(uint8 InIndex) {}; + /* + Called when item changed slots within THE SAME Equipment; + Called on server or in standalone game. + */ + virtual void OnServerItemChangedEquipment(uint8 InIndex) {}; + /* + Called after item has been removed from Equipment; + Called on server or in standalone game. + */ + virtual void OnServerItemRemovedEquipment(uint8 InIndex) {}; + + virtual void PreItemSerializeToJson() {}; + virtual void PreItemLoad() {}; + + virtual void ClientPostItemDeserializeFromJson() {}; + static UIFItemBase* LoadFromJSON() { return nullptr; } + +}; diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFTypes.h b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFTypes.h new file mode 100644 index 0000000..26cc3ff --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Public/IFTypes.h @@ -0,0 +1,58 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Json.h" +#include "Policies/CondensedJsonPrintPolicy.h" +#include "Serialization/JsonTypes.h" +#include "Serialization/JsonReader.h" +#include "Policies/PrettyJsonPrintPolicy.h" +#include "Serialization/JsonSerializer.h" +#include "IFTypes.generated.h" + +DECLARE_MULTICAST_DELEGATE_ThreeParams(FIFItemEvent, uint8, uint8, class UIFItemBase*); +DECLARE_MULTICAST_DELEGATE(FIFOnInventoryChanged); + +USTRUCT(BlueprintType) +struct INVENTORYFRAMEWORK_API FIFItemData +{ + GENERATED_BODY() +public: + UPROPERTY() + class UIFItemBase* Item; + + UPROPERTY(BlueprintReadOnly) + uint8 Index; +}; + + +USTRUCT(BlueprintType) +struct INVENTORYFRAMEWORK_API FIFSlotAcceptedClasses +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere) + TArray> AcceptedClasses; + +}; + +struct INVENTORYFRAMEWORK_API FIFJsonSerializer +{ + static bool ConvertScalarJsonValueToUProperty(TSharedPtr JsonValue, UProperty* Property, void* OutValue); + static bool JsonObjectToUStruct(const TSharedRef& JsonObject, const UStruct* StructDefinition, void* OutStruct); + static bool JsonValueToUProperty(TSharedPtr JsonValue, UProperty* Property, void* OutValue); + static void JsonObjectToUObject(TSharedPtr Object, UObject*& OutObject, UObject* Outer); + static bool JsonAttributesToUObject(const TMap< FString, TSharedPtr >& JsonAttributes, const UStruct* StructDefinition, void* OutStruct); +}; + + +/** + * + */ +class INVENTORYFRAMEWORK_API IFTypes +{ +public: + IFTypes(); + ~IFTypes(); +}; diff --git a/Plugins/InventoryFramework/Source/InventoryFramework/Public/InventoryFramework.h b/Plugins/InventoryFramework/Source/InventoryFramework/Public/InventoryFramework.h new file mode 100644 index 0000000..8d7df26 --- /dev/null +++ b/Plugins/InventoryFramework/Source/InventoryFramework/Public/InventoryFramework.h @@ -0,0 +1,15 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "ModuleManager.h" + +class FInventoryFrameworkModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; \ No newline at end of file diff --git a/Plugins/InventoryFrameworkUI/InventoryFrameworkUI.uplugin b/Plugins/InventoryFrameworkUI/InventoryFrameworkUI.uplugin new file mode 100644 index 0000000..d1a40fa --- /dev/null +++ b/Plugins/InventoryFrameworkUI/InventoryFrameworkUI.uplugin @@ -0,0 +1,29 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "InventoryFrameworkUI", + "Description": "", + "Category": "Other", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "InventoryFrameworkUI", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ], + "Plugins": [ + { + "Name": "InventoryFramework", + "Enabled": true + } + ] +} \ No newline at end of file diff --git a/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/InventoryFrameworkUI.Build.cs b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/InventoryFrameworkUI.Build.cs new file mode 100644 index 0000000..c0690be --- /dev/null +++ b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/InventoryFrameworkUI.Build.cs @@ -0,0 +1,51 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class InventoryFrameworkUI : ModuleRules +{ + public InventoryFrameworkUI(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "InventoryFrameworkUI/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "Core", + "CoreUObject", + "Engine", + "InputCore", + "Slate", + "SlateCore", + "InventoryFramework", + "UMG" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Private/IFItemContainerWidget.cpp b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Private/IFItemContainerWidget.cpp new file mode 100644 index 0000000..03393f3 --- /dev/null +++ b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Private/IFItemContainerWidget.cpp @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "IFItemContainerWidget.h" +#include "IFInventoryComponent.h" +#include "IFItemWidget.h" + +void UIFItemContainerWidget::SetInventory(UIFInventoryComponent* InInventory) +{ + Inventory = InInventory; +} + +void UIFItemContainerWidget::CreateInventory() +{ + NativeOnInventoryCreated(); +} + +void UIFItemContainerWidget::NativeOnInventoryCreated() +{ + BP_OnInventoryCreated(); +} \ No newline at end of file diff --git a/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Private/IFItemWidget.cpp b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Private/IFItemWidget.cpp new file mode 100644 index 0000000..0276e27 --- /dev/null +++ b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Private/IFItemWidget.cpp @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "IFItemWidget.h" +#include "Blueprint/WidgetBlueprintLibrary.h" + +#include "IFInventoryComponent.h" + +void UIFItemWidget::OnSlotCreated(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item) +{ + NetIndex = InNetIndex; + LocalIndex = InLocalIndex; + BP_OnItemCreated(Item); +} + +void UIFItemWidget::OnItemChanged(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item) +{ + BP_OnItemChanged(const_cast(Item)); +} + +void UIFItemWidget::OnItemRemoved(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item) +{ + BP_OnItemRemoved(const_cast(Item)); +} \ No newline at end of file diff --git a/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Private/InventoryFrameworkUI.cpp b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Private/InventoryFrameworkUI.cpp new file mode 100644 index 0000000..40d2c06 --- /dev/null +++ b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Private/InventoryFrameworkUI.cpp @@ -0,0 +1,20 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#include "InventoryFrameworkUI.h" + +#define LOCTEXT_NAMESPACE "FInventoryFrameworkUIModule" + +void FInventoryFrameworkUIModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FInventoryFrameworkUIModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FInventoryFrameworkUIModule, InventoryFrameworkUI) \ No newline at end of file diff --git a/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Public/IFItemContainerWidget.h b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Public/IFItemContainerWidget.h new file mode 100644 index 0000000..65a697b --- /dev/null +++ b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Public/IFItemContainerWidget.h @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "IFItemContainerWidget.generated.h" + +/** + * + */ +UCLASS() +class INVENTORYFRAMEWORKUI_API UIFItemContainerWidget : public UUserWidget +{ + GENERATED_BODY() +protected: + TWeakObjectPtr Inventory; + + UPROPERTY(BlueprintReadOnly, Category = "InventoryFramework") + TArray InventoryWidgets; + + UPROPERTY(EditAnywhere, CAtegory = "Widgets") + TSubclassOf ItemClass; + +public: + void SetInventory(UIFInventoryComponent* InInventory); + + void CreateInventory(); + + /* + Called after all widgets in InvetoryWidgets array has been created. + */ + virtual void NativeOnInventoryCreated(); + + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "On Inventory Created")) + void BP_OnInventoryCreated(); +}; diff --git a/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Public/IFItemWidget.h b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Public/IFItemWidget.h new file mode 100644 index 0000000..f08bb1b --- /dev/null +++ b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Public/IFItemWidget.h @@ -0,0 +1,45 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "IFItemWidget.generated.h" + +/** + * + */ +UCLASS() +class INVENTORYFRAMEWORKUI_API UIFItemWidget : public UUserWidget +{ + GENERATED_BODY() + friend class UIFItemContainerWidget; +public: + TWeakObjectPtr Inventory; + /* + Those indexes correponds to the client copy of items; + */ + + UPROPERTY() + uint8 NetIndex; + UPROPERTY() + uint8 LocalIndex; + + UPROPERTY(BlueprintReadWrite, Category = "InventoryFramework") + UWidget* DragVisual; +public: + virtual void OnSlotCreated(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item); + + virtual void OnItemChanged(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item); + + virtual void OnItemRemoved(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item); + + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "On Item Created")) + void BP_OnItemCreated(class UIFItemBase* Item); + + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "On Item Changed")) + void BP_OnItemChanged(class UIFItemBase* Item); + + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "On Item Removed")) + void BP_OnItemRemoved(class UIFItemBase* Item); +}; diff --git a/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Public/InventoryFrameworkUI.h b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Public/InventoryFrameworkUI.h new file mode 100644 index 0000000..1c74e9a --- /dev/null +++ b/Plugins/InventoryFrameworkUI/Source/InventoryFrameworkUI/Public/InventoryFrameworkUI.h @@ -0,0 +1,15 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class FInventoryFrameworkUIModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/Plugins/JsonUObject/JsonUObject.uplugin b/Plugins/JsonUObject/JsonUObject.uplugin new file mode 100644 index 0000000..312d1d7 --- /dev/null +++ b/Plugins/JsonUObject/JsonUObject.uplugin @@ -0,0 +1,23 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "JsonUObject", + "Description": "Serialize UObject to Json.", + "Category": "Other", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "JsonUObject", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ] +} \ No newline at end of file diff --git a/Plugins/JsonUObject/Source/JsonUObject/JsonUObject.Build.cs b/Plugins/JsonUObject/Source/JsonUObject/JsonUObject.Build.cs new file mode 100644 index 0000000..849cd84 --- /dev/null +++ b/Plugins/JsonUObject/Source/JsonUObject/JsonUObject.Build.cs @@ -0,0 +1,49 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class JsonUObject : ModuleRules +{ + public JsonUObject(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "JsonUObject/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "Json", + "JsonUtilities" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/JsonUObject/Source/JsonUObject/Private/JsonUODeserialize.cpp b/Plugins/JsonUObject/Source/JsonUObject/Private/JsonUODeserialize.cpp new file mode 100644 index 0000000..450959f --- /dev/null +++ b/Plugins/JsonUObject/Source/JsonUObject/Private/JsonUODeserialize.cpp @@ -0,0 +1,11 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "JsonUODeserialize.h" + +JsonUODeserialize::JsonUODeserialize() +{ +} + +JsonUODeserialize::~JsonUODeserialize() +{ +} diff --git a/Plugins/JsonUObject/Source/JsonUObject/Private/JsonUOSerialize.cpp b/Plugins/JsonUObject/Source/JsonUObject/Private/JsonUOSerialize.cpp new file mode 100644 index 0000000..28851ca --- /dev/null +++ b/Plugins/JsonUObject/Source/JsonUObject/Private/JsonUOSerialize.cpp @@ -0,0 +1,219 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "JsonUOSerialize.h" +#include "JsonObjectConverter.h" + +bool FJsonUOSerialize::UObjectToJsonObject(const UStruct* StructDefinition, const void* Struct, TSharedRef OutJsonObject) +{ + OutJsonObject->Values.Add(FString("objectClass"), MakeShareable(new FJsonValueString(StructDefinition->GetPathName()))); + return UStructToJsonAttributes(StructDefinition, Struct, OutJsonObject->Values); +} + +TSharedPtr FJsonUOSerialize::ConvertScalarUPropertyToJsonValue(UProperty* Property, const void* Value) +{ + // See if there's a custom export callback first, so it can override default behavior + + + if (UEnumProperty* EnumProperty = Cast(Property)) + { + // export enums as strings + UEnum* EnumDef = EnumProperty->GetEnum(); + FString StringValue = EnumDef->GetNameStringByValue(EnumProperty->GetUnderlyingProperty()->GetSignedIntPropertyValue(Value)); + return MakeShareable(new FJsonValueString(StringValue)); + } + else if (UNumericProperty *NumericProperty = Cast(Property)) + { + // see if it's an enum + UEnum* EnumDef = NumericProperty->GetIntPropertyEnum(); + if (EnumDef != NULL) + { + // export enums as strings + FString StringValue = EnumDef->GetNameStringByValue(NumericProperty->GetSignedIntPropertyValue(Value)); + return MakeShareable(new FJsonValueString(StringValue)); + } + + // We want to export numbers as numbers + if (NumericProperty->IsFloatingPoint()) + { + return MakeShareable(new FJsonValueNumber(NumericProperty->GetFloatingPointPropertyValue(Value))); + } + else if (NumericProperty->IsInteger()) + { + return MakeShareable(new FJsonValueNumber(NumericProperty->GetSignedIntPropertyValue(Value))); + } + + // fall through to default + } + else if (UBoolProperty *BoolProperty = Cast(Property)) + { + // Export bools as bools + return MakeShareable(new FJsonValueBoolean(BoolProperty->GetPropertyValue(Value))); + } + else if (UStrProperty *StringProperty = Cast(Property)) + { + return MakeShareable(new FJsonValueString(StringProperty->GetPropertyValue(Value))); + } + else if (UTextProperty *TextProperty = Cast(Property)) + { + return MakeShareable(new FJsonValueString(TextProperty->GetPropertyValue(Value).ToString())); + } + else if (UArrayProperty *ArrayProperty = Cast(Property)) + { + TArray< TSharedPtr > Out; + FScriptArrayHelper Helper(ArrayProperty, Value); + for (int32 i = 0, n = Helper.Num(); i Elem = UPropertyToJsonValue(ArrayProperty->Inner, Helper.GetRawPtr(i)); + if (Elem.IsValid()) + { + // add to the array + Out.Push(Elem); + } + } + return MakeShareable(new FJsonValueArray(Out)); + } + else if (USetProperty* SetProperty = Cast(Property)) + { + TArray< TSharedPtr > Out; + FScriptSetHelper Helper(SetProperty, Value); + for (int32 i = 0, n = Helper.Num(); n; ++i) + { + if (Helper.IsValidIndex(i)) + { + TSharedPtr Elem = UPropertyToJsonValue(SetProperty->ElementProp, Helper.GetElementPtr(i)); + if (Elem.IsValid()) + { + // add to the array + Out.Push(Elem); + } + + --n; + } + } + return MakeShareable(new FJsonValueArray(Out)); + } + else if (UMapProperty* MapProperty = Cast(Property)) + { + TSharedRef Out = MakeShareable(new FJsonObject()); + + FScriptMapHelper Helper(MapProperty, Value); + for (int32 i = 0, n = Helper.Num(); n; ++i) + { + if (Helper.IsValidIndex(i)) + { + TSharedPtr KeyElement = UPropertyToJsonValue(MapProperty->KeyProp, Helper.GetKeyPtr(i)); + TSharedPtr ValueElement = UPropertyToJsonValue(MapProperty->ValueProp, Helper.GetValuePtr(i)); + if (KeyElement.IsValid() && ValueElement.IsValid()) + { + FString KeyString = KeyElement->AsString(); + if (KeyString.IsEmpty()) + { + MapProperty->KeyProp->ExportTextItem(KeyString, Helper.GetKeyPtr(i), nullptr, nullptr, 0); + if (KeyString.IsEmpty()) + { + UE_LOG(LogJson, Error, TEXT("Unable to convert key to string for property %s."), *MapProperty->GetName()) + KeyString = FString::Printf(TEXT("Unparsed Key %d"), i); + } + } + + Out->SetField(KeyString, ValueElement); + } + + --n; + } + } + + return MakeShareable(new FJsonValueObject(Out)); + } + else if (UObjectProperty* ObjectProperty = Cast(Property)) + { + TSharedRef Out = MakeShareable(new FJsonObject()); + + UObject* Object = ObjectProperty->GetObjectPropertyValue(Value); + if (Object) + { + UClass* cls = Object->GetClass(); + + if (UObjectToJsonObject(cls, Object, Out)) + { + return MakeShareable(new FJsonValueObject(Out)); + } + } + } + else if (UStructProperty *StructProperty = Cast(Property)) + { + UScriptStruct::ICppStructOps* TheCppStructOps = StructProperty->Struct->GetCppStructOps(); + // Intentionally exclude the JSON Object wrapper, which specifically needs to export JSON in an object representation instead of a string + if (StructProperty->Struct != FJsonObjectWrapper::StaticStruct() && TheCppStructOps && TheCppStructOps->HasExportTextItem()) + { + FString OutValueStr; + TheCppStructOps->ExportTextItem(OutValueStr, Value, nullptr, nullptr, PPF_None, nullptr); + return MakeShareable(new FJsonValueString(OutValueStr)); + } + + TSharedRef Out = MakeShareable(new FJsonObject()); + if (UObjectToJsonObject(StructProperty->Struct, Value, Out)) + { + return MakeShareable(new FJsonValueObject(Out)); + } + // fall through to default + } + else + { + // Default to export as string for everything else + FString StringValue; + Property->ExportTextItem(StringValue, Value, NULL, NULL, PPF_None); + return MakeShareable(new FJsonValueString(StringValue)); + } + + // invalid + return TSharedPtr(); +} + +TSharedPtr FJsonUOSerialize::UPropertyToJsonValue(UProperty* Property, const void* Value) +{ + if (Property->ArrayDim == 1) + { + return ConvertScalarUPropertyToJsonValue(Property, Value); + } + + TArray< TSharedPtr > Array; + for (int Index = 0; Index != Property->ArrayDim; ++Index) + { + Array.Add(ConvertScalarUPropertyToJsonValue(Property, (char*)Value + Index * Property->ElementSize)); + } + return MakeShareable(new FJsonValueArray(Array)); +} + +bool FJsonUOSerialize::UStructToJsonAttributes(const UStruct* StructDefinition, const void* Struct, TMap< FString, TSharedPtr >& OutJsonAttributes) +{ + int64 SerFlag = 0; + SerFlag |= CPF_SaveGame; + + for (TFieldIterator It(StructDefinition); It; ++It) + { + UProperty* Property = *It; + + if (Property->HasAnyPropertyFlags(SerFlag)) + { + FString VariableName = Property->GetName();// StandardizeCase(); + const void* Value = Property->ContainerPtrToValuePtr(Struct); + + // convert the property to a FJsonValue + TSharedPtr JsonValue = UPropertyToJsonValue(Property, Value); + if (JsonValue.IsValid()) + { + OutJsonAttributes.Add(VariableName, JsonValue); + + //return false; + } + else + { + UClass* PropClass = Property->GetClass(); + UE_LOG(LogJson, Error, TEXT("UStructToJsonObject - Unhandled property type '%s': %s"), *PropClass->GetName(), *Property->GetPathName()); + } + } + } + + return true; +} \ No newline at end of file diff --git a/Plugins/JsonUObject/Source/JsonUObject/Private/JsonUObject.cpp b/Plugins/JsonUObject/Source/JsonUObject/Private/JsonUObject.cpp new file mode 100644 index 0000000..36e12d0 --- /dev/null +++ b/Plugins/JsonUObject/Source/JsonUObject/Private/JsonUObject.cpp @@ -0,0 +1,20 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#include "JsonUObject.h" + +#define LOCTEXT_NAMESPACE "FJsonUObjectModule" + +void FJsonUObjectModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FJsonUObjectModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FJsonUObjectModule, JsonUObject) \ No newline at end of file diff --git a/Plugins/JsonUObject/Source/JsonUObject/Public/JsonUODeserialize.h b/Plugins/JsonUObject/Source/JsonUObject/Public/JsonUODeserialize.h new file mode 100644 index 0000000..30f1800 --- /dev/null +++ b/Plugins/JsonUObject/Source/JsonUObject/Public/JsonUODeserialize.h @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + +/** + * + */ +class JSONUOBJECT_API JsonUODeserialize +{ +public: + JsonUODeserialize(); + ~JsonUODeserialize(); +}; diff --git a/Plugins/JsonUObject/Source/JsonUObject/Public/JsonUOSerialize.h b/Plugins/JsonUObject/Source/JsonUObject/Public/JsonUOSerialize.h new file mode 100644 index 0000000..b5da09a --- /dev/null +++ b/Plugins/JsonUObject/Source/JsonUObject/Public/JsonUOSerialize.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + +#include "Json.h" +#include "Policies/CondensedJsonPrintPolicy.h" +#include "Serialization/JsonTypes.h" +#include "Serialization/JsonReader.h" +#include "Policies/PrettyJsonPrintPolicy.h" +#include "Serialization/JsonSerializer.h" + +/** + * + */ +class JSONUOBJECT_API FJsonUOSerialize +{ +public: + static bool UObjectToJsonObject(const UStruct* StructDefinition, const void* Struct, TSharedRef OutJsonObject); +private: + static TSharedPtr ConvertScalarUPropertyToJsonValue(UProperty* Property, const void* Value); + static TSharedPtr UPropertyToJsonValue(UProperty* Property, const void* Value); + static bool UStructToJsonAttributes(const UStruct* StructDefinition, const void* Struct, TMap< FString, TSharedPtr >& OutJsonAttributes); +}; diff --git a/Plugins/JsonUObject/Source/JsonUObject/Public/JsonUObject.h b/Plugins/JsonUObject/Source/JsonUObject/Public/JsonUObject.h new file mode 100644 index 0000000..9589ff7 --- /dev/null +++ b/Plugins/JsonUObject/Source/JsonUObject/Public/JsonUObject.h @@ -0,0 +1,15 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class FJsonUObjectModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/Plugins/OrionAnimation/OrionAnimation.uplugin b/Plugins/OrionAnimation/OrionAnimation.uplugin new file mode 100644 index 0000000..8cdc53a --- /dev/null +++ b/Plugins/OrionAnimation/OrionAnimation.uplugin @@ -0,0 +1,31 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "OrionAnimation", + "Description": "", + "Category": "Other", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "OrionAnimation", + "Type": "Runtime", + "LoadingPhase": "PreDefault" + }, + { + "Name": "OrionAnimationEditor", + "Type": "Editor", + "LoadingPhase": "PreDefault", + "WhitelistPlatforms": [ + "Win64" + ] + } + ] +} \ No newline at end of file diff --git a/Plugins/OrionAnimation/Source/OrionAnimation/OrionAnimation.Build.cs b/Plugins/OrionAnimation/Source/OrionAnimation/OrionAnimation.Build.cs new file mode 100644 index 0000000..23ca89a --- /dev/null +++ b/Plugins/OrionAnimation/Source/OrionAnimation/OrionAnimation.Build.cs @@ -0,0 +1,49 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class OrionAnimation : ModuleRules +{ + public OrionAnimation(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "OrionAnimation/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "AnimationCore", + "AnimGraphRuntime" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/OrionAnimation/Source/OrionAnimation/Public/AnimNode_BlendLocomotionFour.h b/Plugins/OrionAnimation/Source/OrionAnimation/Public/AnimNode_BlendLocomotionFour.h new file mode 100644 index 0000000..1165134 --- /dev/null +++ b/Plugins/OrionAnimation/Source/OrionAnimation/Public/AnimNode_BlendLocomotionFour.h @@ -0,0 +1,146 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Animation/AnimationAsset.h" +#include "Animation/AnimNodeBase.h" +#include "AlphaBlend.h" +#include "BoneContainer.h" +#include "OrionInterface.h" +#include "Animation/InputScaleBias.h" +#include "AnimNode_BlendLocomotionFour.generated.h" + +class UBlendProfile; +class UCurveFloat; + +enum class EECardinalDirection : uint8 +{ + N = 0, + SW = 1, + E = 2, + NW = 3, + S = 4, + NE = 5, + W = 6, + SE = 7 +}; +USTRUCT(BlueprintType) +struct FOAxisSettings +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, Category = "FAxisSettings") + TEnumAsByte YawRotationAxis; + + UPROPERTY(EditAnywhere, Category = "FAxisSettings") + float BodyOrientationAlpha; + + FOAxisSettings() :YawRotationAxis(EAxis::Z) + , BodyOrientationAlpha(0.5f) {} +}; +USTRUCT() +struct FOBoneRef +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, Category = "Settings") + FBoneReference Bone; +}; +// Blend list node; has many children +USTRUCT(BlueprintInternalUseOnly) +struct ORIONANIMATION_API FAnimNode_BlendLocomotionFour : public FAnimNode_Base +{ + GENERATED_USTRUCT_BODY() +public: + UPROPERTY(EditAnywhere, EditFixedSize, BlueprintReadWrite, Category = Links) + TArray BlendPose; + + UPROPERTY(EditAnywhere, EditFixedSize, BlueprintReadWrite, Category = Config, meta = (PinShownByDefault)) + TArray BlendTime; + + UPROPERTY(EditAnywhere, Category = BlendType) + EAlphaBlendOption BlendType; + + UPROPERTY(EditAnywhere, Category = BlendType) + UCurveFloat* CustomBlendCurve; + + UPROPERTY(EditAnywhere, Category = BlendType) + UBlendProfile* BlendProfile; + + UPROPERTY() + TArray Blends; + +protected: + UPROPERTY() + TArray BlendWeights; + + UPROPERTY() + TArray RemainingBlendTimes; + + UPROPERTY() + int32 LastActiveChildIndex; + + UPROPERTY() + TArray PerBoneSampleData; + + //Store which poses we need to evaluate + TArray PosesToEvaluate; + + /** This reinitializes child pose when re-activated. For example, when active child changes */ + UPROPERTY(EditAnywhere, Category = Option) + bool bResetChildOnActivation; + +protected: + int32 CurrentDirection; + EFCardinalDirection OldDirection; + EFCardinalDirection Dir; + float OrientN; + float OrientE; + float OrientS; + float OrientW; + float CurrentOrient; + bool bDirectionChanged; + int32 CurrentPose; + + UPROPERTY(Transient) + mutable float InternalBlendAlpha; + + UPROPERTY(Transient) + class ACharacter* Character; + + UPROPERTY(Transient) + class UCharacterMovementComponent* CMC; + + float RemainingBlendTime; + FAlphaBlend AlphaBlend; + + FAlphaBlend NorthBlend; + FAlphaBlend EastBlend; + + float DotBlendTime; + int32 NDot; + int32 EDot; +public: + FAnimNode_BlendLocomotionFour() + : LastActiveChildIndex(0) + , bResetChildOnActivation(false) + { + BlendTime.SetNum(4); + BlendPose.SetNum(4); + } + + // FAnimNode_Base interface + virtual void Initialize_AnyThread(const FAnimationInitializeContext& Context) override; + virtual void CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) override; + virtual void Update_AnyThread(const FAnimationUpdateContext& Context) override; + virtual void Evaluate_AnyThread(FPoseContext& Output) override; + virtual void GatherDebugData(FNodeDebugData& DebugData) override; + // End of FAnimNode_Base interface + +protected: + virtual int32 GetActiveChildIndex() { return 0; } + virtual FString GetNodeName(FNodeDebugData& DebugData) { return DebugData.GetNodeName(this); } + void Reorient(FCompactPose& CompactPose, FComponentSpacePoseContext& CSOutput, const FBoneContainer& BoneContainer, float Orient); +}; diff --git a/Plugins/OrionAnimation/Source/OrionAnimation/Public/OrionAnimComponent.h b/Plugins/OrionAnimation/Source/OrionAnimation/Public/OrionAnimComponent.h new file mode 100644 index 0000000..16e0c65 --- /dev/null +++ b/Plugins/OrionAnimation/Source/OrionAnimation/Public/OrionAnimComponent.h @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" + +#include "OrionTypes.h" + +#include "OrionAnimComponent.generated.h" + + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class ORIONANIMATION_API UOrionAnimComponent : public UActorComponent +{ + GENERATED_BODY() +protected: + EOrionCardinalDirection CardinalDirection; + + UPROPERTY() + class ACharacter* CharacterOwner; + +public: + // Sets default values for this component's properties + UOrionAnimComponent(); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + void InitializeAnim(ACharacter* InCharacter); + + void CalculateCardinalDirection(); +}; diff --git a/Plugins/OrionAnimation/Source/OrionAnimation/Public/OrionAnimation.h b/Plugins/OrionAnimation/Source/OrionAnimation/Public/OrionAnimation.h new file mode 100644 index 0000000..da88bbe --- /dev/null +++ b/Plugins/OrionAnimation/Source/OrionAnimation/Public/OrionAnimation.h @@ -0,0 +1,15 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class FOrionAnimationModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/Plugins/OrionAnimation/Source/OrionAnimation/Public/OrionInterface.h b/Plugins/OrionAnimation/Source/OrionAnimation/Public/OrionInterface.h new file mode 100644 index 0000000..66aee9d --- /dev/null +++ b/Plugins/OrionAnimation/Source/OrionAnimation/Public/OrionInterface.h @@ -0,0 +1,42 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Interface.h" +#include "OrionInterface.generated.h" + +enum class EFCardinalDirection : uint8 +{ + N = 0, + E = 1, + S = 2, + W = 3 +}; + +// This class does not need to be modified. +UINTERFACE(MinimalAPI) +class UOrionInterface : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class ORIONANIMATION_API IOrionInterface +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + + virtual float GetAnimOrient() { return 0; } + + virtual float GetAnimOrientN() { return 0; } + virtual float GetAnimOrientE() { return 0; } + virtual float GetAnimOrientS() { return 0; } + virtual float GetAnimOrientW() { return 0; } + + virtual EFCardinalDirection GetCardianlDirection() { return EFCardinalDirection::N; } +}; diff --git a/Plugins/OrionAnimation/Source/OrionAnimationEditor/OrionAnimationEditor.Build.cs b/Plugins/OrionAnimation/Source/OrionAnimationEditor/OrionAnimationEditor.Build.cs new file mode 100644 index 0000000..83dcc7f --- /dev/null +++ b/Plugins/OrionAnimation/Source/OrionAnimationEditor/OrionAnimationEditor.Build.cs @@ -0,0 +1,51 @@ +// Copyright 2018 Sean Chen. All Rights Reserved. + +using UnrealBuildTool; + +public class OrionAnimationEditor : ModuleRules +{ + public OrionAnimationEditor(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "OrionAnimationEditor/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "OrionAnimation" + + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "AnimGraph", + "BlueprintGraph" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/OrionAnimation/Source/OrionAnimationEditor/Private/AnimGraphNode_BlendLocomotionFour.cpp b/Plugins/OrionAnimation/Source/OrionAnimationEditor/Private/AnimGraphNode_BlendLocomotionFour.cpp new file mode 100644 index 0000000..359a7c0 --- /dev/null +++ b/Plugins/OrionAnimation/Source/OrionAnimationEditor/Private/AnimGraphNode_BlendLocomotionFour.cpp @@ -0,0 +1,130 @@ +// Copyright 2018 Sean Chen. All Rights Reserved. + +#include "AnimGraphNode_BlendLocomotionFour.h" +#include "OrionAnimationEditor.h" + +#define LOCTEXT_NAMESPACE "A3Nodes" + +UAnimGraphNode_BlendLocomotionFour::UAnimGraphNode_BlendLocomotionFour() +{ + +} + +FLinearColor UAnimGraphNode_BlendLocomotionFour::GetNodeTitleColor() const +{ + return FLinearColor(0.7f, 0.7f, 0.7f); +} + +FText UAnimGraphNode_BlendLocomotionFour::GetTooltipText() const +{ + return LOCTEXT("LocomotionFour", "Locomotion Four Direction"); +} + +FText UAnimGraphNode_BlendLocomotionFour::GetNodeTitle(ENodeTitleType::Type TitleType) const +{ + return LOCTEXT("LocomotionFour", "Locomotion Four Direction"); +} + +FString UAnimGraphNode_BlendLocomotionFour::GetNodeCategory() const +{ + return TEXT("Orion Animation"); +} +void GetPinInformation(const FString& InPinName, int32& Out_PinIndex, bool& Out_bIsPosePin, bool& Out_bIsTimePin) +{ + const int32 UnderscoreIndex = InPinName.Find(TEXT("_"), ESearchCase::CaseSensitive); + if (UnderscoreIndex != INDEX_NONE) + { + const FString ArrayName = InPinName.Left(UnderscoreIndex); + Out_PinIndex = FCString::Atoi(*(InPinName.Mid(UnderscoreIndex + 1))); + + Out_bIsPosePin = (ArrayName == TEXT("BlendPose")); + Out_bIsTimePin = (ArrayName == TEXT("BlendTime")); + } + else + { + Out_bIsPosePin = false; + Out_bIsTimePin = false; + Out_PinIndex = INDEX_NONE; + } +} +void UAnimGraphNode_BlendLocomotionFour::CustomizePinData(UEdGraphPin* Pin, FName SourcePropertyName, int32 ArrayIndex) const +{ + // if pin name starts with BlendPose or BlendWeight, change to enum name + bool bIsPosePin; + bool bIsTimePin; + int32 RawArrayIndex; + GetPinInformation(Pin->PinName.ToString(), /*out*/ RawArrayIndex, /*out*/ bIsPosePin, /*out*/ bIsTimePin); + checkSlow(RawArrayIndex == ArrayIndex); + + + if (bIsPosePin) + { + if (RawArrayIndex == 0) + { + //Pin->PinFriendlyName = FText::FromName("North Pose"); + //FFormatNamedArguments Args; + //Args.Add(TEXT("PinFriendlyName"), Pin->PinFriendlyName); + Pin->PinFriendlyName = FText::FromString("N Pose"); + } + else if (RawArrayIndex == 1) + { + Pin->PinFriendlyName = FText::FromString("E Pose"); + } + else if (RawArrayIndex == 2) + { + Pin->PinFriendlyName = FText::FromString("S Pose"); + } + else if (RawArrayIndex == 3) + { + Pin->PinFriendlyName = FText::FromString("W Pose"); + } + } + //if (bIsPosePin || bIsTimePin) + //{ + // if (RawArrayIndex > 0) + // { + // const int32 ExposedEnumPinIndex = RawArrayIndex - 1; + + // // find pose index and see if it's mapped already or not + // if (VisibleEnumEntries.IsValidIndex(ExposedEnumPinIndex) && (BoundEnum != NULL)) + // { + // const FName& EnumElementName = VisibleEnumEntries[ExposedEnumPinIndex]; + // const int32 EnumIndex = BoundEnum->GetIndexByName(EnumElementName); + // if (EnumIndex != INDEX_NONE) + // { + // Pin->PinFriendlyName = BoundEnum->GetDisplayNameTextByIndex(EnumIndex); + // } + // else + // { + // Pin->PinFriendlyName = FText::FromName(EnumElementName); + // } + // } + // else + // { + // Pin->PinFriendlyName = LOCTEXT("InvalidIndex", "Invalid index"); + // } + // } + // else if (ensure(RawArrayIndex == 0)) + // { + // Pin->PinFriendlyName = LOCTEXT("Default", "Default"); + // } + + // // Append the pin type + // if (bIsPosePin) + // { + // FFormatNamedArguments Args; + // Args.Add(TEXT("PinFriendlyName"), Pin->PinFriendlyName); + // Pin->PinFriendlyName = FText::Format(LOCTEXT("FriendlyNamePose", "{PinFriendlyName} Pose"), Args); + // } + + // if (bIsTimePin) + // { + // FFormatNamedArguments Args; + // Args.Add(TEXT("PinFriendlyName"), Pin->PinFriendlyName); + // Pin->PinFriendlyName = FText::Format(LOCTEXT("FriendlyNameBlendTime", "{PinFriendlyName} Blend Time"), Args); + // } + //} +} + +#undef LOCTEXT_NAMESPACE + diff --git a/Plugins/OrionAnimation/Source/OrionAnimationEditor/Private/OrionAnimationEditor.cpp b/Plugins/OrionAnimation/Source/OrionAnimationEditor/Private/OrionAnimationEditor.cpp new file mode 100644 index 0000000..05b5d7f --- /dev/null +++ b/Plugins/OrionAnimation/Source/OrionAnimationEditor/Private/OrionAnimationEditor.cpp @@ -0,0 +1,20 @@ +// Copyright 2018 Sean Chen. All Rights Reserved. + +#include "OrionAnimationEditor.h" + +#define LOCTEXT_NAMESPACE "OrionAnimationEditorModule" + +void FOrionAnimationEditorModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FOrionAnimationEditorModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FOrionAnimationEditorModule, OrionAnimationEditor) \ No newline at end of file diff --git a/Plugins/OrionAnimation/Source/OrionAnimationEditor/Public/AnimGraphNode_BlendLocomotionFour.h b/Plugins/OrionAnimation/Source/OrionAnimationEditor/Public/AnimGraphNode_BlendLocomotionFour.h new file mode 100644 index 0000000..71f79fb --- /dev/null +++ b/Plugins/OrionAnimation/Source/OrionAnimationEditor/Public/AnimGraphNode_BlendLocomotionFour.h @@ -0,0 +1,35 @@ +// Copyright 2018 Sean Chen. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "AnimGraphNode_Base.h" +#include "AnimNode_BlendLocomotionFour.h" +#include "AnimGraphNode_BlendLocomotionFour.generated.h" + +struct FAnimMode_OrientationWarping; +/** +* +*/ +UCLASS() +class ORIONANIMATIONEDITOR_API UAnimGraphNode_BlendLocomotionFour : public UAnimGraphNode_Base +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, Category = "Settings") + FAnimNode_BlendLocomotionFour Node; + + //~ Begin UEdGraphNode Interface. + virtual FLinearColor GetNodeTitleColor() const override; + virtual FText GetTooltipText() const override; + virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override; + //~ End UEdGraphNode Interface. + + //~ Begin UAnimGraphNode_Base Interface + virtual FString GetNodeCategory() const override; + //~ End UAnimGraphNode_Base Interface + virtual void CustomizePinData(UEdGraphPin* Pin, FName SourcePropertyName, int32 ArrayIndex) const override; + UAnimGraphNode_BlendLocomotionFour(); + + +}; diff --git a/Plugins/OrionAnimation/Source/OrionAnimationEditor/Public/OrionAnimationEditor.h b/Plugins/OrionAnimation/Source/OrionAnimationEditor/Public/OrionAnimationEditor.h new file mode 100644 index 0000000..e60cb6a --- /dev/null +++ b/Plugins/OrionAnimation/Source/OrionAnimationEditor/Public/OrionAnimationEditor.h @@ -0,0 +1,15 @@ +// Copyright 2018 Sean Chen. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "ModuleManager.h" + +class FOrionAnimationEditorModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; \ No newline at end of file diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAI.cpp b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAI.cpp new file mode 100644 index 0000000..44a9f01 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAI.cpp @@ -0,0 +1,20 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#include "SpectrAI.h" + +#define LOCTEXT_NAMESPACE "FSpectrAIModule" + +void FSpectrAIModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FSpectrAIModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FSpectrAIModule, SpectrAI) \ No newline at end of file diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAI.h b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAI.h new file mode 100644 index 0000000..a266684 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAI.h @@ -0,0 +1,15 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "ModuleManager.h" + +class FSpectrAIModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; \ No newline at end of file diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAIController.cpp b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAIController.cpp new file mode 100644 index 0000000..c5103bd --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAIController.cpp @@ -0,0 +1,12 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SpectrAIController.h" +#include "SpectrBrainComponent.h" + + +ASpectrAIController::ASpectrAIController(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + SpectrBrain = ObjectInitializer.CreateDefaultSubobject(this, TEXT("SpectrBrain")); + AIPerception = ObjectInitializer.CreateDefaultSubobject(this, TEXT("AIPerception")); +} \ No newline at end of file diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAIController.h b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAIController.h new file mode 100644 index 0000000..19287ea --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAIController.h @@ -0,0 +1,48 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "AIController.h" +#include "Perception/AIPerceptionComponent.h" +#include "SpectrAIController.generated.h" + +//Consideration (calculates score) +//--normalized 0-1 +//--calculated against curve + +//Qualifier +//--Contains Considerations +//--defines how score Considerations should be combined +//--return score. + +//Decision (what should I do?) +//--contain exactly ONE action to execute if decision wins + +//Decision Score Evaluator (Selector) +//--containts multiple considerations +//--all condsiderations are calculated with given context +//--they are summed (or multiplied) +//--contains single decision to execute. + + + +/** + * + */ +UCLASS() +class SPECTRAI_API ASpectrAIController : public AAIController +{ + GENERATED_BODY() +public: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + class USpectrBrainComponent* SpectrBrain; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + class UAIPerceptionComponent* AIPerception; + + + ASpectrAIController(const FObjectInitializer& ObjectInitializer); + + +}; diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAction.cpp b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAction.cpp new file mode 100644 index 0000000..e57eba5 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAction.cpp @@ -0,0 +1,60 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SpectrAction.h" +#include "SpectrBrainComponent.h" + + +void USpectrAction::NativeMoveTo(class USpectrBrainComponent* Brain) +{ + MoveTo(Brain); +} +void USpectrAction::NativeOnMoveFinished(class USpectrContext* InContext, class AAIController* AIController, class USpectrBrainComponent* Brain) +{ + OnMoveFinished(InContext, AIController, Brain); +} +void USpectrAction::FinishMove(class USpectrContext* InContext, class AAIController* AIController, class USpectrBrainComponent* Brain) +{ + NativeOnMoveFinished(InContext, AIController, Brain); +} +void USpectrAction::MoveTo_Implementation(class USpectrBrainComponent* Brain) +{ + +} + +float USpectrAction::NativeScore(class USpectrContext* InContext, class AAIController* AIController) +{ + return Score(InContext, AIController); +} + +float USpectrAction::Score_Implementation(class USpectrContext* InContext, class AAIController* AIController) +{ + return Cost; +} +bool USpectrAction::NativeEvaluateCondition(class USpectrContext* InContext, class AAIController* AIController) +{ + return EvaluateCondition(InContext, AIController); +} +bool USpectrAction::EvaluateCondition_Implementation(class USpectrContext* InContext, class AAIController* AIController) +{ + return true; +} + +void USpectrAction::NativeFinished() +{ + OwningBrain->OnActionFinished(this); +} + +void USpectrAction::NativeExecute(class USpectrContext* InContext, class AAIController* AIController, class USpectrBrainComponent* Brain) +{ + OnExecute(InContext, AIController, Brain); +} + +void USpectrAction::ActionFinished() +{ + NativeFinished(); +} + +void USpectrAction::MoveToTarget(AActor* Target, float MinimumDistance) +{ + OwningBrain->MoveToActor(Target, MinimumDistance); +} \ No newline at end of file diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAction.h b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAction.h new file mode 100644 index 0000000..b6ac82b --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrAction.h @@ -0,0 +1,94 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "GameplayTags.h" +#include "GameplayTagContainer.h" +#include "SpectrAction.generated.h" + +/** + * Default implmenetations of Native* functions call to either blueprint events + * or blueprint Native functions which can be overriden from blueprint. + * Though they do provide default implementation (where possible). + */ + +UCLASS(BlueprintType, Blueprintable) +class SPECTRAI_API USpectrAction : public UObject +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Category = "State Configuration") + int32 Cost; + /* + Tag Name of requirent condition in agent state, Desiared State Value + */ + UPROPERTY(EditAnywhere, Category = "State Configuration") + TMap PreConditions; + + /* + Tag Name of change applied to agent state is effect is executed, Desiared State Value + */ + UPROPERTY(EditAnywhere, Category = "State Configuration") + TMap Effects; + + UPROPERTY(BlueprintReadOnly, Category = "Spectr AI") + USpectrBrainComponent* OwningBrain; + + /* Override to check if action in rnage of Target/Location to execute */ + virtual bool NativeIsInRange(class AAIController* AIController) + { + return true; + } + + virtual void NativeMoveTo(class USpectrBrainComponent* Brain); + + virtual void NativeOnMoveFinished(class USpectrContext* InContext, class AAIController* AIController, class USpectrBrainComponent* Brain); + + UFUNCTION(BlueprintNativeEvent) + void MoveTo(class USpectrBrainComponent* Brain); + virtual void MoveTo_Implementation(class USpectrBrainComponent* Brain); + + UFUNCTION(BlueprintImplementableEvent, Category = "Spectr AI") + void OnMoveFinished(class USpectrContext* InContext, class AAIController* AIController, class USpectrBrainComponent* Brain); + + UFUNCTION(BlueprintCallable, Category = "Spectr AI") + void FinishMove(class USpectrContext* InContext, class AAIController* AIController, class USpectrBrainComponent* Brain); + + /* + Call Super::NativeExecute if you want to execute OnExecuted BP event, or call it manually. + + Remember to call NativeFinished() somewhere, to indicate that Action finished execution. + */ + virtual void NativeExecute(class USpectrContext* InContext, class AAIController* AIController, class USpectrBrainComponent* Brain); + + virtual float NativeScore(class USpectrContext* InContext, class AAIController* AIController); + + virtual bool NativeEvaluateCondition(class USpectrContext* InContext, class AAIController* AIController); + + /* + Remember to call it always after Action has finished execution. Otherwise Action Queue will be stuck. + */ + void NativeFinished(); + + UFUNCTION(BlueprintImplementableEvent, Category = "Spectr AI") + void OnExecute(class USpectrContext* InContext, class AAIController* AIController, class USpectrBrainComponent* Brain); + + UFUNCTION(BlueprintCallable, Category = "Spectr AI") + void ActionFinished(); + + UFUNCTION(BlueprintNativeEvent) + float Score(class USpectrContext* InContext, class AAIController* AIController); + virtual float Score_Implementation(class USpectrContext* InContext, class AAIController* AIController); + + UFUNCTION(BlueprintNativeEvent) + bool EvaluateCondition(class USpectrContext* InContext, class AAIController* AIController); + virtual bool EvaluateCondition_Implementation(class USpectrContext* InContext, class AAIController* AIController); + + + + + UFUNCTION(BlueprintCallable) + void MoveToTarget(AActor* Target, float MinimumDistance); +}; diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrBrainComponent.cpp b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrBrainComponent.cpp new file mode 100644 index 0000000..9a38a52 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrBrainComponent.cpp @@ -0,0 +1,175 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SpectrBrainComponent.h" +#include "SpectrContext.h" +#include "AIController.h" +#include "Engine/World.h" +#include "TimerManager.h" + +bool operator==(const FSpectrNode& Other, const USpectrAction*& Action) +{ + return Other.Action == Action; +} + +USpectrBrainComponent::USpectrBrainComponent(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + FSMState = ESpectrState::Idle; + if(Context) + CurrentContext = Cast(CreateDefaultSubobject(TEXT("CurrentContext"), Context, Context, true, false, false)); +} + +void USpectrBrainComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + //check for new goals + //evaluate if new goal is worth pursuing over the current one. +} +void USpectrBrainComponent::BeginPlay() +{ + Super::BeginPlay(); + if (AAIController* AIController = Cast(GetOwner())) + { + AIController->GetPathFollowingComponent()->OnRequestFinished.AddUObject(this, &USpectrBrainComponent::OnMoveFinished); + } + for (const TSubclassOf& ActionClass : ActionList) + { + USpectrAction* Action = NewObject(this, ActionClass); + Action->OwningBrain = this; + Actions.Add(Action); + } +} +void USpectrBrainComponent::StarPlanning() +{ + //no point of running planner on clients. + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + return; + } + + TArray OutActionList; + if (AAIController* AIController = Cast(GetOwner())) + { + SpectrAI.Plan(Goal, CurrentState, OutActionList, Actions, CurrentContext, AIController); + } + for (int32 Idx = OutActionList.Num() - 1; Idx >= 0; Idx--) + { + FString name = OutActionList[Idx]->GetName(); + + PendingPlan.Add(OutActionList[Idx]); + PendingPlan2.Enqueue(OutActionList[Idx]); + + UE_LOG(LogTemp, Log, TEXT("Action Name: %s \n"), *name); + } + if (OutActionList.Num() == 0) + { + FTimerManager& Timer = GetWorld()->GetTimerManager(); + FTimerDelegate del = FTimerDelegate::CreateUObject(this, &USpectrBrainComponent::NextPlan); + Timer.SetTimer(NextPlanTimerHandle, del, 0.2f, false, 0.2f); + } + else + { + ExecutePlan(nullptr); + } + +} +void USpectrBrainComponent::NextPlan() +{ + TArray OutActionList; + if (AAIController* AIController = Cast(GetOwner())) + { + SpectrAI.Plan(Goal, CurrentState, OutActionList, Actions, CurrentContext, AIController); + } + if (OutActionList.Num() == 0) + { + FTimerManager& Timer = GetWorld()->GetTimerManager(); + FTimerDelegate del = FTimerDelegate::CreateUObject(this, &USpectrBrainComponent::NextPlan); + Timer.SetTimer(NextPlanTimerHandle, del, 0.2f, false, 0.2f); + } + else + { + ExecutePlan(nullptr); + } + +} +void USpectrBrainComponent::SelectGoal() +{ + +} + +void USpectrBrainComponent::ExecutePlan(class USpectrAction* PreviousAction) +{ + if (PendingPlan2.IsEmpty()) + { + //plan finished + StarPlanning(); //plan again + //in reality look for new goal. + return; + } + while (!PendingPlan2.IsEmpty()) + { + USpectrAction* OutAction; + PendingPlan2.Dequeue(OutAction); + if (OutAction != PreviousAction) + { + CurrentAction = OutAction; + break; + } + } + /*if (PendingPlan.Num() && PendingPlan[0]) + { + CurrentAction = PendingPlan[0]; + PendingPlan.RemoveAt(0, 1, true); + }*/ + if (AAIController* AIController = Cast(GetOwner())) + { + //Not in range + if (!CurrentAction->NativeIsInRange(AIController)) + { + FSMState = ESpectrState::Move; + CurrentAction->NativeMoveTo(this); + FSimpleDelegate Delegate = FSimpleDelegate::CreateUObject(CurrentAction, &USpectrAction::NativeOnMoveFinished, CurrentContext, AIController, this); + PendingMoveEvent = Delegate; + } + else //in range, just execute action. + { + FSMState = ESpectrState::Action; + CurrentAction->NativeExecute(CurrentContext, AIController, this); + } + // + } +} +void USpectrBrainComponent::AbortPlan(const FString& Reason) +{ + +} +void USpectrBrainComponent::OnActionFinished(USpectrAction* InAction) +{ + ExecutePlan(InAction); +} +void USpectrBrainComponent::OnMoveFinished(FAIRequestID RequestID, const FPathFollowingResult& Result) +{ + if (AAIController* AIController = Cast(GetOwner())) + { + if (CurrentAction) + { + CurrentAction->NativeOnMoveFinished(CurrentContext, AIController, this); + } + } + //PendingMoveEvent.ExecuteIfBound(); + //PendingMoveEvent.Unbind(); + //ExecutePlan(); +} + +void USpectrBrainComponent::MoveToLocation() +{ + FSMState = ESpectrState::Move; +} +void USpectrBrainComponent::MoveToActor(AActor* Target, float MinDistance) +{ + FSMState = ESpectrState::Move; + if (AAIController* AIController = Cast(GetOwner())) + { + AIController->MoveToActor(Target, MinDistance); + } +} \ No newline at end of file diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrBrainComponent.h b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrBrainComponent.h new file mode 100644 index 0000000..332e97b --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrBrainComponent.h @@ -0,0 +1,323 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameplayTasksComponent.h" +#include "GameplayTags.h" +#include "GameplayTagContainer.h" +#include "Queue.h" +#include "SpectrAction.h" +#include "Navigation/PathFollowingComponent.h" +#include "AITypes.h" + +#include "SpectrBrainComponent.generated.h" + +enum class ESpectrState : uint8 +{ + Idle = 0, + Action = 1, + Move = 2 +}; + +//Node representing single step in plan. +struct FSpectrNode +{ + int32 Cost; + float Score; + int32 RemainingCost; + TWeakPtr Parent; + TMap State; + USpectrAction* Action; + TArray> Children; + FSpectrNode() {} + FSpectrNode(const TMap& InState, int32 InCost, int32 InRemainingCost) + : Cost(InCost) + , RemainingCost(InRemainingCost) + , State(InState) + {} + + bool Equals(USpectrAction* InAction) + { + return Action == InAction; + } + + bool operator==(const FSpectrNode& Other) const + { + return Action == Other.Action; + } + bool operator==(const USpectrAction*& Other) const + { + return Action == Other; + } + +}; + +bool operator==(const FSpectrNode& Other, const USpectrAction*& Action); + + +USTRUCT(BlueprintType) +struct SPECTRAI_API FSpectrAI +{ + GENERATED_BODY() +public: + //Precondition, List of action for this precondition; + TMap> > ActionMap; + + bool CheckGoal(const TMap& InEffects, const TMap& InGoal) + { + bool bAchieved = false; + for (TPair Test : InGoal) + { + UE_LOG(LogTemp, Log, TEXT("---Build Plan - Check Current Key %s Value %d \n"), *Test.Key.ToString(), Test.Value); + } + + for (TPair Test : InEffects) + { + if (InGoal.Contains(Test.Key)) + { + if (InGoal[Test.Key] == Test.Value) + { + UE_LOG(LogTemp, Log, TEXT("----Build Plan - Check Passed Test %s Value %d \n"), *Test.Key.ToString(), Test.Value); + bAchieved = true; + } + else + { + UE_LOG(LogTemp, Log, TEXT("----Build Plan - Check Failed Test %s Value %d \n"), *Test.Key.ToString(), Test.Value); + bAchieved = false; + break; //all or nothing. + } + } + } + + + return bAchieved; + } + + TMap UpdateState(const TMap& InEffects, + const TMap& InCurrentState) + { + TMap NewState; + NewState.Append(InCurrentState); + for (TPair Effect : InEffects) + { + if (NewState.Contains(Effect.Key)) + { + bool* dd = NewState.Find(Effect.Key); + *dd = Effect.Value; + } + } + return NewState; + } + + TMap AddGoalChanges(const TMap& InCurrentGoal, + const TMap& InGoalChange) + { + TMap NewSet; + + NewSet.Append(InCurrentGoal); + UE_LOG(LogTemp, Log, TEXT("---Build Plan - AddGoalChanges PRE START")); + for (TPair Test : InCurrentGoal) + { + UE_LOG(LogTemp, Log, TEXT("---Build Plan - Key %s Value %d \n"), *Test.Key.ToString(), Test.Value); + } + UE_LOG(LogTemp, Log, TEXT("---Build Plan - AddGoalChanges PRE END")); + for (TPair Change : InGoalChange) + { + if (NewSet.Contains(Change.Key)) + { + /*bool* dd = NewSet.Find(Change.Key); + *dd = Change.Value;*/ + } + else + { + NewSet.Add(Change.Key, Change.Value); + } + } + UE_LOG(LogTemp, Log, TEXT("---Build Plan - AddGoalChanges POST START")); + for (TPair Test : NewSet) + { + UE_LOG(LogTemp, Log, TEXT("---Build Plan - Key %s Value %d \n"), *Test.Key.ToString(), Test.Value); + } + UE_LOG(LogTemp, Log, TEXT("---Build Plan - AddGoalChanges POST END")); + return NewSet; + } + void InitializeMap(const TArray>& ActionList) + { + for (const TSubclassOf Action : ActionList) + { + for (const TPair& Effect : Action.GetDefaultObject()->Effects) + { + TArray>& ActionArray = ActionMap.FindOrAdd(Effect.Key); + ActionArray.Add(Action); + } + + } + } + void Plan(const TMap& InTargetGoal, const TMap& InCurrentState + , TArray& InActionQueue + , const TArray& ActionList + , class USpectrContext* InContext + , class AAIController* AIController) + { + TArray> OpenNodes; + TArray> ClosedNodes; + + TSharedPtr Node = MakeShareable(new FSpectrNode(InTargetGoal, 0, 0)); + + //actually made action when constructing node path. + //and then execute it in reverse (from last item in array to first). + //so we don't was time traversing node tree and then reordering actions.. + TArray ActionPlan; + + OpenNodes.Push(Node); + + TArray AvailableActions = ActionList; + + //reverse A*, or something similiar to it at least.. + while (OpenNodes.Num()) + { + TSharedPtr CurrentNode = OpenNodes.Pop(); + ClosedNodes.Push(CurrentNode); + + for (USpectrAction*& Action : AvailableActions) + { + //or instead of pushing to closed actions... we can remove them for Available Actions hmm ? + if (ClosedNodes.ContainsByPredicate([&](const TSharedPtr& Item) + { + return Item->Equals(Action); + })) + { + continue; + } + + if (!(CurrentNode->Action == Action)) + { + if (CheckGoal(Action->Effects, CurrentNode->State)) + { + //action scored Zero, so it probabaly can't be used anyway. + if (!Action->NativeEvaluateCondition(InContext, AIController)) + { + continue; + } + float Score = Action->NativeScore(InContext, AIController); + + TSharedPtr Node2 = MakeShareable(new FSpectrNode(Action->PreConditions, Action->Cost, 0)); + Node2->Action = Action; + Node2->Score = Score; + OpenNodes.Add(Node2); + + if (CurrentNode->Children.Num() == 0) + { + CurrentNode->Children.Add(Node2); + ActionPlan.Add(Action); + } + else + { + //add new action, only if it is cheaper than current one. + //very primitive we need to check if the actuall path will be cheaper. + //so compare current cost of the path with + if (Score > Node2->Score) + { + ActionPlan.Remove(CurrentNode->Children[0]->Action); + CurrentNode->Children.Empty(); + CurrentNode->Children.Add(Node2); + + ActionPlan.Add(Action); + } + else + { + //action has been discarded, remove it from OpenNodes + OpenNodes.Remove(Node2); + //and add to closed nodes. No reason to ever consider it again. + ClosedNodes.Add(Node2); + } + } + } + } + } + } + + InActionQueue = ActionPlan; + } +}; + +USTRUCT(BlueprintType) +struct FGoalSpec +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Instanced) + class USpectrGoal* Goal; + UPROPERTY(EditAnywhere, Instanced) + TArray Considerations; +}; + +/** + * + */ +UCLASS() +class SPECTRAI_API USpectrBrainComponent : public UGameplayTasksComponent +{ + GENERATED_BODY() +public: + ESpectrState FSMState; + + UPROPERTY(EditAnywhere) + TMap Goal; + UPROPERTY(EditAnywhere) + TMap CurrentState; + UPROPERTY(EditAnywhere) + TArray> ActionList; + UPROPERTY() + TArray Actions; + UPROPERTY(EditAnywhere) + TArray Goals2; + + UPROPERTY(EditAnywhere, Instanced) + TArray Goals; + UPROPERTY() + class USpectrGoal* CurrentGoal; + + + UPROPERTY() + TArray PendingPlan; + + TQueue PendingPlan2; + + UPROPERTY() + USpectrAction* CurrentAction; + + + + UPROPERTY(EditAnywhere) + TSubclassOf Context; + UPROPERTY() + class USpectrContext* CurrentContext; + + FSpectrAI SpectrAI; + + //Map of pending move events. + FSimpleDelegate PendingMoveEvent; + + FTimerHandle NextPlanTimerHandle; + + USpectrBrainComponent(const FObjectInitializer& ObjectInitializer); + virtual void BeginPlay() override; + virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override; + UFUNCTION(BlueprintCallable) + void StarPlanning(); + UFUNCTION() + void NextPlan(); + + void SelectGoal(); + void ExecutePlan(class USpectrAction* PreviousAction); + void AbortPlan(const FString& Reason); + void OnActionFinished(USpectrAction* InAction); + void OnMoveFinished(FAIRequestID RequestID, const FPathFollowingResult& Result); + + void MoveToLocation(); + void MoveToActor(AActor* Target, float MinDistance); + + +}; diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrConsideration.cpp b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrConsideration.cpp new file mode 100644 index 0000000..88cf50e --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrConsideration.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SpectrConsideration.h" + + + + diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrConsideration.h b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrConsideration.h new file mode 100644 index 0000000..da8ec6e --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrConsideration.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "SpectrConsideration.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable, EditInLineNew) +class SPECTRAI_API USpectrConsideration : public UObject +{ + GENERATED_BODY() + +public: + virtual float Score() const { return 0; } + +}; diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrContext.cpp b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrContext.cpp new file mode 100644 index 0000000..988813d --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrContext.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SpectrContext.h" + + + + diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrContext.h b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrContext.h new file mode 100644 index 0000000..8822a25 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrContext.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "SpectrContext.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAI_API USpectrContext : public UObject +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrEvaluator.cpp b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrEvaluator.cpp new file mode 100644 index 0000000..37d9944 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrEvaluator.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SpectrEvaluator.h" + + + + diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrEvaluator.h b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrEvaluator.h new file mode 100644 index 0000000..673ff31 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrEvaluator.h @@ -0,0 +1,72 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "SpectrConsideration.h" +#include "SpectrEvaluator.generated.h" + + +//USTRUCT(BlueprintType) +//struct SPECTRAI_API FSpectrConsideration +//{ +// GENERATED_BODY() +//public: +// virtual float Score() const { return 0; } +// virtual ~FSpectrConsideration() +// {} +//}; + +USTRUCT(BlueprintType) +struct SPECTRAI_API FSpectrQualifier +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Instanced) + TArray Considerations; +public: + virtual ~FSpectrQualifier() + {} + virtual float Qualify() const + { + float TotalScore = 0; + for (USpectrConsideration* Consideration : Considerations) + { + TotalScore += Consideration->Score(); + } + return TotalScore; + } +}; + +USTRUCT(BlueprintType) +struct SPECTRAI_API FSpectrEvaluator +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere) + FSpectrQualifier Qualifier; + + mutable float Score; + + float Evaluate() const + { + Score = 0; + float score = Qualifier.Qualify(); + Score = score; + return score; + } +}; + +/** + * + */ +//UCLASS() +//class SPECTRAI_API USpectrEvaluator : public UObject +//{ +// GENERATED_BODY() +// +// +// +// +//}; diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrGoal.cpp b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrGoal.cpp new file mode 100644 index 0000000..3b2ccbf --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrGoal.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SpectrGoal.h" + + + + diff --git a/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrGoal.h b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrGoal.h new file mode 100644 index 0000000..f2b5ca8 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/Public/SpectrGoal.h @@ -0,0 +1,63 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "GameplayTags.h" +#include "GameplayTagContainer.h" +#include "SpectrEvaluator.h" +#include "SpectrGoal.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable, EditInLineNew) +class SPECTRAI_API USpectrGoal : public UObject +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere) + TMap Goal; + + //What to change in state if goal has been achieved ? + UPROPERTY(EditAnywhere) + TMap FinishedState; + + UPROPERTY(EditAnywhere, Instanced) + TArray Considerations; + + UPROPERTY(EditAnywhere) + FSpectrEvaluator ScoreEvaluator; + + virtual float QualifyGoal(class USpectrContext* InContext) + { + return -1.0f; + } + + //What Should we do if this goal is selected ? + virtual void GoalSelected() + { + + } + + //Called when goal has been selected, just before plan is executed. + virtual void GoalStarted() + { + + } + + //called just after plan finished execution + virtual void GoalFinished() + { + + } + + //called if plan for some reason cannot be finished and is aborted. + virtual void GoalAborted() + { + + } + + +}; diff --git a/Plugins/SpectrAI/Source/SpectrAI/SpectrAI.Build.cs b/Plugins/SpectrAI/Source/SpectrAI/SpectrAI.Build.cs new file mode 100644 index 0000000..7611a7c --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAI/SpectrAI.Build.cs @@ -0,0 +1,52 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class SpectrAI : ModuleRules +{ + public SpectrAI(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "SpectrAI/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "Core", + "CoreUObject", + "Engine", + "InputCore", + "Slate", + "SlateCore", + "AIModule", + "GameplayTags", + "GameplayTasks" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrAIEditor.cpp b/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrAIEditor.cpp new file mode 100644 index 0000000..7e6a50e --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrAIEditor.cpp @@ -0,0 +1,20 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "SpectrAIEditor.h" + +#define LOCTEXT_NAMESPACE "FSpectrAIEditor" + +void FSpectrAIEditorModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FSpectrAIEditorModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FSpectrAIEditorModule, SpectrAIEditor) \ No newline at end of file diff --git a/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrAIEditor.h b/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrAIEditor.h new file mode 100644 index 0000000..7b2e8e7 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrAIEditor.h @@ -0,0 +1,15 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "ModuleManager.h" + +class FSpectrAIEditorModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; \ No newline at end of file diff --git a/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrGoalCustomization.cpp b/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrGoalCustomization.cpp new file mode 100644 index 0000000..6269568 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrGoalCustomization.cpp @@ -0,0 +1,12 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "SpectrGoalCustomization.h" + +TSharedRef FSpectrGoalCustomization::MakeInstance() +{ + return MakeShareable(new FSpectrGoalCustomization()); +} +void FSpectrGoalCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) +{ + +} \ No newline at end of file diff --git a/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrGoalCustomization.h b/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrGoalCustomization.h new file mode 100644 index 0000000..767e7f9 --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAIEditor/Public/SpectrGoalCustomization.h @@ -0,0 +1,17 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrGoal.h" + +#include "IDetailCustomization.h" +#include "PropertyHandle.h" + +class FSpectrGoalCustomization : public IDetailCustomization +{ +public: + /** Makes a new instance of this detail layout class for a specific detail view requesting it */ + static TSharedRef MakeInstance(); + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override; +}; \ No newline at end of file diff --git a/Plugins/SpectrAI/Source/SpectrAIEditor/SpectrAIEditor.Build.cs b/Plugins/SpectrAI/Source/SpectrAIEditor/SpectrAIEditor.Build.cs new file mode 100644 index 0000000..73c1d2c --- /dev/null +++ b/Plugins/SpectrAI/Source/SpectrAIEditor/SpectrAIEditor.Build.cs @@ -0,0 +1,55 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class SpectrAIEditor : ModuleRules +{ + public SpectrAIEditor(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "SpectrAIEditor/Private", + "SpectrAI/Private" + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "Core", + "CoreUObject", + "Engine", + "InputCore", + "Slate", + "SlateCore", + "AIModule", + "UnrealEd", + "PropertyEditor", + "GameplayTags", + "GameplayTasks", + "SpectrAI" + // ... add private dependencies that you statically link with here ... + } + ); + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/SpectrAI/SpectrAI.uplugin b/Plugins/SpectrAI/SpectrAI.uplugin new file mode 100644 index 0000000..0dea0d0 --- /dev/null +++ b/Plugins/SpectrAI/SpectrAI.uplugin @@ -0,0 +1,28 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "SpectrAI", + "Description": "", + "Category": "Other", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "SpectrAI", + "Type": "Runtime", + "LoadingPhase": "Default" + }, + { + "Name": "SpectrAIEditor", + "Type": "Editor", + "LoadingPhase": "Default" + } + ] +} \ No newline at end of file diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAIControllerBase.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAIControllerBase.cpp new file mode 100644 index 0000000..7b04f84 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAIControllerBase.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAIControllerBase.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAIControllerBase.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAIControllerBase.h new file mode 100644 index 0000000..f79cf73 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAIControllerBase.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAIController.h" +#include "STestAIControllerBase.generated.h" + +/** + * + */ +UCLASS() +class SPECTRAITEST_API ASTestAIControllerBase : public ASpectrAIController +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopFirewood.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopFirewood.cpp new file mode 100644 index 0000000..793d1af --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopFirewood.cpp @@ -0,0 +1,54 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_ChopFirewood.h" +#include "AIController.h" +#include "SpectrBrainComponent.h" +#include "STestTree.h" +#include "EngineUtils.h" + +bool USTestAction_ChopFirewood::NativeIsInRange(class AAIController* AIController) +{ + //We can evaluate again here if we have target, and if it worth going. + //we can either find better fit or abort plan at this point. + bool bInRange = false; + if (TargetTree) + { + APawn* Pawn = AIController->GetPawn(); + FVector Position = Pawn->GetActorLocation(); + FVector TargetPosition = TargetTree->GetActorLocation(); + float Distance = FVector::Dist(Position, TargetPosition); + if (Distance < MinDistance) + { + bInRange = true; + } + } + return bInRange; +} +void USTestAction_ChopFirewood::NativeMoveTo(class USpectrBrainComponent* Brain) +{ + Brain->MoveToActor(TargetTree, MinDistance); +} +void USTestAction_ChopFirewood::NativeOnMoveFinished(class USpectrContext* InContext + , class AAIController* AIController + , class USpectrBrainComponent* Brain) +{ + NativeExecute(InContext, AIController, Brain); +} +//void USTestAction_ChopFirewood::NativeExecute(class USpectrContext* InContext +// , class AAIController* AIController +// , class USpectrBrainComponent* Brain) +//{ +// NativeFinished(); +//} + +bool USTestAction_ChopFirewood::NativeEvaluateCondition(class USpectrContext* InContext, class AAIController* AIController) +{ + bool bFound = false; + for (TActorIterator ActorIt(AIController->GetWorld()); ActorIt; ++ActorIt) + { + TargetTree = *ActorIt; + bFound = true; + break; + } + return bFound; +} \ No newline at end of file diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopFirewood.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopFirewood.h new file mode 100644 index 0000000..d2378c8 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopFirewood.h @@ -0,0 +1,36 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_ChopFirewood.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_ChopFirewood : public USpectrAction +{ + GENERATED_BODY() + + UPROPERTY() + AActor* TargetTree; + UPROPERTY(EditAnywhere) + float MinDistance; + +public: + virtual bool NativeIsInRange(class AAIController* AIController) override; + virtual void NativeMoveTo(class USpectrBrainComponent* Brain) override; + virtual void NativeOnMoveFinished(class USpectrContext* InContext + , class AAIController* AIController + , class USpectrBrainComponent* Brain) override; + + //virtual void NativeExecute(class USpectrContext* InContext + // , class AAIController* AIController + // , class USpectrBrainComponent* Brain) override; + + virtual bool NativeEvaluateCondition(class USpectrContext* InContext, class AAIController* AIController); + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopWood.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopWood.cpp new file mode 100644 index 0000000..001a874 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopWood.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_ChopWood.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopWood.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopWood.h new file mode 100644 index 0000000..4428927 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_ChopWood.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_ChopWood.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_ChopWood : public USpectrAction +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectBranches.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectBranches.cpp new file mode 100644 index 0000000..876aefc --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectBranches.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_CollectBranches.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectBranches.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectBranches.h new file mode 100644 index 0000000..bae50a2 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectBranches.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_CollectBranches.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_CollectBranches : public USpectrAction +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectOre.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectOre.cpp new file mode 100644 index 0000000..3800d2d --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectOre.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_CollectOre.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectOre.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectOre.h new file mode 100644 index 0000000..212463b --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_CollectOre.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_CollectOre.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_CollectOre : public USpectrAction +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropFirewood.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropFirewood.cpp new file mode 100644 index 0000000..e23a260 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropFirewood.cpp @@ -0,0 +1,52 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_DropFirewood.h" +#include "AIController.h" +#include "SpectrBrainComponent.h" +#include "STestStorage.h" +#include "EngineUtils.h" + +bool USTestAction_DropFirewood::NativeIsInRange(class AAIController* AIController) +{ + bool bInRange = false; + if (TargetDropPoint) + { + APawn* Pawn = AIController->GetPawn(); + FVector Position = Pawn->GetActorLocation(); + FVector TargetPosition = TargetDropPoint->GetActorLocation(); + float Distance = FVector::Dist(Position, TargetPosition); + if (Distance < MinDistance) + { + bInRange = true; + } + } + return bInRange; +} +void USTestAction_DropFirewood::NativeMoveTo(class USpectrBrainComponent* Brain) +{ + Brain->MoveToActor(TargetDropPoint, MinDistance); +} +void USTestAction_DropFirewood::NativeOnMoveFinished(class USpectrContext* InContext + , class AAIController* AIController + , class USpectrBrainComponent* Brain) +{ + NativeExecute(InContext, AIController, Brain); +} +void USTestAction_DropFirewood::NativeExecute(class USpectrContext* InContext + , class AAIController* AIController + , class USpectrBrainComponent* Brain) +{ + NativeFinished(); +} + +bool USTestAction_DropFirewood::NativeEvaluateCondition(class USpectrContext* InContext, class AAIController* AIController) +{ + bool bFound = false; + for (TActorIterator ActorIt(AIController->GetWorld()); ActorIt; ++ActorIt) + { + TargetDropPoint = *ActorIt; + bFound = true; + break; + } + return bFound; +} \ No newline at end of file diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropFirewood.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropFirewood.h new file mode 100644 index 0000000..9a8cb95 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropFirewood.h @@ -0,0 +1,36 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_DropFirewood.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_DropFirewood : public USpectrAction +{ + GENERATED_BODY() + + UPROPERTY() + AActor* TargetDropPoint; + UPROPERTY(EditAnywhere) + float MinDistance; + +public: + virtual bool NativeIsInRange(class AAIController* AIController) override; + virtual void NativeMoveTo(class USpectrBrainComponent* Brain) override; + virtual void NativeOnMoveFinished(class USpectrContext* InContext + , class AAIController* AIController + , class USpectrBrainComponent* Brain) override; + + virtual void NativeExecute(class USpectrContext* InContext + , class AAIController* AIController + , class USpectrBrainComponent* Brain) override; + + virtual bool NativeEvaluateCondition(class USpectrContext* InContext, class AAIController* AIController); + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropOre.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropOre.cpp new file mode 100644 index 0000000..d017aad --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropOre.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_DropOre.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropOre.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropOre.h new file mode 100644 index 0000000..2883ff4 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropOre.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_DropOre.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_DropOre : public USpectrAction +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropWood.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropWood.cpp new file mode 100644 index 0000000..0cafb3b --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropWood.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_DropWood.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropWood.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropWood.h new file mode 100644 index 0000000..04fb1c8 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_DropWood.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_DropWood.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_DropWood : public USpectrAction +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_GoTo.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_GoTo.cpp new file mode 100644 index 0000000..365c590 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_GoTo.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_GoTo.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_GoTo.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_GoTo.h new file mode 100644 index 0000000..393bce0 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_GoTo.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_GoTo.generated.h" + +/** + * + */ +UCLASS() +class SPECTRAITEST_API USTestAction_GoTo : public USpectrAction +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakeAxe.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakeAxe.cpp new file mode 100644 index 0000000..c9b4702 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakeAxe.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_MakeAxe.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakeAxe.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakeAxe.h new file mode 100644 index 0000000..030d66c --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakeAxe.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_MakeAxe.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_MakeAxe : public USpectrAction +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakePick.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakePick.cpp new file mode 100644 index 0000000..a50a2b5 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakePick.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_MakePick.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakePick.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakePick.h new file mode 100644 index 0000000..b694046 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MakePick.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_MakePick.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_MakePick : public USpectrAction +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MineOre.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MineOre.cpp new file mode 100644 index 0000000..6c91e77 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MineOre.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_MineOre.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MineOre.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MineOre.h new file mode 100644 index 0000000..6472f2e --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_MineOre.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_MineOre.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_MineOre : public USpectrAction +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemAxe.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemAxe.cpp new file mode 100644 index 0000000..eeb7171 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemAxe.cpp @@ -0,0 +1,52 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_PickItemAxe.h" +#include "AIController.h" +#include "SpectrBrainComponent.h" +#include "STestAxePickup.h" +#include "EngineUtils.h" + +bool USTestAction_PickItemAxe::NativeIsInRange(class AAIController* AIController) +{ + bool bInRange = false; + if (TargetItem) + { + APawn* Pawn = AIController->GetPawn(); + FVector Position = Pawn->GetActorLocation(); + FVector TargetPosition = TargetItem->GetActorLocation(); + float Distance = FVector::Dist(Position, TargetPosition); + if (Distance < MinDistance) + { + bInRange = true; + } + } + return bInRange; +} +void USTestAction_PickItemAxe::NativeMoveTo(class USpectrBrainComponent* Brain) +{ + Brain->MoveToActor(TargetItem, MinDistance); +} +void USTestAction_PickItemAxe::NativeOnMoveFinished(class USpectrContext* InContext + , class AAIController* AIController + , class USpectrBrainComponent* Brain) +{ + NativeExecute(InContext, AIController, Brain); +} +void USTestAction_PickItemAxe::NativeExecute(class USpectrContext* InContext + , class AAIController* AIController + , class USpectrBrainComponent* Brain) +{ + NativeFinished(); +} + +bool USTestAction_PickItemAxe::NativeEvaluateCondition(class USpectrContext* InContext, class AAIController* AIController) +{ + bool bFound = false; + for (TActorIterator ActorIt(AIController->GetWorld()); ActorIt; ++ActorIt) + { + TargetItem = *ActorIt; + bFound = true; + break; + } + return bFound; +} \ No newline at end of file diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemAxe.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemAxe.h new file mode 100644 index 0000000..e1a25f0 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemAxe.h @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_PickItemAxe.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_PickItemAxe : public USpectrAction +{ + GENERATED_BODY() +protected: + /* Minimum distance from item to pick it. */ + UPROPERTY(EditAnywhere) + float MinDistance; + UPROPERTY() + AActor* TargetItem; +public: + virtual bool NativeIsInRange(class AAIController* AIController) override; + virtual void NativeMoveTo(class USpectrBrainComponent* Brain) override; + virtual void NativeOnMoveFinished(class USpectrContext* InContext + , class AAIController* AIController + , class USpectrBrainComponent* Brain) override; + + virtual void NativeExecute(class USpectrContext* InContext + , class AAIController* AIController + , class USpectrBrainComponent* Brain) override; + + virtual bool NativeEvaluateCondition(class USpectrContext* InContext, class AAIController* AIController); +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemPick.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemPick.cpp new file mode 100644 index 0000000..4d1578b --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemPick.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAction_PickItemPick.h" + + + + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemPick.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemPick.h new file mode 100644 index 0000000..a22eaff --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAction_PickItemPick.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "SpectrAction.h" +#include "STestAction_PickItemPick.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class SPECTRAITEST_API USTestAction_PickItemPick : public USpectrAction +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAxePickup.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAxePickup.cpp new file mode 100644 index 0000000..a25fb52 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAxePickup.cpp @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestAxePickup.h" + + +// Sets default values +ASTestAxePickup::ASTestAxePickup() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + +} + +// Called when the game starts or when spawned +void ASTestAxePickup::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void ASTestAxePickup::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAxePickup.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAxePickup.h new file mode 100644 index 0000000..970ff76 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestAxePickup.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "STestAxePickup.generated.h" + +UCLASS() +class SPECTRAITEST_API ASTestAxePickup : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ASTestAxePickup(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestBranch.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestBranch.cpp new file mode 100644 index 0000000..9296a87 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestBranch.cpp @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestBranch.h" + + +// Sets default values +ASTestBranch::ASTestBranch() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + +} + +// Called when the game starts or when spawned +void ASTestBranch::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void ASTestBranch::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestBranch.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestBranch.h new file mode 100644 index 0000000..2c1755a --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestBranch.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "STestBranch.generated.h" + +UCLASS() +class SPECTRAITEST_API ASTestBranch : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ASTestBranch(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestForge.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestForge.cpp new file mode 100644 index 0000000..22d4aa4 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestForge.cpp @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestForge.h" + + +// Sets default values +ASTestForge::ASTestForge() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + +} + +// Called when the game starts or when spawned +void ASTestForge::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void ASTestForge::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestForge.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestForge.h new file mode 100644 index 0000000..21f2f0e --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestForge.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "STestForge.generated.h" + +UCLASS() +class SPECTRAITEST_API ASTestForge : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ASTestForge(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestStorage.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestStorage.cpp new file mode 100644 index 0000000..a28db48 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestStorage.cpp @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestStorage.h" + + +// Sets default values +ASTestStorage::ASTestStorage() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + +} + +// Called when the game starts or when spawned +void ASTestStorage::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void ASTestStorage::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestStorage.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestStorage.h new file mode 100644 index 0000000..fcf1463 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestStorage.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "STestStorage.generated.h" + +UCLASS() +class SPECTRAITEST_API ASTestStorage : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ASTestStorage(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestTree.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestTree.cpp new file mode 100644 index 0000000..cc09e79 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestTree.cpp @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "STestTree.h" + + +// Sets default values +ASTestTree::ASTestTree() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + +} + +// Called when the game starts or when spawned +void ASTestTree::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void ASTestTree::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestTree.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestTree.h new file mode 100644 index 0000000..1c0cb6c --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/STestTree.h @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "STestTree.generated.h" + +UCLASS() +class SPECTRAITEST_API ASTestTree : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ASTestTree(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + + +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/SpectrAITest.cpp b/Plugins/SpectrAITest/Source/SpectrAITest/Public/SpectrAITest.cpp new file mode 100644 index 0000000..ebd2517 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/SpectrAITest.cpp @@ -0,0 +1,20 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#include "SpectrAITest.h" + +#define LOCTEXT_NAMESPACE "FSpectrAITestModule" + +void FSpectrAITestModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FSpectrAITestModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FSpectrAITestModule, SpectrAITest) \ No newline at end of file diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/Public/SpectrAITest.h b/Plugins/SpectrAITest/Source/SpectrAITest/Public/SpectrAITest.h new file mode 100644 index 0000000..8f51c72 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/Public/SpectrAITest.h @@ -0,0 +1,15 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class FSpectrAITestModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/Plugins/SpectrAITest/Source/SpectrAITest/SpectrAITest.Build.cs b/Plugins/SpectrAITest/Source/SpectrAITest/SpectrAITest.Build.cs new file mode 100644 index 0000000..018c2d4 --- /dev/null +++ b/Plugins/SpectrAITest/Source/SpectrAITest/SpectrAITest.Build.cs @@ -0,0 +1,53 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class SpectrAITest : ModuleRules +{ + public SpectrAITest(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "SpectrAITest/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "Core", + "CoreUObject", + "Engine", + "InputCore", + "Slate", + "SlateCore", + "AIModule", + "GameplayTags", + "GameplayTasks", + "SpectrAI" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/SpectrAITest/SpectrAITest.uplugin b/Plugins/SpectrAITest/SpectrAITest.uplugin new file mode 100644 index 0000000..fbc88e1 --- /dev/null +++ b/Plugins/SpectrAITest/SpectrAITest.uplugin @@ -0,0 +1,29 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "SpectrAITest", + "Description": "", + "Category": "Other", + "CreatedBy": "", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "SpectrAITest", + "Type": "Developer", + "LoadingPhase": "Default" + } + ], + "Plugins": [ + { + "Name": "SpectrAI", + "Enabled": true + } + ] +} \ No newline at end of file diff --git a/Plugins/TimeOfDay/Source/TimeOfDay/Private/TimeOfDay.cpp b/Plugins/TimeOfDay/Source/TimeOfDay/Private/TimeOfDay.cpp new file mode 100644 index 0000000..6db1c67 --- /dev/null +++ b/Plugins/TimeOfDay/Source/TimeOfDay/Private/TimeOfDay.cpp @@ -0,0 +1,20 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "TimeOfDay.h" + +#define LOCTEXT_NAMESPACE "FTimeOfDayModule" + +void FTimeOfDayModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FTimeOfDayModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FTimeOfDayModule, TimeOfDay) \ No newline at end of file diff --git a/Plugins/TimeOfDay/Source/TimeOfDay/Public/TimeOfDay.h b/Plugins/TimeOfDay/Source/TimeOfDay/Public/TimeOfDay.h new file mode 100644 index 0000000..1dc167f --- /dev/null +++ b/Plugins/TimeOfDay/Source/TimeOfDay/Public/TimeOfDay.h @@ -0,0 +1,15 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "ModuleManager.h" + +class FTimeOfDayModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; \ No newline at end of file diff --git a/Plugins/TimeOfDay/Source/TimeOfDay/TimeOfDay.Build.cs b/Plugins/TimeOfDay/Source/TimeOfDay/TimeOfDay.Build.cs new file mode 100644 index 0000000..5e2f864 --- /dev/null +++ b/Plugins/TimeOfDay/Source/TimeOfDay/TimeOfDay.Build.cs @@ -0,0 +1,47 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class TimeOfDay : ModuleRules +{ + public TimeOfDay(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "TimeOfDay/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/WeaponFramework/Source/WeaponFramework/Private/WeaponFramework.cpp b/Plugins/WeaponFramework/Source/WeaponFramework/Private/WeaponFramework.cpp new file mode 100644 index 0000000..a6f7d38 --- /dev/null +++ b/Plugins/WeaponFramework/Source/WeaponFramework/Private/WeaponFramework.cpp @@ -0,0 +1,20 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#include "WeaponFramework.h" + +#define LOCTEXT_NAMESPACE "FWeaponFrameworkModule" + +void FWeaponFrameworkModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FWeaponFrameworkModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FWeaponFrameworkModule, WeaponFramework) \ No newline at end of file diff --git a/Plugins/WeaponFramework/Source/WeaponFramework/Public/WeaponFramework.h b/Plugins/WeaponFramework/Source/WeaponFramework/Public/WeaponFramework.h new file mode 100644 index 0000000..50e98a9 --- /dev/null +++ b/Plugins/WeaponFramework/Source/WeaponFramework/Public/WeaponFramework.h @@ -0,0 +1,15 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class FWeaponFrameworkModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/Plugins/WeaponFramework/Source/WeaponFramework/WeaponFramework.Build.cs b/Plugins/WeaponFramework/Source/WeaponFramework/WeaponFramework.Build.cs new file mode 100644 index 0000000..27f87a3 --- /dev/null +++ b/Plugins/WeaponFramework/Source/WeaponFramework/WeaponFramework.Build.cs @@ -0,0 +1,48 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class WeaponFramework : ModuleRules +{ + public WeaponFramework(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "WeaponFramework/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "AbilityFramework" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditor.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditor.cpp new file mode 100644 index 0000000..9bf851f --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditor.cpp @@ -0,0 +1,610 @@ +#include "WALandscapeGraphAssetEditor.h" +#include "WALandscapeGraphAssetEditorToolbar.h" +#include "WALandscapeGraphSchema.h" +#include "WALandscapeGraphEditorCommands.h" +#include "WALandscapeGraphEdGraph.h" +#include "AssetToolsModule.h" +#include "WALandscapeGraphAssetEditorToolbar.h" +#include "PropertyEditorModule.h" +#include "BlueprintEditorUtils.h" +#include "EdGraphUtilities.h" +#include "ScopedTransaction.h" +#include "PlatformApplicationMisc.h" +#include "WALandscapeGraph.h" +#include "WALandscapeGraphEdNode_Output.h" + +#define LOCTEXT_NAMESPACE "GenericGraphAssetEditor" + +const FName GenericGraphEditorAppName = FName(TEXT("LandscapeGraphEditor")); + +struct FWALandscapeGraphAssetEditorTabs +{ + // Tab identifiers + static const FName DetailsID; + static const FName ViewportID; +}; + +////////////////////////////////////////////////////////////////////////// + +const FName FWALandscapeGraphAssetEditorTabs::DetailsID(TEXT("Details")); +const FName FWALandscapeGraphAssetEditorTabs::ViewportID(TEXT("Viewport")); + +////////////////////////////////////////////////////////////////////////// + +FWALandscapeGraphAssetEditor::FWALandscapeGraphAssetEditor() +{ + EditingGraph = nullptr; + + OnPackageSavedDelegateHandle = UPackage::PackageSavedEvent.AddRaw(this, &FWALandscapeGraphAssetEditor::OnPackageSaved); +} + +FWALandscapeGraphAssetEditor::~FWALandscapeGraphAssetEditor() +{ + UPackage::PackageSavedEvent.Remove(OnPackageSavedDelegateHandle); +} + +void FWALandscapeGraphAssetEditor::InitGenericGraphAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, UWALandscapeGraph* Graph) +{ + EditingGraph = Graph; + CreateEdGraph(); + + FGenericCommands::Register(); + FGraphEditorCommands::Register(); + FWALandscapeGraphEditorCommands::Register(); + + if (!ToolbarBuilder.IsValid()) + { + ToolbarBuilder = MakeShareable(new FWALandscapeGraphAssetEditorToolbar(SharedThis(this))); + } + + BindCommands(); + + CreateInternalWidgets(); + + TSharedPtr ToolbarExtender = MakeShareable(new FExtender); + + ToolbarBuilder->AddGenericGraphToolbar(ToolbarExtender); + + // Layout + const TSharedRef StandaloneDefaultLayout = FTabManager::NewLayout("Standalone_GenericGraphEditor_Layout_v1") + ->AddArea + ( + FTabManager::NewPrimaryArea()->SetOrientation(Orient_Vertical) + ->Split + ( + FTabManager::NewStack() + ->SetSizeCoefficient(0.1f) + ->AddTab(GetToolbarTabId(), ETabState::OpenedTab)->SetHideTabWell(true) + ) + ->Split + ( + FTabManager::NewSplitter()->SetOrientation(Orient_Horizontal)->SetSizeCoefficient(0.9f) + ->Split + ( + FTabManager::NewStack() + ->SetSizeCoefficient(0.225f) + ->AddTab(FWALandscapeGraphAssetEditorTabs::ViewportID, ETabState::OpenedTab) + ) + ->Split + ( + FTabManager::NewStack() + ->SetSizeCoefficient(0.65f) + ->AddTab(FWALandscapeGraphAssetEditorTabs::DetailsID, ETabState::OpenedTab)->SetHideTabWell(true) + ) + ) + ); + + const bool bCreateDefaultStandaloneMenu = true; + const bool bCreateDefaultToolbar = true; + FAssetEditorToolkit::InitAssetEditor(Mode, InitToolkitHost, GenericGraphEditorAppName, StandaloneDefaultLayout, bCreateDefaultStandaloneMenu, bCreateDefaultToolbar, EditingGraph, false); + + RegenerateMenusAndToolbars(); +} + +void FWALandscapeGraphAssetEditor::RegisterTabSpawners(const TSharedRef& InTabManager) +{ + WorkspaceMenuCategory = InTabManager->AddLocalWorkspaceMenuCategory(LOCTEXT("WorkspaceMenu_SoundCueEditor", "Sound Cue Editor")); + auto WorkspaceMenuCategoryRef = WorkspaceMenuCategory.ToSharedRef(); + + FAssetEditorToolkit::RegisterTabSpawners(InTabManager); + + InTabManager->RegisterTabSpawner(FWALandscapeGraphAssetEditorTabs::ViewportID, FOnSpawnTab::CreateSP(this, &FWALandscapeGraphAssetEditor::SpawnTab_Viewport)) + .SetDisplayName(LOCTEXT("GraphCanvasTab", "Viewport")) + .SetGroup(WorkspaceMenuCategoryRef) + .SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "GraphEditor.EventGraph_16x")); + + InTabManager->RegisterTabSpawner(FWALandscapeGraphAssetEditorTabs::DetailsID, FOnSpawnTab::CreateSP(this, &FWALandscapeGraphAssetEditor::SpawnTab_Details)) + .SetDisplayName(LOCTEXT("DetailsTab", "Details")) + .SetGroup(WorkspaceMenuCategoryRef) + .SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tabs.Details")); +} + +void FWALandscapeGraphAssetEditor::UnregisterTabSpawners(const TSharedRef& InTabManager) +{ + FAssetEditorToolkit::UnregisterTabSpawners(InTabManager); + + InTabManager->UnregisterTabSpawner(FWALandscapeGraphAssetEditorTabs::ViewportID); + InTabManager->UnregisterTabSpawner(FWALandscapeGraphAssetEditorTabs::DetailsID); +} + +FName FWALandscapeGraphAssetEditor::GetToolkitFName() const +{ + return FName("FGenericGraphEditor"); +} + +FText FWALandscapeGraphAssetEditor::GetBaseToolkitName() const +{ + return LOCTEXT("GenericGraphEditorAppLabel", "Generic Graph Editor"); +} + +FText FWALandscapeGraphAssetEditor::GetToolkitName() const +{ + const bool bDirtyState = EditingGraph->GetOutermost()->IsDirty(); + + FFormatNamedArguments Args; + Args.Add(TEXT("GenericGraphName"), FText::FromString(EditingGraph->GetName())); + Args.Add(TEXT("DirtyState"), bDirtyState ? FText::FromString(TEXT("*")) : FText::GetEmpty()); + return FText::Format(LOCTEXT("GenericGraphEditorToolkitName", "{GenericGraphName}{DirtyState}"), Args); +} + +FText FWALandscapeGraphAssetEditor::GetToolkitToolTipText() const +{ + return FAssetEditorToolkit::GetToolTipTextForObject(EditingGraph); +} + +FLinearColor FWALandscapeGraphAssetEditor::GetWorldCentricTabColorScale() const +{ + return FLinearColor::White; +} + +FString FWALandscapeGraphAssetEditor::GetWorldCentricTabPrefix() const +{ + return TEXT("GenericGraphEditor"); +} + +FString FWALandscapeGraphAssetEditor::GetDocumentationLink() const +{ + return TEXT(""); +} + +void FWALandscapeGraphAssetEditor::SaveAsset_Execute() +{ + if (EditingGraph != nullptr) + { + RebuildGenericGraph(); + } + + FAssetEditorToolkit::SaveAsset_Execute(); +} + +void FWALandscapeGraphAssetEditor::AddReferencedObjects(FReferenceCollector& Collector) +{ + Collector.AddReferencedObject(EditingGraph); + Collector.AddReferencedObject(EditingGraph->EdGraph); +} + +TSharedRef FWALandscapeGraphAssetEditor::SpawnTab_Viewport(const FSpawnTabArgs& Args) +{ + check(Args.GetTabId() == FWALandscapeGraphAssetEditorTabs::ViewportID); + + TSharedRef SpawnedTab = SNew(SDockTab) + .Label(FText::FromString("Viewport")); + + if (ViewportWidget.IsValid()) + { + SpawnedTab->SetContent(ViewportWidget.ToSharedRef()); + } + + return SpawnedTab; +} + +TSharedRef FWALandscapeGraphAssetEditor::SpawnTab_Details(const FSpawnTabArgs& Args) +{ + check(Args.GetTabId() == FWALandscapeGraphAssetEditorTabs::DetailsID); + + return SNew(SDockTab) + .Icon(FEditorStyle::GetBrush("LevelEditor.Tabs.Details")) + .Label(FText::FromString("Details")) + [ + PropertyWidget.ToSharedRef() + ]; +} + +void FWALandscapeGraphAssetEditor::CreateInternalWidgets() +{ + ViewportWidget = CreateViewportWidget(); + + FDetailsViewArgs Args; + Args.bHideSelectionTip = true; + Args.NotifyHook = this; + + FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked("PropertyEditor"); + PropertyWidget = PropertyModule.CreateDetailView(Args); + PropertyWidget->SetObject(EditingGraph); + + //PropertyWidget->SetIsPropertyEditingEnabledDelegate(FIsPropertyEditingEnabled::CreateSP(this, &FWALandscapeGraphAssetEditor::IsPropertyEditable)); + PropertyWidget->OnFinishedChangingProperties().AddSP(this, &FWALandscapeGraphAssetEditor::OnFinishedChangingProperties); +} + +TSharedRef FWALandscapeGraphAssetEditor::CreateViewportWidget() +{ + FGraphAppearanceInfo AppearanceInfo; + AppearanceInfo.CornerText = FText::FromString("Landscape Graph"); + + CreateCommandList(); + + SGraphEditor::FGraphEditorEvents InEvents; + InEvents.OnSelectionChanged = SGraphEditor::FOnSelectionChanged::CreateSP(this, &FWALandscapeGraphAssetEditor::OnSelectedNodesChanged); + InEvents.OnNodeDoubleClicked = FSingleNodeEvent::CreateSP(this, &FWALandscapeGraphAssetEditor::OnNodeDoubleClicked); + + return SNew(SGraphEditor) + .AdditionalCommands(GraphEditorCommands) + .IsEditable(true) + .Appearance(AppearanceInfo) + .GraphToEdit(EditingGraph->EdGraph) + .GraphEvents(InEvents) + .AutoExpandActionMenu(true) + .ShowGraphStateOverlay(false); +} + + +void FWALandscapeGraphAssetEditor::BindCommands() +{ + ToolkitCommands->MapAction(FWALandscapeGraphEditorCommands::Get().GraphSettings, + FExecuteAction::CreateSP(this, &FWALandscapeGraphAssetEditor::GraphSettings), + FCanExecuteAction::CreateSP(this, &FWALandscapeGraphAssetEditor::CanGraphSettings) + ); + ToolkitCommands->MapAction(FWALandscapeGraphEditorCommands::Get().GenerateLandscape, + FExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::GenerateLandscape)); +} + +void FWALandscapeGraphAssetEditor::CreateEdGraph() +{ + if (EditingGraph->EdGraph == nullptr) + { + EditingGraph->EdGraph = CastChecked(FBlueprintEditorUtils::CreateNewGraph(EditingGraph, NAME_None, UWALandscapeGraphEdGraph::StaticClass(), UWALandscapeGraphSchema::StaticClass())); + EditingGraph->EdGraph->bAllowDeletion = false; + + // Give the schema a chance to fill out any required nodes (like the results node) + const UEdGraphSchema* Schema = EditingGraph->EdGraph->GetSchema(); + Schema->CreateDefaultNodesForGraph(*EditingGraph->EdGraph); + + EditingGraph->Schema = Cast(const_cast(Schema)); + } +} + +void FWALandscapeGraphAssetEditor::CreateCommandList() +{ + if (GraphEditorCommands.IsValid()) + { + return; + } + + GraphEditorCommands = MakeShareable(new FUICommandList); + + // Can't use CreateSP here because derived editor are already implementing TSharedFromThis + // however it should be safe, since commands are being used only within this editor + // if it ever crashes, this function will have to go away and be reimplemented in each derived class + + GraphEditorCommands->MapAction(FWALandscapeGraphEditorCommands::Get().GraphSettings, + FExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::GraphSettings), + FCanExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::CanGraphSettings)); + + GraphEditorCommands->MapAction(FWALandscapeGraphEditorCommands::Get().GenerateLandscape, + FExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::GenerateLandscape)); + + GraphEditorCommands->MapAction(FGenericCommands::Get().SelectAll, + FExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::SelectAllNodes), + FCanExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::CanSelectAllNodes) + ); + + GraphEditorCommands->MapAction(FGenericCommands::Get().Delete, + FExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::DeleteSelectedNodes), + FCanExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::CanDeleteNodes) + ); + + GraphEditorCommands->MapAction(FGenericCommands::Get().Copy, + FExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::CopySelectedNodes), + FCanExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::CanCopyNodes) + ); + + GraphEditorCommands->MapAction(FGenericCommands::Get().Cut, + FExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::CutSelectedNodes), + FCanExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::CanCutNodes) + ); + + GraphEditorCommands->MapAction(FGenericCommands::Get().Paste, + FExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::PasteNodes), + FCanExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::CanPasteNodes) + ); + + GraphEditorCommands->MapAction(FGenericCommands::Get().Duplicate, + FExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::DuplicateNodes), + FCanExecuteAction::CreateRaw(this, &FWALandscapeGraphAssetEditor::CanDuplicateNodes) + ); +} + +TSharedPtr FWALandscapeGraphAssetEditor::GetCurrGraphEditor() +{ + return ViewportWidget; +} + +FGraphPanelSelectionSet FWALandscapeGraphAssetEditor::GetSelectedNodes() +{ + FGraphPanelSelectionSet CurrentSelection; + TSharedPtr FocusedGraphEd = GetCurrGraphEditor(); + if (FocusedGraphEd.IsValid()) + { + CurrentSelection = FocusedGraphEd->GetSelectedNodes(); + } + + return CurrentSelection; +} + +void FWALandscapeGraphAssetEditor::RebuildGenericGraph() +{ + if (EditingGraph == nullptr) + { + //LOG_WARNING(TEXT("FWALandscapeGraphAssetEditor::RebuildGenericGraph EditingGraph is nullptr")); + return; + } + + UWALandscapeGraphEdGraph* EdGraph = Cast(EditingGraph->EdGraph); + check(EdGraph != nullptr); + + EdGraph->RebuildGenericGraph(); +} + +void FWALandscapeGraphAssetEditor::SelectAllNodes() +{ + TSharedPtr CurrentGraphEditor = GetCurrGraphEditor(); + if (CurrentGraphEditor.IsValid()) + { + CurrentGraphEditor->SelectAllNodes(); + } +} + +bool FWALandscapeGraphAssetEditor::CanSelectAllNodes() +{ + return true; +} + +void FWALandscapeGraphAssetEditor::DeleteSelectedNodes() +{ + TSharedPtr CurrentGraphEditor = GetCurrGraphEditor(); + if (!CurrentGraphEditor.IsValid()) + { + return; + } + + const FScopedTransaction Transaction(FGenericCommands::Get().Delete->GetDescription()); + CurrentGraphEditor->GetCurrentGraph()->Modify(); + + const FGraphPanelSelectionSet SelectedNodes = CurrentGraphEditor->GetSelectedNodes(); + CurrentGraphEditor->ClearSelectionSet(); + + for (FGraphPanelSelectionSet::TConstIterator NodeIt(SelectedNodes); NodeIt; ++NodeIt) + { + if (UEdGraphNode* Node = Cast(*NodeIt)) + { + if (Node->CanUserDeleteNode()) + { + Node->Modify(); + Node->DestroyNode(); + } + } + } + + //LOG_WARNING(TEXT("FWALandscapeGraphAssetEditor::DeleteSelectedNodes Exec")); +} + +bool FWALandscapeGraphAssetEditor::CanDeleteNodes() +{ + // If any of the nodes can be deleted then we should allow deleting + const FGraphPanelSelectionSet SelectedNodes = GetSelectedNodes(); + for (FGraphPanelSelectionSet::TConstIterator SelectedIter(SelectedNodes); SelectedIter; ++SelectedIter) + { + UEdGraphNode* Node = Cast(*SelectedIter); + if (Node != nullptr && Node->CanUserDeleteNode()) + { + return true; + } + } + + //LOG_WARNING(TEXT("FWALandscapeGraphAssetEditor::CanDeleteNodes Can't delete")); + + return false; +} + +void FWALandscapeGraphAssetEditor::DeleteSelectedDuplicatableNodes() +{ + TSharedPtr CurrentGraphEditor = GetCurrGraphEditor(); + if (!CurrentGraphEditor.IsValid()) + { + return; + } + + const FGraphPanelSelectionSet OldSelectedNodes = CurrentGraphEditor->GetSelectedNodes(); + CurrentGraphEditor->ClearSelectionSet(); + + for (FGraphPanelSelectionSet::TConstIterator SelectedIter(OldSelectedNodes); SelectedIter; ++SelectedIter) + { + UEdGraphNode* Node = Cast(*SelectedIter); + if (Node && Node->CanDuplicateNode()) + { + CurrentGraphEditor->SetNodeSelection(Node, true); + } + } + + // Delete the duplicatable nodes + DeleteSelectedNodes(); + + CurrentGraphEditor->ClearSelectionSet(); + + for (FGraphPanelSelectionSet::TConstIterator SelectedIter(OldSelectedNodes); SelectedIter; ++SelectedIter) + { + if (UEdGraphNode* Node = Cast(*SelectedIter)) + { + CurrentGraphEditor->SetNodeSelection(Node, true); + } + } +} + +void FWALandscapeGraphAssetEditor::CutSelectedNodes() +{ + CopySelectedNodes(); + DeleteSelectedDuplicatableNodes(); +} + +bool FWALandscapeGraphAssetEditor::CanCutNodes() +{ + return CanCopyNodes() && CanDeleteNodes(); +} + +void FWALandscapeGraphAssetEditor::CopySelectedNodes() +{ + // Export the selected nodes and place the text on the clipboard + FGraphPanelSelectionSet SelectedNodes = GetSelectedNodes(); + + FString ExportedText; + + for (FGraphPanelSelectionSet::TIterator SelectedIter(SelectedNodes); SelectedIter; ++SelectedIter) + { + UEdGraphNode* Node = Cast(*SelectedIter); + if (Node == nullptr) + { + SelectedIter.RemoveCurrent(); + continue; + } + + Node->PrepareForCopying(); + } + + FEdGraphUtilities::ExportNodesToText(SelectedNodes, ExportedText); + FPlatformApplicationMisc::ClipboardCopy(*ExportedText); +} + +bool FWALandscapeGraphAssetEditor::CanCopyNodes() +{ + // If any of the nodes can be duplicated then we should allow copying + const FGraphPanelSelectionSet SelectedNodes = GetSelectedNodes(); + for (FGraphPanelSelectionSet::TConstIterator SelectedIter(SelectedNodes); SelectedIter; ++SelectedIter) + { + UEdGraphNode* Node = Cast(*SelectedIter); + if (Node && Node->CanDuplicateNode()) + { + return true; + } + } + + return false; +} + +void FWALandscapeGraphAssetEditor::PasteNodes() +{ + TSharedPtr CurrentGraphEditor = GetCurrGraphEditor(); + if (CurrentGraphEditor.IsValid()) + { + PasteNodesHere(CurrentGraphEditor->GetPasteLocation()); + } +} + +void FWALandscapeGraphAssetEditor::PasteNodesHere(const FVector2D& Location) +{ +} + +bool FWALandscapeGraphAssetEditor::CanPasteNodes() +{ + return false; +} + +void FWALandscapeGraphAssetEditor::DuplicateNodes() +{ + CopySelectedNodes(); + PasteNodes(); +} + +bool FWALandscapeGraphAssetEditor::CanDuplicateNodes() +{ + //return CanCopyNodes(); + return false; +} + +void FWALandscapeGraphAssetEditor::GraphSettings() +{ + PropertyWidget->SetObject(EditingGraph); + if (EditingGraph->LandscapeOutput) + { + EditingGraph->LandscapeOutput->GenerateHeightmap(); + } + //LOG_WARNING(TEXT("FWALandscapeGraphAssetEditor::GraphSettings")); +} + +void FWALandscapeGraphAssetEditor::GenerateLandscape() +{ + + if (const UWALandscapeGraphSchema* Schema = Cast(EditingGraph->EdGraph->GetSchema())) + { + TArray out; + Schema->Output->GenerateHeightMap(out); + } + //LOG_WARNING(TEXT("FWALandscapeGraphAssetEditor::GraphSettings")); +} + +bool FWALandscapeGraphAssetEditor::CanGraphSettings() const +{ + return true; +} + +void FWALandscapeGraphAssetEditor::OnSelectedNodesChanged(const TSet& NewSelection) +{ + TArray Selection; + + for (UObject* SelectionEntry : NewSelection) + { + Selection.Add(SelectionEntry); + } + + if (Selection.Num() == 0) + { + PropertyWidget->SetObject(EditingGraph); + + } + else if (Selection.Num() == 1) + { + PropertyWidget->SetObject(Selection[0]); + } + else + { + PropertyWidget->SetObject(nullptr); + } +} + +void FWALandscapeGraphAssetEditor::OnNodeDoubleClicked(UEdGraphNode* Node) +{ + +} + +void FWALandscapeGraphAssetEditor::OnFinishedChangingProperties(const FPropertyChangedEvent& PropertyChangedEvent) +{ + if (EditingGraph == nullptr) + return; + + RebuildGenericGraph(); + + EditingGraph->EdGraph->GetSchema()->ForceVisualizationCacheClear(); +} + +void FWALandscapeGraphAssetEditor::OnPackageSaved(const FString& PackageFileName, UObject* Outer) +{ + RebuildGenericGraph(); +} + +void FWALandscapeGraphAssetEditor::RegisterToolbarTab(const TSharedRef& InTabManager) +{ + FAssetEditorToolkit::RegisterTabSpawners(InTabManager); +} + + +#undef LOCTEXT_NAMESPACE + diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditor.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditor.h new file mode 100644 index 0000000..9f43eb3 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditor.h @@ -0,0 +1,116 @@ +#pragma once +#include "WALandscapeGraphEditorCommands.h" + +#include "GenericCommands.h" +#include "SDockTab.h" +#include "GraphEditor.h" +#include "GraphEditorActions.h" +#include "AssetEditorToolkit.h" +#include "WALandscapeGraph.h" +#include "WALandscapeNode.h" +#include "Misc/NotifyHook.h" +#include "IDetailsView.h" +class FWALandscapeGraphAssetEditorToolbar; + +class FWALandscapeGraphAssetEditor : public FAssetEditorToolkit, public FNotifyHook, public FGCObject +{ +public: + FWALandscapeGraphAssetEditor(); + virtual ~FWALandscapeGraphAssetEditor(); + + void InitGenericGraphAssetEditor(const EToolkitMode::Type Mode, const TSharedPtr< IToolkitHost >& InitToolkitHost, UWALandscapeGraph* Graph); + + // IToolkit interface + virtual void RegisterTabSpawners(const TSharedRef& TabManager) override; + virtual void UnregisterTabSpawners(const TSharedRef& TabManager) override; + // End of IToolkit interface + + // FAssetEditorToolkit + virtual FName GetToolkitFName() const override; + virtual FText GetBaseToolkitName() const override; + virtual FText GetToolkitName() const override; + virtual FText GetToolkitToolTipText() const override; + virtual FLinearColor GetWorldCentricTabColorScale() const override; + virtual FString GetWorldCentricTabPrefix() const override; + virtual FString GetDocumentationLink() const override; + virtual void SaveAsset_Execute() override; + // End of FAssetEditorToolkit + + //Toolbar + void UpdateToolbar(); + TSharedPtr GetToolbarBuilder() { return ToolbarBuilder; } + void RegisterToolbarTab(const TSharedRef& TabManager); + + + // FSerializableObject interface + virtual void AddReferencedObjects(FReferenceCollector& Collector) override; + // End of FSerializableObject interface + +private: + TSharedRef SpawnTab_Viewport(const FSpawnTabArgs& Args); + TSharedRef SpawnTab_Details(const FSpawnTabArgs& Args); + + void CreateInternalWidgets(); + TSharedRef CreateViewportWidget(); + + + void BindCommands(); + + void CreateEdGraph(); + + void CreateCommandList(); + + TSharedPtr GetCurrGraphEditor(); + + FGraphPanelSelectionSet GetSelectedNodes(); + + void RebuildGenericGraph(); + + // Delegates for graph editor commands + void SelectAllNodes(); + bool CanSelectAllNodes(); + void DeleteSelectedNodes(); + bool CanDeleteNodes(); + void DeleteSelectedDuplicatableNodes(); + void CutSelectedNodes(); + bool CanCutNodes(); + void CopySelectedNodes(); + bool CanCopyNodes(); + void PasteNodes(); + void PasteNodesHere(const FVector2D& Location); + bool CanPasteNodes(); + void DuplicateNodes(); + bool CanDuplicateNodes(); + + void GraphSettings(); + void GenerateLandscape(); + bool CanGraphSettings() const; + + ////////////////////////////////////////////////////////////////////////// + // graph editor event + void OnSelectedNodesChanged(const TSet& NewSelection); + + void OnNodeDoubleClicked(UEdGraphNode* Node); + + void OnFinishedChangingProperties(const FPropertyChangedEvent& PropertyChangedEvent); + + void OnPackageSaved(const FString& PackageFileName, UObject* Outer); + + +private: + UWALandscapeGraph* EditingGraph; + + //Toolbar + TSharedPtr ToolbarBuilder; + + /** Handle to the registered OnPackageSave delegate */ + FDelegateHandle OnPackageSavedDelegateHandle; + + TSharedPtr ViewportWidget; + TSharedPtr PropertyWidget; + + /** The command list for this editor */ + TSharedPtr GraphEditorCommands; +}; + + diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditorToolbar.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditorToolbar.cpp new file mode 100644 index 0000000..dd919df --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditorToolbar.cpp @@ -0,0 +1,51 @@ +#include "WALandscapeGraphAssetEditorToolbar.h" +#include "WALandscapeGraphAssetEditor.h" +#include "WALandscapeGraphEditorCommands.h" +#include "MultiBoxBuilder.h" + +#define LOCTEXT_NAMESPACE "GenericGraphAssetEditorToolbar" + +void FWALandscapeGraphAssetEditorToolbar::AddGenericGraphToolbar(TSharedPtr Extender) +{ + check(GenericGraphEditor.IsValid()); + TSharedPtr GenericGraphEditorPtr = GenericGraphEditor.Pin(); + + TSharedPtr ToolbarExtender = MakeShareable(new FExtender); + ToolbarExtender->AddToolBarExtension("Asset", EExtensionHook::After, GenericGraphEditorPtr->GetToolkitCommands(), FToolBarExtensionDelegate::CreateSP( this, &FWALandscapeGraphAssetEditorToolbar::FillGenericGraphToolbar )); + GenericGraphEditorPtr->AddToolbarExtender(ToolbarExtender); +} + +void FWALandscapeGraphAssetEditorToolbar::FillGenericGraphToolbar(FToolBarBuilder& ToolbarBuilder) +{ + check(GenericGraphEditor.IsValid()); + TSharedPtr GenericGraphEditorPtr = GenericGraphEditor.Pin(); + + ToolbarBuilder.BeginSection("Landscape Graph"); + { + { + const FText GraphSettingsLabel = LOCTEXT("GraphSettings_Label", "Graph Settings"); + const FText GraphSettingsTip = LOCTEXT("GraphSettings_ToolTip", "Show the Graph Settings"); + const FSlateIcon GraphSettingsIcon = FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.GameSettings"); + ToolbarBuilder.AddToolBarButton(FWALandscapeGraphEditorCommands::Get().GraphSettings, + NAME_None, + GraphSettingsLabel, + GraphSettingsTip, + GraphSettingsIcon); + } + { + const FText GraphSettingsLabel = LOCTEXT("GraphSettings_Label", "Generate Landscape"); + const FText GraphSettingsTip = LOCTEXT("GraphSettings_ToolTip", "enerate LAndscape from Current graph"); + const FSlateIcon GraphSettingsIcon = FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.GameSettings"); + ToolbarBuilder.AddToolBarButton(FWALandscapeGraphEditorCommands::Get().GenerateLandscape, + NAME_None, + GraphSettingsLabel, + GraphSettingsTip, + GraphSettingsIcon); + } + } + ToolbarBuilder.EndSection(); + +} + + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditorToolbar.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditorToolbar.h new file mode 100644 index 0000000..970caf7 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphAssetEditorToolbar.h @@ -0,0 +1,28 @@ + +#pragma once + +#include "CoreMinimal.h" + +class FWALandscapeGraphAssetEditor; +class FExtender; +class FToolBarBuilder; + +class FWALandscapeGraphAssetEditorToolbar : public TSharedFromThis +{ +public: + FWALandscapeGraphAssetEditorToolbar(TSharedPtr InGenericGraphEditor) + : GenericGraphEditor(InGenericGraphEditor) {} + + //void AddModesToolbar(TSharedPtr Extender); + //void AddDebuggerToolbar(TSharedPtr Extender); + void AddGenericGraphToolbar(TSharedPtr Extender); + +private: + //void FillModesToolbar(FToolBarBuilder& ToolbarBuilder); + //void FillDebuggerToolbar(FToolBarBuilder& ToolbarBuilder); + void FillGenericGraphToolbar(FToolBarBuilder& ToolbarBuilder); + +protected: + /** Pointer back to the blueprint editor tool that owns us */ + TWeakPtr GenericGraphEditor; +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphColors.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphColors.h new file mode 100644 index 0000000..805f26e --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphColors.h @@ -0,0 +1,43 @@ +#pragma once + +namespace WALandscapeGraphColors +{ + namespace NodeBody + { + const FLinearColor Default(0.1f, 0.1f, 0.1f); + const FLinearColor Root(0.5f, 0.5f, 0.5f, 0.1f); + const FLinearColor Error(1.0f, 0.0f, 0.0f); + } + + namespace NodeBorder + { + const FLinearColor Inactive(0.08f, 0.08f, 0.08f); + const FLinearColor Root(0.2f, 0.2f, 0.2f, 0.2f); + const FLinearColor Selected(1.00f, 0.08f, 0.08f); + const FLinearColor ActiveDebugging(1.0f, 1.0f, 0.0f); + const FLinearColor InactiveDebugging(0.4f, 0.4f, 0.0f); + const FLinearColor HighlightAbortRange0(0.0f, 0.22f, 0.4f); + const FLinearColor HighlightAbortRange1(0.0f, 0.4f, 0.22f); + const FLinearColor Disconnected(0.f, 0.f, 0.f); + const FLinearColor BrokenWithParent(1.f, 0.f, 1.f); + const FLinearColor QuickFind(0.f, 0.8f, 0.f); + } + + namespace Pin + { + const FLinearColor Diff(0.9f, 0.2f, 0.15f); + const FLinearColor Hover(1.0f, 0.7f, 0.0f); + const FLinearColor Default(0.02f, 0.02f, 0.02f); + const FLinearColor SingleNode(0.02f, 0.02f, 0.02f); + } + + namespace Connection + { + const FLinearColor Default(1.0f, 1.0f, 1.0f); + } + + namespace Action + { + const FLinearColor DragMarker(1.0f, 1.0f, 0.2f); + } +} diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphConnectionDrawingPolicy.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphConnectionDrawingPolicy.cpp new file mode 100644 index 0000000..bad80ff --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphConnectionDrawingPolicy.cpp @@ -0,0 +1,117 @@ +#include "WALandscapeGraphConnectionDrawingPolicy.h" + +FWALandscapeGraphConnectionDrawingPolicy::FWALandscapeGraphConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float ZoomFactor, const FSlateRect& InClippingRect, FSlateWindowElementList& InDrawElements, UEdGraph* InGraphObj) + : FConnectionDrawingPolicy(InBackLayerID, InFrontLayerID, ZoomFactor, InClippingRect, InDrawElements) + , GraphObj(InGraphObj) +{ +} + +void FWALandscapeGraphConnectionDrawingPolicy::DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ FConnectionParams& Params) +{ + Params.AssociatedPin1 = OutputPin; + Params.AssociatedPin2 = InputPin; + Params.WireThickness = 1.5f; + + const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0; + if (bDeemphasizeUnhoveredPins) + { + ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Params.WireThickness, /*inout*/ Params.WireColor); + } +} + +void FWALandscapeGraphConnectionDrawingPolicy::Draw(TMap, FArrangedWidget>& InPinGeometries, FArrangedChildren& ArrangedNodes) +{ + // Build an acceleration structure to quickly find geometry for the nodes + NodeWidgetMap.Empty(); + for (int32 NodeIndex = 0; NodeIndex < ArrangedNodes.Num(); ++NodeIndex) + { + FArrangedWidget& CurWidget = ArrangedNodes[NodeIndex]; + TSharedRef ChildNode = StaticCastSharedRef(CurWidget.Widget); + NodeWidgetMap.Add(ChildNode->GetNodeObj(), NodeIndex); + } + + // Now draw + FConnectionDrawingPolicy::Draw(InPinGeometries, ArrangedNodes); +} + +void FWALandscapeGraphConnectionDrawingPolicy::DrawPreviewConnector(const FGeometry& PinGeometry, const FVector2D& StartPoint, const FVector2D& EndPoint, UEdGraphPin* Pin) +{ + FConnectionParams Params; + DetermineWiringStyle(Pin, nullptr, /*inout*/ Params); + + if (Pin->Direction == EEdGraphPinDirection::EGPD_Output) + { + DrawSplineWithArrow(FGeometryHelper::FindClosestPointOnGeom(PinGeometry, EndPoint), EndPoint, Params); + } + else + { + DrawSplineWithArrow(FGeometryHelper::FindClosestPointOnGeom(PinGeometry, StartPoint), StartPoint, Params); + } +} + +void FWALandscapeGraphConnectionDrawingPolicy::DrawSplineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params) +{ + // bUserFlag1 indicates that we need to reverse the direction of connection (used by debugger) + const FVector2D& P0 = Params.bUserFlag1 ? EndAnchorPoint : StartAnchorPoint; + const FVector2D& P1 = Params.bUserFlag1 ? StartAnchorPoint : EndAnchorPoint; + + Internal_DrawLineWithArrow(P0, P1, Params); +} + +void FWALandscapeGraphConnectionDrawingPolicy::Internal_DrawLineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params) +{ + //@TODO: Should this be scaled by zoom factor? + const float LineSeparationAmount = 4.5f; + + const FVector2D DeltaPos = EndAnchorPoint - StartAnchorPoint; + const FVector2D UnitDelta = DeltaPos.GetSafeNormal(); + const FVector2D Normal = FVector2D(DeltaPos.Y, -DeltaPos.X).GetSafeNormal(); + + // Come up with the final start/end points + const FVector2D DirectionBias = Normal * LineSeparationAmount; + const FVector2D LengthBias = ArrowRadius.X * UnitDelta; + const FVector2D StartPoint = StartAnchorPoint + DirectionBias + LengthBias; + const FVector2D EndPoint = EndAnchorPoint + DirectionBias - LengthBias; + + // Draw a line/spline + DrawConnection(WireLayerID, StartPoint, EndPoint, Params); + + // Draw the arrow + const FVector2D ArrowDrawPos = EndPoint - ArrowRadius; + const float AngleInRadians = FMath::Atan2(DeltaPos.Y, DeltaPos.X); + + FSlateDrawElement::MakeRotatedBox( + DrawElementsList, + ArrowLayerID, + FPaintGeometry(ArrowDrawPos, ArrowImage->ImageSize * ZoomFactor, ZoomFactor), + ArrowImage, + ESlateDrawEffect::None, + AngleInRadians, + TOptional(), + FSlateDrawElement::RelativeToElement, + Params.WireColor + ); +} + +void FWALandscapeGraphConnectionDrawingPolicy::DrawSplineWithArrow(const FGeometry& StartGeom, const FGeometry& EndGeom, const FConnectionParams& Params) +{ + // Get a reasonable seed point (halfway between the boxes) + const FVector2D StartCenter = FGeometryHelper::CenterOf(StartGeom); + const FVector2D EndCenter = FGeometryHelper::CenterOf(EndGeom); + const FVector2D SeedPoint = (StartCenter + EndCenter) * 0.5f; + + // Find the (approximate) closest points between the two boxes + const FVector2D StartAnchorPoint = FGeometryHelper::FindClosestPointOnGeom(StartGeom, SeedPoint); + const FVector2D EndAnchorPoint = FGeometryHelper::FindClosestPointOnGeom(EndGeom, SeedPoint); + + DrawSplineWithArrow(StartAnchorPoint, EndAnchorPoint, Params); +} + +FVector2D FWALandscapeGraphConnectionDrawingPolicy::ComputeSplineTangent(const FVector2D& Start, const FVector2D& End) const +{ + const FVector2D Delta = End - Start; + const FVector2D NormDelta = Delta.GetSafeNormal(); + + return NormDelta; +} + diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphConnectionDrawingPolicy.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphConnectionDrawingPolicy.h new file mode 100644 index 0000000..16a62be --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphConnectionDrawingPolicy.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ConnectionDrawingPolicy.h" + +class FWALandscapeGraphConnectionDrawingPolicy : public FConnectionDrawingPolicy +{ +protected: + UEdGraph* GraphObj; + TMap NodeWidgetMap; + +public: + FWALandscapeGraphConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float ZoomFactor, const FSlateRect& InClippingRect, FSlateWindowElementList& InDrawElements, UEdGraph* InGraphObj); + + // FConnectionDrawingPolicy interface + virtual void DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ FConnectionParams& Params) override; + virtual void Draw(TMap, FArrangedWidget>& PinGeometries, FArrangedChildren& ArrangedNodes) override; + virtual void DrawSplineWithArrow(const FGeometry& StartGeom, const FGeometry& EndGeom, const FConnectionParams& Params) override; + virtual void DrawSplineWithArrow(const FVector2D& StartPoint, const FVector2D& EndPoint, const FConnectionParams& Params) override; + virtual void DrawPreviewConnector(const FGeometry& PinGeometry, const FVector2D& StartPoint, const FVector2D& EndPoint, UEdGraphPin* Pin) override; + virtual FVector2D ComputeSplineTangent(const FVector2D& Start, const FVector2D& End) const override; + // End of FConnectionDrawingPolicy interface + +protected: + void Internal_DrawLineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params); +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdGraph.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdGraph.cpp new file mode 100644 index 0000000..7e24b85 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdGraph.cpp @@ -0,0 +1,76 @@ +#include "WALandscapeGraphEdGraph.h" +#include "WALandscapeGraphEdNode.h" +#include "WALandscapeGraph.h" +#include "WALandscapeGraphEdGraph.h" +#include "WALandscapeGraphEditorTypes.h" +#include "EdGraph/EdGraphPin.h" + +UWALandscapeGraphEdGraph::UWALandscapeGraphEdGraph() +{ + +} + +UWALandscapeGraphEdGraph::~UWALandscapeGraphEdGraph() +{ + +} + +void UWALandscapeGraphEdGraph::RebuildGenericGraph() +{ + //UWALandscapeGraph* G = CastChecked(GetOuter()); + + //G->ClearGraph(); + //for (int i = 0; i < Nodes.Num(); ++i) + //{ + // UWALandscapeGraphEdNode* EdNode = Cast(Nodes[i]); + + // if (EdNode == nullptr || EdNode->GenericGraphNode == nullptr) + // continue; + + // UWALandscapeNode* GNode = EdNode->GenericGraphNode; + + // G->AllNodes.Add(GNode); + // GNode->MaskNode = nullptr; + // for (int PinIdx = 0; PinIdx < EdNode->Pins.Num(); ++PinIdx) + // { + // UEdGraphPin* Pin = EdNode->Pins[PinIdx]; + + // if (Pin->Direction == EEdGraphPinDirection::EGPD_Input + // && Pin->PinType.PinCategory == UWALandscapeGraphEditorTypes::PinCategory_MaskInput) + // { + // UWALandscapeGraphEdNode* InputNode = nullptr; + // InputNode = Cast(Pin->GetOwningNode()); + // for (UEdGraphPin* LinkedPin : Pin->LinkedTo) + // { + // if (LinkedPin->Direction == EEdGraphPinDirection::EGPD_Output + // && LinkedPin->PinType.PinCategory == UWALandscapeGraphEditorTypes::PinCategory_SingleNode) + // { + // UWALandscapeGraphEdNode* OutputNode = Cast(LinkedPin->GetOwningNode()); + + // if (OutputNode != InputNode) + // { + // UWALandscapeNode* nodeInput = InputNode->GenericGraphNode; + // UWALandscapeNode* nodeOutput = OutputNode->GenericGraphNode; + // if (nodeInput && nodeOutput) + // { + // nodeInput->MaskNode = nodeOutput; + // } + // } + // } + // } + // } + // } + //} +} + +#if WITH_EDITOR +void UWALandscapeGraphEdGraph::PostEditUndo() +{ + Super::PostEditUndo(); + + RebuildGenericGraph(); + + Modify(); +} +#endif + diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdGraph.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdGraph.h new file mode 100644 index 0000000..e7469cc --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdGraph.h @@ -0,0 +1,19 @@ +#pragma once + +#include "WALandscapeGraphEdGraph.generated.h" + +UCLASS() +class UWALandscapeGraphEdGraph : public UEdGraph +{ + GENERATED_BODY() + +public: + UWALandscapeGraphEdGraph(); + virtual ~UWALandscapeGraphEdGraph(); + + virtual void RebuildGenericGraph(); + +#if WITH_EDITOR + virtual void PostEditUndo() override; +#endif +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode.cpp new file mode 100644 index 0000000..2d4d6ee --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode.cpp @@ -0,0 +1,65 @@ +#include "WALandscapeGraphEdNode.h" +#include "WALandscapeGraphEdGraph.h" +#include "WALandscapeGraph.h" +#include "WALandscapeNode.h" +#include "WALandscapeGraphEditorTypes.h" +#include "EdGraph/EdGraphPin.h" +#define LOCTEXT_NAMESPACE "GenericGraphEdNode" + +void UWALandscapeGraphEdNode::AllocateDefaultPins() +{ + CreatePin(EGPD_Input, UWALandscapeGraphEditorTypes::PinCategory_SingleNode, TEXT("Height Out")); + CreatePin(EGPD_Output, UWALandscapeGraphEditorTypes::PinCategory_MaskInput, TEXT("Height In")); + //CreatePin(EGPD_Output, UWALandscapeGraphEditorTypes::PinCategory_SingleNode, TEXT(""), NULL, false, false, TEXT("Height Out")); + //CreatePin(EGPD_Input, UWALandscapeGraphEditorTypes::PinCategory_MaskInput, TEXT(""), NULL, false, false, TEXT("Mask In")); +} + +void UWALandscapeGraphEdNode::NodeConnectionListChanged() +{ + Super::NodeConnectionListChanged(); + + GetGenericGraphEdGraph()->RebuildGenericGraph(); +} + +UWALandscapeGraphEdGraph* UWALandscapeGraphEdNode::GetGenericGraphEdGraph() +{ + return Cast(GetGraph()); +} + +FText UWALandscapeGraphEdNode::GetNodeTitle(ENodeTitleType::Type TitleType) const +{ + if (GenericGraphNode == nullptr) + { + return Super::GetNodeTitle(TitleType); + } + else + { + return FText::FromString(GenericGraphNode->GetNodeTitle()); + } +} + +void UWALandscapeGraphEdNode::SetGenericGraphNode(UWALandscapeNode* InNode) +{ + GenericGraphNode = InNode; +} + +FText UWALandscapeGraphEdNode::GetDescription() const +{ + UWALandscapeGraph* Graph = GenericGraphNode->GetGraph(); + + return FText::FromString("Dupa Description"); +} + +FLinearColor UWALandscapeGraphEdNode::GetBackgroundColor() const +{ + return GenericGraphNode->BackgroundColor; +} +void UWALandscapeGraphEdNode::PinConnectionListChanged(UEdGraphPin* Pin) +{ + +} +void UWALandscapeGraphEdNode::GenerateHeightMap(TArray& InOutMap) +{ + +} +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode.h new file mode 100644 index 0000000..ed8a3f2 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode.h @@ -0,0 +1,33 @@ +#pragma once +#include "EdGraph/EdGraphNode.h" +#include "WALandscapeGraphEdNode.generated.h" + +UCLASS(MinimalAPI) +class UWALandscapeGraphEdNode : public UEdGraphNode +{ + GENERATED_BODY() + +public: + UPROPERTY() + UWALandscapeGraphEdNode* Output; + + UPROPERTY(VisibleAnywhere, instanced, Category = "GenericGraph") + class UWALandscapeNode* GenericGraphNode; + + virtual void AllocateDefaultPins() override; + virtual void NodeConnectionListChanged() override; + + class UWALandscapeGraphEdGraph* GetGenericGraphEdGraph(); + + virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const; + + void SetGenericGraphNode(UWALandscapeNode* InNode); + + virtual FText GetDescription() const; + + FLinearColor GetBackgroundColor() const; + virtual void PinConnectionListChanged(UEdGraphPin* Pin) override; + + virtual void GenerateHeightMap(TArray& InOutMap); + +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Multiply.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Multiply.cpp new file mode 100644 index 0000000..9e6f9b3 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Multiply.cpp @@ -0,0 +1,79 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "WALandscapeGraphEdNode_Multiply.h" +#include "WALandscapeGraphEditorTypes.h" +#include "../WALandscapeNode_Multiply.h" + + +void UWALandscapeGraphEdNode_Multiply::AllocateDefaultPins() +{ + CreatePin(EGPD_Input, UWALandscapeGraphEditorTypes::PinCategory_InputA, TEXT("In A")); + CreatePin(EGPD_Input, UWALandscapeGraphEditorTypes::PinCategory_InputB, TEXT("In B")); + CreatePin(EGPD_Output, UWALandscapeGraphEditorTypes::PinCategory_Output, TEXT("Out")); +} + +void UWALandscapeGraphEdNode_Multiply::PinConnectionListChanged(UEdGraphPin* Pin) +{ + //UWALandscapeGraphEdNode_Output* InputNode = nullptr; + //UWALandscapeGraphEdNode_Multiply* ThisEdNode = this; + //UWALandscapeNode_Multiply* ThisNode = Cast(ThisEdNode->GenericGraphNode); + UWALandscapeGraphEdNode* ThisEdNode = Cast(Pin->GetOwningNode()); + UWALandscapeNode_Multiply* ThisNode = Cast(ThisEdNode->GenericGraphNode); + + if (Pin->Direction == EEdGraphPinDirection::EGPD_Input) + { + if (Pin->PinType.PinCategory == UWALandscapeGraphEditorTypes::PinCategory_InputA) + { + //InputNode = Cast(Pin->GetOwningNode()); + for (UEdGraphPin* LinkedPin : Pin->LinkedTo) + { + if (LinkedPin->Direction == EEdGraphPinDirection::EGPD_Output + && LinkedPin->PinType.PinCategory == UWALandscapeGraphEditorTypes::PinCategory_Output) + { + UWALandscapeGraphEdNode* InputNode = Cast(LinkedPin->GetOwningNode()); + InputA = InputNode; + if (ThisEdNode != InputNode) + { + UWALandscapeNode* NodeA = InputNode->GenericGraphNode; + ThisNode->InputA = NodeA; + } + } + } + } + else if (Pin->PinType.PinCategory == UWALandscapeGraphEditorTypes::PinCategory_InputB) + { + for (UEdGraphPin* LinkedPin : Pin->LinkedTo) + { + if (LinkedPin->Direction == EEdGraphPinDirection::EGPD_Output + && LinkedPin->PinType.PinCategory == UWALandscapeGraphEditorTypes::PinCategory_Output) + { + UWALandscapeGraphEdNode* InputNode = Cast(LinkedPin->GetOwningNode()); + + if (ThisEdNode != InputNode) + { + InputB = InputNode; + UWALandscapeNode* NodeB = InputNode->GenericGraphNode; + ThisNode->InputB = NodeB; + } + } + } + } + } + else if (Pin->Direction == EEdGraphPinDirection::EGPD_Output) + { + //InputNode = Cast(Pin->GetOwningNode()); + } +} +void UWALandscapeGraphEdNode_Multiply::GenerateHeightMap(TArray& InOutMap) +{ + TArray OutputA; + TArray OutputB; + + if (InputA) + { + InputA->GenerateHeightMap(OutputA); + } + if (InputB) + { + InputB->GenerateHeightMap(OutputB); + } +} diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Multiply.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Multiply.h new file mode 100644 index 0000000..a5e0bf8 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Multiply.h @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "LandscapeGraphEditor/WALandscapeGraphEdNode.h" +#include "WALandscapeGraphEdNode_Multiply.generated.h" + +/** + * + */ +UCLASS() +class WORLDARCHITECTEDITOR_API UWALandscapeGraphEdNode_Multiply : public UWALandscapeGraphEdNode +{ + GENERATED_BODY() +public: + UPROPERTY() + UWALandscapeGraphEdNode* InputA; + UPROPERTY() + UWALandscapeGraphEdNode* InputB; +public: + virtual void AllocateDefaultPins() override; + virtual void PinConnectionListChanged(UEdGraphPin* Pin) override; + + virtual void GenerateHeightMap(TArray& InOutMap) override; +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Output.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Output.cpp new file mode 100644 index 0000000..12fffe2 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Output.cpp @@ -0,0 +1,55 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "WALandscapeGraphEdNode_Output.h" +#include "WALandscapeGraphEditorTypes.h" +#include "WALandscapeNode_Output.h" + + + +void UWALandscapeGraphEdNode_Output::AllocateDefaultPins() +{ + CreatePin(EGPD_Input, UWALandscapeGraphEditorTypes::PinCategory_FinalInput, TEXT("In")); +} + +void UWALandscapeGraphEdNode_Output::PinConnectionListChanged(UEdGraphPin* Pin) +{ + UWALandscapeGraphEdNode_Output* InputNode = nullptr; + UWALandscapeGraphEdNode_Output* NodeToAdd = this; + if (Pin->Direction == EEdGraphPinDirection::EGPD_Input) + { + if (Pin->PinType.PinCategory == UWALandscapeGraphEditorTypes::PinCategory_FinalInput) + { + InputNode = Cast(Pin->GetOwningNode()); + for (UEdGraphPin* LinkedPin : Pin->LinkedTo) + { + if (LinkedPin->Direction == EEdGraphPinDirection::EGPD_Output) + { + UWALandscapeGraphEdNode* OutputNode = Cast(LinkedPin->GetOwningNode()); + + Input = OutputNode; + if (OutputNode != InputNode) + { + UWALandscapeNode_Output* nodeInput = Cast(InputNode->GenericGraphNode); + UWALandscapeNode* nodeOutput = OutputNode->GenericGraphNode; + if (nodeInput && nodeOutput) + { + + nodeInput->Heightmap = nodeOutput; + } + } + } + } + } + } + else if (Pin->Direction == EEdGraphPinDirection::EGPD_Output) + { + //InputNode = Cast(Pin->GetOwningNode()); + } +} +void UWALandscapeGraphEdNode_Output::GenerateHeightMap(TArray& InOutMap) +{ + if (Input) + { + TArray Out; + Input->GenerateHeightMap(Out); + } +} diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Output.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Output.h new file mode 100644 index 0000000..f92ab31 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEdNode_Output.h @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "LandscapeGraphEditor/WALandscapeGraphEdNode.h" +#include "WALandscapeGraphEdNode_Output.generated.h" + +/** + * + */ +UCLASS() +class WORLDARCHITECTEDITOR_API UWALandscapeGraphEdNode_Output : public UWALandscapeGraphEdNode +{ + GENERATED_BODY() +public: + UWALandscapeGraphEdNode* Input; +public: + virtual void AllocateDefaultPins() override; + virtual void PinConnectionListChanged(UEdGraphPin* Pin) override; + + virtual void GenerateHeightMap(TArray& InOutMap) override; +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEditorCommands.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEditorCommands.cpp new file mode 100644 index 0000000..6536709 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEditorCommands.cpp @@ -0,0 +1,12 @@ + +#include "WALandscapeGraphEditorCommands.h" + +#define LOCTEXT_NAMESPACE "GenericGraphEditorCommands" + +void FWALandscapeGraphEditorCommands::RegisterCommands() +{ + UI_COMMAND(GraphSettings, "Graph Settings", "Graph Settings", EUserInterfaceActionType::Button, FInputChord()); + UI_COMMAND(GenerateLandscape, "Generate Landscape", "Generate Landscape", EUserInterfaceActionType::Button, FInputChord()); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEditorCommands.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEditorCommands.h new file mode 100644 index 0000000..cb79380 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphEditorCommands.h @@ -0,0 +1,17 @@ +#pragma once + +class FWALandscapeGraphEditorCommands : public TCommands +{ +public: + /** Constructor */ + FWALandscapeGraphEditorCommands() + : TCommands("GenericGraphEditor", NSLOCTEXT("Contexts", "GenericGraphEditor", "Generic Graph Editor"), NAME_None, FEditorStyle::GetStyleSetName()) + { + } + + TSharedPtr GraphSettings; + + TSharedPtr GenerateLandscape; + + virtual void RegisterCommands() override; +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphSchema.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphSchema.cpp new file mode 100644 index 0000000..ef1886b --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphSchema.cpp @@ -0,0 +1,344 @@ +#include "WALandscapeGraphSchema.h" +#include "WALandscapeGraphEdNode.h" +#include "WALandscapeGraphConnectionDrawingPolicy.h" +#include "WALandscapeGraph.h" +#include "WALandscapeNode.h" +#include "EdGraph/EdGraph.h" +#include "GraphEditorActions.h" +#include "WALandscapeGraphEdNode_Output.h" +#include "WALandscapeNode_Output.h" +#include "WALandscapeGraphEdNode_Multiply.h" +#include "../WALandscapeNode_Multiply.h" +#include "../WALGEdNode_Start.h" +#include "GenericCommands.h" + +#define LOCTEXT_NAMESPACE "GenericGraphAssetSchema" + +int32 UWALandscapeGraphSchema::CurrentCacheRefreshID = 0; + +class FNodeVisitorCycleChecker +{ +public: + /** Check whether a loop in the graph would be caused by linking the passed-in nodes */ + bool CheckForLoop(UEdGraphNode* StartNode, UEdGraphNode* EndNode) + { + VisitedNodes.Add(StartNode); + + return TraverseInputNodesToRoot(EndNode); + } + +private: + bool TraverseInputNodesToRoot(UEdGraphNode* Node) + { + VisitedNodes.Add(Node); + + for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex) + { + UEdGraphPin* MyPin = Node->Pins[PinIndex]; + + if (MyPin->Direction == EGPD_Output) + { + for (int32 LinkedPinIndex = 0; LinkedPinIndex < MyPin->LinkedTo.Num(); ++LinkedPinIndex) + { + UEdGraphPin* OtherPin = MyPin->LinkedTo[LinkedPinIndex]; + if (OtherPin) + { + UEdGraphNode* OtherNode = OtherPin->GetOwningNode(); + if (VisitedNodes.Contains(OtherNode)) + { + return false; + } + else + { + return TraverseInputNodesToRoot(OtherNode); + } + } + } + } + } + + return true; + } + + TSet VisitedNodes; +}; + +UEdGraphNode* FWALandscapeGraphAssetSchemaAction_NewNode::PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode /*= true*/) +{ + UWALandscapeGraph* Graph = CastChecked(ParentGraph->GetOuter()); + + //const FScopedTransaction Transaction(LOCTEXT("GenericGraphEditorNewNode", "Generic Graph Editor: New Node")); + ParentGraph->Modify(); + Graph->Modify(); + + UWALandscapeNode* NewNode = NewObject(Graph, NodeType); + + //Graph->AllNodes.Add(NewNode); + + //FGraphNodeCreator NodeCreator(*Graph->EdGraph); + //UWALandscapeGraphEdNode* GraphNode = NodeCreator.CreateNode(true); + //GraphNode->SetGenericGraphNode(NewNode); + //NodeCreator.Finalize(); + + //GraphNode->NodePosX = Location.X; + //GraphNode->NodePosY = Location.Y; + + //GraphNode->AutowireNewNode(FromPin); + + //Graph->PostEditChange(); + //Graph->MarkPackageDirty(); + + //return GraphNode; + + UEdGraphNode* ResultNode = NULL; + + // If there is a template, we actually use it + if (NodeTemplate != NULL) + { + const FScopedTransaction Transaction(LOCTEXT("AddNode", "Add Node")); + ParentGraph->Modify(); + if (FromPin) + { + FromPin->Modify(); + } + + NodeTemplate->SetFlags(RF_Transactional); + + // set outer to be the graph so it doesn't go away + NodeTemplate->Rename(NULL, ParentGraph, REN_NonTransactional); + ParentGraph->AddNode(NodeTemplate, true); + + NodeTemplate->CreateNewGuid(); + NodeTemplate->PostPlacedNewNode(); + + // For input pins, new node will generally overlap node being dragged off + // Work out if we want to visually push away from connected node + //int32 XLocation = Location.X; + //if (FromPin && FromPin->Direction == EGPD_Input) + //{ + // UEdGraphNode* PinNode = FromPin->GetOwningNode(); + // const float XDelta = FMath::Abs(PinNode->NodePosX - Location.X); + + // if (XDelta < NodeDistance) + // { + // // Set location to edge of current node minus the max move distance + // // to force node to push off from connect node enough to give selection handle + // XLocation = PinNode->NodePosX - NodeDistance; + // } + //} + + NodeTemplate->NodePosX = Location.X; + NodeTemplate->NodePosY = Location.Y; + + // setup pins after placing node in correct spot, since pin sorting will happen as soon as link connection change occurs + NodeTemplate->AllocateDefaultPins(); + NodeTemplate->AutowireNewNode(FromPin); + NodeTemplate->SetGenericGraphNode(NewNode); + Graph->PostEditChange(); + Graph->MarkPackageDirty(); + + ResultNode = NodeTemplate; + } + + return ResultNode; +} +void UWALandscapeGraphSchema::CreateDefaultNodesForGraph(UEdGraph& Graph) const +{ + { + FGraphNodeCreator NodeCreator(Graph); + UWALandscapeGraph* LandscapeGraph = CastChecked(Graph.GetOuter()); + UWALandscapeGraphEdNode_Output* MyNode = NodeCreator.CreateNode(); + Output = MyNode; + UWALandscapeNode_Output* NewNode = NewObject(LandscapeGraph, UWALandscapeNode_Output::StaticClass()); + LandscapeGraph->LandscapeOutput = NewNode; + MyNode->SetGenericGraphNode(NewNode); + NodeCreator.Finalize(); + SetNodeMetaData(MyNode, FNodeMetadata::DefaultGraphNode); + } + //{ + // FGraphNodeCreator NodeCreator(Graph); + // UWALandscapeGraph* LandscapeGraph = CastChecked(Graph.GetOuter()); + // UWALGEdNode_Start* MyNode = NodeCreator.CreateNode(); + // //UWALandscapeNode_Output* NewNode = NewObject(LandscapeGraph, UWALandscapeNode_Output::StaticClass()); + // //LandscapeGraph->LandscapeOutput = NewNode; + // //MyNode->SetGenericGraphNode(NewNode); + // NodeCreator.Finalize(); + // SetNodeMetaData(MyNode, FNodeMetadata::DefaultGraphNode); + //} + //WALGEdNode_Start +} +void UWALandscapeGraphSchema::GetBreakLinkToSubMenuActions(class FMenuBuilder& MenuBuilder, class UEdGraphPin* InGraphPin) +{ + // Make sure we have a unique name for every entry in the list + TMap< FString, uint32 > LinkTitleCount; + + // Add all the links we could break from + for (TArray::TConstIterator Links(InGraphPin->LinkedTo); Links; ++Links) + { + UEdGraphPin* Pin = *Links; + FString TitleString = Pin->GetOwningNode()->GetNodeTitle(ENodeTitleType::ListView).ToString(); + FText Title = FText::FromString(TitleString); + if (Pin->PinName != TEXT("")) + { + //TitleString = FString::Printf(TEXT("%s (%s)"), *TitleString, *Pin->PinName); + + // Add name of connection if possible + FFormatNamedArguments Args; + Args.Add(TEXT("NodeTitle"), Title); + Args.Add(TEXT("PinName"), Pin->GetDisplayName()); + Title = FText::Format(LOCTEXT("BreakDescPin", "{NodeTitle} ({PinName})"), Args); + } + + uint32 &Count = LinkTitleCount.FindOrAdd(TitleString); + + FText Description; + FFormatNamedArguments Args; + Args.Add(TEXT("NodeTitle"), Title); + Args.Add(TEXT("NumberOfNodes"), Count); + + if (Count == 0) + { + Description = FText::Format(LOCTEXT("BreakDesc", "Break link to {NodeTitle}"), Args); + } + else + { + Description = FText::Format(LOCTEXT("BreakDescMulti", "Break link to {NodeTitle} ({NumberOfNodes})"), Args); + } + ++Count; + + //MenuBuilder.AddMenuEntry(Description, Description, FSlateIcon(), FUIAction( + // FExecuteAction::CreateUObject(this, &UWALandscapeGraphSchema::BreakSinglePinLink, const_cast(InGraphPin), *Links))); + } +} + +void UWALandscapeGraphSchema::GetGraphContextActions(FGraphContextMenuBuilder& ContextMenuBuilder) const +{ + const bool bNoParent = (ContextMenuBuilder.FromPin == NULL); + { + const FText AddToolTip; + const FText Desc = LOCTEXT("NewGenericGraphNodeTooltip", "Multiply"); + TSharedPtr NewNodeAction(new FWALandscapeGraphAssetSchemaAction_NewNode(LOCTEXT("GenericGraphNodeAction", "Common"), Desc, AddToolTip, 1)); + NewNodeAction->NodeTemplate = NewObject(ContextMenuBuilder.OwnerOfTemporaries); + NewNodeAction->NodeType = UWALandscapeNode_Multiply::StaticClass(); + ContextMenuBuilder.AddAction(NewNodeAction); + } +} + +void UWALandscapeGraphSchema::GetContextMenuActions(const UEdGraph* CurrentGraph, const UEdGraphNode* InGraphNode, const UEdGraphPin* InGraphPin, class FMenuBuilder* MenuBuilder, bool bIsDebugging) const +{ + if (InGraphPin != nullptr) + { + MenuBuilder->BeginSection("GenericGraphAssetGraphSchemaNodeActions", LOCTEXT("PinActionsMenuHeader", "Pin Actions")); + { + // Only display the 'Break Link' option if there is a link to break! + if (InGraphPin->LinkedTo.Num() > 0) + { + MenuBuilder->AddMenuEntry(FGraphEditorCommands::Get().BreakPinLinks); + + // add sub menu for break link to + if (InGraphPin->LinkedTo.Num() > 1) + { + MenuBuilder->AddSubMenu( + LOCTEXT("BreakLinkTo", "Break Link To..."), + LOCTEXT("BreakSpecificLinks", "Break a specific link..."), + FNewMenuDelegate::CreateUObject((UWALandscapeGraphSchema*const)this, &UWALandscapeGraphSchema::GetBreakLinkToSubMenuActions, const_cast(InGraphPin))); + } + else + { + ((UWALandscapeGraphSchema*const)this)->GetBreakLinkToSubMenuActions(*MenuBuilder, const_cast(InGraphPin)); + } + } + } + MenuBuilder->EndSection(); + } + else if(InGraphNode != nullptr) + { + MenuBuilder->BeginSection("GenericGraphAssetGraphSchemaNodeActions", LOCTEXT("NodeActionsMenuHeader", "Node Actions")); + { + MenuBuilder->AddMenuEntry(FGenericCommands::Get().Delete); + MenuBuilder->AddMenuEntry(FGenericCommands::Get().Cut); + MenuBuilder->AddMenuEntry(FGenericCommands::Get().Copy); + MenuBuilder->AddMenuEntry(FGenericCommands::Get().Duplicate); + + MenuBuilder->AddMenuEntry(FGraphEditorCommands::Get().BreakNodeLinks); + } + MenuBuilder->EndSection(); + } + + Super::GetContextMenuActions(CurrentGraph, InGraphNode, InGraphPin, MenuBuilder, bIsDebugging); +} + +const FPinConnectionResponse UWALandscapeGraphSchema::CanCreateConnection(const UEdGraphPin* A, const UEdGraphPin* B) const +{ + // Make sure the pins are not on the same node + if (A->GetOwningNode() == B->GetOwningNode()) + { + return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorSameNode", "Both are on the same node")); + } + + // Compare the directions + if ((A->Direction == EGPD_Input) && (B->Direction == EGPD_Input)) + { + return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorInput", "Can't connect input node to input node")); + } + else if ((A->Direction == EGPD_Output) && (B->Direction == EGPD_Output)) + { + return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorOutput", "Can't connect output node to output node")); + } + + // check for cycles + FNodeVisitorCycleChecker CycleChecker; + if (!CycleChecker.CheckForLoop(A->GetOwningNode(), B->GetOwningNode())) + { + return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorCycle", "Can't create a graph cycle")); + } + + return FPinConnectionResponse(CONNECT_RESPONSE_MAKE, LOCTEXT("PinConnect", "Connect nodes")); +} + +class FConnectionDrawingPolicy* UWALandscapeGraphSchema::CreateConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float InZoomFactor, const FSlateRect& InClippingRect, class FSlateWindowElementList& InDrawElements, class UEdGraph* InGraphObj) const +{ + return new FWALandscapeGraphConnectionDrawingPolicy(InBackLayerID, InFrontLayerID, InZoomFactor, InClippingRect, InDrawElements, InGraphObj); +} + +FLinearColor UWALandscapeGraphSchema::GetPinTypeColor(const FEdGraphPinType& PinType) const +{ + return FColor::White; +} + +void UWALandscapeGraphSchema::BreakNodeLinks(UEdGraphNode& TargetNode) const +{ + const FScopedTransaction Transaction(NSLOCTEXT("UnrealEd", "GraphEd_BreakNodeLinks", "Break Node Links")); + + Super::BreakNodeLinks(TargetNode); +} + +void UWALandscapeGraphSchema::BreakPinLinks(UEdGraphPin& TargetPin, bool bSendsNodeNotifcation) const +{ + const FScopedTransaction Transaction(NSLOCTEXT("UnrealEd", "GraphEd_BreakPinLinks", "Break Pin Links")); + + Super::BreakPinLinks(TargetPin, bSendsNodeNotifcation); +} + +//void UWALandscapeGraphSchema::BreakSinglePinLink(UEdGraphPin* SourcePin, UEdGraphPin* TargetPin) +//{ +// const FScopedTransaction Transaction(NSLOCTEXT("UnrealEd", "GraphEd_BreakSinglePinLink", "Break Pin Link")); +// +// Super::BreakSinglePinLink(SourcePin, TargetPin); +//} + +bool UWALandscapeGraphSchema::IsCacheVisualizationOutOfDate(int32 InVisualizationCacheID) const +{ + return CurrentCacheRefreshID != InVisualizationCacheID; +} + +int32 UWALandscapeGraphSchema::GetCurrentVisualizationCacheID() const +{ + return CurrentCacheRefreshID; +} + +void UWALandscapeGraphSchema::ForceVisualizationCacheClear() const +{ + ++CurrentCacheRefreshID; +} +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphSchema.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphSchema.h new file mode 100644 index 0000000..be8e541 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/LandscapeGraphEditor/WALandscapeGraphSchema.h @@ -0,0 +1,63 @@ +#pragma once +#include "EdGraph/EdGraphSchema.h" +#include "WALandscapeNode.h" + +#include "WALandscapeGraphSchema.generated.h" + +/** Action to add a node to the graph */ +USTRUCT() +struct FWALandscapeGraphAssetSchemaAction_NewNode : public FEdGraphSchemaAction +{ + GENERATED_USTRUCT_BODY(); + + UPROPERTY() + class UWALandscapeGraphEdNode* NodeTemplate; + + TSubclassOf NodeType; + + FWALandscapeGraphAssetSchemaAction_NewNode() + : FEdGraphSchemaAction() + {} + + FWALandscapeGraphAssetSchemaAction_NewNode(const FText& InNodeCategory, const FText& InMenuDesc, const FText& InToolTip, const int32 InGrouping) + : FEdGraphSchemaAction(InNodeCategory, InMenuDesc, InToolTip, InGrouping) + {} + + virtual UEdGraphNode* PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode = true) override; + + +}; + +UCLASS(MinimalAPI) +class UWALandscapeGraphSchema : public UEdGraphSchema +{ + GENERATED_BODY() +public: + UPROPERTY() + mutable class UWALandscapeGraphEdNode_Output* Output; + + void GetBreakLinkToSubMenuActions(class FMenuBuilder& MenuBuilder, class UEdGraphPin* InGraphPin); + + //~ Begin EdGraphSchema Interface + virtual void CreateDefaultNodesForGraph(UEdGraph& Graph) const override; + virtual void GetGraphContextActions(FGraphContextMenuBuilder& ContextMenuBuilder) const override; + virtual void GetContextMenuActions(const UEdGraph* CurrentGraph, const UEdGraphNode* InGraphNode, const UEdGraphPin* InGraphPin, class FMenuBuilder* MenuBuilder, bool bIsDebugging) const override; + virtual const FPinConnectionResponse CanCreateConnection(const UEdGraphPin* A, const UEdGraphPin* B) const override; + virtual class FConnectionDrawingPolicy* CreateConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float InZoomFactor, const FSlateRect& InClippingRect, class FSlateWindowElementList& InDrawElements, class UEdGraph* InGraphObj) const override; + virtual FLinearColor GetPinTypeColor(const FEdGraphPinType& PinType) const override; + virtual void BreakNodeLinks(UEdGraphNode& TargetNode) const override; + virtual void BreakPinLinks(UEdGraphPin& TargetPin, bool bSendsNodeNotifcation) const override; +// virtual void BreakSinglePinLink(UEdGraphPin* SourcePin, UEdGraphPin* TargetPin) override; +// virtual void DroppedAssetsOnGraph(const TArray& Assets, const FVector2D& GraphPosition, UEdGraph* Graph) const override; +// virtual void DroppedAssetsOnNode(const TArray& Assets, const FVector2D& GraphPosition, UEdGraphNode* Node) const override; +// virtual int32 GetNodeSelectionCount(const UEdGraph* Graph) const override; +// virtual TSharedPtr GetCreateCommentAction() const override; + virtual bool IsCacheVisualizationOutOfDate(int32 InVisualizationCacheID) const override; + virtual int32 GetCurrentVisualizationCacheID() const override; + virtual void ForceVisualizationCacheClear() const override; + //~ End EdGraphSchema Interface + +private: + static int32 CurrentCacheRefreshID; +}; + diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeGraph.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeGraph.cpp new file mode 100644 index 0000000..74544cd --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeGraph.cpp @@ -0,0 +1,26 @@ +#include "WALandscapeGraph.h" + +#define LOCTEXT_NAMESPACE "GenericGraph" + +UWALandscapeGraph::UWALandscapeGraph() +{ + NodeType = UWALandscapeNode::StaticClass(); + +#if WITH_EDITORONLY_DATA + EdGraph = nullptr; +#endif +} + +UWALandscapeGraph::~UWALandscapeGraph() +{ + +} + +void UWALandscapeGraph::ClearGraph() +{ +} +void UWALandscapeGraph::GenerateLandscape() +{ + +} +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeGraph.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeGraph.h new file mode 100644 index 0000000..8a52663 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeGraph.h @@ -0,0 +1,41 @@ +#pragma once + +#include "WALandscapeNode.h" +#include "WALandscapeGraph.generated.h" + +UCLASS(Blueprintable) +class WORLDARCHITECTEDITOR_API UWALandscapeGraph : public UObject +{ + GENERATED_BODY() + +public: + UWALandscapeGraph(); + virtual ~UWALandscapeGraph(); + + ////////////////////////////////////////////////////////////////////////// + // uproperties + UPROPERTY(EditAnywhere, Category = "GenericGraph") + FString Name; + + UPROPERTY(EditAnywhere, Category = "GenericGraph") + TSubclassOf NodeType; + + UPROPERTY(BlueprintReadOnly, Category = "GenericGraph") + UWALandscapeNode* LandscapeOutput; + + UPROPERTY(BlueprintReadOnly, Category = "GenericGraph") + TArray RootNodes; + + UPROPERTY(BlueprintReadOnly, Category = "GenericGraph") + TArray AllNodes; + +//#if WITH_EDITORONLY_DATA + UPROPERTY() + class UEdGraph* EdGraph; + + UPROPERTY() + class UWALandscapeGraphSchema* Schema; +//#endif + void GenerateLandscape(); + void ClearGraph(); +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeNode.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeNode.cpp new file mode 100644 index 0000000..b559779 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeNode.cpp @@ -0,0 +1,31 @@ +#include "WALandscapeNode.h" +#include "WALandscapeGraph.h" +#define LOCTEXT_NAMESPACE "GenericGraphNode" + +UWALandscapeNode::UWALandscapeNode() +{ + BackgroundColor = FLinearColor(0.0f, 0.0f, 0.0f, 1.0f); +} + +UWALandscapeNode::~UWALandscapeNode() +{ + +} + +FString UWALandscapeNode::GetNodeTitle() +{ + return CustomNodeTitle; +} + +UWALandscapeGraph* UWALandscapeNode::GetGraph() +{ + return Cast(GetOuter()); +} + +TArray UWALandscapeNode::GenerateHeightmap() +{ + TArray RetVal; + return RetVal; +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeNode.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeNode.h new file mode 100644 index 0000000..5d0243e --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/Runtime/WALandscapeNode.h @@ -0,0 +1,45 @@ +#pragma once + +#include "WALandscapeNode.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FWAOnHeightmapReady, const TArray&, OutHeighmap); + +UCLASS(Blueprintable) +class WORLDARCHITECTEDITOR_API UWALandscapeNode : public UObject +{ + GENERATED_BODY() + +public: + UWALandscapeNode(); + virtual ~UWALandscapeNode(); + UPROPERTY() + bool bDirty; + + ////////////////////////////////////////////////////////////////////////// + // uproperties + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "GenericGraphNode") + FString CustomNodeTitle; + + UPROPERTY(BlueprintReadOnly, Category = "GenericGraphNode") + UWALandscapeNode* MaskNode; + +#if WITH_EDITOR + UPROPERTY(EditDefaultsOnly, Category = "GenericGraphNode") + FLinearColor BackgroundColor; +#endif + UPROPERTY() + FWAOnHeightmapReady OnHeightmapReady; + ////////////////////////////////////////////////////////////////////////// + // ufunctions + UFUNCTION(BlueprintCallable, Category = "GenericGraphNode") + FString GetNodeTitle(); + + virtual void ExecuteNode(const TArray& InHeightData) {}; + + ////////////////////////////////////////////////////////////////////////// + class UWALandscapeGraph* GetGraph(); + + + virtual TArray GenerateHeightmap(); +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Combine.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Combine.cpp new file mode 100644 index 0000000..4735d63 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Combine.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "WALGEdNode_Combine.h" + + + + diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Combine.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Combine.h new file mode 100644 index 0000000..ba6e2e3 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Combine.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "LandscapeGraphEditor/WALandscapeGraphEdNode.h" +#include "WALGEdNode_Combine.generated.h" + +/** + * + */ +UCLASS() +class WORLDARCHITECTEDITOR_API UWALGEdNode_Combine : public UWALandscapeGraphEdNode +{ + GENERATED_BODY() + + + + +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_PerlinNoise.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_PerlinNoise.cpp new file mode 100644 index 0000000..87ab2eb --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_PerlinNoise.cpp @@ -0,0 +1,64 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "WALGEdNode_PerlinNoise.h" +#include "LandscapeEditorUtils.h" +#include "LandscapeInfoMap.h" +#include "LandscapeStreamingProxy.h" + +void UWALGEdNode_PerlinNoise::GenerateHeightMap(TArray& InOutMap) +{ + //GEditor->GetWorld(); + //TArray Landscapes; + //for (TActorIterator LIter(GetEditorMode()->GetWorld()); LIter; ++LIter) + //{ + // Landscapes.Add(*LIter); + //} + //auto& LandscapeInfoMap = ULandscapeInfoMap::GetLandscapeInfoMap(GetEditorMode()->GetWorld()); + + + //if (Landscapes.Num() > 0) + //{ + // FIntRect bounds = Landscapes[0]->GetBoundingRect(); + + // int32 numHeights = (bounds.Width() + 1)*(bounds.Height() + 1); + // TArray Data; + // Data.Init(0, numHeights); + // TArray DataFloat; + // DataFloat.Init(0, numHeights); + // TArray DataFloat2; + // DataFloat2.Init(0, numHeights); + // TArray DataFloat3; + // DataFloat3.Init(0, numHeights); + + // int32 cols = bounds.Width() + 1, rows = bounds.Height() + 1; + // int32 octaves = 16, px = 4, py = 4; + // float amplitude = 20000.f; + // //for (int i = 0; i < Data.Num(); i++) + // //{ + // // float nx = (i % cols) / (float)cols; //normalized col + // // float ny = (i / cols) / (float)rows; //normalized row + // // Data[i] = FMath::Clamp(PerlinNoise2D(nx, ny, amplitude, octaves, px, py), 0, 32768); + // //} + // for (int i = 0; i < DataFloat.Num(); i++) + // { + // float nx = (i % cols) / (float)cols; //normalized col + // float ny = (i / cols) / (float)rows; //normalized row + // DataFloat[i] = PerlinNoise2DFloat(nx, ny, amplitude, octaves, px, py); + // DataFloat2[i] = PerlinNoise2DFloat(nx, ny, amplitude, 4, 12, 12); + // DataFloat3[i] = DataFloat[i] * DataFloat2[i]; + // } + // for (int i = 0; i < Data.Num(); i++) + // { + // Data[i] = (USHRT_MAX / 2.f) + (DataFloat3[i] * amplitude); + // } + // InOutMap = Data; + //} +} +void UWALGEdNode_PerlinNoise::AllocateDefaultPins() +{ + +} +void UWALGEdNode_PerlinNoise::PinConnectionListChanged(UEdGraphPin* Pin) +{ + +} \ No newline at end of file diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_PerlinNoise.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_PerlinNoise.h new file mode 100644 index 0000000..ffa4369 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_PerlinNoise.h @@ -0,0 +1,40 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "WANoise.h" +#include "LandscapeGraphEditor/WALandscapeGraphEdNode.h" +#include "WALGEdNode_PerlinNoise.generated.h" + +/** + * + */ +UCLASS() +class WORLDARCHITECTEDITOR_API UWALGEdNode_PerlinNoise : public UWALandscapeGraphEdNode +{ + GENERATED_BODY() + + virtual void GenerateHeightMap(TArray& InOutMap) override; + virtual void AllocateDefaultPins() override; + virtual void PinConnectionListChanged(UEdGraphPin* Pin) override; + + uint16 PerlinNoise2D(float x, float y, float amp, int32 octaves, int32 px, int32 py) + { + float noise = 0.f; + for (int octave = 1; octave < octaves; octave *= 2) + noise += FNoise::pnoise(x*px*octave, y*py*octave, px, py) / octave; + + return USHRT_MAX / 2.f + amp*noise; + } + float PerlinNoise2DFloat(float x, float y, float amp, int32 octaves, int32 px, int32 py) + { + float noise = 0.f; + for (int octave = 1; octave < octaves; octave *= 2) + noise += FNoise::pnoise(x*px*octave, y*py*octave, px, py) / octave; + + return noise; + } + + +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Start.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Start.cpp new file mode 100644 index 0000000..415623a --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Start.cpp @@ -0,0 +1,12 @@ +// Fill out your copyright notice in the Description page of Project Settings. +#include "WALGEdNode_Start.h" +#include "WALandscapeGraphEditorTypes.h" + + + + + +void UWALGEdNode_Start::AllocateDefaultPins() +{ + CreatePin(EGPD_Output, UWALandscapeGraphEditorTypes::PinCategory_Start, TEXT("Start")); +} \ No newline at end of file diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Start.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Start.h new file mode 100644 index 0000000..076ac01 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALGEdNode_Start.h @@ -0,0 +1,21 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "LandscapeGraphEditor/WALandscapeGraphEdNode.h" +#include "WALGEdNode_Start.generated.h" + +/** + * + */ +UCLASS() +class WORLDARCHITECTEDITOR_API UWALGEdNode_Start : public UWALandscapeGraphEdNode +{ + GENERATED_BODY() + +public: + virtual void AllocateDefaultPins() override; + + +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphAssetTypeActions.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphAssetTypeActions.cpp new file mode 100644 index 0000000..4c7c875 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphAssetTypeActions.cpp @@ -0,0 +1,47 @@ +#include "WALandscapeGraphAssetTypeActions.h" +#include "WALandscapeGraphAssetEditor.h" + +#define LOCTEXT_NAMESPACE "AssetTypeActions" + +FWALandscapeGraphAssetTypeActions::FWALandscapeGraphAssetTypeActions(EAssetTypeCategories::Type InAssetCategory) + : MyAssetCategory(InAssetCategory) +{ +} + +FText FWALandscapeGraphAssetTypeActions::GetName() const +{ + return FText::FromString("Landscape Graph"); +} + +FColor FWALandscapeGraphAssetTypeActions::GetTypeColor() const +{ + return FColor(129, 196, 115); +} + +UClass* FWALandscapeGraphAssetTypeActions::GetSupportedClass() const +{ + return UWALandscapeGraph::StaticClass(); +} + +void FWALandscapeGraphAssetTypeActions::OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor) +{ + const EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone; + + for (auto ObjIt = InObjects.CreateConstIterator(); ObjIt; ++ObjIt) + { + if (UWALandscapeGraph* Graph = Cast(*ObjIt)) + { + TSharedRef NewGraphEditor(new FWALandscapeGraphAssetEditor()); + NewGraphEditor->InitGenericGraphAssetEditor(Mode, EditWithinLevelEditor, Graph); + } + } +} + +uint32 FWALandscapeGraphAssetTypeActions::GetCategories() +{ + return EAssetTypeCategories::Basic | MyAssetCategory; +} + +////////////////////////////////////////////////////////////////////////// + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphAssetTypeActions.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphAssetTypeActions.h new file mode 100644 index 0000000..74e40e1 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphAssetTypeActions.h @@ -0,0 +1,18 @@ +#pragma once + +#include "AssetTypeActions_Base.h" + +class FWALandscapeGraphAssetTypeActions : public FAssetTypeActions_Base +{ +public: + FWALandscapeGraphAssetTypeActions(EAssetTypeCategories::Type InAssetCategory); + + virtual FText GetName() const override; + virtual FColor GetTypeColor() const override; + virtual UClass* GetSupportedClass() const override; + virtual void OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor = TSharedPtr()) override; + virtual uint32 GetCategories() override; + +private: + EAssetTypeCategories::Type MyAssetCategory; +}; \ No newline at end of file diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphEditorTypes.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphEditorTypes.cpp new file mode 100644 index 0000000..4b4155c --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphEditorTypes.cpp @@ -0,0 +1,19 @@ +#include "WALandscapeGraphEditorTypes.h" + + +const FName UWALandscapeGraphEditorTypes::PinCategory_MultipleNodes("MultipleNodes"); +const FName UWALandscapeGraphEditorTypes::PinCategory_SingleNode("HeightOutput"); +const FName UWALandscapeGraphEditorTypes::PinCategory_MaskInput("MaskInput"); +const FName UWALandscapeGraphEditorTypes::PinCategory_FinalInput("FinalInput"); + +const FName UWALandscapeGraphEditorTypes::PinCategory_InputA("InputA"); +const FName UWALandscapeGraphEditorTypes::PinCategory_InputB("InputA"); +const FName UWALandscapeGraphEditorTypes::PinCategory_LerpMask("LerpMask"); + +const FName UWALandscapeGraphEditorTypes::PinCategory_Output("Output"); +const FName UWALandscapeGraphEditorTypes::PinCategory_Start("Start"); + +UWALandscapeGraphEditorTypes::UWALandscapeGraphEditorTypes(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) +{ +} + diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphEditorTypes.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphEditorTypes.h new file mode 100644 index 0000000..0d79a95 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphEditorTypes.h @@ -0,0 +1,21 @@ +#pragma once + +#include "WALandscapeGraphEditorTypes.generated.h" + +UCLASS() +class UWALandscapeGraphEditorTypes : public UObject +{ + GENERATED_UCLASS_BODY() + + static const FName PinCategory_MultipleNodes; + static const FName PinCategory_SingleNode; + static const FName PinCategory_MaskInput; + static const FName PinCategory_FinalInput; + + static const FName PinCategory_InputA; + static const FName PinCategory_InputB; + static const FName PinCategory_LerpMask; + + static const FName PinCategory_Output; + static const FName PinCategory_Start; +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphFactory.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphFactory.cpp new file mode 100644 index 0000000..e7c544f --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphFactory.cpp @@ -0,0 +1,22 @@ +#include "WALandscapeGraphFactory.h" +#include "WALandscapeGraph.h" +#define LOCTEXT_NAMESPACE "GenericGraph" + +UWALandscapeGraphFactory::UWALandscapeGraphFactory() +{ + bCreateNew = true; + bEditAfterNew = true; + SupportedClass = UWALandscapeGraph::StaticClass(); +} + +UWALandscapeGraphFactory::~UWALandscapeGraphFactory() +{ + +} + +UObject* UWALandscapeGraphFactory::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) +{ + return NewObject(InParent, Class, Name, Flags | RF_Transactional); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphFactory.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphFactory.h new file mode 100644 index 0000000..b4dd463 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeGraphFactory.h @@ -0,0 +1,15 @@ +#pragma once + +#include "WALandscapeGraphFactory.generated.h" + +UCLASS() +class WORLDARCHITECTEDITOR_API UWALandscapeGraphFactory : public UFactory +{ + GENERATED_BODY() + +public: + UWALandscapeGraphFactory(); + virtual ~UWALandscapeGraphFactory(); + + virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override; +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Multiply.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Multiply.cpp new file mode 100644 index 0000000..9347038 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Multiply.cpp @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "WALandscapeNode_Multiply.h" + + + +TArray UWALandscapeNode_Multiply::GenerateHeightmap() +{ + TArray OutputA; + TArray OutputB; + TArray RetVal; + + if (InputA && InputB) + { + OutputA = InputA->GenerateHeightmap(); + + OutputB = InputB->GenerateHeightmap(); + + + RetVal.Init(0, OutputA.Num()); + for (int32 Idx = 0; Idx < OutputA.Num(); Idx++) + { + RetVal[Idx] = OutputA[Idx] * OutputB[Idx]; + } + + } + return RetVal; +} diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Multiply.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Multiply.h new file mode 100644 index 0000000..5a1c9e0 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Multiply.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Runtime/WALandscapeNode.h" +#include "WALandscapeNode_Multiply.generated.h" + +/** + * + */ +UCLASS() +class WORLDARCHITECTEDITOR_API UWALandscapeNode_Multiply : public UWALandscapeNode +{ + GENERATED_BODY() +protected: + TArray InputACache; + TArray InputBCache; +public: + UPROPERTY(BlueprintReadOnly, Category = "GenericGraphNode") + UWALandscapeNode* InputA; + UPROPERTY(BlueprintReadOnly, Category = "GenericGraphNode") + UWALandscapeNode* InputB; + UPROPERTY(BlueprintReadOnly, Category = "GenericGraphNode") + UWALandscapeNode* Output; + + virtual TArray GenerateHeightmap() override; + +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Output.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Output.cpp new file mode 100644 index 0000000..fd9434f --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Output.cpp @@ -0,0 +1,16 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "WALandscapeNode_Output.h" + + + + +TArray UWALandscapeNode_Output::GenerateHeightmap() +{ + TArray RetVal; + if (Heightmap) + { + RetVal = Heightmap->GenerateHeightmap(); + } + return RetVal; +} \ No newline at end of file diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Output.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Output.h new file mode 100644 index 0000000..96b1f1c --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_Output.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Runtime/WALandscapeNode.h" +#include "WALandscapeNode_Output.generated.h" + +/** + * + */ +UCLASS() +class WORLDARCHITECTEDITOR_API UWALandscapeNode_Output : public UWALandscapeNode +{ + GENERATED_BODY() +public: + TArray CachedHeightmap; + + UPROPERTY(BlueprintReadOnly, Category = "GenericGraphNode") + UWALandscapeNode* Heightmap; + +public: + virtual TArray GenerateHeightmap() override; +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_PerlinNoise.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_PerlinNoise.cpp new file mode 100644 index 0000000..ab4740a --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_PerlinNoise.cpp @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "WALandscapeNode_PerlinNoise.h" + + + +TArray UWALandscapeNode_PerlinNoise::GenerateHeightmap() +{ + TArray RetVal; + if (bDirty) + { + return RetVal; + } + else + { + return CachedHeightmap; + } +} diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_PerlinNoise.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_PerlinNoise.h new file mode 100644 index 0000000..b007b0f --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WALandscapeNode_PerlinNoise.h @@ -0,0 +1,38 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Runtime/WALandscapeNode.h" +#include "WANoise.h" +#include "WALandscapeNode_PerlinNoise.generated.h" + +/** + * + */ +UCLASS() +class WORLDARCHITECTEDITOR_API UWALandscapeNode_PerlinNoise : public UWALandscapeNode +{ + GENERATED_BODY() +public: + TArray CachedHeightmap; +public: + virtual TArray GenerateHeightmap() override; + + uint16 PerlinNoise2D(float x, float y, float amp, int32 octaves, int32 px, int32 py) + { + float noise = 0.f; + for (int octave = 1; octave < octaves; octave *= 2) + noise += FNoise::pnoise(x*px*octave, y*py*octave, px, py) / octave; + + return USHRT_MAX / 2.f + amp*noise; + } + float PerlinNoise2DFloat(float x, float y, float amp, int32 octaves, int32 px, int32 py) + { + float noise = 0.f; + for (int octave = 1; octave < octaves; octave *= 2) + noise += FNoise::pnoise(x*px*octave, y*py*octave, px, py) / octave; + + return noise; + } +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WANoise.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WANoise.cpp new file mode 100644 index 0000000..06bfbb8 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WANoise.cpp @@ -0,0 +1,29 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. +#include "WANoise.h" +unsigned char FNoise::perm[] = { 151,160,137,91,90,15, +131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, +190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, +88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, +77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, +102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, +135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, +5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, +223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, +129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, +251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, +49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, +138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, +151,160,137,91,90,15, +131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, +190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, +88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, +77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, +102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, +135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, +5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, +223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, +129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, +251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, +49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, +138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 +}; \ No newline at end of file diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WANoise.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WANoise.h new file mode 100644 index 0000000..2f2aba5 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WANoise.h @@ -0,0 +1,459 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + + + +class FNoise +{ +#define FADE(t) ( t * t * t * ( t * ( t * 6 - 15 ) + 10 ) ) + +#define FASTFLOOR(x) ( ((x)>0) ? ((int)x) : ((int)x-1 ) ) +#define LERP(t, a, b) ((a) + (t)*((b)-(a))) + + + //--------------------------------------------------------------------- + // Static data + /* + * Permutation table. This is just a random jumble of all numbers 0-255, + * repeated twice to avoid wrapping the index at 255 for each lookup. + * This needs to be exactly the same for all instances on all platforms, + * so it's easiest to just keep it as static explicit data. + * This also removes the need for any initialisation of this class. + * + * Note that making this an int[] instead of a char[] might make the + * code run faster on platforms with a high penalty for unaligned single + * byte addressing. Intel x86 is generally single-byte-friendly, but + * some other CPUs are faster with 4-aligned reads. + * However, a char[] is smaller, which avoids cache trashing, and that + * is probably the most important aspect on most architectures. + * This array is accessed a *lot* by the noise functions. + * A vector-valued noise over 3D accesses it 96 times, and a + * float-valued 4D noise 64 times. We want this to fit in the cache! + */ +public: + static unsigned char perm[]; + FNoise() + { + + } + static float grad(int hash, float x) { + int h = hash & 15; + float grad = 1.0 + (h & 7); // Gradient value 1.0, 2.0, ..., 8.0 + if (h & 8) grad = -grad; // and a random sign for the gradient + return (grad * x); // Multiply the gradient with the distance + } + + static float grad(int hash, float x, float y) { + int h = hash & 7; // Convert low 3 bits of hash code + float u = h<4 ? x : y; // into 8 simple gradient directions, + float v = h<4 ? y : x; // and compute the dot product with (x,y). + return ((h & 1) ? -u : u) + ((h & 2) ? -2.0*v : 2.0*v); + } + + static float grad(int hash, float x, float y, float z) { + int h = hash & 15; // Convert low 4 bits of hash code into 12 simple + float u = h<8 ? x : y; // gradient directions, and compute dot product. + float v = h<4 ? y : h == 12 || h == 14 ? x : z; // Fix repeats at h = 12 to 15 + return ((h & 1) ? -u : u) + ((h & 2) ? -v : v); + } + + static float grad(int hash, float x, float y, float z, float t) { + int h = hash & 31; // Convert low 5 bits of hash code into 32 simple + float u = h<24 ? x : y; // gradient directions, and compute dot product. + float v = h<16 ? y : z; + float w = h<8 ? z : t; + return ((h & 1) ? -u : u) + ((h & 2) ? -v : v) + ((h & 4) ? -w : w); + } + + //--------------------------------------------------------------------- + /** 1D float Perlin noise, SL "noise()" + */ + static float noise(float x) + { + int ix0, ix1; + float fx0, fx1; + float s, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + fx0 = x - ix0; // Fractional part of x + fx1 = fx0 - 1.0f; + ix1 = (ix0 + 1) & 0xff; + ix0 = ix0 & 0xff; // Wrap to 0..255 + + s = FADE(fx0); + + n0 = grad(perm[ix0], fx0); + n1 = grad(perm[ix1], fx1); + return 0.188f * (LERP(s, n0, n1)); + } + + //--------------------------------------------------------------------- + /** 1D float Perlin periodic noise, SL "pnoise()" + */ + static float pnoise(float x, int px) + { + int ix0, ix1; + float fx0, fx1; + float s, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + fx0 = x - ix0; // Fractional part of x + fx1 = fx0 - 1.0f; + ix1 = ((ix0 + 1) % px) & 0xff; // Wrap to 0..px-1 *and* wrap to 0..255 + ix0 = (ix0 % px) & 0xff; // (because px might be greater than 256) + + s = FADE(fx0); + + n0 = grad(perm[ix0], fx0); + n1 = grad(perm[ix1], fx1); + return 0.188f * (LERP(s, n0, n1)); + } + + + //--------------------------------------------------------------------- + /** 2D float Perlin noise. + */ + static float noise(float x, float y) + { + int ix0, iy0, ix1, iy1; + float fx0, fy0, fx1, fy1; + float s, t, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 + iy1 = (iy0 + 1) & 0xff; + ix0 = ix0 & 0xff; + iy0 = iy0 & 0xff; + + t = FADE(fy0); + s = FADE(fx0); + + nx0 = grad(perm[ix0 + perm[iy0]], fx0, fy0); + nx1 = grad(perm[ix0 + perm[iy1]], fx0, fy1); + n0 = LERP(t, nx0, nx1); + + nx0 = grad(perm[ix1 + perm[iy0]], fx1, fy0); + nx1 = grad(perm[ix1 + perm[iy1]], fx1, fy1); + n1 = LERP(t, nx0, nx1); + + return 0.507f * (LERP(s, n0, n1)); + } + + //--------------------------------------------------------------------- + /** 2D float Perlin periodic noise. + */ + static float pnoise(float x, float y, int px, int py) + { + int ix0, iy0, ix1, iy1; + float fx0, fy0, fx1, fy1; + float s, t, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + ix1 = ((ix0 + 1) % px) & 0xff; // Wrap to 0..px-1 and wrap to 0..255 + iy1 = ((iy0 + 1) % py) & 0xff; // Wrap to 0..py-1 and wrap to 0..255 + ix0 = (ix0 % px) & 0xff; + iy0 = (iy0 % py) & 0xff; + + t = FADE(fy0); + s = FADE(fx0); + + nx0 = grad(perm[ix0 + perm[iy0]], fx0, fy0); + nx1 = grad(perm[ix0 + perm[iy1]], fx0, fy1); + n0 = LERP(t, nx0, nx1); + + nx0 = grad(perm[ix1 + perm[iy0]], fx1, fy0); + nx1 = grad(perm[ix1 + perm[iy1]], fx1, fy1); + n1 = LERP(t, nx0, nx1); + + return 0.507f * (LERP(s, n0, n1)); + } + + + //--------------------------------------------------------------------- + /** 3D float Perlin noise. + */ + static float noise(float x, float y, float z) + { + int ix0, iy0, ix1, iy1, iz0, iz1; + float fx0, fy0, fz0, fx1, fy1, fz1; + float s, t, r; + float nxy0, nxy1, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + iz0 = FASTFLOOR(z); // Integer part of z + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fz0 = z - iz0; // Fractional part of z + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + fz1 = fz0 - 1.0f; + ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 + iy1 = (iy0 + 1) & 0xff; + iz1 = (iz0 + 1) & 0xff; + ix0 = ix0 & 0xff; + iy0 = iy0 & 0xff; + iz0 = iz0 & 0xff; + + r = FADE(fz0); + t = FADE(fy0); + s = FADE(fx0); + + nxy0 = grad(perm[ix0 + perm[iy0 + perm[iz0]]], fx0, fy0, fz0); + nxy1 = grad(perm[ix0 + perm[iy0 + perm[iz1]]], fx0, fy0, fz1); + nx0 = LERP(r, nxy0, nxy1); + + nxy0 = grad(perm[ix0 + perm[iy1 + perm[iz0]]], fx0, fy1, fz0); + nxy1 = grad(perm[ix0 + perm[iy1 + perm[iz1]]], fx0, fy1, fz1); + nx1 = LERP(r, nxy0, nxy1); + + n0 = LERP(t, nx0, nx1); + + nxy0 = grad(perm[ix1 + perm[iy0 + perm[iz0]]], fx1, fy0, fz0); + nxy1 = grad(perm[ix1 + perm[iy0 + perm[iz1]]], fx1, fy0, fz1); + nx0 = LERP(r, nxy0, nxy1); + + nxy0 = grad(perm[ix1 + perm[iy1 + perm[iz0]]], fx1, fy1, fz0); + nxy1 = grad(perm[ix1 + perm[iy1 + perm[iz1]]], fx1, fy1, fz1); + nx1 = LERP(r, nxy0, nxy1); + + n1 = LERP(t, nx0, nx1); + + return 0.936f * (LERP(s, n0, n1)); + } + + //--------------------------------------------------------------------- + /** 3D float Perlin periodic noise. + */ + static float pnoise(float x, float y, float z, int px, int py, int pz) + { + int ix0, iy0, ix1, iy1, iz0, iz1; + float fx0, fy0, fz0, fx1, fy1, fz1; + float s, t, r; + float nxy0, nxy1, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + iz0 = FASTFLOOR(z); // Integer part of z + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fz0 = z - iz0; // Fractional part of z + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + fz1 = fz0 - 1.0f; + ix1 = ((ix0 + 1) % px) & 0xff; // Wrap to 0..px-1 and wrap to 0..255 + iy1 = ((iy0 + 1) % py) & 0xff; // Wrap to 0..py-1 and wrap to 0..255 + iz1 = ((iz0 + 1) % pz) & 0xff; // Wrap to 0..pz-1 and wrap to 0..255 + ix0 = (ix0 % px) & 0xff; + iy0 = (iy0 % py) & 0xff; + iz0 = (iz0 % pz) & 0xff; + + r = FADE(fz0); + t = FADE(fy0); + s = FADE(fx0); + + nxy0 = grad(perm[ix0 + perm[iy0 + perm[iz0]]], fx0, fy0, fz0); + nxy1 = grad(perm[ix0 + perm[iy0 + perm[iz1]]], fx0, fy0, fz1); + nx0 = LERP(r, nxy0, nxy1); + + nxy0 = grad(perm[ix0 + perm[iy1 + perm[iz0]]], fx0, fy1, fz0); + nxy1 = grad(perm[ix0 + perm[iy1 + perm[iz1]]], fx0, fy1, fz1); + nx1 = LERP(r, nxy0, nxy1); + + n0 = LERP(t, nx0, nx1); + + nxy0 = grad(perm[ix1 + perm[iy0 + perm[iz0]]], fx1, fy0, fz0); + nxy1 = grad(perm[ix1 + perm[iy0 + perm[iz1]]], fx1, fy0, fz1); + nx0 = LERP(r, nxy0, nxy1); + + nxy0 = grad(perm[ix1 + perm[iy1 + perm[iz0]]], fx1, fy1, fz0); + nxy1 = grad(perm[ix1 + perm[iy1 + perm[iz1]]], fx1, fy1, fz1); + nx1 = LERP(r, nxy0, nxy1); + + n1 = LERP(t, nx0, nx1); + + return 0.936f * (LERP(s, n0, n1)); + } + + + //--------------------------------------------------------------------- + /** 4D float Perlin noise. + */ + + static float noise(float x, float y, float z, float w) + { + int ix0, iy0, iz0, iw0, ix1, iy1, iz1, iw1; + float fx0, fy0, fz0, fw0, fx1, fy1, fz1, fw1; + float s, t, r, q; + float nxyz0, nxyz1, nxy0, nxy1, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + iz0 = FASTFLOOR(z); // Integer part of y + iw0 = FASTFLOOR(w); // Integer part of w + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fz0 = z - iz0; // Fractional part of z + fw0 = w - iw0; // Fractional part of w + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + fz1 = fz0 - 1.0f; + fw1 = fw0 - 1.0f; + ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 + iy1 = (iy0 + 1) & 0xff; + iz1 = (iz0 + 1) & 0xff; + iw1 = (iw0 + 1) & 0xff; + ix0 = ix0 & 0xff; + iy0 = iy0 & 0xff; + iz0 = iz0 & 0xff; + iw0 = iw0 & 0xff; + + q = FADE(fw0); + r = FADE(fz0); + t = FADE(fy0); + s = FADE(fx0); + + nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx0, fy0, fz0, fw0); + nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx0, fy0, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx0, fy0, fz1, fw0); + nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx0, fy0, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx0 = LERP(r, nxy0, nxy1); + + nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx0, fy1, fz0, fw0); + nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx0, fy1, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx0, fy1, fz1, fw0); + nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx0, fy1, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx1 = LERP(r, nxy0, nxy1); + + n0 = LERP(t, nx0, nx1); + + nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx1, fy0, fz0, fw0); + nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx1, fy0, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx1, fy0, fz1, fw0); + nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx1, fy0, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx0 = LERP(r, nxy0, nxy1); + + nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx1, fy1, fz0, fw0); + nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx1, fy1, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx1, fy1, fz1, fw0); + nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx1, fy1, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx1 = LERP(r, nxy0, nxy1); + + n1 = LERP(t, nx0, nx1); + + return 0.87f * (LERP(s, n0, n1)); + } + + //--------------------------------------------------------------------- + /** 4D float Perlin periodic noise. + */ + + static float pnoise(float x, float y, float z, float w, + int px, int py, int pz, int pw) + { + int ix0, iy0, iz0, iw0, ix1, iy1, iz1, iw1; + float fx0, fy0, fz0, fw0, fx1, fy1, fz1, fw1; + float s, t, r, q; + float nxyz0, nxyz1, nxy0, nxy1, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + iz0 = FASTFLOOR(z); // Integer part of y + iw0 = FASTFLOOR(w); // Integer part of w + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fz0 = z - iz0; // Fractional part of z + fw0 = w - iw0; // Fractional part of w + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + fz1 = fz0 - 1.0f; + fw1 = fw0 - 1.0f; + ix1 = ((ix0 + 1) % px) & 0xff; // Wrap to 0..px-1 and wrap to 0..255 + iy1 = ((iy0 + 1) % py) & 0xff; // Wrap to 0..py-1 and wrap to 0..255 + iz1 = ((iz0 + 1) % pz) & 0xff; // Wrap to 0..pz-1 and wrap to 0..255 + iw1 = ((iw0 + 1) % pw) & 0xff; // Wrap to 0..pw-1 and wrap to 0..255 + ix0 = (ix0 % px) & 0xff; + iy0 = (iy0 % py) & 0xff; + iz0 = (iz0 % pz) & 0xff; + iw0 = (iw0 % pw) & 0xff; + + q = FADE(fw0); + r = FADE(fz0); + t = FADE(fy0); + s = FADE(fx0); + + nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx0, fy0, fz0, fw0); + nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx0, fy0, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx0, fy0, fz1, fw0); + nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx0, fy0, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx0 = LERP(r, nxy0, nxy1); + + nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx0, fy1, fz0, fw0); + nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx0, fy1, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx0, fy1, fz1, fw0); + nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx0, fy1, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx1 = LERP(r, nxy0, nxy1); + + n0 = LERP(t, nx0, nx1); + + nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx1, fy0, fz0, fw0); + nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx1, fy0, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx1, fy0, fz1, fw0); + nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx1, fy0, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx0 = LERP(r, nxy0, nxy1); + + nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx1, fy1, fz0, fw0); + nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx1, fy1, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx1, fy1, fz1, fw0); + nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx1, fy1, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx1 = LERP(r, nxy0, nxy1); + + n1 = LERP(t, nx0, nx1); + + return 0.87f * (LERP(s, n0, n1)); + } + +}; \ No newline at end of file diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdMode.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdMode.cpp new file mode 100644 index 0000000..555b953 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdMode.cpp @@ -0,0 +1,50 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "WorldArchitectEdMode.h" +#include "WorldArchitectEdModeToolkit.h" +#include "Toolkits/ToolkitManager.h" +#include "EditorModeManager.h" + +const FEditorModeID FWorldArchitectEdMode::EM_WorldArchitectEdModeId = TEXT("EM_WorldArchitectEdMode"); + +FWorldArchitectEdMode::FWorldArchitectEdMode() +{ + +} + +FWorldArchitectEdMode::~FWorldArchitectEdMode() +{ + +} + +void FWorldArchitectEdMode::Enter() +{ + FEdMode::Enter(); + + if (!Toolkit.IsValid() && UsesToolkits()) + { + Toolkit = MakeShareable(new FWorldArchitectEdModeToolkit); + Toolkit->Init(Owner->GetToolkitHost()); + } +} + +void FWorldArchitectEdMode::Exit() +{ + if (Toolkit.IsValid()) + { + FToolkitManager::Get().CloseToolkit(Toolkit.ToSharedRef()); + Toolkit.Reset(); + } + + // Call base Exit method to ensure proper cleanup + FEdMode::Exit(); +} + +bool FWorldArchitectEdMode::UsesToolkits() const +{ + return true; +} + + + + diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdMode.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdMode.h new file mode 100644 index 0000000..6a04795 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdMode.h @@ -0,0 +1,24 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "EdMode.h" + +class FWorldArchitectEdMode : public FEdMode +{ +public: + const static FEditorModeID EM_WorldArchitectEdModeId; +public: + FWorldArchitectEdMode(); + virtual ~FWorldArchitectEdMode(); + + // FEdMode interface + virtual void Enter() override; + virtual void Exit() override; + //virtual void Tick(FEditorViewportClient* ViewportClient, float DeltaTime) override; + //virtual void Render(const FSceneView* View, FViewport* Viewport, FPrimitiveDrawInterface* PDI) override; + //virtual void ActorSelectionChangeNotify() override; + bool UsesToolkits() const override; + // End of FEdMode interface +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdModeToolkit.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdModeToolkit.cpp new file mode 100644 index 0000000..8a0a028 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdModeToolkit.cpp @@ -0,0 +1,857 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "WorldArchitectEdModeToolkit.h" +#include "WorldArchitectEdMode.h" +#include "Engine/Selection.h" +#include "Widgets/Input/SButton.h" +#include "Widgets/Text/STextBlock.h" +#include "EditorModeManager.h" +#include "Landscape.h" +#include "LandscapeInfo.h" +#include "EngineUtils.h" +#include "LandscapeEditorUtils.h" +#include "LandscapeInfoMap.h" +#include "LandscapeStreamingProxy.h" +#include "PropertyCustomizationHelpers.h" +#include "Runtime/WALandscapeGraph.h" +#include "WALandscapeGraphFactory.h" +#include "LandscapeGraphEditor/WALandscapeGraphSchema.h" +#include "LandscapeGraphEditor/WALandscapeGraphEdNode_Output.h" + +// Noise1234 +// Author: Stefan Gustavson (stegu@itn.liu.se) +// +// This library is public domain software, released by the author +// into the public domain in February 2011. You may do anything +// you like with it. You may even remove all attributions, +// but of course I'd appreciate it if you kept my name somewhere. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. + +/** \file +\brief Implements the Noise1234 class for producing Perlin noise. +\author Stefan Gustavson (stegu@itn.liu.se) +*/ + +/* +* This implementation is "Improved Noise" as presented by +* Ken Perlin at Siggraph 2002. The 3D function is a direct port +* of his Java reference code available on www.noisemachine.com +* (although I cleaned it up and made the code more readable), +* but the 1D, 2D and 4D cases were implemented from scratch +* by me. +* +* This is a highly reusable class. It has no dependencies +* on any other file, apart from its own header file. +*/ + + +// This is the new and improved, C(2) continuous interpolant +#define FADE(t) ( t * t * t * ( t * ( t * 6 - 15 ) + 10 ) ) + +#define FASTFLOOR(x) ( ((x)>0) ? ((int)x) : ((int)x-1 ) ) +#define LERP(t, a, b) ((a) + (t)*((b)-(a))) + + +//--------------------------------------------------------------------- +// Static data + +/* +* Permutation table. This is just a random jumble of all numbers 0-255, +* repeated twice to avoid wrapping the index at 255 for each lookup. +* This needs to be exactly the same for all instances on all platforms, +* so it's easiest to just keep it as static explicit data. +* This also removes the need for any initialisation of this class. +* +* Note that making this an int[] instead of a char[] might make the +* code run faster on platforms with a high penalty for unaligned single +* byte addressing. Intel x86 is generally single-byte-friendly, but +* some other CPUs are faster with 4-aligned reads. +* However, a char[] is smaller, which avoids cache trashing, and that +* is probably the most important aspect on most architectures. +* This array is accessed a *lot* by the noise functions. +* A vector-valued noise over 3D accesses it 96 times, and a +* float-valued 4D noise 64 times. We want this to fit in the cache! +*/ +unsigned char Noise1234::perm[] = { 151,160,137,91,90,15, +131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, +190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, +88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, +77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, +102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, +135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, +5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, +223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, +129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, +251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, +49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, +138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, +151,160,137,91,90,15, +131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, +190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, +88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, +77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, +102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, +135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, +5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, +223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, +129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, +251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, +49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, +138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 +}; + +//--------------------------------------------------------------------- + +/* +* Helper functions to compute gradients-dot-residualvectors (1D to 4D) +* Note that these generate gradients of more than unit length. To make +* a close match with the value range of classic Perlin noise, the final +* noise values need to be rescaled. To match the RenderMan noise in a +* statistical sense, the approximate scaling values (empirically +* determined from test renderings) are: +* 1D noise needs rescaling with 0.188 +* 2D noise needs rescaling with 0.507 +* 3D noise needs rescaling with 0.936 +* 4D noise needs rescaling with 0.87 +* Note that these noise functions are the most practical and useful +* signed version of Perlin noise. To return values according to the +* RenderMan specification from the SL noise() and pnoise() functions, +* the noise values need to be scaled and offset to [0,1], like this: +* float SLnoise = (Noise1234::noise(x,y,z) + 1.0) * 0.5; +*/ + +float Noise1234::grad(int hash, float x) { + int h = hash & 15; + float grad = 1.0 + (h & 7); // Gradient value 1.0, 2.0, ..., 8.0 + if (h & 8) grad = -grad; // and a random sign for the gradient + return (grad * x); // Multiply the gradient with the distance +} + +float Noise1234::grad(int hash, float x, float y) { + int h = hash & 7; // Convert low 3 bits of hash code + float u = h<4 ? x : y; // into 8 simple gradient directions, + float v = h<4 ? y : x; // and compute the dot product with (x,y). + return ((h & 1) ? -u : u) + ((h & 2) ? -2.0*v : 2.0*v); +} + +float Noise1234::grad(int hash, float x, float y, float z) { + int h = hash & 15; // Convert low 4 bits of hash code into 12 simple + float u = h<8 ? x : y; // gradient directions, and compute dot product. + float v = h<4 ? y : h == 12 || h == 14 ? x : z; // Fix repeats at h = 12 to 15 + return ((h & 1) ? -u : u) + ((h & 2) ? -v : v); +} + +float Noise1234::grad(int hash, float x, float y, float z, float t) { + int h = hash & 31; // Convert low 5 bits of hash code into 32 simple + float u = h<24 ? x : y; // gradient directions, and compute dot product. + float v = h<16 ? y : z; + float w = h<8 ? z : t; + return ((h & 1) ? -u : u) + ((h & 2) ? -v : v) + ((h & 4) ? -w : w); +} + +//--------------------------------------------------------------------- +/** 1D float Perlin noise, SL "noise()" +*/ +float Noise1234::noise(float x) +{ + int ix0, ix1; + float fx0, fx1; + float s, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + fx0 = x - ix0; // Fractional part of x + fx1 = fx0 - 1.0f; + ix1 = (ix0 + 1) & 0xff; + ix0 = ix0 & 0xff; // Wrap to 0..255 + + s = FADE(fx0); + + n0 = grad(perm[ix0], fx0); + n1 = grad(perm[ix1], fx1); + return 0.188f * (LERP(s, n0, n1)); +} + +//--------------------------------------------------------------------- +/** 1D float Perlin periodic noise, SL "pnoise()" +*/ +float Noise1234::pnoise(float x, int px) +{ + int ix0, ix1; + float fx0, fx1; + float s, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + fx0 = x - ix0; // Fractional part of x + fx1 = fx0 - 1.0f; + ix1 = ((ix0 + 1) % px) & 0xff; // Wrap to 0..px-1 *and* wrap to 0..255 + ix0 = (ix0 % px) & 0xff; // (because px might be greater than 256) + + s = FADE(fx0); + + n0 = grad(perm[ix0], fx0); + n1 = grad(perm[ix1], fx1); + return 0.188f * (LERP(s, n0, n1)); +} + + +//--------------------------------------------------------------------- +/** 2D float Perlin noise. +*/ +float Noise1234::noise(float x, float y) +{ + int ix0, iy0, ix1, iy1; + float fx0, fy0, fx1, fy1; + float s, t, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 + iy1 = (iy0 + 1) & 0xff; + ix0 = ix0 & 0xff; + iy0 = iy0 & 0xff; + + t = FADE(fy0); + s = FADE(fx0); + + nx0 = grad(perm[ix0 + perm[iy0]], fx0, fy0); + nx1 = grad(perm[ix0 + perm[iy1]], fx0, fy1); + n0 = LERP(t, nx0, nx1); + + nx0 = grad(perm[ix1 + perm[iy0]], fx1, fy0); + nx1 = grad(perm[ix1 + perm[iy1]], fx1, fy1); + n1 = LERP(t, nx0, nx1); + + return 0.507f * (LERP(s, n0, n1)); +} + +//--------------------------------------------------------------------- +/** 2D float Perlin periodic noise. +*/ +float Noise1234::pnoise(float x, float y, int px, int py) +{ + int ix0, iy0, ix1, iy1; + float fx0, fy0, fx1, fy1; + float s, t, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + ix1 = ((ix0 + 1) % px) & 0xff; // Wrap to 0..px-1 and wrap to 0..255 + iy1 = ((iy0 + 1) % py) & 0xff; // Wrap to 0..py-1 and wrap to 0..255 + ix0 = (ix0 % px) & 0xff; + iy0 = (iy0 % py) & 0xff; + + t = FADE(fy0); + s = FADE(fx0); + + nx0 = grad(perm[ix0 + perm[iy0]], fx0, fy0); + nx1 = grad(perm[ix0 + perm[iy1]], fx0, fy1); + n0 = LERP(t, nx0, nx1); + + nx0 = grad(perm[ix1 + perm[iy0]], fx1, fy0); + nx1 = grad(perm[ix1 + perm[iy1]], fx1, fy1); + n1 = LERP(t, nx0, nx1); + + return 0.507f * (LERP(s, n0, n1)); +} + + +//--------------------------------------------------------------------- +/** 3D float Perlin noise. +*/ +float Noise1234::noise(float x, float y, float z) +{ + int ix0, iy0, ix1, iy1, iz0, iz1; + float fx0, fy0, fz0, fx1, fy1, fz1; + float s, t, r; + float nxy0, nxy1, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + iz0 = FASTFLOOR(z); // Integer part of z + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fz0 = z - iz0; // Fractional part of z + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + fz1 = fz0 - 1.0f; + ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 + iy1 = (iy0 + 1) & 0xff; + iz1 = (iz0 + 1) & 0xff; + ix0 = ix0 & 0xff; + iy0 = iy0 & 0xff; + iz0 = iz0 & 0xff; + + r = FADE(fz0); + t = FADE(fy0); + s = FADE(fx0); + + nxy0 = grad(perm[ix0 + perm[iy0 + perm[iz0]]], fx0, fy0, fz0); + nxy1 = grad(perm[ix0 + perm[iy0 + perm[iz1]]], fx0, fy0, fz1); + nx0 = LERP(r, nxy0, nxy1); + + nxy0 = grad(perm[ix0 + perm[iy1 + perm[iz0]]], fx0, fy1, fz0); + nxy1 = grad(perm[ix0 + perm[iy1 + perm[iz1]]], fx0, fy1, fz1); + nx1 = LERP(r, nxy0, nxy1); + + n0 = LERP(t, nx0, nx1); + + nxy0 = grad(perm[ix1 + perm[iy0 + perm[iz0]]], fx1, fy0, fz0); + nxy1 = grad(perm[ix1 + perm[iy0 + perm[iz1]]], fx1, fy0, fz1); + nx0 = LERP(r, nxy0, nxy1); + + nxy0 = grad(perm[ix1 + perm[iy1 + perm[iz0]]], fx1, fy1, fz0); + nxy1 = grad(perm[ix1 + perm[iy1 + perm[iz1]]], fx1, fy1, fz1); + nx1 = LERP(r, nxy0, nxy1); + + n1 = LERP(t, nx0, nx1); + + return 0.936f * (LERP(s, n0, n1)); +} + +//--------------------------------------------------------------------- +/** 3D float Perlin periodic noise. +*/ +float Noise1234::pnoise(float x, float y, float z, int px, int py, int pz) +{ + int ix0, iy0, ix1, iy1, iz0, iz1; + float fx0, fy0, fz0, fx1, fy1, fz1; + float s, t, r; + float nxy0, nxy1, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + iz0 = FASTFLOOR(z); // Integer part of z + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fz0 = z - iz0; // Fractional part of z + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + fz1 = fz0 - 1.0f; + ix1 = ((ix0 + 1) % px) & 0xff; // Wrap to 0..px-1 and wrap to 0..255 + iy1 = ((iy0 + 1) % py) & 0xff; // Wrap to 0..py-1 and wrap to 0..255 + iz1 = ((iz0 + 1) % pz) & 0xff; // Wrap to 0..pz-1 and wrap to 0..255 + ix0 = (ix0 % px) & 0xff; + iy0 = (iy0 % py) & 0xff; + iz0 = (iz0 % pz) & 0xff; + + r = FADE(fz0); + t = FADE(fy0); + s = FADE(fx0); + + nxy0 = grad(perm[ix0 + perm[iy0 + perm[iz0]]], fx0, fy0, fz0); + nxy1 = grad(perm[ix0 + perm[iy0 + perm[iz1]]], fx0, fy0, fz1); + nx0 = LERP(r, nxy0, nxy1); + + nxy0 = grad(perm[ix0 + perm[iy1 + perm[iz0]]], fx0, fy1, fz0); + nxy1 = grad(perm[ix0 + perm[iy1 + perm[iz1]]], fx0, fy1, fz1); + nx1 = LERP(r, nxy0, nxy1); + + n0 = LERP(t, nx0, nx1); + + nxy0 = grad(perm[ix1 + perm[iy0 + perm[iz0]]], fx1, fy0, fz0); + nxy1 = grad(perm[ix1 + perm[iy0 + perm[iz1]]], fx1, fy0, fz1); + nx0 = LERP(r, nxy0, nxy1); + + nxy0 = grad(perm[ix1 + perm[iy1 + perm[iz0]]], fx1, fy1, fz0); + nxy1 = grad(perm[ix1 + perm[iy1 + perm[iz1]]], fx1, fy1, fz1); + nx1 = LERP(r, nxy0, nxy1); + + n1 = LERP(t, nx0, nx1); + + return 0.936f * (LERP(s, n0, n1)); +} + + +//--------------------------------------------------------------------- +/** 4D float Perlin noise. +*/ + +float Noise1234::noise(float x, float y, float z, float w) +{ + int ix0, iy0, iz0, iw0, ix1, iy1, iz1, iw1; + float fx0, fy0, fz0, fw0, fx1, fy1, fz1, fw1; + float s, t, r, q; + float nxyz0, nxyz1, nxy0, nxy1, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + iz0 = FASTFLOOR(z); // Integer part of y + iw0 = FASTFLOOR(w); // Integer part of w + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fz0 = z - iz0; // Fractional part of z + fw0 = w - iw0; // Fractional part of w + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + fz1 = fz0 - 1.0f; + fw1 = fw0 - 1.0f; + ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255 + iy1 = (iy0 + 1) & 0xff; + iz1 = (iz0 + 1) & 0xff; + iw1 = (iw0 + 1) & 0xff; + ix0 = ix0 & 0xff; + iy0 = iy0 & 0xff; + iz0 = iz0 & 0xff; + iw0 = iw0 & 0xff; + + q = FADE(fw0); + r = FADE(fz0); + t = FADE(fy0); + s = FADE(fx0); + + nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx0, fy0, fz0, fw0); + nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx0, fy0, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx0, fy0, fz1, fw0); + nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx0, fy0, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx0 = LERP(r, nxy0, nxy1); + + nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx0, fy1, fz0, fw0); + nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx0, fy1, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx0, fy1, fz1, fw0); + nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx0, fy1, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx1 = LERP(r, nxy0, nxy1); + + n0 = LERP(t, nx0, nx1); + + nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx1, fy0, fz0, fw0); + nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx1, fy0, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx1, fy0, fz1, fw0); + nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx1, fy0, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx0 = LERP(r, nxy0, nxy1); + + nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx1, fy1, fz0, fw0); + nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx1, fy1, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx1, fy1, fz1, fw0); + nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx1, fy1, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx1 = LERP(r, nxy0, nxy1); + + n1 = LERP(t, nx0, nx1); + + return 0.87f * (LERP(s, n0, n1)); +} + +//--------------------------------------------------------------------- +/** 4D float Perlin periodic noise. +*/ + +float Noise1234::pnoise(float x, float y, float z, float w, + int px, int py, int pz, int pw) +{ + int ix0, iy0, iz0, iw0, ix1, iy1, iz1, iw1; + float fx0, fy0, fz0, fw0, fx1, fy1, fz1, fw1; + float s, t, r, q; + float nxyz0, nxyz1, nxy0, nxy1, nx0, nx1, n0, n1; + + ix0 = FASTFLOOR(x); // Integer part of x + iy0 = FASTFLOOR(y); // Integer part of y + iz0 = FASTFLOOR(z); // Integer part of y + iw0 = FASTFLOOR(w); // Integer part of w + fx0 = x - ix0; // Fractional part of x + fy0 = y - iy0; // Fractional part of y + fz0 = z - iz0; // Fractional part of z + fw0 = w - iw0; // Fractional part of w + fx1 = fx0 - 1.0f; + fy1 = fy0 - 1.0f; + fz1 = fz0 - 1.0f; + fw1 = fw0 - 1.0f; + ix1 = ((ix0 + 1) % px) & 0xff; // Wrap to 0..px-1 and wrap to 0..255 + iy1 = ((iy0 + 1) % py) & 0xff; // Wrap to 0..py-1 and wrap to 0..255 + iz1 = ((iz0 + 1) % pz) & 0xff; // Wrap to 0..pz-1 and wrap to 0..255 + iw1 = ((iw0 + 1) % pw) & 0xff; // Wrap to 0..pw-1 and wrap to 0..255 + ix0 = (ix0 % px) & 0xff; + iy0 = (iy0 % py) & 0xff; + iz0 = (iz0 % pz) & 0xff; + iw0 = (iw0 % pw) & 0xff; + + q = FADE(fw0); + r = FADE(fz0); + t = FADE(fy0); + s = FADE(fx0); + + nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx0, fy0, fz0, fw0); + nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx0, fy0, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx0, fy0, fz1, fw0); + nxyz1 = grad(perm[ix0 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx0, fy0, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx0 = LERP(r, nxy0, nxy1); + + nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx0, fy1, fz0, fw0); + nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx0, fy1, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx0, fy1, fz1, fw0); + nxyz1 = grad(perm[ix0 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx0, fy1, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx1 = LERP(r, nxy0, nxy1); + + n0 = LERP(t, nx0, nx1); + + nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw0]]]], fx1, fy0, fz0, fw0); + nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz0 + perm[iw1]]]], fx1, fy0, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw0]]]], fx1, fy0, fz1, fw0); + nxyz1 = grad(perm[ix1 + perm[iy0 + perm[iz1 + perm[iw1]]]], fx1, fy0, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx0 = LERP(r, nxy0, nxy1); + + nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw0]]]], fx1, fy1, fz0, fw0); + nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz0 + perm[iw1]]]], fx1, fy1, fz0, fw1); + nxy0 = LERP(q, nxyz0, nxyz1); + + nxyz0 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw0]]]], fx1, fy1, fz1, fw0); + nxyz1 = grad(perm[ix1 + perm[iy1 + perm[iz1 + perm[iw1]]]], fx1, fy1, fz1, fw1); + nxy1 = LERP(q, nxyz0, nxyz1); + + nx1 = LERP(r, nxy0, nxy1); + + n1 = LERP(t, nx0, nx1); + + return 0.87f * (LERP(s, n0, n1)); +} + +//--------------------------------------------------------------------- + +#define LOCTEXT_NAMESPACE "FWorldArchitectEdModeToolkit" + +FWorldArchitectEdModeToolkit::FWorldArchitectEdModeToolkit() +{ +} + +void FWorldArchitectEdModeToolkit::Init(const TSharedPtr& InitToolkitHost) +{ + struct Locals + { + static bool IsWidgetEnabled() + { + return GEditor->GetSelectedActors()->Num() != 0; + } + + static FReply OnButtonClick(FVector InOffset) + { + USelection* SelectedActors = GEditor->GetSelectedActors(); + + // Let editor know that we're about to do something that we want to undo/redo + GEditor->BeginTransaction(LOCTEXT("MoveActorsTransactionName", "MoveActors")); + + // For each selected actor + for (FSelectionIterator Iter(*SelectedActors); Iter; ++Iter) + { + if (AActor* LevelActor = Cast(*Iter)) + { + // Register actor in opened transaction (undo/redo) + LevelActor->Modify(); + // Move actor to given location + LevelActor->TeleportTo(LevelActor->GetActorLocation() + InOffset, FRotator(0, 0, 0)); + } + } + + // We're done moving actors so close transaction + GEditor->EndTransaction(); + + return FReply::Handled(); + } + + static TSharedRef MakeButton(FText InLabel, const FVector InOffset) + { + return SNew(SButton) + .Text(InLabel) + .OnClicked_Static(&Locals::OnButtonClick, InOffset); + } + }; + + const float Factor = 256.0f; + FAssetData DefaultAsset; + FOnGetAllowedClasses OnGetAllowedClassesDel = FOnGetAllowedClasses::CreateSP(this, &FWorldArchitectEdModeToolkit::OnGetAllowedClasses); + FOnAssetSelected OnAssetSelectedFromPickerDel = FOnAssetSelected::CreateSP(this, &FWorldArchitectEdModeToolkit::OnAssetSelected); + FOnShouldFilterAsset OnShouldFilterAssetDel = FOnShouldFilterAsset::CreateSP(this, &FWorldArchitectEdModeToolkit::OnShouldFilterAsset); + FSimpleDelegate OnCloseDel; + TArray AllowedClasses; + AllowedClasses.Add(UWALandscapeGraph::StaticClass()); + TArray NewAssetFactory; + NewAssetFactory.Add(UWALandscapeGraphFactory::StaticClass()->GetDefaultObject()); + + SAssignNew(ToolkitWidget, SBorder) + .HAlign(HAlign_Center) + .Padding(25) + //.IsEnabled_Static(&Locals::IsWidgetEnabled) + [ + SNew(SVerticalBox) + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(HAlign_Center) + .Padding(50) + [ + SNew(STextBlock) + .AutoWrapText(true) + .Text(LOCTEXT("HelperLabel", "Select some actors and move them around using buttons below")) + ] + + SVerticalBox::Slot() + .HAlign(HAlign_Center) + .AutoHeight() + [ + Locals::MakeButton(LOCTEXT("UpButtonLabel", "Up"), FVector(0, 0, Factor)) + ] + + SVerticalBox::Slot() + .HAlign(HAlign_Center) + .AutoHeight() + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .AutoWidth() + [ + Locals::MakeButton(LOCTEXT("LeftButtonLabel", "Left"), FVector(0, -Factor, 0)) + ] + + SHorizontalBox::Slot() + .AutoWidth() + [ + Locals::MakeButton(LOCTEXT("RightButtonLabel", "Right"), FVector(0, Factor, 0)) + ] + ] + + SVerticalBox::Slot() + .HAlign(HAlign_Center) + .AutoHeight() + [ + Locals::MakeButton(LOCTEXT("DownButtonLabel", "Down"), FVector(0, 0, -Factor)) + ] + + SVerticalBox::Slot() + .HAlign(HAlign_Center) + .AutoHeight() + [ + SNew(SButton) + .Text(FText::FromString("Make Noise")) + .OnClicked(this, &FWorldArchitectEdModeToolkit::OnGenerateNoise) + ] + + SVerticalBox::Slot() + .HAlign(HAlign_Center) + .AutoHeight() + [ + SNew(SButton) + .Text(FText::FromString("Generate Landscape")) + .OnClicked(this, &FWorldArchitectEdModeToolkit::OnGenerateLandscape) + ] + + SVerticalBox::Slot() + .HAlign(HAlign_Center) + .AutoHeight() + [ + SNew(STextBlock) + .Text(this, &FWorldArchitectEdModeToolkit::OnGetGraphName) + + ] + +SVerticalBox::Slot() + .HAlign(HAlign_Center) + .AutoHeight() + [ + //PropertyCustomizationHelpers::MakeAssetPickerAnchorButton(OnGetAllowedClassesDel, OnAssetSelectedFromPickerDel) + PropertyCustomizationHelpers::MakeAssetPickerWithMenu(DefaultAsset, true, AllowedClasses, NewAssetFactory, OnShouldFilterAssetDel, OnAssetSelectedFromPickerDel, OnCloseDel) + ] + + ]; + + FModeToolkit::Init(InitToolkitHost); +} + +FName FWorldArchitectEdModeToolkit::GetToolkitFName() const +{ + return FName("WorldArchitectEdMode"); +} + +FText FWorldArchitectEdModeToolkit::GetBaseToolkitName() const +{ + return NSLOCTEXT("WorldArchitectEdModeToolkit", "DisplayName", "WorldArchitectEdMode Tool"); +} + +class FEdMode* FWorldArchitectEdModeToolkit::GetEditorMode() const +{ + return GLevelEditorModeTools().GetActiveMode(FWorldArchitectEdMode::EM_WorldArchitectEdModeId); +} +uint16 FWorldArchitectEdModeToolkit::PerlinNoise2D(float x, float y, float amp, int32 octaves, int32 px, int32 py) +{ + float noise = 0.f; + for (int octave = 1; octave < octaves; octave *= 2) + noise += Noise1234::pnoise( x*px*octave, y*py*octave, px, py ) / octave; + + return USHRT_MAX/2.f + amp*noise; +} +float FWorldArchitectEdModeToolkit::PerlinNoise2DFloat(float x, float y, float amp, int32 octaves, int32 px, int32 py) +{ + float noise = 0.f; + for (int octave = 1; octave < octaves; octave *= 2) + noise += Noise1234::pnoise(x*px*octave, y*py*octave, px, py) / octave; + + return noise; +} +FReply FWorldArchitectEdModeToolkit::OnGenerateNoise() +{ + GEditor->GetWorld(); + TArray Landscapes; + for (TActorIterator LIter(GetEditorMode()->GetWorld()); LIter; ++LIter) + { + Landscapes.Add(*LIter); + } + auto& LandscapeInfoMap = ULandscapeInfoMap::GetLandscapeInfoMap(GetEditorMode()->GetWorld()); + + + if (Landscapes.Num() > 0) + { + FIntRect bounds = Landscapes[0]->GetBoundingRect(); + + int32 numHeights = (bounds.Width() + 1)*(bounds.Height() + 1); + TArray Data; + Data.Init(0, numHeights); + TArray DataFloat; + DataFloat.Init(0, numHeights); + TArray DataFloat2; + DataFloat2.Init(0, numHeights); + TArray DataFloat3; + DataFloat3.Init(0, numHeights); + + int32 cols = bounds.Width() + 1, rows = bounds.Height() + 1; + int32 octaves = 16, px = 4, py = 4; + float amplitude = 20000.f; + //for (int i = 0; i < Data.Num(); i++) + //{ + // float nx = (i % cols) / (float)cols; //normalized col + // float ny = (i / cols) / (float)rows; //normalized row + // Data[i] = FMath::Clamp(PerlinNoise2D(nx, ny, amplitude, octaves, px, py), 0, 32768); + //} + for (int i = 0; i < DataFloat.Num(); i++) + { + float nx = (i % cols) / (float)cols; //normalized col + float ny = (i / cols) / (float)rows; //normalized row + DataFloat[i] = PerlinNoise2DFloat(nx, ny, amplitude, octaves, px, py); + DataFloat2[i] = PerlinNoise2DFloat(nx, ny, amplitude, 4, 12, 12); + DataFloat3[i] = DataFloat[i] * DataFloat2[i]; + } + for (int i = 0; i < Data.Num(); i++) + { + Data[i] = (USHRT_MAX / 2.f) + (DataFloat3[i] * amplitude); + } + ULandscapeInfo::RecreateLandscapeInfo(GetEditorMode()->GetWorld(), 1); + LandscapeEditorUtils::SetHeightmapData(Landscapes[0], Data); + ULandscapeInfo::RecreateLandscapeInfo(GetEditorMode()->GetWorld(), 1); + for (auto It = LandscapeInfoMap.Map.CreateIterator(); It; ++It) + { + ULandscapeInfo* LandscapeInfo = It.Value(); + if (LandscapeInfo && !LandscapeInfo->IsPendingKill()) + { + ALandscapeProxy* LandscapeProxy = LandscapeInfo->GetLandscapeProxy(); + if (LandscapeProxy) + { + for (ALandscapeStreamingProxy* Proxy : LandscapeInfo->Proxies) + { + ULandscapeInfo::RecreateLandscapeInfo(GetEditorMode()->GetWorld(), 1); + LandscapeEditorUtils::SetHeightmapData(Proxy, Data); + ULandscapeInfo::RecreateLandscapeInfo(GetEditorMode()->GetWorld(), 1); + } + + //if (CurrentToolTarget.LandscapeInfo == LandscapeInfo) + { + //CurrentIndex = Index; + + // Update GizmoActor Landscape Target (is this necessary?) + //if (CurrentGizmoActor.IsValid()) + { + // CurrentGizmoActor->SetTargetLandscape(LandscapeInfo); + } + } + + int32 MinX, MinY, MaxX, MaxY; + int32 Width = 0, Height = 0; + if (LandscapeInfo->GetLandscapeExtent(MinX, MinY, MaxX, MaxY)) + { + Width = MaxX - MinX + 1; + Height = MaxY - MinY + 1; + } + + /*LandscapeList.Add(FLandscapeListInfo(*LandscapeProxy->GetName(), LandscapeInfo, + LandscapeInfo->ComponentSizeQuads, LandscapeInfo->ComponentNumSubsections, Width, Height)); + Index++;*/ + } + } + } + } + + + //LandscapeEditorUtils::SetHeightmapData(Landscapes[0], Data); + + return FReply::Unhandled(); +} +FReply FWorldArchitectEdModeToolkit::OnGenerateLandscape() +{ + if(!LandscapeGraph.IsValid()) + return FReply::Unhandled(); + + //LandscapeGraph->GenerateLandscape(); + if (!LandscapeGraph->Schema) + return FReply::Unhandled(); + + if (!LandscapeGraph->Schema->Output) + return FReply::Unhandled(); + + TArray Out; + LandscapeGraph->Schema->Output->GenerateHeightMap(Out); + return FReply::Handled(); +} +void FWorldArchitectEdModeToolkit::OnAssetSelected(const FAssetData& InAssetData) +{ + UObject* Object = InAssetData.GetAsset(); + if (UWALandscapeGraph* Graph = Cast(Object)) + { + LandscapeGraph = Graph; + return; + } + + LandscapeGraph.Reset(); +} +void FWorldArchitectEdModeToolkit::OnGetAllowedClasses(TArray& OutAllowedClasses) +{ + OutAllowedClasses.Add(UWALandscapeGraph::StaticClass()); +} +bool FWorldArchitectEdModeToolkit::OnShouldFilterAsset(const FAssetData& InAssetData) +{ + return false; +} +FText FWorldArchitectEdModeToolkit::OnGetGraphName() const +{ + if (LandscapeGraph.IsValid()) + { + return FText::FromString(LandscapeGraph->GetName()); + } + + return FText::FromString("No Graph Selected"); +} +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdModeToolkit.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdModeToolkit.h new file mode 100644 index 0000000..4791b20 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEdModeToolkit.h @@ -0,0 +1,91 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Toolkits/BaseToolkit.h" +// Noise1234 +// Author: Stefan Gustavson (stegu@itn.liu.se) +// +// This library is public domain software, released by the author +// into the public domain in February 2011. You may do anything +// you like with it. You may even remove all attributions, +// but of course I'd appreciate it if you kept my name somewhere. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. + +/** \file +\brief Declares the Noise1234 class for producing Perlin noise. +\author Stefan Gustavson (stegu@itn.liu.se) +*/ + +/* +* This is a clean, fast, modern and free Perlin noise class in C++. +* Being a stand-alone class with no external dependencies, it is +* highly reusable without source code modifications. +* +* Note: +* Replacing the "float" type with "double" can actually make this run faster +* on some platforms. A templatized version of Noise1234 could be useful. +*/ + +class Noise1234 { + +public: + Noise1234() {} + ~Noise1234() {} + + /** 1D, 2D, 3D and 4D float Perlin noise, SL "noise()" + */ + static float noise(float x); + static float noise(float x, float y); + static float noise(float x, float y, float z); + static float noise(float x, float y, float z, float w); + + /** 1D, 2D, 3D and 4D float Perlin periodic noise, SL "pnoise()" + */ + static float pnoise(float x, int px); + static float pnoise(float x, float y, int px, int py); + static float pnoise(float x, float y, float z, int px, int py, int pz); + static float pnoise(float x, float y, float z, float w, + int px, int py, int pz, int pw); + +private: + static unsigned char perm[]; + static float grad(int hash, float x); + static float grad(int hash, float x, float y); + static float grad(int hash, float x, float y, float z); + static float grad(int hash, float x, float y, float z, float t); + +}; +class FWorldArchitectEdModeToolkit : public FModeToolkit +{ + + TWeakObjectPtr LandscapeGraph; +public: + + FWorldArchitectEdModeToolkit(); + + /** FModeToolkit interface */ + virtual void Init(const TSharedPtr& InitToolkitHost) override; + + /** IToolkit interface */ + virtual FName GetToolkitFName() const override; + virtual FText GetBaseToolkitName() const override; + virtual class FEdMode* GetEditorMode() const override; + virtual TSharedPtr GetInlineContent() const override { return ToolkitWidget; } + uint16 PerlinNoise2D(float x, float y, float amp, int32 octaves, int32 px, int32 py); + float PerlinNoise2DFloat(float x, float y, float amp, int32 octaves, int32 px, int32 py); + FReply OnGenerateNoise(); + FReply OnGenerateLandscape(); + void OnAssetSelected(const FAssetData& InAssetData); + void OnGetAllowedClasses(TArray& OutAllowedClasses); + bool OnShouldFilterAsset(const FAssetData& InAssetData); + FText OnGetGraphName() const; +private: + + TSharedPtr ToolkitWidget; +}; diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEditor.cpp b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEditor.cpp new file mode 100644 index 0000000..c7ae9d5 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEditor.cpp @@ -0,0 +1,41 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "WorldArchitectEditor.h" +#include "WorldArchitectEdMode.h" +#include "WALandscapeGraphAssetTypeActions.h" +#define LOCTEXT_NAMESPACE "FWorldArchitectModule" +void FWorldArchitectEditorModule::RegisterAssetTypeAction(IAssetTools& AssetTools, + TSharedRef Action) +{ + AssetTools.RegisterAssetTypeActions(Action); + CreatedAssetTypeActions.Add(Action); +} +void FWorldArchitectEditorModule::StartupModule() +{ + IAssetTools& AssetTools = FModuleManager::LoadModuleChecked("AssetTools").Get(); + + GenericGraphAssetCategoryBit = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("Landscape")), FText::FromString("Landscape")); + RegisterAssetTypeAction(AssetTools, MakeShareable(new FWALandscapeGraphAssetTypeActions(GenericGraphAssetCategoryBit))); + + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module + FEditorModeRegistry::Get().RegisterMode(FWorldArchitectEdMode::EM_WorldArchitectEdModeId, LOCTEXT("WorldArchitectEdModeName", "WorldArchitectEdMode"), FSlateIcon(), true); +} + +void FWorldArchitectEditorModule::ShutdownModule() +{ + if (FModuleManager::Get().IsModuleLoaded("AssetTools")) + { + IAssetTools& AssetTools = FModuleManager::GetModuleChecked("AssetTools").Get(); + for (int32 Index = 0; Index < CreatedAssetTypeActions.Num(); ++Index) + { + AssetTools.UnregisterAssetTypeActions(CreatedAssetTypeActions[Index].ToSharedRef()); + } + } + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. + FEditorModeRegistry::Get().UnregisterMode(FWorldArchitectEdMode::EM_WorldArchitectEdModeId); +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FWorldArchitectEditorModule, WorldArchitect) \ No newline at end of file diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEditor.h b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEditor.h new file mode 100644 index 0000000..01747e7 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/Public/WorldArchitectEditor.h @@ -0,0 +1,18 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "ModuleManager.h" +#include "IAssetTools.h" + +class FWorldArchitectEditorModule : public IModuleInterface +{ + TArray< TSharedPtr > CreatedAssetTypeActions; + EAssetTypeCategories::Type GenericGraphAssetCategoryBit; +public: + void RegisterAssetTypeAction(IAssetTools& AssetTools, TSharedRef Action); + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; \ No newline at end of file diff --git a/Plugins/WorldArchitect/Source/WorldArchitectEditor/WorldArchitectEditor.Build.cs b/Plugins/WorldArchitect/Source/WorldArchitectEditor/WorldArchitectEditor.Build.cs new file mode 100644 index 0000000..6009f34 --- /dev/null +++ b/Plugins/WorldArchitect/Source/WorldArchitectEditor/WorldArchitectEditor.Build.cs @@ -0,0 +1,59 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class WorldArchitectEditor : ModuleRules +{ + public WorldArchitectEditor(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PrivateIncludePaths.AddRange( + new string[] { + "WorldArchitectEditor/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "Core", + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "InputCore", + "UnrealEd", + "LevelEditor", + "Landscape", + "LandscapeEditor", + "GraphEditor", + "PropertyEditor", + "EditorStyle", + "Kismet", + "KismetWidgets", + "ApplicationCore" + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/uFire/Source/uFire/Private/uFire.cpp b/Plugins/uFire/Source/uFire/Private/uFire.cpp new file mode 100644 index 0000000..29ffa31 --- /dev/null +++ b/Plugins/uFire/Source/uFire/Private/uFire.cpp @@ -0,0 +1,20 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#include "uFire.h" + +#define LOCTEXT_NAMESPACE "FuFireModule" + +void FuFireModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +} + +void FuFireModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FuFireModule, uFire) \ No newline at end of file diff --git a/Plugins/uFire/Source/uFire/Public/uFire.h b/Plugins/uFire/Source/uFire/Public/uFire.h new file mode 100644 index 0000000..df4530b --- /dev/null +++ b/Plugins/uFire/Source/uFire/Public/uFire.h @@ -0,0 +1,15 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class FuFireModule : public IModuleInterface +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; +}; diff --git a/Plugins/uFire/Source/uFire/uFire.Build.cs b/Plugins/uFire/Source/uFire/uFire.Build.cs new file mode 100644 index 0000000..fba39a0 --- /dev/null +++ b/Plugins/uFire/Source/uFire/uFire.Build.cs @@ -0,0 +1,50 @@ +// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class uFire : ModuleRules +{ + public uFire(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + //PublicIncludePaths.AddRange(); + + + PrivateIncludePaths.AddRange( + new string[] { + "uFire/Private", + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/Plugins/uFire/uFire.uplugin b/Plugins/uFire/uFire.uplugin new file mode 100644 index 0000000..abc9609 --- /dev/null +++ b/Plugins/uFire/uFire.uplugin @@ -0,0 +1,23 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "uFire", + "Description": "Firebase REST/gRPC API integration.", + "Category": "Other", + "CreatedBy": "Lukasz 'iniside' Baran", + "CreatedByURL": "", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": false, + "Installed": false, + "Modules": [ + { + "Name": "uFire", + "Type": "Developer", + "LoadingPhase": "Default" + } + ] +} \ No newline at end of file diff --git a/README b/README deleted file mode 100644 index f9969d5..0000000 --- a/README +++ /dev/null @@ -1,15 +0,0 @@ -Hello and welcome to ActionRPG Game project for Unreal Engine 4. - -Note: -It is more or less compatibile with latest master branch from official UE4 repo. - -It is under heavy development, sweeping, copatibility breaking changes are to be expected. - -Replication/Multiplayer support is currently rudimentary, though it works, -there is noise advanced prediction. it just dot naive prediction of let client do whatever and then -server override it (since server still have 100% authority). - -License: - -Use at your own risk. I currently do not provide any support. What you fork or clone is yours to -use in any product. \ No newline at end of file diff --git a/Source/ActionRPGGame.Target.cs b/Source/ActionRPGGame.Target.cs index ff9dc29..ca32280 100644 --- a/Source/ActionRPGGame.Target.cs +++ b/Source/ActionRPGGame.Target.cs @@ -1,4 +1,4 @@ -// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; using System.Collections.Generic; @@ -7,8 +7,7 @@ public class ActionRPGGameTarget : TargetRules { public ActionRPGGameTarget(TargetInfo Target) : base(Target) { - LaunchModuleName = "ActionRPGGame"; - ExtraModuleNames.Add("ActionRPGGame"); - Type = TargetType.Game; - } + Type = TargetType.Game; + ExtraModuleNames.Add("ActionRPGGame"); + } } diff --git a/Source/ActionRPGGame/ARCharacter.cpp b/Source/ActionRPGGame/ARCharacter.cpp deleted file mode 100644 index affe2d6..0000000 --- a/Source/ActionRPGGame/ARCharacter.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. - -#include "ARCharacter.h" -#include "Camera/CameraComponent.h" -#include "Components/CapsuleComponent.h" -#include "Components/InputComponent.h" -#include "GameFramework/CharacterMovementComponent.h" -#include "GameFramework/Controller.h" -#include "GameFramework/SpringArmComponent.h" - -////////////////////////////////////////////////////////////////////////// -// AARCharacter - -AARCharacter::AARCharacter() -{ - // Set size for collision capsule - GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f); - - // set our turn rates for input - BaseTurnRate = 45.f; - BaseLookUpRate = 45.f; - - // Don't rotate when the controller rotates. Let that just affect the camera. - bUseControllerRotationPitch = false; - bUseControllerRotationYaw = false; - bUseControllerRotationRoll = false; - - // Configure character movement - GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input... - GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f); // ...at this rotation rate - GetCharacterMovement()->JumpZVelocity = 600.f; - GetCharacterMovement()->AirControl = 0.2f; - - // Create a camera boom (pulls in towards the player if there is a collision) - CameraBoom = CreateDefaultSubobject(TEXT("CameraBoom")); - CameraBoom->SetupAttachment(RootComponent); - CameraBoom->TargetArmLength = 300.0f; // The camera follows at this distance behind the character - CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller - - // Create a follow camera - FollowCamera = CreateDefaultSubobject(TEXT("FollowCamera")); - FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation - FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm - - AbilitiesComponent = CreateDefaultSubobject(TEXT("AbilitiesComponent")); - - // Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) - // are set in the derived blueprint asset named MyCharacter (to avoid direct content references in C++) -} - -////////////////////////////////////////////////////////////////////////// -// Input - -void AARCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) -{ - // Set up gameplay key bindings - check(PlayerInputComponent); - PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump); - PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping); - - PlayerInputComponent->BindAxis("MoveForward", this, &AARCharacter::MoveForward); - PlayerInputComponent->BindAxis("MoveRight", this, &AARCharacter::MoveRight); - - // We have 2 versions of the rotation bindings to handle different kinds of devices differently - // "turn" handles devices that provide an absolute delta, such as a mouse. - // "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick - PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput); - PlayerInputComponent->BindAxis("TurnRate", this, &AARCharacter::TurnAtRate); - PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput); - PlayerInputComponent->BindAxis("LookUpRate", this, &AARCharacter::LookUpAtRate); - - // handle touch devices - PlayerInputComponent->BindTouch(IE_Pressed, this, &AARCharacter::TouchStarted); - PlayerInputComponent->BindTouch(IE_Released, this, &AARCharacter::TouchStopped); - - // VR headset functionality - PlayerInputComponent->BindAction("ResetVR", IE_Pressed, this, &AARCharacter::OnResetVR); -} - - -void AARCharacter::OnResetVR() -{ -} - -void AARCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location) -{ - Jump(); -} - -void AARCharacter::TouchStopped(ETouchIndex::Type FingerIndex, FVector Location) -{ - StopJumping(); -} - -void AARCharacter::TurnAtRate(float Rate) -{ - // calculate delta for this frame from the rate information - AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds()); -} - -void AARCharacter::LookUpAtRate(float Rate) -{ - // calculate delta for this frame from the rate information - AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds()); -} - -void AARCharacter::MoveForward(float Value) -{ - if ((Controller != NULL) && (Value != 0.0f)) - { - // find out which way is forward - const FRotator Rotation = Controller->GetControlRotation(); - const FRotator YawRotation(0, Rotation.Yaw, 0); - - // get forward vector - const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X); - AddMovementInput(Direction, Value); - } -} - -void AARCharacter::MoveRight(float Value) -{ - if ( (Controller != NULL) && (Value != 0.0f) ) - { - // find out which way is right - const FRotator Rotation = Controller->GetControlRotation(); - const FRotator YawRotation(0, Rotation.Yaw, 0); - - // get right vector - const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y); - // add movement in that direction - AddMovementInput(Direction, Value); - } -} diff --git a/Source/ActionRPGGame/ARCharacter.h b/Source/ActionRPGGame/ARCharacter.h deleted file mode 100644 index 5c08a80..0000000 --- a/Source/ActionRPGGame/ARCharacter.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. - -#pragma once - -#include "CoreMinimal.h" -#include "GameFramework/Character.h" -#include "GAAbilitiesComponent.h" -#include "ARCharacter.generated.h" - -UCLASS(config=Game) -class AARCharacter : public ACharacter -{ - GENERATED_BODY() - - /** Camera boom positioning the camera behind the character */ - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) - class USpringArmComponent* CameraBoom; - - /** Follow camera */ - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) - class UCameraComponent* FollowCamera; - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) - class UGAAbilitiesComponent* AbilitiesComponent; -public: - AARCharacter(); - - /** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */ - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera) - float BaseTurnRate; - - /** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */ - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera) - float BaseLookUpRate; - -protected: - - /** Resets HMD orientation in VR. */ - void OnResetVR(); - - /** Called for forwards/backward input */ - void MoveForward(float Value); - - /** Called for side to side input */ - void MoveRight(float Value); - - /** - * Called via input to turn at a given rate. - * @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate - */ - void TurnAtRate(float Rate); - - /** - * Called via input to turn look up/down at a given rate. - * @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate - */ - void LookUpAtRate(float Rate); - - /** Handler for when a touch input begins. */ - void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location); - - /** Handler for when a touch input stops. */ - void TouchStopped(ETouchIndex::Type FingerIndex, FVector Location); - -protected: - // APawn interface - virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; - // End of APawn interface - -public: - /** Returns CameraBoom subobject **/ - FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; } - /** Returns FollowCamera subobject **/ - FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; } -}; - diff --git a/Source/ActionRPGGame/ARGameMode.cpp b/Source/ActionRPGGame/ARGameMode.cpp deleted file mode 100644 index b24ea44..0000000 --- a/Source/ActionRPGGame/ARGameMode.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. - -#include "ARGameMode.h" -#include "ARCharacter.h" -#include "UObject/ConstructorHelpers.h" - -AARGameMode::AARGameMode() -{ -} diff --git a/Source/ActionRPGGame/ActionRPGGame.Build.cs b/Source/ActionRPGGame/ActionRPGGame.Build.cs index b004faf..7df1898 100644 --- a/Source/ActionRPGGame/ActionRPGGame.Build.cs +++ b/Source/ActionRPGGame/ActionRPGGame.Build.cs @@ -4,10 +4,80 @@ public class ActionRPGGame : ModuleRules { - public ActionRPGGame(ReadOnlyTargetRules Target) : base(Target) - { - PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + public ActionRPGGame(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + PublicDefinitions.Add("BOOST_SYSTEM_NOEXCEPT"); + PublicDefinitions.Add("GPR_FORBID_UNREACHABLE_CODE=1"); + PublicDefinitions.Add("GOOGLE_PROTOBUF_NO_RTTI=1"); + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + PublicDependencyModuleNames.AddRange(new string[] { + "Core", + "CoreUObject", + "Engine", + "InputCore", + "Json", + "JsonUtilities", + "GameplayTags", + "AbilityFramework", + "AssetRegistry", + "OrionAnimation", + "ActorSequence", + "JsonUObject", + "InventoryFramework", + "OnlineSubsystem" + }); - PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "AbilityFramework" }); - } + if (Target.Type == TargetRules.TargetType.Editor) + { + PublicDependencyModuleNames.AddRange(new string[] { "UnrealEd", "SourceControl", "Matinee", "PropertyEditor", "ShaderCore", "AbilityFrameworkEditor" }); + PrivateDependencyModuleNames.AddRange(new string[] { "AbilityFrameworkEditor" }); + } + PublicDependencyModuleNames.AddRange(new string[] { "GRPC" }); + PublicDefinitions.Add("GPR_GCOV=1"); //hax + if (Target.Type == TargetRules.TargetType.Server) + { + if (Target.Platform == UnrealTargetPlatform.Linux) + { + PublicDefinitions.Add("WITH_AGONES=1"); + PublicDefinitions.Add("ENABLE_GRPC=1"); //hack + PublicDependencyModuleNames.AddRange(new string[] { "Agones" }); + + } + else + { + PublicDefinitions.Add("WITH_AGONES=0"); + PublicDefinitions.Add("ENABLE_GRPC=0"); //hack + } + } + else + { + PublicDefinitions.Add("WITH_AGONES=0"); + PublicDefinitions.Add("ENABLE_GRPC=0"); //hack + } + + if ( (Target.Type == TargetRules.TargetType.Client) || (Target.Type == TargetRules.TargetType.Editor)) + { + PublicDependencyModuleNames.AddRange(new string[] { + "Slate", + "SlateCore", + "UMG", + "InventoryFrameworkUI", + "DraggableWindow" + }); + + if (Target.Platform == UnrealTargetPlatform.Win64) + { + if (Target.Type == TargetRules.TargetType.Client) + { + bEnableExceptions = true; + } + } + } + } } + diff --git a/Source/ActionRPGGame/ActionRPGGame.cpp b/Source/ActionRPGGame/ActionRPGGame.cpp deleted file mode 100644 index 173c45d..0000000 --- a/Source/ActionRPGGame/ActionRPGGame.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. - -#include "ActionRPGGame.h" -#include "Modules/ModuleManager.h" - -IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, ActionRPGGame, "ActionRPGGame" ); - \ No newline at end of file diff --git a/Source/ActionRPGGame/ActionRPGGame.h b/Source/ActionRPGGame/ActionRPGGame.h deleted file mode 100644 index 25b0d29..0000000 --- a/Source/ActionRPGGame/ActionRPGGame.h +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. - -#pragma once - -#include "CoreMinimal.h" diff --git a/Source/ActionRPGGame/Private/AI/ARAICharacter.cpp b/Source/ActionRPGGame/Private/AI/ARAICharacter.cpp new file mode 100644 index 0000000..395d992 --- /dev/null +++ b/Source/ActionRPGGame/Private/AI/ARAICharacter.cpp @@ -0,0 +1,85 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARAICharacter.h" +#include "AREnemySpawner.h" + +// Sets default values +AARAICharacter::AARAICharacter() +{ + // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + Abilities = CreateDefaultSubobject(TEXT("Abilities")); + EffectsComponent = CreateDefaultSubobject(TEXT("EffectsComponent")); +} + +// Called when the game starts or when spawned +void AARAICharacter::BeginPlay() +{ + Super::BeginPlay(); + +} +void AARAICharacter::OnSpawned(class AAREnemySpawner* InSpawnedBy) +{ + SpawnedBy = InSpawnedBy; +} +// Called every frame +void AARAICharacter::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + +// Called to bind functionality to input +void AARAICharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); + +} + +void AARAICharacter::Kill() +{ + if(SpawnedBy) + SpawnedBy->OnEnemyKilled(this); + + Destroy(); +} + +/* IAFAbilityInterface- BEGIN */ +class UAFAbilityComponent* AARAICharacter::GetAbilityComp() +{ + return Abilities; +}; +class UAFEffectsComponent* AARAICharacter::GetEffectsComponent() +{ + return EffectsComponent; +} +class UAFEffectsComponent* AARAICharacter::NativeGetEffectsComponent() const +{ + return EffectsComponent; +} +float AARAICharacter::GetAttributeValue(FGAAttribute AttributeIn) const +{ + return Abilities->GetAttributeValue(AttributeIn); +} + +void AARAICharacter::ModifyAttribute(FGAEffectMod& ModIn, const FGAEffectHandle& HandleIn, + struct FGAEffectProperty& InProperty, const FGAEffectContext& InContex) +{ + Abilities->ModifyAttribute(ModIn, HandleIn, InProperty, InContex); +} + +FAFAttributeBase* AARAICharacter::GetAttribute(FGAAttribute AttributeIn) +{ + return Abilities->GetAttribute(AttributeIn); +}; + +void AARAICharacter::RemoveBonus(FGAAttribute AttributeIn, const FGAEffectHandle& HandleIn, EGAAttributeMod InMod) +{ + Abilities->RemoveBonus(AttributeIn, HandleIn, InMod); +} + +float AARAICharacter::NativeGetAttributeValue(const FGAAttribute AttributeIn) const +{ + return Abilities->NativeGetAttributeValue(AttributeIn); +} +/* IAFAbilityInterface- END */ \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/AI/ARAIController.cpp b/Source/ActionRPGGame/Private/AI/ARAIController.cpp new file mode 100644 index 0000000..62c59a4 --- /dev/null +++ b/Source/ActionRPGGame/Private/AI/ARAIController.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARAIController.h" + + + + diff --git a/Source/ActionRPGGame/Private/ARCharacter.cpp b/Source/ActionRPGGame/Private/ARCharacter.cpp new file mode 100644 index 0000000..855e75b --- /dev/null +++ b/Source/ActionRPGGame/Private/ARCharacter.cpp @@ -0,0 +1,484 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "ARCharacter.h" +#include "Camera/CameraComponent.h" +#include "Components/CapsuleComponent.h" +#include "Components/InputComponent.h" +#include "GameFramework/CharacterMovementComponent.h" +#include "GameFramework/Controller.h" +#include "GameFramework/SpringArmComponent.h" +#include "Net/UnrealNetwork.h" +#include "Engine/ActorChannel.h" + +#include "Weapons/ARWeaponBase.h" +#include "UI/ARUIComponent.h" + +#include "Weapons/ARWeaponInventoryComponent.h" +#include "ARCharacterMovementComponent.h" +#include "ARPlayerController.h" +#include "ARAbilityBase.h" + +////////////////////////////////////////////////////////////////////////// +// AARCharacter + +const FName WeaponSocket::HolsteredRightWeapon = TEXT("spine_RightWeaponSocket"); +const FName WeaponSocket::HolsteredLeftWeapon = TEXT("spine_LeftWeaponSocket"); +const FName WeaponSocket::EquipedMainWeapon = TEXT("hand_rSocket"); + +AARCharacter::AARCharacter(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer.SetDefaultSubobjectClass(ACharacter::CharacterMovementComponentName)) +{ + // Set size for collision capsule + GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f); + + // set our turn rates for input + BaseTurnRate = 5.f; + BaseLookUpRate = 25.f; + // Don't rotate when the controller rotates. Let that just affect the camera. + bUseControllerRotationPitch = false; + bUseControllerRotationYaw = false; + bUseControllerRotationRoll = false; + + // Configure character movement + GetCharacterMovement()->bOrientRotationToMovement = false; // Character moves in the direction of input... + GetCharacterMovement()->bUseControllerDesiredRotation = true; + GetCharacterMovement()->RotationRate = FRotator(0.0f, 180.0f, 0.0f); // ...at this rotation rate + GetCharacterMovement()->JumpZVelocity = 400.f; + GetCharacterMovement()->AirControl = 0.2f; + + GetCharacterMovement()->MaxAcceleration = 200.0f; + GetCharacterMovement()->BrakingFriction = 1.0; + GetCharacterMovement()->bUseSeparateBrakingFriction = true; + GetCharacterMovement()->Mass = 80.0f; + GetCharacterMovement()->GroundFriction = 1.0f; + GetCharacterMovement()->MaxWalkSpeed = 270.0f; + GetCharacterMovement()->MaxWalkSpeedCrouched = 150.0f; + GetCharacterMovement()->BrakingDecelerationWalking = 150.0f; + + OrionAnimComp = CreateDefaultSubobject(TEXT("OrionAnimComp")); + + // Create a camera boom (pulls in towards the player if there is a collision) + CameraBoom = CreateDefaultSubobject(TEXT("CameraBoom")); + //CameraBoom->SetupAttachment(GetMesh()); + CameraBoom->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, TEXT("headSocket")); + + CameraBoom->TargetArmLength = 285; // The camera follows at this distance behind the character + CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller + CameraBoom->SocketOffset = FVector(0, 35, 65); + CameraBoom->TargetOffset = FVector(0, 0, -45); + CameraBoom->bEnableCameraLag = true; + CameraBoom->bEnableCameraRotationLag = true; + CameraBoom->CameraLagSpeed = 8; + CameraBoom->CameraRotationLagSpeed = 7; + CameraBoom->CameraLagMaxDistance = 10; + CameraBoom->ProbeSize = 0.05f; + + // Create a follow camera + FollowCamera = CreateDefaultSubobject(TEXT("FollowCamera")); + FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation + FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm + + Abilities = CreateDefaultSubobject(TEXT("Abilities")); + Abilities->SetIsReplicated(true); + EffectsComponent = CreateDefaultSubobject(TEXT("EffectsComponent")); + EffectsComponent->SetIsReplicated(true); + + WeaponInventory = ObjectInitializer.CreateDefaultSubobject(this, TEXT("WeaponInventory")); + WeaponInventory->SetIsReplicated(true); + + FollowCamera->TransformUpdated.AddUObject(this, &AARCharacter::OnCameraTransformUpdate); + + Head = CreateDefaultSubobject(TEXT("Head")); + Head->SetupAttachment(GetMesh()); + + Shoulders = CreateDefaultSubobject(TEXT("Shoulders")); + Shoulders->SetupAttachment(GetMesh()); + + + Arms = CreateDefaultSubobject(TEXT("Arms")); + Arms->SetupAttachment(GetMesh()); + + + Hands = CreateDefaultSubobject(TEXT("Hands")); + Hands->SetupAttachment(GetMesh()); + + + Torso = CreateDefaultSubobject(TEXT("Torso")); + Torso->SetupAttachment(GetMesh()); + + + Legs = CreateDefaultSubobject(TEXT("Legs")); + Legs->SetupAttachment(GetMesh()); + + + Feets = CreateDefaultSubobject(TEXT("Feets")); + Feets->SetupAttachment(GetMesh()); + + + Backpack = CreateDefaultSubobject(TEXT("Backpack")); + Backpack->SetupAttachment(GetMesh()); + + + LegsCloth = CreateDefaultSubobject(TEXT("LegsCloth")); + LegsCloth->SetupAttachment(GetMesh()); + + + WeaponHolsteredRight = CreateDefaultSubobject(TEXT("WeaponHolsteredRight")); + //HolsteredRightWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform); + WeaponHolsteredRight->SetupAttachment(GetMesh(), WeaponSocket::HolsteredRightWeapon); + + + WeaponHolsteredLeft = CreateDefaultSubobject(TEXT("WeaponHolsteredLeft")); + //HolsteredLeftWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale); + WeaponHolsteredLeft->SetupAttachment(GetMesh(), WeaponSocket::HolsteredLeftWeapon); + + + HolsteredBackDown = CreateDefaultSubobject(TEXT("HolsteredBackDown")); + //HolsteredBackDownWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale); + HolsteredBackDown->SetupAttachment(GetMesh()); + + + WeaponHolsteredSideLeft = CreateDefaultSubobject(TEXT("WeaponHolsteredSideLeft")); + //HolsteredSideLeftWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale); + WeaponHolsteredSideLeft->SetupAttachment(GetMesh()); + + + WeaponEquipedMain = CreateDefaultSubobject(TEXT("WeaponEquipedMain")); + //EquipedMainWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale); + WeaponEquipedMain->SetupAttachment(GetMesh(), WeaponSocket::EquipedMainWeapon); + + bUseControllerRotationYaw = true; + // Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character) + // are set in the derived blueprint asset named MyCharacter (to avoid direct content references in C++) +} +void AARCharacter::OnConstruction(const FTransform& Transform) +{ + Head->SetMasterPoseComponent(GetMesh()); + Head->UpdateMasterBoneMap(); + + Shoulders->SetMasterPoseComponent(GetMesh()); + Shoulders->UpdateMasterBoneMap(); + + Arms->SetMasterPoseComponent(GetMesh()); + Arms->UpdateMasterBoneMap(); + + Hands->SetMasterPoseComponent(GetMesh()); + Hands->UpdateMasterBoneMap(); + + Torso->SetMasterPoseComponent(GetMesh()); + Torso->UpdateMasterBoneMap(); + + Legs->SetMasterPoseComponent(GetMesh()); + Legs->UpdateMasterBoneMap(); + + Feets->SetMasterPoseComponent(GetMesh()); + Feets->UpdateMasterBoneMap(); + + Backpack->SetMasterPoseComponent(GetMesh()); + Backpack->UpdateMasterBoneMap(); +} +void AARCharacter::PostInitializeComponents() +{ + Super::PostInitializeComponents(); + +} +void AARCharacter::BeginPlay() +{ + Super::BeginPlay(); + + if (!TestAbility01.IsNull()) + { + TestAbility01Handle = FAFAbilitySpecHandle::GenerateHandle(); + FAFOnAbilityReady del1 = FAFOnAbilityReady::CreateUObject(this, &AARCharacter::OnAbility01Ready); + Abilities->AddOnAbilityReadyDelegate(TestAbility01Handle, del1); + + Abilities->NativeAddAbility(TestAbility01, TestAbility01Handle); + } + + if (!TestAbility02.IsNull()) + { + TestAbility02Handle = FAFAbilitySpecHandle::GenerateHandle(); + FAFOnAbilityReady del1 = FAFOnAbilityReady::CreateUObject(this, &AARCharacter::OnAbility02Ready); + Abilities->AddOnAbilityReadyDelegate(TestAbility02Handle, del1); + + Abilities->NativeAddAbility(TestAbility02, TestAbility02Handle); + } + + if (!TestAbility03.IsNull()) + { + TestAbility03Handle = FAFAbilitySpecHandle::GenerateHandle(); + FAFOnAbilityReady del1 = FAFOnAbilityReady::CreateUObject(this, &AARCharacter::OnAbility03Ready); + Abilities->AddOnAbilityReadyDelegate(TestAbility03Handle, del1); + + Abilities->NativeAddAbility(TestAbility03, TestAbility03Handle); + } + + if (!TestAbility04.IsNull()) + { + TestAbility04Handle = FAFAbilitySpecHandle::GenerateHandle(); + FAFOnAbilityReady del1 = FAFOnAbilityReady::CreateUObject(this, &AARCharacter::OnAbility04Ready); + Abilities->AddOnAbilityReadyDelegate(TestAbility04Handle, del1); + + Abilities->NativeAddAbility(TestAbility04, TestAbility04Handle); + } + + //LegsCloth->SetMasterPoseComponent(GetMesh()); + WeaponInventory->SetIsReplicated(true); + WeaponInventory->InitializeWeapons(this); +} + +void AARCharacter::Tick(float DeltaSeconds) +{ + Super::Tick(DeltaSeconds); +} + +void AARCharacter::OnAbility01Ready(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle) +{ + TestAbility01Handle = ServerHandle; + + TArray InputIds; + InputIds.Add(static_cast(AbilityInput::Ability01)); + Abilities->BindAbilityToInputIDs(ServerHandle, InputIds); +} +void AARCharacter::OnAbility02Ready(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle) +{ + TestAbility02Handle = ServerHandle; + + TArray InputIds; + InputIds.Add(static_cast(AbilityInput::Ability02)); + Abilities->BindAbilityToInputIDs(ServerHandle, InputIds); +} +void AARCharacter::OnAbility03Ready(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle) +{ + TestAbility03Handle = ServerHandle; + + TArray InputIds; + InputIds.Add(static_cast(AbilityInput::Ability03)); + Abilities->BindAbilityToInputIDs(ServerHandle, InputIds); +} +void AARCharacter::OnAbility04Ready(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle) +{ + TestAbility04Handle = ServerHandle; + + TArray InputIds; + InputIds.Add(static_cast(AbilityInput::Ability04)); + Abilities->BindAbilityToInputIDs(ServerHandle, InputIds); +} + +////////////////////////////////////////////////////////////////////////// +// Input + +void AARCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) +{ + // Set up gameplay key bindings + check(PlayerInputComponent); + PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump); + PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping); + + PlayerInputComponent->BindAxis("MoveForward", this, &AARCharacter::MoveForward); + PlayerInputComponent->BindAxis("MoveRight", this, &AARCharacter::MoveRight); + + // We have 2 versions of the rotation bindings to handle different kinds of devices differently + // "turn" handles devices that provide an absolute delta, such as a mouse. + // "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick + PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput); + PlayerInputComponent->BindAxis("TurnRate", this, &AARCharacter::TurnAtRate); + PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput); + PlayerInputComponent->BindAxis("LookUpRate", this, &AARCharacter::LookUpAtRate); + + Abilities->BindInputs(PlayerInputComponent, "AbilityInput"); +} + + +void AARCharacter::TurnAtRate(float Rate) +{ + // calculate delta for this frame from the rate information + AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds()); +} + +void AARCharacter::LookUpAtRate(float Rate) +{ + // calculate delta for this frame from the rate information + AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds()); +} + +void AARCharacter::MoveForward(float Value) +{ + if ((Controller != NULL) && (Value != 0.0f)) + { + // find out which way is forward + const FRotator Rotation = Controller->GetControlRotation(); + const FRotator YawRotation(0, Rotation.Yaw, 0); + + // get forward vector + const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X); + AddMovementInput(Direction, Value); + } +} + +void AARCharacter::MoveRight(float Value) +{ + if ( (Controller != NULL) && (Value != 0.0f) ) + { + // find out which way is right + const FRotator Rotation = Controller->GetControlRotation(); + const FRotator YawRotation(0, Rotation.Yaw, 0); + + // get right vector + const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y); + // add movement in that direction + AddMovementInput(Direction, Value); + } +} +/* IAFAbilityInterface- BEGIN */ + +class UAFAbilityComponent* AARCharacter::GetAbilityComp() +{ + return Abilities; +}; + +class UAFEffectsComponent* AARCharacter::GetEffectsComponent() +{ + return EffectsComponent; +} +class UAFEffectsComponent* AARCharacter::NativeGetEffectsComponent() const +{ + return EffectsComponent; +} +float AARCharacter::GetAttributeValue(FGAAttribute AttributeIn) const +{ + return Abilities->GetAttributeValue(AttributeIn); +} + +void AARCharacter::ModifyAttribute(FGAEffectMod& ModIn, const FGAEffectHandle& HandleIn, + struct FGAEffectProperty& InProperty, const FGAEffectContext& InContext) +{ + Abilities->ModifyAttribute(ModIn, HandleIn, InProperty, InContext); +} + +FAFAttributeBase* AARCharacter::GetAttribute(FGAAttribute AttributeIn) +{ + return Abilities->GetAttribute(AttributeIn); +}; + +void AARCharacter::RemoveBonus(FGAAttribute AttributeIn, const FGAEffectHandle& HandleIn, EGAAttributeMod InMod) +{ + Abilities->RemoveBonus(AttributeIn, HandleIn, InMod); +} + +float AARCharacter::NativeGetAttributeValue(const FGAAttribute AttributeIn) const +{ + return Abilities->NativeGetAttributeValue(AttributeIn); +} +/* IAFAbilityInterface- END */ + +void AARCharacter::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const +{ + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + + DOREPLIFETIME_CONDITION(AARCharacter, CameraTransform, COND_SkipOwner); +} + +void AARCharacter::OnCameraTransformUpdate(USceneComponent* UpdatedComponent, EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport) +{ + if (GetNetMode() == ENetMode::NM_Standalone + || Role == ENetRole::ROLE_Authority + || Role == ENetRole::ROLE_AutonomousProxy) + { + CameraTransform.ForwardVector = FollowCamera->GetForwardVector(); + CameraTransform.Location = FollowCamera->GetComponentLocation(); + } +} + +class AARWeaponBase* AARCharacter::GetMainWeapon() const +{ + return GetMainWeapon(); +} + +USkeletalMeshComponent* AARCharacter::GetMainWeaponMesh() const +{ + if (!GetEquipedMainWeapon()->GetChildActor()) + return nullptr; + + return GetMainWeapon()->GetMesh(); +} + +FVector AARCharacter::GetMainWeaponSocket(const FName& Socket) const +{ + USkeletalMeshComponent* Component = GetMainWeaponMesh(); + if (!Component) + return GetMesh()->GetSocketLocation(TEXT("headSocket")); + + return Component->GetSocketLocation(Socket); +} +void AARCharacter::PossessedBy(AController* NewController) +{ + Super::PossessedBy(NewController); + ClientPossesedBy(NewController); + //if (AARPlayerController* PC = Cast(Controller)) + //{ + // WeaponInventory->InitializeInventory(); + //} +} +void AARCharacter::ClientPossesedBy_Implementation(AController* NewController) +{ + +} +void AARCharacter::OnRep_Controller() +{ + Super::OnRep_Controller(); + +} +/* IIFInventoryInterface */ +void AARCharacter::OnInventoryReplicated(class UIFInventoryComponent* Inventory) +{ + +} +/* IIFInventoryInterface */ + + + +void AARCharacter::CalculateSpatialGrid() +{ + FVector Location = GetActorLocation(); + + auto resFunc = [Location]() + { + int32 MaxH = 100; + int32 MaxV = 20; + float HOffset = 0; + float VOffset = 0; + FPostResult Res; + for (int32 IdxH = 0; IdxH < MaxH; IdxH++) + { + HOffset += 30; + VOffset = 0; + for (int32 IdxV = 0; IdxV < MaxV; IdxV++) + { + VOffset += 30; + FVector Pos = Location + FVector(HOffset, VOffset, 0); + Res.Data.Add(Pos); + } + } + return Res; + }; + Result = Async(EAsyncExecution::TaskGraph, resFunc, SpatialComplete()); +} + +TFunction AARCharacter::SpatialComplete() +{ + + //DrawBox() + auto func = [&]() + { + auto func2 = [&]() + { + for (const FVector& Pos : Result.Get().Data) + { + DrawDebugPoint(GetWorld(), Pos, 20, FColor::Red, true, 10); + } + }; + AsyncTask(ENamedThreads::GameThread, func2); + }; + return func; +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/ARCharacterMovementComponent.cpp b/Source/ActionRPGGame/Private/ARCharacterMovementComponent.cpp new file mode 100644 index 0000000..d812da6 --- /dev/null +++ b/Source/ActionRPGGame/Private/ARCharacterMovementComponent.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARCharacterMovementComponent.h" + + diff --git a/Source/ActionRPGGame/Private/AREnemySpawner.cpp b/Source/ActionRPGGame/Private/AREnemySpawner.cpp new file mode 100644 index 0000000..bbd5aa0 --- /dev/null +++ b/Source/ActionRPGGame/Private/AREnemySpawner.cpp @@ -0,0 +1,83 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "AREnemySpawner.h" +#include "Engine/World.h" +#include "AI/ARAICharacter.h" + + +// Sets default values +AAREnemySpawner::AAREnemySpawner() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + MaxSpawned = 7; + BatchSpawn = 1; + TimeBetweenSpawns = 0.3; + MinRespawn = 4; +} + +// Called when the game starts or when spawned +void AAREnemySpawner::BeginPlay() +{ + Super::BeginPlay(); + SetupSpawner(); +} + +void AAREnemySpawner::SetupSpawner() +{ + if (Role == ROLE_Authority) + { + FTimerDelegate Delegate = FTimerDelegate::CreateUObject(this, &AAREnemySpawner::HandleSpawn); + + FTimerManager& Timer = GetWorld()->GetTimerManager(); + Timer.SetTimer(SpawnerHandle, Delegate, TimeBetweenSpawns, true); + } +} + +// Called every frame +void AAREnemySpawner::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void AAREnemySpawner::OnEnemyKilled(AARAICharacter* InEnemy) +{ + if (SpawnedEnemies.Num() > 0) + { + SpawnedEnemies.Remove(InEnemy); + } + if (SpawnedEnemies.Num() < MinRespawn) + { + SetupSpawner(); + } +} + +void AAREnemySpawner::HandleSpawn() +{ + if (SpawnPositions.Num() < MaxSpawned) + { + return; + } + if (SpawnedEnemies.Num() >= MaxSpawned) + { + FTimerManager& Timer = GetWorld()->GetTimerManager(); + Timer.ClearTimer(SpawnerHandle); + return; + } + + + FActorSpawnParameters SpawnParams; + SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + + for (int32 Idx = 0; Idx < BatchSpawn; Idx++) + { + FTransform Transform; + const FVector SpawnPos = SpawnPositions[SpawnedEnemies.Num()] + GetActorLocation(); + Transform.SetLocation(SpawnPos); + Transform.SetScale3D(FVector(1)); + + AARAICharacter* Enemy = GetWorld()->SpawnActor(EnemyClass, Transform, SpawnParams); + Enemy->OnSpawned(this); + SpawnedEnemies.Add(Enemy); + } +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/ARGameInstance.cpp b/Source/ActionRPGGame/Private/ARGameInstance.cpp new file mode 100644 index 0000000..b91fe34 --- /dev/null +++ b/Source/ActionRPGGame/Private/ARGameInstance.cpp @@ -0,0 +1,102 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARGameInstance.h" +#include "Engine/World.h" +#include "Engine/Engine.h" +#include "Kismet/GameplayStatics.h" +#include "Json.h" + +#include "Modules/ModuleManager.h" +#include "AssetRegistryModule.h" +#include "Engine/AssetManager.h" +#include "Abilities/GAAbilityBase.h" +#include "Effects/AFCueActor.h" + +#if WITH_AGONES +#include "IAgones.h" +#endif + +UARGameInstance::UARGameInstance(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + + +void UARGameInstance::OnGameSparksAvailable(bool bAvailable) +{ + + OnConnectedToGameSparks.Broadcast(); +} + +void UARGameInstance::AttemptLogin(const FString& UserName, const FString& Password) +{ + + +} + +void UARGameInstance::RegisterNewPlayer(const FString& UserName, const FString& DisplayName, const FString& Password) +{ + +} + +void UARGameInstance::Init() +{ + Super::Init(); + + FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked("AssetRegistry"); + IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); + //AssetRegistryModule.Get().OnFilesLoaded().AddUObject(this, &UARUIAbilityManagerComponent::FinishedLoadinFiles); + TArray< FString > ContentPaths; + TArray RootPaths; + FPackageName::QueryRootContentPaths(ContentPaths); + AssetRegistry.ScanPathsSynchronous(ContentPaths); + + if (UAssetManager* Manager = UAssetManager::GetIfValid()) + { + Manager->ScanPathsForPrimaryAssets(FPrimaryAssetType("Ability"), ContentPaths, UGAAbilityBase::StaticClass(), true); + Manager->ScanPathsForPrimaryAssets(FPrimaryAssetType("EffectCue"), ContentPaths, AAFCueActor::StaticClass(), true); + } + +#if WITH_AGONES + if (IAgones::Get().AgonesSDK->Connect()) + { + grpc::Status statuc = IAgones::Get().AgonesSDK->Ready(); + FTimerDelegate HealthCheckDel = FTimerDelegate::CreateUObject(this, &UARGameInstance::HealthCheck); + TimerManager->SetTimer(HealthCheckHandle, HealthCheckDel, 1, true, 1); + } +#endif +} +#if WITH_EDITOR + +/* Called to actually start the game when doing Play/Simulate In Editor */ +FGameInstancePIEResult UARGameInstance::StartPlayInEditorGameInstance(ULocalPlayer* LocalPlayer, const FGameInstancePIEParameters& Params) +{ + return Super::StartPlayInEditorGameInstance(LocalPlayer, Params); +} + +#endif + +void UARGameInstance::ConnectToHub() +{ + +} + + +void UARGameInstance::ConnectToWorld() +{ + +} + + +void UARGameInstance::TestGSRequest() +{ +} + + +void UARGameInstance::HealthCheck() +{ +#if WITH_AGONES + IAgones::Get().AgonesSDK->Health(); +#endif +} diff --git a/Source/ActionRPGGame/Private/ARGameMode.cpp b/Source/ActionRPGGame/Private/ARGameMode.cpp new file mode 100644 index 0000000..eaac6da --- /dev/null +++ b/Source/ActionRPGGame/Private/ARGameMode.cpp @@ -0,0 +1,51 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "ARGameMode.h" +#include "UObject/ConstructorHelpers.h" +#include "Modules/ModuleManager.h" +#include "AssetRegistryModule.h" +#include "Engine/AssetManager.h" +#include "Abilities/ARAbilityBase.h" +#include "ARGameInstance.h" +#include "ARPlayerController.h" + + + +AARGameMode::AARGameMode() +{ + +} +void AARGameMode::BeginPlay() +{ + Super::BeginPlay(); + +} + +FString AARGameMode::InitNewPlayer(APlayerController* NewPlayerController + , const FUniqueNetIdRepl& UniqueId + , const FString& Options + , const FString& Portal) +{ + FString ReturnString = Super::InitNewPlayer(NewPlayerController, UniqueId, Options, Portal); + + TArray OutParams; + Options.ParseIntoArray(OutParams, TEXT("?")); + + TArray OutPlayerId; + FString Left; + FString PlayerId; + for (FString& str : OutParams) + { + if (str.Split("PlayerId=", &Left, &PlayerId)) + { + break; + } + } + + if (AARPlayerController* PC = Cast(NewPlayerController)) + { + PC->GameLiftId = PlayerId; + } + + return ReturnString; +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/ARGameSession.cpp b/Source/ActionRPGGame/Private/ARGameSession.cpp new file mode 100644 index 0000000..bacda6e --- /dev/null +++ b/Source/ActionRPGGame/Private/ARGameSession.cpp @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARGameSession.h" +#include "ARGameInstance.h" +#include "ARGameMode.h" +#include "ARPlayerController.h" + + + +FString AARGameSession::ApproveLogin(const FString& Options) +{ + FString Output = Super::ApproveLogin(Options); + + TArray OutParams; + Options.ParseIntoArray(OutParams, TEXT("?")); + + TArray OutPlayerId; + FString Left; + FString PlayerId; + for (FString& str : OutParams) + { + if (str.Split("PlayerId=", &Left, &PlayerId)) + { + break; + } + } + + return Output; +} + +void AARGameSession::UnregisterPlayer(const APlayerController* ExitingPlayer) +{ + Super::UnregisterPlayer(ExitingPlayer); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/ARGameStateBase.cpp b/Source/ActionRPGGame/Private/ARGameStateBase.cpp new file mode 100644 index 0000000..1949c9e --- /dev/null +++ b/Source/ActionRPGGame/Private/ARGameStateBase.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARGameStateBase.h" + + + + diff --git a/Source/ActionRPGGame/Private/ARGlobals.cpp b/Source/ActionRPGGame/Private/ARGlobals.cpp new file mode 100644 index 0000000..ee0d8ed --- /dev/null +++ b/Source/ActionRPGGame/Private/ARGlobals.cpp @@ -0,0 +1,11 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARGlobals.h" + +FARGlobals::FARGlobals() +{ +} + +FARGlobals::~FARGlobals() +{ +} diff --git a/Source/ActionRPGGame/Private/ARItemBase.cpp b/Source/ActionRPGGame/Private/ARItemBase.cpp new file mode 100644 index 0000000..122d41c --- /dev/null +++ b/Source/ActionRPGGame/Private/ARItemBase.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARItemBase.h" + + + + diff --git a/Source/ActionRPGGame/Private/ARItemPickupBase.cpp b/Source/ActionRPGGame/Private/ARItemPickupBase.cpp new file mode 100644 index 0000000..d6185c1 --- /dev/null +++ b/Source/ActionRPGGame/Private/ARItemPickupBase.cpp @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARItemPickupBase.h" +#include "ARItemSpawnerBase.h" + +// Sets default values +AARItemPickupBase::AARItemPickupBase() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + bReplicates = true; + +} + +// Called when the game starts or when spawned +void AARItemPickupBase::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void AARItemPickupBase::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + +void AARItemPickupBase::OnItemPicked() +{ + SpawnedBy->OnItemPicked(); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/ARItemSpawnerBase.cpp b/Source/ActionRPGGame/Private/ARItemSpawnerBase.cpp new file mode 100644 index 0000000..23b6552 --- /dev/null +++ b/Source/ActionRPGGame/Private/ARItemSpawnerBase.cpp @@ -0,0 +1,56 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARItemSpawnerBase.h" +#include "TimerManager.h" +#include "Engine/World.h" +#include "ARItemPickupBase.h" + + +// Sets default values +AARItemSpawnerBase::AARItemSpawnerBase() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + +} + +// Called when the game starts or when spawned +void AARItemSpawnerBase::BeginPlay() +{ + Super::BeginPlay(); + if (Role == ENetRole::ROLE_Authority) + { + FActorSpawnParameters SpawnParams; + const FVector Location = GetActorLocation(); + + AARItemPickupBase* SpawnedItem = GetWorld()->SpawnActor(ItemsToSpawn, Location, GetActorRotation(), SpawnParams); + SpawnedItem->SetSpawnedBy(this); + } +} + +// Called every frame +void AARItemSpawnerBase::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + +void AARItemSpawnerBase::OnItemPicked() +{ + if (RespawnTime <= KINDA_SMALL_NUMBER) + return; + + FTimerManager& Timer = GetWorld()->GetTimerManager(); + + FTimerDelegate Delegate = FTimerDelegate::CreateUObject(this, &AARItemSpawnerBase::HandleRespawn); + Timer.SetTimer(RespawnHandle, Delegate, RespawnTime, false, RespawnTime); + +} +void AARItemSpawnerBase::HandleRespawn() +{ + FActorSpawnParameters SpawnParams; + const FVector Location = GetActorLocation(); + + AARItemPickupBase* SpawnedItem = GetWorld()->SpawnActor(ItemsToSpawn, Location, GetActorRotation(), SpawnParams); + SpawnedItem->SetSpawnedBy(this); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/ARMenuPlayerController.cpp b/Source/ActionRPGGame/Private/ARMenuPlayerController.cpp new file mode 100644 index 0000000..6560a5d --- /dev/null +++ b/Source/ActionRPGGame/Private/ARMenuPlayerController.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARMenuPlayerController.h" + + + + diff --git a/Source/ActionRPGGame/Private/ARPlayerController.cpp b/Source/ActionRPGGame/Private/ARPlayerController.cpp new file mode 100644 index 0000000..6466968 --- /dev/null +++ b/Source/ActionRPGGame/Private/ARPlayerController.cpp @@ -0,0 +1,192 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARPlayerController.h" +#include "ARUIComponent.h" +#include "AFAbilityComponent.h" +#include "AssetRegistryModule.h" +#include "Engine/AssetManager.h" +#include "ARAbilityBase.h" +#include "ARCharacter.h" +#include "Engine/GameViewportClient.h" +#include "Engine/LocalPlayer.h" +#include "Components/CapsuleComponent.h" + + +#include "UI/ARHUD.h" + +AARPlayerController::AARPlayerController(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + UIComponent = ObjectInitializer.CreateDefaultSubobject(this, "UIComponent"); + MainInventory = ObjectInitializer.CreateDefaultSubobject(this, "MainInventory"); + MainInventory->SetIsReplicated(true); + + bInputBount = false; +} +void AARPlayerController::BeginPlay() +{ + Super::BeginPlay(); + ENetMode NetMode = GetNetMode(); + MainInventory->SetIsReplicated(true); + if (NetMode == ENetMode::NM_Client + || NetMode == ENetMode::NM_Standalone) + { + IAFAbilityInterface* ABInt = Cast(GetPawn()); + if (!ABInt) + return; + + UAFAbilityComponent* AbilityComp = ABInt->GetAbilityComp(); + if (!AbilityComp) + return; + + if (!bInputBount) + { + AARCharacter* Character = Cast(GetPawn()); + + bInputBount = true; + } + //doesn't matter. Internally ability component make sure abilities are instanced on server and replicated back. + if (!AbilitytNextWeapon.IsNull()) + { + InputNextWeaponSpecHandle = FAFAbilitySpecHandle::GenerateHandle(); + FAFOnAbilityReady del1 = FAFOnAbilityReady::CreateUObject(this, &AARPlayerController::OnInputAbilityReady); + AbilityComp->AddOnAbilityReadyDelegate(InputNextWeaponSpecHandle, del1); + + AbilityComp->NativeAddAbility(AbilitytNextWeapon, InputNextWeaponSpecHandle); + } + /*if (!AbilitytPreviousWeapon.IsNull()) + { + FAFOnAbilityReady del2 = FAFOnAbilityReady::CreateUObject(this, &AARPlayerController::OnInputAbilityReady, AbilitytPreviousWeapon, InputPreviousWeapon); + AbilityComp->AddOnAbilityReadyDelegate(AbilitytPreviousWeapon, del2); + TArray PrevWeap; + PrevWeap.Add(InputPreviousWeapon); + AbilityComp->NativeAddAbility(AbilitytPreviousWeapon); + } + if (!AbilitytHolstersWeapon.IsNull()) + { + FAFOnAbilityReady del3 = FAFOnAbilityReady::CreateUObject(this, &AARPlayerController::OnInputAbilityReady, AbilitytHolstersWeapon, InputHolsterWeapon); + AbilityComp->AddOnAbilityReadyDelegate(AbilitytHolstersWeapon, del3); + TArray HolsterInput; + HolsterInput.Add(InputHolsterWeapon); + AbilityComp->NativeAddAbility(AbilitytHolstersWeapon); + } + + if (!SetAbilityGroup01.IsNull()) + { + FAFOnAbilityReady del3 = FAFOnAbilityReady::CreateUObject(this, &AARPlayerController::OnInputAbilityReady, SetAbilityGroup01, InputSetAbilityGroup01); + AbilityComp->AddOnAbilityReadyDelegate(SetAbilityGroup01, del3); + TArray HolsterInput; + HolsterInput.Add(InputSetAbilityGroup01); + AbilityComp->NativeAddAbility(SetAbilityGroup01); + } + if (!SetAbilityGroup02.IsNull()) + { + FAFOnAbilityReady del3 = FAFOnAbilityReady::CreateUObject(this, &AARPlayerController::OnInputAbilityReady, SetAbilityGroup02, InputSetAbilityGroup02); + AbilityComp->AddOnAbilityReadyDelegate(SetAbilityGroup02, del3); + TArray HolsterInput; + HolsterInput.Add(InputSetAbilityGroup02); + AbilityComp->NativeAddAbility(SetAbilityGroup02); + }*/ + + } +} +void AARPlayerController::SetPawn(APawn* InPawn) +{ + Super::SetPawn(InPawn); + + + //UIAbilityManagerComponent->BindInputs(); +} +void AARPlayerController::Possess(APawn* aPawn) +{ + Super::Possess(aPawn); + ENetMode NetMode = GetNetMode(); + + + if (NetMode == ENetMode::NM_DedicatedServer + || NetMode == ENetMode::NM_ListenServer) + { + ClientPossesed(aPawn); + } +} + +void AARPlayerController::ClientPossesed_Implementation(APawn* InPawn) +{ + +} + +void AARPlayerController::SetupInputComponent() +{ + Super::SetupInputComponent(); + InputComponent->BindAction("SwitchAbilitySet", IE_Pressed, this, &AARPlayerController::InputSwitchAbilitySet); + InputComponent->BindAction("InputAbilityManager", IE_Pressed, this, &AARPlayerController::InputShowHideAbilityManager); + InputComponent->BindAction("InputInventory", IE_Pressed, this, &AARPlayerController::InputShowHideInventory); +} + +void AARPlayerController::InputSwitchAbilitySet() +{ +} +void AARPlayerController::InputShowHideAbilityManager() +{ +} +void AARPlayerController::InputShowHideInventory() +{ + if (AARHUD* MyHUD = Cast(GetHUD())) + { + MyHUD->ShowHideInventory(); + } +} +void AARPlayerController::OnInputAbilityReady(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle) +{ + IAFAbilityInterface* ABInt = Cast(GetPawn()); + if (!ABInt) + return; + + UAFAbilityComponent* AbilityComp = ABInt->GetAbilityComp(); + if (!AbilityComp) + return; + + InputNextWeaponSpecHandle = ServerHandle; + + TArray InputIds; + InputIds.Add(static_cast(AbilityInput::NextWeapon)); + AbilityComp->BindAbilityToInputIDs(ServerHandle, InputIds); +} + + +/* IIFInventoryInterface */ +void AARPlayerController::OnInventoryReplicated(class UIFInventoryComponent* Inventory) +{ + if (Inventory == MainInventory) + { + UIComponent->InitializeInventory(); + } +} +/* IIFInventoryInterface */ + +float AARPlayerController::ComputeBoundsScreenSize(UCapsuleComponent* InTarget) +{ + ULocalPlayer const* const LP = GetLocalPlayer(); + FVector4 ViewOrigin; + FMatrix ProjMatrix; + if (LP && LP->ViewportClient) + { + // get the projection data + FSceneViewProjectionData ProjectionData; + if (LP->GetProjectionData(LP->ViewportClient->Viewport, eSSP_FULL, /*out*/ ProjectionData)) + { + ViewOrigin = ProjectionData.ViewOrigin; + ProjMatrix = ProjectionData.ProjectionMatrix; + } + } + const float Dist = FVector::Dist(InTarget->Bounds.Origin, ViewOrigin); + + // Get projection multiple accounting for view scaling. + const float ScreenMultiple = FMath::Max(0.5f * ProjMatrix.M[0][0], 0.5f * ProjMatrix.M[1][1]); + + // Calculate screen-space projected radius + const float ScreenRadius = ScreenMultiple * InTarget->Bounds.SphereRadius / FMath::Max(1.0f, Dist); + + // For clarity, we end up comparing the diameter + return ScreenRadius * 2.0f; +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/ARPlayerStateBase.cpp b/Source/ActionRPGGame/Private/ARPlayerStateBase.cpp new file mode 100644 index 0000000..485b8e3 --- /dev/null +++ b/Source/ActionRPGGame/Private/ARPlayerStateBase.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARPlayerStateBase.h" + + + + diff --git a/Source/ActionRPGGame/Private/Abilities/ARAbilityBase.cpp b/Source/ActionRPGGame/Private/Abilities/ARAbilityBase.cpp new file mode 100644 index 0000000..bfa82c3 --- /dev/null +++ b/Source/ActionRPGGame/Private/Abilities/ARAbilityBase.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARAbilityBase.h" + + + + diff --git a/Source/ActionRPGGame/Private/Abilities/ARAbilityUIData.cpp b/Source/ActionRPGGame/Private/Abilities/ARAbilityUIData.cpp new file mode 100644 index 0000000..48f46d8 --- /dev/null +++ b/Source/ActionRPGGame/Private/Abilities/ARAbilityUIData.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARAbilityUIData.h" + + + + diff --git a/Source/ActionRPGGame/Private/Abilities/ARAvailableAbilities.cpp b/Source/ActionRPGGame/Private/Abilities/ARAvailableAbilities.cpp new file mode 100644 index 0000000..2b9557c --- /dev/null +++ b/Source/ActionRPGGame/Private/Abilities/ARAvailableAbilities.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARAvailableAbilities.h" + + + + diff --git a/Source/ActionRPGGame/Private/ActionRPGGame.cpp b/Source/ActionRPGGame/Private/ActionRPGGame.cpp new file mode 100644 index 0000000..7c59797 --- /dev/null +++ b/Source/ActionRPGGame/Private/ActionRPGGame.cpp @@ -0,0 +1,29 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "ActionRPGGame.h" +#include "Modules/ModuleManager.h" + +#if ENABLE_GRPC +#include "IGRPC.h" +#include "grpc++/grpc++.h" +#endif + +#if WITH_EDITOR +#include "IAbilityFrameworkEditor.h" +#endif +void FActionRPGGameModule::StartupModule() +{ +#if ENABLE_GRPC + FModuleManager::Get().LoadModule(TEXT("GRPC")); + grpc::string out = grpc::Version(); + FString ver = FString(ANSI_TO_TCHAR(out.c_str())); + UE_LOG(LogTemp, Warning, TEXT("ActionRPGGame GRPC Version: %s "), *ver); +#endif + +#if WITH_EDITOR + FModuleManager::Get().LoadModule(TEXT("AbilityFrameworkEditor")); + //FModuleManager::LoadModuleChecked(TEXT("AbilityFrameworkEditor")); +#endif //WITH_EDITOR +}; +IMPLEMENT_PRIMARY_GAME_MODULE(FActionRPGGameModule, ActionRPGGame, "ActionRPGGame"); + \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/Attributes/ARAbilityAttributes.cpp b/Source/ActionRPGGame/Private/Attributes/ARAbilityAttributes.cpp new file mode 100644 index 0000000..41a0521 --- /dev/null +++ b/Source/ActionRPGGame/Private/Attributes/ARAbilityAttributes.cpp @@ -0,0 +1,10 @@ +#include "ARAbilityAttributes.h" + + +void UARAbilityAttributes::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const +{ + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME_CONDITION(UARAbilityAttributes, CastTime, COND_OwnerOnly); + DOREPLIFETIME_CONDITION(UARAbilityAttributes, Cooldown, COND_OwnerOnly); + DOREPLIFETIME_CONDITION(UARAbilityAttributes, BaseDamage, COND_OwnerOnly); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/Attributes/ARCharacterAttributes.cpp b/Source/ActionRPGGame/Private/Attributes/ARCharacterAttributes.cpp new file mode 100644 index 0000000..4bd7ad0 --- /dev/null +++ b/Source/ActionRPGGame/Private/Attributes/ARCharacterAttributes.cpp @@ -0,0 +1,29 @@ +#include "ARCharacterAttributes.h" +#include "Net/UnrealNetwork.h" + + +UARCharacterAttributes::UARCharacterAttributes(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} + +void UARCharacterAttributes::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const +{ + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(UARCharacterAttributes, Health); + DOREPLIFETIME(UARCharacterAttributes, Shield); + DOREPLIFETIME(UARCharacterAttributes, Armor); + DOREPLIFETIME(UARCharacterAttributes, Energy); + DOREPLIFETIME(UARCharacterAttributes, Stamina); + DOREPLIFETIME(UARCharacterAttributes, Ammo); + DOREPLIFETIME(UARCharacterAttributes, MachineGunAmmo); +} + +void UARCharacterAttributes::OnRep_Health() +{ + if (Health.CurrentValue) + { + + } +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/Attributes/ARGunAttributes.cpp b/Source/ActionRPGGame/Private/Attributes/ARGunAttributes.cpp new file mode 100644 index 0000000..dacfd5f --- /dev/null +++ b/Source/ActionRPGGame/Private/Attributes/ARGunAttributes.cpp @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARGunAttributes.h" +#include "Net/UnrealNetwork.h" +#include "AFAbilityComponent.h" + +void UARGunAttributes::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const +{ + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(UARGunAttributes, Magazine); +} + +void UARGunAttributes::OnRep_Magazine(FAFAttributeBase OldVal) +{ + float dua = 0; + UARGunAttributes* asd = this; +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/Attributes/ARHealthExtension.cpp b/Source/ActionRPGGame/Private/Attributes/ARHealthExtension.cpp new file mode 100644 index 0000000..1986eaf --- /dev/null +++ b/Source/ActionRPGGame/Private/Attributes/ARHealthExtension.cpp @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARHealthExtension.h" +#include "AFAbilityComponent.h" +#include "AI/ARAICharacter.h" + + +void UARHealthExtension::PreAttributeModify(const FGAEffectContext& InContext, float PreValue) +{ + +} +void UARHealthExtension::PostAttributeModify(const FGAEffectContext& InContext, float PreValue, float PostValue) +{ + AARAICharacter* AIChar = Cast(InContext.Target.Get()); + if (!AIChar) + return; + + if (PostValue <= 0) + { + AIChar->Kill(); + } +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/Calculations/ARAmmoReloadCalculation.cpp b/Source/ActionRPGGame/Private/Calculations/ARAmmoReloadCalculation.cpp new file mode 100644 index 0000000..9012ef7 --- /dev/null +++ b/Source/ActionRPGGame/Private/Calculations/ARAmmoReloadCalculation.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARAmmoReloadCalculation.h" + + + + diff --git a/Source/ActionRPGGame/Private/Equipment/ARCharacterEquipmentComponent.cpp b/Source/ActionRPGGame/Private/Equipment/ARCharacterEquipmentComponent.cpp new file mode 100644 index 0000000..d90b2ab --- /dev/null +++ b/Source/ActionRPGGame/Private/Equipment/ARCharacterEquipmentComponent.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARCharacterEquipmentComponent.h" + + + + diff --git a/Source/ActionRPGGame/Private/Menu/ARMainMenuView.cpp b/Source/ActionRPGGame/Private/Menu/ARMainMenuView.cpp new file mode 100644 index 0000000..f79713a --- /dev/null +++ b/Source/ActionRPGGame/Private/Menu/ARMainMenuView.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARMainMenuView.h" + + + + diff --git a/Source/ActionRPGGame/Private/Menu/ARMenuGameMode.cpp b/Source/ActionRPGGame/Private/Menu/ARMenuGameMode.cpp new file mode 100644 index 0000000..3b45f8a --- /dev/null +++ b/Source/ActionRPGGame/Private/Menu/ARMenuGameMode.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARMenuGameMode.h" + + + + diff --git a/Source/ActionRPGGame/Private/Menu/ARMenuHUD.cpp b/Source/ActionRPGGame/Private/Menu/ARMenuHUD.cpp new file mode 100644 index 0000000..756cc8a --- /dev/null +++ b/Source/ActionRPGGame/Private/Menu/ARMenuHUD.cpp @@ -0,0 +1,79 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARMenuHUD.h" + +#include "UI/Menu/ARLoginScreenView.h" +#include "ARGameInstance.h" +#include "ARMainMenuView.h" +#include "ARRegisterView.h" + + +void AARMenuHUD::BeginPlay() +{ + Super::BeginPlay(); + + if (APlayerController* PC = GetOwningPlayerController()) + { + if (LoginScreenClass) + { + LoginScreen = CreateWidget(PC, LoginScreenClass); + LoginScreen->AddToViewport(); + } + + if (MainMenuScreenClass) + { + MainMenuScreen = CreateWidget(PC, MainMenuScreenClass); + MainMenuScreen->AddToViewport(); + + MainMenuScreen->SetVisibility(ESlateVisibility::Collapsed); + } + + if (RegisterViewClass) + { + RegisterView = CreateWidget(PC, RegisterViewClass); + RegisterView->AddToViewport(); + + RegisterView->SetVisibility(ESlateVisibility::Collapsed); + } + + if (UARGameInstance* GI = Cast(PC->GetGameInstance())) + { + GI->OnLoginSuccess.AddDynamic(this, &AARMenuHUD::OnLoginSuccess); + } + } +} + +void AARMenuHUD::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + Super::EndPlay(EndPlayReason); + + if (LoginScreen) + { + LoginScreen->RemoveFromParent(); + LoginScreen->RemoveFromViewport(); + LoginScreen->SetVisibility(ESlateVisibility::Collapsed); + LoginScreen->MarkPendingKill(); + } + + if (MainMenuScreen) + { + MainMenuScreen->RemoveFromParent(); + MainMenuScreen->RemoveFromViewport(); + MainMenuScreen->SetVisibility(ESlateVisibility::Collapsed); + MainMenuScreen->MarkPendingKill(); + } +} + +void AARMenuHUD::OnLoginSuccess() +{ + if (APlayerController* PC = GetOwningPlayerController()) + { + if (UARGameInstance* GI = Cast(PC->GetGameInstance())) + { + GI->OnLoginSuccess.RemoveDynamic(this, &AARMenuHUD::OnLoginSuccess); + + LoginScreen->SetVisibility(ESlateVisibility::Collapsed); + MainMenuScreen->SetVisibility(ESlateVisibility::Visible); + } + } +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/Menu/ARRegisterView.cpp b/Source/ActionRPGGame/Private/Menu/ARRegisterView.cpp new file mode 100644 index 0000000..6484bc4 --- /dev/null +++ b/Source/ActionRPGGame/Private/Menu/ARRegisterView.cpp @@ -0,0 +1,53 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARRegisterView.h" +#include "ARGameInstance.h" + + + +void UARRegisterView::NativeConstruct() +{ + Super::NativeConstruct(); + + RegisterButton->OnClicked.AddDynamic(this, &UARRegisterView::OnRegisterClicked); +} + + +void UARRegisterView::OnRegisterClicked() +{ + FString UserName = UserNameBox->GetText().ToString(); + FString DisplayName = DisplayNameBox->GetText().ToString(); + FString Password = PasswordBox->GetText().ToString(); + + if (UserName.Len() <= 0) + { + WarrningText->SetText(FText::FromString("Invalid Username")); + return; + } + if (DisplayName.Len() <= 0) + { + WarrningText->SetText(FText::FromString("Invalid DisplayName")); + return; + } + if (Password.Len() <= 0) + { + WarrningText->SetText(FText::FromString("Invalid Password")); + return; + } + + if (UARGameInstance* GI = Cast(GetOwningPlayer()->GetGameInstance())) + { + RegisterButton->SetVisibility(ESlateVisibility::HitTestInvisible); + GI->RegisterNewPlayer(UserName, DisplayName, Password); + } +} + +void UARRegisterView::OnRegisterSuccess() +{ + +} + +void UARRegisterView::OnRegisterFailed() +{ + +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/ARHUD.cpp b/Source/ActionRPGGame/Private/UI/ARHUD.cpp new file mode 100644 index 0000000..da28782 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/ARHUD.cpp @@ -0,0 +1,182 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARHUD.h" +#include "Engine/GameViewportClient.h" +#include "Engine/LocalPlayer.h" +#include "Camera/CameraComponent.h" +#include "Kismet/GameplayStatics.h" +#include "ARCharacter.h" +#include "Attributes/ARCharacterAttributes.h" +#include "UI/Inventory/ARUIInventoryComponent.h" + +#include "AFAbilityInterface.h" +#include "AFAbilityComponent.h" +#include "UI/HUD/ARHUDEnemyHealthBar.h" +#include "UI/HUD/ARHUDFloatingCombatText.h" + +#include "ARPlayerController.h" + +AARHUD::AARHUD(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + UIInventoryComponent = ObjectInitializer.CreateDefaultSubobject(this, TEXT("UIInventoryComponent")); + DistanceScaleEnemyBar = 1000.0f; + HUDFloatingCombatTextClass = UARHUDFloatingCombatText::StaticClass(); + +} + +void AARHUD::BeginPlay() +{ + Super::BeginPlay(); + if (AARPlayerController* PC = Cast(PlayerOwner)) + { + UIInventoryComponent->CreateInventoryView(PC); + + ARPC = PC; + ARCharacter = Cast(GetOwningPawn()); + if (HUDEnemyHealthBarClass) + { + HUDEnemyHealthBar = CreateWidget(PC, HUDEnemyHealthBarClass); + HUDEnemyHealthBar->AddToViewport(); + HUDEnemyHealthBar->SetVisibility(ESlateVisibility::Collapsed); + } + + if (HUDFloatingCombatTextClass) + { + FloatingCombatText = CreateWidget(PC, HUDFloatingCombatTextClass); + FloatingCombatText->AddToViewport(); + FloatingCombatText->SetVisibility(ESlateVisibility::HitTestInvisible); + FloatingCombatText->PC = ARPC; + FloatingCombatText->FCTMoveSpeed = FCTMoveSpeed; + FloatingCombatText->FCTLifeTime = FCTLifeTime; + FloatingCombatText->Font = FCTFont; + FloatingCombatText->Init(100); + } + + if (ARCharacter) + { + UAFAbilityComponent* ABComp = ARCharacter->GetAbilityComp(); + ABComp->OnTargetAttributeModifed.AddDynamic(this, &AARHUD::OnEnemyDamageCaused); + } + } +} + +void AARHUD::Tick(float InDeltaTime) +{ + Super::Tick(InDeltaTime); + + if (ARCharacter) + { + SetEnemyHitResult(); + UpdateEnemyBarInfo(); + FloatingCombatText->Update(InDeltaTime); + } + else + { + ARCharacter = Cast(GetOwningPawn()); + } +} + +void AARHUD::ShowHideInventory() +{ + UIInventoryComponent->ShowHideInventory(); +} +float AARHUD::ComputeBoundsScreenSize(AActor* InTarget) +{ + ULocalPlayer const* const LP = ARPC->GetLocalPlayer(); + FVector4 ViewOrigin; + FMatrix ProjMatrix; + if (LP && LP->ViewportClient) + { + // get the projection data + FSceneViewProjectionData ProjectionData; + if (LP->GetProjectionData(LP->ViewportClient->Viewport, eSSP_FULL, /*out*/ ProjectionData)) + { + ViewOrigin = ProjectionData.ViewOrigin; + ProjMatrix = ProjectionData.ProjectionMatrix; + } + } + FBox Bounds = InTarget->GetComponentsBoundingBox(); + const float Dist = FVector::Dist(InTarget->GetActorLocation(), ViewOrigin); + + // Get projection multiple accounting for view scaling. + const float ScreenMultiple = FMath::Max(0.5f * ProjMatrix.M[0][0], 0.5f * ProjMatrix.M[1][1]); + + // Calculate screen-space projected radius + const float ScreenRadius = ScreenMultiple * Bounds.GetExtent().Z / FMath::Max(1.0f, Dist); + + // For clarity, we end up comparing the diameter + return ScreenRadius * 2.0f; +} +void AARHUD::SetEnemyHitResult() +{ + FVector Start = ARCharacter->GetFollowCamera()->GetComponentLocation(); + FVector Forward = ARCharacter->GetFollowCamera()->GetForwardVector(); + FVector End = (Forward * 10000.0) + Start; + ECollisionChannel CollisionChannel = UEngineTypes::ConvertToCollisionChannel(EnemyChannel); + FCollisionQueryParams Params; + Params.AddIgnoredActor(ARCharacter); + Params.bTraceComplex = false; + Params.OwnerTag = TEXT("HUDLineTrace"); + //make async ? + GetWorld()->LineTraceSingleByChannel(EnemyHitResult, Start, End, CollisionChannel, Params); +} +void AARHUD::UpdateEnemyBarInfo() +{ + if (EnemyHitResult.GetActor()) + { + AActor* Target = EnemyHitResult.GetActor(); + HUDEnemyHealthBar->SetVisibility(ESlateVisibility::HitTestInvisible); + FVector ActorLocation = EnemyHitResult.GetActor()->GetActorLocation(); + FVector2D ScreeLoc; + + UGameplayStatics::ProjectWorldToScreen(ARPC, ActorLocation, ScreeLoc, false); + + float Distance = FVector::Dist(ActorLocation, ARCharacter->GetActorLocation()); + Distance = DistanceScaleEnemyBar / Distance; + Distance = FMath::Clamp(Distance, 0.7, 1); + + float ScreenSize = ComputeBoundsScreenSize(Target); + FVector Extent = Target->GetComponentsBoundingBox().GetExtent(); + + float OffsetY = (Extent.Z * 7) * ScreenSize; + ScreeLoc.Y = ScreeLoc.Y - OffsetY; + + HUDEnemyHealthBar->SetPositionInViewport(ScreeLoc, true); + + FVector2D NewScale(Distance, Distance); + HUDEnemyHealthBar->SetRenderScale(NewScale); + if(IAFAbilityInterface* TargetInt = Cast(Target)) + { + UARCharacterAttributes* Attributes = TargetInt->GetAttributesTyped(); + if (Attributes) + { + float Percent = Attributes->Health.GetCurrentValue() / Attributes->Health.GetFinalValue(); + HUDEnemyHealthBar->UpdateHealth(Percent); + } + } + + } + else + { + HUDEnemyHealthBar->SetVisibility(ESlateVisibility::Collapsed); + } +} + +void AARHUD::OnEnemyDamageCaused(const FAFAttributeChangedData& InMod) +{ + AActor* Target = EnemyHitResult.GetActor(); + if (Target) + { + FVector2D ScreeLoc; + + UGameplayStatics::ProjectWorldToScreen(ARPC, EnemyHitResult.Location, ScreeLoc, false); + FloatingCombatText->SetInfo(InMod.Mod.Value, ScreeLoc); + } + else + { + FVector2D ScreeLoc; + UGameplayStatics::ProjectWorldToScreen(ARPC, InMod.Location, ScreeLoc, false); + FloatingCombatText->SetInfo(InMod.Mod.Value, ScreeLoc); + } +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/ARHUDWidget.cpp b/Source/ActionRPGGame/Private/UI/ARHUDWidget.cpp new file mode 100644 index 0000000..10376e6 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/ARHUDWidget.cpp @@ -0,0 +1,3 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARHUDWidget.h" diff --git a/Source/ActionRPGGame/Private/UI/ARUIComponent.cpp b/Source/ActionRPGGame/Private/UI/ARUIComponent.cpp new file mode 100644 index 0000000..33dc503 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/ARUIComponent.cpp @@ -0,0 +1,67 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARUIComponent.h" +#include "Blueprint/UserWidget.h" + +#include "ARCharacter.h" +#include "ARPlayerController.h" + +#include "Inventory/Weapons/ARWeaponContainerWidget.h" +#include "Inventory/Weapons/ARItemWeaponWidget.h" +#include "Inventory/ARInventoryScreenWidget.h" + + + +// Sets default values for this component's properties +UARUIComponent::UARUIComponent() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = true; + bAutoRegister = true; + bWantsInitializeComponent = true; + // ... +} + +void UARUIComponent::InitializeComponent() +{ + Super::InitializeComponent(); +} +// Called when the game starts +void UARUIComponent::BeginPlay() +{ + Super::BeginPlay(); + + if (GetOwner()->GetNetMode() == ENetMode::NM_Client + || GetOwner()->GetNetMode() == ENetMode::NM_Standalone) + { + AARPlayerController* MyPC = Cast(GetOwner()); + // ... + if (CrosshairClass) + { + CrosshairWidget = CreateWidget(MyPC, CrosshairClass); + CrosshairWidget->SetVisibility(ESlateVisibility::HitTestInvisible); + CrosshairWidget->AddToViewport(); + } + + if (HUDWidgetClass) + { + HUDWidget = CreateWidget(MyPC, HUDWidgetClass); + HUDWidget->AddToViewport(); + } + } +} + + +// Called every frame +void UARUIComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // ... +} + +void UARUIComponent::InitializeInventory() +{ + +} diff --git a/Source/ActionRPGGame/Private/UI/ARUMGWidgetBase.cpp b/Source/ActionRPGGame/Private/UI/ARUMGWidgetBase.cpp new file mode 100644 index 0000000..e2cd6e7 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/ARUMGWidgetBase.cpp @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARUMGWidgetBase.h" +#include "ARPlayerController.h" + + + +void UARUMGWidgetBase::NativePreConstruct() +{ + if (AARPlayerController* MyPC = Cast(GetOwningPlayer())) + { + UIComponent = MyPC->UIComponent; + } + Super::NativePreConstruct(); +} +void UARUMGWidgetBase::NativeConstruct() +{ + if (AARPlayerController* MyPC = Cast(GetOwningPlayer())) + { + UIComponent = MyPC->UIComponent; + } + Super::NativeConstruct(); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/HUD/ARHUDCrosshair.cpp b/Source/ActionRPGGame/Private/UI/HUD/ARHUDCrosshair.cpp new file mode 100644 index 0000000..6791db9 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/HUD/ARHUDCrosshair.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARHUDCrosshair.h" +#include "ARPlayerController.h" + diff --git a/Source/ActionRPGGame/Private/UI/HUD/ARHUDCrosshairInfo.cpp b/Source/ActionRPGGame/Private/UI/HUD/ARHUDCrosshairInfo.cpp new file mode 100644 index 0000000..f955416 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/HUD/ARHUDCrosshairInfo.cpp @@ -0,0 +1,4 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARHUDCrosshairInfo.h" +#include "ARPlayerController.h" diff --git a/Source/ActionRPGGame/Private/UI/HUD/ARHUDEnemyHealthBar.cpp b/Source/ActionRPGGame/Private/UI/HUD/ARHUDEnemyHealthBar.cpp new file mode 100644 index 0000000..8651abd --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/HUD/ARHUDEnemyHealthBar.cpp @@ -0,0 +1,9 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARHUDEnemyHealthBar.h" +#include "Components/ProgressBar.h" + +void UARHUDEnemyHealthBar::UpdateHealth(float NormalizedHealth) +{ + HealthBar->SetPercent(NormalizedHealth); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/HUD/ARHUDFloatingCombatText.cpp b/Source/ActionRPGGame/Private/UI/HUD/ARHUDFloatingCombatText.cpp new file mode 100644 index 0000000..062259b --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/HUD/ARHUDFloatingCombatText.cpp @@ -0,0 +1,105 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARHUDFloatingCombatText.h" +#include "Engine/Engine.h" + +#include "SlateOptMacros.h" + +#include "Slate.h" +#include "SlateCore.h" + +#include "Engine/GameViewportClient.h" +#include "Blueprint/WidgetLayoutLibrary.h" +#include "ARPlayerController.h" + +BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION +void SFCTWidget::Construct(const FArguments& InArgs) +{ + + TAttribute fontInfo = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &SFCTWidget::GetFontInfo)); + ChildSlot + [ + SNew(STextBlock).Text(this, &SFCTWidget::GetText).Font(fontInfo) + ]; +} +END_SLATE_FUNCTION_BUILD_OPTIMIZATION + +SFCTWidget::~SFCTWidget() +{ + +} +FSlateFontInfo SFCTWidget::GetFontInfo() const +{ + return Font; +} +FText SFCTWidget::GetText() const +{ + return Text; +} + +void UARHUDFloatingCombatText::Init(int32 Num) +{ + + Canvas = SNew(SConstraintCanvas); + GEngine->GameViewport->AddViewportWidgetContent(Canvas.ToSharedRef()); + for (int32 Idx = 0; Idx < Num; Idx++) + { + FARHUDFCTUpdate Update; + Update.Widget = SNew(SFCTWidget); + Update.Widget->Font = Font; + + Update.Slot = &Canvas->AddSlot() + [ + Update.Widget.ToSharedRef() + ]; + Update.Widget->SetVisibility(EVisibility::Collapsed); + Widgets.Add(Update); + } +} + +void UARHUDFloatingCombatText::Update(float InDeltaTime) +{ + for (uint8 Idx = 0; Idx < Widgets.Num(); Idx++) + { + if (Widgets[Idx].bUsed) + { + Widgets[Idx].CurrentTime += InDeltaTime; + Widgets[Idx].CurrentPosition = Widgets[Idx].CurrentPosition + (Widgets[Idx].Direction * InDeltaTime * FCTMoveSpeed); + + float Scale = UWidgetLayoutLibrary::GetViewportScale(this); + + FMargin Pos(Widgets[Idx].CurrentPosition.X / Scale, Widgets[Idx].CurrentPosition.Y / Scale, Widgets[Idx].Widget->GetDesiredSize().X, Widgets[Idx].Widget->GetDesiredSize().Y); + Widgets[Idx].Slot->Offset(Pos); + + if (Widgets[Idx].CurrentTime > FCTLifeTime) + { + Widgets[Idx].bUsed = false; + Widgets[Idx].CurrentTime = 0; + + Widgets[Idx].Widget->SetVisibility(EVisibility::Collapsed); + + } + } + } +} + +void UARHUDFloatingCombatText::SetInfo(float InDamage, FVector2D ScreenPosition, FLinearColor TextColor) +{ + for (uint8 Idx = 0; Idx < Widgets.Num(); Idx++) + { + if (!Widgets[Idx].bUsed) + { + Widgets[Idx].bUsed = true; + Widgets[Idx].CurrentTime = 0; + Widgets[Idx].CurrentPosition = ScreenPosition; + float RandomX = FMath::FRandRange(-1, 1); + float RandomY = FMath::FRandRange(-1, 1); + Widgets[Idx].Direction = FVector2D(RandomX, RandomY); + Widgets[Idx].Widget->TextColor = FSlateColor(TextColor); + Widgets[Idx].Widget->SetText(FText::AsNumber(InDamage)); + Widgets[Idx].Widget->SetVisibility(EVisibility::HitTestInvisible); + + break; + } + } +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/HUD/ARHUDPlayerInfo.cpp b/Source/ActionRPGGame/Private/UI/HUD/ARHUDPlayerInfo.cpp new file mode 100644 index 0000000..2f9fcd5 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/HUD/ARHUDPlayerInfo.cpp @@ -0,0 +1,14 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARHUDPlayerInfo.h" + +#include "ARPlayerController.h" + +void UARHUDPlayerInfo::NativePreConstruct() +{ + Super::NativePreConstruct(); +} +void UARHUDPlayerInfo::NativeConstruct() +{ + Super::NativeConstruct(); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/Inventory/ARInventoryScreenWidget.cpp b/Source/ActionRPGGame/Private/UI/Inventory/ARInventoryScreenWidget.cpp new file mode 100644 index 0000000..b580366 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/ARInventoryScreenWidget.cpp @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARInventoryScreenWidget.h" + +#include "Components/TextBlock.h" +#include "Components/Button.h" + +#include "UI/Inventory/Weapons/ARItemWeaponWidget.h" + +#include "ARPlayerController.h" + +void UARInventoryScreenWidget::NativeConstruct() +{ + Super::NativeConstruct(); + + RightWeaponWidget->Index = 0; + LeftWeaponWidget->Index = 1; + SideWeaponWidget->Index = 2; + BottomBackWeaponWidget->Index = 3; + + ModifySelectedWeapon->OnClicked.AddDynamic(this, &UARInventoryScreenWidget::OnModifyWeaponClicked); +} + +void UARInventoryScreenWidget::SetWeaponName(const FString& Name) +{ + SelectedWeapon->SetText(FText::FromString(Name)); +} + + +void UARInventoryScreenWidget::OnModifyWeaponClicked() +{ + Inventory->ModifyWeapon(); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/Inventory/ARItemTooltipView.cpp b/Source/ActionRPGGame/Private/UI/Inventory/ARItemTooltipView.cpp new file mode 100644 index 0000000..aad45d9 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/ARItemTooltipView.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARItemTooltipView.h" + + + + diff --git a/Source/ActionRPGGame/Private/UI/Inventory/ARItemView.cpp b/Source/ActionRPGGame/Private/UI/Inventory/ARItemView.cpp new file mode 100644 index 0000000..956954b --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/ARItemView.cpp @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARItemView.h" + +#include "UI/ARHUD.h" +#include "ARPlayerController.h" + + +void UARItemView::NativeConstruct() +{ + Super::NativeConstruct(); + + if (GetOwningPlayer()) + { + if (AARHUD* HUD = Cast(GetOwningPlayer()->GetHUD())) + { + InventoryComponent = HUD->GetUIInventory(); + } + } +} diff --git a/Source/ActionRPGGame/Private/UI/Inventory/ARListItemView.cpp b/Source/ActionRPGGame/Private/UI/Inventory/ARListItemView.cpp new file mode 100644 index 0000000..a159861 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/ARListItemView.cpp @@ -0,0 +1,57 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARListItemView.h" + +#include "ARItemBase.h" +#include "UI/ARHUD.h" +#include "UI/Inventory/ARUIInventoryComponent.h" +#include "ARPlayerController.h" + + +void UARListItemView::NativeConstruct() +{ + Super::NativeConstruct(); + + if (GetOwningPlayer()) + { + if (AARHUD* HUD = Cast(GetOwningPlayer()->GetHUD())) + { + InventoryComponent = HUD->GetUIInventory(); + } + } +} + +void UARListItemView::OnSlotCreated(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item) +{ + Super::OnSlotCreated(InNetIndex, InLocalIndex, Item); + InvItem = Cast(Item); +} +void UARListItemView::OnItemChanged(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item) +{ + Super::OnItemChanged(InNetIndex, InLocalIndex, Item); +} +void UARListItemView::OnItemRemoved(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item) +{ + Super::OnItemRemoved(InNetIndex, InLocalIndex, Item); + InvItem.Reset(); +} + +void UARListItemView::NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) +{ + if (!InvItem.IsValid()) + return; + + if (!ItemTooltip) + ItemTooltip = CreateWidget(GetOwningPlayer(), InventoryComponent->WeaponItemTooltipViewClass); + + ItemTooltip->OnTooltipCreated(InvItem->GetTooltipData()); + + SetToolTip(ItemTooltip); +} +void UARListItemView::NativeOnMouseLeave(const FPointerEvent& InMouseEvent) +{ + if (!ItemTooltip) + return; + + SetToolTip(nullptr); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/Inventory/ARUIInventoryComponent.cpp b/Source/ActionRPGGame/Private/UI/Inventory/ARUIInventoryComponent.cpp new file mode 100644 index 0000000..7dabc5e --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/ARUIInventoryComponent.cpp @@ -0,0 +1,243 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARUIInventoryComponent.h" +#include "ARPlayerController.h" +#include "ARCharacter.h" + +#include "Weapons/ARItemWeapon.h" +#include "Weapons/ARMagazineUpgradeItem.h" + +#include "UI/ARHUD.h" +#include "UI/Inventory/ARItemView.h" +#include "UI/Inventory/ARInventoryScreenWidget.h" +#include "UI/Inventory/Weapons/ARListItemWeaponWidget.h" +#include "UI/Inventory/Weapons/Modifications/ARItemMagazineView.h" +#include "UI/Inventory/Weapons/Modifications/ARListItemMagazineView.h" +#include "UI/Inventory/Weapons/ARWeaponModificationView.h" + +// Sets default values for this component's properties +UARUIInventoryComponent::UARUIInventoryComponent() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = true; + + // ... +} + + +// Called when the game starts +void UARUIInventoryComponent::BeginPlay() +{ + Super::BeginPlay(); + + if (WeaponModificationViewClass) + { + if (AARHUD* HUD = Cast(GetOwner())) + { + if (AARPlayerController* PC = Cast(HUD->GetOwningPlayerController())) + { + WeaponModificationView = CreateWidget(PC, WeaponModificationViewClass); + + WeaponModificationView->SetVisibility(ESlateVisibility::Collapsed); + WeaponModificationView->AddToViewport(); + } + } + } +} + + +// Called every frame +void UARUIInventoryComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // ... +} + +void UARUIInventoryComponent::CreateInventoryView(AARPlayerController* PC) +{ + if (InventoryViewClass) + { + InventoryView = CreateWidget(PC, InventoryViewClass); + + InventoryView->SetVisibility(ESlateVisibility::Collapsed); + InventoryView->Inventory = this; + InventoryView->AddToViewport(); + } +} + +void UARUIInventoryComponent::ShowHideInventory() +{ + if (InventoryView->GetVisibility() == ESlateVisibility::Collapsed) + { + InventoryView->SetVisibility(ESlateVisibility::SelfHitTestInvisible); + } + else if (InventoryView->GetVisibility() == ESlateVisibility::SelfHitTestInvisible) + { + InventoryView->SetVisibility(ESlateVisibility::Collapsed); + } +} + +void UARUIInventoryComponent::ShowWeaponsForSlot(class UARItemView* ForSlot) +{ + SelectedWeapon = ForSlot->LocalIndex; + TArray Items; + AARPlayerController* PC = nullptr; + if (AARHUD* HUD = Cast(GetOwner())) + { + PC = Cast(HUD->PlayerOwner); + if (PC) + { + Items = PC->MainInventory->GetLocalItemIdxs(UARItemWeapon::StaticClass()); + } + if (AARCharacter* Character = Cast(PC->GetPawn())) + { + UARItemWeapon* Item = Character->WeaponInventory->GetItem(ForSlot->LocalIndex); + ModifiedWeapon = Item; + if (Item) + { + InventoryView->SetWeaponName(Item->GetName()); + } + } + } + + InventoryView->UpdateItemList(Items, ListItemWeaponClass, PC, ForSlot); +} + +void UARUIInventoryComponent::RemoveWeaponFromSlot(int8 Index) +{ + AARPlayerController* PC = nullptr; + AARCharacter* Character = nullptr; + if (AARHUD* HUD = Cast(GetOwner())) + { + PC = Cast(HUD->PlayerOwner); + + if (!PC) + return; + Character = Cast(PC->GetPawn()); + if (!Character) + return; + + PC->MainInventory->AddItemFromEquipmentAnySlot(Character->WeaponInventory, Index); + + } +} + +void UARUIInventoryComponent::AddWeaponToSlot(uint8 TargetNetIndex + , uint8 TargetLocalIndex + , uint8 SourceNetIndex + , uint8 SourceLocalIndex) +{ + AARHUD* HUD = Cast(GetOwner()); + if (!HUD) + return; + AARPlayerController* PC = Cast(HUD->PlayerOwner); + if (!PC) + return; + + AARCharacter* Character = Cast(PC->GetPawn()); + if (!Character) + return; + + Character->WeaponInventory->AddItemFromInventory(PC->MainInventory, SourceNetIndex, TargetNetIndex); +} + +void UARUIInventoryComponent::UnequipWeaponFromSlot(uint8 SourceNetIndex, uint8 SourceLocalIndex) +{ + AARHUD* HUD = Cast(GetOwner()); + if (!HUD) + return; + AARPlayerController* PC = Cast(HUD->PlayerOwner); + if (!PC) + return; + + AARCharacter* Character = Cast(PC->GetPawn()); + if (!Character) + return; + + Character->WeaponInventory->Unequip(SourceLocalIndex); + + if (ModifiedWeapon.IsValid()) + { + ModifiedWeapon.Reset(); + } +} + +void UARUIInventoryComponent::ShowUpgradesForWeapon(class UARItemMagazineView* For) +{ + TArray Items; + AARPlayerController* PC = nullptr; + if (AARHUD* HUD = Cast(GetOwner())) + { + PC = Cast(HUD->PlayerOwner); + if (PC) + { + Items = PC->MainInventory->GetLocalItemIdxs(UARMagazineUpgradeItem::StaticClass()); + } + } + + InventoryView->AddWeaponMods(Items, ListItemMagazinelass, PC, For); +} + +void UARUIInventoryComponent::ModifyWeapon() +{ + AARHUD* HUD = Cast(GetOwner()); + if (!HUD) + return; + AARPlayerController* PC = Cast(HUD->PlayerOwner); + if (!PC) + return; + + AARCharacter* Character = Cast(PC->GetPawn()); + if (!Character) + return; + + UARItemWeapon* Weapon = Character->WeaponInventory->GetItem(SelectedWeapon); + ModifiedWeapon = Weapon; + if (!Weapon) + return; + + //WeaponModificationView->StartModifyWeapon(Weapon); + + if (Weapon->MagazineModification) + { + InventoryView->MagazineUpgrade->OnItemChanged(0, 0, Weapon->MagazineModification); + } +} + +void UARUIInventoryComponent::AddMagazineUpgrade(uint8 SourceNetIndex, uint8 SourceLocalIndex) +{ + //that's prototype. We should handle entire thing on server, either directly on item weapon, or trough WeaponInventory. + AARHUD* HUD = Cast(GetOwner()); + if (!HUD) + return; + AARPlayerController* PC = Cast(HUD->PlayerOwner); + if (!PC) + return; + + AARCharacter* Character = Cast(PC->GetPawn()); + if (!Character) + return; + + UARWeaponInventoryComponent* WeaponInventory = Character->WeaponInventory; + + WeaponInventory->AddMagazineMod(SelectedWeapon, SourceLocalIndex); +} + +void UARUIInventoryComponent::RemoveMagazineUpgrade() +{ + AARHUD* HUD = Cast(GetOwner()); + if (!HUD) + return; + AARPlayerController* PC = Cast(HUD->PlayerOwner); + if (!PC) + return; + + AARCharacter* Character = Cast(PC->GetPawn()); + if (!Character) + return; + + UARWeaponInventoryComponent* WeaponInventory = Character->WeaponInventory; + WeaponInventory->RemoveMagazineMod(SelectedWeapon); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARItemWeaponWidget.cpp b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARItemWeaponWidget.cpp new file mode 100644 index 0000000..4b9e78d --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARItemWeaponWidget.cpp @@ -0,0 +1,123 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARItemWeaponWidget.h" + +#include "IFInventoryComponent.h" + +#include "ARPlayerController.h" +#include "ARCharacter.h" + +#include "Weapons/ARItemWeapon.h" +#include "Weapons/ARWeaponInventoryComponent.h" + +#include "UI/ARHUD.h" +#include "UI/Inventory/ARUIInventoryComponent.h" +#include "UI/Inventory/ARInventoryScreenWidget.h" +#include "UI/Inventory/ARItemTooltipView.h" +#include "UI/Inventory/Weapons/ARWeaponContainerWidget.h" +#include "UI/Inventory/Weapons/ARListItemWeaponWidget.h" + +void UARItemWeaponWidget::NativeConstruct() +{ + Super::NativeConstruct(); + if(GetOwningPlayer()) + { + if (AARPlayerController* PC = Cast(GetOwningPlayer())) + { + Inventory = PC->MainInventory; + if (AARCharacter* Character = Cast(PC->GetPawn())) + { + Character->WeaponInventory->GetOnItemAdded().AddUObject(this, &UARItemWeaponWidget::OnWeaponAdded2); + Character->WeaponInventory->GetOnItemUpdated().AddUObject(this, &UARItemWeaponWidget::OnWeaponUpdated2); + Character->WeaponInventory->GetOnItemRemoved().AddUObject(this, &UARItemWeaponWidget::OnWeaponRemoved2); + } + } + if (AARHUD* HUD = Cast(GetOwningPlayer()->GetHUD())) + { + InventoryComponent = HUD->GetUIInventory(); + if (AARCharacter* Character = Cast(GetOwningPlayer()->GetPawn())) + { + WeaponInventory = Character->WeaponInventory; + } + } + } +} + + +FReply UARItemWeaponWidget::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) +{ + if (InMouseEvent.GetEffectingButton() == EKeys::LeftMouseButton) + { + UObject* Out = GetOuter(); + UARInventoryScreenWidget* MainView = Cast(Out); + InventoryComponent->ShowWeaponsForSlot(this); + } + else if (InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton) + { + InventoryComponent->RemoveWeaponFromSlot(LocalIndex); + } + + + return FReply::Handled(); +} +void UARItemWeaponWidget::NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) +{ + if (!WeaponItem.IsValid()) + return; + + if(!WeaponTooltip) + WeaponTooltip = CreateWidget(GetOwningPlayer(), InventoryComponent->WeaponItemTooltipViewClass); + + WeaponTooltip->OnTooltipCreated(WeaponItem->GetTooltipData()); + + SetToolTip(WeaponTooltip); + + /*FMargin margin = GetFullScreenOffset(); + FVector2D Pos(margin.Left, margin.Top); + WeaponTooltip->AddToViewport(9999); + + WeaponTooltip->SetVisibility(ESlateVisibility::HitTestInvisible); + WeaponTooltip->SetPositionInViewport(Pos);*/ +} +void UARItemWeaponWidget::NativeOnMouseLeave(const FPointerEvent& InMouseEvent) +{ + if (!WeaponTooltip) + return; + + SetToolTip(nullptr); + //WeaponTooltip->SetVisibility(ESlateVisibility::Collapsed); +} +FReply UARItemWeaponWidget::NativeOnMouseButtonDoubleClick(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) +{ + FReply Handled = FReply::Unhandled(); + + InventoryComponent->UnequipWeaponFromSlot(NetIndex, LocalIndex); + Handled = FReply::Handled(); + + return Handled; +} + + +void UARItemWeaponWidget::OnWeaponAdded2(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* InItem) +{ + if (InLocalIndex == Index) + { + OnSlotCreated(InNetIndex, InLocalIndex, InItem); + WeaponItem = Cast(InItem); + } +} +void UARItemWeaponWidget::OnWeaponUpdated2(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* InItem) +{ + if (InLocalIndex == Index) + { + OnItemChanged(InNetIndex, InLocalIndex, InItem); + } +} +void UARItemWeaponWidget::OnWeaponRemoved2(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* InItem) +{ + if (InLocalIndex == Index) + { + OnItemRemoved(InNetIndex, InLocalIndex, InItem); + } + WeaponItem.Reset(); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARListItemWeaponWidget.cpp b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARListItemWeaponWidget.cpp new file mode 100644 index 0000000..e6d120d --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARListItemWeaponWidget.cpp @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARListItemWeaponWidget.h" +#include "UI/Inventory/ARUIInventoryComponent.h" +#include "UI/Inventory/ARItemView.h" + + +FReply UARListItemWeaponWidget::NativeOnMouseButtonDoubleClick(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) +{ + FReply Handled = FReply::Unhandled(); + if (!Target.IsValid()) + return Handled; + + InventoryComponent->AddWeaponToSlot(Target->NetIndex, Target->LocalIndex, NetIndex, LocalIndex); + Handled = FReply::Handled(); + + return Handled; +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARWeaponContainerWidget.cpp b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARWeaponContainerWidget.cpp new file mode 100644 index 0000000..26e88f5 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARWeaponContainerWidget.cpp @@ -0,0 +1,16 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARWeaponContainerWidget.h" + +#include "IFItemWidget.h" + +#include "ARPlayerController.h" +#include "ARCharacter.h" + +#include "UI/ARUIComponent.h" + + +void UARWeaponContainerWidget::InitializeWeaponItems(class UARUIComponent* UIComponent) +{ + +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARWeaponModificationView.cpp b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARWeaponModificationView.cpp new file mode 100644 index 0000000..fd6d3ab --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/ARWeaponModificationView.cpp @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARWeaponModificationView.h" +#include "Components/Button.h" +#include "Components/WrapBox.h" +#include "Weapons/ARItemWeapon.h" +#include "Weapons/ARMagazineUpgradeItem.h" + +void UARWeaponModificationView::NativeConstruct() +{ + Super::NativeConstruct(); + CloseUpgradeView->OnClicked.AddDynamic(this, &UARWeaponModificationView::CloseModificationView); +} +void UARWeaponModificationView::StartModifyWeapon(class UARItemWeapon* WeaponItem) +{ + SetVisibility(ESlateVisibility::SelfHitTestInvisible); +} +void UARWeaponModificationView::StopModifyWeapon() +{ + +} + +void UARWeaponModificationView::CloseModificationView() +{ + StopModifyWeapon(); + SetVisibility(ESlateVisibility::Collapsed); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/Inventory/Weapons/Modifications/ARItemMagazineView.cpp b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/Modifications/ARItemMagazineView.cpp new file mode 100644 index 0000000..5fd4507 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/Modifications/ARItemMagazineView.cpp @@ -0,0 +1,57 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARItemMagazineView.h" +#include "Components/Image.h" +#include "ARCharacter.h" +#include "UI/Inventory/ARUIInventoryComponent.h" +#include "Weapons/ARMagazineUpgradeItem.h" + +void UARItemMagazineView::NativeConstruct() +{ + Super::NativeConstruct(); + + if (GetOwningPlayer()) + { + if (AARCharacter* Character = Cast(GetOwningPlayer()->GetPawn())) + { + Character->WeaponInventory->GetOnUpgradeInstalled().AddDynamic(this, &UARItemMagazineView::OnMagazineUpgradeInstalled); + Character->WeaponInventory->GetOnUpgradeRemoved().AddDynamic(this, &UARItemMagazineView::OnMagazineUpgradeRemoved); + } + } +} + +FReply UARItemMagazineView::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) +{ + InventoryComponent->ShowUpgradesForWeapon(this); + return FReply::Unhandled(); +} + +FReply UARItemMagazineView::NativeOnMouseButtonDoubleClick(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) +{ + FReply Handled = FReply::Unhandled(); + + InventoryComponent->RemoveMagazineUpgrade(); + Handled = FReply::Handled(); + + return Handled; +} + +void UARItemMagazineView::OnMagazineUpgradeInstalled(class UARItemWeapon* Weapon + , class UARWeaponUpgradeItem* Upgrade + , int8 WeaponIndex) +{ + if (UARMagazineUpgradeItem* Magazine = Cast(Upgrade)) + { + Icon->SetBrushFromTexture(Upgrade->Icon); + } +} + +void UARItemMagazineView::OnMagazineUpgradeRemoved(class UARItemWeapon* Weapon + , class UARWeaponUpgradeItem* Upgrade + , int8 WeaponIndex) +{ + if (UARMagazineUpgradeItem* Magazine = Cast(Upgrade)) + { + Icon->SetBrushFromTexture(nullptr); + } +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/Inventory/Weapons/Modifications/ARItemWeaponUpgradeView.cpp b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/Modifications/ARItemWeaponUpgradeView.cpp new file mode 100644 index 0000000..1517495 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/Modifications/ARItemWeaponUpgradeView.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARItemWeaponUpgradeView.h" + + + + diff --git a/Source/ActionRPGGame/Private/UI/Inventory/Weapons/Modifications/ARListItemMagazineView.cpp b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/Modifications/ARListItemMagazineView.cpp new file mode 100644 index 0000000..2030c3b --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Inventory/Weapons/Modifications/ARListItemMagazineView.cpp @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARListItemMagazineView.h" +#include "UI/Inventory/ARUIInventoryComponent.h" +#include "UI/Inventory/ARItemView.h" + +FReply UARListItemMagazineView::NativeOnMouseButtonDoubleClick(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) +{ + FReply Handled = FReply::Unhandled(); + + + InventoryComponent->AddMagazineUpgrade(NetIndex, LocalIndex); + Handled = FReply::Handled(); + + return Handled; +} + diff --git a/Source/ActionRPGGame/Private/UI/Menu/ARLoginScreenView.cpp b/Source/ActionRPGGame/Private/UI/Menu/ARLoginScreenView.cpp new file mode 100644 index 0000000..1aa1d13 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/Menu/ARLoginScreenView.cpp @@ -0,0 +1,64 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARLoginScreenView.h" +#include "ARGameInstance.h" +#include "Menu/ARRegisterView.h" +#include "ARMenuHUD.h" + + +void UARLoginScreenView::NativeConstruct() +{ + Super::NativeConstruct(); + + LoginButton->OnClicked.AddDynamic(this, &UARLoginScreenView::OnLoginClicked); + RegisterButton->OnClicked.AddDynamic(this, &UARLoginScreenView::OnRegisterClicked); +} + +void UARLoginScreenView::OnLoginClicked() +{ + if (UserNameBox->GetText().IsEmpty()) + { + WarrningText->SetText(FText::FromString("Enter User Name")); + return; + } + if (PasswordBox->GetText().IsEmpty()) + { + WarrningText->SetText(FText::FromString("Enter User Name")); + return; + } + + if (UARGameInstance* GI = Cast(GetOwningPlayer()->GetGameInstance())) + { + GI->OnLoginSuccess.AddDynamic(this, &UARLoginScreenView::OnLoginSuccess); + GI->OnLoginFailed.AddDynamic(this, &UARLoginScreenView::OnLoginFailed); + GI->AttemptLogin(UserNameBox->GetText().ToString(), PasswordBox->GetText().ToString()); + } +} + +void UARLoginScreenView::OnLoginSuccess() +{ + if (UARGameInstance* GI = Cast(GetOwningPlayer()->GetGameInstance())) + { + WarrningText->SetText(FText::FromString("Login Success")); + GI->OnLoginSuccess.RemoveDynamic(this, &UARLoginScreenView::OnLoginSuccess); + GI->OnLoginFailed.RemoveDynamic(this, &UARLoginScreenView::OnLoginFailed); + } +} + + +void UARLoginScreenView::OnLoginFailed() +{ + +} + +void UARLoginScreenView::OnRegisterClicked() +{ + if (!GetOwningPlayer()) + return; + + AARMenuHUD* Hud = Cast(GetOwningPlayer()->GetHUD()); + if (!Hud) + return; + + Hud->GetRegisterView()->SetVisibility(ESlateVisibility::Visible); +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/UI/SARCrosshairBase.cpp b/Source/ActionRPGGame/Private/UI/SARCrosshairBase.cpp new file mode 100644 index 0000000..5618cda --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/SARCrosshairBase.cpp @@ -0,0 +1,16 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SARCrosshairBase.h" +#include "SlateOptMacros.h" + +BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION +void SARCrosshairBase::Construct(const FArguments& InArgs) +{ + /* + ChildSlot + [ + // Populate the widget + ]; + */ +} +END_SLATE_FUNCTION_BUILD_OPTIMIZATION diff --git a/Source/ActionRPGGame/Private/UI/SARDrawTestWidget.cpp b/Source/ActionRPGGame/Private/UI/SARDrawTestWidget.cpp new file mode 100644 index 0000000..3e5a1e3 --- /dev/null +++ b/Source/ActionRPGGame/Private/UI/SARDrawTestWidget.cpp @@ -0,0 +1,185 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SARDrawTestWidget.h" +#include "Rendering/DrawElements.h" +#include "SlateOptMacros.h" + +BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION +void SARDrawTestWidget::Construct(const FArguments& InArgs) +{ + + ProgressStep = 0.25f; + Progress = 0.0f; + /* + ChildSlot + [ + // Populate the widget + ]; + */ +} +END_SLATE_FUNCTION_BUILD_OPTIMIZATION +SARDrawTestWidget::SARDrawTestWidget() +{ + Brush = nullptr; +} +int32 SARDrawTestWidget::OnPaint(const FPaintArgs& Args + , const FGeometry& AllottedGeometry + , const FSlateRect& MyCullingRect + , FSlateWindowElementList& OutDrawElements + , int32 LayerId + , const FWidgetStyle& InWidgetStyle + , bool bParentEnabled) const +{ + /*TArray PointsUp; + PointsUp.Add(FVector2D(10, 0)); + PointsUp.Add(FVector2D(20, 0)); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), PointsUp, ESlateDrawEffect::None, FLinearColor::White, true, 2); + + TArray PointsDown; + PointsDown.Add(FVector2D(-10, 0)); + PointsDown.Add(FVector2D(-20, 0)); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), PointsDown, ESlateDrawEffect::None, FLinearColor::White, true, 2); + + TArray PointsLeft; + PointsLeft.Add(FVector2D(0, 10)); + PointsLeft.Add(FVector2D(0, 20)); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), PointsLeft, ESlateDrawEffect::None, FLinearColor::White, true, 2); + + + TArray PointsRight; + PointsRight.Add(FVector2D(0, -10)); + PointsRight.Add(FVector2D(0, -20)); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), PointsRight, ESlateDrawEffect::None, FLinearColor::White, true, 2);*/ + + + float X = FMath::Sin(FMath::DegreesToRadians(60.0f)); + float Y = FMath::Cos(FMath::DegreesToRadians(60.0f)); + FVector2D Dir(X, Y); + TArray PointsRight; + PointsRight.Add(Dir*10); + + + PointsRight.Add(Dir*30); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), PointsRight, ESlateDrawEffect::None, FLinearColor::White, true, 2); + + float X2 = FMath::Sin(FMath::DegreesToRadians(-60.0f)); + float Y2 = FMath::Cos(FMath::DegreesToRadians(-60.0f)); + FVector2D Dir2(X2, Y2); + TArray PointsLeft; + PointsLeft.Add(FVector2D(Dir2 * 10)); + PointsLeft.Add(Dir2 * 30); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), PointsLeft, ESlateDrawEffect::None, FLinearColor::White, true, 2); + + float X3 = FMath::Sin(FMath::DegreesToRadians(180.0f)); + float Y3 = FMath::Cos(FMath::DegreesToRadians(180.0f)); + FVector2D Dir3(X3, Y3); + TArray PointsTop; + PointsTop.Add(FVector2D(Dir3 * 10)); + PointsTop.Add(Dir3 * 30); + FSlateDrawElement::MakeLines(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), PointsTop, ESlateDrawEffect::None, FLinearColor::White, true, 2); + + if (Brush) + { + FSlateLayoutTransform Transform(FVector2D(0, 0)); + FSlateDrawElement::MakeBox(OutDrawElements + , LayerId + , AllottedGeometry.ToPaintGeometry(FVector2D(128,128), Transform) + , Brush); + } + + + float Step = 3.0f; + int32 Steps = 30; + + //{ + // TArray CirclePoints; + // for (int32 Idx = 0; Idx < Steps; Idx++) + // { + // float XC = FMath::Sin(FMath::DegreesToRadians(Idx*Step) - 120); + // float YC = FMath::Cos(FMath::DegreesToRadians(Idx*Step) - 120); + // FVector2D CDir(XC, YC); + // CirclePoints.Add(FVector2D(CDir*40.0f)); + // } + // FSlateDrawElement::MakeLines(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), CirclePoints, ESlateDrawEffect::None, FLinearColor::White, true, 12); + //} + //{ + // TArray ProgressPoints; + // for (int32 Idx = 0; Idx < Steps; Idx++) + // { + // float XC = FMath::Sin(FMath::DegreesToRadians(Idx*Step *Progress) - 120); + // float YC = FMath::Cos(FMath::DegreesToRadians(Idx*Step *Progress) - 120); + // FVector2D CDir(XC, YC); + // ProgressPoints.Add(FVector2D(CDir*40.0f)); + // } + // FSlateDrawElement::MakeLines(OutDrawElements, LayerId + 1, AllottedGeometry.ToPaintGeometry(), ProgressPoints, ESlateDrawEffect::None, FLinearColor::Red, true, 12); + //} + + //{ + // TArray CirclePoints; + // for (int32 Idx = 0; Idx < Steps; Idx++) + // { + // float XC = FMath::Sin(FMath::DegreesToRadians(Idx*Step) + 120); + // float YC = FMath::Cos(FMath::DegreesToRadians(Idx*Step) + 120); + // FVector2D CDir(XC, YC); + // CirclePoints.Add(FVector2D(CDir*40.0f)); + // } + // /* FPaintGeometry PG = AllottedGeometry.ToPaintGeometry(); + // FSlateRenderTransform RT; + + // PG.AppendTransform()*/ + // FSlateDrawElement::MakeLines(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), CirclePoints, ESlateDrawEffect::None, FLinearColor::White, true, 12); + //} + //{ + // TArray ProgressPoints; + // for (int32 Idx = 0; Idx < Steps; Idx++) + // { + // float XC = FMath::Sin(FMath::DegreesToRadians(Idx*Step *Progress) + 120); + // float YC = FMath::Cos(FMath::DegreesToRadians(Idx*Step *Progress) + 120); + // FVector2D CDir(XC, YC); + // ProgressPoints.Add(FVector2D(CDir*40.0f)); + // } + // FSlateDrawElement::MakeLines(OutDrawElements, LayerId + 1, AllottedGeometry.ToPaintGeometry(), ProgressPoints, ESlateDrawEffect::None, FLinearColor::Red, true, 12); + //} + + //{ + // TArray CirclePoints; + // for (int32 Idx = 0; Idx < Steps; Idx++) + // { + // float XC = FMath::Sin(FMath::DegreesToRadians(Idx*Step) + 20); + // float YC = FMath::Cos(FMath::DegreesToRadians(Idx*Step) + 20); + // FVector2D CDir(XC, YC); + // CirclePoints.Add(FVector2D(CDir*40.0f)); + // } + // /* FPaintGeometry PG = AllottedGeometry.ToPaintGeometry(); + // FSlateRenderTransform RT; + + // PG.AppendTransform()*/ + // FSlateDrawElement::MakeLines(OutDrawElements, LayerId, AllottedGeometry.ToPaintGeometry(), CirclePoints, ESlateDrawEffect::None, FLinearColor::White, true, 12); + //} + //{ + // TArray ProgressPoints; + // for (int32 Idx = 0; Idx < Steps; Idx++) + // { + // float XC = FMath::Sin(FMath::DegreesToRadians(Idx*Step *Progress) + 20); + // float YC = FMath::Cos(FMath::DegreesToRadians(Idx*Step *Progress) + 20); + // FVector2D CDir(XC, YC); + // ProgressPoints.Add(FVector2D(CDir*40.0f)); + // } + // FSlateDrawElement::MakeLines(OutDrawElements, LayerId + 1, AllottedGeometry.ToPaintGeometry(), ProgressPoints, ESlateDrawEffect::None, FLinearColor::Red, true, 12); + //} + + return LayerId; +} +void SARDrawTestWidget::Tick(const FGeometry& AllottedGeometry + , const double InCurrentTime + , const float InDeltaTime) +{ + if (Progress > 1.0f) + { + Progress = 0; + } + else + { + Progress += (ProgressStep*InDeltaTime); + } +} diff --git a/Source/ActionRPGGame/Private/Weapons/ARItemWeapon.cpp b/Source/ActionRPGGame/Private/Weapons/ARItemWeapon.cpp new file mode 100644 index 0000000..2867376 --- /dev/null +++ b/Source/ActionRPGGame/Private/Weapons/ARItemWeapon.cpp @@ -0,0 +1,210 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARItemWeapon.h" + +#include "Effects/GABlueprintLibrary.h" +#include "IFInventoryComponent.h" + +#include "ARCharacter.h" +#include "ARPlayerController.h" +#include "Attributes/ARGunAttributes.h" +#include "UI/ARHUD.h" +#include "UI/Inventory/ARUIInventoryComponent.h" +#include "UI/Inventory/ARInventoryScreenWidget.h" +#include "UI/Inventory/Weapons/Modifications/ARItemMagazineView.h" + +#include "Weapons/ARWeaponAbilityBase.h" +#include "Weapons/ARMagazineUpgradeItem.h" +#include "Weapons/ARWeaponInventoryComponent.h" +#include "Weapons/ARMagazineUpgradeEffect.h" + +UARItemWeapon::UARItemWeapon() +{ + AbilityHandle = FAFAbilitySpecHandle::GenerateHandle(); +} + +void UARItemWeapon::SetAbility(class UARWeaponAbilityBase* InAbility) +{ + AbilityInstance = InAbility; + AbilityInstance->SetWeaponItem(this); + + if (AbilityInstance) + { + AbilityInstance->GetAttributes()->CopyFromStruct(FARGunAttributesItem::StaticStruct(), &GeneratedAttributes); + } + +} +void UARItemWeapon::AddMagazineUpgrade(class UARMagazineUpgradeItem* InMagazineUpgrade) +{ + if (!AbilityInstance) + { + return; //add log. + } + + UARWeaponInventoryComponent* WeaponComponent = Cast(GetOuter()); + //might also check for PC inventory. + + if (!WeaponComponent) + return; + + AARCharacter* Character = Cast(WeaponComponent->GetOwner()); + if (!Character) + return; + + MagazineModification = DuplicateObject(InMagazineUpgrade, this); + + //this part only on server. + if (Character->Role >= ENetRole::ROLE_Authority) + { + MagazineUpgradeValue = InMagazineUpgrade->MagazineUpgradeValue; + AbilityInstance->AddMagazineUpgrade(InMagazineUpgrade->UpgradeEffect, MagazineUpgradeValue); + } + OnMagazineUpdateAdded(); +} +void UARItemWeapon::OnMagazineUpdateAdded() +{ +} + +UARMagazineUpgradeItem* UARItemWeapon::RemoveMagazineUpgrade() +{ + AbilityInstance->RemoveMagazineUpgrade(); + + return MagazineModification; +} + +bool UARItemWeapon::SpawnAbility() +{ + bool bSpawned = false; + + if (AbilityInstance) + return true; + + AARCharacter* Character = nullptr; + if (UIFInventoryComponent* InventoryComp = Cast(GetOuter())) + { + AARPlayerController* PC = Cast(InventoryComp->GetOwner()); + if (!PC) + return bSpawned; + + Character = Cast(PC->GetPawn()); + } + else if(UIFEquipmentComponent* EquipComp = Cast(GetOuter())) + { + Character = Cast(EquipComp->GetOwner()); + } + + if (!Character) + return bSpawned; + + TSubclassOf ABClass = Ability.LoadSynchronous(); + if (ABClass) + { + AbilityInstance = NewObject(Character, ABClass); + AbilityInstance->GetAttributes()->CopyFromStruct(FARGunAttributesItem::StaticStruct(), &GeneratedAttributes); + if (MagazineModification) + { + AbilityInstance->AddMagazineUpgrade(MagazineModification); + } + bSpawned = true; + } + + return bSpawned; +} +void UARItemWeapon::OnServerItemLoaded() +{ + /* + 1. Generate Weapon Stats here. + 2. Add random perks (weapon) + 3. Add random attributes to give (Character). + 4. Add random effects to give (Character). + */ +} +void UARItemWeapon::OnItemAdded(uint8 InIndex) +{ + SpawnAbility(); +} +void UARItemWeapon::OnItemRemoved(uint8 InIndex) +{ + +} +void UARItemWeapon::OnServerItemAdded(uint8 InIndex) +{ + SpawnAbility(); +} +void UARItemWeapon::OnServerItemChanged(uint8 InIndex) +{ +} +void UARItemWeapon::OnServerItemRemoved(uint8 InIndex) +{ +} + +void UARItemWeapon::OnItemAddedEquipment(uint8 InIndex) +{ +}; +void UARItemWeapon::OnItemChangedEquipment(uint8 InIndex) +{ +}; +void UARItemWeapon::OnItemRemovedEquipment(uint8 InIndex) +{ +}; + +void UARItemWeapon::OnServerItemAddedEquipment(uint8 InIndex) +{ + UARWeaponInventoryComponent* WeaponComponent = Cast(GetOuter()); + if (!WeaponComponent) + return; + +}; +void UARItemWeapon::OnServerItemChangedEquipment(uint8 InIndex) +{ +}; +void UARItemWeapon::OnServerItemRemovedEquipment(uint8 InIndex) +{ +}; + +void UARItemWeapon::ClientPostItemDeserializeFromJson() +{ +} + +TArray UARItemWeapon::GetTooltipData() +{ + TArray Data; + + FARItemTooltipData ItemName("ItemName", GetName()); + Data.Add(ItemName); + + if (!AbilityInstance) + return Data; + + UARGunAttributes* ABAttr = AbilityInstance->GetAttributesTyped(); + + if (ABAttr) + { + FARItemTooltipData BaseDamage("BaseDamage", FString::SanitizeFloat(ABAttr->BaseDamage.GetCurrentValue())); + Data.Add(BaseDamage); + + FARItemTooltipData CritChance("CritChance", FString::SanitizeFloat(ABAttr->CritChance.GetCurrentValue())); + Data.Add(CritChance); + + FARItemTooltipData Magazine("Magazine", FString::SanitizeFloat(ABAttr->Magazine.GetCurrentValue())); + Data.Add(Magazine); + + FARItemTooltipData RateOfFire("RateOfFire", FString::SanitizeFloat(ABAttr->RateOfFire.GetCurrentValue())); + Data.Add(RateOfFire); + + FARItemTooltipData ReloadSpeed("ReloadSpeed", FString::SanitizeFloat(ABAttr->ReloadSpeed.GetCurrentValue())); + Data.Add(ReloadSpeed); + + FARItemTooltipData HorizontalStability("HorizontalStability", FString::SanitizeFloat(ABAttr->HorizontalStability.GetCurrentValue())); + Data.Add(HorizontalStability); + + FARItemTooltipData VerticalStability("VerticalStability", FString::SanitizeFloat(ABAttr->VerticalStability.GetCurrentValue())); + Data.Add(VerticalStability); + + FARItemTooltipData Spread("Spread", FString::SanitizeFloat(ABAttr->Spread.GetCurrentValue())); + Data.Add(Spread); + + } + + return Data; +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/Weapons/ARMagazineUpgradeEffect.cpp b/Source/ActionRPGGame/Private/Weapons/ARMagazineUpgradeEffect.cpp new file mode 100644 index 0000000..2ecaf41 --- /dev/null +++ b/Source/ActionRPGGame/Private/Weapons/ARMagazineUpgradeEffect.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARMagazineUpgradeEffect.h" + + + + diff --git a/Source/ActionRPGGame/Private/Weapons/ARMagazineUpgradeItem.cpp b/Source/ActionRPGGame/Private/Weapons/ARMagazineUpgradeItem.cpp new file mode 100644 index 0000000..b344720 --- /dev/null +++ b/Source/ActionRPGGame/Private/Weapons/ARMagazineUpgradeItem.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARMagazineUpgradeItem.h" + + + + diff --git a/Source/ActionRPGGame/Private/Weapons/ARWeaponAbilityBase.cpp b/Source/ActionRPGGame/Private/Weapons/ARWeaponAbilityBase.cpp new file mode 100644 index 0000000..262f1b3 --- /dev/null +++ b/Source/ActionRPGGame/Private/Weapons/ARWeaponAbilityBase.cpp @@ -0,0 +1,123 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARWeaponAbilityBase.h" +#include "Effects/GABlueprintLibrary.h" + +#include "Weapons/ARItemWeapon.h" +#include "Weapons/ARMagazineUpgradeItem.h" + +#include "ARCharacter.h" +#include "ARWeaponBase.h" + +void UARWeaponAbilityBase::SetAttributes(UGAAttributesBase* InAttributes) +{ + Attributes = InAttributes; +} +class UGAAttributesBase* UARWeaponAbilityBase::GetAttributes() const +{ + return Attributes; +} +class UGAAttributesBase* UARWeaponAbilityBase::GetAttributes() +{ + return Attributes; +} + +void UARWeaponAbilityBase::OnAbilityInited() +{ + ResetDamageEffects(); +} +void UARWeaponAbilityBase::OnAbilityInputReady() +{ + if (AARCharacter* Character = Cast(POwner)) + { + if (AARWeaponBase* Weapon = Cast(Character->GetEquipedMainWeapon()->GetChildActor())) + { + WeaponActor = Weapon; + } + } +} +void UARWeaponAbilityBase::OnAvatarReady() +{ + //AARWeaponBase* Weapon = Cast(AvatarActor); + //Weapon->SetPawn(POwner); + //Weapon->Equip(); +} + +void UARWeaponAbilityBase::ReplaceDamageEffects(const TArray& InEffects) +{ + +} + +void UARWeaponAbilityBase::AddDamageEffects(const TArray& InEffects) +{ + +} + +void UARWeaponAbilityBase::ResetDamageEffects() +{ + DamageEffects.Empty(); + DamageEffects.Append(DefaultDamageEffects); + AppliedEffectHandles.Empty(); + AppliedEffectHandles.AddZeroed(DamageEffects.Num()); +} + +void UARWeaponAbilityBase::ApplyDamageEffect(UObject* Target, FAFFunctionModifier Modifier) +{ + for (int32 Idx = 0; Idx < DamageEffects.Num(); Idx++) + { + UGABlueprintLibrary::ApplyGameEffectToObject(DamageEffects[Idx] + , Target + , POwner + , this + , Modifier); + } +} +void UARWeaponAbilityBase::ReloadWeapon() +{ + +} +void UARWeaponAbilityBase::AddMagazineUpgrade(class UARMagazineUpgradeItem* InMagazineUpgrade) +{ + AddMagazineUpgrade(InMagazineUpgrade->UpgradeEffect, InMagazineUpgrade->MagazineUpgradeValue); +} +void UARWeaponAbilityBase::AddMagazineUpgrade(TSubclassOf InMagazineUpgrade, float UpgradeValue) +{ + MagazineUpgradeProperty = InMagazineUpgrade; + if (AARCharacter* Character = Cast(POwner)) + { + AddUpgrade(MagazineUpgradeProperty, MagazineEffectHandle, MagazineSpecHandle, Character, UpgradeValue); + } +} + +void UARWeaponAbilityBase::RemoveMagazineUpgrade() +{ + FGAEffectMod Mod = MagazineSpecHandle.GetModifier(); + RemoveBonus(Mod.Attribute, MagazineEffectHandle, Mod.AttributeMod); + UpgradeContainer.RemoveEffect(MagazineEffectHandle); + + MagazineUpgradeProperty.Reset(); + MagazineSpecHandle.Reset(); +} + +void UARWeaponAbilityBase::AddUpgrade(FAFPropertytHandle& PropertyHandle + , FGAEffectHandle& EffectHandle + , FAFEffectSpecHandle& SpecHandle + , class AARCharacter* Character + , float UpgradeValue) +{ + //UGABlueprintLibrary::CreateEffectSpec(SpecHandle, PropertyHandle, this, Character, Character); + + //EffectHandle = FGAEffectHandle::GenerateHandle(); + //SpecHandle.CalculateAttributeModifier(EffectHandle); + //SpecHandle.OverrideAttributeModifier(UpgradeValue); + + //FGAEffect Effect(SpecHandle.GetPtr(), EffectHandle); + + //UpgradeContainer.ApplyEffect(EffectHandle, Effect); + + //FAFContextHandle Context = FAFContextHandle::Generate(&DefaultContext); + + //FGAEffectMod Mod = SpecHandle.GetModifier(); + //ModifyAttribute(Mod, EffectHandle, PropertyHandle.GetRef(), Context); + +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/Weapons/ARWeaponBase.cpp b/Source/ActionRPGGame/Private/Weapons/ARWeaponBase.cpp new file mode 100644 index 0000000..a2efacb --- /dev/null +++ b/Source/ActionRPGGame/Private/Weapons/ARWeaponBase.cpp @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARWeaponBase.h" + +#include "Components/SkeletalMeshComponent.h" +// Sets default values +AARWeaponBase::AARWeaponBase() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + + Mesh = CreateDefaultSubobject(TEXT("Mesh")); + SetRootComponent(Mesh); +} + +// Called when the game starts or when spawned +void AARWeaponBase::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void AARWeaponBase::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + diff --git a/Source/ActionRPGGame/Private/Weapons/ARWeaponInventoryComponent.cpp b/Source/ActionRPGGame/Private/Weapons/ARWeaponInventoryComponent.cpp new file mode 100644 index 0000000..08c9a37 --- /dev/null +++ b/Source/ActionRPGGame/Private/Weapons/ARWeaponInventoryComponent.cpp @@ -0,0 +1,775 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARWeaponInventoryComponent.h" +#include "Engine/AssetManager.h" +#include "ARItemWeapon.h" +#include "Weapons/ARWeaponAbilityBase.h" +#include "ARCharacter.h" +#include "ARPlayerController.h" +#include "AFAbilityComponent.h" + +// Sets default values for this component's properties +UARWeaponInventoryComponent::UARWeaponInventoryComponent() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = true; + + + MaxSlots = 4; + AvailableSlots = 4; + ClientWeaponAbilities.SetNum(4); + ServerWeaponAbilities.SetNum(4); + CurrentWeaponIndex = -1; + // ... +} + + +// Called when the game starts +void UARWeaponInventoryComponent::BeginPlay() +{ + Super::BeginPlay(); + + // ... + +} +void UARWeaponInventoryComponent::BindInputs(UInputComponent* InputComponent, class UAFAbilityComponent* AbilityComponent) +{ +} +void UARWeaponInventoryComponent::InitializeWeapons(APawn* Pawn) +{ + if (AARCharacter* Character = Cast(Pawn)) + { + GroupToComponent.Add(0, Character->GetHolsteredRightWeapon()); + GroupToComponent.Add(1, Character->GetHolsteredLeftWeapon()); + GroupToComponent.Add(2, Character->GetHolsteredBackDownWeapon()); + GroupToComponent.Add(3, Character->GetHolsteredSideLeftWeapon()); + POwner = Character; + } +} +// Called every frame +void UARWeaponInventoryComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + // ... +} + +void UARWeaponInventoryComponent::SetWeapon(const FARWeaponRPC& InWeapon, UChildActorComponent* Component) +{ + //if (InWeapon.Weapon.IsValid() || InWeapon.Weapon.IsNull()) + { + TSubclassOf WpnClass = TSoftClassPtr(InWeapon.Weapon).LoadSynchronous(); + Component->SetChildActorClass(WpnClass); + Component->SetRelativeLocation(FVector(0, 0, 0)); + Component->SetRelativeRotation(FRotator(0, 0, 0)); + + Component->SetRelativeLocation(InWeapon.Position); + Component->SetRelativeRotation(InWeapon.Rotation); + } +} +void UARWeaponInventoryComponent::OnClientPreItemAdded(UIFItemBase* Item, uint8 Index) +{ + if (UARItemWeapon* ItemWeapon = Cast(Item)) + { + + } +} +void UARWeaponInventoryComponent::OnItemAdded(UIFItemBase* Item, uint8 LocalIndex) +{ + if (UARItemWeapon* ItemWeapon = Cast(Item)) + { + if (AARCharacter* Character = Cast(POwner)) + { + UAFAbilityComponent* AbilityComp = Character->GetAbilityComp(); + if (!AbilityComp) + return; + FAFOnAbilityReady Del = FAFOnAbilityReady::CreateUObject(this, &UARWeaponInventoryComponent::OnAbilityAdded); + AbilityComp->AddOnAbilityReadyDelegate(ItemWeapon->AbilityHandle, Del); + + ClientWeaponAbilities[LocalIndex] = ItemWeapon->AbilityHandle; + //handle case of Client/Server ability handle. + AbilityComp->NativeAddAbility(ItemWeapon->Ability, ItemWeapon->AbilityHandle); + } + } +} +void UARWeaponInventoryComponent::OnAbilityAdded(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle) +{ + int32 Idx = ClientWeaponAbilities.IndexOfByKey(ClientHandle); + ServerWeaponAbilities[Idx] = ServerHandle; +} +void UARWeaponInventoryComponent::OnServerItemAdded(UIFItemBase* Item, uint8 LocalIndex) +{ + if (UARItemWeapon* ItemWeapon = Cast(Item)) + { + ServerWeaponAbilities[LocalIndex] = ItemWeapon->AbilityHandle; + } +} +void UARWeaponInventoryComponent::OnWeaponReady(TSoftClassPtr InAbilityTag, int8 LocalIndex) +{ + AARCharacter* Character = Cast(POwner); + if (!Character) + return; + + UAFAbilityComponent* AbilityComp = Character->GetAbilityComp(); + + UGAAbilityBase* Ability = Cast(AbilityComp->BP_GetAbilityByHandle(ServerWeaponAbilities[LocalIndex])); + SetAbilityToItem(LocalIndex, Ability); +} +void UARWeaponInventoryComponent::SetAbilityToItem(int8 InLocalIndex, class UGAAbilityBase* InAbility) +{ + UARItemWeapon* ItemWeapon = GetItem(InLocalIndex); + + if (!ItemWeapon) + return; + + ItemWeapon->SetAbility(Cast(InAbility)); +} +void UARWeaponInventoryComponent::OnItemRemoved(uint8 LocalIndex) +{ + AARCharacter* Character = Cast(POwner); + + //Character->GetAbilityComp()->NativeRemoveAbility(WeaponAbilities[LocalIndex]); + + FARWeaponRPC Data; + Data.Weapon.Reset(); + //Data.SocketName = InWeapon->Socket; + Data.Position = FVector::ZeroVector; + Data.Rotation = FRotator::ZeroRotator; + Data.AttachSlot = static_cast(LocalIndex); + + SetWeapon(Data, GroupToComponent[LocalIndex]); + if (LocalIndex == CurrentWeaponIndex) + { + Unequip(LocalIndex); + } +} + + +void UARWeaponInventoryComponent::OnServerItemRemoved(uint8 LocalIndex) +{ + FARWeaponRPC Data; + Data.Weapon.Reset(); + Data.Index = LocalIndex; + //Data.SocketName = InWeapon->Socket; + Data.Position = FVector::ZeroVector; + Data.Rotation = FRotator::ZeroRotator; + Data.AttachSlot = static_cast(LocalIndex); + MulticastRemoveWeapon(Data); +} +void UARWeaponInventoryComponent::MulticastAddWeapon_Implementation(const FARWeaponRPC& WeaponData) +{ + if (AARCharacter* Character = Cast(POwner)) + { + switch (WeaponData.AttachSlot) + { + case EARWeaponPosition::Right: + SetWeapon(WeaponData, Character->GetHolsteredRightWeapon()); + break; + case EARWeaponPosition::Left: + SetWeapon(WeaponData, Character->GetHolsteredLeftWeapon()); + break; + case EARWeaponPosition::BottomBack: + SetWeapon(WeaponData, Character->GetHolsteredBackDownWeapon()); + break; + case EARWeaponPosition::Side: + SetWeapon(WeaponData, Character->GetHolsteredSideLeftWeapon()); + break; + case EARWeaponPosition::Equiped: + SetWeapon(WeaponData, Character->GetEquipedMainWeapon()); + break; + default: + break; + } + } +} +void UARWeaponInventoryComponent::MulticastRemoveWeapon_Implementation(const FARWeaponRPC& WeaponData) +{ + if (AARCharacter* Character = Cast(POwner)) + { + switch (WeaponData.AttachSlot) + { + case EARWeaponPosition::Right: + Character->GetHolsteredRightWeapon()->SetChildActorClass(nullptr); + break; + case EARWeaponPosition::Left: + Character->GetHolsteredLeftWeapon()->SetChildActorClass(nullptr); + break; + case EARWeaponPosition::BottomBack: + Character->GetHolsteredBackDownWeapon()->SetChildActorClass(nullptr); + break; + case EARWeaponPosition::Side: + Character->GetHolsteredSideLeftWeapon()->SetChildActorClass(nullptr); + break; + case EARWeaponPosition::Equiped: + Character->GetEquipedMainWeapon()->SetChildActorClass(nullptr); + break; + default: + break; + } + } + + if (WeaponData.Index == CurrentWeaponIndex) + { + if (AARCharacter* Character = Cast(POwner)) + { + Character->GetEquipedMainWeapon()->SetChildActorClass(nullptr); + } + } +} + +void UARWeaponInventoryComponent::MulticastEquipWeapon_Implementation(int8 WeaponIndex, const FARWeaponRPC& WeaponData) +{ + ENetRole Role = GetOwnerRole(); + if (AARCharacter* Character = Cast(POwner)) + { + SetWeapon(WeaponData, Character->GetEquipedMainWeapon()); + GroupToComponent[WeaponIndex]->SetChildActorClass(nullptr); + } + CurrentWeaponIndex = WeaponIndex; +} +void UARWeaponInventoryComponent::MulticastUnequipWeapon_Implementation(int8 OldWeaponIndex, const FARWeaponRPC& WeaponData) +{ + UARItemWeapon* EquipedWeapon = GetItem(OldWeaponIndex); + if (!EquipedWeapon) + return; + if (AARCharacter* Character = Cast(POwner)) + { + if (!Character->GetEquipedMainWeapon()->GetChildActor()) + { + return; + } + Character->GetEquipedMainWeapon()->SetChildActorClass(nullptr); + } + SetWeapon(WeaponData, GroupToComponent[OldWeaponIndex]); +} +void UARWeaponInventoryComponent::Equip(int8 WeaponIndex, const FARWeaponRPC& WeaponData) +{ + if (WeaponIndex < 0) + return; + + if (AARCharacter* Character = Cast(POwner)) + { + SetWeapon(WeaponData, Character->GetEquipedMainWeapon()); + GroupToComponent[WeaponIndex]->SetChildActorClass(nullptr); + CurrentWeaponIndex = WeaponIndex; + } +} +void UARWeaponInventoryComponent::Unequip(int8 WeaponIndex) +{ + UARItemWeapon* EquipedWeapon = GetItem(WeaponIndex); + if (!EquipedWeapon) + return; + if (AARCharacter* Character = Cast(POwner)) + { + if (!Character->GetEquipedMainWeapon()->GetChildActor()) + { + return; + } + Character->GetEquipedMainWeapon()->SetChildActorClass(nullptr); + } + FARWeaponRPC Data; + Data.Weapon = EquipedWeapon->Weapon.ToString(); + //Data.SocketName = InWeapon->Socket; + Data.Position = EquipedWeapon->HolsteredPosition; + Data.Rotation = EquipedWeapon->HolsteredRotation; + Data.AttachSlot = static_cast(WeaponIndex); + SetWeapon(Data, GroupToComponent[WeaponIndex]); + ServerHolster(Data); + CurrentWeaponIndex = -1; +} +void UARWeaponInventoryComponent::Holster() +{ + UARItemWeapon* EquipedWeapon = GetItem(CurrentWeaponIndex); + if (!EquipedWeapon) + return; + if (AARCharacter* Character = Cast(POwner)) + { + Character->GetEquipedMainWeapon()->SetChildActorClass(nullptr); + } + FARWeaponRPC Data; + Data.Weapon = EquipedWeapon->Weapon.ToString(); + //Data.SocketName = InWeapon->Socket; + Data.Position = EquipedWeapon->HolsteredPosition; + Data.Rotation = EquipedWeapon->HolsteredRotation; + Data.AttachSlot = static_cast(CurrentWeaponIndex); + SetWeapon(Data, GroupToComponent[CurrentWeaponIndex]); + ServerHolster(Data); + CurrentWeaponIndex = -1; +} +void UARWeaponInventoryComponent::ServerHolster_Implementation(const FARWeaponRPC& WeaponData) +{ + MulticastHolster(WeaponData); +} +bool UARWeaponInventoryComponent::ServerHolster_Validate(const FARWeaponRPC& WeaponData) +{ + return true; +} +void UARWeaponInventoryComponent::MulticastHolster_Implementation(const FARWeaponRPC& WeaponData) +{ + ENetRole Role = GetOwnerRole(); + if (Role != ENetRole::ROLE_AutonomousProxy + && Role != ENetRole::ROLE_Authority) + { + SetWeapon(WeaponData, GroupToComponent[CurrentWeaponIndex]); + CurrentWeaponIndex = -1; + } +} + +void UARWeaponInventoryComponent::NextWeapon() +{ + ENetMode NetMode = GetOwner()->GetNetMode(); + bool bProceed = false; + switch (NetMode) + { + case NM_Standalone: + bProceed = true; + break; + case NM_DedicatedServer: + break; + case NM_ListenServer: + break; + case NM_Client: + bProceed = true; + break; + case NM_MAX: + break; + default: + break; + } + + if (!bProceed) + { + return; + } + + int8 OldGroup = CurrentWeaponIndex; + if (OldGroup > -1) + Unequip(OldGroup); + + int8 CurrentIndex = CurrentWeaponIndex; + CurrentIndex++; + if (CurrentIndex > 4 || CurrentIndex < 0) + { + CurrentWeaponIndex = 0; + } + else + { + CurrentWeaponIndex = CurrentIndex; + } + + UARItemWeapon* InWeapon = GetItem(CurrentWeaponIndex); + if (!InWeapon) + { + InWeapon = FindNextValid(); + } + if (!InWeapon) + { + //we don't have any weapon. + return; + } + FARWeaponRPC Data; + Data.Weapon = InWeapon->Weapon.ToString(); + //Data.SocketName = InWeapon->Socket; + Data.Position = InWeapon->EquipedPosition; + Data.Rotation = InWeapon->EquipedRotation; + Data.AttachSlot = EARWeaponPosition::Equiped; + + + Equip(CurrentWeaponIndex, Data); + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + ServerNextWeapon(CurrentWeaponIndex); + } +} +void UARWeaponInventoryComponent::PreviousWeapon() +{ + ENetMode NetMode = GetOwner()->GetNetMode(); + bool bProceed = false; + switch (NetMode) + { + case NM_Standalone: + bProceed = true; + break; + case NM_DedicatedServer: + break; + case NM_ListenServer: + break; + case NM_Client: + bProceed = true; + break; + case NM_MAX: + break; + default: + break; + } + + if (!bProceed) + { + return; + } + int8 OldGroup = CurrentWeaponIndex; + + int8 CurrentIndex = CurrentWeaponIndex; + CurrentIndex--; + CurrentWeaponIndex = CurrentIndex; + if (CurrentIndex < 0) + { + CurrentWeaponIndex = 3; + } + UARItemWeapon* NextWeaponAbility = GetItem(CurrentWeaponIndex); + if (!NextWeaponAbility) + { + NextWeaponAbility = FindPreviousValid(); + } + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + ServerPreviousWeapon(CurrentWeaponIndex); + } +} + +void UARWeaponInventoryComponent::HolsterWeapon() +{ + Holster(); +} +void UARWeaponInventoryComponent::ServerNextWeapon_Implementation(int8 WeaponIndex) +{ + int8 OldGroup = CurrentWeaponIndex; + + int8 CurrentIndex = CurrentWeaponIndex; + //if (WeaponIndex > CurrentIndex) + CurrentIndex++; + + if (CurrentIndex > 4 || CurrentIndex < 0) + { + CurrentWeaponIndex = 0; + } + else + { + CurrentWeaponIndex = CurrentIndex; + } + + if (OldGroup > -1) + { + UARItemWeapon* OldWeapon = GetItem(OldGroup); + if (OldWeapon) + { + FARWeaponRPC OldData; + OldData.Weapon = OldWeapon->Weapon.ToString(); + OldData.Position = OldWeapon->HolsteredPosition; + OldData.Rotation = OldWeapon->HolsteredRotation; + OldData.AttachSlot = static_cast(OldGroup); + MulticastUnequipWeapon(OldGroup, OldData); + } + } + + UARItemWeapon* InWeapon = GetItem(CurrentWeaponIndex); + if (!InWeapon) + { + InWeapon = FindNextValid(); + } + FARWeaponRPC Data; + Data.Weapon = InWeapon->Weapon.ToString(); + Data.Position = InWeapon->EquipedPosition; + Data.Rotation = InWeapon->EquipedRotation; + Data.AttachSlot = EARWeaponPosition::Equiped; + MulticastEquipWeapon(CurrentWeaponIndex, Data); + if (WeaponIndex == CurrentWeaponIndex) + { + ClientNextWeapon(CurrentWeaponIndex, true); + } + else + { + ClientNextWeapon(CurrentWeaponIndex, false); + } +} +bool UARWeaponInventoryComponent::ServerNextWeapon_Validate(int8 WeaponIndex) +{ + return true; +} +void UARWeaponInventoryComponent::ClientNextWeapon_Implementation(int8 WeaponIndex, bool bPredictionSuccess) +{ + HandleClientPrediction(WeaponIndex, bPredictionSuccess); +} + +void UARWeaponInventoryComponent::ServerPreviousWeapon_Implementation(int8 WeaponIndex) +{ + int8 CurrentIndex = CurrentWeaponIndex; + if (CurrentIndex > WeaponIndex) + CurrentIndex--; + + if (CurrentIndex < 0) + { + CurrentWeaponIndex = 3; + } + else + { + CurrentWeaponIndex = CurrentIndex; + } + + UARItemWeapon* OldWeapon = GetItem(CurrentIndex); + if (OldWeapon) + { + FARWeaponRPC OldData; + OldData.Weapon = OldWeapon->Weapon.ToString(); + OldData.Position = OldWeapon->HolsteredPosition; + OldData.Rotation = OldWeapon->HolsteredRotation; + OldData.AttachSlot = static_cast(CurrentIndex); + MulticastUnequipWeapon(CurrentIndex, OldData); + } + + UARItemWeapon* InWeapon = GetItem(CurrentWeaponIndex); + if (!InWeapon) + { + InWeapon = FindNextValid(); + } + FARWeaponRPC Data; + Data.Weapon = InWeapon->Weapon.ToString(); + Data.Position = InWeapon->EquipedPosition; + Data.Rotation = InWeapon->EquipedRotation; + Data.AttachSlot = EARWeaponPosition::Equiped; + MulticastEquipWeapon(CurrentWeaponIndex, Data); + + //so Server index is different. Client might tried to cheat + //or sometrhing. We will override it. + //situation where client can chage multiple weapons within second + //should not have place, as there is animation and/or internal cooldown on weapon change. + //since it will be done trough ability. + //Equip(CurrentWeaponIndex, NextWeaponAbility); + if (CurrentWeaponIndex != WeaponIndex) + { + ClientPreviousWeapon(CurrentWeaponIndex, false); + } + else + { + ClientPreviousWeapon(CurrentWeaponIndex, true); + } +} +bool UARWeaponInventoryComponent::ServerPreviousWeapon_Validate(int8 WeaponIndex) +{ + return true; +} +void UARWeaponInventoryComponent::ClientPreviousWeapon_Implementation(int8 WeaponIndex, bool bPredictionSuccess) +{ + HandleClientPrediction(WeaponIndex, bPredictionSuccess); +} + +void UARWeaponInventoryComponent::HandleClientPrediction(int8 WeaponIndex, bool bPredictionSuccess) +{ + if (bPredictionSuccess) + { + if (AARCharacter* Character = Cast(POwner)) + { + UARItemWeapon* Item = GetItem(WeaponIndex); + + UAFAbilityComponent* AbilityComp = Character->GetAbilityComp(); + if (!AbilityComp) + return; + //TODO + TArray InputIDs; + InputIDs.Add(static_cast(AbilityInput::Shoot)); + InputIDs.Add(static_cast(AbilityInput::Reload)); + AbilityComp->BindAbilityToInputIDs(ServerWeaponAbilities[WeaponIndex], InputIDs); + } + return; + } + else //override client decision. + { + CurrentWeaponIndex = WeaponIndex; + UARItemWeapon* InWeapon = GetItem(CurrentWeaponIndex); + if (!InWeapon) + { + InWeapon = FindNextValid(); + } + FARWeaponRPC Data; + Data.Weapon = InWeapon->Weapon.ToString(); + //Data.SocketName = InWeapon->Socket; + Data.Position = InWeapon->EquipedPosition; + Data.Rotation = InWeapon->EquipedRotation; + Data.AttachSlot = EARWeaponPosition::Equiped; + + Equip(CurrentWeaponIndex, Data); + + if (AARCharacter* Character = Cast(POwner)) + { + UAFAbilityComponent* AbilityComp = Character->GetAbilityComp(); + if (!AbilityComp) + return; + //TODO + TArray InputIDs; + InputIDs.Add(static_cast(AbilityInput::Shoot)); + InputIDs.Add(static_cast(AbilityInput::Reload)); + AbilityComp->BindAbilityToInputIDs(ServerWeaponAbilities[WeaponIndex], InputIDs); + } + } +} + +UARItemWeapon* UARWeaponInventoryComponent::FindNextValid() +{ + UARItemWeapon* WeaponAbilityTag = nullptr; + + int8 Idx = CurrentWeaponIndex; + while (!WeaponAbilityTag) + { + Idx++; + if (Idx > 4 - 1) + { + Idx = 0; + } + WeaponAbilityTag = GetItem(Idx); + + //no weapon at first index, just assume there is nothing equipped. + if ((Idx == 0) && !WeaponAbilityTag) + { + break; + } + } + if (WeaponAbilityTag) + { + CurrentWeaponIndex = Idx; + } + return WeaponAbilityTag; +} + +UARItemWeapon* UARWeaponInventoryComponent::FindPreviousValid() +{ + UARItemWeapon* WeaponAbilityTag = nullptr; + int8 Idx = CurrentWeaponIndex; + while (!WeaponAbilityTag) + { + Idx--; + if (Idx < 0) + { + Idx = 4 - 1; + } + + //again no ability for weapon. + if ((Idx == (4 - 1)) && !WeaponAbilityTag) + { + break; + } + WeaponAbilityTag = GetItem(Idx); + } + if (WeaponAbilityTag) + { + CurrentWeaponIndex = Idx; + } + return WeaponAbilityTag; +} + +void UARWeaponInventoryComponent::AsynWeaponLoaded(UChildActorComponent* Component, FARWeaponRPC InWeapon) +{ + Component->SetChildActorClass(TSoftClassPtr(InWeapon.Weapon).LoadSynchronous()); + + Component->SetRelativeLocation(FVector(0,0,0)); + Component->SetRelativeRotation(FRotator(0,0,0)); + + Component->SetRelativeLocation(InWeapon.Position); + Component->SetRelativeRotation(InWeapon.Rotation); +} +void UARWeaponInventoryComponent::AddMagazineMod(int8 WeaponIdx, int8 MagazineModIndex) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + ServerAddMagazineMod(WeaponIdx, MagazineModIndex); + return; + } +} +void UARWeaponInventoryComponent::ServerAddMagazineMod_Implementation(int8 WeaponIdx, int8 MagazineModIndex) +{ + if (AARCharacter* Character = Cast(GetOwner())) + { + if (AARPlayerController* PC = Cast(Character->Controller)) + { + UIFInventoryComponent* MainInventory = PC->MainInventory; + + UARMagazineUpgradeItem* Magazine = MainInventory->GetItem(MagazineModIndex); + if (Magazine) + { + UARItemWeapon* Weapon = GetItem(WeaponIdx); + if (Weapon) + { + Weapon->AddMagazineUpgrade(Magazine); + ClientAddMagazineMod(WeaponIdx, MagazineModIndex); + } + } + } + } +} +bool UARWeaponInventoryComponent::ServerAddMagazineMod_Validate(int8 WeaponIdx, int8 MagazineModIndex) +{ + return true; +} + +void UARWeaponInventoryComponent::ClientAddMagazineMod_Implementation(int8 WeaponIdx, int8 MagazineModIndex) +{ + if (AARCharacter* Character = Cast(GetOwner())) + { + if (AARPlayerController* PC = Cast(Character->Controller)) + { + UIFInventoryComponent* MainInventory = PC->MainInventory; + + UARMagazineUpgradeItem* Magazine = MainInventory->GetItem(MagazineModIndex); + if (Magazine) + { + UARItemWeapon* Weapon = GetItem(WeaponIdx); + if (Weapon) + { + Weapon->AddMagazineUpgrade(Magazine); + MainInventory->RemoveItem(MagazineModIndex); + + OnUpgradeInstalled.Broadcast(Weapon, Magazine, WeaponIdx); + } + } + } + } +} + +void UARWeaponInventoryComponent::RemoveMagazineMod(int8 WeaponIdx) +{ + if (GetOwnerRole() < ENetRole::ROLE_Authority) + { + ServerRemoveMagazineMod(WeaponIdx); + return; + } + +} +void UARWeaponInventoryComponent::ServerRemoveMagazineMod_Implementation(int8 WeaponIdx) +{ + if (AARCharacter* Character = Cast(GetOwner())) + { + if (AARPlayerController* PC = Cast(Character->Controller)) + { + UIFInventoryComponent* MainInventory = PC->MainInventory; + + UARItemWeapon* Weapon = GetItem(WeaponIdx); + if (Weapon) + { + UARMagazineUpgradeItem* MagazineUpgrade = Weapon->RemoveMagazineUpgrade(); + ServerRemoveMagazineMod(WeaponIdx); + PC->MainInventory->AddItemAnySlot(MagazineUpgrade); + ClientRemoveMagazineMod(WeaponIdx); + } + } + } +} +bool UARWeaponInventoryComponent::ServerRemoveMagazineMod_Validate(int8 WeaponIdx) +{ + return true; +} +void UARWeaponInventoryComponent::ClientRemoveMagazineMod_Implementation(int8 WeaponIdx) +{ + if (AARCharacter* Character = Cast(GetOwner())) + { + if (AARPlayerController* PC = Cast(Character->Controller)) + { + UIFInventoryComponent* MainInventory = PC->MainInventory; + + UARItemWeapon* Weapon = GetItem(WeaponIdx); + if (Weapon) + { + UARMagazineUpgradeItem* MagazineUpgrade = Weapon->RemoveMagazineUpgrade(); + OnUpgradeRemoved.Broadcast(Weapon, MagazineUpgrade, WeaponIdx); + } + } + } +} \ No newline at end of file diff --git a/Source/ActionRPGGame/Private/Weapons/ARWeaponUpgradeItem.cpp b/Source/ActionRPGGame/Private/Weapons/ARWeaponUpgradeItem.cpp new file mode 100644 index 0000000..1e691da --- /dev/null +++ b/Source/ActionRPGGame/Private/Weapons/ARWeaponUpgradeItem.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARWeaponUpgradeItem.h" + + + + diff --git a/Source/ActionRPGGame/Private/Weapons/ARWeaponsTypes.cpp b/Source/ActionRPGGame/Private/Weapons/ARWeaponsTypes.cpp new file mode 100644 index 0000000..dcd3165 --- /dev/null +++ b/Source/ActionRPGGame/Private/Weapons/ARWeaponsTypes.cpp @@ -0,0 +1,3 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "ARWeaponsTypes.h" diff --git a/Source/ActionRPGGame/Public/AI/ARAICharacter.h b/Source/ActionRPGGame/Public/AI/ARAICharacter.h new file mode 100644 index 0000000..bd658f0 --- /dev/null +++ b/Source/ActionRPGGame/Public/AI/ARAICharacter.h @@ -0,0 +1,70 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Character.h" +#include "GameplayTags.h" +#include "AFAbilityComponent.h" +#include "AFEffectsComponent.h" + +#include "AFAbilityInterface.h" + +#include "ARAICharacter.generated.h" + +UCLASS() +class ACTIONRPGGAME_API AARAICharacter : public ACharacter, public IAFAbilityInterface +{ + GENERATED_BODY() + friend class AAREnemySpawner; +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + class UAFAbilityComponent* Abilities; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + class UAFEffectsComponent* EffectsComponent; + + UPROPERTY(BlueprintReadOnly, Category = "ActionRPGGame|Spawn") + class AAREnemySpawner* SpawnedBy; + +public: + // Sets default values for this character's properties + AARAICharacter(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + + virtual void OnSpawned(class AAREnemySpawner* InSpawnedBy); + + +public: + virtual void Kill(); + // Called every frame + virtual void Tick(float DeltaTime) override; + + // Called to bind functionality to input + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + + + /* IAFAbilityInterface- BEGIN */ + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + virtual class UAFAbilityComponent* GetAbilityComp() override; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + virtual class UAFEffectsComponent* GetEffectsComponent() override; + + virtual class UAFEffectsComponent* NativeGetEffectsComponent() const override; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + virtual float GetAttributeValue(FGAAttribute AttributeIn) const override; + + virtual void ModifyAttribute(FGAEffectMod& ModIn, const FGAEffectHandle& HandleIn, + struct FGAEffectProperty& InProperty, const FGAEffectContext& InContext) override; + virtual FAFAttributeBase* GetAttribute(FGAAttribute AttributeIn) override; + virtual void RemoveBonus(FGAAttribute AttributeIn, const FGAEffectHandle& HandleIn, EGAAttributeMod InMod) override; + + virtual float NativeGetAttributeValue(const FGAAttribute AttributeIn) const override; + + + /* IAFAbilityInterface- END */ +}; diff --git a/Source/ActionRPGGame/Public/AI/ARAIController.h b/Source/ActionRPGGame/Public/AI/ARAIController.h new file mode 100644 index 0000000..44c9882 --- /dev/null +++ b/Source/ActionRPGGame/Public/AI/ARAIController.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "AIController.h" +#include "ARAIController.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API AARAIController : public AAIController +{ + GENERATED_BODY() + + + + +}; diff --git a/Source/ActionRPGGame/Public/ARCharacter.h b/Source/ActionRPGGame/Public/ARCharacter.h new file mode 100644 index 0000000..9185fa3 --- /dev/null +++ b/Source/ActionRPGGame/Public/ARCharacter.h @@ -0,0 +1,277 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Character.h" +#include "Components/ChildActorComponent.h" +#include "GameplayTags.h" +#include "AFEffectsComponent.h" +#include "AFAbilityComponent.h" +#include "AFAbilityInterface.h" +#include "OrionInterface.h" +#include "OrionAnimComponent.h" +#include "IFInventoryInterface.h" +#include "Weapons/ARWeaponInventoryComponent.h" + +#include "OrionAnimComponent.h" + +#include "ARCharacter.generated.h" +USTRUCT(BlueprintType) +struct FARCameraTransform +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintReadOnly) + FVector ForwardVector; + UPROPERTY(BlueprintReadOnly) + FVector Location; +}; +struct WeaponSocket +{ + static const FName HolsteredRightWeapon; + static const FName HolsteredLeftWeapon; + + static const FName EquipedMainWeapon; +}; + +UENUM(BlueprintType) +enum class AbilityInput : uint8 +{ + Shoot = 0, + Reload = 1, + NextWeapon = 2, + PreviousWeapon = 3, + NextAbilitySet = 4, + PreviousAbilitySet = 5, + Ability01 = 6, + Ability02 = 7, + Ability03 = 8, + Ability04 = 9 +}; + +UCLASS(config=Game) +class AARCharacter : public ACharacter, public IAFAbilityInterface, public IOrionInterface, public IIFInventoryInterface +{ + GENERATED_BODY() + + /** Camera boom positioning the camera behind the character */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + class USpringArmComponent* CameraBoom; + + /** Follow camera */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + class UCameraComponent* FollowCamera; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + class UAFAbilityComponent* Abilities; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + class UAFEffectsComponent* EffectsComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + UOrionAnimComponent* OrionAnimComp; +public: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + class UARWeaponInventoryComponent* WeaponInventory; + +protected: + UPROPERTY(EditAnywhere, Category = "Default Abilities") + TArray AbilitiesToGive; + + //Character parts: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Parts", meta = (AllowPrivateAccess = "true")) + USkeletalMeshComponent* Head; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Parts", meta = (AllowPrivateAccess = "true")) + USkeletalMeshComponent* Shoulders; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Parts", meta = (AllowPrivateAccess = "true")) + USkeletalMeshComponent* Arms; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Parts", meta = (AllowPrivateAccess = "true")) + USkeletalMeshComponent* Hands; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Parts", meta = (AllowPrivateAccess = "true")) + USkeletalMeshComponent* Torso; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Parts", meta = (AllowPrivateAccess = "true")) + USkeletalMeshComponent* Legs; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Parts", meta = (AllowPrivateAccess = "true")) + USkeletalMeshComponent* Feets; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Parts", meta = (AllowPrivateAccess = "true")) + USkeletalMeshComponent* Backpack; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character Parts", meta = (AllowPrivateAccess = "true")) + USkeletalMeshComponent* LegsCloth; + + + //Weapons + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Weapons", meta = (AllowPrivateAccess = "true")) + UChildActorComponent* WeaponHolsteredRight; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Weapons", meta = (AllowPrivateAccess = "true")) + UChildActorComponent* WeaponHolsteredLeft; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Weapons", meta = (AllowPrivateAccess = "true")) + UChildActorComponent* HolsteredBackDown; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Weapons", meta = (AllowPrivateAccess = "true")) + UChildActorComponent* WeaponHolsteredSideLeft; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Weapons", meta = (AllowPrivateAccess = "true")) + UChildActorComponent* WeaponEquipedMain; +public: + UPROPERTY(BlueprintReadOnly, Replicated, Category = "Player Character Camera") + FARCameraTransform CameraTransform; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Test Ability") + TSoftClassPtr TestAbility01; + UPROPERTY(Transient) + FAFAbilitySpecHandle TestAbility01Handle; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Test Ability") + TSoftClassPtr TestAbility02; + UPROPERTY(Transient) + FAFAbilitySpecHandle TestAbility02Handle; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Test Ability") + TSoftClassPtr TestAbility03; + UPROPERTY(Transient) + FAFAbilitySpecHandle TestAbility03Handle; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Test Ability") + TSoftClassPtr TestAbility04; + UPROPERTY(Transient) + FAFAbilitySpecHandle TestAbility04Handle; +public: + AARCharacter(const FObjectInitializer& ObjectInitializer); + virtual void OnConstruction(const FTransform& Transform) override; + virtual void PostInitializeComponents() override; + + virtual void BeginPlay() override; + virtual void Tick(float DeltaSeconds) override; + + void OnAbility01Ready(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle); + void OnAbility02Ready(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle); + void OnAbility03Ready(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle); + void OnAbility04Ready(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle); + + /** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera) + float BaseTurnRate; + + /** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera) + float BaseLookUpRate; + +protected: + + /** Called for forwards/backward input */ + void MoveForward(float Value); + + /** Called for side to side input */ + void MoveRight(float Value); + + /** + * Called via input to turn at a given rate. + * @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate + */ + void TurnAtRate(float Rate); + + /** + * Called via input to turn look up/down at a given rate. + * @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate + */ + void LookUpAtRate(float Rate); + +protected: + // APawn interface + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + // End of APawn interface +public: + /** Returns CameraBoom subobject **/ + FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; } + /** Returns FollowCamera subobject **/ + FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; } + + /* IAFAbilityInterface- BEGIN */ + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + virtual class UAFAbilityComponent* GetAbilityComp() override; + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + virtual class UAFEffectsComponent* GetEffectsComponent() override; + virtual class UAFEffectsComponent* NativeGetEffectsComponent() const override; + + UFUNCTION(BlueprintCallable, Category = "AbilityFramework|Attributes") + virtual float GetAttributeValue(FGAAttribute AttributeIn) const override; + + virtual void ModifyAttribute(FGAEffectMod& ModIn, const FGAEffectHandle& HandleIn, + struct FGAEffectProperty& InProperty, const FGAEffectContext& InContext) override; + virtual FAFAttributeBase* GetAttribute(FGAAttribute AttributeIn) override; + virtual void RemoveBonus(FGAAttribute AttributeIn, const FGAEffectHandle& HandleIn, EGAAttributeMod InMod) override; + + virtual float NativeGetAttributeValue(const FGAAttribute AttributeIn) const override; + /* IAFAbilityInterface- END */ + + void OnCameraTransformUpdate(USceneComponent* UpdatedComponent, EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport); + + inline UChildActorComponent* GetHolsteredRightWeapon() + { + return WeaponHolsteredRight; + } + inline UChildActorComponent* GetHolsteredLeftWeapon() + { + return WeaponHolsteredLeft; + } + inline UChildActorComponent* GetHolsteredBackDownWeapon() + { + return HolsteredBackDown; + } + inline UChildActorComponent* GetHolsteredSideLeftWeapon() + { + return WeaponHolsteredSideLeft; + } + + inline UChildActorComponent* GetEquipedMainWeapon() const + { + return WeaponEquipedMain; + } + + template + T* GetMainWeapon() const + { + return Cast(GetEquipedMainWeapon()->GetChildActor()); + } + + UFUNCTION(BlueprintPure, Category = "Character | Weapons") + class AARWeaponBase* GetMainWeapon() const; + + UFUNCTION(BlueprintPure, Category = "Character | Weapons") + USkeletalMeshComponent* GetMainWeaponMesh() const; + + UFUNCTION(BlueprintPure, Category = "Character | Weapons") + FVector GetMainWeaponSocket(const FName& Socket) const; + + virtual void PossessedBy(AController* NewController) override; + + UFUNCTION(Client, Reliable) + void ClientPossesedBy(AController* NewController); + void ClientPossesedBy_Implementation(AController* NewController); + + virtual void OnRep_Controller() override; + + /* IIFInventoryInterface */ + virtual void OnInventoryReplicated(class UIFInventoryComponent* Inventory) override; + /* IIFInventoryInterface */ + + + + UFUNCTION(BlueprintCallable, Category = "ActionRPGGame") + void CalculateSpatialGrid(); + + struct FPostResult + { + TArray Data; + }; + TFuture Result; + TFunction SpatialComplete(); +}; + diff --git a/Source/ActionRPGGame/Public/ARCharacterMovementComponent.h b/Source/ActionRPGGame/Public/ARCharacterMovementComponent.h new file mode 100644 index 0000000..e6f4c3f --- /dev/null +++ b/Source/ActionRPGGame/Public/ARCharacterMovementComponent.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/CharacterMovementComponent.h" +#include "ARCharacterMovementComponent.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARCharacterMovementComponent : public UCharacterMovementComponent +{ + GENERATED_BODY() + +}; diff --git a/Source/ActionRPGGame/Public/AREnemySpawner.h b/Source/ActionRPGGame/Public/AREnemySpawner.h new file mode 100644 index 0000000..835c4c2 --- /dev/null +++ b/Source/ActionRPGGame/Public/AREnemySpawner.h @@ -0,0 +1,55 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "AREnemySpawner.generated.h" + +UCLASS() +class ACTIONRPGGAME_API AAREnemySpawner : public AActor +{ + GENERATED_BODY() +protected: + UPROPERTY(EditAnywhere, Category = "Enemy") + TSubclassOf EnemyClass; + UPROPERTY(EditAnywhere, Category = "Enemy") + int32 MaxSpawned; + UPROPERTY(EditAnywhere, Category = "Enemy") + int32 BatchSpawn; + UPROPERTY(EditAnywhere, Category = "Enemy") + float TimeBetweenSpawns; + + UPROPERTY(EditAnywhere, meta = (MakeEditWidget), Category = "Enemy") + TArray SpawnPositions; + + /* + If enemy count reaches this number start respawning. + */ + UPROPERTY(EditAnywhere, Category = "Enemy") + int32 MinRespawn; + + TSet SpawnedEnemies; + + FTimerHandle SpawnerHandle; + +public: + // Sets default values for this actor's properties + AAREnemySpawner(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + + void SetupSpawner(); + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + void OnEnemyKilled(AARAICharacter* InEnemy); + + UFUNCTION() + void HandleSpawn(); + +}; diff --git a/Source/ActionRPGGame/Public/ARGameInstance.h b/Source/ActionRPGGame/Public/ARGameInstance.h new file mode 100644 index 0000000..9968b9d --- /dev/null +++ b/Source/ActionRPGGame/Public/ARGameInstance.h @@ -0,0 +1,67 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/GameInstance.h" + +#include "ARGameInstance.generated.h" +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FAROnConnectedToGS); +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FARLoginAttemptEvent); + +/** + * + */ +UCLASS(Config=ARGame) +class ACTIONRPGGAME_API UARGameInstance : public UGameInstance +{ + GENERATED_BODY() +protected: + UPROPERTY(Config) + FString GSKey; + UPROPERTY(Config) + FString GSSecret; +public: + UPROPERTY(BlueprintReadOnly, BlueprintAssignable) + FAROnConnectedToGS OnConnectedToGameSparks; + + UPROPERTY(BlueprintReadOnly, BlueprintAssignable) + FARLoginAttemptEvent OnLoginSuccess; + + UPROPERTY(BlueprintReadOnly, BlueprintAssignable) + FARLoginAttemptEvent OnLoginFailed; +public: + UARGameInstance(const FObjectInitializer& ObjectInitializer); + + void AttemptLogin(const FString& UserName, const FString& Password); + void RegisterNewPlayer(const FString& UserName, const FString& DisplayName, const FString& Password); + //Function used to determine what happens if GameSparks connects or fails to (Needs to be UFUNCTION) + UFUNCTION() + void OnGameSparksAvailable(bool bAvailable); + + + virtual void Init() override; +#if WITH_EDITOR + + /* Called to actually start the game when doing Play/Simulate In Editor */ + virtual FGameInstancePIEResult StartPlayInEditorGameInstance(ULocalPlayer* LocalPlayer, const FGameInstancePIEParameters& Params) override; + +#endif + + UFUNCTION(BlueprintCallable, Category = "GameLift|Test") + void ConnectToHub(); + UFUNCTION(BlueprintCallable, Category = "GameLift|Test") + void ConnectToWorld(); + + + UFUNCTION(BlueprintCallable, Category = "GameLift|Test") + void TestGSRequest(); + +protected: +#if WITH_AGONES + FTimerHandle HealthCheckHandle; +#endif + UFUNCTION() + void HealthCheck(); + +}; diff --git a/Source/ActionRPGGame/ARGameMode.h b/Source/ActionRPGGame/Public/ARGameMode.h similarity index 57% rename from Source/ActionRPGGame/ARGameMode.h rename to Source/ActionRPGGame/Public/ARGameMode.h index 46e5fe9..410fc14 100644 --- a/Source/ActionRPGGame/ARGameMode.h +++ b/Source/ActionRPGGame/Public/ARGameMode.h @@ -1,7 +1,6 @@ // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. #pragma once - #include "CoreMinimal.h" #include "GameFramework/GameModeBase.h" #include "ARGameMode.generated.h" @@ -13,6 +12,10 @@ class AARGameMode : public AGameModeBase public: AARGameMode(); + + virtual void BeginPlay() override; + + virtual FString InitNewPlayer(APlayerController* NewPlayerController, const FUniqueNetIdRepl& UniqueId, const FString& Options, const FString& Portal = TEXT("")) override; }; diff --git a/Source/ActionRPGGame/Public/ARGameSession.h b/Source/ActionRPGGame/Public/ARGameSession.h new file mode 100644 index 0000000..3851601 --- /dev/null +++ b/Source/ActionRPGGame/Public/ARGameSession.h @@ -0,0 +1,21 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameSession.h" + +#include "ARGameSession.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API AARGameSession : public AGameSession +{ + GENERATED_BODY() + + virtual FString ApproveLogin(const FString& Options) override; + virtual void UnregisterPlayer(const APlayerController* ExitingPlayer) override; + +}; diff --git a/Source/ActionRPGGame/Public/ARGameStateBase.h b/Source/ActionRPGGame/Public/ARGameStateBase.h new file mode 100644 index 0000000..f628bbc --- /dev/null +++ b/Source/ActionRPGGame/Public/ARGameStateBase.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameStateBase.h" +#include "ARGameStateBase.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API AARGameStateBase : public AGameStateBase +{ + GENERATED_BODY() + + + + +}; diff --git a/Source/ActionRPGGame/Public/ARGlobals.h b/Source/ActionRPGGame/Public/ARGlobals.h new file mode 100644 index 0000000..56db515 --- /dev/null +++ b/Source/ActionRPGGame/Public/ARGlobals.h @@ -0,0 +1,36 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "AssetRegistryModule.h" +#include "Engine/AssetManager.h" +#include "GameplayTags.h" + +/** + * + */ +class ACTIONRPGGAME_API FARGlobals +{ +public: + FARGlobals(); + ~FARGlobals(); + static FPrimaryAssetId MakeAbilityAssetId(const FAssetData& InAssetData) + { + return FPrimaryAssetId(FPrimaryAssetType("Ability"), InAssetData.AssetName); + } + static FAssetData GetAbilityAssetByTag(const FGameplayTag& InTag) + { + FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked("AssetRegistry"); + IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); + + TArray AssetData; + FARFilter Filter; + Filter.TagsAndValues.Add("AbilityTagSearch", InTag.ToString()); + AssetRegistryModule.Get().GetAssets(Filter, AssetData); + if (AssetData.Num() == 1) + return AssetData[0]; + + return FAssetData(); + } +}; diff --git a/Source/ActionRPGGame/Public/ARItemBase.h b/Source/ActionRPGGame/Public/ARItemBase.h new file mode 100644 index 0000000..11f6e26 --- /dev/null +++ b/Source/ActionRPGGame/Public/ARItemBase.h @@ -0,0 +1,85 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "IFItemBase.h" +#include "Effects/GAGameEffect.h" +#include "ARItemBase.generated.h" + + +USTRUCT(BlueprintType) +struct FARPlayerAttributeMod +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Category = "Mod") + FGAAttribute Attribute; + + UPROPERTY(EditAnywhere, Category = "Mod") + float Value; + + UPROPERTY(EditAnywhere, Category = "Mod") + EGAAttributeMod ModType; +}; + +USTRUCT(BlueprintType) +struct FARItemTooltipData +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintReadOnly) + FString Key; + UPROPERTY(BlueprintReadOnly) + FString Value; + + FARItemTooltipData() + {}; + + FARItemTooltipData(const FString& InKey, const FString InValue) + : Key(InKey) + , Value(InValue) + {}; +}; + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARItemBase : public UIFItemBase +{ + GENERATED_BODY() +public: + + /* + Perks (Effects with extensions), to apply to owner of this item. + */ + UPROPERTY(EditAnywhere, Category = "Apply To Player") + TArray> EffectsToApply; + + /* + Attribute modifying effects which will be applied to player. + */ + UPROPERTY(EditAnywhere, Category = "Apply To Player") + TArray AttributesModifiers; + /* + An Template from which attribute effects will be created. + Values from AttributesModifiers property will be used. + */ + UPROPERTY(EditAnywhere, Category = "Apply To Player") + TSubclassOf AttributeEffectClass; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Visual") + UTexture2D* Icon; + /* + Containes upgrades to THIS item. + */ + UPROPERTY(Transient) + FAFEffectContainerSimple UpgradeContainer; + + virtual TArray GetTooltipData() + { + TArray Data; + return Data; + } +}; diff --git a/Source/ActionRPGGame/Public/ARItemPickupBase.h b/Source/ActionRPGGame/Public/ARItemPickupBase.h new file mode 100644 index 0000000..bec8494 --- /dev/null +++ b/Source/ActionRPGGame/Public/ARItemPickupBase.h @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "IFItemActorBase.h" +#include "ARItemPickupBase.generated.h" + +UCLASS() +class ACTIONRPGGAME_API AARItemPickupBase : public AIFItemActorBase +{ + GENERATED_BODY() + + UPROPERTY() + class AARItemSpawnerBase* SpawnedBy; +public: + // Sets default values for this actor's properties + AARItemPickupBase(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + inline void SetSpawnedBy(class AARItemSpawnerBase* InSpawnedBy) { SpawnedBy = InSpawnedBy; } + + + virtual void OnItemPicked() override; +}; diff --git a/Source/ActionRPGGame/Public/ARItemSpawnerBase.h b/Source/ActionRPGGame/Public/ARItemSpawnerBase.h new file mode 100644 index 0000000..9766480 --- /dev/null +++ b/Source/ActionRPGGame/Public/ARItemSpawnerBase.h @@ -0,0 +1,46 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "ARItemSpawnerBase.generated.h" + + +/* + 1. Should only store templates. + 2. Should ask databse about item to spawn. + 3. Should not be placed manually. +*/ +UCLASS() +class ACTIONRPGGAME_API AARItemSpawnerBase : public AActor +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Category = "Items") + TSubclassOf ItemsToSpawn; + + /* + If <= 0, no respawn. Otherwise time after item will be respawned. + */ + UPROPERTY(EditAnywhere, Category = "Items") + float RespawnTime; + + FTimerHandle RespawnHandle; +public: + // Sets default values for this actor's properties + AARItemSpawnerBase(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + void OnItemPicked(); + UFUNCTION() + void HandleRespawn(); + +}; diff --git a/Source/ActionRPGGame/Public/ARMenuPlayerController.h b/Source/ActionRPGGame/Public/ARMenuPlayerController.h new file mode 100644 index 0000000..0939dff --- /dev/null +++ b/Source/ActionRPGGame/Public/ARMenuPlayerController.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerController.h" +#include "ARMenuPlayerController.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API AARMenuPlayerController : public APlayerController +{ + GENERATED_BODY() + + + + +}; diff --git a/Source/ActionRPGGame/Public/ARPlayerController.h b/Source/ActionRPGGame/Public/ARPlayerController.h new file mode 100644 index 0000000..2b1267f --- /dev/null +++ b/Source/ActionRPGGame/Public/ARPlayerController.h @@ -0,0 +1,80 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerController.h" +#include "GameplayTags.h" +#include "IFInventoryComponent.h" +#include "IFInventoryInterface.h" +#include "AFAbilityTypes.h" +#include "ARPlayerController.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API AARPlayerController : public APlayerController, public IIFInventoryInterface +{ + GENERATED_BODY() +public: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components|UI") + class UARUIComponent* UIComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components|UI") + class UIFInventoryComponent* MainInventory; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Input") + FGameplayTag InputNextWeapon; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Input") + TSoftClassPtr AbilitytNextWeapon; + UPROPERTY(Transient) + FAFAbilitySpecHandle InputNextWeaponSpecHandle; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Input") + FGameplayTag InputPreviousWeapon; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Input") + TSoftClassPtr AbilitytPreviousWeapon; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Input") + FGameplayTag InputHolsterWeapon; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Input") + TSoftClassPtr AbilitytHolstersWeapon; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Input") + FGameplayTag InputSetAbilityGroup01; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Input") + TSoftClassPtr SetAbilityGroup01; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Input") + FGameplayTag InputSetAbilityGroup02; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability Input") + TSoftClassPtr SetAbilityGroup02; + + bool bInputBount; + + UPROPERTY() + FString GameLiftId; +public: + AARPlayerController(const FObjectInitializer& ObjectInitializer); + virtual void BeginPlay() override; + virtual void SetPawn(APawn* InPawn) override; + virtual void Possess(APawn* aPawn) override; + void SetupInputComponent(); + + void InputSwitchAbilitySet(); + void InputShowHideAbilityManager(); + void InputShowHideInventory(); + void OnInputAbilityReady(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle); + + UFUNCTION(Client, Reliable) + void ClientPossesed(APawn* InPawn); + void ClientPossesed_Implementation(APawn* InPawn); + + /* IIFInventoryInterface */ + virtual void OnInventoryReplicated(class UIFInventoryComponent* Inventory) override; + /* IIFInventoryInterface */ + + UFUNCTION(BlueprintCallable, Category = "ActionRPGGame|HUD") + float ComputeBoundsScreenSize(UCapsuleComponent* InTarget); +}; diff --git a/Source/ActionRPGGame/Public/ARPlayerStateBase.h b/Source/ActionRPGGame/Public/ARPlayerStateBase.h new file mode 100644 index 0000000..3557415 --- /dev/null +++ b/Source/ActionRPGGame/Public/ARPlayerStateBase.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerState.h" +#include "ARPlayerStateBase.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API AARPlayerStateBase : public APlayerState +{ + GENERATED_BODY() + + + + +}; diff --git a/Source/ActionRPGGame/Public/Abilities/ARAbilityBase.h b/Source/ActionRPGGame/Public/Abilities/ARAbilityBase.h new file mode 100644 index 0000000..164ced0 --- /dev/null +++ b/Source/ActionRPGGame/Public/Abilities/ARAbilityBase.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Abilities/GAAbilityBase.h" +#include "ARAbilityBase.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARAbilityBase : public UGAAbilityBase +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadOnly, Instanced, Category = "UI Config") + class UARAbilityUIData* UIData; + + +}; diff --git a/Source/ActionRPGGame/Public/Abilities/ARAbilityUIData.h b/Source/ActionRPGGame/Public/Abilities/ARAbilityUIData.h new file mode 100644 index 0000000..98b2ecf --- /dev/null +++ b/Source/ActionRPGGame/Public/Abilities/ARAbilityUIData.h @@ -0,0 +1,25 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "ARAbilityUIData.generated.h" + +/** + * + */ +UCLASS(Blueprintable, BlueprintType, EditInLineNew) +class ACTIONRPGGAME_API UARAbilityUIData : public UObject +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, BlueprintReadOnly) + FText DisplayName; + UPROPERTY(EditAnywhere, BlueprintReadOnly) + FText Description; + + UPROPERTY(EditAnywhere, BlueprintReadOnly) + UTexture2D* Icon; + +}; diff --git a/Source/ActionRPGGame/Public/Abilities/ARAvailableAbilities.h b/Source/ActionRPGGame/Public/Abilities/ARAvailableAbilities.h new file mode 100644 index 0000000..59e9d13 --- /dev/null +++ b/Source/ActionRPGGame/Public/Abilities/ARAvailableAbilities.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "GameplayTags.h" +#include "ARAvailableAbilities.generated.h" + +/** + * + */ +UCLASS(Blueprintable, BlueprintType) +class ACTIONRPGGAME_API UARAvailableAbilities : public UObject +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, BlueprintReadOnly) + TArray Abilities; + + +}; diff --git a/Source/ActionRPGGame/Public/ActionRPGGame.h b/Source/ActionRPGGame/Public/ActionRPGGame.h new file mode 100644 index 0000000..2986d44 --- /dev/null +++ b/Source/ActionRPGGame/Public/ActionRPGGame.h @@ -0,0 +1,11 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" + +class FActionRPGGameModule : public FDefaultGameModuleImpl +{ + virtual void StartupModule() override; +}; \ No newline at end of file diff --git a/Source/ActionRPGGame/Public/Attributes/ARAbilityAttributes.h b/Source/ActionRPGGame/Public/Attributes/ARAbilityAttributes.h new file mode 100644 index 0000000..6973f04 --- /dev/null +++ b/Source/ActionRPGGame/Public/Attributes/ARAbilityAttributes.h @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Attributes/GAAttributesBase.h" +#include "ARAbilityAttributes.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARAbilityAttributes : public UGAAttributesBase +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Replicated, Category = "Base") + FAFAttributeBase CastTime; + UPROPERTY(EditAnywhere, Replicated, Category = "Base") + FAFAttributeBase Cooldown; + UPROPERTY(EditAnywhere, Replicated, Category = "Base") + FAFAttributeBase BaseDamage; + + + +}; diff --git a/Source/ActionRPGGame/Public/Attributes/ARCharacterAttributes.h b/Source/ActionRPGGame/Public/Attributes/ARCharacterAttributes.h new file mode 100644 index 0000000..edbf0d0 --- /dev/null +++ b/Source/ActionRPGGame/Public/Attributes/ARCharacterAttributes.h @@ -0,0 +1,45 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Attributes/GAAttributesBase.h" +#include "ARCharacterAttributes.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARCharacterAttributes : public UGAAttributesBase +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, ReplicatedUsing=OnRep_Health, Category = "Base") + FAFAttributeBase Health; + UPROPERTY(EditAnywhere, Replicated, Category = "Base") + FAFAttributeBase Shield; + UPROPERTY(EditAnywhere, Replicated, Category = "Base") + FAFAttributeBase Armor; + UPROPERTY(EditAnywhere, Replicated, Category = "Base") + FAFAttributeBase Energy; + UPROPERTY(EditAnywhere, Replicated, Category = "Base") + FAFAttributeBase Stamina; + + UPROPERTY(EditAnywhere, Replicated, Category = "Base") + FAFAttributeBase Ammo; + UPROPERTY(EditAnywhere, Replicated, Category = "Base") + FAFAttributeBase MachineGunAmmo; + UPROPERTY(EditAnywhere, Category = "Base") + FAFAttributeBase ShotgunAmmo; + UPROPERTY(EditAnywhere, Category = "Base") + FAFAttributeBase ArrowAmmo; +public: + + UARCharacterAttributes(const FObjectInitializer& ObjectInitializer); + + UFUNCTION() + void OnRep_Health(); + + +}; diff --git a/Source/ActionRPGGame/Public/Attributes/ARGunAttributes.h b/Source/ActionRPGGame/Public/Attributes/ARGunAttributes.h new file mode 100644 index 0000000..c82f201 --- /dev/null +++ b/Source/ActionRPGGame/Public/Attributes/ARGunAttributes.h @@ -0,0 +1,67 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Attributes/GAAttributesBase.h" +#include "ARGunAttributes.generated.h" + + +/* + Mirror of Attribute Object to be used inside Items. +*/ +USTRUCT() +struct ACTIONRPGGAME_API FARGunAttributesItem +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase BaseDamage; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase CritChance; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase Magazine; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase RateOfFire; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase ReloadSpeed; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase HorizontalStability; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase VerticalStability; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase Spread; +}; + +/** + * 1. Register FAFReplicationHandle with attribute change. + * 2. If handle is valid then attribute change is also valid (for attribute prediction) + * 3. If valid we don't override with server values. + * 4. Wont work on attributes which can be changed by several sources at the same time like HP. + * This will require custom treatment. + */ +UCLASS() +class ACTIONRPGGAME_API UARGunAttributes : public UGAAttributesBase +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase BaseDamage; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase CritChance; + UPROPERTY(EditAnywhere, SaveGame, ReplicatedUsing=OnRep_Magazine, Category = "Base") + FAFAttributeBase Magazine; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase RateOfFire; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase ReloadSpeed; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase HorizontalStability; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase VerticalStability; + UPROPERTY(EditAnywhere, SaveGame, Category = "Base") + FAFAttributeBase Spread; + + UFUNCTION() + void OnRep_Magazine(FAFAttributeBase OldVal); +}; diff --git a/Source/ActionRPGGame/Public/Attributes/ARHealthExtension.h b/Source/ActionRPGGame/Public/Attributes/ARHealthExtension.h new file mode 100644 index 0000000..57126e9 --- /dev/null +++ b/Source/ActionRPGGame/Public/Attributes/ARHealthExtension.h @@ -0,0 +1,21 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Attributes/GAAttributeExtension.h" +#include "ARHealthExtension.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class ACTIONRPGGAME_API UARHealthExtension : public UGAAttributeExtension +{ + GENERATED_BODY() + + virtual void PreAttributeModify(const FGAEffectContext& InContext, float PreValue) override; + virtual void PostAttributeModify(const FGAEffectContext& InContext, float PreValue, float PostValue) override; + + +}; diff --git a/Source/ActionRPGGame/Public/Calculations/ARAmmoReloadCalculation.h b/Source/ActionRPGGame/Public/Calculations/ARAmmoReloadCalculation.h new file mode 100644 index 0000000..20c13ac --- /dev/null +++ b/Source/ActionRPGGame/Public/Calculations/ARAmmoReloadCalculation.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/GACustomCalculation.h" +#include "ARAmmoReloadCalculation.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARAmmoReloadCalculation : public UGACustomCalculation +{ + GENERATED_BODY() + + + + +}; diff --git a/Source/ActionRPGGame/Public/Equipment/ARCharacterEquipmentComponent.h b/Source/ActionRPGGame/Public/Equipment/ARCharacterEquipmentComponent.h new file mode 100644 index 0000000..2679564 --- /dev/null +++ b/Source/ActionRPGGame/Public/Equipment/ARCharacterEquipmentComponent.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "IFEquipmentComponent.h" +#include "ARCharacterEquipmentComponent.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARCharacterEquipmentComponent : public UIFEquipmentComponent +{ + GENERATED_BODY() + + + + +}; diff --git a/Source/ActionRPGGame/Public/Menu/ARMainMenuView.h b/Source/ActionRPGGame/Public/Menu/ARMainMenuView.h new file mode 100644 index 0000000..84200c8 --- /dev/null +++ b/Source/ActionRPGGame/Public/Menu/ARMainMenuView.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "ARMainMenuView.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARMainMenuView : public UUserWidget +{ + GENERATED_BODY() + + + + +}; diff --git a/Source/ActionRPGGame/Public/Menu/ARMenuGameMode.h b/Source/ActionRPGGame/Public/Menu/ARMenuGameMode.h new file mode 100644 index 0000000..6759159 --- /dev/null +++ b/Source/ActionRPGGame/Public/Menu/ARMenuGameMode.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameModeBase.h" +#include "ARMenuGameMode.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API AARMenuGameMode : public AGameModeBase +{ + GENERATED_BODY() + + + + +}; diff --git a/Source/ActionRPGGame/Public/Menu/ARMenuHUD.h b/Source/ActionRPGGame/Public/Menu/ARMenuHUD.h new file mode 100644 index 0000000..a8bdb6b --- /dev/null +++ b/Source/ActionRPGGame/Public/Menu/ARMenuHUD.h @@ -0,0 +1,47 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/HUD.h" +#include "ARMenuHUD.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API AARMenuHUD : public AHUD +{ + GENERATED_BODY() + +protected: + UPROPERTY(EditAnywhere, Category = "Widgets") + TSubclassOf LoginScreenClass; + UPROPERTY(EditAnywhere, Category = "Widgets") + TSubclassOf MainMenuScreenClass; + UPROPERTY(EditAnywhere, Category = "Widgets") + TSubclassOf RegisterViewClass; + + UPROPERTY(BlueprintReadOnly) + class UARLoginScreenView* LoginScreen; + + UPROPERTY(BlueprintReadOnly) + class UARMainMenuView* MainMenuScreen; + + UPROPERTY(BlueprintReadOnly) + class UARRegisterView* RegisterView; + +public: + + inline class UARRegisterView* GetRegisterView() + { + return RegisterView; + } + + virtual void BeginPlay() override; + + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + + UFUNCTION() + void OnLoginSuccess(); +}; diff --git a/Source/ActionRPGGame/Public/Menu/ARRegisterView.h b/Source/ActionRPGGame/Public/Menu/ARRegisterView.h new file mode 100644 index 0000000..ec08a49 --- /dev/null +++ b/Source/ActionRPGGame/Public/Menu/ARRegisterView.h @@ -0,0 +1,47 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" + +#include "Components/EditableTextBox.h" +#include "Components/Button.h" +#include "Components/TextBlock.h" + +#include "ARRegisterView.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARRegisterView : public UUserWidget +{ + GENERATED_BODY() + +public: + virtual void NativeConstruct() override; + +protected: + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UEditableTextBox* UserNameBox; + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UEditableTextBox* DisplayNameBox; + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UEditableTextBox* PasswordBox; + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UButton* RegisterButton; + + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UTextBlock* WarrningText; + + + UFUNCTION() + void OnRegisterClicked(); + + UFUNCTION() + void OnRegisterSuccess(); + + UFUNCTION() + void OnRegisterFailed(); +}; diff --git a/Source/ActionRPGGame/Public/UI/ARHUD.h b/Source/ActionRPGGame/Public/UI/ARHUD.h new file mode 100644 index 0000000..94d1cd6 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/ARHUD.h @@ -0,0 +1,70 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/HUD.h" +#include "ARHUD.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API AARHUD : public AHUD +{ + GENERATED_BODY() +protected: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components|UI") + class UARUIInventoryComponent* UIInventoryComponent; + + UPROPERTY(EditAnywhere, Category = "Enemy Info") + + TSubclassOf HUDEnemyHealthBarClass; + UPROPERTY(EditAnywhere, Category = "Enemy Info") + TEnumAsByte EnemyChannel; + UPROPERTY(EditAnywhere, Category = "Enemy Info") + float DistanceScaleEnemyBar; + + UPROPERTY(BlueprintReadOnly, Category = "Enemy Info") + class UARHUDEnemyHealthBar* HUDEnemyHealthBar; + + UPROPERTY(EditAnywhere, Category = "Floating Combat Text") + TSubclassOf HUDFloatingCombatTextClass; + UPROPERTY(BlueprintReadOnly, Category = "Floating Combat Text") + class UARHUDFloatingCombatText* FloatingCombatText; + UPROPERTY(EditAnywhere, Category = "Floating Combat Text") + float FCTMoveSpeed; + UPROPERTY(EditAnywhere, Category = "Floating Combat Text") + float FCTLifeTime; + UPROPERTY(EditAnywhere, Category = "Floating Combat Text") + FSlateFontInfo FCTFont; + + UPROPERTY() + class AARCharacter* ARCharacter; + UPROPERTY() + class AARPlayerController* ARPC; + + FHitResult EnemyHitResult; +public: + AARHUD(const FObjectInitializer& ObjectInitializer); + + virtual void BeginPlay() override; + + virtual void Tick(float InDeltaTime) override; + + inline UARUIInventoryComponent* GetUIInventory() + { + return UIInventoryComponent; + } + + + void ShowHideInventory(); + +protected: + float ComputeBoundsScreenSize(AActor* InTarget); + void SetEnemyHitResult(); + void UpdateEnemyBarInfo(); + + UFUNCTION() + void OnEnemyDamageCaused(const FAFAttributeChangedData& InMod); +}; diff --git a/Source/ActionRPGGame/Public/UI/ARHUDWidget.h b/Source/ActionRPGGame/Public/UI/ARHUDWidget.h new file mode 100644 index 0000000..2ae7340 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/ARHUDWidget.h @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "Blueprint/WidgetTree.h" +#include "Components/UniformGridPanel.h" + +#include "UI/HUD/ARHUDPlayerInfo.h" +#include "ARHUDWidget.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARHUDWidget : public UUserWidget +{ + GENERATED_BODY() +protected: + + TWeakObjectPtr UIComponent; +public: + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UARHUDPlayerInfo* PlayerInfo; +}; diff --git a/Source/ActionRPGGame/Public/UI/ARUIComponent.h b/Source/ActionRPGGame/Public/UI/ARUIComponent.h new file mode 100644 index 0000000..839e92c --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/ARUIComponent.h @@ -0,0 +1,57 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "ARHUDWidget.h" +#include "SARDrawTestWidget.h" + +#include "IFItemContainerWidget.h" + +#include "ARUIComponent.generated.h" + + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class ACTIONRPGGAME_API UARUIComponent : public UActorComponent +{ + GENERATED_BODY() +protected: + UPROPERTY(EditAnywhere, Category="Cross Hair") + FSlateBrush Brush; + + UPROPERTY(EditAnywhere, Category = "Widgets") + TSubclassOf CrosshairClass; + + UPROPERTY() + UUserWidget* CrosshairWidget; + + UPROPERTY(EditAnywhere, Category = "Widgets") + TSubclassOf HUDWidgetClass; + + + +public: + UPROPERTY(BlueprintReadOnly, Category = "Widgets") + UARHUDWidget* HUDWidget; + + + + TSharedPtr DrawWidget; + TSharedPtr CrosshairWidget2; +public: + // Sets default values for this component's properties + UARUIComponent(); + +protected: + virtual void InitializeComponent() override; + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + void InitializeInventory(); + +}; diff --git a/Source/ActionRPGGame/Public/UI/ARUMGWidgetBase.h b/Source/ActionRPGGame/Public/UI/ARUMGWidgetBase.h new file mode 100644 index 0000000..1b785f6 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/ARUMGWidgetBase.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "ARUMGWidgetBase.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARUMGWidgetBase : public UUserWidget +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintReadOnly) + class UARUIComponent* UIComponent; +public: + virtual void NativePreConstruct() override; + virtual void NativeConstruct() override; + + +}; diff --git a/Source/ActionRPGGame/Public/UI/HUD/ARHUDCrosshair.h b/Source/ActionRPGGame/Public/UI/HUD/ARHUDCrosshair.h new file mode 100644 index 0000000..a7a4093 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/HUD/ARHUDCrosshair.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "UI/ARUMGWidgetBase.h" +#include "ARHUDCrosshair.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARHUDCrosshair : public UARUMGWidgetBase +{ + GENERATED_BODY() +}; diff --git a/Source/ActionRPGGame/Public/UI/HUD/ARHUDCrosshairInfo.h b/Source/ActionRPGGame/Public/UI/HUD/ARHUDCrosshairInfo.h new file mode 100644 index 0000000..46ae60f --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/HUD/ARHUDCrosshairInfo.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "UI/ARUMGWidgetBase.h" +#include "ARHUDCrosshairInfo.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARHUDCrosshairInfo : public UARUMGWidgetBase +{ + GENERATED_BODY() +}; diff --git a/Source/ActionRPGGame/Public/UI/HUD/ARHUDEnemyHealthBar.h b/Source/ActionRPGGame/Public/UI/HUD/ARHUDEnemyHealthBar.h new file mode 100644 index 0000000..d381655 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/HUD/ARHUDEnemyHealthBar.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "Widgets/Text/STextBlock.h" +#include "Widgets/Notifications/SProgressBar.h" +#include "ARHUDEnemyHealthBar.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARHUDEnemyHealthBar : public UUserWidget +{ + GENERATED_BODY() +protected: + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + class UProgressBar* HealthBar; + +public: + void UpdateHealth(float NormalizedHealth); +}; diff --git a/Source/ActionRPGGame/Public/UI/HUD/ARHUDFloatingCombatText.h b/Source/ActionRPGGame/Public/UI/HUD/ARHUDFloatingCombatText.h new file mode 100644 index 0000000..3e50403 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/HUD/ARHUDFloatingCombatText.h @@ -0,0 +1,98 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "Containers/Queue.h" +#include "Widgets/Text/STextBlock.h" +#include "Widgets/Layout/SConstraintCanvas.h" +#include "Widgets/SCanvas.h" +#include "Widgets/SCompoundWidget.h" +#include "Components/TextBlock.h" + +#include "ARHUDFloatingCombatText.generated.h" +UCLASS() +class ACTIONRPGGAME_API UARFCTText : public UUserWidget +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UTextBlock* Text; + + void SetText(const FText& InText) + { + Text->SetText(InText); + } +}; + +class SFCTWidget : public SCompoundWidget +{ + SLATE_BEGIN_ARGS(SFCTWidget) {} + SLATE_END_ARGS() + +public: + FSlateFontInfo Font; + FText Text; + FSlateColor TextColor; +public: + /** Constructs this widget with InArgs */ + void Construct(const FArguments& InArgs); + ~SFCTWidget(); + inline void SetText(const FText& InText) { Text = InText; }; + FSlateFontInfo GetFontInfo() const; + FText GetText() const; +}; + +struct FARHUDFCTUpdate +{ + + TSharedPtr Widget; + + float CurrentTime; + bool bUsed; + FVector2D CurrentPosition; + FVector2D Direction; + SConstraintCanvas::FSlot* Slot; + FARHUDFCTUpdate() + : CurrentTime(0) + , bUsed(false) + , CurrentPosition(FVector2D::ZeroVector) + , Direction(FVector2D::ZeroVector) + {}; +}; + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARHUDFloatingCombatText : public UUserWidget +{ + GENERATED_BODY() + friend class AARHUD; + + UPROPERTY(EditAnywhere) + TSubclassOf UARFCTTextClass; + UPROPERTY() + class AARPlayerController* PC; + + float FCTMoveSpeed; + float FCTLifeTime; + /* Pool of available widgets */ + TQueue UnsedWidgtes; + /* Pool of used Widgets which are updateing. */ + TArray Widgets; + + TSharedPtr Canvas; + + FSlateFontInfo Font; + + +public: + void Init(int32 Num); + + void Update(float InDeltaTime); + + void SetInfo(float InDamage, FVector2D ScreenPosition, FLinearColor TextColor = FLinearColor::White); + +}; diff --git a/Source/ActionRPGGame/Public/UI/HUD/ARHUDPlayerInfo.h b/Source/ActionRPGGame/Public/UI/HUD/ARHUDPlayerInfo.h new file mode 100644 index 0000000..3a28112 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/HUD/ARHUDPlayerInfo.h @@ -0,0 +1,52 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "Components/ProgressBar.h" + +#include "UI/ARUMGWidgetBase.h" +#include "ARHUDPlayerInfo.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARHUDPlayerInfo : public UARUMGWidgetBase +{ + GENERATED_BODY() +protected: + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UProgressBar* PlayerHealth; + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UProgressBar* PlayerStamina; + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UProgressBar* PlayerEnergy; +public: + //UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + // UARAbilitySlotWidget* AbilityGroup001Slot001; + //UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + // UARAbilitySlotWidget* AbilityGroup001Slot002; + //UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + // UARAbilitySlotWidget* AbilityGroup001Slot003; + + //UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + // UARAbilitySlotWidget* AbilityGroup002Slot001; + //UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + // UARAbilitySlotWidget* AbilityGroup002Slot002; + //UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + // UARAbilitySlotWidget* AbilityGroup002Slot003; + + //UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + // UARWeaponSlotWidget* Weapon001; + //UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + // UARWeaponSlotWidget* Weapon002; + //UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + // UARWeaponSlotWidget* Weapon003; + //UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + // UARWeaponSlotWidget* Weapon004; + + virtual void NativePreConstruct() override; + virtual void NativeConstruct() override; +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/ARInventoryScreenWidget.h b/Source/ActionRPGGame/Public/UI/Inventory/ARInventoryScreenWidget.h new file mode 100644 index 0000000..62b4aef --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/ARInventoryScreenWidget.h @@ -0,0 +1,132 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UI/ARUMGWidgetBase.h" + +#include "Components/WrapBox.h" + +#include "IFInventoryComponent.h" +#include "IFItemWidget.h" + +#include "UI/ARUIComponent.h" +#include "ARPlayerController.h" +#include "ARInventoryScreenWidget.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARInventoryScreenWidget : public UARUMGWidgetBase +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintReadOnly, Category = "Widgets", meta = (BindWidget)) + class UARItemWeaponWidget* RightWeaponWidget; + + UPROPERTY(BlueprintReadOnly, Category = "Widgets", meta = (BindWidget)) + class UARItemWeaponWidget* LeftWeaponWidget; + + UPROPERTY(BlueprintReadOnly, Category = "Widgets", meta = (BindWidget)) + class UARItemWeaponWidget* SideWeaponWidget; + + UPROPERTY(BlueprintReadOnly, Category = "Widgets", meta = (BindWidget)) + class UARItemWeaponWidget* BottomBackWeaponWidget; + + UPROPERTY(BlueprintReadOnly, Category = "Widgets", meta = (BindWidget)) + UButton* ModifySelectedWeapon; + + UPROPERTY(BlueprintReadOnly, Category = "Widgets", meta = (BindWidget)) + class UARItemMagazineView* MagazineUpgrade; + + + /* + Contains list of items compatibile with selected slot. + */ + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UWrapBox* SelectedItemsContainer; + + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UWrapBox* WeaponModificationContainer; + + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UTextBlock* SelectedWeapon; + + TWeakObjectPtr Inventory; +public: + virtual void NativeConstruct() override; + + void SetWeaponName(const FString& Name); + + template + void UpdateItemList(const TArray& LocalIdxs, TSubclassOf WidgetClass, class AARPlayerController* PC, class UARItemView* ForSlot) + { + SelectedItemsContainer->ClearChildren(); + + for (uint8 Idx : LocalIdxs) + { + ItemType* Item = PC->MainInventory->GetItem(Idx); + + if (Item) + { + const FIFItemData& Slot = PC->MainInventory->GetSlot(Idx); + WidgetType* ItemWidget = CreateWidget(PC, WidgetClass); + ItemWidget->SetTarget(ForSlot); + ItemWidget->OnSlotCreated(Slot.Index, Slot.Index, Item); + ItemWidget->OnItemChanged(Slot.Index, Slot.Index, Item); + + SelectedItemsContainer->AddChild(ItemWidget); + } + } + } + + template + void AddItems(const TArray& Items, TSubclassOf WidgetClass, class AARPlayerController* PC, class UARItemView* ForSlot) + { + SelectedItemsContainer->ClearChildren(); + + uint8 Idx = 0; + for (ItemType* Item : Items) + { + if (Item) + { + const FIFItemData& Slot = PC->MainInventory->GetSlot(Idx); + WidgetType* ItemWidget = CreateWidget(PC, WidgetClass); + + ItemWidget->SetTarget(ForSlot); + ItemWidget->OnSlotCreated(Slot.Index, Slot.Index, Item); + ItemWidget->OnItemChanged(Slot.Index, Slot.Index, Item); + + SelectedItemsContainer->AddChild(ItemWidget); + } + Idx++; + } + } + + template + void AddWeaponMods(const TArray& Items, TSubclassOf WidgetClass, class AARPlayerController* PC, class UARItemView* ForSlot) + { + WeaponModificationContainer->ClearChildren(); + + for (uint8 Idx : Items) + { + ItemType* Item = PC->MainInventory->GetItem(Idx); + + if (Item) + { + const FIFItemData& Slot = PC->MainInventory->GetSlot(Idx); + WidgetType* ItemWidget = CreateWidget(PC, WidgetClass); + + ItemWidget->OnSlotCreated(Slot.Index, Slot.Index, Item); + ItemWidget->OnItemChanged(Slot.Index, Slot.Index, Item); + + WeaponModificationContainer->AddChild(ItemWidget); + } + } + } + +protected: + UFUNCTION() + void OnModifyWeaponClicked(); +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/ARItemTooltipView.h b/Source/ActionRPGGame/Public/UI/Inventory/ARItemTooltipView.h new file mode 100644 index 0000000..68c941e --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/ARItemTooltipView.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ARItemBase.h" +#include "UI/Inventory/ARItemView.h" +#include "ARItemTooltipView.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARItemTooltipView : public UARItemView +{ + GENERATED_BODY() +public: + UFUNCTION(BlueprintImplementableEvent, Category = "ActionRPGGame|UI") + void OnTooltipCreated(const TArray& OutItems); + + +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/ARItemView.h b/Source/ActionRPGGame/Public/UI/Inventory/ARItemView.h new file mode 100644 index 0000000..b8efd2c --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/ARItemView.h @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "IFItemWidget.h" +#include "ARItemView.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARItemView : public UIFItemWidget +{ + GENERATED_BODY() +public: + TWeakObjectPtr InventoryComponent; + + UPROPERTY(BlueprintReadOnly, Category = "Widgets", meta = (BindWidget)) + UImage* Icon; + +public: + virtual void NativeConstruct() override; + + + +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/ARListItemView.h b/Source/ActionRPGGame/Public/UI/Inventory/ARListItemView.h new file mode 100644 index 0000000..68964df --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/ARListItemView.h @@ -0,0 +1,39 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "IFItemWidget.h" +#include "ARListItemView.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARListItemView : public UIFItemWidget +{ + GENERATED_BODY() + +protected: + TWeakObjectPtr Target; + TWeakObjectPtr InventoryComponent; + + TWeakObjectPtr InvItem; + + UPROPERTY(Transient) + class UARItemTooltipView* ItemTooltip; +public: + virtual void NativeConstruct() override; + + inline void SetTarget(TWeakObjectPtr ForSlot) { Target = ForSlot; } + inline TWeakObjectPtr GetTarget() { return Target; } + + virtual void OnSlotCreated(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item) override; + + virtual void OnItemChanged(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item) override; + + virtual void OnItemRemoved(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* Item) override; + + virtual void NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; + virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override; +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/ARUIInventoryComponent.h b/Source/ActionRPGGame/Public/UI/Inventory/ARUIInventoryComponent.h new file mode 100644 index 0000000..34d050c --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/ARUIInventoryComponent.h @@ -0,0 +1,71 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "ARUIInventoryComponent.generated.h" + + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class ACTIONRPGGAME_API UARUIInventoryComponent : public UActorComponent +{ + GENERATED_BODY() +protected: + UPROPERTY(EditAnywhere, Category = "Views") + TSubclassOf InventoryViewClass; + UPROPERTY(EditAnywhere, Category = "Views") + TSubclassOf ListItemWeaponClass; + + UPROPERTY(EditAnywhere, Category = "Views") + TSubclassOf ListItemMagazinelass; + + UPROPERTY(EditAnywhere, Category = "Views") + TSubclassOf WeaponModificationViewClass; +public: + UPROPERTY(EditAnywhere, Category = "Views") + TSubclassOf WeaponItemTooltipViewClass; +protected: + UPROPERTY(BlueprintReadOnly, Category = "ActionRPGGame|UI|Inventory") + class UARInventoryScreenWidget* InventoryView; + + UPROPERTY(BlueprintReadOnly, Category = "ActionRPGGame|UI|Inventory") + class UARWeaponModificationView* WeaponModificationView; + + /* NetIndex of selected Weapon. */ + UPROPERTY(BlueprintReadOnly, Category = "ActionRPGGame|UI|Inventory") + uint8 SelectedWeapon; + + TWeakObjectPtr ModifiedWeapon; + +public: + // Sets default values for this component's properties + UARUIInventoryComponent(); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + inline UARInventoryScreenWidget* GetInventoryView() { return InventoryView; } + void CreateInventoryView(AARPlayerController* PC); + void ShowHideInventory(); + +public: + void ShowWeaponsForSlot(class UARItemView* ForSlot); + void RemoveWeaponFromSlot(int8 Index); + void AddWeaponToSlot(uint8 TargetNetIndex + , uint8 TargetLocalIndex + , uint8 SourceNetIndex + , uint8 SourceLocalIndex); + + void UnequipWeaponFromSlot(uint8 SourceNetIndex, uint8 SourceLocalIndex); + + void ShowUpgradesForWeapon(class UARItemMagazineView* For); + + void ModifyWeapon(); + void AddMagazineUpgrade(uint8 SourceNetIndex, uint8 SourceLocalIndex); + void RemoveMagazineUpgrade(); +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARItemWeaponWidget.h b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARItemWeaponWidget.h new file mode 100644 index 0000000..0ed1394 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARItemWeaponWidget.h @@ -0,0 +1,40 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UI/Inventory/ARItemView.h" +#include "ARItemWeaponWidget.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARItemWeaponWidget : public UARItemView +{ + GENERATED_BODY() +public: + TWeakObjectPtr InventoryComponent; + TWeakObjectPtr WeaponInventory; + + int8 Index; + + TWeakObjectPtr WeaponItem; + UPROPERTY(Transient) + UARItemTooltipView* WeaponTooltip; +public: + virtual void NativeConstruct() override; +public: + virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent); + virtual void NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent); + virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override; + + virtual FReply NativeOnMouseButtonDoubleClick(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; + + UFUNCTION() + void OnWeaponAdded2(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* InItem); + UFUNCTION() + void OnWeaponUpdated2(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* InItem); + UFUNCTION() + void OnWeaponRemoved2(uint8 InNetIndex, uint8 InLocalIndex, class UIFItemBase* InItem); +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARListItemWeaponWidget.h b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARListItemWeaponWidget.h new file mode 100644 index 0000000..6ecdf88 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARListItemWeaponWidget.h @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UI/Inventory/ARListItemView.h" +#include "ARListItemWeaponWidget.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARListItemWeaponWidget : public UARListItemView +{ + GENERATED_BODY() +public: + virtual FReply NativeOnMouseButtonDoubleClick(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARWeaponContainerWidget.h b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARWeaponContainerWidget.h new file mode 100644 index 0000000..bb9ba22 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARWeaponContainerWidget.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "IFItemContainerWidget.h" +#include "ARWeaponContainerWidget.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARWeaponContainerWidget : public UIFItemContainerWidget +{ + GENERATED_BODY() +public: + void InitializeWeaponItems(class UARUIComponent* UIComponent); + + +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARWeaponModificationView.h b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARWeaponModificationView.h new file mode 100644 index 0000000..6ea9433 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/ARWeaponModificationView.h @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UI/ARUMGWidgetBase.h" +#include "ARWeaponModificationView.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARWeaponModificationView : public UARUMGWidgetBase +{ + GENERATED_BODY() +public: + UPROPERTY(BlueprintReadOnly, Category = "Widgets", meta = (BindWidget)) + class UARItemMagazineView* MagazineUpgrade; + + UPROPERTY(BlueprintReadOnly, Category = "Widgets", meta = (BindWidget)) + class UButton* CloseUpgradeView; + + UPROPERTY(BlueprintReadOnly, Category = "Widgets", meta = (BindWidget)) + class UWrapBox* UpgradeList; + + virtual void NativeConstruct() override; + void StartModifyWeapon(class UARItemWeapon* WeaponItem); + void StopModifyWeapon(); + + UFUNCTION() + void CloseModificationView(); + +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/Weapons/Modifications/ARItemMagazineView.h b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/Modifications/ARItemMagazineView.h new file mode 100644 index 0000000..7054790 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/Modifications/ARItemMagazineView.h @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UI/Inventory/ARItemView.h" +#include "ARItemMagazineView.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARItemMagazineView : public UARItemView +{ + GENERATED_BODY() +public: + virtual void NativeConstruct() override; + + virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; + + virtual FReply NativeOnMouseButtonDoubleClick(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; + + UFUNCTION() + void OnMagazineUpgradeInstalled(class UARItemWeapon* Weapon + , class UARWeaponUpgradeItem* Upgrade + , int8 WeaponIndex); + UFUNCTION() + void OnMagazineUpgradeRemoved(class UARItemWeapon* Weapon + , class UARWeaponUpgradeItem* Upgrade + , int8 WeaponIndex); +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/Weapons/Modifications/ARItemWeaponUpgradeView.h b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/Modifications/ARItemWeaponUpgradeView.h new file mode 100644 index 0000000..cbfc72d --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/Modifications/ARItemWeaponUpgradeView.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UI/Inventory/ARItemView.h" +#include "ARItemWeaponUpgradeView.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARItemWeaponUpgradeView : public UARItemView +{ + GENERATED_BODY() + + + + +}; diff --git a/Source/ActionRPGGame/Public/UI/Inventory/Weapons/Modifications/ARListItemMagazineView.h b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/Modifications/ARListItemMagazineView.h new file mode 100644 index 0000000..e0bc2e3 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Inventory/Weapons/Modifications/ARListItemMagazineView.h @@ -0,0 +1,21 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UI/Inventory/ARListItemView.h" +#include "ARListItemMagazineView.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARListItemMagazineView : public UARListItemView +{ + GENERATED_BODY() + +public: + virtual FReply NativeOnMouseButtonDoubleClick(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; + + +}; diff --git a/Source/ActionRPGGame/Public/UI/Menu/ARLoginScreenView.h b/Source/ActionRPGGame/Public/UI/Menu/ARLoginScreenView.h new file mode 100644 index 0000000..7710ca3 --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/Menu/ARLoginScreenView.h @@ -0,0 +1,49 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + +#include "Components/EditableTextBox.h" +#include "Components/Button.h" +#include "Components/TextBlock.h" +#include "UI/ARUMGWidgetBase.h" +#include "ARLoginScreenView.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARLoginScreenView : public UARUMGWidgetBase +{ + GENERATED_BODY() + +public: + virtual void NativeConstruct() override; + +protected: + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UEditableTextBox* UserNameBox; + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UEditableTextBox* PasswordBox; + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UButton* LoginButton; + + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UButton* RegisterButton; + + UPROPERTY(BlueprintReadOnly, meta = (BindWidget)) + UTextBlock* WarrningText; + + UFUNCTION() + void OnLoginClicked(); + + UFUNCTION() + void OnLoginSuccess(); + + UFUNCTION() + void OnLoginFailed(); + + UFUNCTION() + void OnRegisterClicked(); +}; diff --git a/Source/ActionRPGGame/Public/UI/SARCrosshairBase.h b/Source/ActionRPGGame/Public/UI/SARCrosshairBase.h new file mode 100644 index 0000000..068a0ca --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/SARCrosshairBase.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Widgets/SCompoundWidget.h" + +/** + * + */ +class ACTIONRPGGAME_API SARCrosshairBase : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SARCrosshairBase) + {} + SLATE_END_ARGS() + + /** Constructs this widget with InArgs */ + void Construct(const FArguments& InArgs); +}; diff --git a/Source/ActionRPGGame/Public/UI/SARDrawTestWidget.h b/Source/ActionRPGGame/Public/UI/SARDrawTestWidget.h new file mode 100644 index 0000000..3b2a91a --- /dev/null +++ b/Source/ActionRPGGame/Public/UI/SARDrawTestWidget.h @@ -0,0 +1,35 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Widgets/SCompoundWidget.h" + +/** + * + */ +class ACTIONRPGGAME_API SARDrawTestWidget : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SARDrawTestWidget) + {} + SLATE_END_ARGS() + SARDrawTestWidget(); + float Progress; + float ProgressStep; + FSlateBrush* Brush; + /** Constructs this widget with InArgs */ + void Construct(const FArguments& InArgs); + + virtual int32 OnPaint(const FPaintArgs& Args + , const FGeometry& AllottedGeometry + , const FSlateRect& MyCullingRect + , FSlateWindowElementList& OutDrawElements + , int32 LayerId + , const FWidgetStyle& InWidgetStyle + , bool bParentEnabled) const override; + + virtual void Tick(const FGeometry& AllottedGeometry + , const double InCurrentTime + , const float InDeltaTime) override; +}; diff --git a/Source/ActionRPGGame/Public/Weapons/ARItemWeapon.h b/Source/ActionRPGGame/Public/Weapons/ARItemWeapon.h new file mode 100644 index 0000000..8525dfa --- /dev/null +++ b/Source/ActionRPGGame/Public/Weapons/ARItemWeapon.h @@ -0,0 +1,92 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "Effects/GAGameEffect.h" +#include "ARMagazineUpgradeItem.h" +#include "IFTypes.h" +#include "GameplayTags.h" +#include "ARItemWeapon.generated.h" + +UENUM() +enum class EARWeaponUpgradeType : uint8 +{ + Magazine +}; + +/** + * + */ +UCLASS(Blueprintable, BlueprintType) +class ACTIONRPGGAME_API UARItemWeapon : public UARItemBase +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Category = "Ability") + TSoftClassPtr Ability; + UPROPERTY(EditAnywhere, SaveGame, Category = "Ability") + FARGunAttributesItem GeneratedAttributes; + + UPROPERTY(EditAnywhere, Category = "Visual") + TSoftClassPtr Weapon; + + UPROPERTY(EditAnywhere, Category = "Transforms") + FVector HolsteredPosition; + UPROPERTY(EditAnywhere, Category = "Transforms") + FRotator HolsteredRotation; + + UPROPERTY(EditAnywhere, Category = "Transforms") + FVector EquipedPosition; + UPROPERTY(EditAnywhere, Category = "Transforms") + FRotator EquipedRotation; + + UPROPERTY(BlueprintReadOnly, Transient, Category = "Ability") + UARWeaponAbilityBase* AbilityInstance; + + //possibly replace with struct containing identical fields. + //so it can be easier serialized and saved. + UPROPERTY(BlueprintReadOnly, SaveGame, Category = "Ability") + class UARMagazineUpgradeItem* MagazineModification; + + UPROPERTY(Transient) + float MagazineUpgradeValue; + + UPROPERTY(Transient) + FAFAbilitySpecHandle AbilityHandle; + + UARItemWeapon(); + + void SetAbility(class UARWeaponAbilityBase* InAbility); + + void AddMagazineUpgrade(class UARMagazineUpgradeItem* InMagazineUpgrade); + void OnMagazineUpdateAdded(); + + UARMagazineUpgradeItem* RemoveMagazineUpgrade(); + + bool SpawnAbility(); + + virtual void OnServerItemLoaded() override; + + virtual void OnItemAdded(uint8 InIndex) override; + virtual void OnItemRemoved(uint8 InIndex) override; + + virtual void OnServerItemAdded(uint8 InIndex) override; + virtual void OnServerItemChanged(uint8 InIndex) override; + virtual void OnServerItemRemoved(uint8 InIndex) override; + + virtual void OnItemAddedEquipment(uint8 InIndex) override; + virtual void OnItemChangedEquipment(uint8 InIndex) override; + virtual void OnItemRemovedEquipment(uint8 InIndex) override; + + virtual void OnServerItemAddedEquipment(uint8 InIndex) override; + virtual void OnServerItemChangedEquipment(uint8 InIndex) override; + virtual void OnServerItemRemovedEquipment(uint8 InIndex) override; + + virtual void ClientPostItemDeserializeFromJson(); + + virtual TArray GetTooltipData() override; + +protected: +}; diff --git a/Source/ActionRPGGame/Public/Weapons/ARMagazineUpgradeEffect.h b/Source/ActionRPGGame/Public/Weapons/ARMagazineUpgradeEffect.h new file mode 100644 index 0000000..0416e00 --- /dev/null +++ b/Source/ActionRPGGame/Public/Weapons/ARMagazineUpgradeEffect.h @@ -0,0 +1,20 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Effects/GAGameEffect.h" +#include "ARMagazineUpgradeEffect.generated.h" + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARMagazineUpgradeEffect : public UAFEffectSpecBase +{ + GENERATED_BODY() + + + + +}; diff --git a/Source/ActionRPGGame/Public/Weapons/ARMagazineUpgradeItem.h b/Source/ActionRPGGame/Public/Weapons/ARMagazineUpgradeItem.h new file mode 100644 index 0000000..1916758 --- /dev/null +++ b/Source/ActionRPGGame/Public/Weapons/ARMagazineUpgradeItem.h @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Weapons/ARWeaponUpgradeItem.h" +#include "ARMagazineUpgradeItem.generated.h" + + +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARMagazineUpgradeItem : public UARWeaponUpgradeItem +{ + GENERATED_BODY() +public: + /* + An actual modifier value of this upgrade. + */ + UPROPERTY(EditAnywhere, SaveGame) + float MagazineUpgradeValue; + + UPROPERTY(EditAnywhere) + EGAAttributeMod ModType; + /* + Effect template + */ + UPROPERTY(EditAnywhere) + TSubclassOf UpgradeEffect; +}; diff --git a/Source/ActionRPGGame/Public/Weapons/ARWeaponAbilityBase.h b/Source/ActionRPGGame/Public/Weapons/ARWeaponAbilityBase.h new file mode 100644 index 0000000..4ab038a --- /dev/null +++ b/Source/ActionRPGGame/Public/Weapons/ARWeaponAbilityBase.h @@ -0,0 +1,129 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Abilities/ARAbilityBase.h" +#include "Effects/GAGameEffect.h" +#include "ARWeaponAbilityBase.generated.h" + +class AARWeaponAvatar; +/** + * + */ +UCLASS() +class ACTIONRPGGAME_API UARWeaponAbilityBase : public UARAbilityBase +{ + GENERATED_BODY() +protected: + + /* Amount of ammunition to add to magazine */ + UPROPERTY(EditAnywhere, Category = "Weapon Reload Effects") + FAFPropertytHandle AmmoToAdd; + FGAEffectHandle AmmoToAddHandle; + + /* Amount of ammo to take from owner */ + UPROPERTY(EditAnywhere, Category = "Weapon Reload Effects") + FAFPropertytHandle AmmoToTake; + FGAEffectHandle AmmoToTakeHandle; + + /* + Default damage effects used, when no upgrades are present for this weapon ability. + */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Damage") + TArray DefaultDamageEffects; + + /* + Damage effects which are actually applied by this weapon. + */ + UPROPERTY(BlueprintReadOnly, Category = "Damage") + TArray DamageEffects; + + /* + Handles to currently applied effects. Their order matches effects from DamageEffects array. + */ + TArray AppliedEffectHandles; + + UPROPERTY(BlueprintReadOnly, Category = "ActionRPGGame|Weapon") + class AARWeaponBase* WeaponActor; + + /* + Weapon item to which this abiliy belongs. + */ + UPROPERTY(BlueprintReadOnly, Transient, Category = "ActionRPGGame|Weapon") + class UARItemWeapon* WeaponItem; + + + /* + Upgrades for this ability. + */ + UPROPERTY(Transient) + FAFEffectContainerSimple UpgradeContainer; + + UPROPERTY(Transient) + FAFPropertytHandle MagazineUpgradeProperty; + UPROPERTY(Transient) + FGAEffectHandle MagazineEffectHandle; + UPROPERTY(Transient) + FAFEffectSpecHandle MagazineSpecHandle; + + UPROPERTY(Transient) + FAFPropertytHandle BarrelUpgradeProperty; + UPROPERTY(Transient) + FGAEffectHandle BarrelEffectHandle; + UPROPERTY(Transient) + FAFEffectSpecHandle BarrelSpecHandle; + + UPROPERTY(Transient) + FAFPropertytHandle ScopeUpgradeProperty; + UPROPERTY(Transient) + FGAEffectHandle ScopeEffectHandle; + UPROPERTY(Transient) + FAFEffectSpecHandle ScopeSpecHandle; + +public: + inline void SetWeaponItem(class UARItemWeapon* InItem) + { + WeaponItem = InItem; + }; + + virtual void SetAttributes(UGAAttributesBase* InAttributes) override; + virtual class UGAAttributesBase* GetAttributes() const override; + virtual class UGAAttributesBase* GetAttributes() override; + virtual void OnAbilityInited() override; + virtual void OnAbilityInputReady() override; + virtual void OnAvatarReady() override; + + void ReplaceDamageEffects(const TArray& InEffects); + void AddDamageEffects(const TArray& InEffects); + void ResetDamageEffects(); + + /* + Replaces current DamageEffects with the one provided as Paremeter. + */ + virtual void InstallAmmoType(TSubclassOf AmmoType) {}; + + virtual void InstallAmmoType(TSoftClassPtr AmmoType) {}; + + virtual void InstallMagazineUpgrade(TSubclassOf MagazineUpgrade) {}; + /* + */ + virtual void OnAmmoTypeInstalled(TSubclassOf AmmoType) {}; + + + UFUNCTION(BlueprintCallable, Category = "ActionRPGGame|Weapon") + void ApplyDamageEffect(UObject* Target, FAFFunctionModifier Modifier); + + UFUNCTION(BlueprintCallable, Category = "ActionRPGGame|Weapon") + void ReloadWeapon(); + + void AddMagazineUpgrade(class UARMagazineUpgradeItem* InMagazineUpgrade); + void AddMagazineUpgrade(TSubclassOf InMagazineUpgrade, float UpgradeValue); + void RemoveMagazineUpgrade(); +protected: + void AddUpgrade(FAFPropertytHandle& PropertyHandle + , FGAEffectHandle& EffectHandle + , FAFEffectSpecHandle& SpecHandle + , class AARCharacter* Character + , float UpgradeValue); +}; diff --git a/Source/ActionRPGGame/Public/Weapons/ARWeaponBase.h b/Source/ActionRPGGame/Public/Weapons/ARWeaponBase.h new file mode 100644 index 0000000..d6d4e29 --- /dev/null +++ b/Source/ActionRPGGame/Public/Weapons/ARWeaponBase.h @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "ARWeaponBase.generated.h" + +UCLASS() +class ACTIONRPGGAME_API AARWeaponBase : public AActor +{ + GENERATED_BODY() +private: + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) + class USkeletalMeshComponent* Mesh; +public: + // Sets default values for this actor's properties + AARWeaponBase(); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + + class USkeletalMeshComponent* GetMesh() + { + return Mesh; + } +}; diff --git a/Source/ActionRPGGame/Public/Weapons/ARWeaponInventoryComponent.h b/Source/ActionRPGGame/Public/Weapons/ARWeaponInventoryComponent.h new file mode 100644 index 0000000..2f1e385 --- /dev/null +++ b/Source/ActionRPGGame/Public/Weapons/ARWeaponInventoryComponent.h @@ -0,0 +1,222 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" + +#include "Net/UnrealNetwork.h" +#include "Engine/ActorChannel.h" +#include "IFInventoryComponent.h" +#include "IFEquipmentComponent.h" +#include "Weapons/ARWeaponAbilityBase.h" +#include "ARWeaponInventoryComponent.generated.h" + +USTRUCT() +struct FARWeapon +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Category = "Attachment Test") + TSoftClassPtr Weapon; + UPROPERTY(EditAnywhere, Category = "Attachment Test") + TSubclassOf Item; + + UPROPERTY(EditAnywhere, Category = "Attachment Test") + FName SocketName; + + UPROPERTY(EditAnywhere, Category = "Attachment Test") + FVector Position; + UPROPERTY(EditAnywhere, Category = "Attachment Test") + FRotator Rotation; + UPROPERTY(EditAnywhere, Category = "Attachment Test") + int8 NetIndex; + + UPROPERTY(EditAnywhere, Category = "Attachment Test") + int8 RepCounter; +}; + +UENUM() +enum class EARWeaponPosition +{ + Right= 0, + Left = 1, + BottomBack = 2, + Side = 3, + Equiped = 4 +}; + +USTRUCT() +struct FARWeaponRPC +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Category = "Attachment Test") + FSoftClassPath Weapon; + + UPROPERTY() + uint8 Index; + + UPROPERTY(EditAnywhere, Category = "Attachment Test") + FVector Position; + UPROPERTY(EditAnywhere, Category = "Attachment Test") + FRotator Rotation; + UPROPERTY(EditAnywhere, Category = "Attachment Test") + EARWeaponPosition AttachSlot; +}; + + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FAROnUpgradeInstalled, class UARItemWeapon*, Weapon, class UARWeaponUpgradeItem*, Upgrade, int8, WeaponIndex); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FAROnUpgradeRemoved, class UARItemWeapon*, Weapon, class UARWeaponUpgradeItem*, Upgrade, int8, WeaponIndex); +/* + Manages currently equipped weapons (holstered and unholstered). +*/ +UCLASS( ClassGroup=(Inventory), meta=(BlueprintSpawnableComponent) ) +class ACTIONRPGGAME_API UARWeaponInventoryComponent : public UIFEquipmentComponent +{ + GENERATED_BODY() +protected: + + UPROPERTY() + class APawn* POwner; + + UPROPERTY(EditAnywhere, CAtegory = "Input") + TArray WeaponInput; + + TMap GroupToComponent; + + TArray ClientWeaponAbilities; + TArray ServerWeaponAbilities; + + int8 CurrentWeaponIndex; + + FAROnUpgradeInstalled OnUpgradeInstalled; + FAROnUpgradeRemoved OnUpgradeRemoved; + +public: + // Sets default values for this component's properties + UARWeaponInventoryComponent(); + void BindInputs(UInputComponent* InputComponent, class UAFAbilityComponent* AbilityComponent); +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: + void InitializeWeapons(APawn* Pawn); + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + inline FAROnUpgradeInstalled& GetOnUpgradeInstalled() + { + return OnUpgradeInstalled; + } + inline FAROnUpgradeRemoved& GetOnUpgradeRemoved() + { + return OnUpgradeRemoved; + } + virtual void OnClientPreItemAdded(UIFItemBase* Item, uint8 Index) override; + virtual void OnItemAdded(UIFItemBase* Item, uint8 LocalIndex) override; + UFUNCTION() + void OnAbilityAdded(FAFAbilitySpec Spec, FAFAbilitySpecHandle ServerHandle, FAFAbilitySpecHandle ClientHandle); + virtual void OnItemRemoved(uint8 LocalIndex) override; + + virtual void OnServerItemAdded(UIFItemBase* Item, uint8 LocalIndex) override; + virtual void OnServerItemRemoved(uint8 LocalIndex) override; + + void OnWeaponReady(TSoftClassPtr InAbilityTag, int8 Index); + void SetAbilityToItem(int8 InLocalIndex, class UGAAbilityBase* InAbility); + + UFUNCTION(NetMulticast, Reliable) + void MulticastAddWeapon(const FARWeaponRPC& WeaponData); + void MulticastAddWeapon_Implementation(const FARWeaponRPC& WeaponData); + + UFUNCTION(NetMulticast, Reliable) + void MulticastRemoveWeapon(const FARWeaponRPC& WeaponData); + void MulticastRemoveWeapon_Implementation(const FARWeaponRPC& WeaponData); + + UFUNCTION(NetMulticast, Reliable) + void MulticastEquipWeapon(int8 WeaponIndex, const FARWeaponRPC& WeaponData); + void MulticastEquipWeapon_Implementation(int8 WeaponIndex, const FARWeaponRPC& WeaponData); + + UFUNCTION(NetMulticast, Reliable) + void MulticastUnequipWeapon(int8 OldWeaponIndex, const FARWeaponRPC& WeaponData); + void MulticastUnequipWeapon_Implementation(int8 OldWeaponIndex, const FARWeaponRPC& WeaponData); + + void Equip(int8 WeaponIndex, const FARWeaponRPC& WeaponData); + void Unequip(int8 WeaponIndex); + void Holster(); + + UFUNCTION(Server, Reliable, WithValidation) + void ServerHolster(const FARWeaponRPC& WeaponData); + void ServerHolster_Implementation(const FARWeaponRPC& WeaponData); + bool ServerHolster_Validate(const FARWeaponRPC& WeaponData); + UFUNCTION(NetMulticast, Reliable) + void MulticastHolster(const FARWeaponRPC& WeaponData); + void MulticastHolster_Implementation(const FARWeaponRPC& WeaponData); + + inline void SetPOwner(APawn* InPawn) + { + POwner = InPawn; + } + + UFUNCTION(BlueprintCallable) + void NextWeapon(); + UFUNCTION(BlueprintCallable) + void PreviousWeapon(); + + UFUNCTION(BlueprintCallable) + void HolsterWeapon(); + +protected: + UFUNCTION(Server, Reliable, WithValidation) + void ServerNextWeapon(int8 WeaponIndex); + void ServerNextWeapon_Implementation(int8 WeaponIndex); + bool ServerNextWeapon_Validate(int8 WeaponIndex); + UFUNCTION(Client, Reliable) + void ClientNextWeapon(int8 WeaponIndex, bool bPredictionSuccess); + void ClientNextWeapon_Implementation(int8 WeaponIndex, bool bPredictionSuccess); + + UFUNCTION(Server, Reliable, WithValidation) + void ServerPreviousWeapon(int8 WeaponIndex); + void ServerPreviousWeapon_Implementation(int8 WeaponIndex); + bool ServerPreviousWeapon_Validate(int8 WeaponIndex); + UFUNCTION(Client, Reliable) + void ClientPreviousWeapon(int8 WeaponIndex, bool bPredictionSuccess); + void ClientPreviousWeapon_Implementation(int8 WeaponIndex, bool bPredictionSuccess); + + void HandleClientPrediction(int8 WeaponIndex, bool bPredictionSuccess); + + UARItemWeapon* FindNextValid(); + UARItemWeapon* FindPreviousValid(); + +protected: + void SetWeapon(const FARWeaponRPC& InWeapon, UChildActorComponent* Component); + + UFUNCTION() + void AsynWeaponLoaded(UChildActorComponent* Component, FARWeaponRPC InWeapon); + +public: + //Local Indexes + void AddMagazineMod(int8 WeaponIdx, int8 MagazineModIndex); + UFUNCTION(Server, Reliable, WithValidation) + void ServerAddMagazineMod(int8 WeaponIdx, int8 MagazineModIndex); + + void ServerAddMagazineMod_Implementation(int8 WeaponIdx, int8 MagazineModIndex); + bool ServerAddMagazineMod_Validate(int8 WeaponIdx, int8 MagazineModIndex); + + UFUNCTION(Client, Reliable) + void ClientAddMagazineMod(int8 WeaponIdx, int8 MagazineModIndex); + void ClientAddMagazineMod_Implementation(int8 WeaponIdx, int8 MagazineModIndex); + + void RemoveMagazineMod(int8 WeaponIdx); + UFUNCTION(Server, Reliable, WithValidation) + void ServerRemoveMagazineMod(int8 WeaponIdx); + + void ServerRemoveMagazineMod_Implementation(int8 WeaponIdx); + bool ServerRemoveMagazineMod_Validate(int8 WeaponIdx); + + UFUNCTION(Client, Reliable) + void ClientRemoveMagazineMod(int8 WeaponIdx); + void ClientRemoveMagazineMod_Implementation(int8 WeaponIdx); + +}; diff --git a/Source/ActionRPGGame/Public/Weapons/ARWeaponUpgradeItem.h b/Source/ActionRPGGame/Public/Weapons/ARWeaponUpgradeItem.h new file mode 100644 index 0000000..5d6b536 --- /dev/null +++ b/Source/ActionRPGGame/Public/Weapons/ARWeaponUpgradeItem.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "ARItemBase.h" +#include "ARWeaponUpgradeItem.generated.h" + +/** + * + */ +UCLASS(BlueprintType, Blueprintable) +class ACTIONRPGGAME_API UARWeaponUpgradeItem : public UARItemBase +{ + GENERATED_BODY() +}; diff --git a/Source/ActionRPGGame/Public/Weapons/ARWeaponsTypes.h b/Source/ActionRPGGame/Public/Weapons/ARWeaponsTypes.h new file mode 100644 index 0000000..ca151b1 --- /dev/null +++ b/Source/ActionRPGGame/Public/Weapons/ARWeaponsTypes.h @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "ARWeaponsTypes.generated.h" + +UENUM(BlueprintType) +enum class EARWeaponSlot : uint8 +{ + Slot1 = 0, + Slot2 = 1, + Slot3 = 2, + Slot4 = 3, + + MAX +}; diff --git a/Source/ActionRPGGameClient.Target.cs b/Source/ActionRPGGameClient.Target.cs index fbfd4ca..6e4eedd 100644 --- a/Source/ActionRPGGameClient.Target.cs +++ b/Source/ActionRPGGameClient.Target.cs @@ -1,14 +1,13 @@ -// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; using System.Collections.Generic; public class ActionRPGGameClientTarget : TargetRules { - public ActionRPGGameClientTarget(TargetInfo Target) : base(Target) - { - Type = TargetType.Client; - LaunchModuleName = "ActionRPGGame"; - ExtraModuleNames.Add("ActionRPGGame"); + public ActionRPGGameClientTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Client; + ExtraModuleNames.Add("ActionRPGGame"); } } diff --git a/Source/ActionRPGGameEditor.Target.cs b/Source/ActionRPGGameEditor.Target.cs index 7f23780..86bd66f 100644 --- a/Source/ActionRPGGameEditor.Target.cs +++ b/Source/ActionRPGGameEditor.Target.cs @@ -1,14 +1,14 @@ -// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; using System.Collections.Generic; public class ActionRPGGameEditorTarget : TargetRules { - public ActionRPGGameEditorTarget(TargetInfo Target) : base (Target) + public ActionRPGGameEditorTarget(TargetInfo Target) : base(Target) { - Type = TargetType.Editor; - ExtraModuleNames.Add("ActionRPGGame"); - //ExtraModuleNames.Add("ActionRPGGameEditor"); + Type = TargetType.Editor; + ExtraModuleNames.Add("ActionRPGGame"); + ExtraModuleNames.Add("ActionRPGGameEditor"); } } diff --git a/Source/ActionRPGGameEditor/ActionRPGGameEditor.Build.cs b/Source/ActionRPGGameEditor/ActionRPGGameEditor.Build.cs new file mode 100644 index 0000000..7075209 --- /dev/null +++ b/Source/ActionRPGGameEditor/ActionRPGGameEditor.Build.cs @@ -0,0 +1,37 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; + +public class ActionRPGGameEditor : ModuleRules +{ + public ActionRPGGameEditor(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + PublicDependencyModuleNames.AddRange(new string[] { + "Core", + "CoreUObject", + "Engine", + "InputCore", + "Slate", + "SlateCore", + "UMG", + "GameplayTags", + "AbilityFramework", + "UnrealEd", "SourceControl", "Matinee", "PropertyEditor", "ShaderCore", "AbilityFrameworkEditor" + }); + + PrivateDependencyModuleNames.AddRange(new string[] { "AbilityFrameworkEditor" }); + + } +} diff --git a/Source/ActionRPGGameEditor/ActionRPGGameEditor.cpp b/Source/ActionRPGGameEditor/ActionRPGGameEditor.cpp new file mode 100644 index 0000000..0526ce7 --- /dev/null +++ b/Source/ActionRPGGameEditor/ActionRPGGameEditor.cpp @@ -0,0 +1,14 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "ActionRPGGameEditor.h" +#include "Modules/ModuleManager.h" +#include "Misc/CommandLine.h" +#include "IAbilityFrameworkEditor.h" + +void FActionRPGGameEditorModule::StartupModule() +{ + //FModuleManager::Get().LoadModule("Kismet"); + FModuleManager::LoadModuleChecked(TEXT("AbilityFrameworkEditor")); +}; +IMPLEMENT_PRIMARY_GAME_MODULE(FActionRPGGameEditorModule, ActionRPGGameEditor, "ActionRPGGameEditor"); + \ No newline at end of file diff --git a/Source/ActionRPGGameEditor/ActionRPGGameEditor.h b/Source/ActionRPGGameEditor/ActionRPGGameEditor.h new file mode 100644 index 0000000..aa288ee --- /dev/null +++ b/Source/ActionRPGGameEditor/ActionRPGGameEditor.h @@ -0,0 +1,9 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +class FActionRPGGameEditorModule : public FDefaultGameModuleImpl +{ + virtual void StartupModule() override; +}; \ No newline at end of file diff --git a/Source/ActionRPGGameServer.Target.cs b/Source/ActionRPGGameServer.Target.cs index 81d0745..e951c77 100644 --- a/Source/ActionRPGGameServer.Target.cs +++ b/Source/ActionRPGGameServer.Target.cs @@ -1,4 +1,4 @@ -// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; using System.Collections.Generic; @@ -6,11 +6,9 @@ [SupportedPlatforms(UnrealPlatformClass.Server)] public class ActionRPGGameServerTarget : TargetRules { - public ActionRPGGameServerTarget(TargetInfo Target) : base(Target) - { - Type = TargetType.Server; - //bUsesSlate = false; - LaunchModuleName = "ActionRPGGame"; - ExtraModuleNames.Add("ActionRPGGame"); - } + public ActionRPGGameServerTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Server; + ExtraModuleNames.Add("ActionRPGGame"); + } }