Adds Custom DataAsset UI + Added Request buttons for RaceDatas/TeamList/Rankings request to ApiStatus Tab + Addes Tracked Requests For Rankings + Added Utils Module For Blueprint Utilities Functions

This commit is contained in:
2025-07-08 16:50:31 +02:00
parent 7e1ce2cdfa
commit b63f2dd7b5
40 changed files with 4027 additions and 1199 deletions

View File

@ -5,12 +5,11 @@
#include "SlateOptMacros.h"
#include "DTFluxAPIStatusModule.h"
#include "EditorStyleSet.h"
#include "ISettingsCategory.h"
#include "ISettingsContainer.h"
#include "DTFluxCoreSubsystem.h"
#include "ISettingsModule.h"
#include "ISettingsSection.h"
#include "Styling/SlateIconFinder.h"
#include "MovieSceneSequenceID.h"
#include "OutputLogCreationParams.h"
#include "OutputLogModule.h"
#include "Types/Enum/DTFluxCoreEnum.h"
#include "Subsystems/DTFluxNetworkSubsystem.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
@ -27,32 +26,32 @@ void SDTFluxStatusWidget::OnOpenSettingsClicked()
FReply SDTFluxStatusWidget::OnRaceDatasClicked()
{
DTFlux->SendRequest(EDTFluxRequestType::RaceData);
DTFluxNetwork->SendRequest(EDTFluxRequestType::RaceData);
return FReply::Handled();
}
FReply SDTFluxStatusWidget::OnTeamListClicked()
{
DTFlux->SendRequest(EDTFluxRequestType::TeamList);
DTFluxNetwork->SendRequest(EDTFluxRequestType::TeamList);
return FReply::Handled();
}
void SDTFluxStatusWidget::Construct(const FArguments& InArgs)
{
DTFlux =
GEngine->GetEngineSubsystem<UDTFluxNetworkSubsystem>();
DTFluxNetwork =
GEngine->GetEngineSubsystem<UDTFluxNetworkSubsystem>();
DTFluxCore =
GEngine->GetEngineSubsystem<UDTFluxCoreSubsystem>();
ConnectionActionButtonText.Set(
DTFlux->WsStatus != EDTFluxConnectionStatus::Connected ?
FText::FromString("Connect") :
FText::FromString("Disconnect")
);
DTFluxNetwork->WsStatus != EDTFluxConnectionStatus::Connected
? FText::FromString("Connect")
: FText::FromString("Disconnect")
);
FOutputLogModule& OutputLogModule = FModuleManager::LoadModuleChecked<FOutputLogModule>("OutputLog");
const FOutputLogCreationParams Params;
bCanSupportFocus = true;
PopulateComboBoxItems();
FSlimHorizontalToolBarBuilder ToolBarBuilder(
nullptr,
FMultiBoxCustomization::None,
@ -72,234 +71,200 @@ void SDTFluxStatusWidget::Construct(const FArguments& InArgs)
}
ToolBarBuilder.EndSection();
FSlateFontInfo TitleTextFont = FCoreStyle::Get().GetFontStyle(FName("EmbossedText"));
TitleTextFont.Size = 15;
ChildSlot
[
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
#pragma region ToolBarSection
SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
[
SNew(SBox)
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.FillWidth(2.0)
SNew(SBox)
[
SNew(SSpacer)
]
+SHorizontalBox::Slot()
.AutoWidth()
.FillWidth(1.0)
.VAlign(VAlign_Center)
.HAlign(HAlign_Right)
[
ToolBarBuilder.MakeWidget()
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.FillWidth(2.0)
[
SNew(SSpacer)
]
+ SHorizontalBox::Slot()
.AutoWidth()
.FillWidth(1.0)
.VAlign(VAlign_Center)
.HAlign(HAlign_Right)
[
ToolBarBuilder.MakeWidget()
]
]
#pragma endregion
]
]
#pragma endregion
#pragma region WebsocketStatusSection
// Main VerticalBox
+SVerticalBox::Slot()
.AutoHeight()
[
SNew(SBorder)
.Padding(6.0f)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
.MaxWidth(175.0)
.MinWidth(150.0)
#pragma region WebsocketStatusSection
SNew(SBorder)
.Padding(6.0f)
[
SNew(STextBlock )
.Text(FText::FromString(TEXT("Websocket connection :")))
.Justification(ETextJustify::Left)
]
+SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.MinWidth(50.0)
.MaxWidth(100.0)
[
SAssignNew( WsStatusText, STextBlock)
.Text(this, &SDTFluxStatusWidget::GetWebSocketStatusText)
.Justification(ETextJustify::Left)
.ColorAndOpacity(this, &SDTFluxStatusWidget::GetWebSocketStatusColor)
]
+SHorizontalBox::Slot()
.MaxWidth(100.0)
.MinWidth(30.0)
[
SAssignNew(ConnectionActionButton, SButton)
.Text(this, &SDTFluxStatusWidget::GetWebConnectActionButtonText)
.ForegroundColor_Raw(this, &SDTFluxStatusWidget::GetWebConnectActionButtonColor)
.OnClicked(this,&SDTFluxStatusWidget::OnConnectionActionButtonClicked)
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
.ContentPadding(1.5f)
.MaxWidth(175.0)
.MinWidth(150.0)
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("Websocket connection :")))
.Justification(ETextJustify::Left)
]
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.MinWidth(50.0)
.MaxWidth(100.0)
[
SAssignNew(WsStatusText, STextBlock)
.Text(this, &SDTFluxStatusWidget::GetWebSocketStatusText)
.Justification(ETextJustify::Left)
.ColorAndOpacity(this, &SDTFluxStatusWidget::GetWebSocketStatusColor)
]
+ SHorizontalBox::Slot()
.MaxWidth(100.0)
.MinWidth(30.0)
[
SAssignNew(ConnectionActionButton, SButton)
.Text(this, &SDTFluxStatusWidget::GetWebConnectActionButtonText)
.ForegroundColor_Raw(this, &SDTFluxStatusWidget::GetWebConnectActionButtonColor)
.OnClicked(this, &SDTFluxStatusWidget::OnConnectionActionButtonClicked)
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
.ContentPadding(1.5f)
]
]
]
]
#pragma endregion
#pragma region DataModelControlSection
+SVerticalBox::Slot()
.VAlign(VAlign_Fill)
.HAlign(HAlign_Fill)
.AutoHeight()
[
SNew(SBox)
]
+ SVerticalBox::Slot()
.VAlign(VAlign_Fill)
.HAlign(HAlign_Fill)
.AutoHeight()
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
#pragma region DataModelControlSection
SNew(SBorder)
.Padding(6.0f)
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
[
SNew(SButton)
.Text(FText::FromString("Get RaceDatas"))
.OnClicked(this, &SDTFluxStatusWidget::OnRaceDatasClicked)
]
+SHorizontalBox::Slot()
[
SNew(SButton)
.Text(FText::FromString("Get TeamList"))
.OnClicked(this, &SDTFluxStatusWidget::OnTeamListClicked)
]
]
]
#pragma endregion
#pragma region HTTPStatusSection
// +SVerticalBox::Slot()
// .AutoHeight()
// [
// SNew(SHorizontalBox)
// +SHorizontalBox::Slot()
// [
// SNew(STextBlock)
// .Text(FText::FromString(TEXT("HTTP connection :")))
// .Justification(ETextJustify::Left)
// ]
// +SHorizontalBox::Slot()
// [
// SNew(STextBlock)
// .Text(FText::FromString(TEXT("invalid")))
// .Justification(ETextJustify::Center)
// .ColorAndOpacity(FColor::Red)
// ]
// +SHorizontalBox::Slot()
// [
// SNew(SButton)
// .Text(FText::FromString(TEXT("Connection test")))
// ]
// ]
#pragma endregion
#pragma region ContestsDataSection
// +SVerticalBox::Slot()
// .AutoHeight()
// .VAlign(VAlign_Fill)
// .HAlign(HAlign_Fill)
// [
// SNew(SBorder)
// .Padding(1.5f)
// .VAlign(VAlign_Fill)
// .HAlign(HAlign_Fill)
// [
// SNew(STextBlock)
// .Justification(ETextJustify::Left)
// .Text(FText::FromString("Contest :"))
// .ColorAndOpacity(FColor::White)
// ]
// ]
// +SVerticalBox::Slot()
// .AutoHeight()
// .VAlign(VAlign_Center)
// .HAlign(HAlign_Fill)
// [
// SNew(SBorder)
// .Padding(1.0f)
// .VAlign(VAlign_Center)
// .HAlign(HAlign_Fill)
// [
// SNew(SDatastorageView, DTFlux)
// ]
// ]
#pragma endregion
#pragma region ParticipantsDataSection
// +SVerticalBox::Slot()
// .AutoHeight()
// [
// SNew(SHorizontalBox)
// +SHorizontalBox::Slot()
// [
// SNew(STextBlock)
// .Text(FText::FromString(TEXT("Participants")))
// .Justification(ETextJustify::Left)
// ]
// +SHorizontalBox::Slot()
// [
// SNew(SButton)
// .Text(FText::FromString(TEXT("Show")))
// ]
// ]
#pragma endregion
#pragma region EventsSection
// +SVerticalBox::Slot()
// .AutoHeight()
// [
// SNew(SHorizontalBox)
// +SHorizontalBox::Slot()
// [
// SNew(STextBlock)
// .Text(FText::FromString(TEXT("Future Events")))
// .Justification(ETextJustify::Left)
// ]
// +SHorizontalBox::Slot()
// [
// SNew(SButton)
// .Text(FText::FromString(TEXT("Show")))
// ]
// ]
#pragma endregion
#pragma region SequencesSection
// +SVerticalBox::Slot()
// .AutoHeight()
// [
// SNew(SHorizontalBox)
// +SHorizontalBox::Slot()
// [
// SNew(STextBlock)
// .Text(FText::FromString(TEXT("Sequence On Air")))
// .Justification(ETextJustify::Left)
// ]
// +SHorizontalBox::Slot()
// [
// SNew(SButton)
// .Text(FText::FromString(TEXT("Show")))
// ]
// ]
#pragma endregion
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
[
SNew(SButton)
.Text(FText::FromString("Get RaceDatas"))
.OnClicked(this, &SDTFluxStatusWidget::OnRaceDatasClicked)
]
+ SHorizontalBox::Slot()
[
SNew(SButton)
.Text(FText::FromString("Get TeamList"))
.OnClicked(this, &SDTFluxStatusWidget::OnTeamListClicked)
]
]
#pragma endregion
]
+ SVerticalBox::Slot()
.VAlign(VAlign_Fill)
.HAlign(HAlign_Fill)
.AutoHeight()
[
#pragma region RankingSection
SNew(SBorder)
.Padding(6.0f)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
[
SNew(SBorder)
.Padding(6.0f)
.BorderImage(FAppStyle::GetBrush("ToolPanel.DarkGroupBorder"))
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.HAlign(HAlign_Left)
.AutoWidth()
[
SNew(STextBlock)
.Text(FText::FromString(TEXT("Contest Rankings:")))
.Margin(FMargin(0.0f, 0.0f, 8.0f, 0.0f))
]
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.FillWidth(1.0f)
.MaxWidth(200.0f)
[
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
[
SAssignNew(ContestComboBox, SComboBox<TSharedPtr<FComboBoxItem>>)
.OptionsSource(&ContestComboBoxItems)
.OnGenerateWidget(this, &SDTFluxStatusWidget::OnGeneRankingComboWidget)
.OnSelectionChanged(this, &SDTFluxStatusWidget::OnComboContestRankingChanged)
.Content()
[
SNew(STextBlock)
.Text(this, &SDTFluxStatusWidget::GetCurrContestComboBoxValue)
]
]
]
]
+ SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.AutoWidth()
.Padding(FMargin(8.0f, 0.0f, 0.0f, 0.0f))
[
SNew(SButton)
.Text(FText::FromString(TEXT("RequestRanking")))
.OnClicked(this, &SDTFluxStatusWidget::OnRankingButtonClicked)
.ContentPadding(FMargin(12.0f, 4.0f))
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
]
]
]
]
#pragma endregion
]
+ SVerticalBox::Slot()
.FillHeight(1.0f)
.Padding(3.0f)
[
OutputLogModule.MakeOutputLogWidget(Params)
]
]
];
}
FText SDTFluxStatusWidget::GetWebSocketStatusText() const
{
FString Status =
UEnum::GetDisplayValueAsText(DTFlux->WsStatus).ToString();
UEnum::GetDisplayValueAsText(DTFluxNetwork->WsStatus).ToString();
return
FText::FromString(Status);
FText::FromString(Status);
// FText::FromString("Unknown");
}
FText SDTFluxStatusWidget::GetWebConnectActionButtonText() const
{
switch (DTFlux->WsStatus)
switch (DTFluxNetwork->WsStatus)
{
case EDTFluxConnectionStatus::Connected:
return FText::FromString("Disconnect");
@ -310,39 +275,40 @@ FText SDTFluxStatusWidget::GetWebConnectActionButtonText() const
FReply SDTFluxStatusWidget::OnConnectionActionButtonClicked()
{
if(DTFlux)
if (DTFluxNetwork)
{
switch (DTFlux->WsStatus)
switch (DTFluxNetwork->WsStatus)
{
case EDTFluxConnectionStatus::Connected:
DTFlux->Reconnect();
break;
default:
DTFlux->Connect();
break;
case EDTFluxConnectionStatus::Connected:
DTFluxNetwork->Reconnect();
break;
default:
DTFluxNetwork->Connect();
break;
}
}
return FReply::Handled();
}
FSlateColor SDTFluxStatusWidget::GetWebSocketStatusColor() const
{
FColor Color;
switch (DTFlux->WsStatus)
switch (DTFluxNetwork->WsStatus)
{
case EDTFluxConnectionStatus::Unset:
Color = FColor::Orange;
break;
case EDTFluxConnectionStatus::Connected:
Color = FColor::Green;
Color = FColor::Green;
break;
case EDTFluxConnectionStatus::NotConnected:
Color = FColor::Orange;
Color = FColor::Orange;
break;
case EDTFluxConnectionStatus::Closed:
Color = FColor::Magenta;
Color = FColor::Magenta;
break;
default:
Color = FColor::Red;
Color = FColor::Red;
break;
}
return FSlateColor(Color);
@ -350,8 +316,8 @@ FSlateColor SDTFluxStatusWidget::GetWebSocketStatusColor() const
FSlateColor SDTFluxStatusWidget::GetWebConnectActionButtonColor() const
{
FColor Color= FColor::Green;
switch (DTFlux->WsStatus)
FColor Color = FColor::Green;
switch (DTFluxNetwork->WsStatus)
{
case EDTFluxConnectionStatus::Connected:
Color = FColor::Red;
@ -364,4 +330,119 @@ FSlateColor SDTFluxStatusWidget::GetWebConnectActionButtonColor() const
}
void SDTFluxStatusWidget::PopulateComboBoxItems()
{
ContestComboBoxItems.Empty();
if (DTFluxNetwork)
{
FString Separator = " | ";
FString RootSeparator = " -> ";
TArray<FDTFluxContest> DataFromSubsystem = DTFluxCore->GetContests();
for (const auto& Contest : DataFromSubsystem)
{
ContestComboBoxItems.Add(
FComboBoxItem::CreateItem(EComboBoxItemType::Contest, Contest.Name + RootSeparator, Contest.ContestId));
for (const auto& Stage : Contest.Stages)
{
int StageId = Stage.StageId;
FString StageDisplayName = Contest.Name + Separator + Stage.Name;
ContestComboBoxItems.Add(FComboBoxItem::CreateItem(EComboBoxItemType::Stage,
StageDisplayName + RootSeparator, Contest.ContestId,
StageId));
for (const auto& Split : Contest.Splits)
{
ContestComboBoxItems.Add(FComboBoxItem::CreateItem(EComboBoxItemType::Split,
StageDisplayName + Separator + Split.Name,
Contest.ContestId, StageId, Split.SplitId));
}
}
}
}
if (ContestComboBox.IsValid())
{
ContestComboBox->RefreshOptions();
if (ContestComboBoxItems.Num() > 0)
{
ContestComboBox->SetSelectedItem(ContestComboBoxItems[0]);
SelectedContestComboBoxItem = ContestComboBoxItems[0];
}
}
}
TSharedRef<SWidget> SDTFluxStatusWidget::OnGeneRankingComboWidget(TSharedPtr<FComboBoxItem> InItem)
{
return SNew(STextBlock)
.Text(FText::FromString(InItem->DisplayText))
.ColorAndOpacity(GetComboItemRankingColor(InItem))
.Margin(FMargin(2.0f, 1.0f));
}
void SDTFluxStatusWidget::OnComboContestRankingChanged(TSharedPtr<FComboBoxItem> NewSelection,
ESelectInfo::Type SelectInfo)
{
SelectedContestComboBoxItem = NewSelection;
}
FText SDTFluxStatusWidget::GetCurrContestComboBoxValue() const
{
if (SelectedContestComboBoxItem.IsValid())
{
return FText::FromString(SelectedContestComboBoxItem->DisplayText);
}
return FText::FromString("None");
}
FSlateColor SDTFluxStatusWidget::GetComboItemRankingColor(const TSharedPtr<FComboBoxItem> Item)
{
switch (Item->Type)
{
case EComboBoxItemType::Contest:
return FSlateColor(FLinearColor(0.2f, 0.6f, 1.0f));
case EComboBoxItemType::Stage:
return FSlateColor(FLinearColor(0.2f, 0.8f, 0.2f));
case EComboBoxItemType::Split:
return FSlateColor(FLinearColor(1.0f, 0.8f, 0.2f));
case EComboBoxItemType::None:
return FSlateColor(FLinearColor(0.6f, 0.28f, 0.28f));
default:
return FSlateColor(FLinearColor::White);
}
}
FReply SDTFluxStatusWidget::OnRankingButtonClicked() const
{
if (DTFluxNetwork)
{
// Exemple d'envoi de requête basée sur la sélection
int ForContest = SelectedContestComboBoxItem.IsValid() ? SelectedContestComboBoxItem->ContestId : -1;
int ForStage = SelectedContestComboBoxItem.IsValid() ? SelectedContestComboBoxItem->StageId : -1;
int ForSplit = SelectedContestComboBoxItem.IsValid() ? SelectedContestComboBoxItem->SplitId : -1;
EDTFluxApiDataType RequestType = EDTFluxApiDataType::None;
if (ForContest == -1)
{
UE_LOG(logDTFluxStatus, Error, TEXT("Contest not selected !!!!"));
return FReply::Handled();
}
if (ForStage == -1)
{
UE_LOG(logDTFluxStatus, Warning, TEXT("Stage not selected !!!! Requesting contest Ranking"));
RequestType = EDTFluxApiDataType::ContestRanking;
DTFluxNetwork->SendRequest(RequestType, ForContest);
return FReply::Handled();
}
RequestType = ForSplit == -1 ? EDTFluxApiDataType::StageRanking : EDTFluxApiDataType::SplitRanking;
UE_LOG(logDTFluxStatus, Warning, TEXT("Requesting %s Ranking"), *UEnum::GetValueAsString(RequestType));
DTFluxNetwork->SendRequest(RequestType, ForContest, ForStage, ForSplit);
}
return FReply::Handled();
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION