Config for building for Quest

This commit is contained in:
2024-05-29 11:53:41 +03:00
parent 15cbcf8752
commit 0db31c34d1
353 changed files with 74095 additions and 3 deletions

View File

@@ -0,0 +1,119 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "CoreMinimal.h"
#include "DetailColumnSizeData.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/Layout/SScrollBox.h"
#include "OculusXRRuleProcessorSubsystem.h"
class FActiveTimerHandle;
/**
* Slate widget for the Project Setup Tool main tab
*/
class SOculusXRProjectSetupToolWidget : public SCompoundWidget
{
SLATE_BEGIN_ARGS(SOculusXRProjectSetupToolWidget) {}
SLATE_END_ARGS()
/** Construct the slate layout for the widget */
void Construct(const FArguments& InArgs);
private:
enum class ERulesSection : uint8
{
Filter,
Required,
Recommended,
Applied,
Ignored
};
/** Build the main layout */
void BuildLayout(const TSharedPtr<SVerticalBox>& RootContainer);
/** Build the title section layout*/
void BuildTitleSectionLayout(const TSharedPtr<SVerticalBox>& RootContainer);
/** Build the filter section layout */
void BuildFilterSectionLayout(const TSharedPtr<SVerticalBox>& RootContainer, const uint32 PlatformFilterIndex);
/** Build a container for a rules section */
TSharedPtr<SVerticalBox> BuildRulesContainerLayout(const TSharedPtr<SScrollBox>& RootContainer, ERulesSection Section, const FText& SectionTitle);
/** Build a single rules item */
void BuildRowItemLayout(const TSharedPtr<SVerticalBox>& SectionContentContainer, ERulesSection Section, const SetupRulePtr& Rule, const uint32 PlatformFilterIndex);
/** Build the rules section layouts */
void BuildRequiredRulesSectionLayout(const TSharedPtr<SScrollBox>& RootContainer);
void BuildRecommendedRulesSectionLayout(const TSharedPtr<SScrollBox>& RootContainer);
void BuildAppliedRulesSectionLayout(const TSharedPtr<SScrollBox>& RootContainer);
void BuildIgnoredRulesSectionLayout(const TSharedPtr<SScrollBox>& RootContainer);
/** Platform filter callbacks */
FReply OnPlatformFilterChanged(ESetupRulePlatform ItemSelected);
/** Button handling callbacks */
FReply OnApplyRuleClicked(SetupRulePtr Rule);
static bool OnApplyRuleEnabled(ERulesSection Section);
FReply OnApplyAllRulesClicked(ERulesSection Section);
bool OnApplyAllRulesEnabled(ERulesSection Section) const;
void OnIgnoreRuleClicked(SetupRulePtr Rule, ERulesSection Section);
static bool OnIgnoreRuleEnabled(ERulesSection Section);
/** Rule visibility callback */
EVisibility OnRowVisibility(ERulesSection Section, ESetupRulePlatform CurrentPlatform, SetupRulePtr Rule) const;
/** Expander callbacks */
const FSlateBrush* GetHeaderExpanderImage(ERulesSection Section) const;
static EVisibility OnHeaderExpanderVisibility(ERulesSection Section);
FReply OnHeaderExpanderClicked(ERulesSection Section);
/** Restart Editor Notice Visibility */
EVisibility OnRestartEditorNoticeVisibility() const;
/** Restart Editor Button Clicked */
FReply OnRestartEditorButtonClicked();
/** Perform refresh */
static void Refresh();
/** Register/Unregister timer */
void UpdateActiveTimer(bool Register);
/** Update the status of rules */
void UpdateProjectStatus();
/** Update the status string */
void UpdateProjectStatusString() const;
/** Root container */
TSharedPtr<SVerticalBox> RootContainerWidget{};
/** Column size data */
TSharedPtr<FDetailColumnSizeData> ColumnSizeData{};
/** Platform filter */
TArray<ESetupRulePlatform> PlatformFilters{};
uint32 CurrentPlatformFilterIndex{};
/** Active timer handle */
TWeakPtr<FActiveTimerHandle> ActiveTimerHandle;
/** Restart pending after rule application */
bool bShowButtonToRestart = false;
/** Expanded/collapsed state for each section */
TArray<bool> BIsSectionExpanded{ true, true, true, true, true };
/** Status string */
TSharedPtr<STextBlock> ProjectStatusWidget;
/** Rules status */
UOculusXRRuleProcessorSubsystem::RuleStatus RuleStatus{};
};

