Once again made a lot of changes that are too numerous to adequately describe. Rest assured it was a lot.

This commit is contained in:
Jamie Greunbaum 2023-03-23 02:22:06 -04:00
parent a19e70d8f6
commit 5abc7ca484
17 changed files with 636 additions and 86 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/M_Arrow.uasset Normal file

Binary file not shown.

Binary file not shown.

BIN
Content/SM_Arrow.uasset Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,6 @@
// ©2022 Batty Bovine Productions, LLC. All Rights Reserved.
#include "BugFormTextEntryButton.h"

View File

@ -75,7 +75,8 @@ void ABugPlacerPawn::Tick(float DeltaSeconds)
this->LaserGlow->SetVisibility(false, true); this->LaserGlow->SetVisibility(false, true);
// If the debugger requests arbitrary placement, put the marker a set distance away from the camera. // If the debugger requests arbitrary placement, put the marker a set distance away from the camera.
this->PlacementMarkerRoot->SetRelativeLocationAndRotation(FVector(GetDefault<UUnrealzillaGlobalSettings>()->ArbitraryBugPlacementDistance, 0.0f, 0.0f), FRotator::ZeroRotator); this->PlacementMarkerRoot->SetRelativeLocation(FVector(GetDefault<UUnrealzillaGlobalSettings>()->ArbitraryBugPlacementDistance, 0.0f, 0.0f));
this->PlacementMarkerRoot->SetWorldRotation(FRotator::ZeroRotator);
} }
else else
{ {
@ -108,24 +109,6 @@ void ABugPlacerPawn::Tick(float DeltaSeconds)
this->TraceOriginComponent->SetRelativeScale3D(FVector(1.0f, 1.0f, (TraceEnd - TraceStart).Length())); this->TraceOriginComponent->SetRelativeScale3D(FVector(1.0f, 1.0f, (TraceEnd - TraceStart).Length()));
} }
//#if ENABLE_DRAW_DEBUG
// if (bTraceHit && TraceHit.bBlockingHit)
// {
// // Line trace and impact point
// DrawDebugLine(World, TraceStart, TraceHit.ImpactPoint, FColor::Red, false);
// DrawDebugLine(World, TraceHit.ImpactPoint, TraceEnd, FColor::Green, false);
// DrawDebugPoint(World, TraceHit.ImpactPoint, 10.0f, FColor::Red, false);
//
// // Impact normal
// DrawDebugLine(World, TraceHit.ImpactPoint, TraceHit.ImpactPoint + (TraceHit.ImpactNormal * 50.0f), FColor(0, 100, 255, 255), false);
// }
// else
// {
// // Line trace, no impact
// DrawDebugLine(World, TraceStart, TraceEnd, FColor::Red, false);
// }
//#endif
} }
} }
@ -169,51 +152,31 @@ void ABugPlacerPawn::Deactivate()
void ABugPlacerPawn::ExitStarted() void ABugPlacerPawn::ExitStarted()
{ {
if (this->ExitingBugPlacementScreenClass.IsValid())
{
this->ExitingBugPlacementScreen = CreateWidget<UExitingBugPlacementScreen>(UGameplayStatics::GetPlayerController(this, 0), this->ExitingBugPlacementScreenClass.Get()); this->ExitingBugPlacementScreen = CreateWidget<UExitingBugPlacementScreen>(UGameplayStatics::GetPlayerController(this, 0), this->ExitingBugPlacementScreenClass.Get());
this->ExitingBugPlacementScreen->AddToViewport(GetDefault<UUnrealzillaGlobalSettings>()->BugReportWidgetDepth + 10); this->ExitingBugPlacementScreen->AddToViewport(GetDefault<UUnrealzillaGlobalSettings>()->BugReportWidgetDepth + 10);
}
else
{
this->ExitingBugPlacementScreen = nullptr;
}
} }
void ABugPlacerPawn::ExitOngoing(const float ElapsedSeconds) void ABugPlacerPawn::ExitOngoing(const float ElapsedSeconds)
{ {
if (this->ExitingBugPlacementScreen)
{
this->ExitingBugPlacementScreen->SetPercent(ElapsedSeconds); this->ExitingBugPlacementScreen->SetPercent(ElapsedSeconds);
}
} }
void ABugPlacerPawn::ExitTriggered() void ABugPlacerPawn::ExitTriggered()
{ {
if (this->ExitingBugPlacementScreen)
{
this->ExitingBugPlacementScreen->RemoveFromParent(); this->ExitingBugPlacementScreen->RemoveFromParent();
this->Deactivate(); this->Deactivate();
}
} }
void ABugPlacerPawn::ExitCanceled() void ABugPlacerPawn::ExitCanceled()
{ {
if (this->ExitingBugPlacementScreen)
{
this->ExitingBugPlacementScreen->RemoveFromParent(); this->ExitingBugPlacementScreen->RemoveFromParent();
}
} }
void ABugPlacerPawn::SpawnBugPlacerPawn(const UObject *WorldContextObject, TSoftClassPtr<ABugPlacerPawn> Class) void ABugPlacerPawn::SpawnBugPlacerPawn(const UObject *WorldContextObject, TSubclassOf<ABugPlacerPawn> Class)
{ {
if (Class.IsValid())
{
const FTransform &Transform = UGameplayStatics::GetPlayerCameraManager(WorldContextObject, 0)->GetActorTransform(); const FTransform &Transform = UGameplayStatics::GetPlayerCameraManager(WorldContextObject, 0)->GetActorTransform();
FActorSpawnParameters SpawnParams; FActorSpawnParameters SpawnParams;
//SpawnParams.Name = TEXT("BugPlacerPawn");
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
WorldContextObject->GetWorld()->SpawnActor<ABugPlacerPawn>(Class.Get(), Transform, SpawnParams); WorldContextObject->GetWorld()->SpawnActor<ABugPlacerPawn>(Class.Get(), Transform, SpawnParams);
}
} }

