// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. #include "Models/WidgetReflectorNode.h" #include "Modules/ModuleManager.h" #include "Serialization/JsonTypes.h" #include "Dom/JsonValue.h" #include "Dom/JsonObject.h" #include "Layout/Visibility.h" #include "Layout/ArrangedChildren.h" #include "Layout/WidgetPath.h" #include "AssetRegistryModule.h" #include "Types/ReflectionMetadata.h" #define LOCTEXT_NAMESPACE "WidgetReflectorNode" /** * ----------------------------------------------------------------------------- * FWidgetReflectorNodeBase * ----------------------------------------------------------------------------- */ FWidgetReflectorNodeBase::FWidgetReflectorNodeBase() : Tint(FLinearColor::White) { HitTestInfo.IsHitTestVisible = false; HitTestInfo.AreChildrenHitTestVisible = false; } FWidgetReflectorNodeBase::FWidgetReflectorNodeBase(const FArrangedWidget& InArrangedWidget) : WidgetGeometry(InArrangedWidget.Geometry) , Tint(FLinearColor::White) { const EVisibility WidgetVisibility = InArrangedWidget.Widget->GetVisibility(); HitTestInfo.IsHitTestVisible = WidgetVisibility.IsHitTestVisible(); HitTestInfo.AreChildrenHitTestVisible = WidgetVisibility.AreChildrenHitTestVisible(); } const FGeometry& FWidgetReflectorNodeBase::GetGeometry() const { return WidgetGeometry; } FSlateLayoutTransform FWidgetReflectorNodeBase::GetAccumulatedLayoutTransform() const { return WidgetGeometry.GetAccumulatedLayoutTransform(); } const FSlateRenderTransform& FWidgetReflectorNodeBase::GetAccumulatedRenderTransform() const { return WidgetGeometry.GetAccumulatedRenderTransform(); } const FVector2D& FWidgetReflectorNodeBase::GetLocalSize() const { return WidgetGeometry.GetLocalSize(); } const FWidgetHitTestInfo& FWidgetReflectorNodeBase::GetHitTestInfo() const { return HitTestInfo; } const FLinearColor& FWidgetReflectorNodeBase::GetTint() const { return Tint; } void FWidgetReflectorNodeBase::SetTint(const FLinearColor& InTint) { Tint = InTint; } void FWidgetReflectorNodeBase::AddChildNode(TSharedRef InChildNode) { ChildNodes.Add(MoveTemp(InChildNode)); } const TArray>& FWidgetReflectorNodeBase::GetChildNodes() const { return ChildNodes; } /** * ----------------------------------------------------------------------------- * FLiveWidgetReflectorNode * ----------------------------------------------------------------------------- */ TSharedRef FLiveWidgetReflectorNode::Create(const FArrangedWidget& InArrangedWidget) { return MakeShareable(new FLiveWidgetReflectorNode(InArrangedWidget)); } FLiveWidgetReflectorNode::FLiveWidgetReflectorNode(const FArrangedWidget& InArrangedWidget) : FWidgetReflectorNodeBase(InArrangedWidget) , Widget(InArrangedWidget.Widget) { } EWidgetReflectorNodeType FLiveWidgetReflectorNode::GetNodeType() const { return EWidgetReflectorNodeType::Live; } TSharedPtr FLiveWidgetReflectorNode::GetLiveWidget() const { return Widget.Pin(); } FText FLiveWidgetReflectorNode::GetWidgetType() const { return FWidgetReflectorNodeUtils::GetWidgetType(Widget.Pin()); } FText FLiveWidgetReflectorNode::GetWidgetTypeAndShortName() const { return FWidgetReflectorNodeUtils::GetWidgetTypeAndShortName(Widget.Pin()); } FText FLiveWidgetReflectorNode::GetWidgetVisibilityText() const { return FWidgetReflectorNodeUtils::GetWidgetVisibilityText(Widget.Pin()); } bool FLiveWidgetReflectorNode::GetWidgetVisible() const { return FWidgetReflectorNodeUtils::GetWidgetVisibility(Widget.Pin()); } FText FLiveWidgetReflectorNode::GetWidgetClippingText() const { return FWidgetReflectorNodeUtils::GetWidgetClippingText(Widget.Pin()); } bool FLiveWidgetReflectorNode::GetWidgetFocusable() const { return FWidgetReflectorNodeUtils::GetWidgetFocusable(Widget.Pin()); } FText FLiveWidgetReflectorNode::GetWidgetReadableLocation() const { return FWidgetReflectorNodeUtils::GetWidgetReadableLocation(Widget.Pin()); } FString FLiveWidgetReflectorNode::GetWidgetFile() const { return FWidgetReflectorNodeUtils::GetWidgetFile(Widget.Pin()); } int32 FLiveWidgetReflectorNode::GetWidgetLineNumber() const { return FWidgetReflectorNodeUtils::GetWidgetLineNumber(Widget.Pin()); } FAssetData FLiveWidgetReflectorNode::GetWidgetAssetData() const { return FWidgetReflectorNodeUtils::GetWidgetAssetData(Widget.Pin()); } FVector2D FLiveWidgetReflectorNode::GetWidgetDesiredSize() const { return FWidgetReflectorNodeUtils::GetWidgetDesiredSize(Widget.Pin()); } FSlateColor FLiveWidgetReflectorNode::GetWidgetForegroundColor() const { return FWidgetReflectorNodeUtils::GetWidgetForegroundColor(Widget.Pin()); } FString FLiveWidgetReflectorNode::GetWidgetAddress() const { return FWidgetReflectorNodeUtils::GetWidgetAddress(Widget.Pin()); } bool FLiveWidgetReflectorNode::GetWidgetEnabled() const { return FWidgetReflectorNodeUtils::GetWidgetEnabled(Widget.Pin()); } /** * ----------------------------------------------------------------------------- * FSnapshotWidgetReflectorNode * ----------------------------------------------------------------------------- */ TSharedRef FSnapshotWidgetReflectorNode::Create() { return MakeShareable(new FSnapshotWidgetReflectorNode()); } TSharedRef FSnapshotWidgetReflectorNode::Create(const FArrangedWidget& InWidgetGeometry) { return MakeShareable(new FSnapshotWidgetReflectorNode(InWidgetGeometry)); } FSnapshotWidgetReflectorNode::FSnapshotWidgetReflectorNode() : CachedWidgetLineNumber(0) , CachedWidgetEnabled(false) { } FSnapshotWidgetReflectorNode::FSnapshotWidgetReflectorNode(const FArrangedWidget& InArrangedWidget) : FWidgetReflectorNodeBase(InArrangedWidget) , CachedWidgetType(FWidgetReflectorNodeUtils::GetWidgetType(InArrangedWidget.Widget)) , CachedWidgetTypeAndShortName(FWidgetReflectorNodeUtils::GetWidgetTypeAndShortName(InArrangedWidget.Widget)) , CachedWidgetVisibilityText(FWidgetReflectorNodeUtils::GetWidgetVisibilityText(InArrangedWidget.Widget)) , bCachedWidgetVisible(FWidgetReflectorNodeUtils::GetWidgetVisibility(InArrangedWidget.Widget)) , bCachedWidgetFocusable(FWidgetReflectorNodeUtils::GetWidgetFocusable(InArrangedWidget.Widget)) , CachedWidgetClippingText(FWidgetReflectorNodeUtils::GetWidgetClippingText(InArrangedWidget.Widget)) , CachedWidgetReadableLocation(FWidgetReflectorNodeUtils::GetWidgetReadableLocation(InArrangedWidget.Widget)) , CachedWidgetFile(FWidgetReflectorNodeUtils::GetWidgetFile(InArrangedWidget.Widget)) , CachedWidgetLineNumber(FWidgetReflectorNodeUtils::GetWidgetLineNumber(InArrangedWidget.Widget)) , CachedWidgetAssetData(FWidgetReflectorNodeUtils::GetWidgetAssetData(InArrangedWidget.Widget)) , CachedWidgetDesiredSize(FWidgetReflectorNodeUtils::GetWidgetDesiredSize(InArrangedWidget.Widget)) , CachedWidgetForegroundColor(FWidgetReflectorNodeUtils::GetWidgetForegroundColor(InArrangedWidget.Widget)) , CachedWidgetAddress(FWidgetReflectorNodeUtils::GetWidgetAddress(InArrangedWidget.Widget)) , CachedWidgetEnabled(FWidgetReflectorNodeUtils::GetWidgetEnabled(InArrangedWidget.Widget)) { } EWidgetReflectorNodeType FSnapshotWidgetReflectorNode::GetNodeType() const { return EWidgetReflectorNodeType::Snapshot; } TSharedPtr FSnapshotWidgetReflectorNode::GetLiveWidget() const { return nullptr; } FText FSnapshotWidgetReflectorNode::GetWidgetType() const { return CachedWidgetType; } FText FSnapshotWidgetReflectorNode::GetWidgetTypeAndShortName() const { return CachedWidgetTypeAndShortName; } FText FSnapshotWidgetReflectorNode::GetWidgetVisibilityText() const { return CachedWidgetVisibilityText; } bool FSnapshotWidgetReflectorNode::GetWidgetFocusable() const { return bCachedWidgetFocusable; } bool FSnapshotWidgetReflectorNode::GetWidgetVisible() const { return bCachedWidgetFocusable; } FText FSnapshotWidgetReflectorNode::GetWidgetClippingText() const { return CachedWidgetClippingText; } FText FSnapshotWidgetReflectorNode::GetWidgetReadableLocation() const { return CachedWidgetReadableLocation; } FString FSnapshotWidgetReflectorNode::GetWidgetFile() const { return CachedWidgetFile; } int32 FSnapshotWidgetReflectorNode::GetWidgetLineNumber() const { return CachedWidgetLineNumber; } FAssetData FSnapshotWidgetReflectorNode::GetWidgetAssetData() const { return CachedWidgetAssetData; } FVector2D FSnapshotWidgetReflectorNode::GetWidgetDesiredSize() const { return CachedWidgetDesiredSize; } FSlateColor FSnapshotWidgetReflectorNode::GetWidgetForegroundColor() const { return CachedWidgetForegroundColor; } FString FSnapshotWidgetReflectorNode::GetWidgetAddress() const { return CachedWidgetAddress; } bool FSnapshotWidgetReflectorNode::GetWidgetEnabled() const { return CachedWidgetEnabled; } TSharedRef FSnapshotWidgetReflectorNode::ToJson(const TSharedRef& RootSnapshotNode) { struct Internal { static TSharedRef CreateVector2DJsonValue(const FVector2D& InVec2D) { TArray> StructJsonArray; StructJsonArray.Add(MakeShareable(new FJsonValueNumber(InVec2D.X))); StructJsonArray.Add(MakeShareable(new FJsonValueNumber(InVec2D.Y))); return MakeShareable(new FJsonValueArray(StructJsonArray)); } static TSharedRef CreateMatrix2x2JsonValue(const FMatrix2x2& InMatrix) { float m00, m01, m10, m11; InMatrix.GetMatrix(m00, m01, m10, m11); TArray> StructJsonArray; StructJsonArray.Add(MakeShareable(new FJsonValueNumber(m00))); StructJsonArray.Add(MakeShareable(new FJsonValueNumber(m01))); StructJsonArray.Add(MakeShareable(new FJsonValueNumber(m10))); StructJsonArray.Add(MakeShareable(new FJsonValueNumber(m11))); return MakeShareable(new FJsonValueArray(StructJsonArray)); } static TSharedRef CreateSlateLayoutTransformJsonValue(const FSlateLayoutTransform& InLayoutTransform) { TSharedRef StructJsonObject = MakeShareable(new FJsonObject()); StructJsonObject->SetNumberField(TEXT("Scale"), InLayoutTransform.GetScale()); StructJsonObject->SetField(TEXT("Translation"), CreateVector2DJsonValue(InLayoutTransform.GetTranslation())); return MakeShareable(new FJsonValueObject(StructJsonObject)); } static TSharedRef CreateSlateRenderTransformJsonValue(const FSlateRenderTransform& InRenderTransform) { TSharedRef StructJsonObject = MakeShareable(new FJsonObject()); StructJsonObject->SetField(TEXT("Matrix"), CreateMatrix2x2JsonValue(InRenderTransform.GetMatrix())); StructJsonObject->SetField(TEXT("Translation"), CreateVector2DJsonValue(InRenderTransform.GetTranslation())); return MakeShareable(new FJsonValueObject(StructJsonObject)); } static TSharedRef CreateLinearColorJsonValue(const FLinearColor& InColor) { TArray> StructJsonArray; StructJsonArray.Add(MakeShareable(new FJsonValueNumber(InColor.R))); StructJsonArray.Add(MakeShareable(new FJsonValueNumber(InColor.G))); StructJsonArray.Add(MakeShareable(new FJsonValueNumber(InColor.B))); StructJsonArray.Add(MakeShareable(new FJsonValueNumber(InColor.A))); return MakeShareable(new FJsonValueArray(StructJsonArray)); } static TSharedRef CreateSlateColorJsonValue(const FSlateColor& InColor) { const bool bIsColorSpecified = InColor.IsColorSpecified(); const FLinearColor ColorToUse = (bIsColorSpecified) ? InColor.GetSpecifiedColor() : FLinearColor::White; TSharedRef StructJsonObject = MakeShareable(new FJsonObject()); StructJsonObject->SetBoolField(TEXT("IsColorSpecified"), bIsColorSpecified); StructJsonObject->SetField(TEXT("Color"), CreateLinearColorJsonValue(ColorToUse)); return MakeShareable(new FJsonValueObject(StructJsonObject)); } static TSharedRef CreateWidgetHitTestInfoJsonValue(const FWidgetHitTestInfo& InHitTestInfo) { TSharedRef StructJsonObject = MakeShareable(new FJsonObject()); StructJsonObject->SetBoolField(TEXT("IsHitTestVisible"), InHitTestInfo.IsHitTestVisible); StructJsonObject->SetBoolField(TEXT("AreChildrenHitTestVisible"), InHitTestInfo.AreChildrenHitTestVisible); return MakeShareable(new FJsonValueObject(StructJsonObject)); } }; TSharedRef RootJsonObject = MakeShareable(new FJsonObject()); RootJsonObject->SetField(TEXT("AccumulatedLayoutTransform"), Internal::CreateSlateLayoutTransformJsonValue(RootSnapshotNode->GetAccumulatedLayoutTransform())); RootJsonObject->SetField(TEXT("AccumulatedRenderTransform"), Internal::CreateSlateRenderTransformJsonValue(RootSnapshotNode->GetAccumulatedRenderTransform())); RootJsonObject->SetField(TEXT("LocalSize"), Internal::CreateVector2DJsonValue(RootSnapshotNode->GetLocalSize())); RootJsonObject->SetField(TEXT("HitTestInfo"), Internal::CreateWidgetHitTestInfoJsonValue(RootSnapshotNode->HitTestInfo)); RootJsonObject->SetStringField(TEXT("WidgetType"), RootSnapshotNode->CachedWidgetType.ToString()); RootJsonObject->SetStringField(TEXT("WidgetVisibilityText"), RootSnapshotNode->CachedWidgetVisibilityText.ToString()); RootJsonObject->SetBoolField(TEXT("WidgetFocusable"), RootSnapshotNode->bCachedWidgetFocusable); RootJsonObject->SetStringField(TEXT("WidgetReadableLocation"), RootSnapshotNode->CachedWidgetReadableLocation.ToString()); RootJsonObject->SetStringField(TEXT("WidgetFile"), RootSnapshotNode->CachedWidgetFile); RootJsonObject->SetNumberField(TEXT("WidgetLineNumber"), RootSnapshotNode->CachedWidgetLineNumber); RootJsonObject->SetStringField(TEXT("WidgetAssetPath"), RootSnapshotNode->CachedWidgetAssetData.ObjectPath.ToString()); RootJsonObject->SetField(TEXT("WidgetDesiredSize"), Internal::CreateVector2DJsonValue(RootSnapshotNode->CachedWidgetDesiredSize)); RootJsonObject->SetField(TEXT("WidgetForegroundColor"), Internal::CreateSlateColorJsonValue(RootSnapshotNode->CachedWidgetForegroundColor)); RootJsonObject->SetStringField(TEXT("WidgetAddress"), RootSnapshotNode->CachedWidgetAddress); RootJsonObject->SetBoolField(TEXT("WidgetEnabled"), RootSnapshotNode->CachedWidgetEnabled); TArray> ChildNodesJsonArray; for (const auto& ChildReflectorNode : RootSnapshotNode->ChildNodes) { check(ChildReflectorNode->GetNodeType() == EWidgetReflectorNodeType::Snapshot); ChildNodesJsonArray.Add(FSnapshotWidgetReflectorNode::ToJson(StaticCastSharedRef(ChildReflectorNode))); } RootJsonObject->SetArrayField(TEXT("ChildNodes"), ChildNodesJsonArray); return MakeShareable(new FJsonValueObject(RootJsonObject)); } TSharedRef FSnapshotWidgetReflectorNode::FromJson(const TSharedRef& RootJsonValue) { struct Internal { static FVector2D ParseVector2DJsonValue(const TSharedPtr& InJsonValue) { check(InJsonValue.IsValid()); const TArray>& StructJsonArray = InJsonValue->AsArray(); check(StructJsonArray.Num() == 2); return FVector2D( StructJsonArray[0]->AsNumber(), StructJsonArray[1]->AsNumber() ); } static FMatrix2x2 ParseMatrix2x2JsonValue(const TSharedPtr& InJsonValue) { check(InJsonValue.IsValid()); const TArray>& StructJsonArray = InJsonValue->AsArray(); check(StructJsonArray.Num() == 4); return FMatrix2x2( StructJsonArray[0]->AsNumber(), StructJsonArray[1]->AsNumber(), StructJsonArray[2]->AsNumber(), StructJsonArray[3]->AsNumber() ); } static FSlateLayoutTransform ParseSlateLayoutTransformJsonValue(const TSharedPtr& InJsonValue) { check(InJsonValue.IsValid()); const TSharedPtr& StructJsonObject = InJsonValue->AsObject(); check(StructJsonObject.IsValid()); return FSlateLayoutTransform( StructJsonObject->GetNumberField(TEXT("Scale")), ParseVector2DJsonValue(StructJsonObject->GetField(TEXT("Translation"))) ); } static FSlateRenderTransform ParseSlateRenderTransformJsonValue(const TSharedPtr& InJsonValue) { check(InJsonValue.IsValid()); const TSharedPtr& StructJsonObject = InJsonValue->AsObject(); check(StructJsonObject.IsValid()); return FSlateRenderTransform( ParseMatrix2x2JsonValue(StructJsonObject->GetField(TEXT("Matrix"))), ParseVector2DJsonValue(StructJsonObject->GetField(TEXT("Translation"))) ); } static FLinearColor ParseLinearColorJsonValue(const TSharedPtr& InJsonValue) { check(InJsonValue.IsValid()); const TArray>& StructJsonArray = InJsonValue->AsArray(); check(StructJsonArray.Num() == 4); return FLinearColor( StructJsonArray[0]->AsNumber(), StructJsonArray[1]->AsNumber(), StructJsonArray[2]->AsNumber(), StructJsonArray[3]->AsNumber() ); } static FSlateColor ParseSlateColorJsonValue(const TSharedPtr& InJsonValue) { check(InJsonValue.IsValid()); const TSharedPtr& StructJsonObject = InJsonValue->AsObject(); check(StructJsonObject.IsValid()); const bool bIsColorSpecified = StructJsonObject->GetBoolField(TEXT("IsColorSpecified")); if (bIsColorSpecified) { return FSlateColor(ParseLinearColorJsonValue(StructJsonObject->GetField(TEXT("Color")))); } else { return FSlateColor::UseForeground(); } } static FWidgetHitTestInfo ParseWidgetHitTestInfoJsonValue(const TSharedPtr& InJsonValue) { check(InJsonValue.IsValid()); const TSharedPtr& StructJsonObject = InJsonValue->AsObject(); check(StructJsonObject.IsValid()); FWidgetHitTestInfo HitTestInfo; HitTestInfo.IsHitTestVisible = StructJsonObject->GetBoolField(TEXT("IsHitTestVisible")); HitTestInfo.AreChildrenHitTestVisible = StructJsonObject->GetBoolField(TEXT("AreChildrenHitTestVisible")); return HitTestInfo; } }; const TSharedPtr& RootJsonObject = RootJsonValue->AsObject(); check(RootJsonObject.IsValid()); auto RootSnapshotNode = FSnapshotWidgetReflectorNode::Create(); const FSlateLayoutTransform LayoutTransform = Internal::ParseSlateLayoutTransformJsonValue(RootJsonObject->GetField(TEXT("AccumulatedLayoutTransform"))); const FSlateRenderTransform RenderTransform = Internal::ParseSlateRenderTransformJsonValue(RootJsonObject->GetField(TEXT("AccumulatedRenderTransform"))); const FVector2D LocalSize = Internal::ParseVector2DJsonValue(RootJsonObject->GetField(TEXT("LocalSize"))); RootSnapshotNode->WidgetGeometry = FGeometry::MakeRoot(LocalSize, LayoutTransform, RenderTransform); RootSnapshotNode->HitTestInfo = Internal::ParseWidgetHitTestInfoJsonValue(RootJsonObject->GetField(TEXT("HitTestInfo"))); RootSnapshotNode->CachedWidgetType = FText::FromString(RootJsonObject->GetStringField(TEXT("WidgetType"))); RootSnapshotNode->CachedWidgetVisibilityText = FText::FromString(RootJsonObject->GetStringField(TEXT("WidgetVisibilityText"))); RootSnapshotNode->bCachedWidgetFocusable = RootJsonObject->GetBoolField(TEXT("WidgetFocusable")); RootSnapshotNode->CachedWidgetReadableLocation = FText::FromString(RootJsonObject->GetStringField(TEXT("WidgetReadableLocation"))); RootSnapshotNode->CachedWidgetFile = RootJsonObject->GetStringField(TEXT("WidgetFile")); RootSnapshotNode->CachedWidgetLineNumber = RootJsonObject->GetIntegerField(TEXT("WidgetLineNumber")); RootSnapshotNode->CachedWidgetDesiredSize = Internal::ParseVector2DJsonValue(RootJsonObject->GetField(TEXT("WidgetDesiredSize"))); RootSnapshotNode->CachedWidgetForegroundColor = Internal::ParseSlateColorJsonValue(RootJsonObject->GetField(TEXT("WidgetForegroundColor"))); RootSnapshotNode->CachedWidgetAddress = RootJsonObject->GetStringField(TEXT("WidgetAddress")); RootSnapshotNode->CachedWidgetEnabled = RootJsonObject->GetBoolField(TEXT("WidgetEnabled")); FName AssetPath(*RootJsonObject->GetStringField(TEXT("WidgetAssetPath"))); IAssetRegistry& AssetRegistry = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")).Get(); RootSnapshotNode->CachedWidgetAssetData = AssetRegistry.GetAssetByObjectPath(AssetPath); const TArray>& ChildNodesJsonArray = RootJsonObject->GetArrayField(TEXT("ChildNodes")); for (const TSharedPtr& ChildNodeJsonValue : ChildNodesJsonArray) { RootSnapshotNode->AddChildNode(FSnapshotWidgetReflectorNode::FromJson(ChildNodeJsonValue.ToSharedRef())); } return RootSnapshotNode; } /** * ----------------------------------------------------------------------------- * FWidgetReflectorNodeUtils * ----------------------------------------------------------------------------- */ TSharedRef FWidgetReflectorNodeUtils::NewLiveNode(const FArrangedWidget& InWidgetGeometry) { return StaticCastSharedRef(NewNode(EWidgetReflectorNodeType::Live, InWidgetGeometry)); } TSharedRef FWidgetReflectorNodeUtils::NewLiveNodeTreeFrom(const FArrangedWidget& InWidgetGeometry) { return StaticCastSharedRef(NewNodeTreeFrom(EWidgetReflectorNodeType::Live, InWidgetGeometry)); } TSharedRef FWidgetReflectorNodeUtils::NewSnapshotNode(const FArrangedWidget& InWidgetGeometry) { return StaticCastSharedRef(NewNode(EWidgetReflectorNodeType::Snapshot, InWidgetGeometry)); } TSharedRef FWidgetReflectorNodeUtils::NewSnapshotNodeTreeFrom(const FArrangedWidget& InWidgetGeometry) { return StaticCastSharedRef(NewNodeTreeFrom(EWidgetReflectorNodeType::Snapshot, InWidgetGeometry)); } TSharedRef FWidgetReflectorNodeUtils::NewNode(const EWidgetReflectorNodeType InNodeType, const FArrangedWidget& InWidgetGeometry) { switch (InNodeType) { case EWidgetReflectorNodeType::Live: return FLiveWidgetReflectorNode::Create(InWidgetGeometry); case EWidgetReflectorNodeType::Snapshot: return FSnapshotWidgetReflectorNode::Create(InWidgetGeometry); default: // Should never reach this point, but we have to return something! check(false); return FLiveWidgetReflectorNode::Create(InWidgetGeometry); } } TSharedRef FWidgetReflectorNodeUtils::NewNodeTreeFrom(const EWidgetReflectorNodeType InNodeType, const FArrangedWidget& InWidgetGeometry) { TSharedRef NewNodeInstance = NewNode(InNodeType, InWidgetGeometry); TSharedRef CurWidgetParent = InWidgetGeometry.Widget; if (FChildren* Children = CurWidgetParent->GetChildren()) { for (int32 ChildIndex = 0; ChildIndex < Children->Num(); ++ChildIndex) { TSharedRef ChildWidget = Children->GetChildAt(ChildIndex); FGeometry ChildGeometry = ChildWidget->GetCachedGeometry(); const EVisibility CurWidgetVisibility = ChildWidget->GetVisibility(); // Don't add geometry for completely collapsed stuff if (CurWidgetVisibility == EVisibility::Collapsed) { ChildGeometry = FGeometry(); } else if (!CurWidgetParent->ValidatePathToChild(&ChildWidget.Get())) { ChildGeometry = FGeometry(); } // Note that we include both visible and invisible children! NewNodeInstance->AddChildNode(NewNodeTreeFrom(InNodeType, FArrangedWidget(ChildWidget, ChildGeometry))); } } return NewNodeInstance; } void FWidgetReflectorNodeUtils::FindLiveWidgetPath(const TArray>& CandidateNodes, const FWidgetPath& WidgetPathToFind, TArray>& SearchResult, int32 NodeIndexToFind) { if (NodeIndexToFind < WidgetPathToFind.Widgets.Num()) { const FArrangedWidget& WidgetToFind = WidgetPathToFind.Widgets[NodeIndexToFind]; for (int32 NodeIndex = 0; NodeIndex < CandidateNodes.Num(); ++NodeIndex) { if (CandidateNodes[NodeIndex]->GetWidgetAddress() == GetWidgetAddress(WidgetPathToFind.Widgets[NodeIndexToFind].Widget)) { SearchResult.Add(CandidateNodes[NodeIndex]); FindLiveWidgetPath(CandidateNodes[NodeIndex]->GetChildNodes(), WidgetPathToFind, SearchResult, NodeIndexToFind + 1); } } } } FText FWidgetReflectorNodeUtils::GetWidgetType(const TSharedPtr& InWidget) { return (InWidget.IsValid()) ? FText::FromString(InWidget->GetTypeAsString()) : FText::GetEmpty(); } FText FWidgetReflectorNodeUtils::GetWidgetTypeAndShortName(const TSharedPtr& InWidget) { if (InWidget.IsValid()) { FText WidgetType = GetWidgetType(InWidget); // UMG widgets have meta-data to help track them TSharedPtr MetaData = InWidget->GetMetaData(); if (MetaData.IsValid()) { if (MetaData->Name != NAME_None) { return FText::Format(LOCTEXT("WidgetTypeAndName", "{0} ({1})"), WidgetType, FText::FromName(MetaData->Name)); } } return WidgetType; } return FText::GetEmpty(); } FText FWidgetReflectorNodeUtils::GetWidgetVisibilityText(const TSharedPtr& InWidget) { return (InWidget.IsValid()) ? FText::FromString(InWidget->GetVisibility().ToString()) : FText::GetEmpty(); } bool FWidgetReflectorNodeUtils::GetWidgetVisibility(const TSharedPtr& InWidget) { return InWidget.IsValid() ? InWidget->GetVisibility().IsVisible() : false; } bool FWidgetReflectorNodeUtils::GetWidgetFocusable(const TSharedPtr& InWidget) { return InWidget.IsValid() ? InWidget->SupportsKeyboardFocus() : false; } FText FWidgetReflectorNodeUtils::GetWidgetClippingText(const TSharedPtr& InWidget) { if ( InWidget.IsValid() ) { switch ( InWidget->GetClipping() ) { case EWidgetClipping::Inherit: return LOCTEXT("WidgetClippingNo", "No"); case EWidgetClipping::ClipToBounds: return LOCTEXT("WidgetClippingYes", "Yes"); case EWidgetClipping::ClipToBoundsAlways: return LOCTEXT("WidgetClippingYesAlways", "Yes (Always)"); case EWidgetClipping::ClipToBoundsWithoutIntersecting: return LOCTEXT("WidgetClippingYesWithoutIntersecting", "Yes (No Intersect)"); case EWidgetClipping::OnDemand: return LOCTEXT("WidgetClippingOnDemand", "On Demand"); } } return FText::GetEmpty(); } FText FWidgetReflectorNodeUtils::GetWidgetReadableLocation(const TSharedPtr& InWidget) { return FText::FromString(FReflectionMetaData::GetWidgetDebugInfo(InWidget.Get())); } FString FWidgetReflectorNodeUtils::GetWidgetFile(const TSharedPtr& InWidget) { return (InWidget.IsValid()) ? InWidget->GetCreatedInLocation().GetPlainNameString() : FString(); } int32 FWidgetReflectorNodeUtils::GetWidgetLineNumber(const TSharedPtr& InWidget) { return (InWidget.IsValid()) ? InWidget->GetCreatedInLocation().GetNumber() : 0; } FAssetData FWidgetReflectorNodeUtils::GetWidgetAssetData(const TSharedPtr& InWidget) { if (InWidget.IsValid()) { // UMG widgets have meta-data to help track them TSharedPtr MetaData = InWidget->GetMetaData(); if (MetaData.IsValid() && MetaData->Asset.Get() != nullptr) { return FAssetData(MetaData->Asset.Get()); } } return FAssetData(); } FVector2D FWidgetReflectorNodeUtils::GetWidgetDesiredSize(const TSharedPtr& InWidget) { return (InWidget.IsValid()) ? InWidget->GetDesiredSize() : FVector2D::ZeroVector; } FString FWidgetReflectorNodeUtils::GetWidgetAddress(const TSharedPtr& InWidget) { return FString::Printf(TEXT("0x%0llx"), reinterpret_cast(InWidget.Get())); } FSlateColor FWidgetReflectorNodeUtils::GetWidgetForegroundColor(const TSharedPtr& InWidget) { return (InWidget.IsValid()) ? InWidget->GetForegroundColor() : FSlateColor::UseForeground(); } bool FWidgetReflectorNodeUtils::GetWidgetEnabled(const TSharedPtr& InWidget) { return (InWidget.IsValid()) ? InWidget->IsEnabled() : false; } #undef LOCTEXT_NAMESPACE