TSharedRef<SToolTip> FUICommandInfo::MakeTooltip( const TAttribute<FText>& InText, const TAttribute< EVisibility >& InToolTipVisibility ) const
{
	return 
		SNew(SToolTip)
		.Visibility(InToolTipVisibility.IsBound() ? InToolTipVisibility : EVisibility::Visible)
		.Content()
		[
			SNew(SVerticalBox)
			+SVerticalBox::Slot()
			.Padding(0.0f, 0.0f, 0.0f, 4.0f)
			[
				SNew(STextBlock)
				.Text(InText.IsBound() ? InText : GetDescription())
				.Font(FCoreStyle::Get().GetFontStyle( "ToolTip.Font" ))
				.ColorAndOpacity( FSlateColor::UseForeground() )
			]
			+SVerticalBox::Slot()
			[
				SNew(STextBlock)
				.Text(GetInputText())
				.Font(FCoreStyle::Get().GetFontStyle( "ToolTip.Font" ))
				.ColorAndOpacity( FSlateColor::UseSubduedForeground() )
			]
		];
}
void FDetailPropertyRow::GenerateChildrenForPropertyNode( TSharedPtr<FPropertyNode>& RootPropertyNode, FDetailNodeList& OutChildren )
{
	// Children should be disabled if we are disabled
	TAttribute<bool> ParentEnabledState = CustomIsEnabledAttrib;
	if( IsParentEnabled.IsBound() || HasEditCondition() )
	{
		// Bind a delegate to the edit condition so our children will be disabled if the edit condition fails
		ParentEnabledState.Bind( this, &FDetailPropertyRow::GetEnabledState );
	}

	if( PropertyTypeLayoutBuilder.IsValid() && bShowCustomPropertyChildren )
	{
		const TArray< FDetailLayoutCustomization >& ChildRows = PropertyTypeLayoutBuilder->GetChildCustomizations();

		for( int32 ChildIndex = 0; ChildIndex < ChildRows.Num(); ++ChildIndex )
		{
			TSharedRef<FDetailItemNode> ChildNodeItem = MakeShareable( new FDetailItemNode( ChildRows[ChildIndex], ParentCategory.Pin().ToSharedRef(), ParentEnabledState ) );
			ChildNodeItem->Initialize();
			OutChildren.Add( ChildNodeItem );
		}
	}
	else if (bShowCustomPropertyChildren || !CustomPropertyWidget.IsValid() )
	{
		TSharedRef<FDetailCategoryImpl> ParentCategoryRef = ParentCategory.Pin().ToSharedRef();
		IDetailLayoutBuilder& LayoutBuilder = ParentCategoryRef->GetParentLayout();
		UProperty* ParentProperty = RootPropertyNode->GetProperty();

		const bool bStructProperty = ParentProperty && ParentProperty->IsA<UStructProperty>();

		for( int32 ChildIndex = 0; ChildIndex < RootPropertyNode->GetNumChildNodes(); ++ChildIndex )
		{
			TSharedPtr<FPropertyNode> ChildNode = RootPropertyNode->GetChildNode(ChildIndex);

			if( ChildNode.IsValid() && ChildNode->HasNodeFlags( EPropertyNodeFlags::IsCustomized ) == 0 )
			{
				if( ChildNode->AsObjectNode() )
				{
					// Skip over object nodes and generate their children.  Object nodes are not visible
					GenerateChildrenForPropertyNode( ChildNode, OutChildren );
				}
				// Only struct children can have custom visibility that is different from their parent.
				else if ( !bStructProperty || LayoutBuilder.IsPropertyVisible( FPropertyAndParent(*ChildNode->GetProperty(), ParentProperty ) ) )
				{			
					FDetailLayoutCustomization Customization;
					Customization.PropertyRow = MakeShareable( new FDetailPropertyRow( ChildNode, ParentCategoryRef ) );
					TSharedRef<FDetailItemNode> ChildNodeItem = MakeShareable( new FDetailItemNode( Customization, ParentCategoryRef, ParentEnabledState ) );
					ChildNodeItem->Initialize();
					OutChildren.Add( ChildNodeItem );
				}
			}
		}
	}
}
void FFloatPropertySection::GenerateSectionLayout(class ISectionLayoutBuilder& LayoutBuilder) const
{
	UMovieSceneFloatSection* FloatSection = Cast<UMovieSceneFloatSection>(&SectionObject);
	TAttribute<TOptional<float>> ExternalValue;
	if (CanGetPropertyValue())
	{
		ExternalValue.Bind(TAttribute<TOptional<float>>::FGetter::CreateLambda([&]
		{
			return GetPropertyValue<float>();
		}));
	}
	TSharedRef<FFloatCurveKeyArea> KeyArea = MakeShareable(
		new FFloatCurveKeyArea(&FloatSection->GetFloatCurve(), ExternalValue, FloatSection));
	LayoutBuilder.SetSectionAsKeyArea(KeyArea);
}
		/** Appends the key binding to the end of the provided ToolTip */
		static FText AppendKeyBindingToToolTip( const TAttribute<FText> ToolTip, TWeakPtr< const FUICommandInfo> Command )
		{
			TSharedPtr<const FUICommandInfo> CommandPtr = Command.Pin();

			if( CommandPtr.IsValid() && CommandPtr->GetActiveChord()->IsValidChord() )
			{
				FFormatNamedArguments Args;
				Args.Add( TEXT("ToolTipDescription"), ToolTip.Get() );
				Args.Add( TEXT("Keybinding"), CommandPtr->GetInputText() );
				return FText::Format( NSLOCTEXT("ToolBar", "ToolTip + Keybinding", "{ToolTipDescription} ({Keybinding})"), Args );
			}
			else
			{
				return ToolTip.Get();
			}
		}
Пример #5
0
	/** Sets the text and delegate for the hyperlink */
	virtual void SetHyperlink( const FSimpleDelegate& InHyperlink, const TAttribute< FText >& InHyperlinkText = TAttribute< FText >() ) override
	{
		Hyperlink = InHyperlink;

		// Only replace the text if specified
		if ( InHyperlinkText.IsBound() )
		{
			HyperlinkText = InHyperlinkText;
		}
	}
