/* 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
	);
}
Esempio n. 8
0
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;
};
Esempio n. 12
0
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
    ];
}
Esempio n. 15
0
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()
			];
	}
}
Esempio n. 16
0
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 )
		];
	}
}
Esempio n. 18
0
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);
		}
	}
Esempio n. 20
0
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();
	}
}
Esempio n. 21
0
    /**
     * 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
            ]
        ];
    }
Esempio n. 22
0
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;
}