Reworked a whole lot of code so that we can eventually add more than just Bugzilla support to the plugin.

This commit is contained in:
Jamie Greunbaum
2023-03-30 18:59:16 -04:00
parent 3f20507962
commit 5816ec390b
21 changed files with 98 additions and 672 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -10,15 +10,15 @@
EBugStatus ABugMarkerActor::GetBugStatus() const EBugStatus ABugMarkerActor::GetBugStatus() const
{ {
if (GetDefault<UUnrealzillaGlobalSettings>()->ResolvedStatuses.Contains(this->BugData.status)) if (GetDefault<UUnrealzillaGlobalSettings>()->ResolvedStatuses.Contains(this->BugData.Status))
{ {
return EBugStatus::Resolved; return EBugStatus::Resolved;
} }
else if (GetDefault<UUnrealzillaGlobalSettings>()->InProgressStatuses.Contains(this->BugData.status)) else if (GetDefault<UUnrealzillaGlobalSettings>()->InProgressStatuses.Contains(this->BugData.Status))
{ {
return EBugStatus::InProgress; return EBugStatus::InProgress;
} }
else if (GetDefault<UUnrealzillaGlobalSettings>()->UnresolvedStatuses.Contains(this->BugData.status)) else if (GetDefault<UUnrealzillaGlobalSettings>()->UnresolvedStatuses.Contains(this->BugData.Status))
{ {
return EBugStatus::Unresolved; return EBugStatus::Unresolved;
} }
@@ -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<UUnrealzillaGlobalSettings>()->SubmissionServer + "/rest.cgi";
TArray<FString> StatusQueries;
if (GetDefault<UUnrealzillaGlobalSettings>()->bShowUnresolvedBugs)
{
for (const FString Unresolved : GetDefault<UUnrealzillaGlobalSettings>()->UnresolvedStatuses)
{
StatusQueries.Add("status=" + Unresolved);
}
}
if (GetDefault<UUnrealzillaGlobalSettings>()->bShowInProgressBugs)
{
for (const FString InProgress : GetDefault<UUnrealzillaGlobalSettings>()->InProgressStatuses)
{
StatusQueries.Add("status=" + InProgress);
}
}
if (GetDefault<UUnrealzillaGlobalSettings>()->bShowResolvedBugs)
{
for (const FString Resolved : GetDefault<UUnrealzillaGlobalSettings>()->ResolvedStatuses)
{
StatusQueries.Add("status=" + Resolved);
}
}
StatusQueries.Add("cf_mapname=" + this->GetWorld()->GetMapName().RightChop(this->GetWorld()->StreamingLevelsPrefix.Len()));
StatusQueries.Add("api_key=" + GetDefault<UUnrealzillaGlobalSettings>()->APIKey);
const FString QueryString = FString::Join(StatusQueries, TEXT("&"));
FHttpModule &HttpModule = FHttpModule::Get();
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> 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<ABugMarkerActor> 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<ABugMarkerActor>(Class, Transform, SpawnParams);
Marker->SetBugData(BugData);
this->Markers.Add(Marker);
this->BugBatch.RemoveAt(0);
if (!(this->BugBatch.Num() % GetDefault<UUnrealzillaGlobalSettings>()->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<UUnrealzillaGlobalSettings>()->UnloadMarkersBatch))
{
break;
}
}
if (!this->Markers.IsEmpty())
{
this->GetWorldTimerManager().SetTimer(this->UnloadAllTimerHandle, this, &ABugMarkerLoader::UnloadAll, this->GetWorld()->GetDeltaSeconds());
}
else
{
this->Destroy();
}
}
Binary file not shown.
+7 -22
View File
@@ -3,10 +3,10 @@
#include "BugPlacerPawn.h" #include "BugPlacerPawn.h"
#include "BugMarkerActor.h" #include "BugMarkerActor.h"
#include "BugMarkerLoader.h" #include "BugMarkerSubsystem.h"
#include "ExitingBugPlacementScreen.h" #include "ExitingBugPlacementScreen.h"
#include "UnrealzillaGlobalSettings.h" #include "UnrealzillaGlobalSettings.h"
#include "UnrealzillaJSON.h" #include "BugzillaJSONStructs.h"
#include "Components/MaterialBillboardComponent.h" #include "Components/MaterialBillboardComponent.h"
#include "Components/SphereComponent.h" #include "Components/SphereComponent.h"
@@ -100,7 +100,7 @@ void ABugPlacerPawn::TraceTimerElapsed()
else else
{ {
this->PlacementMarkerRoot->SetVisibility(true, true); this->PlacementMarkerRoot->SetVisibility(true, true);
this->UpdateBugInformation(FJSONBugData()); this->UpdateBugInformation(FUnrealzillaBugData());
this->ShowDummyMarker(true); this->ShowDummyMarker(true);
} }
@@ -209,31 +209,16 @@ void ABugPlacerPawn::SpawnBugPlacerPawn(const UObject *WorldContextObject, TSubc
void ABugPlacerPawn::ShowBugMarkersInLevel(const UObject *WorldContextObject) void ABugPlacerPawn::ShowBugMarkersInLevel(const UObject *WorldContextObject)
{ {
for (TActorIterator<AActor> Iterator(WorldContextObject->GetWorld(), ABugMarkerLoader::StaticClass()); Iterator; ++Iterator) if (UBugMarkerSubsystem *BugMarkerSubsystem = UGameplayStatics::GetPlayerController(WorldContextObject, 0)->GetLocalPlayer()->GetSubsystem<UBugMarkerSubsystem>())
{ {
return; BugMarkerSubsystem->ShowBugMarkers();
} }
WorldContextObject->GetWorld()->SpawnActor<ABugMarkerLoader>(ABugMarkerLoader::StaticClass(), FVector::ZeroVector, FRotator::ZeroRotator);
} }
void ABugPlacerPawn::HideBugMarkersInLevel(const UObject *WorldContextObject) void ABugPlacerPawn::HideBugMarkersInLevel(const UObject *WorldContextObject)
{ {
for (TActorIterator<AActor> Iterator(WorldContextObject->GetWorld(), ABugMarkerLoader::StaticClass()); Iterator; ++Iterator) if (UBugMarkerSubsystem *BugMarkerSubsystem = UGameplayStatics::GetPlayerController(WorldContextObject, 0)->GetLocalPlayer()->GetSubsystem<UBugMarkerSubsystem>())
{ {
ABugMarkerLoader *BugMarkerLoader = Cast<ABugMarkerLoader>(*Iterator); BugMarkerSubsystem->HideBugMarkers();
BugMarkerLoader->UnloadAll();
} }
} }
const FString ABugPlacerPawn::FormatQueryString(const TMap<FString, FString> &QueryData)
{
TArray<FString> AssembledKeyValuePairs;
TArray<FString> QueryKeys;
QueryData.GenerateKeyArray(QueryKeys);
for (const FString &QueryKey : QueryKeys)
{
AssembledKeyValuePairs.Add(QueryKey + "=" + QueryData[QueryKey]);
}
return FString::Join(AssembledKeyValuePairs, TEXT("&"));
}
+40 -413
View File
@@ -3,13 +3,13 @@
#include "BugSubmissionForm.h" #include "BugSubmissionForm.h"
#include "BugMarkerActor.h" #include "BugMarkerActor.h"
#include "BugPlacerPawn.h" //#include "BugPlacerPawn.h"
#include "BugMarkerSubsystem.h"
#include "CommonButtonBase.h" #include "CommonButtonBase.h"
#include "CommonTextBlock.h" #include "CommonTextBlock.h"
#include "HttpModule.h" #include "HttpModule.h"
#include "JsonObjectConverter.h" #include "JsonObjectConverter.h"
#include "UnrealzillaGlobalSettings.h" #include "UnrealzillaGlobalSettings.h"
#include "UnrealzillaJSON.h"
#include "Components/CircularThrobber.h" #include "Components/CircularThrobber.h"
#include "Components/Overlay.h" #include "Components/Overlay.h"
@@ -33,67 +33,33 @@ const FText FormatFloatToText(float Float, int32 IntegralDigits, int32 Fractiona
return FText::AsNumber(Float, &NumberFormat); 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() void UBugSubmissionForm::NativeOnInitialized()
{ {
this->ShowProcessingOverlayLoading(); this->ShowProcessingOverlayLoading();
this->ProductNameValue->SetText(FText::AsCultureInvariant(GetDefault<UUnrealzillaGlobalSettings>()->ProductName)); this->ProductNameValue->SetText(FText::AsCultureInvariant(GetDefault<UUnrealzillaGlobalSettings>()->ProductName));
const FString FullURL = GetDefault<UUnrealzillaGlobalSettings>()->SubmissionServer + "/rest.cgi"; UBugMarkerSubsystem *BugMarkerSubsystem = UGameplayStatics::GetPlayerController(this, 0)->GetLocalPlayer()->GetSubsystem<UBugMarkerSubsystem>();
BugMarkerSubsystem->FormPrepResponse.BindUObject(this, &UBugSubmissionForm::PrepareFormData);
// Assemble query data into key:value pairs BugMarkerSubsystem->PrepareSubmissionFormData();
TMap<FString, FString> QueryData;
QueryData.Add("api_key", GetDefault<UUnrealzillaGlobalSettings>()->APIKey);
const FString QueryString = ABugPlacerPawn::FormatQueryString(QueryData);
// Query the server for information about the current product
FHttpModule &HttpModule = FHttpModule::Get();
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> ProductRequest = HttpModule.CreateRequest();
ProductRequest->SetVerb(TEXT("GET"));
ProductRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
ProductRequest->SetURL(FullURL + "/product/" + GetDefault<UUnrealzillaGlobalSettings>()->ProductName + "?" + QueryString);
ProductRequest->OnProcessRequestComplete().BindUObject(this, &UBugSubmissionForm::ServerProductInfoResponse);
ProductRequest->ProcessRequest();
// Send a second query to retrieve severity options
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> 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<IHttpRequest, ESPMode::ThreadSafe> 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<IHttpRequest, ESPMode::ThreadSafe> 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();
this->SubmitButton->OnClicked().AddUObject(this, &UBugSubmissionForm::SubmitForm); this->SubmitButton->OnClicked().AddUObject(this, &UBugSubmissionForm::SubmitForm);
this->CancelButton->OnClicked().AddUObject(this, &UBugSubmissionForm::CancelForm); 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) void UBugSubmissionForm::SetMarkerData(ABugMarkerActor *BugMarker)
@@ -153,74 +119,30 @@ void UBugSubmissionForm::SubmitForm()
{ {
this->ShowProcessingOverlayLoading(); this->ShowProcessingOverlayLoading();
const FString FullURL = GetDefault<UUnrealzillaGlobalSettings>()->SubmissionServer + "/rest.cgi"; FUnrealzillaPostData PostData;
const FString RequestURL = "/bug"; 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 UBugMarkerSubsystem *BugMarkerSubsystem = UGameplayStatics::GetPlayerController(this, 0)->GetLocalPlayer()->GetSubsystem<UBugMarkerSubsystem>();
TMap<FString, FString> QueryData; BugMarkerSubsystem->FormPostResponse.BindUObject(this, &UBugSubmissionForm::UpdateReportMarker);
QueryData.Add("api_key", GetDefault<UUnrealzillaGlobalSettings>()->APIKey); BugMarkerSubsystem->SubmitForm(PostData);
const FString SummaryText = this->SummaryEntryBox->GetText().ToString();
const FString CommentText = this->CommentEntryBox->GetText().ToString();
const FString DefaultStatus = GetDefault<UUnrealzillaGlobalSettings>()->DefaultStatus;
FString PostJsonString;
FJSONPostBug PostData;
PostData.product = GetDefault<UUnrealzillaGlobalSettings>()->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<IHttpRequest, ESPMode::ThreadSafe> 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();
this->OnFormSubmit.ExecuteIfBound(); this->OnFormSubmit.ExecuteIfBound();
} }
void UBugSubmissionForm::UpdateReportMarker(const FUnrealzillaBugData &BugData)
{
this->BugMarkerActor->SetBugData(BugData);
this->CloseForm();
}
void UBugSubmissionForm::CancelForm() void UBugSubmissionForm::CancelForm()
{ {
this->OnFormCancelled.ExecuteIfBound(); 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) this->ShowProcessingOverlayMessage(Error.ErrorMessage);
{
FJSONPostResponse ResponseData;
FString JSONResponse = Response->GetContentAsString();
FJsonObjectConverter::JsonObjectStringToUStruct(JSONResponse, &ResponseData);
if (ResponseData.error)
{
this->ShowProcessingOverlayMessage(ResponseData.message);
}
else
{
const FString FullURL = GetDefault<UUnrealzillaGlobalSettings>()->SubmissionServer + "/rest.cgi";
TArray<FString> StatusQueries;
StatusQueries.Add("id=" + FString::FromInt(ResponseData.id));
if (GetDefault<UUnrealzillaGlobalSettings>()->bShowUnresolvedBugs)
{
for (const FString Unresolved : GetDefault<UUnrealzillaGlobalSettings>()->UnresolvedStatuses)
{
StatusQueries.Add("status=" + Unresolved);
}
}
if (GetDefault<UUnrealzillaGlobalSettings>()->bShowInProgressBugs)
{
for (const FString InProgress : GetDefault<UUnrealzillaGlobalSettings>()->InProgressStatuses)
{
StatusQueries.Add("status=" + InProgress);
}
}
if (GetDefault<UUnrealzillaGlobalSettings>()->bShowResolvedBugs)
{
for (const FString Resolved : GetDefault<UUnrealzillaGlobalSettings>()->ResolvedStatuses)
{
StatusQueries.Add("status=" + Resolved);
}
}
StatusQueries.Add("cf_mapname=" + this->GetWorld()->GetMapName().RightChop(this->GetWorld()->StreamingLevelsPrefix.Len()));
StatusQueries.Add("api_key=" + GetDefault<UUnrealzillaGlobalSettings>()->APIKey);
const FString QueryString = FString::Join(StatusQueries, TEXT("&"));
FHttpModule &HttpModule = FHttpModule::Get();
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> 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<UUnrealzillaGlobalSettings>()->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<UUnrealzillaGlobalSettings>()->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);
}
} }
Binary file not shown.
+5 -4
View File
@@ -3,7 +3,8 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "UnrealzillaJSON.h"
#include "ServerREST.h"
#include "BugMarkerActor.generated.h" #include "BugMarkerActor.generated.h"
@@ -32,12 +33,12 @@ public:
void LoadBugSubmissionForm(); void LoadBugSubmissionForm();
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void SetBugData(const FJSONBugData &Data) { this->BugData = Data; this->ReloadBugData(); } void SetBugData(const FUnrealzillaBugData &Data) { this->BugData = Data; this->ReloadBugData(); }
UFUNCTION(BlueprintPure) UFUNCTION(BlueprintPure)
FJSONBugData GetBugData() const { return this->BugData; } FUnrealzillaBugData GetBugData() const { return this->BugData; }
UFUNCTION(BlueprintPure) UFUNCTION(BlueprintPure)
EBugStatus GetBugStatus() const; EBugStatus GetBugStatus() const;
protected: protected:
FJSONBugData BugData; FUnrealzillaBugData BugData;
}; };
@@ -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<AActor*> Markers;
TArray<FJSONBugData> BugBatch;
FTimerHandle NewBatchTimerHandle;
FTimerHandle UnloadAllTimerHandle;
};
Binary file not shown.
+2 -5
View File
@@ -3,7 +3,7 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "UnrealzillaJSON.h" #include "BugzillaJSONStructs.h"
#include "GameFramework/Pawn.h" #include "GameFramework/Pawn.h"
#include "BugPlacerPawn.generated.h" #include "BugPlacerPawn.generated.h"
@@ -27,7 +27,7 @@ public:
void Deactivate(); void Deactivate();
UFUNCTION(BlueprintImplementableEvent) UFUNCTION(BlueprintImplementableEvent)
void UpdateBugInformation(const FJSONBugData &BugData); void UpdateBugInformation(const FUnrealzillaBugData &BugData);
UFUNCTION(BlueprintImplementableEvent) UFUNCTION(BlueprintImplementableEvent)
void ShowDummyMarker(const bool bShow); void ShowDummyMarker(const bool bShow);
UFUNCTION(BlueprintImplementableEvent) UFUNCTION(BlueprintImplementableEvent)
@@ -40,9 +40,6 @@ public:
UFUNCTION(BlueprintCallable, meta=(WorldContext="WorldContextObject")) UFUNCTION(BlueprintCallable, meta=(WorldContext="WorldContextObject"))
static void HideBugMarkersInLevel(const UObject *WorldContextObject); static void HideBugMarkersInLevel(const UObject *WorldContextObject);
UFUNCTION(BlueprintPure)
static const FString FormatQueryString(const TMap<FString, FString> &QueryData);
protected: protected:
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void SetArbitraryPlacement(bool bSet); void SetArbitraryPlacement(bool bSet);
+9 -15
View File
@@ -6,7 +6,7 @@
#include "BugFormButton.h" #include "BugFormButton.h"
#include "CommonActivatableWidget.h" #include "CommonActivatableWidget.h"
#include "UnrealzillaJSON.h" #include "BugzillaJSONStructs.h"
#include "Interfaces/IHttpRequest.h" #include "Interfaces/IHttpRequest.h"
#include "Interfaces/IHttpResponse.h" #include "Interfaces/IHttpResponse.h"
@@ -30,7 +30,7 @@ protected:
virtual void NativeOnInitialized() override; virtual void NativeOnInitialized() override;
UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName="Display POST Response")) UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName="Display POST Response"))
void DisplayPOSTResponse(const FJSONPostResponse &Response); void DisplayPOSTResponse(const FBugzillaJSONPostResponse &Response);
UPROPERTY(BlueprintReadOnly, meta=(BindWidget)) UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UCommonTextBlock> ProductNameValue; TObjectPtr<class UCommonTextBlock> ProductNameValue;
@@ -67,26 +67,18 @@ protected:
UPROPERTY(BlueprintReadOnly, meta=(BindWidget)) UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UCommonButtonBase> ProcessingRequestErrorButton; TObjectPtr<class UCommonButtonBase> ProcessingRequestErrorButton;
UPROPERTY(BlueprintReadOnly)
TArray<FString> ComponentsList;
UPROPERTY(BlueprintReadOnly)
TArray<FString> SeverityList;
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
TArray<FString> VersionsList; TArray<FString> VersionsList;
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
TArray<FString> PlatformsList; TArray<FString> PlatformsList;
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
TArray<FString> OSList; TArray<FString> OSList;
UPROPERTY(BlueprintReadOnly)
TArray<FString> ComponentList;
UPROPERTY(BlueprintReadOnly)
TArray<FString> SeverityList;
private: 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) UFUNCTION(BlueprintCallable)
void ShowProcessingOverlayLoading(); void ShowProcessingOverlayLoading();
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
@@ -101,7 +93,9 @@ private:
void CloseForm(); 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 MapName;
FText MarkerLocation; FText MarkerLocation;
@@ -4,14 +4,14 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "UnrealzillaJSON.generated.h" #include "BugzillaJSONStructs.generated.h"
/** /**
* JSON structs for POST * JSON structs for POST
*/ */
USTRUCT() USTRUCT()
struct FJSONPostBug struct FBugzillaJSONPostBug
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
@@ -40,7 +40,7 @@ public:
}; };
USTRUCT(Blueprintable) USTRUCT(Blueprintable)
struct FJSONPostResponse struct FBugzillaJSONPostResponse
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
@@ -64,7 +64,7 @@ public:
* JSON structs for product data * JSON structs for product data
*/ */
USTRUCT(Blueprintable) USTRUCT(Blueprintable)
struct FJSONComponentData struct FBugzillaJSONComponentData
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
@@ -83,7 +83,7 @@ public:
}; };
USTRUCT(Blueprintable) USTRUCT(Blueprintable)
struct FJSONVersionData struct FBugzillaJSONVersionData
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
@@ -98,7 +98,7 @@ public:
}; };
USTRUCT(Blueprintable) USTRUCT(Blueprintable)
struct FJSONProductData struct FBugzillaJSONProductData
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
@@ -109,18 +109,18 @@ public:
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
FString description; FString description;
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
TArray<FJSONComponentData> components; TArray<FBugzillaJSONComponentData> components;
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
TArray<FJSONVersionData> versions; TArray<FBugzillaJSONVersionData> versions;
}; };
USTRUCT(Blueprintable) USTRUCT(Blueprintable)
struct FJSONProductResponse struct FBugzillaJSONProductResponse
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
TArray<FJSONProductData> products; TArray<FBugzillaJSONProductData> products;
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
bool error = false; bool error = false;
@@ -140,7 +140,7 @@ public:
* JSON structs for product data * JSON structs for product data
*/ */
USTRUCT(Blueprintable) USTRUCT(Blueprintable)
struct FJSONFieldValueData struct FBugzillaJSONFieldValueData
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
@@ -151,7 +151,7 @@ public:
}; };
USTRUCT(Blueprintable) USTRUCT(Blueprintable)
struct FJSONFieldData struct FBugzillaJSONFieldData
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
@@ -164,16 +164,16 @@ public:
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
bool is_mandatory = false; bool is_mandatory = false;
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
TArray<FJSONFieldValueData> values; TArray<FBugzillaJSONFieldValueData> values;
}; };
USTRUCT(Blueprintable) USTRUCT(Blueprintable)
struct FJSONFieldResponse struct FBugzillaJSONFieldResponse
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
TArray<FJSONFieldData> fields; TArray<FBugzillaJSONFieldData> fields;
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
bool error = false; bool error = false;
@@ -193,7 +193,7 @@ public:
* JSON structs for bug lists * JSON structs for bug lists
*/ */
USTRUCT(Blueprintable) USTRUCT(Blueprintable)
struct FJSONBugData struct FBugzillaJSONBugData
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
@@ -224,12 +224,12 @@ public:
}; };
USTRUCT(Blueprintable) USTRUCT(Blueprintable)
struct FJSONBugResponse struct FBugzillaJSONBugResponse
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
TArray<FJSONBugData> bugs; TArray<FBugzillaJSONBugData> bugs;
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
bool error = false; bool error = false;
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
@@ -0,0 +1,7 @@
// ©2022 Batty Bovine Productions, LLC. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
//#include "JiraJSONStructs.generated.h"
Binary file not shown.
@@ -24,22 +24,21 @@ public:
UPROPERTY(Config, BlueprintReadOnly, EditDefaultsOnly, Category="Bug Placement", meta=(DisplayName="Arbitrary Placement Distance")) UPROPERTY(Config, BlueprintReadOnly, EditDefaultsOnly, Category="Bug Placement", meta=(DisplayName="Arbitrary Placement Distance"))
float ArbitraryBugPlacementDistance = 250.0f; 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. // The Bugzilla server where bugs will be posted.
UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting") UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting|Bugzilla")
FString SubmissionServer; FString SubmissionServer;
// The name of the product for which bugs will be posted. // 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; 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. // 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; FString APIKey;
// The viewport depth of the bug report interface widget. // 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; 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. // Whether to show unresolved bugs when displaying bug report markers.
UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Marking") UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Marking")