// Copyright Epic Games, Inc. All Rights Reserved. #include "Components/Border.h" #include "Slate/SlateBrushAsset.h" #include "Materials/MaterialInterface.h" #include "Engine/Texture2D.h" #include "Materials/MaterialInstanceDynamic.h" #include "Widgets/SNullWidget.h" #include "Widgets/DeclarativeSyntaxSupport.h" #include "Widgets/Layout/SBorder.h" #include "Components/BorderSlot.h" #include "ObjectEditorUtils.h" #define LOCTEXT_NAMESPACE "UMG" ///////////////////////////////////////////////////// // UBorder UBorder::UBorder(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { bIsVariable = false; PRAGMA_DISABLE_DEPRECATION_WARNINGS ContentColorAndOpacity = FLinearColor::White; BrushColor = FLinearColor::White; Padding = FMargin(4, 2); HorizontalAlignment = HAlign_Fill; VerticalAlignment = VAlign_Fill; DesiredSizeScale = FVector2D(1, 1); bShowEffectWhenDisabled = true; PRAGMA_ENABLE_DEPRECATION_WARNINGS } void UBorder::ReleaseSlateResources(bool bReleaseChildren) { Super::ReleaseSlateResources(bReleaseChildren); MyBorder.Reset(); } TSharedRef UBorder::RebuildWidget() { MyBorder = SNew(SBorder) .FlipForRightToLeftFlowDirection(bFlipForRightToLeftFlowDirection); if ( GetChildrenCount() > 0 ) { Cast(GetContentSlot())->BuildSlot(MyBorder.ToSharedRef()); } return MyBorder.ToSharedRef(); } void UBorder::SynchronizeProperties() { Super::SynchronizeProperties(); PRAGMA_DISABLE_DEPRECATION_WARNINGS TAttribute ContentColorAndOpacityBinding = PROPERTY_BINDING(FLinearColor, ContentColorAndOpacity); TAttribute BrushColorBinding = OPTIONAL_BINDING_CONVERT(FLinearColor, BrushColor, FSlateColor, ConvertLinearColorToSlateColor); TAttribute ImageBinding = OPTIONAL_BINDING_CONVERT(FSlateBrush, Background, const FSlateBrush*, ConvertImage); MyBorder->SetPadding(Padding); MyBorder->SetBorderBackgroundColor(BrushColorBinding); MyBorder->SetColorAndOpacity(ContentColorAndOpacityBinding); MyBorder->SetBorderImage(ImageBinding); MyBorder->SetDesiredSizeScale(DesiredSizeScale); MyBorder->SetShowEffectWhenDisabled(bShowEffectWhenDisabled != 0); PRAGMA_ENABLE_DEPRECATION_WARNINGS MyBorder->SetOnMouseButtonDown(BIND_UOBJECT_DELEGATE(FPointerEventHandler, HandleMouseButtonDown)); MyBorder->SetOnMouseButtonUp(BIND_UOBJECT_DELEGATE(FPointerEventHandler, HandleMouseButtonUp)); MyBorder->SetOnMouseMove(BIND_UOBJECT_DELEGATE(FPointerEventHandler, HandleMouseMove)); MyBorder->SetOnMouseDoubleClick(BIND_UOBJECT_DELEGATE(FPointerEventHandler, HandleMouseDoubleClick)); } UClass* UBorder::GetSlotClass() const { return UBorderSlot::StaticClass(); } void UBorder::OnSlotAdded(UPanelSlot* InSlot) { PRAGMA_DISABLE_DEPRECATION_WARNINGS // Copy the content properties into the new slot so that it matches what has been setup // so far by the user. UBorderSlot* BorderSlot = CastChecked(InSlot); BorderSlot->Padding = Padding; BorderSlot->HorizontalAlignment = HorizontalAlignment; BorderSlot->VerticalAlignment = VerticalAlignment; PRAGMA_ENABLE_DEPRECATION_WARNINGS // Add the child to the live slot if it already exists if ( MyBorder.IsValid() ) { // Construct the underlying slot. BorderSlot->BuildSlot(MyBorder.ToSharedRef()); } } void UBorder::OnSlotRemoved(UPanelSlot* InSlot) { // Remove the widget from the live slot if it exists. if ( MyBorder.IsValid() ) { MyBorder->SetContent(SNullWidget::NullWidget); } } PRAGMA_DISABLE_DEPRECATION_WARNINGS FLinearColor UBorder::GetContentColorAndOpacity() const { if (MyBorder.IsValid()) { return MyBorder->GetColorAndOpacity(); } return ContentColorAndOpacity; } void UBorder::SetContentColorAndOpacity(FLinearColor Color) { ContentColorAndOpacity = Color; if ( MyBorder.IsValid() ) { MyBorder->SetColorAndOpacity(Color); } } FMargin UBorder::GetPadding() const { return Padding; } void UBorder::SetPadding(FMargin InPadding) { Padding = InPadding; if ( MyBorder.IsValid() ) { MyBorder->SetPadding(InPadding); } } EHorizontalAlignment UBorder::GetHorizontalAlignment() const { return HorizontalAlignment; } void UBorder::SetHorizontalAlignment(EHorizontalAlignment InHorizontalAlignment) { HorizontalAlignment = InHorizontalAlignment; if (MyBorder.IsValid()) { MyBorder->SetHAlign(InHorizontalAlignment); } } EVerticalAlignment UBorder::GetVerticalAlignment() const { return VerticalAlignment; } void UBorder::SetVerticalAlignment(EVerticalAlignment InVerticalAlignment) { VerticalAlignment = InVerticalAlignment; if ( MyBorder.IsValid() ) { MyBorder->SetVAlign(InVerticalAlignment); } } FLinearColor UBorder::GetBrushColor() const { return BrushColor; } void UBorder::SetBrushColor(FLinearColor Color) { BrushColor = Color; if ( MyBorder.IsValid() ) { MyBorder->SetBorderBackgroundColor(Color); } } PRAGMA_ENABLE_DEPRECATION_WARNINGS FReply UBorder::HandleMouseButtonDown(const FGeometry& Geometry, const FPointerEvent& MouseEvent) { if ( OnMouseButtonDownEvent.IsBound() ) { return OnMouseButtonDownEvent.Execute(Geometry, MouseEvent).NativeReply; } return FReply::Unhandled(); } FReply UBorder::HandleMouseButtonUp(const FGeometry& Geometry, const FPointerEvent& MouseEvent) { if ( OnMouseButtonUpEvent.IsBound() ) { return OnMouseButtonUpEvent.Execute(Geometry, MouseEvent).NativeReply; } return FReply::Unhandled(); } FReply UBorder::HandleMouseMove(const FGeometry& Geometry, const FPointerEvent& MouseEvent) { if ( OnMouseMoveEvent.IsBound() ) { return OnMouseMoveEvent.Execute(Geometry, MouseEvent).NativeReply; } return FReply::Unhandled(); } FReply UBorder::HandleMouseDoubleClick(const FGeometry& Geometry, const FPointerEvent& MouseEvent) { if ( OnMouseDoubleClickEvent.IsBound() ) { return OnMouseDoubleClickEvent.Execute(Geometry, MouseEvent).NativeReply; } return FReply::Unhandled(); } void UBorder::SetBrush(const FSlateBrush& Brush) { Background = Brush; if ( MyBorder.IsValid() ) { MyBorder->SetBorderImage(&Background); } } void UBorder::SetBrushFromAsset(USlateBrushAsset* Asset) { Background = Asset ? Asset->Brush : FSlateBrush(); if ( MyBorder.IsValid() ) { MyBorder->SetBorderImage(&Background); } } void UBorder::SetBrushFromTexture(UTexture2D* Texture) { Background.SetResourceObject(Texture); if ( MyBorder.IsValid() ) { MyBorder->SetBorderImage(&Background); } } void UBorder::SetBrushFromMaterial(UMaterialInterface* Material) { if (!Material) { UE_LOG(LogSlate, Log, TEXT("UBorder::SetBrushFromMaterial. Incoming material is null")); } Background.SetResourceObject(Material); //TODO UMG Check if the material can be used with the UI if ( MyBorder.IsValid() ) { MyBorder->SetBorderImage(&Background); } } PRAGMA_DISABLE_DEPRECATION_WARNINGS bool UBorder::GetShowEffectWhenDisabled() const { return bShowEffectWhenDisabled; } void UBorder::SetShowEffectWhenDisabled(bool bInShowEffectWhenDisabled) { bShowEffectWhenDisabled = bInShowEffectWhenDisabled; if(MyBorder) { MyBorder->SetShowEffectWhenDisabled(bShowEffectWhenDisabled != 0); } } PRAGMA_ENABLE_DEPRECATION_WARNINGS UMaterialInstanceDynamic* UBorder::GetDynamicMaterial() { UMaterialInterface* Material = nullptr; UObject* Resource = Background.GetResourceObject(); Material = Cast(Resource); if ( Material ) { UMaterialInstanceDynamic* DynamicMaterial = Cast(Material); if ( !DynamicMaterial ) { DynamicMaterial = UMaterialInstanceDynamic::Create(Material, this); Background.SetResourceObject(DynamicMaterial); if ( MyBorder.IsValid() ) { MyBorder->SetBorderImage(&Background); } } return DynamicMaterial; } //TODO UMG can we do something for textures? General purpose dynamic material for them? return nullptr; } PRAGMA_DISABLE_DEPRECATION_WARNINGS FVector2D UBorder::GetDesiredSizeScale() const { return DesiredSizeScale; } void UBorder::SetDesiredSizeScale(FVector2D InScale) { DesiredSizeScale = InScale; if (MyBorder.IsValid()) { MyBorder->SetDesiredSizeScale(InScale); } } PRAGMA_ENABLE_DEPRECATION_WARNINGS const FSlateBrush* UBorder::ConvertImage(TAttribute InImageAsset) const { UBorder* MutableThis = const_cast( this ); MutableThis->Background = InImageAsset.Get(); return &Background; } void UBorder::PostLoad() { Super::PostLoad(); if ( GetChildrenCount() > 0 ) { //TODO UMG Pre-Release Upgrade, now have slots of their own. Convert existing slot to new slot. if ( UPanelSlot* PanelSlot = GetContentSlot() ) { UBorderSlot* BorderSlot = Cast(PanelSlot); if ( BorderSlot == NULL ) { BorderSlot = NewObject(this); BorderSlot->Content = GetContentSlot()->Content; BorderSlot->Content->Slot = BorderSlot; Slots[0] = BorderSlot; } } } } #if WITH_EDITOR void UBorder::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) { Super::PostEditChangeProperty(PropertyChangedEvent); static bool IsReentrant = false; if ( !IsReentrant ) { IsReentrant = true; if ( PropertyChangedEvent.Property ) { static const FName PaddingName("Padding"); static const FName HorizontalAlignmentName("HorizontalAlignment"); static const FName VerticalAlignmentName("VerticalAlignment"); FName PropertyName = PropertyChangedEvent.Property->GetFName(); if ( UBorderSlot* BorderSlot = Cast(GetContentSlot()) ) { if (PropertyName == PaddingName) { FObjectEditorUtils::MigratePropertyValue(this, PaddingName, BorderSlot, PaddingName); } else if (PropertyName == HorizontalAlignmentName) { FObjectEditorUtils::MigratePropertyValue(this, HorizontalAlignmentName, BorderSlot, HorizontalAlignmentName); } else if (PropertyName == VerticalAlignmentName) { FObjectEditorUtils::MigratePropertyValue(this, VerticalAlignmentName, BorderSlot, VerticalAlignmentName); } } } IsReentrant = false; } } const FText UBorder::GetPaletteCategory() { return LOCTEXT("Common", "Common"); } #endif ///////////////////////////////////////////////////// #undef LOCTEXT_NAMESPACE