Пример #6
0
TSharedRef< class SToolTip > FDocumentation::CreateToolTip(const TAttribute<FText>& Text, const TSharedPtr<SWidget>& OverrideContent, const FString& Link, const FString& ExcerptName) const
{
	TSharedPtr< SDocumentationToolTip > DocToolTip;

	if ( !Text.IsBound() && Text.Get().IsEmpty() )
	{
		return SNew( SToolTip );
	}

	if ( OverrideContent.IsValid() )
	{
		SAssignNew( DocToolTip, SDocumentationToolTip )
		.DocumentationLink( Link )
		.ExcerptName( ExcerptName )
		[
			OverrideContent.ToSharedRef()
		];
	}
	else
	{
		SAssignNew( DocToolTip, SDocumentationToolTip )
		.Text( Text )
		.DocumentationLink( Link )
		.ExcerptName( ExcerptName );
	}
	
	return SNew( SToolTip )
		.IsInteractive( DocToolTip.ToSharedRef(), &SDocumentationToolTip::IsInteractive )

		// Emulate text-only tool-tip styling that SToolTip uses when no custom content is supplied.  We want documentation tool-tips to 
		// be styled just like text-only tool-tips
		.BorderImage( FCoreStyle::Get().GetBrush("ToolTip.BrightBackground") )
		.TextMargin(FMargin(11.0f))
		[
			DocToolTip.ToSharedRef()
		];
}
void FMenuBuilder::BeginSection( FName InExtensionHook, const TAttribute< FText >& InHeadingText )
{
	check(CurrentSectionExtensionHook == NAME_None && !bSectionNeedsToBeApplied);

	ApplyHook(InExtensionHook, EExtensionHook::Before);
	
	// Do not actually apply the section header, because if this section is ended immediately
	// then nothing ever gets created, preventing empty sections from ever appearing
	bSectionNeedsToBeApplied = true;
	CurrentSectionExtensionHook = InExtensionHook;
	CurrentSectionHeadingText = InHeadingText.Get();

	// Do apply the section beginning if we are in developer "show me all the hooks" mode
	if (FMultiBoxSettings::DisplayMultiboxHooks.Get())
	{
		ApplySectionBeginning();
	}

	ApplyHook(InExtensionHook, EExtensionHook::First);
}
Пример #8
0
void SWidget::Construct(
	const TAttribute<FText> & InToolTipText ,
	const TSharedPtr<IToolTip> & InToolTip ,
	const TAttribute< TOptional<EMouseCursor::Type> > & InCursor ,
	const TAttribute<bool> & InEnabledState ,
	const TAttribute<EVisibility> & InVisibility,
	const TAttribute<TOptional<FSlateRenderTransform>>& InTransform,
	const TAttribute<FVector2D>& InTransformPivot,
	const FName& InTag,
	const bool InForceVolatile,
	const TArray<TSharedRef<ISlateMetaData>>& InMetaData
)
{
	if ( InToolTip.IsValid() )
	{
		// If someone specified a fancy widget tooltip, use it.
		ToolTip = InToolTip;
	}
	else if ( InToolTipText.IsSet() )
	{
		// If someone specified a text binding, make a tooltip out of it
		ToolTip = FSlateApplicationBase::Get().MakeToolTip(InToolTipText);
	}
	else if( !ToolTip.IsValid() || (ToolTip.IsValid() && ToolTip->IsEmpty()) )
	{	
		// We don't have a tooltip.
		ToolTip.Reset();
	}

	Cursor = InCursor;
	EnabledState = InEnabledState;
	Visibility = InVisibility;
	RenderTransform = InTransform;
	RenderTransformPivot = InTransformPivot;
	Tag = InTag;
	bForceVolatile = InForceVolatile;
	MetaData = InMetaData;
}
void FFoliageTypePaintingCustomization::GetHiddenPropertyVisibility(const TSharedPtr<IPropertyHandle>& PropertyHandle, bool bHideInReapplyTool, TAttribute<EVisibility>& OutVisibility) const
{
    TAttribute<EVisibility>::FGetter VisibilityGetter;
    FFoliageTypeCustomizationHelpers::BindHiddenPropertyVisibilityGetter(PropertyHandle, VisibilityGetter);

    if (bHideInReapplyTool)
    {
        // In addition to hiding it it behind the given property, only show this in the reapply tool
        OutVisibility = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateLambda([=]
        {
            if (!FoliageEditMode->UISettings.GetReapplyToolSelected() && VisibilityGetter.IsBound())
            {
                const EVisibility ReturnVal = VisibilityGetter.Execute();
                return ReturnVal;
            }
            return EVisibility::Collapsed;
        }));
    }
    else
    {
        OutVisibility.Bind(VisibilityGetter);
    }
}
Пример #10
0
static Sxmlattribute	__releaseAttr (TAttribute attr)					{ Sxmlattribute xml(attr); attr->removeReference(); return xml; }
Пример #11
0
EXP void		factoryFreeAttribute	(TFactory f, TAttribute attr)	{ attr->removeReference(); }
Пример #12
0
void FMainMenu::FillEditMenu( FMenuBuilder& MenuBuilder, const TSharedRef< FExtender > Extender, const TSharedPtr<FTabManager> TabManager )
{
	MenuBuilder.BeginSection("EditHistory", LOCTEXT("HistoryHeading", "History"));
	{
		struct Local
		{
			/** @return Returns a dynamic text string for Undo that contains the name of the action */
			static FText GetUndoLabelText()
			{
				return FText::Format(LOCTEXT("DynamicUndoLabel", "Undo {0}"), GUnrealEd->Trans->GetUndoContext().Title);
			}

			/** @return Returns a dynamic text string for Redo that contains the name of the action */
			static FText GetRedoLabelText()
			{
				return FText::Format(LOCTEXT("DynamicRedoLabel", "Redo {0}"), GUnrealEd->Trans->GetRedoContext().Title);
			}
		};

		// Undo
		TAttribute<FText> DynamicUndoLabel;
		DynamicUndoLabel.BindStatic(&Local::GetUndoLabelText);
		MenuBuilder.AddMenuEntry( FGenericCommands::Get().Undo, "Undo", DynamicUndoLabel); // TAttribute< FString >::Create( &Local::GetUndoLabelText ) );

		// Redo
		TAttribute< FText > DynamicRedoLabel;
		DynamicRedoLabel.BindStatic( &Local::GetRedoLabelText );
		MenuBuilder.AddMenuEntry(FGenericCommands::Get().Redo, "Redo", DynamicRedoLabel); // TAttribute< FString >::Create( &Local::GetRedoLabelText ) );

		// Show undo history
		MenuBuilder.AddMenuEntry(
			LOCTEXT("UndoHistoryTabTitle", "Undo History"),
			LOCTEXT("UndoHistoryTooltipText", "View the entire undo history."),
			FSlateIcon(FEditorStyle::GetStyleSetName(), "UndoHistory.TabIcon"),
			FUIAction(FExecuteAction::CreateStatic(&FUndoHistoryModule::ExecuteOpenUndoHistory))
			);
	}
	MenuBuilder.EndSection();

	MenuBuilder.BeginSection("EditLocalTabSpawners", LOCTEXT("ConfigurationHeading", "Configuration"));
	{
		if (GetDefault<UEditorExperimentalSettings>()->bToolbarCustomization)
		{
			FUIAction ToggleMultiBoxEditMode(
				FExecuteAction::CreateStatic(&FMultiBoxSettings::ToggleToolbarEditing),
				FCanExecuteAction(),
				FIsActionChecked::CreateStatic(&FMultiBoxSettings::IsInToolbarEditMode)
			);
		
			MenuBuilder.AddMenuEntry(
				LOCTEXT("EditToolbarsLabel", "Edit Toolbars"),
				LOCTEXT("EditToolbarsToolTip", "Allows customization of each toolbar"),
				FSlateIcon(),
				ToggleMultiBoxEditMode,
				NAME_None,
				EUserInterfaceActionType::ToggleButton
			);

			// Automatically populate tab spawners from TabManager
			if (TabManager.IsValid())
			{
				const IWorkspaceMenuStructure& MenuStructure = WorkspaceMenu::GetMenuStructure();
				TabManager->PopulateTabSpawnerMenu(MenuBuilder, MenuStructure.GetEditOptions());
			}
		}

		if (GetDefault<UEditorStyleSettings>()->bExpandConfigurationMenus)
		{
			MenuBuilder.AddSubMenu(
				LOCTEXT("EditorPreferencesSubMenuLabel", "Editor Preferences"),
				LOCTEXT("EditorPreferencesSubMenuToolTip", "Configure the behavior and features of this Editor"),
				FNewMenuDelegate::CreateStatic(&FSettingsMenu::MakeMenu, FName("Editor")),
				false,
				FSlateIcon(FEditorStyle::GetStyleSetName(), "EditorPreferences.TabIcon")
			);

			MenuBuilder.AddSubMenu(
				LOCTEXT("ProjectSettingsSubMenuLabel", "Project Settings"),
				LOCTEXT("ProjectSettingsSubMenuToolTip", "Change the settings of the currently loaded project"),
				FNewMenuDelegate::CreateStatic(&FSettingsMenu::MakeMenu, FName("Project")),
				false,
				FSlateIcon(FEditorStyle::GetStyleSetName(), "ProjectSettings.TabIcon")
			);
		}
		else
		{
#if !PLATFORM_MAC // Handled by app's menu in menu bar
			MenuBuilder.AddMenuEntry(
				LOCTEXT("EditorPreferencesMenuLabel", "Editor Preferences..."),
				LOCTEXT("EditorPreferencesMenuToolTip", "Configure the behavior and features of the Unreal Editor."),
				FSlateIcon(FEditorStyle::GetStyleSetName(), "EditorPreferences.TabIcon"),
				FUIAction(FExecuteAction::CreateStatic(&FSettingsMenu::OpenSettings, FName("Editor"), FName("General"), FName("Appearance")))
			);
#endif

			MenuBuilder.AddMenuEntry(
				LOCTEXT("ProjectSettingsMenuLabel", "Project Settings..."),
				LOCTEXT("ProjectSettingsMenuToolTip", "Change the settings of the currently loaded project."),
				FSlateIcon(FEditorStyle::GetStyleSetName(), "ProjectSettings.TabIcon"),
				FUIAction(FExecuteAction::CreateStatic(&FSettingsMenu::OpenSettings, FName("Project"), FName("Project"), FName("General")))
			);

			//@todo The tab system needs to be able to be extendable by plugins [9/3/2013 Justin.Sargent]
			if (IModularFeatures::Get().IsModularFeatureAvailable(EditorFeatures::PluginsEditor))
			{
				FGlobalTabmanager::Get()->PopulateTabSpawnerMenu(MenuBuilder, "PluginsEditor");
			}
		}
	}
	MenuBuilder.EndSection();
}
Пример #13
0
		static FText PassThroughAttribute( TAttribute< FString > InString )
		{
			return FText::FromString( InString.Get( TEXT("") ) );
		}