View File

@@ -0,0 +1,331 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRProjectTutorialWidget.h"
#include "OculusXRProjectSetupToolModule.h"
#include "OculusXRPSTEvents.h"
#include "OculusXRPSTSettings.h"
#include "OculusXRTelemetry.h"
#include "Widgets/Layout/SScrollBox.h"
#include "Widgets/Input/SButton.h"
#include "Styling/SlateStyle.h"
#include "Styling/SlateStyleMacros.h"
#define LOCTEXT_NAMESPACE "OculusXRProjectTutorialWidget"
static constexpr int32 NumTutorialPages = 3;
/**
* Construct the layout for the project setup tool tab
*
* @param InArgs [in] the arguments associated with this tool
*/
void SOculusXRTutorialWindow::Construct(const FArguments& InArgs)
{
// Construct the layout
RootContainerWidget = SNew(SVerticalBox);
BuildGuidedTutorialLayout(RootContainerWidget);
ChildSlot
[SNew(SBox)
.WidthOverride(1080)
.HeightOverride(600)
[RootContainerWidget.ToSharedRef()]];
}
/**
* Build the guided tutorial layout
*/
void SOculusXRTutorialWindow::BuildGuidedTutorialLayout(const TSharedPtr<SVerticalBox>& RootContainer)
{
// Construct the row of buttons
const TSharedPtr<SHorizontalBox> PreviousNextWidget = SNew(SHorizontalBox);
PreviousNextWidget->AddSlot()
.AutoWidth()
[SNew(SButton)
.OnClicked(this, &SOculusXRTutorialWindow::OnPreviousClicked)
.IsEnabled(this, &SOculusXRTutorialWindow::OnPreviousEnabled)
.Text(LOCTEXT("Previous", "Previous"))];
PreviousNextWidget->AddSlot()
.AutoWidth()
.Padding(10, 0, 0, 0)
[SNew(SButton)
.OnClicked(this, &SOculusXRTutorialWindow::OnNextClicked)
.IsEnabled(this, &SOculusXRTutorialWindow::OnNextEnabled)
.Text(LOCTEXT("Next", "Next"))];
const TSharedPtr<SHorizontalBox> SkipWidget = SNew(SHorizontalBox);
SkipWidget->AddSlot()
.AutoWidth()
[SNew(SButton)
.OnClicked(this, &SOculusXRTutorialWindow::OnSkipClicked)
.ButtonStyle(&FAppStyle::Get().GetWidgetStyle<FButtonStyle>("PrimaryButton"))
.Text_Lambda([this]() {
if (GuidedTutorialPageIndex == NumTutorialPages - 1)
{
return LOCTEXT("Close", "Close");
}
return LOCTEXT("Skip", "Skip");
})];
const TSharedPtr<SHorizontalBox> PaginationWidget = SNew(SHorizontalBox);
for (int i = 0; i < NumTutorialPages; ++i)
{
PaginationWidget->AddSlot()
.Padding(4.0f, 0.0f)
[SNew(SImage)
.DesiredSizeOverride(FVector2D(8.0f, 8.0f))
.Image_Raw(this, &SOculusXRTutorialWindow::GetPaginationImageForIndex, i)];
}
const TSharedPtr<SHorizontalBox> ButtonsWidget = SNew(SHorizontalBox);
ButtonsWidget->AddSlot()
.HAlign(HAlign_Left)
[PreviousNextWidget.ToSharedRef()];
ButtonsWidget->AddSlot()
.Padding(0.0f, 7.0f)
.HAlign(HAlign_Center)
[PaginationWidget.ToSharedRef()];
ButtonsWidget->AddSlot()
.HAlign(HAlign_Right)
[SkipWidget.ToSharedRef()];
// Construct the text widget
const TSharedPtr<SVerticalBox> TextWidget = SNew(SVerticalBox);
AddTutorialPage1(TextWidget);
AddTutorialPage2(TextWidget);
AddTutorialPage3(TextWidget);
// Construct the image panel
const TSharedPtr<SOverlay> ImagePanel = SNew(SOverlay);
ImagePanel->AddSlot()
[SNew(SImage)
.Image(FOculusXRProjectSetupToolModule::GetSlateStyle()->GetBrush("ProjectSetupTool.MetaQuestBackground"))];
// Construct the instruction panel
const TSharedPtr<SOverlay> InstructionsPanel = SNew(SOverlay);
InstructionsPanel->AddSlot()
[SNew(SVerticalBox)
+ SVerticalBox::Slot()
.Padding(40)
.VAlign(VAlign_Center)
[TextWidget.ToSharedRef()]];
InstructionsPanel->AddSlot()
[SNew(SVerticalBox)
+ SVerticalBox::Slot()
.Padding(40, 20)
.VAlign(VAlign_Bottom)
[ButtonsWidget.ToSharedRef()]];
// Construct the main panel
const TSharedPtr<SHorizontalBox> MainPanel = SNew(SHorizontalBox);
MainPanel->AddSlot()
[ImagePanel.ToSharedRef()];
MainPanel->AddSlot()
[InstructionsPanel.ToSharedRef()];
// Add to the root container
RootContainer->AddSlot()
[MainPanel.ToSharedRef()];
}
/**
* Previous button clicked
*/
FReply SOculusXRTutorialWindow::OnPreviousClicked()
{
--GuidedTutorialPageIndex;
if (GuidedTutorialPageIndex < 0)
{
GuidedTutorialPageIndex = 0;
}
const OculusXRTelemetry::TScopedMarker<OculusXRTelemetry::Events::FProjectSetupToolPrev> Previous;
const auto& Annotated = Previous
.AddAnnotation(OculusXRTelemetry::Annotations::Value,
TCHAR_TO_ANSI(*FString::FromInt(GuidedTutorialPageIndex)));
return FReply::Handled();
}
/**
* Previous button enabled
*/
bool SOculusXRTutorialWindow::OnPreviousEnabled() const
{
return GuidedTutorialPageIndex > 0;
}
/**
* Next button clicked
*/
FReply SOculusXRTutorialWindow::OnNextClicked()
{
++GuidedTutorialPageIndex;
if (GuidedTutorialPageIndex == NumTutorialPages - 1)
{
GetMutableDefault<UOculusXRPSTSettings>()->bGuidedTutorialComplete = true;
GetMutableDefault<UOculusXRPSTSettings>()->SaveConfig();
}
const OculusXRTelemetry::TScopedMarker<OculusXRTelemetry::Events::FProjectSetupToolNext> NextEvent;
const auto& Annotated = NextEvent
.AddAnnotation(OculusXRTelemetry::Annotations::Value,
TCHAR_TO_ANSI(*FString::FromInt(GuidedTutorialPageIndex)));
return FReply::Handled();
}
/**
* Next button enabled
*/
bool SOculusXRTutorialWindow::OnNextEnabled() const
{
return GuidedTutorialPageIndex < NumTutorialPages - 1;
}
/**
* Skip button clicked
*/
FReply SOculusXRTutorialWindow::OnSkipClicked() const
{
FSlateApplication::Get().FindWidgetWindow(AsShared())->RequestDestroyWindow();
return FReply::Handled();
}
/**
* Get the image to use for the pagination indicator
*/
const FSlateBrush* SOculusXRTutorialWindow::GetPaginationImageForIndex(int32 PageIndex) const
{
if (PageIndex == GuidedTutorialPageIndex)
{
return FOculusXRProjectSetupToolModule::GetSlateStyle()->GetBrush("ProjectSetupTool.WhiteDot");
}
return FOculusXRProjectSetupToolModule::GetSlateStyle()->GetBrush("ProjectSetupTool.GreyDot");
}
void SOculusXRTutorialWindow::AddTutorialPage1(const TSharedPtr<SVerticalBox>& TextWidget) const
{
TextWidget->AddSlot()
.AutoHeight()
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Regular", 24))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 0 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Title1", "Welcome to the Meta XR Project Setup Tool"))];
TextWidget->AddSlot()
.AutoHeight()
.Padding(0, 20, 0, 0)
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Regular", 12))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 0 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Body1",
"The Unreal Project Setup Tool can help you quickly configure projects using the Meta XR Plugin. This tool guides you through the necessary steps so you can start developing faster. The Unreal Project Setup Tool tests a registry of rules called Configuration Tasks. We provide default rules to make your project Quest Ready."))];
}
void SOculusXRTutorialWindow::AddTutorialPage2(const TSharedPtr<SVerticalBox>& TextWidget) const
{
TextWidget->AddSlot()
.AutoHeight()
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Regular", 24))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 1 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Title2", "Here are the key things to know about Unreal Project Setup Tool"))];
TextWidget->AddSlot()
.AutoHeight()
.Padding(0, 10, 0, 0)
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Bold", 12))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 1 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Body2.1", "Actions"))];
TextWidget->AddSlot()
.AutoHeight()
.Padding(0, 3, 0, 0)
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Regular", 12))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 1 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Body2.2", "A Configuration Task is regularly checked for its validation. You can interact directly with a Task in the following ways."))];
TextWidget->AddSlot()
.AutoHeight()
.Padding(0, 3, 0, 0)
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Bold", 12))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 1 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Body2.3", "Fix/Apply"))];
TextWidget->AddSlot()
.AutoHeight()
.Padding(0, 3, 0, 0)
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Regular", 12))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 1 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Body2.3", "Manually call the fix delegate for this Task in order to resolve the issue. This action is only available for tasks that are not already validated."))];
TextWidget->AddSlot()
.AutoHeight()
.Padding(0, 3, 0, 0)
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Bold", 12))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 1 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Body2.4", "Ignore / Unignore"))];
TextWidget->AddSlot()
.AutoHeight()
.Padding(0, 3, 0, 0)
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Regular", 12))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 1 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Body2.5", "This moves the task to another category that will get ignored for both checks and fixes. This gives the control back to developers who may not want to be forced to follow some guidelines or even requirements in some specific cases."))];
}
void SOculusXRTutorialWindow::AddTutorialPage3(const TSharedPtr<SVerticalBox>& TextWidget) const
{
TextWidget->AddSlot()
.AutoHeight()
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Bold", 24))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 2 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Title3", "Youre good to go! Start developing faster with Unreal Project Setup Tool"))];
TextWidget->AddSlot()
.AutoHeight()
.Padding(0, 20, 0, 0)
[SNew(STextBlock)
.AutoWrapText(true)
.Font(DEFAULT_FONT("Regular", 12))
.Visibility_Lambda([this]() { return GuidedTutorialPageIndex == 2 ? EVisibility::Visible : EVisibility::Collapsed; })
.Text(LOCTEXT("Body3", "You can check Unreal Project Setup Tool from the Tools menu bar, Meta XR Plugin Settings Page or from the Meta icon on the bottom bar. The tool proactively checks for configuration changes."))];
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,46 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "CoreMinimal.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/Layout/SScrollBox.h"
class FActiveTimerHandle;
/**
* Slate widget for the tutorial
*/
class SOculusXRTutorialWindow : public SCompoundWidget
{
SLATE_BEGIN_ARGS(SOculusXRTutorialWindow) {}
SLATE_END_ARGS()
/** Construct the slate layout for the widget */
void Construct(const FArguments& InArgs);
private:
/** Build the guided tutorial layout */
void BuildGuidedTutorialLayout(const TSharedPtr<SVerticalBox>& RootContainer);
FReply OnPreviousClicked();
bool OnPreviousEnabled() const;
FReply OnNextClicked();
bool OnNextEnabled() const;
FReply OnSkipClicked() const;
const FSlateBrush* GetPaginationImageForIndex(int32 PageIndex) const;
void AddTutorialPage1(const TSharedPtr<SVerticalBox>& TextWidget) const;
void AddTutorialPage2(const TSharedPtr<SVerticalBox>& TextWidget) const;
void AddTutorialPage3(const TSharedPtr<SVerticalBox>& TextWidget) const;
/** Root container */
TSharedPtr<SVerticalBox> RootContainerWidget{};
/** Current tutorial page */
int32 GuidedTutorialPageIndex = 0;
};