View File

@ -6,8 +6,12 @@
#include "CommonButtonBase.h" #include "CommonButtonBase.h"
#include "CommonTextBlock.h" #include "CommonTextBlock.h"
#include "HttpModule.h" #include "HttpModule.h"
#include "JsonObjectConverter.h"
#include "UnrealzillaGlobalSettings.h" #include "UnrealzillaGlobalSettings.h"
#include "Components/CircularThrobber.h"
#include "Components/Overlay.h" #include "Components/Overlay.h"
#include "Components/VerticalBox.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
@ -23,13 +27,70 @@ const FText FormatFloatToText(float Float, int32 IntegralDigits, int32 Fractiona
NumberFormat.MaximumIntegralDigits = INT32_MAX; NumberFormat.MaximumIntegralDigits = INT32_MAX;
NumberFormat.MinimumFractionalDigits = FractionalDigits; NumberFormat.MinimumFractionalDigits = FractionalDigits;
NumberFormat.MaximumFractionalDigits = FractionalDigits; NumberFormat.MaximumFractionalDigits = FractionalDigits;
NumberFormat.UseGrouping = false;
return FText::AsNumber(Float, &NumberFormat); return FText::AsNumber(Float, &NumberFormat);
} }
const FString 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("&"));
}
void UBugSubmissionForm::NativeOnInitialized() void UBugSubmissionForm::NativeOnInitialized()
{ {
this->ShowProcessingOverlayLoading();
this->ProductNameValue->SetText(FText::FromString(GetDefault<UUnrealzillaGlobalSettings>()->ProductName));
const FString FullURL = GetDefault<UUnrealzillaGlobalSettings>()->SubmissionServer + "/rest.cgi";
// Assemble query data into key:value pairs
TMap<FString, FString> QueryData;
QueryData.Add("api_key", GetDefault<UUnrealzillaGlobalSettings>()->APIKey);
const FString QueryString = 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);
} }
@ -58,27 +119,75 @@ void UBugSubmissionForm::SetMarkerData(ABugMarkerActor *BugMarker)
FFormatNamedArguments MapDataArgs; FFormatNamedArguments MapDataArgs;
MapDataArgs.Add("MarkerLocation", MarkerLocationText); MapDataArgs.Add("MarkerLocation", MarkerLocationText);
MapDataArgs.Add("MarkerUpVector", MarkerUpVectorText); MapDataArgs.Add("MarkerUpVector", MarkerUpVectorText);
const FText MapDataText = FText::Format(NSLOCTEXT("BugSubmissionForm", "MapDataFormat", "{MarkerLocation}\n{MarkerUpVector}"), MapDataArgs); const FText MapDataText = FText::Format(NSLOCTEXT("BugSubmissionForm", "MapDataFormat", "{MarkerLocation}:{MarkerUpVector}"), MapDataArgs);
this->LocationValue->SetText(MapDataText); this->LocationValue->SetText(MapDataText);
} }
void UBugSubmissionForm::ShowProcessingOverlayLoading()
{
this->ProcessingRequestErrorText->SetText(FText::FromString(""));
this->ProcessingRequestOverlay->SetVisibility(ESlateVisibility::Visible);
this->ProcessingRequestThrobber->SetVisibility(ESlateVisibility::Visible);
this->ProcessingRequestErrorBox->SetVisibility(ESlateVisibility::Collapsed);
}
void UBugSubmissionForm::ShowProcessingOverlayMessage(const FString Message)
{
this->ProcessingRequestErrorText->SetText(FText::FromString(Message));
this->ProcessingRequestOverlay->SetVisibility(ESlateVisibility::Visible);
this->ProcessingRequestThrobber->SetVisibility(ESlateVisibility::Collapsed);
this->ProcessingRequestErrorBox->SetVisibility(ESlateVisibility::Visible);
}
void UBugSubmissionForm::HideProcessingOverlay()
{
this->ProcessingRequestOverlay->SetVisibility(ESlateVisibility::Collapsed);
}
void UBugSubmissionForm::SubmitForm() void UBugSubmissionForm::SubmitForm()
{ {
this->ProcessingRequestOverlay->SetVisibility(ESlateVisibility::Visible); this->ShowProcessingOverlayLoading();
const FString RESTURL = "/rest.cgi"; const FString FullURL = GetDefault<UUnrealzillaGlobalSettings>()->SubmissionServer + "/rest.cgi";
const FString RequestURL = "/bug"; const FString RequestURL = "/bug";
const FString QueryString = "api_key=" + GetDefault<UUnrealzillaGlobalSettings>()->APIKey;
// Assemble query data into key:value pairs
TMap<FString, FString> QueryData;
QueryData.Add("api_key", GetDefault<UUnrealzillaGlobalSettings>()->APIKey);
const FString SummaryText = this->SummaryEntryBox->GetText().ToString();
const FString CommentText = this->CommentEntryBox->GetText().ToString();
if (SummaryText.IsEmpty())
{
this->ShowProcessingOverlayMessage("You must provide a summary.");
}
//if (CommentText.IsEmpty())
//{
// this->ShowProcessingOverlayMessage("You must provide a description.");
//}
FString PostJsonString;
FJSONPostBug PostData;
PostData.product = GetDefault<UUnrealzillaGlobalSettings>()->ProductName;
PostData.component = "Component";
PostData.version = "unspecified";
PostData.cf_mapname = this->MapNameValue->GetText().ToString();
PostData.cf_location = this->LocationValue->GetText().ToString();
PostData.summary = SummaryText;
PostData.description = CommentText;
FJsonObjectConverter::UStructToJsonObjectString(PostData, PostJsonString);
FHttpModule &HttpModule = FHttpModule::Get(); FHttpModule &HttpModule = FHttpModule::Get();
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> Request = HttpModule.CreateRequest(); TSharedRef<IHttpRequest, ESPMode::ThreadSafe> Request = HttpModule.CreateRequest();
Request->SetVerb(TEXT("GET")); Request->SetVerb(TEXT("POST"));
Request->SetHeader(TEXT("Content-Type"), TEXT("application/json")); Request->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
Request->SetURL(GetDefault<UUnrealzillaGlobalSettings>()->SubmissionServer + RESTURL + RequestURL Request->SetURL(FullURL + RequestURL + "?" + FormatQueryString(QueryData));
+ "?" + QueryString); Request->SetContentAsString(PostJsonString);
Request->OnProcessRequestComplete().BindUObject(this, &UBugSubmissionForm::ServerResponse); Request->OnProcessRequestComplete().BindUObject(this, &UBugSubmissionForm::ServerPOSTResponse);
Request->ProcessRequest(); Request->ProcessRequest();
this->OnFormSubmit.ExecuteIfBound(); this->OnFormSubmit.ExecuteIfBound();
@ -101,34 +210,226 @@ void UBugSubmissionForm::CloseForm()
} }
void UBugSubmissionForm::ServerResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success) void UBugSubmissionForm::ServerPOSTResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success)
{ {
if (Success) if (Success)
{ {
UE_LOG(LogTemp, Log, TEXT("%s"), *Response->GetContentAsString()); FJSONPostResponse ResponseData;
FString JSONResponse = Response->GetContentAsString();
FJsonObjectConverter::JsonObjectStringToUStruct(JSONResponse, &ResponseData);
this->CloseForm(); if (ResponseData.error)
{
this->ShowProcessingOverlayMessage(ResponseData.message);
} }
else else
{ {
switch (Request->GetStatus()) { this->CloseForm();
case EHttpRequestStatus::Failed_ConnectionError:
UE_LOG(LogTemp, Error, TEXT("Unable to connect"));
break;
case EHttpRequestStatus::NotStarted:
UE_LOG(LogTemp, Error, TEXT("Connection not started"));
break;
case EHttpRequestStatus::Processing:
UE_LOG(LogTemp, Error, TEXT("Connection processing"));
break;
case EHttpRequestStatus::Failed:
UE_LOG(LogTemp, Error, TEXT("Connection failed"));
break;
case EHttpRequestStatus::Succeeded:
UE_LOG(LogTemp, Log, TEXT("Connection succeeded"));
break;
default:
UE_LOG(LogTemp, Error, TEXT("Request failed"));
} }
} }
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
{
for (const FJSONProductData &ProductData : ResponseData.products)
{
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);
}
break;
}
}
this->CheckIfAllInitialResponsesAreIn();
}
}
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())
{
if (this->PlatformsList.Contains("PC"))
{
if (UGameplayStatics::GetPlatformName() == "Windows" && this->OSList.Contains("Windows"))
{
this->ShowProcessingOverlayMessage("Windows detected");
}
else if (UGameplayStatics::GetPlatformName() == "Linux" && this->OSList.Contains("Linux"))
{
this->ShowProcessingOverlayMessage("Linux on PC detected");
}
else if (UGameplayStatics::GetPlatformName() == "Mac" && this->OSList.Contains("Mac OS"))
{
this->ShowProcessingOverlayMessage("This should not be possible");
}
else
{
this->ShowProcessingOverlayMessage("Could not auto-detect operating system");
}
}
else if (this->PlatformsList.Contains("Macintosh"))
{
if (UGameplayStatics::GetPlatformName() == "Windows" && this->OSList.Contains("Windows"))
{
this->ShowProcessingOverlayMessage("Windows on a Macintosh detected");
}
else if (UGameplayStatics::GetPlatformName() == "Linux" && this->OSList.Contains("Linux"))
{
this->ShowProcessingOverlayMessage("Linux on a Macintosh detected");
}
else if (UGameplayStatics::GetPlatformName() == "Mac" && this->OSList.Contains("Mac OS"))
{
this->ShowProcessingOverlayMessage("macOS detected");
}
else
{
this->ShowProcessingOverlayMessage("Could not auto-detect operating system");
}
}
else // At this stage, don't bother trying to auto-detect; we'll just set it to All here.
{
this->ShowProcessingOverlayMessage("Can't auto-detect platform");
}
//this->HideProcessingOverlay();
}
}
void UBugSubmissionForm::ServerConnectionError(const EHttpRequestStatus::Type Status)
{
switch (Status) {
case EHttpRequestStatus::Failed_ConnectionError:
this->ShowProcessingOverlayMessage("Unable to connect to the server");
break;
case EHttpRequestStatus::NotStarted:
this->ShowProcessingOverlayMessage("Connection could not start");
break;
case EHttpRequestStatus::Failed:
this->ShowProcessingOverlayMessage("Connection failed");
break;
default:
this->ShowProcessingOverlayMessage("Request failed for unknown reasons");
}
} }