void FFoliageTypePaintingCustomization::ShowFoliagePropertiesForCategory(IDetailLayoutBuilder& DetailLayoutBuilder, const FName CategoryName, TMap<const FName, IDetailPropertyRow*>& OutDetailRowsByPropertyName)
{
    // Properties that have a ReapplyCondition should be disabled behind the specified property when in reapply mode
    static const FName ReapplyConditionKey("ReapplyCondition");

    // Properties with a HideBehind property specified should only be shown if that property is true, non-zero, or not empty
    static const FName HideBehindKey("HideBehind");

    IDetailCategoryBuilder& CategoryBuilder = DetailLayoutBuilder.EditCategory(CategoryName);
    TArray<TSharedRef<IPropertyHandle>> CategoryProperties;
    CategoryBuilder.GetDefaultProperties(CategoryProperties, true, true);

    // Determine whether each property should be shown and how
    for (auto& PropertyHandle : CategoryProperties)
    {
        bool bShowingProperty = false;
        if (UProperty* Property = PropertyHandle->GetProperty())
        {
            // Check to see if this property can be reapplied
            TSharedPtr<IPropertyHandle> ReapplyConditionPropertyHandle = DetailLayoutBuilder.GetProperty(*Property->GetMetaData(ReapplyConditionKey));
            if (ReapplyConditionPropertyHandle.IsValid() && ReapplyConditionPropertyHandle->IsValidHandle())
            {
                // Create a custom entry that allows explicit enabling/disabling of the property when reapplying
                TSharedPtr<IPropertyHandle> PropertyHandlePtr = PropertyHandle;
                OutDetailRowsByPropertyName.FindOrAdd(PropertyHandle->GetProperty()->GetFName()) =
                    &AddFoliageProperty(CategoryBuilder, PropertyHandlePtr, ReapplyConditionPropertyHandle, TAttribute<EVisibility>(), TAttribute<bool>());
            }
            else
            {
                TSharedPtr<IPropertyHandle> InvalidProperty;
                TSharedPtr<IPropertyHandle> PropertyHandlePtr = PropertyHandle;

                // Check to see if this property is hidden behind another
                TSharedPtr<IPropertyHandle> HiddenBehindPropertyHandle = DetailLayoutBuilder.GetProperty(*Property->GetMetaData(HideBehindKey));
                if (HiddenBehindPropertyHandle.IsValid() && HiddenBehindPropertyHandle->IsValidHandle())
                {
                    TAttribute<bool> IsEnabledAttribute;
                    ReapplyConditionPropertyHandle = DetailLayoutBuilder.GetProperty(*HiddenBehindPropertyHandle->GetProperty()->GetMetaData(ReapplyConditionKey));
                    if (ReapplyConditionPropertyHandle.IsValid() && ReapplyConditionPropertyHandle->IsValidHandle())
                    {
                        // If the property this is hidden behind has a reapply condition, disable this when the condition is false
                        IsEnabledAttribute = TAttribute<bool>::Create(TAttribute<bool>::FGetter::CreateSP(this, &FFoliageTypePaintingCustomization::IsReapplyPropertyEnabled, ReapplyConditionPropertyHandle));
                    }

                    TAttribute<EVisibility> VisibilityAttribute;
                    GetHiddenPropertyVisibility(HiddenBehindPropertyHandle, !IsEnabledAttribute.IsSet(), VisibilityAttribute);

                    OutDetailRowsByPropertyName.FindOrAdd(PropertyHandle->GetProperty()->GetFName()) =
                        &AddFoliageProperty(CategoryBuilder, PropertyHandlePtr, InvalidProperty, VisibilityAttribute, IsEnabledAttribute);
                }
                else
                {
                    // This property cannot be reapplied and isn't hidden behind anything, so show it whenever the reapply tool isn't active
                    OutDetailRowsByPropertyName.FindOrAdd(PropertyHandle->GetProperty()->GetFName()) =
                        &AddFoliageProperty(CategoryBuilder, PropertyHandlePtr, InvalidProperty,
                                            TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FFoliageTypePaintingCustomization::GetNonReapplyPropertyVisibility)),
                                            TAttribute<bool>());
                }
            }
        }
    }
}
void FDetailPropertyRow::MakeValueWidget( FDetailWidgetRow& Row, const TSharedPtr<FDetailWidgetRow> InCustomRow, bool bAddWidgetDecoration ) const
{
	EVerticalAlignment VerticalAlignment = VAlign_Center;
	EHorizontalAlignment HorizontalAlignment = HAlign_Left;

	TOptional<float> MinWidth;
	TOptional<float> MaxWidth;

	if( InCustomRow.IsValid() )
	{
		VerticalAlignment = InCustomRow->ValueWidget.VerticalAlignment;
		HorizontalAlignment = InCustomRow->ValueWidget.HorizontalAlignment;
	}

	TAttribute<bool> IsEnabledAttrib = CustomIsEnabledAttrib;
	if( HasEditCondition() )
	{
		IsEnabledAttrib.Bind( this, &FDetailPropertyRow::GetEnabledState );
	}

	TSharedRef<SHorizontalBox> ValueWidget = 
		SNew( SHorizontalBox )
		.IsEnabled( IsEnabledAttrib );

	if( InCustomRow.IsValid() )
	{
		MinWidth = InCustomRow->ValueWidget.MinWidth;
		MaxWidth = InCustomRow->ValueWidget.MaxWidth;

		ValueWidget->AddSlot()
		[
			InCustomRow->ValueWidget.Widget
		];
	}
	else
	{
		TSharedPtr<SPropertyValueWidget> PropertyValue;

		ValueWidget->AddSlot()
		.Padding( 0.0f, 0.0f, 4.0f, 0.0f )
		[
			SAssignNew( PropertyValue, SPropertyValueWidget, PropertyEditor, GetPropertyUtilities() )
			.ShowPropertyButtons( false ) // We handle this ourselves
		];

		MinWidth = PropertyValue->GetMinDesiredWidth();
		MaxWidth = PropertyValue->GetMaxDesiredWidth();
	}

	if(bAddWidgetDecoration)
	{
		if( bShowPropertyButtons )
		{
			TArray< TSharedRef<SWidget> > RequiredButtons;
			PropertyEditorHelpers::MakeRequiredPropertyButtons( PropertyEditor.ToSharedRef(), /*OUT*/RequiredButtons );

			for( int32 ButtonIndex = 0; ButtonIndex < RequiredButtons.Num(); ++ButtonIndex )
			{
				ValueWidget->AddSlot()
				.AutoWidth()
				.HAlign(HAlign_Left)
				.VAlign(VAlign_Center)
				.Padding(2.0f, 1.0f)
				[ 
					RequiredButtons[ButtonIndex]
				];
			}
		}

		if (PropertyHandle->HasMetaData(TEXT("ConfigHierarchyEditable")))
		{
			ValueWidget->AddSlot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			.HAlign(HAlign_Left)
			.Padding(0.0f, 0.0f, 4.0f, 0.0f)
			[
				PropertyCustomizationHelpers::MakeEditConfigHierarchyButton(FSimpleDelegate::CreateSP(PropertyEditor.ToSharedRef(), &FPropertyEditor::EditConfigHierarchy))
			];
		}

		if (!PropertyHandle->HasMetaData(TEXT("NoResetToDefault")))
		{
			ValueWidget->AddSlot()
			.Padding( 2.0f, 0.0f )
			.AutoWidth()
			.VAlign(VAlign_Center)
			.HAlign(HAlign_Left)
			[
				SNew( SResetToDefaultPropertyEditor, PropertyEditor.ToSharedRef() )
				.IsEnabled( IsEnabledAttrib )
				.CustomResetToDefault(CustomResetToDefault)
			];
		}
	}

	Row.ValueContent()
	.HAlign( HorizontalAlignment )
	.VAlign( VerticalAlignment )	
	.MinDesiredWidth( MinWidth )
	.MaxDesiredWidth( MaxWidth )
	[
		ValueWidget
	];
}
void FDetailPropertyRow::MakeNameOrKeyWidget( FDetailWidgetRow& Row, const TSharedPtr<FDetailWidgetRow> InCustomRow ) const
{
	EVerticalAlignment VerticalAlignment = VAlign_Center;
	EHorizontalAlignment HorizontalAlignment = HAlign_Fill;

	bool bHasKeyNode = PropertyNode->GetPropertyKeyNode().IsValid();

	if( !bHasKeyNode && InCustomRow.IsValid() )
	{
		VerticalAlignment = InCustomRow->NameWidget.VerticalAlignment;
		HorizontalAlignment = InCustomRow->NameWidget.HorizontalAlignment;
	}

	TAttribute<bool> IsEnabledAttrib = CustomIsEnabledAttrib;

	TSharedRef<SHorizontalBox> NameHorizontalBox = SNew( SHorizontalBox );
	
	if( HasEditCondition() )
	{
		IsEnabledAttrib.Bind( this, &FDetailPropertyRow::GetEnabledState );

		NameHorizontalBox->AddSlot()
		.AutoWidth()
		.Padding( 0.0f, 0.0f )
		.VAlign(VAlign_Center)
		[
			SNew( SEditConditionWidget, PropertyEditor )
			.CustomEditCondition( CustomEditCondition.IsValid() ? *CustomEditCondition : FCustomEditCondition() )
		];
	}

	TSharedPtr<SWidget> NameWidget;

	// Key nodes will take precedence over custom rows.
	if (bHasKeyNode)
	{
		const TSharedRef<IPropertyUtilities> PropertyUtilities = ParentCategory.Pin()->GetParentLayoutImpl().GetPropertyUtilities();

		NameWidget =
			SNew(SPropertyValueWidget, PropertyKeyEditor, PropertyUtilities)
			.IsEnabled(IsEnabledAttrib)
			.ShowPropertyButtons(false);
	}
	else if(InCustomRow.IsValid())
	{
		NameWidget = 
			SNew( SBox )
			.IsEnabled( IsEnabledAttrib )
			[
				InCustomRow->NameWidget.Widget
			];
	}
	else
	{
		NameWidget = 
			SNew( SPropertyNameWidget, PropertyEditor )
			.IsEnabled( IsEnabledAttrib )
			.DisplayResetToDefault( false );
	}

	SHorizontalBox::FSlot& Slot = NameHorizontalBox->AddSlot()
	[
		NameWidget.ToSharedRef()
	];

	if (bHasKeyNode)
	{
		Slot.Padding(0.0f, 0.0f, 20.0f, 0.0f);
	}
	else
	{
		Slot.AutoWidth();
	}

	Row.NameContent()
	.HAlign( HorizontalAlignment )
	.VAlign( VerticalAlignment )
	[
		NameHorizontalBox
	];
}
void FPaperTileMapDetailsCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailLayout)
{
    const TArray< TWeakObjectPtr<UObject> >& SelectedObjects = DetailLayout.GetDetailsView().GetSelectedObjects();
    MyDetailLayout = &DetailLayout;

    FNotifyHook* NotifyHook = DetailLayout.GetPropertyUtilities()->GetNotifyHook();

    bool bEditingActor = false;

    UPaperTileMap* TileMap = nullptr;
    UPaperTileMapComponent* TileComponent = nullptr;
    for (int32 ObjectIndex = 0; ObjectIndex < SelectedObjects.Num(); ++ObjectIndex)
    {
        UObject* TestObject = SelectedObjects[ObjectIndex].Get();
        if (AActor* CurrentActor = Cast<AActor>(TestObject))
        {
            if (UPaperTileMapComponent* CurrentComponent = CurrentActor->FindComponentByClass<UPaperTileMapComponent>())
            {
                bEditingActor = true;
                TileComponent = CurrentComponent;
                TileMap = CurrentComponent->TileMap;
                break;
            }
        }
        else if (UPaperTileMapComponent* TestComponent = Cast<UPaperTileMapComponent>(TestObject))
        {
            TileComponent = TestComponent;
            TileMap = TestComponent->TileMap;
            break;
        }
        else if (UPaperTileMap* TestTileMap = Cast<UPaperTileMap>(TestObject))
        {
            TileMap = TestTileMap;
            break;
        }
    }
    TileMapPtr = TileMap;
    TileMapComponentPtr = TileComponent;

    IDetailCategoryBuilder& TileMapCategory = DetailLayout.EditCategory("Tile Map");

    TAttribute<EVisibility> InternalInstanceVis = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FPaperTileMapDetailsCustomization::GetVisibilityForInstancedOnlyProperties));

    if (TileComponent != nullptr)
    {
        TileMapCategory
        .AddCustomRow(LOCTEXT( "TileMapInstancingControlsSearchText", "Edit New Promote Asset"))
        [
            SNew(SVerticalBox)
            + SVerticalBox::Slot()
            .Padding(0.0f, 2.0f, 0.0f, 0.0f)
            .FillHeight(1.0f)
            .VAlign(VAlign_Center)
            [
                SNew(SHorizontalBox)

                // Edit button
                +SHorizontalBox::Slot()
                .AutoWidth()
                .Padding( 2.0f, 0.0f )
                .VAlign(VAlign_Center)
                .HAlign(HAlign_Left)
                [
                    SNew(SButton)
                    .VAlign(VAlign_Center)
                    .OnClicked(this, &FPaperTileMapDetailsCustomization::EnterTileMapEditingMode)
                    .Visibility(this, &FPaperTileMapDetailsCustomization::GetNonEditModeVisibility)
                    .Text( LOCTEXT("EditAsset", "Edit") )
                    .ToolTipText( LOCTEXT("EditAssetToolTip", "Edit this tile map") )
                ]

                // Create new tile map button
                +SHorizontalBox::Slot()
                .AutoWidth()
                .Padding( 2.0f, 0.0f )
                .VAlign(VAlign_Center)
                .HAlign(HAlign_Left)
                [
                    SNew(SButton)
                    .VAlign(VAlign_Center)
                    .OnClicked(this, &FPaperTileMapDetailsCustomization::OnNewButtonClicked)
                    .Visibility(this, &FPaperTileMapDetailsCustomization::GetNewButtonVisiblity)
                    .Text(LOCTEXT("CreateNewInstancedMap", "New"))
                    .ToolTipText( LOCTEXT("CreateNewInstancedMapToolTip", "Create a new tile map") )
                ]

                // Promote to asset button
                +SHorizontalBox::Slot()
                .AutoWidth()
                .Padding( 2.0f, 0.0f )
                .VAlign(VAlign_Center)
                .HAlign(HAlign_Left)
                [
                    SNew(SButton)
                    .VAlign(VAlign_Center)
                    .OnClicked(this, &FPaperTileMapDetailsCustomization::OnPromoteButtonClicked)
                    .Visibility(this, &FPaperTileMapDetailsCustomization::GetVisibilityForInstancedOnlyProperties)
                    .Text(LOCTEXT("PromoteToAsset", "Promote to asset"))
                    .ToolTipText(LOCTEXT("PromoteToAssetToolTip", "Save this tile map as a reusable asset"))
                ]
            ]
        ];

        TileMapCategory.AddProperty(GET_MEMBER_NAME_CHECKED(UPaperTileMapComponent, TileMap));
    }

    // Add the layer browser
    if (TileMap != nullptr)
    {
        TAttribute<EVisibility> LayerBrowserVis;
        LayerBrowserVis.Set(EVisibility::Visible);
        if (TileComponent != nullptr)
        {
            LayerBrowserVis = InternalInstanceVis;
        }

        FText TileLayerListText = LOCTEXT("TileLayerList", "Tile layer list");
        TileMapCategory.AddCustomRow(TileLayerListText)
        .Visibility(LayerBrowserVis)
        [
            SNew(SVerticalBox)
            +SVerticalBox::Slot()
            .AutoHeight()
            [
                SNew(STextBlock)
                .Font(DetailLayout.GetDetailFont())
                .Text(TileLayerListText)
            ]
            +SVerticalBox::Slot()
            [
                SNew(STileLayerList, TileMap, NotifyHook)
            ]
        ];
    }

    // Add all of the properties from the inline tilemap
    if ((TileComponent != nullptr) && (TileComponent->OwnsTileMap()))
    {
        TArray<UObject*> ListOfTileMaps;
        ListOfTileMaps.Add(TileMap);

        for (TFieldIterator<UProperty> PropIt(UPaperTileMap::StaticClass()); PropIt; ++PropIt)
        {
            UProperty* TestProperty = *PropIt;

            if (TestProperty->HasAnyPropertyFlags(CPF_Edit))
            {
                FName CategoryName(*TestProperty->GetMetaData(TEXT("Category")));
                IDetailCategoryBuilder& Category = DetailLayout.EditCategory(CategoryName);

                if (IDetailPropertyRow* ExternalRow = Category.AddExternalProperty(ListOfTileMaps, TestProperty->GetFName()))
                {
                    ExternalRow->Visibility(InternalInstanceVis);
                }
            }
        }
    }

    // Make sure the setup category is near the top
    DetailLayout.EditCategory("Setup");
}
Пример #18
0
		static FString GetPIENotifyText(TAttribute<FGraphAppearanceInfo> Appearance, FString DefaultText)
		{
			FString OverrideText = Appearance.Get().PIENotifyText;
			return OverrideText.Len() ? OverrideText : DefaultText;
		}