View File

@@ -0,0 +1,77 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "OculusXRStatusBarWidget.h"
#include "OculusXRProjectSetupToolModule.h"
#include "OculusXRRuleProcessorSubsystem.h"
#define LOCTEXT_NAMESPACE "OculusXRStatusBarWidget"
/**
* Construct the layout for the status bar widget
*
* @param InArgs [in] the arguments associated with this tool
*/
void SOculusXRStatusBarWidget::Construct(const FArguments& InArgs)
{
ChildSlot
[SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
[SNew(SButton)
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
.ButtonStyle(FAppStyle::Get(), "SimpleButton")
.ToolTipText(LOCTEXT("StatusBarWidget_Tooltip", "Launch Meta XR Project Setup tool"))
.OnClicked_Lambda([]() -> FReply {
IOculusXRProjectSetupToolModule::Get().ShowProjectSetupTool("Toolbar");
return FReply::Handled();
})
.ContentPadding(0)
[SNew(SOverlay)
+ SOverlay::Slot()
[SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
[SNew(SImage)
.Image(FOculusXRProjectSetupToolModule::GetSlateStyle()->GetBrush("ProjectSetupTool.MetaLogo"))
.DesiredSizeOverride(FVector2D(22.0f, 22.0f))]]
+ SOverlay::Slot()
[SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(16, 4, -2, 10)
[SNew(SImage)
.Image_Static(SOculusXRStatusBarWidget::GetDotImage)
.DesiredSizeOverride(FVector2D(8.0f, 8.0f))]]]]];
}
/**
* Determine the correct image to use
*/
const FSlateBrush* SOculusXRStatusBarWidget::GetDotImage()
{
const UOculusXRRuleProcessorSubsystem* RuleProcessorSubsystem = GEngine->GetEngineSubsystem<UOculusXRRuleProcessorSubsystem>();
if (RuleProcessorSubsystem == nullptr)
{
return FOculusXRProjectSetupToolModule::GetSlateStyle()->GetBrush("ProjectSetupTool.GreenDot");
}
const auto& RuleStatus = RuleProcessorSubsystem->UnAppliedRulesStatus(MetaQuest_All);
if (RuleStatus.PendingRequiredRulesCount > 0)
{
return FOculusXRProjectSetupToolModule::GetSlateStyle()->GetBrush("ProjectSetupTool.RedDot");
}
if (RuleStatus.PendingRecommendedRulesCount > 0)
{
return FOculusXRProjectSetupToolModule::GetSlateStyle()->GetBrush("ProjectSetupTool.YellowDot");
}
return FOculusXRProjectSetupToolModule::GetSlateStyle()->GetBrush("ProjectSetupTool.GreenDot");
}
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,27 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "CoreMinimal.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/SCompoundWidget.h"
/**
* Slate widget for the widget used to show any outstanding issues in the status bar
*/
class SOculusXRStatusBarWidget : public SCompoundWidget
{
SLATE_BEGIN_ARGS(SOculusXRStatusBarWidget) {}
SLATE_END_ARGS()
/** Construct the slate layout for the widget */
void Construct(const FArguments& InArgs);
private:
/**
* Determine the correct image to use
*/
static const FSlateBrush* GetDotImage();
};