View File

@ -0,0 +1,26 @@
// ©2022 Batty Bovine Productions, LLC. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "CommonButtonBase.h"
#include "CommonTextBlock.h"
#include "BugFormTextEntryButton.generated.h"
UCLASS()
class UNREALZILLA_API UBugFormTextEntryButton : public UCommonButtonBase
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void SetText(const FText Text) { this->TextLabel->SetText(Text); }
UFUNCTION(BlueprintPure)
FText GetText() const { return this->TextLabel->GetText(); }
protected:
UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UCommonTextBlock> TextLabel;
};

View File

@ -28,7 +28,7 @@ public:
void Deactivate(); void Deactivate();
UFUNCTION(BlueprintCallable, meta=(WorldContext="WorldContextObject")) UFUNCTION(BlueprintCallable, meta=(WorldContext="WorldContextObject"))
static void SpawnBugPlacerPawn(const UObject *WorldContextObject, TSoftClassPtr<class ABugPlacerPawn> Class); static void SpawnBugPlacerPawn(const UObject *WorldContextObject, TSubclassOf<class ABugPlacerPawn> Class);
protected: protected:
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
@ -64,9 +64,9 @@ protected:
TObjectPtr<class UFloatingPawnMovement> PawnMovement; TObjectPtr<class UFloatingPawnMovement> PawnMovement;
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly) UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
TSoftClassPtr<class ABugMarkerActor> BugMarkerBlueprintClass; TSubclassOf<class ABugMarkerActor> BugMarkerBlueprintClass;
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly) UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
TSoftClassPtr<class UExitingBugPlacementScreen> ExitingBugPlacementScreenClass; TSubclassOf<class UExitingBugPlacementScreen> ExitingBugPlacementScreenClass;
UPROPERTY(BlueprintReadWrite) UPROPERTY(BlueprintReadWrite)
float SavedMaxSpeed = 0.0f; float SavedMaxSpeed = 0.0f;

