From a8d865d0a40fb01fa94eb387602038f4afc833bc Mon Sep 17 00:00:00 2001 From: nutti Date: Sun, 10 Dec 2023 21:29:33 +0900 Subject: [PATCH] Add: Functional Test --- .circleci/config.yml | 66 -------- .github/workflows/lint.yaml | 32 ++-- .../BlueprintToRSTDoc.Build.cs | 4 +- .../BlueprintToRSTDoc/Private/BPLibrary.cpp | 153 +++++++---------- .../Private/BlueprintToRSTDoc.cpp | 46 ++++- .../BlueprintToRSTDoc/Public/BPLibrary.h | 4 +- .../Source/BlueprintToRSTDoc/Public/Common.h | 6 + .../Source/SampleProject.Target.cs | 9 +- .../SampleProject/SampleProject.Build.cs | 9 +- .../Source/SampleProject/SampleProject.cpp | 9 +- .../Source/SampleProject/SampleProject.h | 9 +- .../Source/SampleProjectEditor.Target.cs | 9 +- .../functional_test/FunctionalTest/.gitignore | 78 +++++++++ .../FunctionalTest/Config/DefaultEditor.ini | 0 .../FunctionalTest/Config/DefaultEngine.ini | 76 +++++++++ .../FunctionalTest/Config/DefaultGame.ini | 3 + .../FunctionalTest/Config/DefaultInput.ini | 85 ++++++++++ .../FunctionalTest/Content/Blank.umap | Bin 0 -> 6332 bytes .../Content/FunctionalTest/TestActor.uasset | Bin 0 -> 47027 bytes .../FunctionalTest/TestEnumeration.uasset | Bin 0 -> 2969 bytes .../FunctionalTest/TestStructure.uasset | Bin 0 -> 5053 bytes .../FunctionalTest/FunctionalTest.uproject | 22 +++ .../Game/FunctionalTest/TestActor.rst | 159 ++++++++++++++++++ .../FunctionalTest/Expected/rst/DocsList.txt | 3 + .../Game/FunctionalTest/TestEnumeration.rst | 17 ++ .../Game/FunctionalTest/TestStructure.rst | 29 ++++ .../Source/FunctionalTest.Target.cs | 22 +++ .../FunctionalTest/FunctionalTest.Build.cs | 31 ++++ .../Source/FunctionalTest/FunctionalTest.cpp | 14 ++ .../Source/FunctionalTest/FunctionalTest.h | 12 ++ .../FunctionalTestAutomationTest.cpp | 82 +++++++++ .../Source/FunctionalTestEditor.Target.cs | 22 +++ 32 files changed, 831 insertions(+), 180 deletions(-) create mode 100644 BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Public/Common.h create mode 100644 tests/functional_test/FunctionalTest/.gitignore create mode 100644 tests/functional_test/FunctionalTest/Config/DefaultEditor.ini create mode 100644 tests/functional_test/FunctionalTest/Config/DefaultEngine.ini create mode 100644 tests/functional_test/FunctionalTest/Config/DefaultGame.ini create mode 100644 tests/functional_test/FunctionalTest/Config/DefaultInput.ini create mode 100644 tests/functional_test/FunctionalTest/Content/Blank.umap create mode 100644 tests/functional_test/FunctionalTest/Content/FunctionalTest/TestActor.uasset create mode 100644 tests/functional_test/FunctionalTest/Content/FunctionalTest/TestEnumeration.uasset create mode 100644 tests/functional_test/FunctionalTest/Content/FunctionalTest/TestStructure.uasset create mode 100644 tests/functional_test/FunctionalTest/FunctionalTest.uproject create mode 100644 tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Blueprint/Game/FunctionalTest/TestActor.rst create mode 100644 tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/DocsList.txt create mode 100644 tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Enum/Game/FunctionalTest/TestEnumeration.rst create mode 100644 tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Struct/Game/FunctionalTest/TestStructure.rst create mode 100644 tests/functional_test/FunctionalTest/Source/FunctionalTest.Target.cs create mode 100644 tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.Build.cs create mode 100644 tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.cpp create mode 100644 tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.h create mode 100644 tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTestAutomationTest.cpp create mode 100644 tests/functional_test/FunctionalTest/Source/FunctionalTestEditor.Target.cs diff --git a/.circleci/config.yml b/.circleci/config.yml index 477b61c..0f4f323 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,13 +4,6 @@ workflows: version: 2.1 build: jobs: - # - functional-test-plugin: - # context: - # - unreal-engine-ci - # matrix: - # parameters: - # unreal-engine-version: ["5.3.0"] - # version: ["full"] - build-plugin: context: - unreal-engine-ci @@ -30,65 +23,6 @@ workflows: version: 2.1 jobs: - # functional-test-plugin: - # parameters: - # unreal-engine-version: - # type: string - # version: - # type: string - # docker: - # - image: ghcr.io/epicgames/unreal-engine:dev-slim-<< parameters.unreal-engine-version >> - # auth: - # username: $GHCR_USERNAME - # password: $GHCR_PASSWORD - # steps: - # - checkout - # - run: - # name: Run scripts for the license removing - # command: bash tools/remove_license.sh BlueprintToRSTDoc << parameters.version >> - # - run: - # name: Run scripts for the code removing - # command: bash tools/remove_code.sh BlueprintToRSTDoc << parameters.unreal-engine-version >> << parameters.version >> . - # - run: - # name: "Run scripts for the release" - # command: bash tools/replace_engine_version.sh BlueprintToRSTDoc << parameters.unreal-engine-version >> - # - run: - # name: "Copy plugin" - # command: | - # mkdir ${PWD}/tests/functional_test/FunctionalTest/Plugins - # cp -r BlueprintToRSTDoc ${PWD}/tests/functional_test/FunctionalTest/Plugins - # - run: - # name: "Build project" - # command: | - # /home/ue4/UnrealEngine/Engine/Build/BatchFiles/RunUAT.sh BuildCookRun \ - # -utf8output \ - # -platform=Linux \ - # -clientconfig=Shipping \ - # -serverconfig=Shipping \ - # -project=${PWD}/tests/functional_test/FunctionalTest/FunctionalTest.uproject \ - # -noP4 \ - # -nodebuginfo \ - # -allmaps \ - # -cook \ - # -build \ - # -stage \ - # -prereqs \ - # -pak \ - # -archive \ - # -archivedirectory=/tmp/Packaged - # - run: - # name: "Functional test against Plugin" - # command: | - # /home/ue4/UnrealEngine/Engine/Binaries/Linux/UnrealEditor \ - # ${PWD}/tests/functional_test/FunctionalTest/FunctionalTest.uproject \ - # -unattended \ - # -nopause \ - # -NullRHI \ - # -ExecCmds="Automation RunTests BlueprintToRSTDoc; Quit" \ - # -testexit="Automation Test Queue Empty" \ - # -log=RunTests.log \ - # -ReportOutputPath="/tmp/FunctionalTestsReport" - build-plugin: parameters: unreal-engine-version: diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 4b01764..6998399 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -47,22 +47,22 @@ jobs: run: | bash tests/lint/clang-format/run.sh samples/SampleProject - # functional-test-clang-format: - # name: functional-test-clang-format - # runs-on: ubuntu-latest - # container: - # image: ubuntu:20.04 - # steps: - # - name: Checkout repo - # uses: actions/checkout@v2 - - # - name: Install clang-format - # run: | - # apt update - # apt install -y clang-format - # - name: clang-format - # run: | - # bash tests/lint/clang-format/run.sh tests/functional_test/FunctionalTest + functional-test-clang-format: + name: functional-test-clang-format + runs-on: ubuntu-latest + container: + image: ubuntu:20.04 + steps: + - name: Checkout repo + uses: actions/checkout@v2 + + - name: Install clang-format + run: | + apt update + apt install -y clang-format + - name: clang-format + run: | + bash tests/lint/clang-format/run.sh tests/functional_test/FunctionalTest markdownlint: name: markdownlint diff --git a/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/BlueprintToRSTDoc.Build.cs b/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/BlueprintToRSTDoc.Build.cs index 87fe74b..46f656a 100644 --- a/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/BlueprintToRSTDoc.Build.cs +++ b/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/BlueprintToRSTDoc.Build.cs @@ -11,8 +11,8 @@ public BlueprintToRSTDoc(ReadOnlyTargetRules Target) : base(Target) PublicIncludePaths.AddRange(new string[]{}); PrivateIncludePaths.AddRange(new string[]{"BlueprintToRSTDoc/Public"}); PublicDependencyModuleNames.AddRange(new string[]{"Core"}); - PrivateDependencyModuleNames.AddRange( - new string[]{"Projects", "CoreUObject", "Engine", "Slate", "SlateCore", "BlueprintGraph", "ToolMenus", "Kismet", "DesktopPlatform", "InputCore"}); + PrivateDependencyModuleNames.AddRange(new string[]{"Projects", "CoreUObject", "Engine", "Slate", "SlateCore", + "BlueprintGraph", "ToolMenus", "Kismet", "DesktopPlatform", "InputCore"}); DynamicallyLoadedModuleNames.AddRange(new string[]{}); } } diff --git a/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Private/BPLibrary.cpp b/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Private/BPLibrary.cpp index c1baee6..e3d8402 100644 --- a/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Private/BPLibrary.cpp +++ b/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Private/BPLibrary.cpp @@ -1,20 +1,15 @@ #include "BPLibrary.h" #include "AssetRegistry/AssetRegistryModule.h" -#include "DesktopPlatformModule.h" +#include "Common.h" #include "EdGraphSchema_K2.h" #include "Engine/UserDefinedEnum.h" #include "Engine/UserDefinedStruct.h" #include "GenericPlatform/GenericPlatformFile.h" #include "HAL/FileManagerGeneric.h" -#include "IDesktopPlatform.h" +#include "Misc/EngineVersionComparison.h" #include "Settings.h" -#define ERROR_MESSAGE_BOX(Message) \ - FPlatformMisc::MessageBoxExt(EAppMsgType::Ok, \ - *FString::Format(TEXT("Error:\n\n{0}\n\n---\n\n{1} (Line:{2})"), {Message, *FString(__FILE__), __LINE__}), \ - TEXT("BlueprintToRSTDoc")); - void ConvertBPNameToCPPName(FString& Out, const FString& Type) { Out = Type; @@ -454,24 +449,7 @@ bool ParseProperty(FRSTDocProperty& Out, FProperty* Property, bool bIsBlueprint return true; } -bool OpenOutputDirectory(FString& OutDirectory) -{ - void* ParentWindowPtr = FSlateApplication::Get().GetActiveTopLevelWindow()->GetNativeWindow()->GetOSWindowHandle(); - IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); - if (!DesktopPlatform) - { - ERROR_MESSAGE_BOX(TEXT("Failed to get DesktopPlatform.\n")); - return false; - } - if (!DesktopPlatform->OpenDirectoryDialog(ParentWindowPtr, TEXT("Save RST Documents To"), TEXT(""), OutDirectory)) - { - return false; - } - - return true; -} - -bool GetBlueprintAssets(TArray& Blueprints, const UBlueprintToRSTDocSettings& Settings) +bool GetBlueprintAssets(TArray& Blueprints, const TArray& ExcludePaths, FString& ErrorMessage) { FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(FName("AssetRegistry")); IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); @@ -484,7 +462,7 @@ bool GetBlueprintAssets(TArray& Blueprints, const UBlueprintToRSTDoc if (!AssetRegistry.GetAssets(Filter, Blueprints)) { - ERROR_MESSAGE_BOX(TEXT("Failed to get assets of 'UBlueprint'.")); + ErrorMessage = TEXT("Failed to get assets of 'UBlueprint'."); return false; } @@ -493,7 +471,7 @@ bool GetBlueprintAssets(TArray& Blueprints, const UBlueprintToRSTDoc for (auto& BP : Blueprints) { bool bFound = false; - for (auto& Path : Settings.ExcludePaths) + for (auto& Path : ExcludePaths) { if (BP.PackagePath.ToString().Find(Path) != -1) { @@ -514,7 +492,7 @@ bool GetBlueprintAssets(TArray& Blueprints, const UBlueprintToRSTDoc return true; } -bool GetStructureAssets(TArray& ScriptStructs, const UBlueprintToRSTDocSettings& Settings) +bool GetStructureAssets(TArray& ScriptStructs, const TArray& ExcludePaths, FString& ErrorMessage) { FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(FName("AssetRegistry")); IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); @@ -527,7 +505,7 @@ bool GetStructureAssets(TArray& ScriptStructs, const UBlueprintToRST if (!AssetRegistry.GetAssets(Filter, ScriptStructs)) { - ERROR_MESSAGE_BOX(TEXT("Failed to get assets of 'UUserDefinedStruct'.")); + ErrorMessage = TEXT("Failed to get assets of 'UUserDefinedStruct'."); return false; } @@ -536,7 +514,7 @@ bool GetStructureAssets(TArray& ScriptStructs, const UBlueprintToRST for (auto& S : ScriptStructs) { bool bFound = false; - for (auto& Path : Settings.ExcludePaths) + for (auto& Path : ExcludePaths) { if (S.PackagePath.ToString().Find(Path) != -1) { @@ -557,7 +535,7 @@ bool GetStructureAssets(TArray& ScriptStructs, const UBlueprintToRST return true; } -bool GetEnumerationAssets(TArray& Enums, const UBlueprintToRSTDocSettings& Settings) +bool GetEnumerationAssets(TArray& Enums, const TArray& ExcludePaths, FString& ErrorMessage) { FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(FName("AssetRegistry")); IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); @@ -570,7 +548,7 @@ bool GetEnumerationAssets(TArray& Enums, const UBlueprintToRSTDocSet if (!AssetRegistry.GetAssets(Filter, Enums)) { - ERROR_MESSAGE_BOX(TEXT("Failed to get assets of 'UEnum'.")); + ErrorMessage = TEXT("Failed to get assets of 'UEnum'."); return false; } @@ -579,7 +557,7 @@ bool GetEnumerationAssets(TArray& Enums, const UBlueprintToRSTDocSet for (auto& E : Enums) { bool bFound = false; - for (auto& Path : Settings.ExcludePaths) + for (auto& Path : ExcludePaths) { if (E.PackagePath.ToString().Find(Path) != -1) { @@ -1053,7 +1031,7 @@ void CreateRSTEnumerationDoc(FString& Doc, RSTDocIndent& Indent, const FRSTDocEn Indent.Decrement(); } -bool CreateDirectoryRecursive(const FString& BaseDirectory, const FString& Directory) +bool CreateDirectoryRecursive(const FString& BaseDirectory, const FString& Directory, FString& ErrorMessage) { IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); @@ -1067,7 +1045,7 @@ bool CreateDirectoryRecursive(const FString& BaseDirectory, const FString& Direc FullPath += D; if (!PlatformFile.CreateDirectory(*FullPath)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Failed to create directory.\n{0}"), {FullPath})); + ErrorMessage = FString::Format(TEXT("Failed to create directory.\n{0}"), {FullPath}); return false; } } @@ -1075,7 +1053,8 @@ bool CreateDirectoryRecursive(const FString& BaseDirectory, const FString& Direc return true; } -bool WriteRSTBlueprintDocs(const TArray& Data, const FString& OutputDirectory, TArray& OutputDocsList) +bool WriteRSTBlueprintDocs( + const TArray& Data, const FString& OutputDirectory, TArray& OutputDocsList, FString& ErrorMessage) { IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); @@ -1085,13 +1064,13 @@ bool WriteRSTBlueprintDocs(const TArray& Data, const FString& ClassDirectory = FString::Format(TEXT("{0}/Blueprint"), {OutputDirectory}); if (!PlatformFile.CreateDirectory(*ClassDirectory)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Failed to create directory.\n{0}"), {ClassDirectory})); + ErrorMessage = FString::Format(TEXT("Failed to create directory.\n{0}"), {ClassDirectory}); return false; } for (auto& D : Data) { - if (!CreateDirectoryRecursive(ClassDirectory, D.Path.RightChop(1))) + if (!CreateDirectoryRecursive(ClassDirectory, D.Path.RightChop(1), ErrorMessage)) { return false; } @@ -1104,7 +1083,7 @@ bool WriteRSTBlueprintDocs(const TArray& Data, const FString& if (!FFileHelper::SaveStringToFile(Contents, *FilePath)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Failed to save file.\n{0}"), {FilePath})); + ErrorMessage = FString::Format(TEXT("Failed to save file.\n{0}"), {FilePath}); return false; } @@ -1115,7 +1094,8 @@ bool WriteRSTBlueprintDocs(const TArray& Data, const FString& return true; } -bool WriteRSTStructureDocs(const TArray& Data, const FString& OutputDirectory, TArray& OutputDocsList) +bool WriteRSTStructureDocs( + const TArray& Data, const FString& OutputDirectory, TArray& OutputDocsList, FString& ErrorMessage) { IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); @@ -1125,13 +1105,13 @@ bool WriteRSTStructureDocs(const TArray& Data, const FString& StructDirectory = FString::Format(TEXT("{0}/Struct"), {OutputDirectory}); if (!PlatformFile.CreateDirectory(*StructDirectory)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Failed to create directory.\n{0}"), {StructDirectory})); + ErrorMessage = FString::Format(TEXT("Failed to create directory.\n{0}"), {StructDirectory}); return false; } for (auto& D : Data) { - if (!CreateDirectoryRecursive(StructDirectory, D.Path.RightChop(1))) + if (!CreateDirectoryRecursive(StructDirectory, D.Path.RightChop(1), ErrorMessage)) { return false; } @@ -1144,7 +1124,7 @@ bool WriteRSTStructureDocs(const TArray& Data, const FString& if (!FFileHelper::SaveStringToFile(Contents, *FilePath)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Failed to save file.\n{0}"), {FilePath})); + ErrorMessage = FString::Format(TEXT("Failed to save file.\n{0}"), {FilePath}); return false; } @@ -1156,7 +1136,7 @@ bool WriteRSTStructureDocs(const TArray& Data, const FString& } bool WriteRSTEnumerationDocs( - const TArray& Data, const FString& OutputDirectory, TArray& OutputDocsList) + const TArray& Data, const FString& OutputDirectory, TArray& OutputDocsList, FString& ErrorMessage) { IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); @@ -1166,13 +1146,13 @@ bool WriteRSTEnumerationDocs( EnumDirectory = FString::Format(TEXT("{0}/Enum"), {OutputDirectory}); if (!PlatformFile.CreateDirectory(*EnumDirectory)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Failed to create directory.\n{0}"), {EnumDirectory})); + ErrorMessage = FString::Format(TEXT("Failed to create directory.\n{0}"), {EnumDirectory}); return false; } for (auto& D : Data) { - if (!CreateDirectoryRecursive(EnumDirectory, D.Path.RightChop(1))) + if (!CreateDirectoryRecursive(EnumDirectory, D.Path.RightChop(1), ErrorMessage)) { return false; } @@ -1185,7 +1165,7 @@ bool WriteRSTEnumerationDocs( if (!FFileHelper::SaveStringToFile(Contents, *FilePath)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Failed to save file.\n{0}"), {FilePath})); + ErrorMessage = FString::Format(TEXT("Failed to save file.\n{0}"), {FilePath}); return false; } @@ -1196,7 +1176,7 @@ bool WriteRSTEnumerationDocs( return true; } -void AskCleanupOrNot(const FString& Directory) +void AskCleanupOrNot(const FString& Directory, FString& ErrorMessage) { EAppReturnType::Type ReturnType = FPlatformMisc::MessageBoxExt(EAppMsgType::YesNo, *FString::Format(TEXT("Delete incompleted output files.\n{0}"), {Directory}), TEXT("BlueprintToRSTDoc")); @@ -1205,58 +1185,59 @@ void AskCleanupOrNot(const FString& Directory) { if (!FFileManagerGeneric::Get().DeleteDirectory(*Directory, true, true)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Failed to delete directory.\n{0}"), {Directory})); + ErrorMessage = FString::Format(TEXT("Failed to delete directory.\n{0}"), {Directory}); } } } bool WriteRSTDocs(const TArray& BlueprintData, const TArray& StructData, - const TArray& EnumData, const FString& OutputDirectory, TArray& OutputDocsList) + const TArray& EnumData, const FString& OutputDirectory, TArray& OutputDocsList, + FString& ErrorMessage) { FString RSTOutputDirectory = FString::Format(TEXT("{0}/rst"), {OutputDirectory}); IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); if (PlatformFile.DirectoryExists(*RSTOutputDirectory)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Directory is already exist.\n{0}"), {RSTOutputDirectory})); + ErrorMessage = FString::Format(TEXT("Directory is already exist.\n{0}"), {RSTOutputDirectory}); return false; } if (!PlatformFile.CreateDirectory(*RSTOutputDirectory)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Failed to create directory.\n{0}"), {RSTOutputDirectory})); + ErrorMessage = FString::Format(TEXT("Failed to create directory.\n{0}"), {RSTOutputDirectory}); return false; } - if (!WriteRSTBlueprintDocs(BlueprintData, RSTOutputDirectory, OutputDocsList)) + if (!WriteRSTBlueprintDocs(BlueprintData, RSTOutputDirectory, OutputDocsList, ErrorMessage)) { - AskCleanupOrNot(RSTOutputDirectory); + AskCleanupOrNot(RSTOutputDirectory, ErrorMessage); return false; } - if (!WriteRSTStructureDocs(StructData, RSTOutputDirectory, OutputDocsList)) + if (!WriteRSTStructureDocs(StructData, RSTOutputDirectory, OutputDocsList, ErrorMessage)) { - AskCleanupOrNot(RSTOutputDirectory); + AskCleanupOrNot(RSTOutputDirectory, ErrorMessage); return false; } - if (!WriteRSTEnumerationDocs(EnumData, RSTOutputDirectory, OutputDocsList)) + if (!WriteRSTEnumerationDocs(EnumData, RSTOutputDirectory, OutputDocsList, ErrorMessage)) { - AskCleanupOrNot(RSTOutputDirectory); + AskCleanupOrNot(RSTOutputDirectory, ErrorMessage); return false; } return true; } -bool OutputDocsListFile( - const FString& OutputDirectory, const TArray& OutputDocsList, const UBlueprintToRSTDocSettings& Settings) +bool OutputDocsListFile(const FString& OutputDirectory, const TArray& OutputDocsList, bool bOutputDocsListFullPath, + const FString& OutputDocsListFileName, FString& ErrorMessage) { FString RSTOutputDirectory = FString::Format(TEXT("{0}/rst"), {OutputDirectory}); TArray DocsList; for (auto& Doc : OutputDocsList) { - if (Settings.bOutputDocsListFullPath) + if (bOutputDocsListFullPath) { DocsList.Add(Doc); } @@ -1268,84 +1249,78 @@ bool OutputDocsListFile( } else { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("{0} does not include {1}."), {RSTOutputDirectory, Doc})); - AskCleanupOrNot(RSTOutputDirectory); + ErrorMessage = FString::Format(TEXT("{0} does not include {1}."), {RSTOutputDirectory, Doc}); + AskCleanupOrNot(RSTOutputDirectory, ErrorMessage); return false; } } } - FString FilePath = FString::Format(TEXT("{0}/{1}"), {RSTOutputDirectory, Settings.OutputDocsListFileName}); + FString FilePath = FString::Format(TEXT("{0}/{1}"), {RSTOutputDirectory, OutputDocsListFileName}); FString Contents = FString::Join(DocsList, TEXT("\n")); if (!FFileHelper::SaveStringToFile(Contents, *FilePath)) { - ERROR_MESSAGE_BOX(*FString::Format(TEXT("Failed to create file.\n{0}"), {FilePath})); - AskCleanupOrNot(RSTOutputDirectory); + ErrorMessage = FString::Format(TEXT("Failed to create file.\n{0}"), {FilePath}); + AskCleanupOrNot(RSTOutputDirectory, ErrorMessage); return false; } return true; } -void UBlueprintToRSTDocBPLibrary::GenerateRSTDoc() +void UBlueprintToRSTDocBPLibrary::GenerateRSTDoc(const FString& OutputDirectory, const TArray& ExcludePaths, + bool& bSuccess, FString& ErrorMessage, bool bOutputBlueprint, bool bOutputStructure, bool bOutputEnumeration, + bool bOutputDocsList, const FString& OutputDocsListFileName, bool bOutputDocsListFullPath) { - UBlueprintToRSTDocSettings* Settings = GetMutableDefault(); - - FString OutputDirectory = Settings->OutputDirectory; - if (Settings->bAlwaysAskOutputDirectory) - { - if (!OpenOutputDirectory(OutputDirectory)) - { - return; - } - } - TArray DocBlueprints; - if (Settings->bOutputBlueprint) + if (bOutputBlueprint) { TArray Blueprints; - if (!GetBlueprintAssets(Blueprints, *Settings)) + if (!GetBlueprintAssets(Blueprints, ExcludePaths, ErrorMessage)) { + bSuccess = false; return; } ParseBlueprints(DocBlueprints, Blueprints); } TArray DocStructures; - if (Settings->bOutputStructure) + if (bOutputStructure) { TArray ScriptStructs; - if (!GetStructureAssets(ScriptStructs, *Settings)) + if (!GetStructureAssets(ScriptStructs, ExcludePaths, ErrorMessage)) { + bSuccess = false; return; } ParseStructures(DocStructures, ScriptStructs); } TArray DocEnumerations; - if (Settings->bOutputEnumeration) + if (bOutputEnumeration) { TArray Enums; - if (!GetEnumerationAssets(Enums, *Settings)) + if (!GetEnumerationAssets(Enums, ExcludePaths, ErrorMessage)) { + bSuccess = false; return; } ParseEnumerations(DocEnumerations, Enums); } TArray OutputDocsList; - if (!WriteRSTDocs(DocBlueprints, DocStructures, DocEnumerations, OutputDirectory, OutputDocsList)) + if (!WriteRSTDocs(DocBlueprints, DocStructures, DocEnumerations, OutputDirectory, OutputDocsList, ErrorMessage)) { + bSuccess = false; return; } - if (Settings->bOutputDocsList) + if (bOutputDocsList) { - if (!OutputDocsListFile(OutputDirectory, OutputDocsList, *Settings)) + if (!OutputDocsListFile(OutputDirectory, OutputDocsList, bOutputDocsListFullPath, OutputDocsListFileName, ErrorMessage)) { + bSuccess = false; return; } } - - FPlatformMisc::MessageBoxExt(EAppMsgType::Ok, TEXT("Generated documents successfully."), TEXT("BlueprintToRSTDoc")); } \ No newline at end of file diff --git a/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Private/BlueprintToRSTDoc.cpp b/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Private/BlueprintToRSTDoc.cpp index 0550123..91cdfc4 100644 --- a/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Private/BlueprintToRSTDoc.cpp +++ b/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Private/BlueprintToRSTDoc.cpp @@ -4,7 +4,10 @@ #include "BPLibrary.h" #include "Commands.h" +#include "Common.h" +#include "DesktopPlatformModule.h" #include "Framework/MultiBox/MultiBoxBuilder.h" +#include "IDesktopPlatform.h" #include "ISettingsModule.h" #include "LevelEditor.h" #include "Misc/EngineVersionComparison.h" @@ -14,6 +17,23 @@ #define LOCTEXT_NAMESPACE "BlueprintToRSTDoc" +bool OpenOutputDirectory(FString& OutDirectory) +{ + void* ParentWindowPtr = FSlateApplication::Get().GetActiveTopLevelWindow()->GetNativeWindow()->GetOSWindowHandle(); + IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); + if (!DesktopPlatform) + { + ERROR_MESSAGE_BOX(TEXT("Failed to get DesktopPlatform.\n")); + return false; + } + if (!DesktopPlatform->OpenDirectoryDialog(ParentWindowPtr, TEXT("Save RST Documents To"), TEXT(""), OutDirectory)) + { + return false; + } + + return true; +} + void FBlueprintToRSTDocModule::StartupModule() { FBlueprintToRSTDocStyle::Initialize(); @@ -69,7 +89,31 @@ void FBlueprintToRSTDocModule::ShutdownModule() void FBlueprintToRSTDocModule::CommandExecuted() { - UBlueprintToRSTDocBPLibrary::GenerateRSTDoc(); + UBlueprintToRSTDocSettings* Settings = GetMutableDefault(); + + FString OutputDirectory = Settings->OutputDirectory; + if (Settings->bAlwaysAskOutputDirectory) + { + if (!OpenOutputDirectory(OutputDirectory)) + { + return; + } + } + + bool bSuccess; + FString ErrorMessage; + UBlueprintToRSTDocBPLibrary::GenerateRSTDoc(OutputDirectory, Settings->ExcludePaths, bSuccess, ErrorMessage, + Settings->bOutputBlueprint, Settings->bOutputStructure, Settings->bOutputEnumeration, Settings->bOutputDocsList, + Settings->OutputDocsListFileName, Settings->bOutputDocsListFullPath); + + if (!bSuccess) + { + ERROR_MESSAGE_BOX(ErrorMessage); + } + else + { + FPlatformMisc::MessageBoxExt(EAppMsgType::Ok, TEXT("Generated documents successfully."), TEXT("BlueprintToRSTDoc")); + } } void FBlueprintToRSTDocModule::AddToolBarExtension(FToolBarBuilder& Builder) diff --git a/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Public/BPLibrary.h b/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Public/BPLibrary.h index 39ca79b..7b5b8be 100644 --- a/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Public/BPLibrary.h +++ b/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Public/BPLibrary.h @@ -189,5 +189,7 @@ class BLUEPRINTTORSTDOC_API UBlueprintToRSTDocBPLibrary : public UBlueprintFunct public: UFUNCTION(BluePrintCallable, exec, category = "BlueprintToRSTDoc") - static void GenerateRSTDoc(); + static void GenerateRSTDoc(const FString& OutputDirectory, const TArray& ExcludePaths, bool& bSuccess, + FString& ErrorMessage, bool bOutputBlueprint = true, bool bOutputStructure = true, bool bOutputEnumeration = true, + bool bOutputDocsList = true, const FString& OutputDocsListFileName = "DocsList.txt", bool bOutputDocsListFullPath = false); }; \ No newline at end of file diff --git a/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Public/Common.h b/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Public/Common.h new file mode 100644 index 0000000..989a494 --- /dev/null +++ b/BlueprintToRSTDoc/Source/BlueprintToRSTDoc/Public/Common.h @@ -0,0 +1,6 @@ +#pragma once + +#define ERROR_MESSAGE_BOX(Message) \ + FPlatformMisc::MessageBoxExt(EAppMsgType::Ok, \ + *FString::Format(TEXT("Error:\n\n{0}\n\n---\n\n{1} (Line:{2})"), {Message, *FString(__FILE__), __LINE__}), \ + TEXT("BlueprintToRSTDoc")); \ No newline at end of file diff --git a/samples/SampleProject/Source/SampleProject.Target.cs b/samples/SampleProject/Source/SampleProject.Target.cs index 1e393dd..f43d703 100644 --- a/samples/SampleProject/Source/SampleProject.Target.cs +++ b/samples/SampleProject/Source/SampleProject.Target.cs @@ -1,4 +1,11 @@ -// Copyright Epic Games, Inc. All Rights Reserved. +/*! + * SampleProject + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ using UnrealBuildTool; using System.Collections.Generic; diff --git a/samples/SampleProject/Source/SampleProject/SampleProject.Build.cs b/samples/SampleProject/Source/SampleProject/SampleProject.Build.cs index f7d9254..8706522 100644 --- a/samples/SampleProject/Source/SampleProject/SampleProject.Build.cs +++ b/samples/SampleProject/Source/SampleProject/SampleProject.Build.cs @@ -1,4 +1,11 @@ -// Copyright Epic Games, Inc. All Rights Reserved. +/*! + * SampleProject + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ using UnrealBuildTool; diff --git a/samples/SampleProject/Source/SampleProject/SampleProject.cpp b/samples/SampleProject/Source/SampleProject/SampleProject.cpp index 0238559..4804008 100644 --- a/samples/SampleProject/Source/SampleProject/SampleProject.cpp +++ b/samples/SampleProject/Source/SampleProject/SampleProject.cpp @@ -1,4 +1,11 @@ -// Copyright Epic Games, Inc. All Rights Reserved. +/*! + * SampleProject + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ #include "SampleProject.h" diff --git a/samples/SampleProject/Source/SampleProject/SampleProject.h b/samples/SampleProject/Source/SampleProject/SampleProject.h index ddbf2e2..1966188 100644 --- a/samples/SampleProject/Source/SampleProject/SampleProject.h +++ b/samples/SampleProject/Source/SampleProject/SampleProject.h @@ -1,4 +1,11 @@ -// Copyright Epic Games, Inc. All Rights Reserved. +/*! + * SampleProject + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ #pragma once diff --git a/samples/SampleProject/Source/SampleProjectEditor.Target.cs b/samples/SampleProject/Source/SampleProjectEditor.Target.cs index a391846..65343d9 100644 --- a/samples/SampleProject/Source/SampleProjectEditor.Target.cs +++ b/samples/SampleProject/Source/SampleProjectEditor.Target.cs @@ -1,4 +1,11 @@ -// Copyright Epic Games, Inc. All Rights Reserved. +/*! + * SampleProject + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ using UnrealBuildTool; using System.Collections.Generic; diff --git a/tests/functional_test/FunctionalTest/.gitignore b/tests/functional_test/FunctionalTest/.gitignore new file mode 100644 index 0000000..ea6f021 --- /dev/null +++ b/tests/functional_test/FunctionalTest/.gitignore @@ -0,0 +1,78 @@ +# Original: https://github.com/github/gitignore/blob/main/UnrealEngine.gitignore + +Plugins/BlueprintToRSTDoc + +# Visual Studio 2015 user specific files +.vs/ + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +*.ipa + +# These project files can be generated by the engine +*.xcodeproj +*.xcworkspace +*.sln +*.suo +*.opensdf +*.sdf +*.VC.db +*.VC.opendb + +# Precompiled Assets +SourceArt/**/*.png +SourceArt/**/*.tga + +# Binary Files +Binaries/* +Plugins/*/Binaries/* + +# Builds +Build/* + +# Whitelist PakBlacklist-.txt files +!Build/*/ +Build/*/** +!Build/*/PakBlacklist*.txt + +# Don't ignore icon files in Build +!Build/**/*.ico + +# Built data for maps +*_BuiltData.uasset + +# Configuration files generated by the Editor +Saved/* + +# Compiled source files for the engine to use +Intermediate/* +Plugins/*/Intermediate/* + +# Cache files for the editor to use +DerivedDataCache/* \ No newline at end of file diff --git a/tests/functional_test/FunctionalTest/Config/DefaultEditor.ini b/tests/functional_test/FunctionalTest/Config/DefaultEditor.ini new file mode 100644 index 0000000..e69de29 diff --git a/tests/functional_test/FunctionalTest/Config/DefaultEngine.ini b/tests/functional_test/FunctionalTest/Config/DefaultEngine.ini new file mode 100644 index 0000000..346c6cc --- /dev/null +++ b/tests/functional_test/FunctionalTest/Config/DefaultEngine.ini @@ -0,0 +1,76 @@ + + +[/Script/EngineSettings.GameMapsSettings] +GameDefaultMap=/Game/Blank.Blank +EditorStartupMap=/Game/Blank.Blank + +[/Script/WindowsTargetPlatform.WindowsTargetSettings] +DefaultGraphicsRHI=DefaultGraphicsRHI_DX12 +-D3D12TargetedShaderFormats=PCD3D_SM5 ++D3D12TargetedShaderFormats=PCD3D_SM6 +-D3D11TargetedShaderFormats=PCD3D_SM5 ++D3D11TargetedShaderFormats=PCD3D_SM5 +Compiler=Default +AudioSampleRate=48000 +AudioCallbackBufferFrameSize=1024 +AudioNumBuffersToEnqueue=1 +AudioMaxChannels=0 +AudioNumSourceWorkers=4 +SpatializationPlugin= +SourceDataOverridePlugin= +ReverbPlugin= +OcclusionPlugin= +CompressionOverrides=(bOverrideCompressionTimes=False,DurationThreshold=5.000000,MaxNumRandomBranches=0,SoundCueQualityIndex=0) +CacheSizeKB=65536 +MaxChunkSizeOverrideKB=0 +bResampleForDevice=False +MaxSampleRate=48000.000000 +HighSampleRate=32000.000000 +MedSampleRate=24000.000000 +LowSampleRate=12000.000000 +MinSampleRate=8000.000000 +CompressionQualityModifier=1.000000 +AutoStreamingThreshold=0.000000 +SoundCueCookQualityIndex=-1 + +[/Script/HardwareTargeting.HardwareTargetingSettings] +TargetedHardwareClass=Desktop +AppliedTargetedHardwareClass=Desktop +DefaultGraphicsPerformance=Maximum +AppliedDefaultGraphicsPerformance=Maximum + +[/Script/Engine.RendererSettings] +r.GenerateMeshDistanceFields=True +r.DynamicGlobalIlluminationMethod=1 +r.ReflectionMethod=1 +r.Shadow.Virtual.Enable=1 +r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=True +r.DefaultFeature.LocalExposure.HighlightContrastScale=0.8 +r.DefaultFeature.LocalExposure.ShadowContrastScale=0.8 + +[/Script/WorldPartitionEditor.WorldPartitionEditorSettings] +CommandletClass=Class'/Script/UnrealEd.WorldPartitionConvertCommandlet' + +[/Script/Engine.UserInterfaceSettings] +bAuthorizeAutomaticWidgetVariableCreation=False +FontDPIPreset=Standard +FontDPI=72 + +[/Script/Engine.Engine] ++ActiveGameNameRedirects=(OldGameName="TP_Blank",NewGameName="/Script/FunctionalTest") ++ActiveGameNameRedirects=(OldGameName="/Script/TP_Blank",NewGameName="/Script/FunctionalTest") + +[/Script/AndroidFileServerEditor.AndroidFileServerRuntimeSettings] +bEnablePlugin=True +bAllowNetworkConnection=True +SecurityToken=67D7A6A846F80E71AF293FB7A28FE181 +bIncludeInShipping=False +bAllowExternalStartInShipping=False +bCompileAFSProject=False +bUseCompression=False +bLogFiles=False +bReportStats=False +ConnectionType=USBOnly +bUseManualIPAddress=False +ManualIPAddress= + diff --git a/tests/functional_test/FunctionalTest/Config/DefaultGame.ini b/tests/functional_test/FunctionalTest/Config/DefaultGame.ini new file mode 100644 index 0000000..8c9ccbf --- /dev/null +++ b/tests/functional_test/FunctionalTest/Config/DefaultGame.ini @@ -0,0 +1,3 @@ + +[/Script/EngineSettings.GeneralProjectSettings] +ProjectID=BBB5D5204BE05E43E38083ACA2DD0382 diff --git a/tests/functional_test/FunctionalTest/Config/DefaultInput.ini b/tests/functional_test/FunctionalTest/Config/DefaultInput.ini new file mode 100644 index 0000000..4cc3605 --- /dev/null +++ b/tests/functional_test/FunctionalTest/Config/DefaultInput.ini @@ -0,0 +1,85 @@ +[/Script/Engine.InputSettings] +-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="Mouse2D",AxisProperties=(DeadZone=0.f,Exponent=1.f,Sensitivity=0.07f)) ++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="Mouse2D",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="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="Vive_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="Vive_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="MixedReality_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="OculusTouch_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Left_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Grip_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trigger_Axis",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Thumbstick_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_X",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Y",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) ++AxisConfig=(AxisKeyName="ValveIndex_Right_Trackpad_Force",AxisProperties=(DeadZone=0.000000,Sensitivity=1.000000,Exponent=1.000000,bInvert=False)) +bAltEnterTogglesFullscreen=True +bF11TogglesFullscreen=True +bUseMouseForTouch=False +bEnableMouseSmoothing=True +bEnableFOVScaling=True +bCaptureMouseOnLaunch=True +bEnableLegacyInputScales=True +bEnableMotionControls=True +bFilterInputByPlatformUser=False +bShouldFlushPressedKeysOnViewportFocusLost=True +bAlwaysShowTouchInterface=False +bShowConsoleOnFourFingerTap=True +bEnableGestureRecognizer=False +bUseAutocorrect=False +DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown +DefaultViewportMouseLockMode=LockOnCapture +FOVScale=0.011110 +DoubleClickTime=0.200000 +DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput +DefaultInputComponentClass=/Script/EnhancedInput.EnhancedInputComponent +DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks +-ConsoleKeys=Tilde ++ConsoleKeys=Tilde ++ConsoleKeys=Caret + diff --git a/tests/functional_test/FunctionalTest/Content/Blank.umap b/tests/functional_test/FunctionalTest/Content/Blank.umap new file mode 100644 index 0000000000000000000000000000000000000000..af05a58935278d7a505cc1b09a66511f67b34baa GIT binary patch literal 6332 zcmc&(4RBS(72ZH76hUYTK}Ey>MItYG4`P&{BYE$UKgb_Ruwg91CGRG=Ud^3ImD@jvcLAldtof2Q7(`^z&8?~LDd?(eSYUn5!B@{`N* z3+5)RUADG;!$<9*Q6zinwka#umjw2m`crc2yKkHuYmn@_C!W-P<1P8u`6Y{5XB|HB zS_8?Zov7IPTFK14xg%4ybgnz7xJdTyE7x{aCX^JcOG^2mdGDr&Mw4uT)$>-Q%Q-SAumU9mdk=n?}CDTEF!b#!`sS&GKi> z%gDMf)8q4H`7*p2^Zavja_;weax*hCy!SsqDvX6l8IHV2s~_*QLt|~AcH&2=bW%A{ zz5T(nXZGZ@A4+^?!>vzm+R_ub`s}#HCBHtk?uC{ehsI!H;G|I*!G@DbR~L6ABvEVj z?4>!Gv&&RnRZKN4Gd+X%GuGBtTbpfilrIB@sf323^#VgTV)yHyoeTHdHbgo5eoB$!%Aam*a)d% ztC1D7{X+xLDsRLx%0tSUV3B5;TCj!?7b=#*k}jt$K)9^R*8%}G$i8#DV01Ft#fFt@ zg#Egv2Cb5Cxf*Uz!)#(o+d)j?GmN@=C0xfRV>K0bY@mffsz+xYpV;;T+7adpN6cE5 z{#kNhoM`!t`j8PMT-LsUfR8UOYH@-%LQo< zV@lDN6Rgq5El*{CzW`e##7l!=Rnc<-%$2xp6pu1~e;n9)unR|@$6V9}9yTuc@F&o+ zx5`?xb|dCks8%Zx-CD824$d+AdeW(kHh5xyPkJmQUQHK4M&fqaP$AeHj{4XSY zK+JM*DE(nxryjt)=MeB@Od$u4W&afkU-%!ouzwFKM9)k3wxstf&ovZ$xEf<*{KfKx z)C_^Usvm(Yk>R@$!34G+@4h$uFjNuLt_KR&Tlml8QJ6za;W-R~2!pGji zKb}O4q8#^2;QvRmA6R$eLj+%C@*1U-$Vvtw*e}))%l>W&AN~<{8ti}B!8{fR-%*R{ zpGy)x&KK@D*aLiI4WK8al-QQ^eueFj#Ihg0Mrs8P`=N7{3S@$SA>JGz8!E@x-Uk{r z`*+Oil+(WH+-pL|?wLqBB8jncn{@kiheqf6>s#Zl~NTr*Mk`N^{pc8o? zcaof1A+560SR)b)n8*|Hqk%i&ky)NphQlH$`G=Dq)MRlYc>1JL0j*%UY$GB^W{j_}NyD)wvYwu977 z5oo$A)cTN4(P6qvLTb>CTdqkTh4Kjz>O%H^;qu~O0F1(^1Eo-j`)>*T0r<#4J}a~B zj$YncSo!bA57%Xj2o&5=)mZlCaiGG?EM60~g)ZrK)jfsx;lM3YEavd^G^4xf1K-A%L zx{39f&uhyeYg!~VaVhra^y;!LAu~*n6#-kmppr4a8Cw~)f&|WbI;R;*D3V$kWjT8? xr|w?(lf8%JC15JKeT@DeVq5p~P3aH5{x%W-{L`~c4X5TUNqn;-)#C`E|34JAy&C`k literal 0 HcmV?d00001 diff --git a/tests/functional_test/FunctionalTest/Content/FunctionalTest/TestActor.uasset b/tests/functional_test/FunctionalTest/Content/FunctionalTest/TestActor.uasset new file mode 100644 index 0000000000000000000000000000000000000000..751d65dcde7ff1a9e4c244cb589b9258d5d0d6a8 GIT binary patch literal 47027 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

h4#{F1kGU^uNaLe2B*fIUF*qk|8VDzcXZ5C6M4D zo$;X_e4H?L=r0Pc*j04#Q&avB9eMBNRxmbF^byvrI~2CPP|T9kAo4q9g{jqkbl%_# zMpg0qW9^Kq#c+IKho8?5eWTpd_uv^fpL2Ch+t9s5;3pBrJ^{S({ItuVQj(prLUyz| z*yh0;5PC(jCV?`~y~kmH$!qe&UL$LG`?g75+g@gxR|qoC8bvrtirsFP%T<&^`yaWk z?410Zyn=j}+nZnFa^+?gXz$^e<*Sc`6ZURdYh6w%`nUFbBs}8u^37NIAL%a@6;N1Kz~e0|U`&=3i2Ifm$RRB& zuyO$8R_*wTV zIzfrU8NcH>n5toX_WH)(<4HvihU_6rK+#>6(D&P531Wq)QFM!jgP^RXPsW4^g9bV$ zI6dJ|lpI7nwdai1M*=Oe6P@(@h_fZ=t5@-4U$n*79&*-)n_I#mH57}AX9E3UXIMOC z5>;cZEt3VRY4nVs>ck6joUKuMb}$ffdLpVXrt0tS(Vq`Q`wabeD=_vrI;sU7$~+KD z1;2t2ud7j`8Ks2Y8=37ERiQ5U!ogF}lf;CwnK0Xwx{ zm1xgQI@LBc(&20X?I$_|4bE7gehJ-E$K#f2NPF7SBopBm)S??g$fVJ`II`dXL$Yh( zhb*3OFeq;I>wL|lr~tm8zJb~h?M-Tk?1h-{)zgyD873}+z7|-CW*`E5qO*bO)MdWr zmZ0kN!MHl;5v6utP!mCj?9AtkMFNeDYD8GmKrcG934;@3gzFZo^<;fbzBXW}3x+lE z)iaeT#%Kz}Vi2eIqQf4$r?Qc3!l(9(jKX5 zZjHt?V(R#{RFxXsnDZxRZvqW0a;<~Zta(q@`b z1<`%!dzCm#m`?3Y(dhYon$M7mG)i_x(UI;!6?uw^3JbFH3QOpJL2gz-L7qD=GrJ_$ zOA82*1fqR%f@)3|(Sm<1QilsFP`4=fEhv5$i;`4{Fpqo^g&#{9t6j<;+5u0sr#fy^ z#k`?(fo#poC|(lsUO6MvkMFKqmG#wt>ngUcn{)S3@8570KLs;iwg7Tb#>k_Y)1?vy zrJ`_SW=te|5CtTS(rH8HmNDpZ0~Yhp=L>ws<32pUTrA;<2S?)XgS7@9ohlnn(~bkC zZIA$#AoH|b!uLea+qlk=UAlc>+XYAdX8RgP;t!IUN`9v6G})0^aU}k-8TH%==Z~H{ k;hL?V-MDJEYz1|&nTiZ%v z3Zm)1d?b)4Mo|-^F=?=bKL{a>RTC4n`j13oG1?}I(I6Hjiqx6C-Suu;xMG}S-^a|n zdA~PrX7&v~U-!zzsi~>Q=K@sB0r(YrBI?!*Zw~+U!1(-gd*Ik}JL>K(N8WwLrO*1+ zLFLTyz58>X>Z-et_w$p3<3C0YOjdryACXT)eO}~!vJik|O)YvCYl?QK;zlB!(vvZk zGn%N;Qr%rFs}mR1%3&q8`^vCEisDYIun$BzP4;V&=#Pq`9EmD&gx7*Wh4+h`$SHmk zB`G6t_-Q_w0a%CqI}31t^d9!~y^o)8;dIZ~f|V_=zWkB2X6K(HLlu8~duMg1{oTPu zUv~adwVL)OI|O7NTAl-!*PSX`hO_$m4lP*!5KA&W#~On^zbOZJyWz+c*8<0(&R9P;bO=L`Oe*OBv(~FUhIvca;49gmQ5InGJ*AnE>T8Fv&{KBp8B1hf&rxmLv{gK?ANoI>wu*OFo%?R|=sYr-PBECA`@xcG zoNUzNPwU&+`gB}RCZ088fdJ+*dYr*Bqi?{2O0HmOZg#;v$+u0E*5jd~!MmFxa+*CC zV@sRd3EyW%?;(H1Sg+yuYoysYju!^x2?ITG?CcaHPjs}V48P#0jWvjC>0UZgi5=aH z4%C|3%6g%*&09I^l=$?};VsM2NYf_sUYnG3mUV1+;wct4;9_gzy|k|_(^A_L=+zhR zf1wp)AC#n?%Yo6;yLS=J+L)oMx}n2(|ImIyZ#f-uEdwhErZso;4mZ5Pi0^U>Oun`A zta+>)%c^V}?zokr1}5sxx0`u;GcK~@2(#K#7?UUhQlhMuFp0x~h(8e4_^_mD3MYkS zP6`RCpBGdi3>qrUrf&FL5Pj}UFkzuFo6I?;BD5N;%fp#$8xQ11!{v+M%E7R#sOZFiAgO#% z(?W_A;zhqCgg8~^#s3X1KWn%*TEJIW{oh#NZnDM{i8i_QE}`D7mT)FLswy_wYfI@- z>JSy`QNhh~^DV_I5mo3D<|zN$vW8~7x+BPzxor{uvdjK0mNM1$Z!ALtg@7!%-I0pD z-%R#xJ$FxQW=hPNlK41A|1ebnBzv7Ji{N&Y6_*xYhb!mprS61Fo+JdtuyAW zd9>6I{IQw_Pfe+MKsr~bD>b#|FTaA0gH-5Tf=D+@PXe3h2V`Ws8Bp~kx?0JiQc6Vs zXR}-s6*S9-Kmlo16TV1HyW6N%;kc9|U@0mQ(WMbNu;~ou8v=WJ8W45mJFC3|`_i7C zUFp4=L+DII)(a6v^HT?^jm~5fWOBDd*MPEQDK04CG<4`1_9$6Dojv%Xu%g2kJl4#u w>9Iv*JBS_*ME13n4dWyG;O}qt`&N&9PR!d(@xRS8W8#D5AD^n_EEehi12)~2&Hw-a literal 0 HcmV?d00001 diff --git a/tests/functional_test/FunctionalTest/Content/FunctionalTest/TestStructure.uasset b/tests/functional_test/FunctionalTest/Content/FunctionalTest/TestStructure.uasset new file mode 100644 index 0000000000000000000000000000000000000000..4194581cee87a24c3f66df293cc44fceb7231cb7 GIT binary patch literal 5053 zcmeHLdvH|M89yNbqC7+(r3Gv^ii(iOZgw|pfC{^tyCFOzX%b-2A>3py;g;oYynB}t z%Q!(1DT)m8a2&-MF}_-*8I^WMw1F1-2dzV;oq@Jf)0rZpbbJougID~1=bm$OliiT$ zKmDiQ%-(a(_kHJko$ve3Nsc}^rbv@jAXG(H0F{W6X-Xl{7m%U{|Z(;da8KJ-q#u@Kk}R5J;CMN`2K zIWS~6&4#h7i@I{g(`x3-1|>N2Ct5;NQ(AGb#LwxB{j%u50Cd{K;o$V=)?gAP{lA!C z8Dz=#lEU8zH=}aY?8kQ2*t))h_k+M{ySz~V=*nM&wXo{gWB{YA0xgKxPEcW}KuNqs>i(isX zSo&h!(CW2~7CTuq@padxI(37F17w?aoZbrckwjW+HFd+PZ)?@q=o=sJ9s_JLnQ&|x zm)E)dM#!(%%=J1Qd37q9B%@em`~0Po`x1nA%T2YF9AfFFmU)xbu~#+NaP(? zzIc|7ltoobYe|}I?92Q29EVjT-%`m1lUwyl!Hy>plxW&CHN&dZ)~Mv;GL=kcO>3`w z0E_z|$Nlkwe>9MKsx_gu-35p5+j}koAxgZ8j9V*x;R>GJ5J-;VG~G&?m8zw(BMV-9 z7jhLNz21pL?dkpVkwHq0ZuB)Vb~-oo{cM!kv+qh88r#+I$U6`hGj+{~Cv1~)kDnMd zoRC#%Je-YW_% zL>wCo{ob^O_*Tc+!e9N}#9nfiC&L!svG!tn&7Jo)mNhCB(Qsv1S!E#Tk9ZY-)awr` zp;#mmh;WDvw5d;fi2IS)?rF3kTS+ zksBv{&!s8ligSu>-`ABCcJU&*x@m+D2e^znSkh!KOwEfA@lH7Q!srQzhHQn3(L(jj zw$6X38fPQX4Tho@}9^aL4;^RO{JLivyHpZD3)lJ%FFX?`y0Dqm`GWcs@hh7 zHYe5&-~OTw4biq6u$@tCQNfmN=rVn8E$_;^k0F5?QkqG1Mb^ay|AU8ze=s#01r1vC zim_uL+olS!z#C$dnB$6-fGZxqY|vj8c&_%7KSyjt>+cqV=3+4b zxb<*d$1{RI& zxWfR2^c(c8iLL`cVFPgYa=@bzdH^@u14C;8NW8sreY;W*?|dl7U)6ElhV4_{>3G2H znPh`!cq0Hx?13WT;n9Fnv_}9kP~LhTuj4yNKfs3o>^?8w3A+&|8yvmT@=`$*n2X+K7qos0f3s|AP*atGeAll zG^>hFo%nF>*g4AKodE9C^pSR!ED literal 0 HcmV?d00001 diff --git a/tests/functional_test/FunctionalTest/FunctionalTest.uproject b/tests/functional_test/FunctionalTest/FunctionalTest.uproject new file mode 100644 index 0000000..592c2c0 --- /dev/null +++ b/tests/functional_test/FunctionalTest/FunctionalTest.uproject @@ -0,0 +1,22 @@ +{ + "FileVersion": 3, + "EngineAssociation": "5.3", + "Category": "", + "Description": "", + "Modules": [ + { + "Name": "FunctionalTest", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ], + "Plugins": [ + { + "Name": "ModelingToolsEditorMode", + "Enabled": true, + "TargetAllowList": [ + "Editor" + ] + } + ] +} \ No newline at end of file diff --git a/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Blueprint/Game/FunctionalTest/TestActor.rst b/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Blueprint/Game/FunctionalTest/TestActor.rst new file mode 100644 index 0000000..cd3e8ea --- /dev/null +++ b/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Blueprint/Game/FunctionalTest/TestActor.rst @@ -0,0 +1,159 @@ +TestActor +========== + +Path: /Game/FunctionalTest/TestActor + +.. cpp:class:: TestActor : public Actor + + .. cpp:function:: void Construction_Script(exec then) + + Type: Construction script, the place to spawn components and do other setup. @note Name used in CreateBlueprint function + + Category: + + Access Modifier: Public + + Constant: False + + Flags: Required API, Event, Blueprint Event + + Construction script, the place to spawn components and do other setup. @note Name used in CreateBlueprint function + + :arg then: + :type then: exec + + .. cpp:function:: void Function_0(exec then, Vector Input_0, TestStructure Input_1) + + Type: Function 0 Description + + Category: Test + + Access Modifier: Public + + Constant: False + + Flags: Blueprint Callable, Blueprint Event, Blueprint Pure + + Function 0 Description + + :arg then: + :type then: exec + :arg Input_0: + :type Input_0: Vector + :arg Input_1: + :type Input_1: TestStructure + + .. cpp:function:: (exec, TestEnumeration, EDOFMode) Function_1(exec then) + + Type: Function 1 Description + + Category: Test + + Access Modifier: Public + + Constant: False + + Flags: Has Out Params, Blueprint Callable, Blueprint Event + + Function 1 Description + + :arg then: + :type then: exec + :returns execute: + :rtype execute: exec + :returns Output_0: (Default: NewEnumerator0) + :rtype Output_0: TestEnumeration + :returns Output_1: (Default: Default) + :rtype Output_1: EDOFMode + + .. cpp:function:: (exec, bool, string) Function_2(exec then, int Input_0, int Input_1) + + Type: Function 2 Description + + Category: + + Access Modifier: Public + + Constant: True + + Flags: Has Out Params, Blueprint Callable, Blueprint Event + + Function 2 Description + + :arg then: + :type then: exec + :arg Input_0: + :type Input_0: int + :arg Input_1: + :type Input_1: int + :returns execute: + :rtype execute: exec + :returns Output_0: (Default: false) + :rtype Output_0: bool + :returns Output_1: + :rtype Output_1: string + + .. cpp:function:: void Macro_0() + + Type: Macro 0 Description + + Category: + + Access Modifier: + + Constant: False + + Flags: + + Macro 0 Description + + .. cpp:member:: SceneComponent DefaultSceneRoot + + Category: Default + + Access Modifier: + Flags: Blueprint Visible, Zero Constructor, Instanced Reference, Non Transactional, No Destructor, Has Get Value Type Hash + Lifetime Condition: None + + + + .. cpp:member:: bool Variable_0 + + Category: Test + + Access Modifier: + Flags: Edit, Blueprint Visible, Zero Constructor, Disable Edit On Instance, Is Plain Old Data, No Destructor, Has Get Value Type Hash + Lifetime Condition: None + + Variable 0 Description + + .. cpp:member:: Vector Variable_1 + + Category: Test + + Access Modifier: + Flags: Edit, Blueprint Visible, Net, Zero Constructor, Is Plain Old Data, No Destructor, Has Get Value Type Hash + Lifetime Condition: Autonomous Only + + Variable 1 Description + + .. cpp:member:: TestStructure Variable_2 + + Category: Default + + Access Modifier: + Flags: Edit, Blueprint Visible, Disable Edit On Instance, Is Plain Old Data, No Destructor, Has Get Value Type Hash + Lifetime Condition: None + + Variable 2 Description + + .. cpp:member:: MulticastInlineDelegate Event_0 + + Category: Default + + Access Modifier: + Flags: Edit, Blueprint Visible, Zero Constructor, Disable Edit On Instance, Blueprint Assignable, Blueprint Callable + Lifetime Condition: None + + Event 0 Description + diff --git a/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/DocsList.txt b/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/DocsList.txt new file mode 100644 index 0000000..71d77c0 --- /dev/null +++ b/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/DocsList.txt @@ -0,0 +1,3 @@ +Blueprint/Game/FunctionalTest/TestActor.rst +Struct/Game/FunctionalTest/TestStructure.rst +Enum/Game/FunctionalTest/TestEnumeration.rst \ No newline at end of file diff --git a/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Enum/Game/FunctionalTest/TestEnumeration.rst b/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Enum/Game/FunctionalTest/TestEnumeration.rst new file mode 100644 index 0000000..f8988e8 --- /dev/null +++ b/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Enum/Game/FunctionalTest/TestEnumeration.rst @@ -0,0 +1,17 @@ +TestEnumeration +================ + +Path: /Game/FunctionalTest/TestEnumeration + +.. cpp:enum:: TestEnumeration + + Enumeration Description + + .. cpp:enumerator:: Item_0 = 0 + + tem 0 Description + + .. cpp:enumerator:: Item_1 = 1 + + Item 1 Description + diff --git a/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Struct/Game/FunctionalTest/TestStructure.rst b/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Struct/Game/FunctionalTest/TestStructure.rst new file mode 100644 index 0000000..ff7b166 --- /dev/null +++ b/tests/functional_test/FunctionalTest/FunctionalTest/Expected/rst/Struct/Game/FunctionalTest/TestStructure.rst @@ -0,0 +1,29 @@ +TestStructure +============== + +Path: /Game/FunctionalTest/TestStructure + +.. cpp:class:: TestStructure + + Structure Description + + .. cpp:member:: int Variable_0 + + Category: + + Access Modifier: + Flags: Edit, Blueprint Visible, Zero Constructor, Is Plain Old Data, No Destructor, Has Get Value Type Hash + Lifetime Condition: None + + + + .. cpp:member:: Vector Variable_1 + + Category: + + Access Modifier: + Flags: Edit, Blueprint Visible, Zero Constructor, Is Plain Old Data, No Destructor, Has Get Value Type Hash + Lifetime Condition: None + + + diff --git a/tests/functional_test/FunctionalTest/Source/FunctionalTest.Target.cs b/tests/functional_test/FunctionalTest/Source/FunctionalTest.Target.cs new file mode 100644 index 0000000..de12945 --- /dev/null +++ b/tests/functional_test/FunctionalTest/Source/FunctionalTest.Target.cs @@ -0,0 +1,22 @@ +/*! + * FunctionalTest + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +using UnrealBuildTool; +using System.Collections.Generic; + +public class FunctionalTestTarget : TargetRules +{ + public FunctionalTestTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Game; + DefaultBuildSettings = BuildSettingsVersion.V4; + IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_3; + ExtraModuleNames.Add("FunctionalTest"); + } +} diff --git a/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.Build.cs b/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.Build.cs new file mode 100644 index 0000000..db90016 --- /dev/null +++ b/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.Build.cs @@ -0,0 +1,31 @@ +/*! + * FunctionalTest + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +using UnrealBuildTool; + +public class FunctionalTest : ModuleRules +{ + public FunctionalTest(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange(new string[]{"Core", "CoreUObject", "Engine", "InputCore", "BlueprintToRSTDoc"}); + + PrivateDependencyModuleNames.AddRange(new string[]{}); + + // Uncomment if you are using Slate UI + // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); + + // Uncomment if you are using online features + // PrivateDependencyModuleNames.Add("OnlineSubsystem"); + + // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to + // true + } +} diff --git a/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.cpp b/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.cpp new file mode 100644 index 0000000..8fccf9c --- /dev/null +++ b/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.cpp @@ -0,0 +1,14 @@ +/*! + * FunctionalTest + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "FunctionalTest.h" + +#include "Modules/ModuleManager.h" + +IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, FunctionalTest, "FunctionalTest"); diff --git a/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.h b/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.h new file mode 100644 index 0000000..a894edc --- /dev/null +++ b/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTest.h @@ -0,0 +1,12 @@ +/*! + * FunctionalTest + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once + +#include "CoreMinimal.h" diff --git a/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTestAutomationTest.cpp b/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTestAutomationTest.cpp new file mode 100644 index 0000000..3e20bd0 --- /dev/null +++ b/tests/functional_test/FunctionalTest/Source/FunctionalTest/FunctionalTestAutomationTest.cpp @@ -0,0 +1,82 @@ +/*! + * FunctionalTest + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "BPLibrary.h" +#include "GenericPlatform/GenericPlatformFile.h" +#include "HAL/FileManagerGeneric.h" +#include "Kismet/KismetSystemLibrary.h" +#include "Misc/AutomationTest.h" + +IMPLEMENT_SIMPLE_AUTOMATION_TEST(FFuntionalTestSyncVersion, "BlueprintToRSTDoc.FunctionalTest.GenerateRSTDocument", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter); + +bool FFuntionalTestSyncVersion::RunTest(const FString& Parameters) +{ + FString ProjectFilePath = FPaths::GetProjectFilePath(); + FString OutputDirectory = FString::Format(TEXT("{0}/_FunctionalTestOutput"), {FPaths::GetPath(ProjectFilePath)}); + + // Create an output directory. + IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); + if (!PlatformFile.DirectoryExists(*OutputDirectory)) + { + PlatformFile.CreateDirectory(*OutputDirectory); + } + + // Generate RST documents. + bool bSuccess; + FString ErrorMessage; + UBlueprintToRSTDocBPLibrary::GenerateRSTDoc( + OutputDirectory, {"ChaosNiagara", "Engine", "DatasmithContent", "Niagara"}, bSuccess, ErrorMessage); + if (!bSuccess) + { + UE_LOG(LogTemp, Error, TEXT("%s"), *ErrorMessage); + return 1; + } + + IFileManager& FileManager = FFileManagerGeneric::Get(); + FString ExpectedFilesDirectory = FString::Format(TEXT("{0}/FunctionalTest/Expected"), {FPaths::GetPath(ProjectFilePath)}); + TArray ExpectedFiles; + FString ActualFilesDirectory = OutputDirectory; + TArray ActualFiles; + FileManager.FindFilesRecursive(ExpectedFiles, *ExpectedFilesDirectory, TEXT("*.*"), true, false, false); + FileManager.FindFilesRecursive(ActualFiles, *ActualFilesDirectory, TEXT("*.*"), true, false, false); + + if (ExpectedFiles.Num() != ActualFiles.Num()) + { + UE_LOG(LogTemp, Error, TEXT("Number of Files is not matched: %d (Expected) vs %d (Actual)"), ExpectedFiles.Num(), + ActualFiles.Num()); + return 1; + } + + TMap FilePairs; + for (auto E : ExpectedFiles) + { + FString FileName = E.Mid(ExpectedFilesDirectory.Len()); + int32 Index = ActualFiles.Find(ActualFilesDirectory + FileName); + if (Index == INDEX_NONE) + { + UE_LOG(LogTemp, Error, TEXT("Not Found: %s"), *FileName); + return 1; + } + + FString Expected; + FString Actual; + FFileHelper::LoadFileToString(Expected, *E); + FFileHelper::LoadFileToString(Actual, *ActualFiles[Index]); + if (Expected != Actual) + { + UE_LOG(LogTemp, Error, TEXT("File Content does not match (File: %s)"), *E); + return 1; + } + } + + PlatformFile.DeleteDirectoryRecursively(*OutputDirectory); + + return 0; +} diff --git a/tests/functional_test/FunctionalTest/Source/FunctionalTestEditor.Target.cs b/tests/functional_test/FunctionalTest/Source/FunctionalTestEditor.Target.cs new file mode 100644 index 0000000..c4c9253 --- /dev/null +++ b/tests/functional_test/FunctionalTest/Source/FunctionalTestEditor.Target.cs @@ -0,0 +1,22 @@ +/*! + * FunctionalTest + * + * Copyright (c) 2019-2023 nutti + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +using UnrealBuildTool; +using System.Collections.Generic; + +public class FunctionalTestEditorTarget : TargetRules +{ + public FunctionalTestEditorTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Editor; + DefaultBuildSettings = BuildSettingsVersion.V4; + IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_3; + ExtraModuleNames.Add("FunctionalTest"); + } +}