diff --git a/Content/BP_BugMarkerActorDummy.uasset b/Content/BP_BugMarkerActorDummy.uasset index 764326c..ed34e0a 100644 Binary files a/Content/BP_BugMarkerActorDummy.uasset and b/Content/BP_BugMarkerActorDummy.uasset differ diff --git a/Content/BP_BugPlacerPawn.uasset b/Content/BP_BugPlacerPawn.uasset index cd9d41e..d897a50 100644 Binary files a/Content/BP_BugPlacerPawn.uasset and b/Content/BP_BugPlacerPawn.uasset differ diff --git a/Content/MI_BuggieIcon.uasset b/Content/MI_BuggieIcon.uasset new file mode 100644 index 0000000..993419e Binary files /dev/null and b/Content/MI_BuggieIcon.uasset differ diff --git a/Content/M_BuggieIcon.uasset b/Content/M_BuggieIcon.uasset index c97b9fa..b7f4ec8 100644 Binary files a/Content/M_BuggieIcon.uasset and b/Content/M_BuggieIcon.uasset differ diff --git a/Content/UI/CUI_BugSubmissionForm.uasset b/Content/UI/CUI_BugSubmissionForm.uasset index 8d36acb..cb28931 100644 Binary files a/Content/UI/CUI_BugSubmissionForm.uasset and b/Content/UI/CUI_BugSubmissionForm.uasset differ diff --git a/Content/UI/UMG_BugPlacementOverlay.uasset b/Content/UI/UMG_BugPlacementOverlay.uasset index 08344b9..16af420 100644 Binary files a/Content/UI/UMG_BugPlacementOverlay.uasset and b/Content/UI/UMG_BugPlacementOverlay.uasset differ diff --git a/Source/Unrealzilla/Private/BugMarkerActor.cpp b/Source/Unrealzilla/Private/BugMarkerActor.cpp index a9ad55c..2d9f415 100644 --- a/Source/Unrealzilla/Private/BugMarkerActor.cpp +++ b/Source/Unrealzilla/Private/BugMarkerActor.cpp @@ -10,15 +10,15 @@ EBugStatus ABugMarkerActor::GetBugStatus() const { - if (GetDefault()->ResolvedStatuses.Contains(this->BugData.status)) + if (GetDefault()->ResolvedStatuses.Contains(this->BugData.Status)) { return EBugStatus::Resolved; } - else if (GetDefault()->InProgressStatuses.Contains(this->BugData.status)) + else if (GetDefault()->InProgressStatuses.Contains(this->BugData.Status)) { return EBugStatus::InProgress; } - else if (GetDefault()->UnresolvedStatuses.Contains(this->BugData.status)) + else if (GetDefault()->UnresolvedStatuses.Contains(this->BugData.Status)) { return EBugStatus::Unresolved; } diff --git a/Source/Unrealzilla/Private/BugMarkerLoader.cpp b/Source/Unrealzilla/Private/BugMarkerLoader.cpp deleted file mode 100644 index 022a0f4..0000000 --- a/Source/Unrealzilla/Private/BugMarkerLoader.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// ©2022 Batty Bovine Productions, LLC. All Rights Reserved. - -#include "BugMarkerLoader.h" - -#include "BugMarkerActor.h" -#include "HttpModule.h" -#include "JsonObjectConverter.h" -#include "UnrealzillaGlobalSettings.h" -#include "Kismet/GameplayStatics.h" - - -void ABugMarkerLoader::BeginPlay() -{ - Super::BeginPlay(); - - const FString FullURL = GetDefault()->SubmissionServer + "/rest.cgi"; - - TArray StatusQueries; - if (GetDefault()->bShowUnresolvedBugs) - { - for (const FString Unresolved : GetDefault()->UnresolvedStatuses) - { - StatusQueries.Add("status=" + Unresolved); - } - } - if (GetDefault()->bShowInProgressBugs) - { - for (const FString InProgress : GetDefault()->InProgressStatuses) - { - StatusQueries.Add("status=" + InProgress); - } - } - if (GetDefault()->bShowResolvedBugs) - { - for (const FString Resolved : GetDefault()->ResolvedStatuses) - { - StatusQueries.Add("status=" + Resolved); - } - } - StatusQueries.Add("cf_mapname=" + this->GetWorld()->GetMapName().RightChop(this->GetWorld()->StreamingLevelsPrefix.Len())); - StatusQueries.Add("api_key=" + GetDefault()->APIKey); - const FString QueryString = FString::Join(StatusQueries, TEXT("&")); - - FHttpModule &HttpModule = FHttpModule::Get(); - TSharedRef SeverityRequest = HttpModule.CreateRequest(); - SeverityRequest->SetVerb(TEXT("GET")); - SeverityRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); - SeverityRequest->SetURL(FullURL + "/bug" + "?" + QueryString); - SeverityRequest->OnProcessRequestComplete().BindUObject(this, &ABugMarkerLoader::ServerBugResponse); - SeverityRequest->ProcessRequest(); -} - -void ABugMarkerLoader::EndPlay(const EEndPlayReason::Type EndPlayReason) -{ - this->GetWorldTimerManager().ClearTimer(this->NewBatchTimerHandle); - this->GetWorldTimerManager().ClearTimer(this->UnloadAllTimerHandle); - - Super::EndPlay(EndPlayReason); -} - -void ABugMarkerLoader::ServerBugResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success) -{ - if (Success) - { - FJSONBugResponse ResponseData; - FString JSONResponse = Response->GetContentAsString(); - FJsonObjectConverter::JsonObjectStringToUStruct(JSONResponse, &ResponseData); - - if (ResponseData.error) - { - this->Destroy(); - return; - } - else - { - this->BugBatch = ResponseData.bugs; - this->GetWorldTimerManager().SetTimer(this->NewBatchTimerHandle, this, &ABugMarkerLoader::LoadNewBatch, 1.0f/*this->GetWorld()->GetDeltaSeconds()*/); - } - } - else - { - this->Destroy(); - return; - } -} -void ABugMarkerLoader::LoadNewBatch() -{ - while (!this->BugBatch.IsEmpty()) - { - const FJSONBugData BugData = this->BugBatch[0]; - - FString LocationString, UpVectorString; - BugData.cf_location.Split(":", &LocationString, &UpVectorString); - - FString LocationX, LocationY, LocationZ; - LocationString.Split(",", &LocationX, &LocationY); - LocationY.Split(",", &LocationY, &LocationZ); - - FString UpVectorX, UpVectorY, UpVectorZ; - UpVectorString.Split(",", &UpVectorX, &UpVectorY); - UpVectorY.Split(",", &UpVectorY, &UpVectorZ); - - const FVector Location(FCString::Atof(*LocationX),FCString::Atof(*LocationY),FCString::Atof(*LocationZ)); - const FVector UpVector(FCString::Atof(*UpVectorX),FCString::Atof(*UpVectorY),FCString::Atof(*UpVectorZ)); - - TSubclassOf Class = StaticLoadClass(ABugMarkerActor::StaticClass(), this, BUG_MARKER_ACTOR_BP); - FActorSpawnParameters SpawnParams; - SpawnParams.Owner = this; - const FTransform Transform = FTransform(FRotationMatrix::MakeFromZ(UpVector).Rotator(), Location, FVector::OneVector); - ABugMarkerActor *Marker = this->GetWorld()->SpawnActor(Class, Transform, SpawnParams); - Marker->SetBugData(BugData); - this->Markers.Add(Marker); - - this->BugBatch.RemoveAt(0); - if (!(this->BugBatch.Num() % GetDefault()->LoadMarkersBatch)) - { - break; - } - } - - if (!this->BugBatch.IsEmpty()) - { - this->GetWorldTimerManager().SetTimer(this->NewBatchTimerHandle, this, &ABugMarkerLoader::LoadNewBatch, this->GetWorld()->GetDeltaSeconds()); - } -} - -void ABugMarkerLoader::UnloadAll() -{ - this->GetWorldTimerManager().ClearTimer(this->NewBatchTimerHandle); - - while (!this->Markers.IsEmpty()) - { - AActor *Marker = this->Markers[0]; - this->Markers.RemoveAt(0); - Marker->Destroy(); - if (!(this->Markers.Num() % GetDefault()->UnloadMarkersBatch)) - { - break; - } - } - - if (!this->Markers.IsEmpty()) - { - this->GetWorldTimerManager().SetTimer(this->UnloadAllTimerHandle, this, &ABugMarkerLoader::UnloadAll, this->GetWorld()->GetDeltaSeconds()); - } - else - { - this->Destroy(); - } -} diff --git a/Source/Unrealzilla/Private/BugMarkerSubsystem.cpp b/Source/Unrealzilla/Private/BugMarkerSubsystem.cpp new file mode 100644 index 0000000..b0a2a52 Binary files /dev/null and b/Source/Unrealzilla/Private/BugMarkerSubsystem.cpp differ diff --git a/Source/Unrealzilla/Private/BugPlacerPawn.cpp b/Source/Unrealzilla/Private/BugPlacerPawn.cpp index e2c43f4..54c19ef 100644 --- a/Source/Unrealzilla/Private/BugPlacerPawn.cpp +++ b/Source/Unrealzilla/Private/BugPlacerPawn.cpp @@ -3,10 +3,10 @@ #include "BugPlacerPawn.h" #include "BugMarkerActor.h" -#include "BugMarkerLoader.h" +#include "BugMarkerSubsystem.h" #include "ExitingBugPlacementScreen.h" #include "UnrealzillaGlobalSettings.h" -#include "UnrealzillaJSON.h" +#include "BugzillaJSONStructs.h" #include "Components/MaterialBillboardComponent.h" #include "Components/SphereComponent.h" @@ -100,7 +100,7 @@ void ABugPlacerPawn::TraceTimerElapsed() else { this->PlacementMarkerRoot->SetVisibility(true, true); - this->UpdateBugInformation(FJSONBugData()); + this->UpdateBugInformation(FUnrealzillaBugData()); this->ShowDummyMarker(true); } @@ -209,31 +209,16 @@ void ABugPlacerPawn::SpawnBugPlacerPawn(const UObject *WorldContextObject, TSubc void ABugPlacerPawn::ShowBugMarkersInLevel(const UObject *WorldContextObject) { - for (TActorIterator Iterator(WorldContextObject->GetWorld(), ABugMarkerLoader::StaticClass()); Iterator; ++Iterator) + if (UBugMarkerSubsystem *BugMarkerSubsystem = UGameplayStatics::GetPlayerController(WorldContextObject, 0)->GetLocalPlayer()->GetSubsystem()) { - return; + BugMarkerSubsystem->ShowBugMarkers(); } - WorldContextObject->GetWorld()->SpawnActor(ABugMarkerLoader::StaticClass(), FVector::ZeroVector, FRotator::ZeroRotator); } void ABugPlacerPawn::HideBugMarkersInLevel(const UObject *WorldContextObject) { - for (TActorIterator Iterator(WorldContextObject->GetWorld(), ABugMarkerLoader::StaticClass()); Iterator; ++Iterator) + if (UBugMarkerSubsystem *BugMarkerSubsystem = UGameplayStatics::GetPlayerController(WorldContextObject, 0)->GetLocalPlayer()->GetSubsystem()) { - ABugMarkerLoader *BugMarkerLoader = Cast(*Iterator); - BugMarkerLoader->UnloadAll(); + BugMarkerSubsystem->HideBugMarkers(); } } - -const FString ABugPlacerPawn::FormatQueryString(const TMap &QueryData) -{ - TArray AssembledKeyValuePairs; - TArray QueryKeys; - QueryData.GenerateKeyArray(QueryKeys); - for (const FString &QueryKey : QueryKeys) - { - AssembledKeyValuePairs.Add(QueryKey + "=" + QueryData[QueryKey]); - } - - return FString::Join(AssembledKeyValuePairs, TEXT("&")); -} diff --git a/Source/Unrealzilla/Private/BugSubmissionForm.cpp b/Source/Unrealzilla/Private/BugSubmissionForm.cpp index cdcf5e6..bcd71b6 100644 --- a/Source/Unrealzilla/Private/BugSubmissionForm.cpp +++ b/Source/Unrealzilla/Private/BugSubmissionForm.cpp @@ -3,13 +3,13 @@ #include "BugSubmissionForm.h" #include "BugMarkerActor.h" -#include "BugPlacerPawn.h" +//#include "BugPlacerPawn.h" +#include "BugMarkerSubsystem.h" #include "CommonButtonBase.h" #include "CommonTextBlock.h" #include "HttpModule.h" #include "JsonObjectConverter.h" #include "UnrealzillaGlobalSettings.h" -#include "UnrealzillaJSON.h" #include "Components/CircularThrobber.h" #include "Components/Overlay.h" @@ -33,67 +33,33 @@ const FText FormatFloatToText(float Float, int32 IntegralDigits, int32 Fractiona return FText::AsNumber(Float, &NumberFormat); } -const FString GetGameVersion() -{ - FString GameVersion; - GConfig->GetString(TEXT("/Script/EngineSettings.GeneralProjectSettings"), TEXT("ProjectVersion"), GameVersion, GGameIni); - if (GameVersion.IsEmpty()) - { - GameVersion = "1.0.0.0"; - } - return GameVersion; -} - - void UBugSubmissionForm::NativeOnInitialized() { this->ShowProcessingOverlayLoading(); this->ProductNameValue->SetText(FText::AsCultureInvariant(GetDefault()->ProductName)); - const FString FullURL = GetDefault()->SubmissionServer + "/rest.cgi"; - - // Assemble query data into key:value pairs - TMap QueryData; - QueryData.Add("api_key", GetDefault()->APIKey); - const FString QueryString = ABugPlacerPawn::FormatQueryString(QueryData); - - // Query the server for information about the current product - FHttpModule &HttpModule = FHttpModule::Get(); - TSharedRef ProductRequest = HttpModule.CreateRequest(); - ProductRequest->SetVerb(TEXT("GET")); - ProductRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); - ProductRequest->SetURL(FullURL + "/product/" + GetDefault()->ProductName + "?" + QueryString); - ProductRequest->OnProcessRequestComplete().BindUObject(this, &UBugSubmissionForm::ServerProductInfoResponse); - ProductRequest->ProcessRequest(); - - // Send a second query to retrieve severity options - TSharedRef SeverityRequest = HttpModule.CreateRequest(); - SeverityRequest->SetVerb(TEXT("GET")); - SeverityRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); - SeverityRequest->SetURL(FullURL + "/field/bug/bug_severity" + "?" + QueryString); - SeverityRequest->OnProcessRequestComplete().BindUObject(this, &UBugSubmissionForm::ServerSeverityInfoResponse); - SeverityRequest->ProcessRequest(); - - // Send a third query to retrieve platform options - TSharedRef PlatformsRequest = HttpModule.CreateRequest(); - PlatformsRequest->SetVerb(TEXT("GET")); - PlatformsRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); - PlatformsRequest->SetURL(FullURL + "/field/bug/rep_platform" + "?" + QueryString); - PlatformsRequest->OnProcessRequestComplete().BindUObject(this, &UBugSubmissionForm::ServerPlatformInfoResponse); - PlatformsRequest->ProcessRequest(); - - // Send a final query to retrieve OS options - TSharedRef OSRequest = HttpModule.CreateRequest(); - OSRequest->SetVerb(TEXT("GET")); - OSRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); - OSRequest->SetURL(FullURL + "/field/bug/op_sys" + "?" + QueryString); - OSRequest->OnProcessRequestComplete().BindUObject(this, &UBugSubmissionForm::ServerOSInfoResponse); - OSRequest->ProcessRequest(); + UBugMarkerSubsystem *BugMarkerSubsystem = UGameplayStatics::GetPlayerController(this, 0)->GetLocalPlayer()->GetSubsystem(); + BugMarkerSubsystem->FormPrepResponse.BindUObject(this, &UBugSubmissionForm::PrepareFormData); + BugMarkerSubsystem->PrepareSubmissionFormData(); this->SubmitButton->OnClicked().AddUObject(this, &UBugSubmissionForm::SubmitForm); this->CancelButton->OnClicked().AddUObject(this, &UBugSubmissionForm::CancelForm); } +void UBugSubmissionForm::PrepareFormData(const FUnrealzillaFormPrepData &Data) +{ + this->ComponentsList = Data.ComponentsList; + this->SeverityList = Data.SeverityList; + this->VersionsList = Data.VersionsList; + this->PlatformsList = Data.PlatformsList; + this->OSList = Data.OSList; + + this->VersionButton->SetText(FText::AsCultureInvariant(Data.DetectedVersion)); + this->HardwareButton->SetText(FText::AsCultureInvariant(Data.DetectedHardware)); + this->OSButton->SetText(FText::AsCultureInvariant(Data.DetectedOS)); + + this->HideProcessingOverlay(); +} void UBugSubmissionForm::SetMarkerData(ABugMarkerActor *BugMarker) @@ -153,74 +119,30 @@ void UBugSubmissionForm::SubmitForm() { this->ShowProcessingOverlayLoading(); - const FString FullURL = GetDefault()->SubmissionServer + "/rest.cgi"; - const FString RequestURL = "/bug"; + FUnrealzillaPostData PostData; + PostData.Version = this->VersionButton->GetText().ToString(); + PostData.Platform = this->HardwareButton->GetText().ToString(); + PostData.OS = this->OSButton->GetText().ToString(); + PostData.Component = this->ComponentButton->GetText().ToString(); + PostData.Severity = this->SeverityButton->GetText().ToString(); + PostData.MapName = this->MapName.ToString(); + PostData.MapLocation = this->MarkerLocation.ToString(); + PostData.Summary = this->SummaryEntryBox->GetText().ToString(); + PostData.Comment = this->CommentEntryBox->GetText().ToString(); - // Assemble query data into key:value pairs - TMap QueryData; - QueryData.Add("api_key", GetDefault()->APIKey); - - const FString SummaryText = this->SummaryEntryBox->GetText().ToString(); - const FString CommentText = this->CommentEntryBox->GetText().ToString(); - - const FString DefaultStatus = GetDefault()->DefaultStatus; - - FString PostJsonString; - FJSONPostBug PostData; - PostData.product = GetDefault()->ProductName; - PostData.version = this->VersionButton->GetText().ToString(); - PostData.platform = this->HardwareButton->GetText().ToString(); - PostData.op_sys = this->OSButton->GetText().ToString(); - PostData.component = this->ComponentButton->GetText().ToString(); - PostData.severity = this->SeverityButton->GetText().ToString(); - PostData.cf_mapname = this->MapName.ToString(); - PostData.cf_location = this->MarkerLocation.ToString(); - PostData.summary = SummaryText; - PostData.description = CommentText; - if (!DefaultStatus.IsEmpty()) - { - PostData.status = DefaultStatus; - } - FJsonObjectConverter::UStructToJsonObjectString(PostData, PostJsonString); - - if (PostData.version.IsEmpty()) - { - this->ShowProcessingOverlayMessage("You must select a version number."); - return; - } - if (PostData.platform.IsEmpty() || PostData.op_sys.IsEmpty()) - { - PostData.platform = "All"; - PostData.op_sys = "All"; - } - if (PostData.component.IsEmpty()) - { - this->ShowProcessingOverlayMessage("You must select a component."); - return; - } - if (PostData.severity.IsEmpty()) - { - this->ShowProcessingOverlayMessage("You must select a severity level."); - return; - } - if (SummaryText.IsEmpty()) - { - this->ShowProcessingOverlayMessage("You must provide a summary."); - return; - } - - FHttpModule &HttpModule = FHttpModule::Get(); - TSharedRef Request = HttpModule.CreateRequest(); - Request->SetVerb(TEXT("POST")); - Request->SetHeader(TEXT("Content-Type"), TEXT("application/json")); - Request->SetURL(FullURL + RequestURL + "?" + ABugPlacerPawn::FormatQueryString(QueryData)); - Request->SetContentAsString(PostJsonString); - Request->OnProcessRequestComplete().BindUObject(this, &UBugSubmissionForm::ServerPOSTResponse); - Request->ProcessRequest(); + UBugMarkerSubsystem *BugMarkerSubsystem = UGameplayStatics::GetPlayerController(this, 0)->GetLocalPlayer()->GetSubsystem(); + BugMarkerSubsystem->FormPostResponse.BindUObject(this, &UBugSubmissionForm::UpdateReportMarker); + BugMarkerSubsystem->SubmitForm(PostData); this->OnFormSubmit.ExecuteIfBound(); } +void UBugSubmissionForm::UpdateReportMarker(const FUnrealzillaBugData &BugData) +{ + this->BugMarkerActor->SetBugData(BugData); + this->CloseForm(); +} + void UBugSubmissionForm::CancelForm() { this->OnFormCancelled.ExecuteIfBound(); @@ -238,302 +160,7 @@ void UBugSubmissionForm::CloseForm() } -void UBugSubmissionForm::ServerPOSTResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success) +void UBugSubmissionForm::ErrorResponseCallback(const FUnrealzillaErrorData &Error) { - if (Success) - { - FJSONPostResponse ResponseData; - FString JSONResponse = Response->GetContentAsString(); - FJsonObjectConverter::JsonObjectStringToUStruct(JSONResponse, &ResponseData); - - if (ResponseData.error) - { - this->ShowProcessingOverlayMessage(ResponseData.message); - } - else - { - const FString FullURL = GetDefault()->SubmissionServer + "/rest.cgi"; - - TArray StatusQueries; - StatusQueries.Add("id=" + FString::FromInt(ResponseData.id)); - if (GetDefault()->bShowUnresolvedBugs) - { - for (const FString Unresolved : GetDefault()->UnresolvedStatuses) - { - StatusQueries.Add("status=" + Unresolved); - } - } - if (GetDefault()->bShowInProgressBugs) - { - for (const FString InProgress : GetDefault()->InProgressStatuses) - { - StatusQueries.Add("status=" + InProgress); - } - } - if (GetDefault()->bShowResolvedBugs) - { - for (const FString Resolved : GetDefault()->ResolvedStatuses) - { - StatusQueries.Add("status=" + Resolved); - } - } - StatusQueries.Add("cf_mapname=" + this->GetWorld()->GetMapName().RightChop(this->GetWorld()->StreamingLevelsPrefix.Len())); - StatusQueries.Add("api_key=" + GetDefault()->APIKey); - const FString QueryString = FString::Join(StatusQueries, TEXT("&")); - - FHttpModule &HttpModule = FHttpModule::Get(); - TSharedRef SeverityRequest = HttpModule.CreateRequest(); - SeverityRequest->SetVerb(TEXT("GET")); - SeverityRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); - SeverityRequest->SetURL(FullURL + "/bug" + "?" + QueryString); - SeverityRequest->OnProcessRequestComplete().BindUObject(this, &UBugSubmissionForm::ServerPOSTUpdateMarkerResponse); - SeverityRequest->ProcessRequest(); - } - } - else - { - this->ServerConnectionError(Request->GetStatus()); - } -} - -void UBugSubmissionForm::ServerPOSTUpdateMarkerResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success) -{ - if (Success) - { - FJSONBugResponse ResponseData; - FString JSONResponse = Response->GetContentAsString(); - FJsonObjectConverter::JsonObjectStringToUStruct(JSONResponse, &ResponseData); - - if (ResponseData.error) - { - this->ShowProcessingOverlayMessage(ResponseData.message); - } - else - { - if (!ResponseData.bugs.IsEmpty()) - { - this->BugMarkerActor->SetBugData(ResponseData.bugs[0]); - } - this->CloseForm(); - } - } - else - { - this->ServerConnectionError(Request->GetStatus()); - } -} - -void UBugSubmissionForm::ServerProductInfoResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success) -{ - if (Success) - { - FJSONProductResponse ResponseData; - FString JSONResponse = Response->GetContentAsString(); - FJsonObjectConverter::JsonObjectStringToUStruct(JSONResponse, &ResponseData); - - if (ResponseData.error) - { - this->ShowProcessingOverlayMessage(ResponseData.message); - } - else - { - if (!ResponseData.products.IsEmpty()) - { - const FJSONProductData &ProductData = ResponseData.products[0]; - if (ProductData.name == GetDefault()->ProductName) - { - for (const FJSONComponentData &ComponentData : ProductData.components) - { - this->ComponentList.Add(ComponentData.name); - } - for (const FJSONVersionData &VersionData : ProductData.versions) - { - this->VersionsList.Add(VersionData.name); - } - } - - if (this->VersionsList.Contains(GetGameVersion())) - { - this->VersionButton->SetText(FText::AsCultureInvariant(GetGameVersion())); - } - else if (this->VersionsList.Contains("unspecified")) - { - this->VersionButton->SetText(FText::AsCultureInvariant("unspecified")); - } - else if (this->VersionsList.Contains("Latest")) - { - this->VersionButton->SetText(FText::AsCultureInvariant("Latest")); - } - else if (!this->VersionsList.IsEmpty()) - { - this->VersionButton->SetText(FText::AsCultureInvariant(this->VersionsList[0])); - } - - this->CheckIfAllInitialResponsesAreIn(); - } - else - { - FStringFormatOrderedArguments Args; - Args.Add(FStringFormatArg(GetDefault()->ProductName)); - this->ShowProcessingOverlayMessage(FString::Format(TEXT("Could not find data for a product called {0}"), Args), true); - } - } - } - else - { - this->ServerConnectionError(Request->GetStatus()); - } -} - -void UBugSubmissionForm::ServerSeverityInfoResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success) -{ - if (Success) - { - FJSONFieldResponse ResponseData; - FString JSONResponse = Response->GetContentAsString(); - FJsonObjectConverter::JsonObjectStringToUStruct(JSONResponse, &ResponseData); - - if (ResponseData.error) - { - this->ShowProcessingOverlayMessage(ResponseData.message); - } - else - { - if (!ResponseData.fields.IsEmpty() && ResponseData.fields[0].name == "bug_severity") - { - for (const FJSONFieldValueData &FieldValue : ResponseData.fields[0].values) - { - this->SeverityList.Add(FieldValue.name); - } - } - - this->CheckIfAllInitialResponsesAreIn(); - } - } - else - { - this->ServerConnectionError(Request->GetStatus()); - } -} - -void UBugSubmissionForm::ServerPlatformInfoResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success) -{ - if (Success) - { - FJSONFieldResponse ResponseData; - FString JSONResponse = Response->GetContentAsString(); - FJsonObjectConverter::JsonObjectStringToUStruct(JSONResponse, &ResponseData); - - if (ResponseData.error) - { - this->ShowProcessingOverlayMessage(ResponseData.message); - } - else - { - if (!ResponseData.fields.IsEmpty() && ResponseData.fields[0].name == "rep_platform") - { - for (const FJSONFieldValueData &FieldValue : ResponseData.fields[0].values) - { - this->PlatformsList.Add(FieldValue.name); - } - } - - this->CheckIfAllInitialResponsesAreIn(); - } - } - else - { - this->ServerConnectionError(Request->GetStatus()); - } -} - -void UBugSubmissionForm::ServerOSInfoResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success) -{ - if (Success) - { - FJSONFieldResponse ResponseData; - FString JSONResponse = Response->GetContentAsString(); - FJsonObjectConverter::JsonObjectStringToUStruct(JSONResponse, &ResponseData); - - if (ResponseData.error) - { - this->ShowProcessingOverlayMessage(ResponseData.message); - } - else - { - if (!ResponseData.fields.IsEmpty() && ResponseData.fields[0].name == "op_sys") - { - for (const FJSONFieldValueData &FieldValue : ResponseData.fields[0].values) - { - this->OSList.Add(FieldValue.name); - } - } - - this->CheckIfAllInitialResponsesAreIn(); - } - } - else - { - this->ServerConnectionError(Request->GetStatus()); - } -} - -void UBugSubmissionForm::CheckIfAllInitialResponsesAreIn() -{ - if (!this->ComponentList.IsEmpty() && !this->VersionsList.IsEmpty() && !this->SeverityList.IsEmpty() && - !this->PlatformsList.IsEmpty() && !this->OSList.IsEmpty()) - { - // Set these as defaults in case nothing below changes this setting - this->HardwareButton->SetText(FText::AsCultureInvariant("All")); - this->OSButton->SetText(FText::AsCultureInvariant("All")); - - if (this->PlatformsList.Contains("PC")) // Try our best to auto-detect PC hardware - { - if (UGameplayStatics::GetPlatformName() == "Windows" && this->OSList.Contains("Windows")) - { - this->HardwareButton->SetText(FText::AsCultureInvariant("PC")); - this->OSButton->SetText(FText::AsCultureInvariant("Windows")); - } - else if (UGameplayStatics::GetPlatformName() == "Linux" && this->OSList.Contains("Linux")) - { - this->HardwareButton->SetText(FText::AsCultureInvariant("PC")); - this->OSButton->SetText(FText::AsCultureInvariant("Linux")); - } - else if (UGameplayStatics::GetPlatformName() == "Mac" && this->OSList.Contains("Mac OS")) - { - this->HardwareButton->SetText(FText::AsCultureInvariant("All")); - this->OSButton->SetText(FText::AsCultureInvariant("Mac OS")); - } - } - if (UGameplayStatics::GetPlatformName() == "Mac") // Try our best to auto-detect Macintosh hardware - { - if (this->PlatformsList.Contains("Macintosh")) - { - if (this->OSList.Contains("Mac OS")) - { - this->HardwareButton->SetText(FText::AsCultureInvariant("Macintosh")); - this->OSButton->SetText(FText::AsCultureInvariant("Mac OS")); - } - } - } - - this->HideProcessingOverlay(); - } -} - -void UBugSubmissionForm::ServerConnectionError(const EHttpRequestStatus::Type Status) -{ - switch (Status) { - case EHttpRequestStatus::Failed_ConnectionError: - this->ShowProcessingOverlayMessage("Unable to connect to the server", true); - break; - case EHttpRequestStatus::NotStarted: - this->ShowProcessingOverlayMessage("Connection could not start", true); - break; - case EHttpRequestStatus::Failed: - this->ShowProcessingOverlayMessage("Connection failed", true); - break; - default: - this->ShowProcessingOverlayMessage("Request failed for unknown reasons", true); - } + this->ShowProcessingOverlayMessage(Error.ErrorMessage); } diff --git a/Source/Unrealzilla/Private/ServerREST.cpp b/Source/Unrealzilla/Private/ServerREST.cpp new file mode 100644 index 0000000..1fd5294 Binary files /dev/null and b/Source/Unrealzilla/Private/ServerREST.cpp differ diff --git a/Source/Unrealzilla/Public/BugMarkerActor.h b/Source/Unrealzilla/Public/BugMarkerActor.h index fac7a2a..f3ee144 100644 --- a/Source/Unrealzilla/Public/BugMarkerActor.h +++ b/Source/Unrealzilla/Public/BugMarkerActor.h @@ -3,7 +3,8 @@ #pragma once #include "CoreMinimal.h" -#include "UnrealzillaJSON.h" + +#include "ServerREST.h" #include "BugMarkerActor.generated.h" @@ -32,12 +33,12 @@ public: void LoadBugSubmissionForm(); UFUNCTION(BlueprintCallable) - void SetBugData(const FJSONBugData &Data) { this->BugData = Data; this->ReloadBugData(); } + void SetBugData(const FUnrealzillaBugData &Data) { this->BugData = Data; this->ReloadBugData(); } UFUNCTION(BlueprintPure) - FJSONBugData GetBugData() const { return this->BugData; } + FUnrealzillaBugData GetBugData() const { return this->BugData; } UFUNCTION(BlueprintPure) EBugStatus GetBugStatus() const; protected: - FJSONBugData BugData; + FUnrealzillaBugData BugData; }; diff --git a/Source/Unrealzilla/Public/BugMarkerLoader.h b/Source/Unrealzilla/Public/BugMarkerLoader.h deleted file mode 100644 index b6fad08..0000000 --- a/Source/Unrealzilla/Public/BugMarkerLoader.h +++ /dev/null @@ -1,34 +0,0 @@ -// ©2022 Batty Bovine Productions, LLC. All Rights Reserved. - -#pragma once - -#include "CoreMinimal.h" - -#include "UnrealzillaJSON.h" -#include "Interfaces/IHttpRequest.h" -#include "Interfaces/IHttpResponse.h" - -#include "BugMarkerLoader.generated.h" - - -UCLASS() -class UNREALZILLA_API ABugMarkerLoader : public AActor -{ - GENERATED_BODY() - -public: - virtual void BeginPlay() override; - virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; - - void UnloadAll(); - -private: - void ServerBugResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success); - void LoadNewBatch(); - - TArray Markers; - - TArray BugBatch; - FTimerHandle NewBatchTimerHandle; - FTimerHandle UnloadAllTimerHandle; -}; diff --git a/Source/Unrealzilla/Public/BugMarkerSubsystem.h b/Source/Unrealzilla/Public/BugMarkerSubsystem.h new file mode 100644 index 0000000..294cc86 Binary files /dev/null and b/Source/Unrealzilla/Public/BugMarkerSubsystem.h differ diff --git a/Source/Unrealzilla/Public/BugPlacerPawn.h b/Source/Unrealzilla/Public/BugPlacerPawn.h index 0e5ca21..9b92837 100644 --- a/Source/Unrealzilla/Public/BugPlacerPawn.h +++ b/Source/Unrealzilla/Public/BugPlacerPawn.h @@ -3,7 +3,7 @@ #pragma once #include "CoreMinimal.h" -#include "UnrealzillaJSON.h" +#include "BugzillaJSONStructs.h" #include "GameFramework/Pawn.h" #include "BugPlacerPawn.generated.h" @@ -27,7 +27,7 @@ public: void Deactivate(); UFUNCTION(BlueprintImplementableEvent) - void UpdateBugInformation(const FJSONBugData &BugData); + void UpdateBugInformation(const FUnrealzillaBugData &BugData); UFUNCTION(BlueprintImplementableEvent) void ShowDummyMarker(const bool bShow); UFUNCTION(BlueprintImplementableEvent) @@ -40,9 +40,6 @@ public: UFUNCTION(BlueprintCallable, meta=(WorldContext="WorldContextObject")) static void HideBugMarkersInLevel(const UObject *WorldContextObject); - UFUNCTION(BlueprintPure) - static const FString FormatQueryString(const TMap &QueryData); - protected: UFUNCTION(BlueprintCallable) void SetArbitraryPlacement(bool bSet); diff --git a/Source/Unrealzilla/Public/BugSubmissionForm.h b/Source/Unrealzilla/Public/BugSubmissionForm.h index 76ad1a7..e364f1e 100644 --- a/Source/Unrealzilla/Public/BugSubmissionForm.h +++ b/Source/Unrealzilla/Public/BugSubmissionForm.h @@ -6,7 +6,7 @@ #include "BugFormButton.h" #include "CommonActivatableWidget.h" -#include "UnrealzillaJSON.h" +#include "BugzillaJSONStructs.h" #include "Interfaces/IHttpRequest.h" #include "Interfaces/IHttpResponse.h" @@ -30,7 +30,7 @@ protected: virtual void NativeOnInitialized() override; UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName="Display POST Response")) - void DisplayPOSTResponse(const FJSONPostResponse &Response); + void DisplayPOSTResponse(const FBugzillaJSONPostResponse &Response); UPROPERTY(BlueprintReadOnly, meta=(BindWidget)) TObjectPtr ProductNameValue; @@ -67,26 +67,18 @@ protected: UPROPERTY(BlueprintReadOnly, meta=(BindWidget)) TObjectPtr ProcessingRequestErrorButton; + UPROPERTY(BlueprintReadOnly) + TArray ComponentsList; + UPROPERTY(BlueprintReadOnly) + TArray SeverityList; UPROPERTY(BlueprintReadOnly) TArray VersionsList; UPROPERTY(BlueprintReadOnly) TArray PlatformsList; UPROPERTY(BlueprintReadOnly) TArray OSList; - UPROPERTY(BlueprintReadOnly) - TArray ComponentList; - UPROPERTY(BlueprintReadOnly) - TArray SeverityList; private: - void ServerPOSTResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success); - void ServerPOSTUpdateMarkerResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success); - void ServerProductInfoResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success); - void ServerSeverityInfoResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success); - void ServerPlatformInfoResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success); - void ServerOSInfoResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success); - void CheckIfAllInitialResponsesAreIn(); - UFUNCTION(BlueprintCallable) void ShowProcessingOverlayLoading(); UFUNCTION(BlueprintCallable) @@ -101,7 +93,9 @@ private: void CloseForm(); - void ServerConnectionError(const EHttpRequestStatus::Type Status); + void PrepareFormData(const struct FUnrealzillaFormPrepData &Data); + void ErrorResponseCallback(const struct FUnrealzillaErrorData &Error); + void UpdateReportMarker(const struct FUnrealzillaBugData &BugData); FText MapName; FText MarkerLocation; diff --git a/Source/Unrealzilla/Public/UnrealzillaJSON.h b/Source/Unrealzilla/Public/JSON/BugzillaJSONStructs.h similarity index 85% rename from Source/Unrealzilla/Public/UnrealzillaJSON.h rename to Source/Unrealzilla/Public/JSON/BugzillaJSONStructs.h index c032e1f..1736be5 100644 --- a/Source/Unrealzilla/Public/UnrealzillaJSON.h +++ b/Source/Unrealzilla/Public/JSON/BugzillaJSONStructs.h @@ -4,14 +4,14 @@ #include "CoreMinimal.h" -#include "UnrealzillaJSON.generated.h" +#include "BugzillaJSONStructs.generated.h" /** * JSON structs for POST */ USTRUCT() -struct FJSONPostBug +struct FBugzillaJSONPostBug { GENERATED_BODY() public: @@ -40,7 +40,7 @@ public: }; USTRUCT(Blueprintable) -struct FJSONPostResponse +struct FBugzillaJSONPostResponse { GENERATED_BODY() public: @@ -64,7 +64,7 @@ public: * JSON structs for product data */ USTRUCT(Blueprintable) -struct FJSONComponentData +struct FBugzillaJSONComponentData { GENERATED_BODY() public: @@ -83,7 +83,7 @@ public: }; USTRUCT(Blueprintable) -struct FJSONVersionData +struct FBugzillaJSONVersionData { GENERATED_BODY() public: @@ -98,7 +98,7 @@ public: }; USTRUCT(Blueprintable) -struct FJSONProductData +struct FBugzillaJSONProductData { GENERATED_BODY() public: @@ -109,18 +109,18 @@ public: UPROPERTY(BlueprintReadOnly) FString description; UPROPERTY(BlueprintReadOnly) - TArray components; + TArray components; UPROPERTY(BlueprintReadOnly) - TArray versions; + TArray versions; }; USTRUCT(Blueprintable) -struct FJSONProductResponse +struct FBugzillaJSONProductResponse { GENERATED_BODY() public: UPROPERTY(BlueprintReadOnly) - TArray products; + TArray products; UPROPERTY(BlueprintReadOnly) bool error = false; @@ -140,7 +140,7 @@ public: * JSON structs for product data */ USTRUCT(Blueprintable) -struct FJSONFieldValueData +struct FBugzillaJSONFieldValueData { GENERATED_BODY() public: @@ -151,7 +151,7 @@ public: }; USTRUCT(Blueprintable) -struct FJSONFieldData +struct FBugzillaJSONFieldData { GENERATED_BODY() public: @@ -164,16 +164,16 @@ public: UPROPERTY(BlueprintReadOnly) bool is_mandatory = false; UPROPERTY(BlueprintReadOnly) - TArray values; + TArray values; }; USTRUCT(Blueprintable) -struct FJSONFieldResponse +struct FBugzillaJSONFieldResponse { GENERATED_BODY() public: UPROPERTY(BlueprintReadOnly) - TArray fields; + TArray fields; UPROPERTY(BlueprintReadOnly) bool error = false; @@ -193,7 +193,7 @@ public: * JSON structs for bug lists */ USTRUCT(Blueprintable) -struct FJSONBugData +struct FBugzillaJSONBugData { GENERATED_BODY() public: @@ -224,12 +224,12 @@ public: }; USTRUCT(Blueprintable) -struct FJSONBugResponse +struct FBugzillaJSONBugResponse { GENERATED_BODY() public: UPROPERTY(BlueprintReadOnly) - TArray bugs; + TArray bugs; UPROPERTY(BlueprintReadOnly) bool error = false; UPROPERTY(BlueprintReadOnly) diff --git a/Source/Unrealzilla/Public/JSON/JiraJSONStructs.h b/Source/Unrealzilla/Public/JSON/JiraJSONStructs.h new file mode 100644 index 0000000..73ae81e --- /dev/null +++ b/Source/Unrealzilla/Public/JSON/JiraJSONStructs.h @@ -0,0 +1,7 @@ +// ©2022 Batty Bovine Productions, LLC. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" + +//#include "JiraJSONStructs.generated.h" diff --git a/Source/Unrealzilla/Public/ServerREST.h b/Source/Unrealzilla/Public/ServerREST.h new file mode 100644 index 0000000..a8b14fc Binary files /dev/null and b/Source/Unrealzilla/Public/ServerREST.h differ diff --git a/Source/Unrealzilla/Public/UnrealzillaGlobalSettings.h b/Source/Unrealzilla/Public/UnrealzillaGlobalSettings.h index 0bb4d96..96edce1 100644 --- a/Source/Unrealzilla/Public/UnrealzillaGlobalSettings.h +++ b/Source/Unrealzilla/Public/UnrealzillaGlobalSettings.h @@ -24,22 +24,21 @@ public: UPROPERTY(Config, BlueprintReadOnly, EditDefaultsOnly, Category="Bug Placement", meta=(DisplayName="Arbitrary Placement Distance")) float ArbitraryBugPlacementDistance = 250.0f; - // The status to use when filing a new bug. A status such as "UNCONFIRMED" is suggested. - UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting") - FString DefaultStatus; - // The Bugzilla server where bugs will be posted. - UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting") + UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting|Bugzilla") FString SubmissionServer; // The name of the product for which bugs will be posted. - UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting") + UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting|Bugzilla") FString ProductName; // The API key to use when posting bugs. All bugs will be posted under the account of the owner of this API key. - UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting", meta=(DisplayName="API Key")) + UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting|Bugzilla", meta=(DisplayName="API Key")) FString APIKey; // The viewport depth of the bug report interface widget. - UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting") + UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting|Bugzilla") int32 BugReportWidgetDepth = 0; + // The status to use when filing a new bug. A status such as "UNCONFIRMED" is suggested. + UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting|Bugzilla") + FString DefaultStatus; // Whether to show unresolved bugs when displaying bug report markers. UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Marking")