/* Add the source code box to any vertical box*/ void AddSourceCodeToVerticalBox(TSharedPtr<SVerticalBox>& VerticalBox, const FString& SourceCode) { if (SourceCode.Len() > 0) { // Replace tabs with two spaces for display in the widget, as the rich text block doesn't support tabs FString spacedSource = SourceCode.Replace(TEXT("\t"), TEXT(" ")); VerticalBox->AddSlot() .AutoHeight() [ SNew(SSeparator) ]; VerticalBox->AddSlot() .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(TEXT("Source Code"))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(true) .Padding(WidgetPadding) .BodyContent() [ SNew(SRichTextBlock) .Text(FText::FromString(spacedSource)) .TextStyle(FMaliOCStyle::Get(), "Text.Normal") .AutoWrapText(true) ] ]; } }
void Construct(const FArguments& InArgs) { PoseWatch = InArgs._PoseWatch; static FColor PoseWatchColours[] = { FColor::Red, FColor::Green, FColor::Blue, FColor::Cyan, FColor::Orange, FColor::Purple, FColor::Yellow, FColor::Black }; const int32 Rows = 2; const int32 Columns = 4; TSharedPtr<SVerticalBox> Layout = SNew(SVerticalBox); for (int32 RowIndex = 0; RowIndex < Rows; ++RowIndex) { TSharedPtr<SHorizontalBox> Row = SNew(SHorizontalBox); for (int32 RowItem = 0; RowItem < Columns; ++RowItem) { int32 ColourIndex = RowItem + (RowIndex * Columns); FColor Colour = PoseWatchColours[ColourIndex]; Row->AddSlot() .Padding(5.f, 2.f) [ SNew(SButton) .HAlign(HAlign_Center) .OnClicked(this, &SPoseViewColourPickerPopup::NewPoseWatchColourPicked, Colour) .ButtonColorAndOpacity(Colour) ]; } Layout->AddSlot() [ Row.ToSharedRef() ]; } Layout->AddSlot() .AutoHeight() .Padding(5.f, 2.f) [ SNew(SButton) .Text(NSLOCTEXT("AnimationGraphNode", "RemovePoseWatch", "Remove Pose Watch")) .OnClicked(this, &SPoseViewColourPickerPopup::RemovePoseWatch) ]; this->ChildSlot [ SNew(SBorder) .BorderImage(FEditorStyle::GetBrush(TEXT("Menu.Background"))) .Padding(10) [ Layout->AsShared() ] ]; }
void FMathStructCustomization::MakeHeaderRow( TSharedRef<class IPropertyHandle>& StructPropertyHandle, FDetailWidgetRow& Row ) { // We'll set up reset to default ourselves const bool bDisplayResetToDefault = false; const FString DisplayNameOverride = TEXT(""); TSharedPtr<SHorizontalBox> HorizontalBox; Row.NameContent() [ StructPropertyHandle->CreatePropertyNameWidget( DisplayNameOverride, bDisplayResetToDefault ) ] .ValueContent() // Make enough space for each child handle .MinDesiredWidth(125.0f * SortedChildHandles.Num() ) .MaxDesiredWidth(125.0f * SortedChildHandles.Num() ) [ SAssignNew( HorizontalBox, SHorizontalBox ) ]; for( int32 ChildIndex = 0; ChildIndex < SortedChildHandles.Num(); ++ChildIndex ) { TSharedRef<IPropertyHandle> ChildHandle = SortedChildHandles[ChildIndex]; const bool bLastChild = SortedChildHandles.Num()-1 == ChildIndex; // Make a widget for each property. The vector component properties will be displayed in the header HorizontalBox->AddSlot() .Padding( FMargin(0.0f, 2.0f, bLastChild ? 0.0f : 3.0f, 2.0f ) ) [ MakeChildWidget( ChildHandle ) ]; } }
void FMarginStructCustomization::CustomizeHeader( TSharedRef<class IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils ) { this->StructPropertyHandle = StructPropertyHandle; const FString UVSpaceString( StructPropertyHandle->GetProperty()->GetMetaData( TEXT( "UVSpace" ) ) ); bIsMarginUsingUVSpace = UVSpaceString.Len() > 0 && UVSpaceString == TEXT( "true" ); uint32 NumChildren; StructPropertyHandle->GetNumChildren( NumChildren ); for( uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex ) { ChildPropertyHandles.Add( StructPropertyHandle->GetChildHandle( ChildIndex ).ToSharedRef() ); } TSharedPtr<SHorizontalBox> HorizontalBox; HeaderRow.NameContent() [ StructPropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MinDesiredWidth( 250.0f ) .MaxDesiredWidth( 250.0f ) [ SAssignNew( HorizontalBox, SHorizontalBox ) ]; HorizontalBox->AddSlot() [ MakePropertyWidget() ]; }
TSharedRef< class SWidget > FTextPropertyTableCellPresenter::ConstructEditModeDropDownWidget() { TSharedRef< SWidget > Result = SNullWidget::NullWidget; TArray< TSharedRef<SWidget> > RequiredButtons; PropertyEditorHelpers::MakeRequiredPropertyButtons( PropertyEditor, /*OUT*/RequiredButtons ); if ( RequiredButtons.Num() > 0 ) { TSharedPtr< SHorizontalBox > ButtonBox; Result = SNew( SBorder ) .BorderImage(FEditorStyle::GetBrush("PropertyTable.Cell.DropDown.Background")) .Padding( 0 ) .Content() [ SAssignNew( ButtonBox, SHorizontalBox ) ]; for( int32 ButtonIndex = 0; ButtonIndex < RequiredButtons.Num(); ++ButtonIndex ) { ButtonBox->AddSlot() .AutoWidth() .HAlign(HAlign_Center) .VAlign(VAlign_Center) .Padding( 2.0f, 1.0f ) [ RequiredButtons[ButtonIndex] ]; } } return Result; }
TSharedRef<SWidget> SFriendsItem::OnGetMenuContent() { TArray< EFriendsActionType::Type > FriendActions; if ( FriendItem.IsValid() ) { if ( FriendItem->GetListType() == EFriendsDisplayLists::RecentPlayersDisplay ) { if ( !FFriendsAndChatManager::Get()->FindUserID( FriendItem->GetName() ).IsValid() && FFriendsAndChatManager::Get()->IsPendingInvite( FriendItem->GetName() ) == false ) { FriendActions.Add( EFriendsActionType::Add_Friend ); } } else if ( FriendItem->GetInviteStatus() == EInviteStatus::Accepted ) { if ( FFriendsAndChatManager::Get()->IsInSession() ) { FriendActions.Add(EFriendsActionType::Invite_To_Game ); } FriendActions.Add( EFriendsActionType::Delete_Friend ); } else if ( FriendItem->GetInviteStatus() == EInviteStatus::PendingOutbound && FriendItem->GetOnlineFriend().IsValid() ) { FriendActions.Add( EFriendsActionType::Cancel_Request ); } else if ( FriendItem->GetInviteStatus() == EInviteStatus::PendingInbound ) { FriendActions.Add( EFriendsActionType::Accept_Friend ); FriendActions.Add( EFriendsActionType::Reject_Friend ); } } if ( FriendActions.Num() == 0 ) { return SNullWidget::NullWidget; } TSharedPtr< SVerticalBox > DisplayBox; SAssignNew( DisplayBox, SVerticalBox ); for( auto Iter(FriendActions.CreateConstIterator()); Iter; Iter++ ) { DisplayBox->AddSlot() .AutoHeight() [ SNew( SButton ) .OnClicked( this, &SFriendsItem::OnOptionSelected, *Iter ) [ SNew( STextBlock ) .Text( GetActionText( *Iter ) ) .TextStyle( &FriendStyle.TextStyle ) .ColorAndOpacity( FriendStyle.MenuSetColor ) ] ]; } return DisplayBox.ToSharedRef(); }
void SDetailCategoryTableRow::Construct( const FArguments& InArgs, TSharedRef<IDetailTreeNode> InOwnerTreeNode, const TSharedRef<STableViewBase>& InOwnerTableView ) { OwnerTreeNode = InOwnerTreeNode; bIsInnerCategory = InArgs._InnerCategory; TSharedPtr<SHorizontalBox> MyContent; ChildSlot .Padding( 0.0f, 2.0f, 0.0f, 0.0f ) [ SNew( SBorder ) .BorderImage( this, &SDetailCategoryTableRow::GetBackgroundImage ) .Padding( FMargin( 0.0f, 3.0f, SDetailTableRowBase::ScrollbarPaddingSize, 3.0f ) ) .BorderBackgroundColor( FLinearColor( .6,.6,.6, 1.0f ) ) [ SAssignNew( MyContent, SHorizontalBox ) +SHorizontalBox::Slot() .VAlign(VAlign_Center) .Padding(2.0f, 2.0f, 2.0f, 2.0f) .AutoWidth() [ SNew( SExpanderArrow, SharedThis(this) ) ] +SHorizontalBox::Slot() .VAlign(VAlign_Center) .AutoWidth() [ SNew( STextBlock ) .Text( InArgs._DisplayName ) .Font( FEditorStyle::GetFontStyle( bIsInnerCategory ? "PropertyWindow.NormalFont" : "DetailsView.CategoryFontStyle" ) ) .ShadowOffset( bIsInnerCategory ? FVector2D::ZeroVector : FVector2D(1.0f, 1.0f) ) ] ] ]; if( InArgs._HeaderContent.IsValid() ) { MyContent->AddSlot() .VAlign(VAlign_Center) [ InArgs._HeaderContent.ToSharedRef() ]; } STableRow< TSharedPtr< IDetailTreeNode > >::ConstructInternal( STableRow::FArguments() .Style(FEditorStyle::Get(), "DetailsView.TreeView.TableRow") .ShowSelection(false), InOwnerTableView ); }
void AUTDomGameMode::CreateConfigWidgets(TSharedPtr<class SVerticalBox> MenuSpace, bool bCreateReadOnly, TArray< TSharedPtr<TAttributePropertyBase> >& ConfigProps, int32 MinimumPlayers) { Super::CreateConfigWidgets(MenuSpace, bCreateReadOnly, ConfigProps, MinimumPlayers); TSharedPtr< TAttributePropertyBool > AllowTransAttr = StaticCastSharedPtr<TAttributePropertyBool>(FindGameURLOption(ConfigProps, TEXT("AllowTrans"))); if (AllowTransAttr.IsValid()) { MenuSpace->AddSlot() .Padding(0.0f, 0.0f, 0.0f, 5.0f) .AutoHeight() [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) [ SNew(SBox) .WidthOverride(350) [ SNew(STextBlock) .TextStyle(SUWindowsStyle::Get(), "UT.Common.NormalText") .Text(NSLOCTEXT("UTDomGameMode", "AllowTranslocator", "Translocator")) ] ] + SHorizontalBox::Slot() .Padding(20.0f, 0.0f, 0.0f, 0.0f) .AutoWidth() [ SNew(SBox) .WidthOverride(300) [ bCreateReadOnly ? StaticCastSharedRef<SWidget>( SNew(SCheckBox) .IsChecked(AllowTransAttr.ToSharedRef(), &TAttributePropertyBool::GetAsCheckBox) .Type(ESlateCheckBoxType::CheckBox) .Style(SUWindowsStyle::Get(), "UT.Common.CheckBox") ) : StaticCastSharedRef<SWidget>( SNew(SCheckBox) .IsChecked(AllowTransAttr.ToSharedRef(), &TAttributePropertyBool::GetAsCheckBox) .OnCheckStateChanged(AllowTransAttr.ToSharedRef(), &TAttributePropertyBool::SetFromCheckBox) .Type(ESlateCheckBoxType::CheckBox) .Style(SUWindowsStyle::Get(), "UT.Common.CheckBox") ) ] ] ]; } }
void SGraphNodeK2CreateDelegate::CreateBelowWidgetControls(TSharedPtr<SVerticalBox> MainBox) { if(UK2Node_CreateDelegate* Node = Cast<UK2Node_CreateDelegate>(GraphNode)) { UFunction* FunctionSignature = Node->GetDelegateSignature(); UClass* ScopeClass = Node->GetScopeClass(); if(FunctionSignature && ScopeClass) { FunctionDataItems.Empty(); for(TFieldIterator<UFunction> It(ScopeClass); It; ++It) { UFunction* Func = *It; if (Func && FunctionSignature->IsSignatureCompatibleWith(Func) && UEdGraphSchema_K2::FunctionCanBeUsedInDelegate(Func)) { TSharedPtr<FFunctionItemData> ItemData = MakeShareable(new FFunctionItemData()); ItemData->Name = Func->GetFName(); ItemData->Description = FunctionDescription(Func); FunctionDataItems.Add(ItemData); } } TSharedRef<SComboButton> SelectFunctionWidgetRef = SNew(SComboButton) .Method(EPopupMethod::UseCurrentWindow) .ButtonContent() [ SNew(STextBlock) .Text(this, &SGraphNodeK2CreateDelegate::GetCurrentFunctionDescription) ] .MenuContent() [ SNew(SListView<TSharedPtr<FFunctionItemData> >) .ListItemsSource( &FunctionDataItems ) .OnGenerateRow(this, &SGraphNodeK2CreateDelegate::HandleGenerateRowFunction) .OnSelectionChanged(this, &SGraphNodeK2CreateDelegate::OnFunctionSelected) ]; MainBox->AddSlot() .AutoHeight() .VAlign(VAlign_Fill) [ SelectFunctionWidgetRef ]; SelectFunctionWidget = SelectFunctionWidgetRef; } } }
void SGraphNode_MultiCompareGameplayTag::CreateOutputSideRemoveButton(TSharedPtr<SVerticalBox> OutputBox) { TSharedPtr<SWidget> ButtonContent; SAssignNew(ButtonContent, SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() .HAlign(HAlign_Left) [ SNew(STextBlock) .Text(NSLOCTEXT("CompareNode", "CompareNodeRemovePinButton", "Remove Case")) .ColorAndOpacity(FLinearColor::White) ] + SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) .Padding(7, 0, 0, 0) [ SNew(SImage) .Image(FEditorStyle::GetBrush(TEXT("PropertyWindow.Button_RemoveFromArray"))) ]; TSharedPtr<SToolTip> Tooltip; Tooltip = IDocumentation::Get()->CreateToolTip(NSLOCTEXT("CompareNode", "CompareNodeRemoveCaseButton_Tooltip", "Remove last case pins"), NULL, GraphNode->GetDocumentationLink(), FString()); TSharedRef<SButton> RemovePinButton = SNew(SButton) .ContentPadding(0.0f) .ButtonStyle(FEditorStyle::Get(), "NoBorder") .OnClicked(this, &SGraphNode_MultiCompareGameplayTag::OnRemovePin) .ToolTipText(NSLOCTEXT("CompareNode", "CompareNodeRemovePinButton_Tooltip", "Remove last pin")) .ToolTip(Tooltip) .Visibility(this, &SGraphNode_MultiCompareGameplayTag::IsRemovePinButtonVisible) [ ButtonContent.ToSharedRef() ]; RemovePinButton->SetCursor(EMouseCursor::Hand); FMargin AddPinPadding = Settings->GetOutputPinPadding(); AddPinPadding.Top += 6.0f; OutputBox->AddSlot() .AutoHeight() .VAlign(VAlign_Center) .Padding(AddPinPadding) [ RemovePinButton ]; }
/* Generate a Midgard stats table */ TSharedRef<SVerticalBox> GenerateMidgardStatsTable(const TSharedRef<FMaliOCReport::FMidgardReport::FRenderTarget>& RenderTarget) { TSharedRef<SVerticalBox> rtBox = SNew(SVerticalBox); int index = 0; // Four rows, 5 columns for (int i = 0; i < 4; i++) { TSharedPtr<SHorizontalBox> curRow = nullptr; rtBox->AddSlot() .AutoHeight() [ SAssignNew(curRow, SHorizontalBox) ]; const float columnWidths[] = { 2.5f, 1.0f, 1.0f, 1.0f, 2.0f }; const float widthScaleFactor = 50.0f; for (int j = 0; j < 5; j++) { curRow->AddSlot() .FillWidth(columnWidths[j]) .MaxWidth(columnWidths[j] * widthScaleFactor) [ SNew(STextBlock) .Text(*RenderTarget->StatsTable[index]) .Font(FEditorStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont"))) ]; index++; } } rtBox->AddSlot() .AutoHeight() [ SNew(SSeparator) ]; rtBox->AddSlot() .AutoHeight() [ GenerateFStringListView(RenderTarget->ExtraDetails) ]; return rtBox; };
void SGraphNodeK2Sequence::CreateOutputSideAddButton(TSharedPtr<SVerticalBox> OutputBox) { TSharedRef<SWidget> AddPinButton = AddPinButtonContent( NSLOCTEXT("SequencerNode", "SequencerNodeAddPinButton", "Add pin"), NSLOCTEXT("SequencerNode", "SequencerNodeAddPinButton_ToolTip", "Add new pin")); FMargin AddPinPadding = Settings->GetOutputPinPadding(); AddPinPadding.Top += 6.0f; OutputBox->AddSlot() .AutoHeight() .VAlign(VAlign_Center) .Padding(AddPinPadding) [ AddPinButton ]; }
void SGraphNode_MultiCompareGameplayTag::CreateOutputSideAddButton(TSharedPtr<SVerticalBox> OutputBox) { TSharedRef<SWidget> AddPinButton = AddPinButtonContent( NSLOCTEXT("CompareNode", "CompareNodeAddPinButton", "Add Case"), NSLOCTEXT("CompareNode", "CompareNodeAddPinButton_Tooltip", "Add new case pins")); FMargin AddPinPadding = Settings->GetOutputPinPadding(); AddPinPadding.Top += 6.0f; OutputBox->AddSlot() .AutoHeight() .VAlign(VAlign_Center) .Padding(AddPinPadding) [ AddPinButton ]; }
void SGraphNodeSoundBase::CreateOutputSideAddButton(TSharedPtr<SVerticalBox> OutputBox) { TSharedRef<SWidget> AddPinButton = AddPinButtonContent( NSLOCTEXT("SoundNode", "SoundNodeAddPinButton", "Add input"), NSLOCTEXT("SoundNode", "SoundNodeAddPinButton_Tooltip", "Adds an input to the sound node") ); FMargin AddPinPadding = Settings->GetOutputPinPadding(); AddPinPadding.Top += 6.0f; OutputBox->AddSlot() .AutoHeight() .VAlign(VAlign_Center) .Padding(AddPinPadding) [ AddPinButton ]; }
void SScreenHistoryView::RegenerateWidgets() { // Clear the box before regenerating the widgets WidgetBox->ClearChildren(); TSharedPtr< SHorizontalBox > HolderBox; // Box where all widgets go WidgetBox->AddSlot() .AutoHeight() .VAlign( VAlign_Center ) .HAlign( HAlign_Left ) [ SAssignNew( HolderBox, SHorizontalBox ) ]; // Get the filtered views TArray<TSharedPtr<IScreenShotData> >& DevicesArray = ScreenShotData->GetFilteredChildren(); // Create a new widget for each screen shot for ( int32 ChildSlots = FirstItemToShow; ChildSlots < DevicesArray.Num(); ChildSlots++ ) { HolderBox->AddSlot() .AutoWidth() .VAlign( VAlign_Center ) .HAlign( HAlign_Center ) [ SNew( SScreenShotItem ) .ScreenShotData( DevicesArray[ChildSlots] ) ]; } // Only show scroll bar if we have more than 1 screenshot if ( DevicesArray.Num() > 1 ) { // Add the cached scrollbar back to the created widgets WidgetBox->AddSlot() .AutoHeight() .Padding(8, 0) [ ScrollBox.ToSharedRef() ]; } }
void SFlareSkirmishScoreMenu::FillResults(TSharedPtr<SVerticalBox> Box, FText Title, FFlareSkirmishPlayerResult Result) { const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme(); // Title Box->AddSlot() .AutoHeight() .HAlign(HAlign_Left) .Padding(Theme.TitlePadding) [ SNew(STextBlock) .Text(Title) .TextStyle(&Theme.SubTitleFont) ]; // Results AddResult(Box, LOCTEXT("ResultDisabled", "Ships disabled"), Result.ShipsDisabled); AddResult(Box, LOCTEXT("ResultDestroyed", "Ships destroyed"), Result.ShipsDestroyed); AddResult(Box, LOCTEXT("ResultFired", "Projectiles fired"), Result.AmmoFired); AddResult(Box, LOCTEXT("ResultHit", "Successful hits"), Result.AmmoHit); }
void SSurveyPage::Construct( const FArguments& Args, const TSharedRef< FSurveyPage >& Page ) { TArray< TSharedRef< FQuestionBlock > > Blocks = Page->GetBlocks(); TSharedPtr<SVerticalBox> TargetBox; this->ChildSlot [ SAssignNew(TargetBox,SVerticalBox) ]; for (int BlockIndex = 0; BlockIndex < Blocks.Num(); BlockIndex++) { const TSharedRef< FQuestionBlock > Block = Blocks[BlockIndex]; TargetBox->AddSlot() .AutoHeight() [ SNew(SQuestionBlock, Block ) ]; } }
void SFlareSkirmishScoreMenu::AddResult(TSharedPtr<SVerticalBox> Box, FText Name, int32 Result) { const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme(); // Slot Box->AddSlot() .AutoHeight() .HAlign(HAlign_Left) .Padding(Theme.ContentPadding) [ SNew(SHorizontalBox) // Stat name + SHorizontalBox::Slot() .AutoWidth() [ SNew(SBox) .WidthOverride(Theme.ContentWidth / 3) [ SNew(STextBlock) .TextStyle(&Theme.TextFont) .Text(Name) ] ] // Stat value + SHorizontalBox::Slot() .AutoWidth() [ SNew(SBox) .WidthOverride(Theme.ContentWidth / 3) [ SNew(STextBlock) .TextStyle(&Theme.TextFont) .Text(FText::AsNumber(Result)) ] ] ]; }
/** * Takes the provided menu builder and adds elements representing various * profiles that the user can choose from (default, tutorial, etc.). * * @param MenuBuilder The builder to modify and add entries to. */ static void BuildProfilesSubMenu(FMenuBuilder& MenuBuilder) { TArray<FString> AvailableProfiles; const UEditorPerProjectUserSettings* EditorPerProjectUserSettings = GetDefault<UEditorPerProjectUserSettings>(); if (EditorPerProjectUserSettings->BlueprintFavorites != NULL) { static FString const ProfilesConfigKey("Profiles"); GConfig->GetArray(*SBlueprintFavoritesPaletteUtils::ConfigSection, *ProfilesConfigKey, AvailableProfiles, GEditorIni); } struct LocalUtils { static bool CanExecute() { return true; } static bool CannotExecute() { return false; } static void NavigateToURL(FString URL) { FPlatformProcess::LaunchURL(*URL, NULL, NULL); } }; if (AvailableProfiles.Num() > 0) { for (FString const& Profile : AvailableProfiles) { FString ProfileName; FParse::Value(*Profile, TEXT("Name="), ProfileName); FString FriendlyProfileName; FParse::Value(*Profile, TEXT("FriendlyName="), FriendlyProfileName); FString ProfileToolTip; FParse::Value(*Profile, TEXT("ToolTip="), ProfileToolTip); FString ProfileURL; FParse::Value(*Profile, TEXT("URL="), ProfileURL); FString ProfileURLName; FParse::Value(*Profile, TEXT("URLText="), ProfileURLName); // @TODO how to best localize this? FText ToolTipText = FText::FromString(ProfileToolTip); if (ProfileURLName.IsEmpty()) { ProfileURLName = ProfileURL; } if (FriendlyProfileName.IsEmpty()) { FriendlyProfileName = ProfileName; } FUIAction ProfileAction; if (SBlueprintFavoritesPaletteUtils::CanLoadFavoritesProfile(ProfileName)) { if (ToolTipText.IsEmpty()) { ToolTipText = FText::Format(LOCTEXT("ProfileAvailableFmt", "Loads {0} node favorites"), FText::FromString(FriendlyProfileName)); } ProfileAction = FUIAction( FExecuteAction::CreateStatic(&SBlueprintFavoritesPaletteUtils::LoadFavoritesProfile, ProfileName), FCanExecuteAction::CreateStatic(&LocalUtils::CanExecute) ); } else { if (ToolTipText.IsEmpty()) { ToolTipText = LOCTEXT("ProfileLoaded", "Current profile"); } ProfileAction = FUIAction( FExecuteAction(), FCanExecuteAction::CreateStatic(&LocalUtils::CannotExecute) ); } // build the text that goes in the sub-menu TSharedRef<STextBlock> MenuTextEntry = SNew(STextBlock) .TextStyle(MenuBuilder.GetStyleSet(), FEditorStyle::Join("Menu", ".Label")) // @TODO how do we best localize this .Text(FText::FromString(FriendlyProfileName)); FSlateFontInfo ToolTipFont(FPaths::EngineContentDir() / TEXT("Slate/Fonts/Roboto-Regular.ttf"), 8); TSharedPtr<SVerticalBox> ToolTipBox; // build the specialized tooltip TSharedRef<SToolTip> ToolTipWidget = SNew(SToolTip) [ SAssignNew(ToolTipBox, SVerticalBox) +SVerticalBox::Slot() [ SNew(STextBlock) .WrapTextAt(400) .Font(ToolTipFont) .Text(ToolTipText) ] ]; // add the url if one was specified if (!ProfileURL.IsEmpty()) { ToolTipBox->AddSlot() .AutoHeight() .HAlign(HAlign_Right) [ SNew(SHyperlink) // @TODO how to best localize this? .Text(FText::FromString(ProfileURLName)) .OnNavigate_Static(&LocalUtils::NavigateToURL, ProfileURL) ]; } // now build the actual menu widget TSharedRef<SWidget> MenuEntryWidget = SNew(SHorizontalBox) .ToolTip(ToolTipWidget) // so the tool tip shows up for the whole entry: .Visibility(EVisibility::Visible) +SHorizontalBox::Slot() // match the padding with normal sub-men entries .Padding(FMargin(18.f, 0.f, 6.f, 0.f)) .FillWidth(1.0f) [ MenuTextEntry ]; MenuBuilder.AddMenuEntry(ProfileAction, MenuEntryWidget); } } else { FUIAction NullProfileAction(FExecuteAction(), FCanExecuteAction::CreateStatic(&LocalUtils::CannotExecute)); MenuBuilder.AddMenuEntry(LOCTEXT("NoProfiles", "No profiles available"), FText::GetEmpty(), FSlateIcon(), NullProfileAction); } }
void SSingleProperty::SetObject( UObject* InObject ) { DestroyColorPicker(); if( !RootPropertyNode.IsValid() ) { RootPropertyNode = MakeShareable( new FObjectPropertyNode ); } RootPropertyNode->RemoveAllObjects(); ValueNode.Reset(); if( InObject ) { RootPropertyNode->AddObject( InObject ); } FPropertyNodeInitParams InitParams; InitParams.ParentNode = NULL; InitParams.Property = NULL; InitParams.ArrayOffset = 0; InitParams.ArrayIndex = INDEX_NONE; // we'll generate the children InitParams.bAllowChildren = false; InitParams.bForceHiddenPropertyVisibility = false; RootPropertyNode->InitNode( InitParams ); ValueNode = RootPropertyNode->GenerateSingleChild( PropertyName ); bool bIsAcceptableProperty = false; // valid criteria for standalone properties if( ValueNode.IsValid() ) { UProperty* Property = ValueNode->GetProperty(); bIsAcceptableProperty = true; // not an array property (dynamic or static) bIsAcceptableProperty &= !( Property->IsA( UArrayProperty::StaticClass() ) || (Property->ArrayDim > 1 && ValueNode->GetArrayIndex() == INDEX_NONE) ); // not a struct property unless its a built in type like a vector bIsAcceptableProperty &= ( !Property->IsA( UStructProperty::StaticClass() ) || PropertyEditorHelpers::IsBuiltInStructProperty( Property ) ); } if( bIsAcceptableProperty ) { ValueNode->RebuildChildren(); TSharedRef< FPropertyEditor > PropertyEditor = FPropertyEditor::Create( ValueNode.ToSharedRef(), TSharedPtr< IPropertyUtilities >( PropertyUtilities ).ToSharedRef() ); ValueNode->SetDisplayNameOverride( NameOverride ); TSharedPtr<SHorizontalBox> HorizontalBox; ChildSlot [ SAssignNew( HorizontalBox, SHorizontalBox ) ]; if( NamePlacement != EPropertyNamePlacement::Hidden ) { HorizontalBox->AddSlot() .Padding( 2.0f, 0.0f, 2.0f, 4.0f ) .AutoWidth() .VAlign( VAlign_Center ) [ SNew( SPropertyNameWidget, PropertyEditor ) .DisplayResetToDefault( false ) ]; } HorizontalBox->AddSlot() .Padding( 0.0f, 2.0f, 0.0f, 2.0f ) .FillWidth(1.0f) .VAlign( VAlign_Center ) [ SNew( SPropertyValueWidget, PropertyEditor, PropertyUtilities.ToSharedRef() ) ]; HorizontalBox->AddSlot() .Padding( 2.0f ) .AutoWidth() .VAlign( VAlign_Center ) [ SNew( SResetToDefaultPropertyEditor, PropertyEditor ) ]; } else { ChildSlot [ SNew(STextBlock) .Font(PropertyFont) .Text(NSLOCTEXT("PropertyEditor", "SinglePropertyInvalidType", "Cannot Edit Inline")) .ToolTipText(NSLOCTEXT("PropertyEditor", "SinglePropertyInvalidType_Tooltip", "Properties of this type cannot be edited inline; edit it elsewhere")) ]; // invalid or missing property RootPropertyNode->RemoveAllObjects(); ValueNode.Reset(); RootPropertyNode.Reset(); } }
/** * Construct the widget * * @param InDeclaration A declaration from which to construct the widget */ void Construct( const STableColumnHeader::FArguments& InArgs, const SHeaderRow::FColumn& Column, const FMargin DefaultHeaderContentPadding ) { check(InArgs._Style); SWidget::Construct( InArgs._ToolTipText, InArgs._ToolTip, InArgs._Cursor, InArgs._IsEnabled, InArgs._Visibility, InArgs._RenderTransform, InArgs._RenderTransformPivot, InArgs._Tag, InArgs._ForceVolatile, InArgs.MetaData ); Style = InArgs._Style; ColumnId = Column.ColumnId; SortMode = Column.SortMode; SortPriority = Column.SortPriority; OnSortModeChanged = Column.OnSortModeChanged; ContextMenuContent = Column.HeaderMenuContent.Widget; ComboVisibility = Column.HeaderComboVisibility; FMargin AdjustedDefaultHeaderContentPadding = DefaultHeaderContentPadding; TAttribute< FText > LabelText = Column.DefaultText; TAttribute< FText > TooltipText = Column.DefaultTooltip; if (Column.HeaderContent.Widget == SNullWidget::NullWidget) { if (!Column.DefaultText.IsSet()) { LabelText = FText::FromString( Column.ColumnId.ToString() + TEXT("[LabelMissing]") ); } if (!Column.DefaultTooltip.IsSet()) { TooltipText = LabelText; } } TSharedPtr< SHorizontalBox > Box; TSharedRef< SOverlay > Overlay = SNew( SOverlay ); Overlay->AddSlot( 0 ) [ SAssignNew( Box, SHorizontalBox ) ]; TSharedRef< SWidget > PrimaryContent = Column.HeaderContent.Widget; if ( PrimaryContent == SNullWidget::NullWidget ) { PrimaryContent = SNew( SBox ) .Padding( OnSortModeChanged.IsBound() ? FMargin( 0, 2, 0, 2 ) : FMargin( 0, 4, 0, 4 ) ) .VAlign( VAlign_Center ) [ SNew(STextBlock) .Text( LabelText ) .ToolTipText( TooltipText ) ]; } if ( OnSortModeChanged.IsBound() ) { //optional main button with the column's title. Used to toggle sorting modes. PrimaryContent = SNew(SButton) .ButtonStyle( FCoreStyle::Get(), "NoBorder" ) .ForegroundColor( FSlateColor::UseForeground() ) .ContentPadding( FMargin( 0, 2, 0, 2 ) ) .OnClicked(this, &STableColumnHeader::OnTitleClicked) [ PrimaryContent ]; } Box->AddSlot() .FillWidth(1.0f) [ PrimaryContent ]; if( Column.HeaderMenuContent.Widget != SNullWidget::NullWidget ) { // Add Drop down menu button (only if menu content has been specified) Box->AddSlot() .AutoWidth() [ SAssignNew( MenuOverlay, SOverlay ) .Visibility( this, &STableColumnHeader::GetMenuOverlayVisibility ) +SOverlay::Slot() [ SNew( SSpacer ) .Size( FVector2D( 12.0f, 0 ) ) ] +SOverlay::Slot() .Padding(FMargin(0,1,0,1)) [ SNew( SBorder ) .Padding( FMargin( 0, 0, AdjustedDefaultHeaderContentPadding.Right, 0 ) ) .BorderImage( this, &STableColumnHeader::GetComboButtonBorderBrush ) [ SAssignNew( ComboButton, SComboButton) .HasDownArrow(false) .ButtonStyle( FCoreStyle::Get(), "NoBorder" ) .ContentPadding( FMargin(0) ) .ButtonContent() [ SNew( SSpacer ) .Size( FVector2D( 14.0f, 0 ) ) ] .MenuContent() [ ContextMenuContent ] ] ] +SOverlay::Slot() .Padding(FMargin(0,0,0,2)) .HAlign( HAlign_Center ) .VAlign( VAlign_Bottom ) [ SNew(SImage) .Image( &Style->MenuDropdownImage ) .ColorAndOpacity( this, &STableColumnHeader::GetComboButtonTint ) .Visibility( EVisibility::HitTestInvisible ) ] ]; AdjustedDefaultHeaderContentPadding.Right = 0; } Overlay->AddSlot( 1 ) .HAlign(HAlign_Center) .VAlign( VAlign_Top ) .Padding( FMargin( 0, 2, 0, 0 ) ) [ SNew(SImage) .Image( this, &STableColumnHeader::GetSortingBrush ) .Visibility( this, &STableColumnHeader::GetSortModeVisibility ) ]; this->ChildSlot [ SNew( SBorder ) .BorderImage( this, &STableColumnHeader::GetHeaderBackgroundBrush ) .HAlign( Column.HeaderHAlignment ) .VAlign( Column.HeaderVAlignment ) .Padding( Column.HeaderContentPadding.Get( AdjustedDefaultHeaderContentPadding ) ) [ Overlay ] ]; }
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void FBrushDetails::CustomizeDetails( IDetailLayoutBuilder& DetailLayout ) { // Get level editor commands for our menus FLevelEditorModule& LevelEditor = FModuleManager::GetModuleChecked<FLevelEditorModule>( TEXT("LevelEditor") ); TSharedRef<const FUICommandList> CommandBindings = LevelEditor.GetGlobalLevelEditorActions(); const FLevelEditorCommands& Commands = LevelEditor.GetLevelEditorCommands(); // See if we have a volume. If we do - we hide the BSP stuff (solidity, order) bool bHaveAVolume = false; TArray< TWeakObjectPtr<UObject> > SelectedObjects = DetailLayout.GetDetailsView().GetSelectedObjects(); for (int32 ObjIdx = 0; ObjIdx < SelectedObjects.Num(); ObjIdx++) { if (ABrush* Brush = Cast<ABrush>(SelectedObjects[ObjIdx].Get())) { if (AVolume* Volume = Cast<AVolume>(Brush)) { bHaveAVolume = true; } if (!FActorEditorUtils::IsABuilderBrush(Brush)) { // Store the selected actors for use later. Its fine to do this when CustomizeDetails is called because if the selected actors changes, CustomizeDetails will be called again on a new instance // and our current resource would be destroyed. SelectedBrushes.Add(Brush); } } } FMenuBuilder PolygonsMenuBuilder( true, CommandBindings ); { PolygonsMenuBuilder.BeginSection("BrushDetailsPolygons"); { PolygonsMenuBuilder.AddMenuEntry( Commands.MergePolys ); PolygonsMenuBuilder.AddMenuEntry( Commands.SeparatePolys ); } PolygonsMenuBuilder.EndSection(); } FMenuBuilder SolidityMenuBuilder( true, CommandBindings ); { SolidityMenuBuilder.AddMenuEntry( Commands.MakeSolid ); SolidityMenuBuilder.AddMenuEntry( Commands.MakeSemiSolid ); SolidityMenuBuilder.AddMenuEntry( Commands.MakeNonSolid ); } FMenuBuilder OrderMenuBuilder( true, CommandBindings ); { OrderMenuBuilder.AddMenuEntry( Commands.OrderFirst ); OrderMenuBuilder.AddMenuEntry( Commands.OrderLast ); } struct Local { static FReply ExecuteExecCommand(FString InCommand) { GUnrealEd->Exec( GWorld, *InCommand ); return FReply::Handled(); } static TSharedRef<SWidget> GenerateBuildMenuContent(TSharedRef<IPropertyHandle> BrushBuilderHandle, IDetailLayoutBuilder* InDetailLayout) { class FBrushFilter : public IClassViewerFilter { public: virtual bool IsClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const UClass* InClass, TSharedRef< class FClassViewerFilterFuncs > InFilterFuncs ) { return !InClass->HasAnyClassFlags(CLASS_NotPlaceable) && !InClass->HasAnyClassFlags(CLASS_Abstract) && InClass->IsChildOf(UBrushBuilder::StaticClass()); } virtual bool IsUnloadedClassAllowed(const FClassViewerInitializationOptions& InInitOptions, const TSharedRef< const class IUnloadedBlueprintData > InUnloadedClassData, TSharedRef< class FClassViewerFilterFuncs > InFilterFuncs) { return false; } }; FClassViewerInitializationOptions Options; Options.ClassFilter = MakeShareable(new FBrushFilter); Options.Mode = EClassViewerMode::ClassPicker; Options.DisplayMode = EClassViewerDisplayMode::ListView; return FModuleManager::LoadModuleChecked<FClassViewerModule>("ClassViewer").CreateClassViewer(Options, FOnClassPicked::CreateStatic(&Local::OnClassPicked, BrushBuilderHandle, InDetailLayout)); } static void OnClassPicked(UClass* InChosenClass, TSharedRef<IPropertyHandle> BrushBuilderHandle, IDetailLayoutBuilder* InDetailLayout) { FSlateApplication::Get().DismissAllMenus(); TArray<UObject*> OuterObjects; BrushBuilderHandle->GetOuterObjects(OuterObjects); struct FNewBrushBuilder { UBrushBuilder* Builder; ABrush* Brush; }; TArray<FNewBrushBuilder> NewBuilders; TArray<FString> NewObjectPaths; { const FScopedTransaction Transaction(NSLOCTEXT("UnrealEd", "BrushSet", "Brush Set")); for (UObject* OuterObject : OuterObjects) { UBrushBuilder* NewUObject = NewObject<UBrushBuilder>(OuterObject, InChosenClass, NAME_None, RF_Transactional); FNewBrushBuilder NewBuilder; NewBuilder.Builder = NewUObject; NewBuilder.Brush = CastChecked<ABrush>(OuterObject); NewBuilders.Add(NewBuilder); NewObjectPaths.Add(NewUObject->GetPathName()); } BrushBuilderHandle->SetPerObjectValues(NewObjectPaths); // make sure the brushes are rebuilt for (FNewBrushBuilder& NewObject : NewBuilders) { NewObject.Builder->Build(NewObject.Brush->GetWorld(), NewObject.Brush); } GEditor->RebuildAlteredBSP(); } InDetailLayout->ForceRefreshDetails(); } static FText GetBuilderText(TSharedRef<IPropertyHandle> BrushBuilderHandle) { UObject* Object = nullptr; BrushBuilderHandle->GetValue(Object); if(Object != nullptr) { UBrushBuilder* BrushBuilder = CastChecked<UBrushBuilder>(Object); const FText NameText = BrushBuilder->GetClass()->GetDisplayNameText(); if(!NameText.IsEmpty()) { return NameText; } else { return FText::FromString(FName::NameToDisplayString(BrushBuilder->GetClass()->GetName(), false)); } } return LOCTEXT("None", "None"); } }; // Hide the brush builder if it is NULL TSharedRef<IPropertyHandle> BrushBuilderPropertyHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(ABrush, BrushBuilder)); UObject* BrushBuilderObject = nullptr; BrushBuilderPropertyHandle->GetValue(BrushBuilderObject); if(BrushBuilderObject == nullptr) { DetailLayout.HideProperty("BrushBuilder"); } else { BrushBuilderObject->SetFlags( RF_Transactional ); } IDetailCategoryBuilder& BrushBuilderCategory = DetailLayout.EditCategory( "BrushSettings", FText::GetEmpty(), ECategoryPriority::Important ); BrushBuilderCategory.AddProperty( GET_MEMBER_NAME_CHECKED(ABrush, BrushType) ); BrushBuilderCategory.AddCustomRow( LOCTEXT("BrushShape", "Brush Shape") ) .NameContent() [ SNew( STextBlock ) .Text( LOCTEXT("BrushShape", "Brush Shape")) .Font( IDetailLayoutBuilder::GetDetailFont() ) ] .ValueContent() .MinDesiredWidth(113) .MaxDesiredWidth(113) [ SNew(SComboButton) .ToolTipText(LOCTEXT("BspModeBuildTooltip", "Rebuild this brush from a parametric builder.")) .OnGetMenuContent_Static(&Local::GenerateBuildMenuContent, BrushBuilderPropertyHandle, &DetailLayout) .ContentPadding(2) .ButtonContent() [ SNew(STextBlock) .Text_Static(&Local::GetBuilderText, BrushBuilderPropertyHandle) .Font( IDetailLayoutBuilder::GetDetailFont() ) ] ]; BrushBuilderCategory.AddCustomRow( FText::GetEmpty(), true ) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .FillWidth(1) .Padding(1.0f) [ SNew(SComboButton) .ContentPadding(2) .ButtonContent() [ SNew(STextBlock) .Text(NSLOCTEXT("BrushDetails", "PolygonsMenu", "Polygons")) .ToolTipText(NSLOCTEXT("BrushDetails", "PolygonsMenu_ToolTip", "Polygon options")) .Font(IDetailLayoutBuilder::GetDetailFont()) ] .MenuContent() [ PolygonsMenuBuilder.MakeWidget() ] ] + SHorizontalBox::Slot() .FillWidth(1) .Padding(1.0f) [ SNew(SComboButton) .ContentPadding(2) .Visibility(bHaveAVolume ? EVisibility::Collapsed : EVisibility::Visible) .ButtonContent() [ SNew(STextBlock) .Text(NSLOCTEXT("BrushDetails", "SolidityMenu", "Solidity")) .ToolTipText(NSLOCTEXT("BrushDetails", "SolidityMenu_ToolTip", "Solidity options")) .Font(IDetailLayoutBuilder::GetDetailFont()) ] .MenuContent() [ SolidityMenuBuilder.MakeWidget() ] ] + SHorizontalBox::Slot() .FillWidth(1) .Padding(1.0f) [ SNew(SComboButton) .ContentPadding(2) .Visibility(bHaveAVolume ? EVisibility::Collapsed : EVisibility::Visible) .ButtonContent() [ SNew(STextBlock) .Text(NSLOCTEXT("BrushDetails", "OrderMenu", "Order")) .ToolTipText(NSLOCTEXT("BrushDetails", "OrderMenu_ToolTip", "Order options")) .Font(IDetailLayoutBuilder::GetDetailFont()) ] .MenuContent() [ OrderMenuBuilder.MakeWidget() ] ] ]; TSharedPtr< SHorizontalBox > BrushHorizontalBox; BrushBuilderCategory.AddCustomRow( FText::GetEmpty(), true) [ SAssignNew(BrushHorizontalBox, SHorizontalBox) +SHorizontalBox::Slot() [ SNew( SButton ) .ToolTipText( LOCTEXT("AlignBrushVerts_Tooltip", "Aligns each vertex of the brush to the grid.") ) .OnClicked( FOnClicked::CreateStatic( &Local::ExecuteExecCommand, FString( TEXT("ACTOR ALIGN VERTS") ) ) ) .HAlign( HAlign_Center ) [ SNew( STextBlock ) .Text( LOCTEXT("AlignBrushVerts", "Align Brush Vertices") ) .Font( IDetailLayoutBuilder::GetDetailFont() ) ] ] ]; if (SelectedBrushes.Num() > 0) { BrushHorizontalBox->AddSlot() [ SNew( SButton ) .ToolTipText( LOCTEXT("CreateStaticMeshActor_Tooltip", "Creates a static mesh from selected brushes or volumes and replaces them in the scene with the new static mesh") ) .OnClicked( this, &FBrushDetails::OnCreateStaticMesh ) .HAlign( HAlign_Center ) [ SNew( STextBlock ) .Text( LOCTEXT("CreateStaticMeshActor", "Create Static Mesh") ) .Font( IDetailLayoutBuilder::GetDetailFont() ) ] ]; } }
void SPropertyEditorAsset::Construct( const FArguments& InArgs, const TSharedPtr<FPropertyEditor>& InPropertyEditor ) { PropertyEditor = InPropertyEditor; PropertyHandle = InArgs._PropertyHandle; OnSetObject = InArgs._OnSetObject; UObject* Object = NULL; if(PropertyEditor.IsValid()) { UProperty* NodeProperty = PropertyEditor->GetPropertyNode()->GetProperty(); UObjectPropertyBase* ObjectProperty = Cast<UObjectPropertyBase>( NodeProperty ); check(ObjectProperty); bAllowClear = !(NodeProperty->PropertyFlags & CPF_NoClear); PropertyEditor->GetPropertyHandle()->GetValue( Object ); ObjectClass = ObjectProperty->PropertyClass; bIsActor = ObjectProperty->PropertyClass->IsChildOf( AActor::StaticClass() ); } else { bAllowClear = InArgs._AllowClear; ObjectPath = InArgs._ObjectPath; ObjectClass = InArgs._Class; bIsActor = ObjectClass->IsChildOf( AActor::StaticClass() ); } OnShouldFilterAsset = InArgs._OnShouldFilterAsset; TSharedPtr<SHorizontalBox> HorizontalBox = NULL; ChildSlot [ SNew( SAssetDropTarget ) .OnIsAssetAcceptableForDrop( this, &SPropertyEditorAsset::OnAssetDraggedOver ) .OnAssetDropped( this, &SPropertyEditorAsset::OnAssetDropped ) [ SAssignNew( HorizontalBox, SHorizontalBox ) ] ]; if(ShouldDisplayThumbnail(InArgs)) { FObjectOrAssetData Value; GetValue( Value ); AssetThumbnail = MakeShareable( new FAssetThumbnail( Value.AssetData, InArgs._ThumbnailSize.X, InArgs._ThumbnailSize.Y, InArgs._ThumbnailPool ) ); if( AssetThumbnail.IsValid() ) { HorizontalBox->AddSlot() .Padding( 0.0f, 0.0f, 2.0f, 0.0f ) .AutoWidth() [ SNew(SBorder) .Padding(2.0f) .BorderImage( FEditorStyle::GetBrush("PropertyEditor.AssetThumbnailShadow") ) .OnMouseDoubleClick( this, &SPropertyEditorAsset::OnAssetThumbnailDoubleClick ) [ SNew( SBox ) .ToolTipText( this, &SPropertyEditorAsset::OnGetToolTip ) .WidthOverride( InArgs._ThumbnailSize.X ) .HeightOverride( InArgs._ThumbnailSize.Y ) [ AssetThumbnail->MakeThumbnailWidget() ] ] ]; } } TSharedPtr<SHorizontalBox> ButtonBox; HorizontalBox->AddSlot() .FillWidth(1.0f) .Padding( 0.0f, 4.0f, 4.0f, 4.0f ) .VAlign(VAlign_Center) [ SNew(SVerticalBox) +SVerticalBox::Slot() .VAlign( VAlign_Center ) [ SAssignNew( ButtonBox, SHorizontalBox ) .IsEnabled( this, &SPropertyEditorAsset::CanEdit ) + SHorizontalBox::Slot() [ SAssignNew(AssetComboButton, SComboButton) .ToolTipText( this, &SPropertyEditorAsset::OnGetToolTip ) .ButtonStyle( FEditorStyle::Get(), "PropertyEditor.AssetComboStyle" ) .ForegroundColor(FEditorStyle::GetColor("PropertyEditor.AssetName.ColorAndOpacity")) .OnGetMenuContent( this, &SPropertyEditorAsset::OnGetMenuContent ) .ContentPadding(2.0f) .ButtonContent() [ // Show the name of the asset or actor SNew(STextBlock) .TextStyle( FEditorStyle::Get(), "PropertyEditor.AssetClass" ) .Font( FEditorStyle::GetFontStyle( PropertyEditorConstants::PropertyFontStyle ) ) .Text(this,&SPropertyEditorAsset::OnGetAssetName) ] ] ] +SVerticalBox::Slot() .AutoHeight() .Padding( InArgs._CustomContentSlot.Widget == SNullWidget::NullWidget ? FMargin( 0.0f, 0.0f ) : FMargin( 0.0f, 2.0f ) ) [ InArgs._CustomContentSlot.Widget ] ]; if(!bIsActor) { ButtonBox->AddSlot() .VAlign(VAlign_Center) .Padding( 2.0f, 0.0f ) .AutoWidth() [ PropertyCustomizationHelpers::MakeUseSelectedButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnUse ) ) ]; } ButtonBox->AddSlot() .AutoWidth() .Padding( 2.0f, 0.0f ) .VAlign(VAlign_Center) [ PropertyCustomizationHelpers::MakeBrowseButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnBrowse ), TAttribute<FText>( this, &SPropertyEditorAsset::GetOnBrowseToolTip ) ) ]; if(bIsActor) { ButtonBox->AddSlot() .AutoWidth() .Padding( 2.0f, 0.0f ) .VAlign(VAlign_Center) [ PropertyCustomizationHelpers::MakeInteractiveActorPicker( FOnGetAllowedClasses::CreateSP(this, &SPropertyEditorAsset::OnGetAllowedClasses), FOnActorSelected::CreateSP( this, &SPropertyEditorAsset::OnActorSelected ) ) ]; } if( InArgs._ResetToDefaultSlot.Widget != SNullWidget::NullWidget ) { ButtonBox->AddSlot() .AutoWidth() .Padding( 2.0f, 0.0f ) .VAlign(VAlign_Center) [ InArgs._ResetToDefaultSlot.Widget ]; } }
//------------------------------------------------------------------------------ void SBlueprintContextTargetMenu::Construct(const FArguments& InArgs, const FBlueprintActionContext& MenuContext) { TargetProfile = FContextMenuTargetProfile(MenuContext); OnTargetMaskChanged = InArgs._OnTargetMaskChanged; FSlateFontInfo HeaderFontStyle = FEditorStyle::GetFontStyle("BlueprintEditor.ActionMenu.ContextDescriptionFont"); HeaderFontStyle.Size -= 2.f; FText const HeaderText = ContextMenuTargetProfileImpl::GetProfileDescription(MenuContext); FText const MenuToolTip = LOCTEXT("MenuToolTip", "Select whose functions/variables you want to see.\nNOTE: Unchecking everything is akin to 'SHOW EVERYTHING' (you're choosing to have NO target context and to not limit the scope)"); TSharedPtr<SHorizontalBox> MenuBody; SBorder::Construct(SBorder::FArguments() .BorderImage(FEditorStyle::GetBrush("Menu.Background")) .Padding(5.f) .ToolTipText(MenuToolTip) [ SNew(SBox) .MinDesiredWidth(200) .ToolTipText(MenuToolTip) .Padding(FMargin(0.f, 0.f, 0.f, 18.f)) [ SNew(SVerticalBox) +SVerticalBox::Slot() .AutoHeight() [ SNew(SBorder) .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) .ForegroundColor(FEditorStyle::GetSlateColor("DefaultForeground")) [ SNew(STextBlock) .Text(HeaderText) .Font(HeaderFontStyle) ] ] +SVerticalBox::Slot() .VAlign(VAlign_Fill) .HAlign(HAlign_Fill) [ SAssignNew(MenuBody, SHorizontalBox) .ToolTipText(MenuToolTip) ] ] ] ); const uint32 ColumnCount = 2; TSharedPtr<SVerticalBox> Columns[ColumnCount]; for (int32 Col = 0; Col < ColumnCount; ++Col) { MenuBody->AddSlot() .AutoWidth() [ SAssignNew(Columns[Col], SVerticalBox) .ToolTipText(MenuToolTip) ]; } UEnum* const TargetEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EContextTargetFlags")); uint32 const GreatestFlag = (EContextTargetFlags::ContextTargetFlagsEnd & ~1); int32 ColIndex = 0; uint32 TargetFlag = (1<<0); while (TargetFlag <= GreatestFlag) { EContextTargetFlags::Type ContextTarget = (EContextTargetFlags::Type)TargetFlag; TargetFlag <<= 1; if (TargetEnum && TargetEnum->HasMetaData(TEXT("Hidden"), ContextTarget)) { continue; } FText const MenuName = BlueprintContextTargetMenuImpl::GetContextTargetDisplayName(TargetEnum, ContextTarget); const FContextMenuTargetProfile& ProfileRef = TargetProfile; Columns[ColIndex]->AddSlot() .AutoHeight() .VAlign(VAlign_Top) .Padding(3.f, 2.5f) [ SNew(SCheckBox) .IsEnabled_Raw(&TargetProfile, &FContextMenuTargetProfile::IsTargetEnabled, ContextTarget) .IsChecked(this, &SBlueprintContextTargetMenu::GetTargetCheckedState, ContextTarget) .OnCheckStateChanged(this, &SBlueprintContextTargetMenu::OnTargetCheckStateChanged, ContextTarget) .ToolTipText_Lambda([TargetEnum, ContextTarget, &ProfileRef]()->FText { if (!ProfileRef.IsTargetEnabled(ContextTarget)) { return LOCTEXT("DisabledTargetTooltip", "This target is invalid or redundent for this context."); } else if (TargetEnum != nullptr) { return TargetEnum->GetToolTipText(ContextTarget); } return LOCTEXT("GenericTargetTooltip", "Include variables/functions that belong to this target."); }) [ SNew(STextBlock).Text(MenuName) ] ]; ColIndex = (ColIndex + 1) % ColumnCount; } }
void SAnimMontageSectionsPanel::Update() { int32 ColorIdx=0; FLinearColor Colors[] = { FLinearColor(0.9f, 0.9f, 0.9f, 0.9f), FLinearColor(0.5f, 0.5f, 0.5f) }; FLinearColor NodeColor = FLinearColor(0.f, 0.5f, 0.0f, 0.5f); FLinearColor SelectedColor = FLinearColor(1.0f,0.65,0.0f); FLinearColor LoopColor = FLinearColor(0.0f, 0.25f, 0.25f, 0.5f); if ( Montage != NULL ) { TSharedPtr<STrack> Track; TSharedPtr<SVerticalBox> MontageSlots; PanelArea->SetContent( SAssignNew( MontageSlots, SVerticalBox ) ); SectionMap.Empty(); TopSelectionSet.Empty(); SelectionSet.Empty(); MontageSlots->ClearChildren(); SMontageEditor * Editor = MontageEditor.Pin().Get(); TArray<bool> Used; Used.AddZeroed(Montage->CompositeSections.Num()); int RowIdx=0; /** Create Buttons for reseting/creating default section ordering */ MontageSlots->AddSlot() .AutoHeight() .VAlign(VAlign_Center) .Padding( FMargin(0.5f, 0.5f) ) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) [ SNew(SButton) .IsEnabled(!bChildAnimMontage) .Visibility( EVisibility::Visible ) .Text( LOCTEXT("CreateDefault", "Create Default") ) .ToolTipText( LOCTEXT("CreateDefaultToolTip", "Reconstructs section ordering based on start time") ) .OnClicked(this, &SAnimMontageSectionsPanel::MakeDefaultSequence) .HAlign(HAlign_Center) .VAlign(VAlign_Center) ] + SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) [ SNew(SButton) .IsEnabled(!bChildAnimMontage) .Visibility( EVisibility::Visible ) .Text( LOCTEXT("Clear", "Clear") ) .ToolTipText( LOCTEXT("ClearToolTip", "Resets section orderings") ) .OnClicked(this, &SAnimMontageSectionsPanel::ClearSequence) .HAlign(HAlign_Center) .VAlign(VAlign_Center) ] ]; /** Create top track of section nodes */ MontageSlots->AddSlot() .AutoHeight() .VAlign(VAlign_Center) .Padding( FMargin(0.5f, 20.0f) ) [ SAssignNew(Track, STrack) .IsEnabled(!bChildAnimMontage) .ViewInputMin(0) .ViewInputMax(100) .TrackColor( FLinearColor(0.0f, 0.0f, 0.0f, 0.0f)) .TrackMaxValue(100) ]; for(int32 SectionIdx=0; SectionIdx < Montage->CompositeSections.Num(); SectionIdx++) { const float NodeLength = 100.f / static_cast<float>(Montage->CompositeSections.Num()+1); const float NodeSpacing = 100.f / static_cast<float>(Montage->CompositeSections.Num()); Track->AddTrackNode( SNew(STrackNode) .ViewInputMax(100) .ViewInputMin(0) .NodeColor(NodeColor) .SelectedNodeColor(SelectedColor) .DataLength(NodeLength) .DataStartPos(NodeSpacing * SectionIdx) .NodeName(Montage->CompositeSections[SectionIdx].SectionName.ToString()) .NodeSelectionSet(&TopSelectionSet) .OnTrackNodeClicked( this, &SAnimMontageSectionsPanel::TopSectionClicked, SectionIdx) .AllowDrag(false) ); } MontageSlots->AddSlot() .AutoHeight() .VAlign(VAlign_Center) .Padding( FMargin(0.5f, 0.0f) ) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) [ SNew(SButton) .Visibility( EVisibility::Visible ) .Text( LOCTEXT("PreviewAll", "Preview All Sections") ) .ToolTipText( LOCTEXT("PreviewAllToolTip", "Preview all sections in order they are") ) .OnClicked(this, &SAnimMontageSectionsPanel::PreviewAllSectionsClicked) .HAlign(HAlign_Center) .VAlign(VAlign_Center) ] ]; /** Create as many tracks as necessary to show each section at least once * -Each track represents one chain of sections (section->next->next) */ while(true) { int32 SectionIdx = 0; TArray<bool> UsedInThisRow; UsedInThisRow.AddZeroed(Montage->CompositeSections.Num()); /** Find first section we haven't shown yet */ for(;SectionIdx < Montage->CompositeSections.Num(); SectionIdx++) { if(!Used[SectionIdx]) break; } if(SectionIdx >= Montage->CompositeSections.Num()) { // Ran out of stuff to show - done break; } /** Create new track */ SectionMap.Add( TArray<int32>() ); MontageSlots->AddSlot() .AutoHeight() .VAlign(VAlign_Center) .Padding( FMargin(0.5f, 0.5f) ) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) [ SNew(SButton) .Visibility( EVisibility::Visible ) .Text( LOCTEXT("Preview", "Preview") ) .ToolTipText( LOCTEXT("PreviewToolTip", "Preview this track") ) .OnClicked(this, &SAnimMontageSectionsPanel::PreviewSectionClicked, SectionIdx) .HAlign(HAlign_Center) .VAlign(VAlign_Center) ] + SHorizontalBox::Slot() .FillWidth(1.0f) .VAlign(VAlign_Center) [ SAssignNew(Track, STrack) .ViewInputMin(0) .ViewInputMax(100) .TrackColor( Colors[ColorIdx++ & 1]) .TrackMaxValue(100) ] ]; /** Add each track in this chain to the track we just created */ int count =0; float TrackPos = 0; const float BarLength = 8; const float XLength = 1; while(true) { /** Add section if it hasn't already been used in this row (if its used in another row, thats ok) */ if(Montage->IsValidSectionIndex(SectionIdx) && UsedInThisRow[SectionIdx]==false) { UsedInThisRow[SectionIdx] = true; Used[SectionIdx] = true; SectionMap[RowIdx].Add(SectionIdx); Track->AddTrackNode( SNew(STrackNode) .IsEnabled(!bChildAnimMontage) .ViewInputMax(100) .ViewInputMin(0) .NodeColor( IsLoop(SectionIdx) ? LoopColor : NodeColor) .SelectedNodeColor(SelectedColor) .DataLength(BarLength) .DataStartPos(TrackPos) .NodeName(Montage->CompositeSections[SectionIdx].SectionName.ToString()) .OnTrackNodeDragged( this, &SAnimMontageSectionsPanel::SetSectionPos, SectionIdx, RowIdx) .OnTrackNodeDropped( this, &SAnimMontageSectionsPanel::OnSectionDrop) .OnTrackNodeClicked( this, &SAnimMontageSectionsPanel::SectionClicked, SectionIdx) .NodeSelectionSet(&SelectionSet) .AllowDrag(false) ); TrackPos += BarLength + 0.25f; /** If this has a next section, create an X to delete that link */ if(Montage->CompositeSections[SectionIdx].NextSectionName != NAME_None) { Track->AddTrackNode( SNew(STrackNode) .IsEnabled(!bChildAnimMontage) .ViewInputMax(100) .ViewInputMin(0) .NodeColor(IsLoop(SectionIdx) ? LoopColor : NodeColor) .SelectedNodeColor(SelectedColor) .DataStartPos(TrackPos) .NodeName(TEXT("x")) .OnTrackNodeDropped( this, &SAnimMontageSectionsPanel::OnSectionDrop) .OnTrackNodeClicked( this, &SAnimMontageSectionsPanel::RemoveLink, SectionIdx) .NodeSelectionSet(&SelectionSet) .AllowDrag(false) ); TrackPos += XLength + 0.25; } count++; SectionIdx = Montage->GetSectionIndex( Montage->CompositeSections[SectionIdx].NextSectionName ); continue; } else { break; } } } RowIdx++; } SelectedCompositeSection = INDEX_NONE; }
/* Make the Midgard dump widget (where we dump the statistics for Midgard compilation) */ TSharedRef<SWidget> ConstructMidgardDumpWidget(const TArray<TSharedRef<FMaliOCReport::FMidgardReport>>& Reports, bool DumpSourceCode) { TSharedRef<SVerticalBox> midgardBox = SNew(SVerticalBox); for (const auto& report : Reports) { TSharedPtr<SVerticalBox> reportWarningBox = nullptr; midgardBox->AddSlot() .Padding(WidgetPadding) .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(report->TitleName)) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .ToolTipText(FText::FromString(report->TitleName)) .InitiallyCollapsed(false) .Padding(WidgetPadding) .BodyContent() [ SAssignNew(reportWarningBox, SVerticalBox) ] ]; // Print the details of the shader (such as frequency) reportWarningBox->AddSlot() .AutoHeight() [ GenerateFStringListView(report->Details) ]; // If there's only one render target, don't make an expandable area if (report->RenderTargets.Num() == 1) { reportWarningBox->AddSlot() .AutoHeight() [ SNew(SSeparator) ]; reportWarningBox->AddSlot() .AutoHeight() [ GenerateMidgardStatsTable(report->RenderTargets[0]) ]; } else { for (const auto& rt : report->RenderTargets) { reportWarningBox->AddSlot() .AutoHeight() [ SNew(SSeparator) ]; reportWarningBox->AddSlot() .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(FString::Printf(TEXT("Render Target %u"), rt->Index))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(false) .Padding(WidgetPadding) .BodyContent() [ GenerateMidgardStatsTable(rt) ] ]; } } // Dump the warnings if (report->Warnings.Num() > 0) { reportWarningBox->AddSlot() .AutoHeight() [ SNew(SSeparator) ]; reportWarningBox->AddSlot() .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(TEXT("Warnings"))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(false) .Padding(WidgetPadding) .BodyContent() [ GenerateFStringListView(report->Warnings) ] ]; } if (DumpSourceCode) { AddSourceCodeToVerticalBox(reportWarningBox, report->SourceCode); } } return midgardBox; }
void SPropertyEditorAsset::Construct( const FArguments& InArgs, const TSharedPtr<FPropertyEditor>& InPropertyEditor ) { PropertyEditor = InPropertyEditor; PropertyHandle = InArgs._PropertyHandle; OnSetObject = InArgs._OnSetObject; OnShouldFilterAsset = InArgs._OnShouldFilterAsset; UProperty* Property = nullptr; if(PropertyEditor.IsValid()) { Property = PropertyEditor->GetPropertyNode()->GetProperty(); UObjectPropertyBase* ObjectProperty = Cast<UObjectPropertyBase>(Property); check(ObjectProperty); bAllowClear = !(Property->PropertyFlags & CPF_NoClear); ObjectClass = ObjectProperty->PropertyClass; bIsActor = ObjectProperty->PropertyClass->IsChildOf( AActor::StaticClass() ); } else { bAllowClear = InArgs._AllowClear; ObjectPath = InArgs._ObjectPath; ObjectClass = InArgs._Class; bIsActor = ObjectClass->IsChildOf( AActor::StaticClass() ); if (PropertyHandle.IsValid() && PropertyHandle->IsValidHandle()) { Property = PropertyHandle->GetProperty(); } else { CustomClassFilters.Add(ObjectClass); } } // Account for the allowed classes specified in the property metadata if (Property) { FString ClassFilterString; if (UArrayProperty* ArrayParent = Cast<UArrayProperty>(Property->GetOuter())) { ClassFilterString = ArrayParent->GetMetaData("AllowedClasses"); } else { ClassFilterString = Property->GetMetaData("AllowedClasses"); } if (ClassFilterString.IsEmpty()) { CustomClassFilters.Add(ObjectClass); } else { TArray<FString> CustomClassFilterNames; ClassFilterString.ParseIntoArray(CustomClassFilterNames, TEXT(","), true); for (auto It = CustomClassFilterNames.CreateConstIterator(); It; ++It) { const FString& ClassName = *It; UClass* Class = FindObject<UClass>(ANY_PACKAGE, *ClassName); if (!Class) { Class = LoadObject<UClass>(nullptr, *ClassName); } if (Class) { // If the class is an interface, expand it to be all classes in memory that implement the class. if (Class->HasAnyClassFlags(CLASS_Interface)) { for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* const ClassWithInterface = (*ClassIt); if (ClassWithInterface->ImplementsInterface(Class)) { CustomClassFilters.Add(ClassWithInterface); } } } else { CustomClassFilters.Add(Class); } } } } } if (InArgs._NewAssetFactories.IsSet()) { NewAssetFactories = InArgs._NewAssetFactories.GetValue(); } else if (CustomClassFilters.Num() > 1 || !CustomClassFilters.Contains(UObject::StaticClass())) { NewAssetFactories = PropertyCustomizationHelpers::GetNewAssetFactoriesForClasses(CustomClassFilters); } TSharedPtr<SHorizontalBox> ValueContentBox = NULL; ChildSlot [ SNew( SAssetDropTarget ) .OnIsAssetAcceptableForDrop( this, &SPropertyEditorAsset::OnAssetDraggedOver ) .OnAssetDropped( this, &SPropertyEditorAsset::OnAssetDropped ) [ SAssignNew( ValueContentBox, SHorizontalBox ) ] ]; TAttribute<bool> IsEnabledAttribute(this, &SPropertyEditorAsset::CanEdit); TAttribute<FText> TooltipAttribute(this, &SPropertyEditorAsset::OnGetToolTip); if (Property && Property->HasAllPropertyFlags(CPF_DisableEditOnTemplate)) { // There are some cases where editing an Actor Property is not allowed, such as when it is contained within a struct or a CDO TArray<UObject*> ObjectList; PropertyEditor->GetPropertyHandle()->GetOuterObjects(ObjectList); // If there is no objects, that means we must have a struct asset managing this property if (ObjectList.Num() == 0) { IsEnabledAttribute.Set(false); TooltipAttribute.Set(LOCTEXT("VariableHasDisableEditOnTemplate", "Editing this value in structure's defaults is not allowed")); } else { // Go through all the found objects and see if any are a CDO, we can't set an actor in a CDO default. for (UObject* Obj : ObjectList) { if (Obj->HasAllFlags(RF_ClassDefaultObject)) { IsEnabledAttribute.Set(false); TooltipAttribute.Set(LOCTEXT("VariableHasDisableEditOnTemplateTooltip", "Editing this value in a Class Default Object is not allowed")); break; } } } } AssetComboButton = SNew(SComboButton) .ToolTipText(TooltipAttribute) .ButtonStyle( FEditorStyle::Get(), "PropertyEditor.AssetComboStyle" ) .ForegroundColor(FEditorStyle::GetColor("PropertyEditor.AssetName.ColorAndOpacity")) .OnGetMenuContent( this, &SPropertyEditorAsset::OnGetMenuContent ) .OnMenuOpenChanged( this, &SPropertyEditorAsset::OnMenuOpenChanged ) .IsEnabled( IsEnabledAttribute ) .ContentPadding(2.0f) .ButtonContent() [ // Show the name of the asset or actor SNew(STextBlock) .TextStyle( FEditorStyle::Get(), "PropertyEditor.AssetClass" ) .Font( FEditorStyle::GetFontStyle( PropertyEditorConstants::PropertyFontStyle ) ) .Text(this,&SPropertyEditorAsset::OnGetAssetName) ]; TSharedRef<SHorizontalBox> ButtonBox = SNew( SHorizontalBox ); TSharedPtr<SVerticalBox> CustomContentBox; if( ShouldDisplayThumbnail(InArgs) ) { FObjectOrAssetData Value; GetValue( Value ); AssetThumbnail = MakeShareable( new FAssetThumbnail( Value.AssetData, InArgs._ThumbnailSize.X, InArgs._ThumbnailSize.Y, InArgs._ThumbnailPool ) ); ValueContentBox->AddSlot() .Padding( 0.0f, 0.0f, 2.0f, 0.0f ) .AutoWidth() [ SAssignNew( ThumbnailBorder, SBorder ) .Padding( 5.0f ) .BorderImage( this, &SPropertyEditorAsset::GetThumbnailBorder ) .OnMouseDoubleClick( this, &SPropertyEditorAsset::OnAssetThumbnailDoubleClick ) [ SNew( SBox ) .ToolTipText(TooltipAttribute) .WidthOverride( InArgs._ThumbnailSize.X ) .HeightOverride( InArgs._ThumbnailSize.Y ) [ AssetThumbnail->MakeThumbnailWidget() ] ] ]; ValueContentBox->AddSlot() [ SNew( SBox ) .VAlign( VAlign_Center ) [ SAssignNew( CustomContentBox, SVerticalBox ) + SVerticalBox::Slot() [ AssetComboButton.ToSharedRef() ] + SVerticalBox::Slot() .AutoHeight() .Padding( 0.0f, 2.0f, 4.0f, 2.0f ) [ ButtonBox ] ] ]; } else { ValueContentBox->AddSlot() [ SAssignNew( CustomContentBox, SVerticalBox ) +SVerticalBox::Slot() .VAlign( VAlign_Center ) [ SNew( SHorizontalBox ) + SHorizontalBox::Slot() [ AssetComboButton.ToSharedRef() ] + SHorizontalBox::Slot() .AutoWidth() .Padding( 4.f, 0.f ) [ ButtonBox ] ] ]; } if( InArgs._CustomContentSlot.Widget != SNullWidget::NullWidget ) { CustomContentBox->AddSlot() .VAlign( VAlign_Center ) .Padding( FMargin( 0.0f, 2.0f ) ) [ InArgs._CustomContentSlot.Widget ]; } if( !bIsActor && InArgs._DisplayUseSelected ) { ButtonBox->AddSlot() .VAlign(VAlign_Center) .AutoWidth() .Padding( 2.0f, 0.0f ) [ PropertyCustomizationHelpers::MakeUseSelectedButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnUse ), FText(), IsEnabledAttribute ) ]; } if( InArgs._DisplayBrowse ) { ButtonBox->AddSlot() .Padding( 2.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ PropertyCustomizationHelpers::MakeBrowseButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnBrowse ), TAttribute<FText>( this, &SPropertyEditorAsset::GetOnBrowseToolTip ) ) ]; } if( bIsActor ) { TSharedRef<SWidget> ActorPicker = PropertyCustomizationHelpers::MakeInteractiveActorPicker( FOnGetAllowedClasses::CreateSP(this, &SPropertyEditorAsset::OnGetAllowedClasses), FOnShouldFilterActor(), FOnActorSelected::CreateSP( this, &SPropertyEditorAsset::OnActorSelected ) ); ActorPicker->SetEnabled( IsEnabledAttribute ); ButtonBox->AddSlot() .Padding( 2.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ ActorPicker ]; } if( InArgs._ResetToDefaultSlot.Widget != SNullWidget::NullWidget ) { TSharedRef<SWidget> ResetToDefaultWidget = InArgs._ResetToDefaultSlot.Widget; ResetToDefaultWidget->SetEnabled( IsEnabledAttribute ); ButtonBox->AddSlot() .Padding( 4.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ ResetToDefaultWidget ]; } }
/* Make the Utgard dump widget (where we dump the statistics for Utgard compilation) */ TSharedRef<SWidget> ConstructUtgardDumpWidget(const TArray<TSharedRef<FMaliOCReport::FUtgardReport>>& Reports, bool DumpSourceCode) { TSharedRef<SVerticalBox> utgardBox = SNew(SVerticalBox); for (const auto& report : Reports) { TSharedPtr<SVerticalBox> reportWarningBox = nullptr; utgardBox->AddSlot() .Padding(WidgetPadding) .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(report->TitleName)) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .ToolTipText(FText::FromString(report->TitleName)) .InitiallyCollapsed(false) .Padding(WidgetPadding) .BodyContent() [ SAssignNew(reportWarningBox, SVerticalBox) + SVerticalBox::Slot() .AutoHeight() [ GenerateFStringListView(report->Details) ] + SVerticalBox::Slot() .AutoHeight() [ SNew(SSeparator) ] + SVerticalBox::Slot() .AutoHeight() [ GenerateFStringListView(report->ExtraDetails) ] ] ]; // Dump the warnings if (report->Warnings.Num() > 0) { reportWarningBox->AddSlot() .AutoHeight() [ SNew(SSeparator) ]; reportWarningBox->AddSlot() .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(TEXT("Warnings"))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(false) .Padding(WidgetPadding) .BodyContent() [ GenerateFStringListView(report->Warnings) ] ]; } if (DumpSourceCode) { AddSourceCodeToVerticalBox(reportWarningBox, report->SourceCode); } } return utgardBox; }
/* Construct the error widget from an array of errors*/ TSharedRef<SWidget> ConstructErrorWidget(const TArray<TSharedRef<FMaliOCReport::FErrorReport>>& Errors) { TSharedRef<SVerticalBox> errorBox = SNew(SVerticalBox); for (const auto& error : Errors) { TSharedPtr<SVerticalBox> errorWarningBox = nullptr; errorBox->AddSlot() .Padding(WidgetPadding) .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(error->TitleName)) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(false) .Padding(WidgetPadding) .BodyContent() [ SAssignNew(errorWarningBox, SVerticalBox) ] ]; // Print the details of the shader (such as frequency) errorWarningBox->AddSlot() .AutoHeight() [ GenerateFStringListView(error->Details) ]; if (error->Errors.Num() > 0) { errorWarningBox->AddSlot() .AutoHeight() [ SNew(SSeparator) ]; errorWarningBox->AddSlot() .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(TEXT("Errors"))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(false) .Padding(WidgetPadding) .BodyContent() [ GenerateFStringListView(error->Errors) ] ]; } if (error->Warnings.Num() > 0) { errorWarningBox->AddSlot() .AutoHeight() [ SNew(SSeparator) ]; errorWarningBox->AddSlot() .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(TEXT("Warnings"))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(false) .Padding(WidgetPadding) .BodyContent() [ GenerateFStringListView(error->Warnings) ] ]; } AddSourceCodeToVerticalBox(errorWarningBox, error->SourceCode); } return errorBox; }
/* Create the top level report widget */ TSharedPtr<SWidget> ConstructReportWidget(const FAsyncReportGenerator& Generator) { TSharedPtr<SVerticalBox> Widget = nullptr; TSharedPtr<SWidget> ReportWidget = SNew(SScrollBox) + SScrollBox::Slot() [ SAssignNew(Widget, SVerticalBox) ]; auto Report = Generator.GetReport(); // First show any errors, if there are any if (Report->ErrorList.Num() > 0) { Widget->AddSlot() .Padding(WidgetPadding) .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(TEXT("Error Summary"))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(false) .BorderBackgroundColor(FLinearColor(0.5f, 0.5f, 0.5f, 1.0f)) .Padding(WidgetPadding) .BodyContent() [ ConstructErrorWidget(Report->ErrorList) ] ]; } // Next show Midgard reports if there are any if (Report->MidgardReports.Num() > 0) { Widget->AddSlot() .Padding(WidgetPadding) .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(TEXT("Statistics Summary"))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(false) .BorderBackgroundColor(FLinearColor(0.5f, 0.5f, 0.5f, 1.0f)) .Padding(WidgetPadding) .BodyContent() [ SNew(SVerticalBox) + SVerticalBox::Slot() .Padding(WidgetPadding) .AutoHeight() [ GenerateFStringListView(Report->ShaderSummaryStrings) ] + SVerticalBox::Slot() .AutoHeight() [ ConstructMidgardDumpWidget(Report->MidgardSummaryReports, false) ] ] ]; // Dump the rest of the shaders by vertex factory name TMap<FString, TArray<TSharedRef<FMaliOCReport::FMidgardReport>>> VertexFactoryNames; for (auto& report : Report->MidgardReports) { VertexFactoryNames.FindOrAdd(report->VertexFactoryName).Add(report); } for (const auto& name : VertexFactoryNames) { Widget->AddSlot() .Padding(WidgetPadding) .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(FString::Printf(TEXT("All %s"), *name.Key))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(true) .BorderBackgroundColor(FLinearColor(0.5f, 0.5f, 0.5f, 1.0f)) .Padding(WidgetPadding) .BodyContent() [ ConstructMidgardDumpWidget(name.Value, true) ] ]; } } // Next show Utgard reports, if there are any. These should be mutually exclusive with Midgard reports if (Report->UtgardReports.Num() > 0) { Widget->AddSlot() .Padding(WidgetPadding) .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(TEXT("Statistics Summary"))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(false) .BorderBackgroundColor(FLinearColor(0.5f, 0.5f, 0.5f, 1.0f)) .Padding(WidgetPadding) .BodyContent() [ SNew(SVerticalBox) + SVerticalBox::Slot() .Padding(WidgetPadding) .AutoHeight() [ GenerateFStringListView(Report->ShaderSummaryStrings) ] + SVerticalBox::Slot() .AutoHeight() [ ConstructUtgardDumpWidget(Report->UtgardSummaryReports, false) ] ] ]; // Dump the rest of the shaders by vertex factory name TMap<FString, TArray<TSharedRef<FMaliOCReport::FUtgardReport>>> VertexFactoryNames; for (auto& report : Report->UtgardReports) { VertexFactoryNames.FindOrAdd(report->VertexFactoryName).Add(report); } for (const auto& name : VertexFactoryNames) { Widget->AddSlot() .Padding(WidgetPadding) .AutoHeight() [ SNew(SExpandableArea) .AreaTitle(FText::FromString(FString::Printf(TEXT("All %s"), *name.Key))) .AreaTitleFont(FEditorStyle::GetFontStyle(TEXT("DetailsView.CategoryFontStyle"))) .InitiallyCollapsed(true) .BorderBackgroundColor(FLinearColor(0.5f, 0.5f, 0.5f, 1.0f)) .Padding(WidgetPadding) .BodyContent() [ ConstructUtgardDumpWidget(name.Value, true) ] ]; } } return ReportWidget; }