View File

@ -3,6 +3,8 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "BugFormTextEntryButton.h"
#include "CommonActivatableWidget.h" #include "CommonActivatableWidget.h"
#include "Interfaces/IHttpRequest.h" #include "Interfaces/IHttpRequest.h"
#include "Interfaces/IHttpResponse.h" #include "Interfaces/IHttpResponse.h"
@ -10,6 +12,221 @@
#include "BugSubmissionForm.generated.h" #include "BugSubmissionForm.generated.h"
/**
* JSON structs for POST
*/
USTRUCT()
struct FJSONPostBug
{
GENERATED_BODY()
public:
UPROPERTY()
FString product;
UPROPERTY()
FString component;
UPROPERTY()
FString version;
UPROPERTY()
FString cf_mapname;
UPROPERTY()
FString cf_location;
UPROPERTY()
FString platform;
UPROPERTY()
FString op_sys;
UPROPERTY()
FString summary;
UPROPERTY()
FString description;
};
USTRUCT(Blueprintable)
struct FJSONPostResponse
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
int32 id = -1;
UPROPERTY(BlueprintReadOnly)
bool error = false;
UPROPERTY(BlueprintReadOnly)
int32 code = -1;
UPROPERTY(BlueprintReadOnly)
FString message;
UPROPERTY(BlueprintReadOnly)
FString documentation;
};
/**
* END JSON structs for POST
*/
/**
* JSON structs for bug lists
*/
USTRUCT(Blueprintable)
struct FJSONBugData
{
GENERATED_BODY()
public:
UPROPERTY()
FString component;
UPROPERTY()
FString cf_mapname;
UPROPERTY()
FString cf_location;
};
USTRUCT(Blueprintable)
struct FJSONBugResponse
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
TArray<FJSONBugData> bugs;
UPROPERTY(BlueprintReadOnly)
bool error = false;
UPROPERTY(BlueprintReadOnly)
int32 code = -1;
UPROPERTY(BlueprintReadOnly)
FString message;
UPROPERTY(BlueprintReadOnly)
FString documentation;
};
/**
* END JSON structs for bug lists
*/
/**
* JSON structs for product data
*/
USTRUCT(Blueprintable)
struct FJSONComponentData
{
GENERATED_BODY()
public:
UPROPERTY()
int32 id = -1;
UPROPERTY()
bool is_active = false;
UPROPERTY()
FString name;
UPROPERTY()
FString description;
UPROPERTY()
FString default_assigned_to;
UPROPERTY()
int32 sort_key = -1;
};
USTRUCT(Blueprintable)
struct FJSONVersionData
{
GENERATED_BODY()
public:
UPROPERTY()
int32 id = -1;
UPROPERTY()
bool is_active = false;
UPROPERTY()
FString name;
UPROPERTY()
int32 sort_key = -1;
};
USTRUCT(Blueprintable)
struct FJSONProductData
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
FString name;
UPROPERTY(BlueprintReadOnly)
FString classification;
UPROPERTY(BlueprintReadOnly)
FString description;
UPROPERTY(BlueprintReadOnly)
TArray<FJSONComponentData> components;
UPROPERTY(BlueprintReadOnly)
TArray<FJSONVersionData> versions;
};
USTRUCT(Blueprintable)
struct FJSONProductResponse
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
TArray<FJSONProductData> products;
UPROPERTY(BlueprintReadOnly)
bool error = false;
UPROPERTY(BlueprintReadOnly)
int32 code = -1;
UPROPERTY(BlueprintReadOnly)
FString message;
UPROPERTY(BlueprintReadOnly)
FString documentation;
};
/**
* END JSON structs for product data
*/
/**
* JSON structs for product data
*/
USTRUCT(Blueprintable)
struct FJSONFieldValueData
{
GENERATED_BODY()
public:
UPROPERTY()
FString name;
UPROPERTY()
int32 sort_key = -1;
};
USTRUCT(Blueprintable)
struct FJSONFieldData
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
int32 id = -1;
UPROPERTY(BlueprintReadOnly)
FString name;
UPROPERTY(BlueprintReadOnly)
FString display_name;
UPROPERTY(BlueprintReadOnly)
bool is_mandatory = false;
UPROPERTY(BlueprintReadOnly)
TArray<FJSONFieldValueData> values;
};
USTRUCT(Blueprintable)
struct FJSONFieldResponse
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
TArray<FJSONFieldData> fields;
UPROPERTY(BlueprintReadOnly)
bool error = false;
UPROPERTY(BlueprintReadOnly)
int32 code = -1;
UPROPERTY(BlueprintReadOnly)
FString message;
UPROPERTY(BlueprintReadOnly)
FString documentation;
};
/**
* END JSON structs for product data
*/
UCLASS() UCLASS()
class UNREALZILLA_API UBugSubmissionForm : public UCommonActivatableWidget class UNREALZILLA_API UBugSubmissionForm : public UCommonActivatableWidget
{ {
@ -26,12 +243,19 @@ public:
protected: protected:
virtual void NativeOnInitialized() override; virtual void NativeOnInitialized() override;
UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName="Display POST Response"))
void DisplayPOSTResponse(const FJSONPostResponse &Response);
UPROPERTY(BlueprintReadOnly, meta=(BindWidget)) UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UCommonTextBlock> ProductNameValue; TObjectPtr<class UCommonTextBlock> ProductNameValue;
UPROPERTY(BlueprintReadOnly, meta=(BindWidget)) UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UCommonTextBlock> MapNameValue; TObjectPtr<class UCommonTextBlock> MapNameValue;
UPROPERTY(BlueprintReadOnly, meta=(BindWidget)) UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UCommonTextBlock> LocationValue; TObjectPtr<class UCommonTextBlock> LocationValue;
UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UBugFormTextEntryButton> SummaryEntryBox;
UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UBugFormTextEntryButton> CommentEntryBox;
UPROPERTY(BlueprintReadOnly, meta=(BindWidget)) UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UCommonButtonBase> CancelButton; TObjectPtr<class UCommonButtonBase> CancelButton;
@ -40,9 +264,27 @@ protected:
UPROPERTY(BlueprintReadOnly, meta=(BindWidget)) UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UOverlay> ProcessingRequestOverlay; TObjectPtr<class UOverlay> ProcessingRequestOverlay;
UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UCircularThrobber> ProcessingRequestThrobber;
UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UVerticalBox> ProcessingRequestErrorBox;
UPROPERTY(BlueprintReadOnly, meta=(BindWidget))
TObjectPtr<class UCommonTextBlock> ProcessingRequestErrorText;
private: private:
void ServerResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool Success); void ServerPOSTResponse(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)
void ShowProcessingOverlayMessage(const FString Message);
UFUNCTION(BlueprintCallable)
void HideProcessingOverlay();
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void SubmitForm(); void SubmitForm();
@ -51,5 +293,13 @@ private:
void CloseForm(); void CloseForm();
void ServerConnectionError(const EHttpRequestStatus::Type Status);
TArray<FString> ComponentList;
TArray<FString> VersionsList;
TArray<FString> SeverityList;
TArray<FString> PlatformsList;
TArray<FString> OSList;
TObjectPtr<class ABugMarkerActor> BugMarkerActor; TObjectPtr<class ABugMarkerActor> BugMarkerActor;
}; };

View File

@ -17,12 +17,14 @@ class UNREALZILLA_API UUnrealzillaGlobalSettings : public UDeveloperSettingsBack
public: public:
UPROPERTY(Config, BlueprintReadOnly, EditDefaultsOnly, Category="Bug Placement", meta=(DisplayName="Precise Placement Distance")) UPROPERTY(Config, BlueprintReadOnly, EditDefaultsOnly, Category="Bug Placement", meta=(DisplayName="Precise Placement Distance"))
float BugPlacementTraceDistance = 1000.0f; float BugPlacementTraceDistance = 1500.0f;
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;
UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting") UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting")
FString SubmissionServer; FString SubmissionServer;
UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting")
FString ProductName;
UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting", meta=(DisplayName="API Key")) UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting", meta=(DisplayName="API Key"))
FString APIKey; FString APIKey;
UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting") UPROPERTY(Config, EditDefaultsOnly, BlueprintReadOnly, Category="Reporting")

View File

@ -39,6 +39,8 @@ namespace UnrealBuildTool.Rules
new string[] new string[]
{ {
"HTTP", "HTTP",
"Json",
"JsonUtilities",
"UMG", "UMG",
"CommonUI" "CommonUI"
} }