void SAssetSearchBox::SetText(const TAttribute< FText >& InNewText)
{
    InputText->SetText(InNewText);
    PreCommittedText = InNewText.Get();
}
/**
 * Builds this MultiBlock widget up from the MultiBlock associated with it
 */
void SToolBarButtonBlock::BuildMultiBlockWidget(const ISlateStyle* StyleSet, const FName& StyleName)
{
	struct Local
	{
		/** Appends the key binding to the end of the provided ToolTip */
		static FText AppendKeyBindingToToolTip( const TAttribute<FText> ToolTip, TWeakPtr< const FUICommandInfo> Command )
		{
			TSharedPtr<const FUICommandInfo> CommandPtr = Command.Pin();

			if( CommandPtr.IsValid() && CommandPtr->GetActiveChord()->IsValidChord() )
			{
				FFormatNamedArguments Args;
				Args.Add( TEXT("ToolTipDescription"), ToolTip.Get() );
				Args.Add( TEXT("Keybinding"), CommandPtr->GetInputText() );
				return FText::Format( NSLOCTEXT("ToolBar", "ToolTip + Keybinding", "{ToolTipDescription} ({Keybinding})"), Args );
			}
			else
			{
				return ToolTip.Get();
			}
		}
	};


	TSharedRef< const FMultiBox > MultiBox( OwnerMultiBoxWidget.Pin()->GetMultiBox() );
	
	TSharedRef< const FToolBarButtonBlock > ToolBarButtonBlock = StaticCastSharedRef< const FToolBarButtonBlock >( MultiBlock.ToSharedRef() );

	// Allow the block to override the action's label and tool tip string, if desired
	TAttribute<FText> ActualLabel;
	if (ToolBarButtonBlock->LabelOverride.IsSet())
	{
		ActualLabel = ToolBarButtonBlock->LabelOverride;
	}
	else
	{
		ActualLabel = ToolBarButtonBlock->GetAction()->GetLabel();
	}

	// Add this widget to the search list of the multibox
	if (MultiBlock->GetSearchable())
		OwnerMultiBoxWidget.Pin()->AddSearchElement(this->AsWidget(), ActualLabel.Get());

	TAttribute<FText> ActualToolTip;
	if (ToolBarButtonBlock->ToolTipOverride.IsSet())
	{
		ActualToolTip = ToolBarButtonBlock->ToolTipOverride;
	}
	else
	{
		ActualToolTip = ToolBarButtonBlock->GetAction()->GetDescription();
	}

	// If a key is bound to the command, append it to the tooltip text.
	TWeakPtr<const FUICommandInfo> Action = ToolBarButtonBlock->GetAction();
	ActualToolTip = TAttribute< FText >::Create( TAttribute< FText >::FGetter::CreateStatic( &Local::AppendKeyBindingToToolTip, ActualToolTip, Action ) );
	
	// If we were supplied an image than go ahead and use that, otherwise we use a null widget
	TSharedRef< SWidget > IconWidget =
		SNew( SImage )
		.Visibility( this, &SToolBarButtonBlock::GetIconVisibility, false )	
		.Image( this, &SToolBarButtonBlock::GetIconBrush );
	TSharedRef< SWidget > SmallIconWidget =
		SNew( SImage )
		.Visibility( this, &SToolBarButtonBlock::GetIconVisibility, true )	
		.Image( this, &SToolBarButtonBlock::GetSmallIconBrush );

	// Create the content for our button
	TSharedRef< SWidget > ButtonContent =

		SNew(SHorizontalBox)
		.AddMetaData<FTagMetaData>(FTagMetaData(TutorialHighlightName))

		+ SHorizontalBox::Slot()
		.FillWidth(1)
		.VAlign(VAlign_Center)
		[
			SNew( SVerticalBox )

			// Icon image
			+ SVerticalBox::Slot()
			.AutoHeight()
			.HAlign( HAlign_Center )	// Center the icon horizontally, so that large labels don't stretch out the artwork
			[
				IconWidget
			]
			+ SVerticalBox::Slot().AutoHeight()
			.HAlign( HAlign_Center )
			[
				SmallIconWidget
			]

			// Label text
			+ SVerticalBox::Slot().AutoHeight()
			.HAlign( HAlign_Center )	// Center the label text horizontally
			[
				SNew( STextBlock )
					.Visibility( LabelVisibility )
					.Text( ActualLabel )
					.TextStyle( StyleSet, ISlateStyle::Join( StyleName, ".Label" ) )	// Smaller font for tool tip labels
					.ShadowOffset( FVector2D::UnitVector )
			]
		];

	EMultiBlockLocation::Type BlockLocation = GetMultiBlockLocation();
	
	// What type of UI should we create for this block?
	EUserInterfaceActionType::Type UserInterfaceType = ToolBarButtonBlock->UserInterfaceActionType;
	if ( Action.IsValid() )
	{
		// If we have a UICommand, then this is specified in the command.
		UserInterfaceType = Action.Pin()->GetUserInterfaceType();
	}
	
	if( UserInterfaceType == EUserInterfaceActionType::Button )
	{
		FName BlockStyle = EMultiBlockLocation::ToName(ISlateStyle::Join( StyleName, ".Button" ), BlockLocation);
		ChildSlot
		[
			// Create a button
			SNew( SButton )
				.ContentPadding(0)

				// Use the tool bar item style for this button
				.ButtonStyle( StyleSet, BlockStyle )

				.ForegroundColor( FSlateColor::UseForeground() )

				.IsFocusable(bIsFocusable)
				[
					ButtonContent
				]

				// Bind the button's "on clicked" event to our object's method for this
				.OnClicked( this, &SToolBarButtonBlock::OnClicked )

				// Pass along the block's tool-tip string
				.ToolTip( FMultiBoxSettings::ToolTipConstructor.Execute( ActualToolTip, nullptr, Action.Pin() ) )
		];
	}
	else if( ensure( UserInterfaceType == EUserInterfaceActionType::ToggleButton || UserInterfaceType == EUserInterfaceActionType::RadioButton ) )
	{
		FName BlockStyle = EMultiBlockLocation::ToName(ISlateStyle::Join( StyleName, ".ToggleButton" ), BlockLocation);
		FName CheckboxStyle = ISlateStyle::Join( StyleName, ".SToolBarButtonBlock.CheckBox.Padding" );

		ChildSlot
		[
			// Create a check box
			SNew( SCheckBox )

				// Use the tool bar style for this check box
				.Style( StyleSet, BlockStyle )

				// User will have set the focusable attribute for the block, honor it
				.IsFocusable( bIsFocusable )

				// Pass along the block's tool-tip string
				.ToolTip( FMultiBoxSettings::ToolTipConstructor.Execute( ActualToolTip, nullptr, Action.Pin() ) )
				[
					ButtonContent
				]

				// Bind the button's "on checked" event to our object's method for this
				.OnCheckStateChanged( this, &SToolBarButtonBlock::OnCheckStateChanged )

				// Bind the check box's "checked" state to our user interface action
				.IsChecked( this, &SToolBarButtonBlock::OnIsChecked )

				.Padding( StyleSet->GetMargin(CheckboxStyle) )
		];
	}
	
	ChildSlot.Padding(StyleSet->GetMargin(ISlateStyle::Join( StyleName, ".SToolBarButtonBlock.Padding" )));

	// Bind our widget's enabled state to whether or not our action can execute
	SetEnabled( TAttribute< bool >( this, &SToolBarButtonBlock::IsEnabled ) );

	// Bind our widget's visible state to whether or not the button should be visible
	SetVisibility( TAttribute<EVisibility>(this, &SToolBarButtonBlock::GetBlockVisibility) );
}
Пример #21
0
void FMainMenu::FillEditMenu( FMenuBuilder& MenuBuilder, const TSharedRef< FExtender > Extender, const TSharedPtr<FTabManager> TabManager )
{
	MenuBuilder.BeginSection("EditHistory", LOCTEXT("HistoryHeading", "History"));
	{
		struct Local
		{
			/** @return Returns a dynamic text string for Undo that contains the name of the action */
			static FText GetUndoLabelText()
			{
				return FText::Format(LOCTEXT("DynamicUndoLabel", "Undo {0}"), GUnrealEd->Trans->GetUndoContext().Title);
			}

			/** @return Returns a dynamic text string for Redo that contains the name of the action */
			static FText GetRedoLabelText()
			{
				return FText::Format(LOCTEXT("DynamicRedoLabel", "Redo {0}"), GUnrealEd->Trans->GetRedoContext().Title);
			}
		};

		// Undo
		TAttribute<FText> DynamicUndoLabel;
		DynamicUndoLabel.BindStatic(&Local::GetUndoLabelText);
		MenuBuilder.AddMenuEntry( FGenericCommands::Get().Undo, "Undo", DynamicUndoLabel); // TAttribute< FString >::Create( &Local::GetUndoLabelText ) );

		// Redo
		TAttribute< FText > DynamicRedoLabel;
		DynamicRedoLabel.BindStatic( &Local::GetRedoLabelText );
		MenuBuilder.AddMenuEntry(FGenericCommands::Get().Redo, "Redo", DynamicRedoLabel); // TAttribute< FString >::Create( &Local::GetRedoLabelText ) );
	}
	MenuBuilder.EndSection();

	MenuBuilder.BeginSection("EditLocalTabSpawners", LOCTEXT("ConfigurationHeading", "Configuration"));
	{
		if (GetDefault<UEditorExperimentalSettings>()->bToolbarCustomization)
		{
			FUIAction ToggleMultiBoxEditMode(
				FExecuteAction::CreateStatic(&FMultiBoxSettings::ToggleToolbarEditing),
				FCanExecuteAction(),
				FIsActionChecked::CreateStatic(&FMultiBoxSettings::IsInToolbarEditMode)
			);
		
			MenuBuilder.AddMenuEntry(
				LOCTEXT("EditToolbarsLabel", "Edit Toolbars"),
				LOCTEXT("EditToolbarsToolTip", "Allows customization of each toolbar"),
				FSlateIcon(),
				ToggleMultiBoxEditMode,
				NAME_None,
				EUserInterfaceActionType::ToggleButton
			);

			// Automatically populate tab spawners from TabManager
			if (TabManager.IsValid())
			{
				const IWorkspaceMenuStructure& MenuStructure = WorkspaceMenu::GetMenuStructure();
				TabManager->PopulateTabSpawnerMenu(MenuBuilder, MenuStructure.GetEditOptions());
			}
		}

		if (GetDefault<UEditorStyleSettings>()->bExpandConfigurationMenus)
		{
			MenuBuilder.AddSubMenu(
				LOCTEXT("EditorPreferencesSubMenuLabel", "Editor Preferences"),
				LOCTEXT("EditorPreferencesSubMenuToolTip", "Configure the behavior and features of this Editor"),
				FNewMenuDelegate::CreateStatic(&FSettingsMenu::MakeMenu, FName("Editor"))
			);

			MenuBuilder.AddSubMenu(
				LOCTEXT("ProjectSettingsSubMenuLabel", "Project Settings"),
				LOCTEXT("ProjectSettingsSubMenuToolTip", "Change the settings of the currently loaded project"),
				FNewMenuDelegate::CreateStatic(&FSettingsMenu::MakeMenu, FName("Project"))
			);
		}
		else
		{
			MenuBuilder.AddMenuEntry(
				LOCTEXT("EditorPreferencesMenuLabel", "Editor Preferences..."),
				LOCTEXT("EditorPreferencesMenuToolTip", "Configure the behavior and features of this Editor"),
				FSlateIcon(),
				FUIAction(FExecuteAction::CreateStatic(&FSettingsMenu::OpenSettings, FName("Editor"), FName("General"), FName("Appearance")))
			);

			MenuBuilder.AddMenuEntry(
				LOCTEXT("ProjectSettingsMenuLabel", "Project Settings..."),
				LOCTEXT("ProjectSettingsMenuToolTip", "Change the settings of the currently loaded project"),
				FSlateIcon(),
				FUIAction(FExecuteAction::CreateStatic(&FSettingsMenu::OpenSettings, FName("Project"), FName("Game"), FName("General")))
			);
		}
	}
	MenuBuilder.EndSection();
}
void SMessageLogMessageListRow::CreateMessage(const TSharedRef<SHorizontalBox>& InHorzBox, const TSharedRef<IMessageToken>& InMessageToken, float Padding)
{
	TSharedPtr<SWidget> RowContent;
	FName IconBrushName;

	TAttribute<EVisibility> TokenContentVisbility;
	
	switch (InMessageToken->GetType())
	{
	case EMessageToken::Image:
	{
		const TSharedRef<FImageToken> ImageToken = StaticCastSharedRef<FImageToken>(InMessageToken);

		if (ImageToken->GetImageName() != NAME_None)
		{
			if (InMessageToken->GetOnMessageTokenActivated().IsBound())
			{
				RowContent = SNew(SButton)
					.OnClicked(this, &SMessageLogMessageListRow::HandleTokenButtonClicked, InMessageToken)
					.Content()
					[
						SNew(SImage)
						.Image(FEditorStyle::GetBrush(ImageToken->GetImageName()))
					];
			}
			else
			{
				RowContent = SNew(SImage)
					.Image(FEditorStyle::GetBrush(ImageToken->GetImageName()));
			}
		}
	}
		break;

	case EMessageToken::Object:
	{
		const TSharedRef<FUObjectToken> UObjectToken = StaticCastSharedRef<FUObjectToken>(InMessageToken);

		IconBrushName = FName("PropertyWindow.Button_Browse");

		UObject* Object = nullptr;

		// Due to blueprint reconstruction, we can't directly use the Object as it will get trashed during the blueprint reconstruction and the message token will no longer point to the right UObject.
		// Instead we will retrieve the object from the name which should always be good.
		if (UObjectToken->GetObject().IsValid())
		{
			if (!UObjectToken->ToText().ToString().Equals(UObjectToken->GetObject().Get()->GetName()))
			{
				Object = FindObject<UObject>(nullptr, *UObjectToken->GetOriginalObjectPathName());
			}
			else
			{
				Object = const_cast<UObject*>(UObjectToken->GetObject().Get());
			}
		}
		else
		{
			// We have no object (probably because is now stale), try finding the original object linked to this message token to see if it still exist
			Object = FindObject<UObject>(nullptr, *UObjectToken->GetOriginalObjectPathName());
		}

		RowContent = CreateHyperlink(InMessageToken, FUObjectToken::DefaultOnGetObjectDisplayName().IsBound()
			? FUObjectToken::DefaultOnGetObjectDisplayName().Execute(Object, true)
			: UObjectToken->ToText());
	}
		break;

	case EMessageToken::URL:
	{
		const TSharedRef<FURLToken> URLToken = StaticCastSharedRef<FURLToken>(InMessageToken);

		IconBrushName = FName("MessageLog.Url");
		RowContent = CreateHyperlink(InMessageToken, FText::FromString(URLToken->GetURL()));
	}
		break;
	case EMessageToken::EdGraph:
	{
		IconBrushName = FName("PropertyWindow.Button_Browse");
		RowContent = CreateHyperlink(InMessageToken, InMessageToken->ToText());
	}
	break;
	case EMessageToken::Action:
	{
		const TSharedRef<FActionToken> ActionToken = StaticCastSharedRef<FActionToken>(InMessageToken);

		IconBrushName = FName("MessageLog.Action");
		RowContent = SNew(SHyperlink)
			.Text(InMessageToken->ToText())
			.ToolTipText(ActionToken->GetActionDescription())
			.TextStyle(FEditorStyle::Get(), "MessageLog")
			.OnNavigate(this, &SMessageLogMessageListRow::HandleActionHyperlinkNavigate, ActionToken);

		TokenContentVisbility = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateRaw(this, &SMessageLogMessageListRow::GetActionLinkVisibility, ActionToken));
	}
		break;

	case EMessageToken::AssetName:
	{
		const TSharedRef<FAssetNameToken> AssetNameToken = StaticCastSharedRef<FAssetNameToken>(InMessageToken);

		IconBrushName = FName("PropertyWindow.Button_Browse");
		RowContent = CreateHyperlink(InMessageToken, AssetNameToken->ToText());
	}
		break;

#if WITH_EDITOR
	case EMessageToken::Documentation:
	{
		const TSharedRef<FDocumentationToken> DocumentationToken = StaticCastSharedRef<FDocumentationToken>(InMessageToken);

		IconBrushName = FName("MessageLog.Docs");
		RowContent = SNew(SHyperlink)
			.Text(LOCTEXT("DocsLabel", "Docs"))
			.ToolTip(IDocumentation::Get()->CreateToolTip(
			LOCTEXT("DocumentationTokenToolTip", "Click to open documentation"),
			NULL,
			DocumentationToken->GetPreviewExcerptLink(),
			DocumentationToken->GetPreviewExcerptName())
			)
			.TextStyle(FEditorStyle::Get(), "MessageLog")
			.OnNavigate(this, &SMessageLogMessageListRow::HandleDocsHyperlinkNavigate, DocumentationToken->GetDocumentationLink());
	}
		break;

	case EMessageToken::Text:
	{
		if (InMessageToken->GetOnMessageTokenActivated().IsBound())
		{
			RowContent = CreateHyperlink(InMessageToken, InMessageToken->ToText());
		}
		else
		{
			FString MessageString = InMessageToken->ToText().ToString();

			// ^((?:[\w]\:|\\)(?:(?:\\[a-z_\-\s0-9\.]+)+)\.(?:cpp|h))\((\d+)\)
			// https://regex101.com/r/vV4cV7/1
			FRegexPattern FileAndLinePattern(TEXT("^((?:[\\w]\\:|\\\\)(?:(?:\\\\[a-z_\\-\\s0-9\\.]+)+)\\.(?:cpp|h))\\((\\d+)\\)"));
			FRegexMatcher FileAndLineRegexMatcher(FileAndLinePattern, MessageString);

			TSharedRef<SWidget> SourceLink = SNullWidget::NullWidget;

			if ( FileAndLineRegexMatcher.FindNext() )
			{
				FString FileName = FileAndLineRegexMatcher.GetCaptureGroup(1);
				int32 LineNumber = FCString::Atoi(*FileAndLineRegexMatcher.GetCaptureGroup(2));

				// Remove the hyperlink from the message, since we're splitting it into its own string.
				MessageString = MessageString.RightChop(FileAndLineRegexMatcher.GetMatchEnding());

				SourceLink = SNew(SHyperlink)
					.Style(FEditorStyle::Get(), "Common.GotoNativeCodeHyperlink")
					.TextStyle(FEditorStyle::Get(), "MessageLog")
					.OnNavigate_Lambda([=] { FSlateApplication::Get().GotoLineInSource(FileName, LineNumber); })
					.Text(FText::FromString(FileAndLineRegexMatcher.GetCaptureGroup(0)));
			}

			RowContent = SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(0)
			[
				SourceLink
			]

			+ SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(0)
			[
				SNew(STextBlock)
				.ColorAndOpacity(FSlateColor::UseSubduedForeground())
				.Text(FText::FromString(MessageString))
			];
		}
	}
		break;

	case EMessageToken::Tutorial:
	{
		const TSharedRef<FTutorialToken> TutorialToken = StaticCastSharedRef<FTutorialToken>(InMessageToken);

		IconBrushName = FName("MessageLog.Tutorial");
		RowContent = SNew(SHyperlink)
			.Text(LOCTEXT("TutorialLabel", "Tutorial"))
			.ToolTipText(LOCTEXT("TutorialTokenToolTip", "Click to open tutorial"))
			.TextStyle(FEditorStyle::Get(), "MessageLog")
			.OnNavigate(this, &SMessageLogMessageListRow::HandleTutorialHyperlinkNavigate, TutorialToken->GetTutorialAssetName());
	}
		break;
#endif
	}

	if (RowContent.IsValid())
	{
		InHorzBox->AddSlot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			.Padding(Padding, 0.0f, 0.0f, 0.0f)
			[
				SNew(SHorizontalBox)
				.Visibility(TokenContentVisbility.IsBound() ? TokenContentVisbility : EVisibility::Visible)

				+ SHorizontalBox::Slot()
				.AutoWidth()
				.VAlign(VAlign_Center)
				[
					(IconBrushName == NAME_None)
					? SNullWidget::NullWidget
					: static_cast<TSharedRef<SWidget>>(SNew(SImage)
					.ColorAndOpacity(FSlateColor::UseForeground())
					.Image(FEditorStyle::GetBrush(IconBrushName)))
				]

				+ SHorizontalBox::Slot()
					.AutoWidth()
					.VAlign(VAlign_Center)
					.Padding(2.0f, 0.0f, 0.0f, 0.0f)
					[
						RowContent.ToSharedRef()
					]
			];
	}
}