void UVREditorMode::Enter()
{
	bWantsToExitMode = false;
	ExitType = EVREditorExitType::Normal;

	{
		IViewportWorldInteractionManager& ViewportWorldInteraction = IViewportInteractionModule::Get().GetWorldInteractionManager();
		ViewportWorldInteraction.OnPreWorldInteractionTick().AddUObject( this, &UVREditorMode::PreTick );
		ViewportWorldInteraction.OnPostWorldInteractionTick().AddUObject( this, &UVREditorMode::Tick );
	}

	// @todo vreditor: We need to make sure the user can never switch to orthographic mode, or activate settings that
	// would disrupt the user's ability to view the VR scene.

	// @todo vreditor: Don't bother drawing toolbars in VR, or other things that won't matter in VR

	{
		const TSharedRef< ILevelEditor >& LevelEditor = FModuleManager::GetModuleChecked<FLevelEditorModule>("LevelEditor").GetFirstLevelEditor().ToSharedRef();

		bool bSummonNewWindow = true;

		// Do we have an active perspective viewport that is valid for VR?  If so, go ahead and use that.
		TSharedPtr<SLevelViewport> ExistingActiveLevelViewport;
		{
			TSharedPtr<ILevelViewport> ActiveLevelViewport = LevelEditor->GetActiveViewportInterface();
			if(ActiveLevelViewport.IsValid())
			{
				ExistingActiveLevelViewport = StaticCastSharedRef< SLevelViewport >(ActiveLevelViewport->AsWidget());

				// Use the currently active window instead
				bSummonNewWindow = false;
			}
		}

		TSharedPtr< SLevelViewport > VREditorLevelViewport;
		if(bSummonNewWindow)
		{
			// @todo vreditor: The resolution we set here doesn't matter, as HMDs will draw at their native resolution
			// no matter what.  We should probably allow the window to be freely resizable by the user
			// @todo vreditor: Should save and restore window position and size settings
			FVector2D WindowSize;
			{
				IHeadMountedDisplay::MonitorInfo HMDMonitorInfo;
				if(bActuallyUsingVR && GEngine->HMDDevice->GetHMDMonitorInfo(HMDMonitorInfo))
				{
					WindowSize = FVector2D(HMDMonitorInfo.ResolutionX, HMDMonitorInfo.ResolutionY);
				}
				else
				{
					// @todo vreditor: Hard-coded failsafe window size
					WindowSize = FVector2D(1920.0f, 1080.0f);
				}
			}

			// @todo vreditor: Use SLevelEditor::GetTableTitle() for the VR window title (needs dynamic update)
			const FText VREditorWindowTitle = NSLOCTEXT("VREditor", "VRWindowTitle", "Unreal Editor VR");

			TSharedRef< SWindow > VREditorWindow = SNew(SWindow)
				.Title(VREditorWindowTitle)
				.ClientSize(WindowSize)
				.AutoCenter(EAutoCenter::PreferredWorkArea)
				.UseOSWindowBorder(true)	// @todo vreditor: Allow window to be freely resized?  Shouldn't really hurt anything.  We should save position/size too.
				.SizingRule(ESizingRule::UserSized);
			this->VREditorWindowWeakPtr = VREditorWindow;

			VREditorLevelViewport =
				SNew(SLevelViewport)
				.ViewportType(LVT_Perspective) // Perspective
				.Realtime(true)
				//				.ParentLayout( AsShared() )	// @todo vreditor: We don't have one and we probably don't need one, right?  Make sure a null parent layout is handled properly everywhere.
				.ParentLevelEditor(LevelEditor)
				//				.ConfigKey( BottomLeftKey )	// @todo vreditor: This is for saving/loading layout.  We would need this in order to remember viewport settings like show flags, etc.
				.IsEnabled(FSlateApplication::Get().GetNormalExecutionAttribute());

			// Allow the editor to keep track of this editor viewport.  Because it's not inside of a normal tab, 
			// we need to explicitly tell the level editor about it
			LevelEditor->AddStandaloneLevelViewport(VREditorLevelViewport.ToSharedRef());

			VREditorWindow->SetContent(VREditorLevelViewport.ToSharedRef());

			// NOTE: We're intentionally not adding this window natively parented to the main frame window, because we don't want it
			// to minimize/restore when the main frame is minimized/restored
			FSlateApplication::Get().AddWindow(VREditorWindow);

			VREditorWindow->SetOnWindowClosed(FOnWindowClosed::CreateUObject(this, &UVREditorMode::OnVREditorWindowClosed));

			VREditorWindow->BringToFront();	// @todo vreditor: Not sure if this is needed, especially if we decide the window should be hidden (copied this from PIE code)
		}
		else
		{
			VREditorLevelViewport = ExistingActiveLevelViewport;

			if(bActuallyUsingVR)
			{
				// Switch to immersive mode
				const bool bWantImmersive = true;
				const bool bAllowAnimation = false;
				ExistingActiveLevelViewport->MakeImmersive(bWantImmersive, bAllowAnimation);
			}
		}

		this->VREditorLevelViewportWeakPtr = VREditorLevelViewport;

		{
			FLevelEditorViewportClient& VRViewportClient = VREditorLevelViewport->GetLevelViewportClient();
			FEditorViewportClient& VREditorViewportClient = VRViewportClient;

			// Make sure we are in perspective mode
			// @todo vreditor: We should never allow ortho switching while in VR
			SavedEditorState.ViewportType = VREditorViewportClient.GetViewportType();
			VREditorViewportClient.SetViewportType(LVT_Perspective);

			// Set the initial camera location
			// @todo vreditor: This should instead be calculated using the currently active perspective camera's
			// location and orientation, compensating for the current HMD offset from the tracking space origin.
			// Perhaps, we also want to teleport the original viewport's camera back when we exit this mode, too!
			// @todo vreditor: Should save and restore camera position and any other settings we change (viewport type, pitch locking, etc.)
			SavedEditorState.ViewLocation = VRViewportClient.GetViewLocation();
			SavedEditorState.ViewRotation = VRViewportClient.GetViewRotation();

			// Don't allow the tracking space to pitch up or down.  People hate that in VR.
			// @todo vreditor: This doesn't seem to prevent people from pitching the camera with RMB drag
			SavedEditorState.bLockedPitch = VRViewportClient.GetCameraController()->GetConfig().bLockedPitch;
			if(bActuallyUsingVR)
			{
				VRViewportClient.GetCameraController()->AccessConfig().bLockedPitch = true;
			}

			// Set "game mode" to be enabled, to get better performance.  Also hit proxies won't work in VR, anyway
			SavedEditorState.bGameView = VREditorViewportClient.IsInGameView();
			VREditorViewportClient.SetGameView(true);

			SavedEditorState.bRealTime = VREditorViewportClient.IsRealtime();
			VREditorViewportClient.SetRealtime(true);

			SavedEditorState.ShowFlags = VREditorViewportClient.EngineShowFlags;

			// Never show the traditional Unreal transform widget.  It doesn't work in VR because we don't have hit proxies.
			VREditorViewportClient.EngineShowFlags.SetModeWidgets(false);

			// Make sure the mode widgets don't come back when users click on things
			VRViewportClient.bAlwaysShowModeWidgetAfterSelectionChanges = false;

			// Force tiny near clip plane distance, because user can scale themselves to be very small.
			// @todo vreditor: Make this automatically change based on WorldToMetersScale?
			SavedEditorState.NearClipPlane = GNearClippingPlane;
			GNearClippingPlane = 1.0f;	// Normally defaults to 10cm (NOTE: If we go too small, skyboxes become affected)

			SavedEditorState.bOnScreenMessages = GAreScreenMessagesEnabled;
			GAreScreenMessagesEnabled = false;

			// Save the world to meters scale
			SavedEditorState.WorldToMetersScale = VRViewportClient.GetWorld()->GetWorldSettings()->WorldToMeters;

			if(bActuallyUsingVR)
			{
				SavedEditorState.TrackingOrigin = GEngine->HMDDevice->GetTrackingOrigin();
				GEngine->HMDDevice->SetTrackingOrigin(EHMDTrackingOrigin::Floor);
			}

			// Make the new viewport the active level editing viewport right away
			GCurrentLevelEditingViewportClient = &VRViewportClient;

			// Enable selection outline right away
			VREditorViewportClient.EngineShowFlags.SetSelection( true );
			VREditorViewportClient.EngineShowFlags.SetSelectionOutline( true );
		}

		VREditorLevelViewport->EnableStereoRendering( bActuallyUsingVR );
		VREditorLevelViewport->SetRenderDirectlyToWindow( bActuallyUsingVR );

		if( bActuallyUsingVR )
		{
			GEngine->HMDDevice->EnableStereo( true );

			// @todo vreditor: Force single eye, undistorted mirror for demos
			const bool bIsVREditorDemo = FParse::Param( FCommandLine::Get(), TEXT( "VREditorDemo" ) );	// @todo vreditor: Remove this when no longer needed (console variable, too!)
			if( bIsVREditorDemo && GetHMDDeviceType() == EHMDDeviceType::DT_OculusRift )
			{
				// If we're using an Oculus Rift, go ahead and set the mirror mode to a single undistorted eye
				GEngine->DeferredCommands.Add( FString::Printf( TEXT( "HMD MIRROR MODE %i" ), VREd::ForceOculusMirrorMode->GetInt() ) );
			}
		}

		if( bActuallyUsingVR )
		{
			// Tell Slate to require a larger pixel distance threshold before the drag starts.  This is important for things 
			// like Content Browser drag and drop.
			SavedEditorState.DragTriggerDistance = FSlateApplication::Get().GetDragTriggerDistance();
			FSlateApplication::Get().SetDragTriggerDistance( 100.0f );	// @todo vreditor tweak
		}
	}

	// Setup sub systems
	{
		// Setup world interaction
		TSharedPtr<FEditorViewportClient> ViewportClient = VREditorLevelViewportWeakPtr.Pin()->GetViewportClient();
		WorldInteraction->SetViewport( ViewportClient );
		WorldInteraction->Activate( true );

		WorldInteraction->OnHandleKeyInput().AddUObject( this, &UVREditorMode::InputKey );

		// Motion controllers
		if(bActuallyUsingVR)
		{
			LeftHandInteractor = NewObject<UVREditorMotionControllerInteractor>( WorldInteraction );
			LeftHandInteractor->SetControllerHandSide( EControllerHand::Left );
			LeftHandInteractor->Init( this );
			WorldInteraction->AddInteractor( LeftHandInteractor );

			RightHandInteractor = NewObject<UVREditorMotionControllerInteractor>( WorldInteraction );
			RightHandInteractor->SetControllerHandSide( EControllerHand::Right );
			RightHandInteractor->Init( this );
			WorldInteraction->AddInteractor( RightHandInteractor );

			WorldInteraction->PairInteractors( LeftHandInteractor, RightHandInteractor );
		}
		else
		{
			// Register an interactor for the mouse cursor
			MouseCursorInteractor = NewObject<UMouseCursorInteractor>( WorldInteraction );
			MouseCursorInteractor->Init();
			WorldInteraction->AddInteractor( MouseCursorInteractor );
		}

		// Setup the UI system
		UISystem = NewObject<UVREditorUISystem>();
		UISystem->SetOwner( this );
		UISystem->Init();

		VRWorldInteractionExtension = NewObject<UVREditorWorldInteraction>();
		VRWorldInteractionExtension->Init( this, WorldInteraction );

		// Setup teleporter
		TeleporterSystem = NewObject<UVREditorTeleporter>();
		TeleporterSystem->Init( this );

		// Setup autoscaler
		AutoScalerSystem = NewObject<UVREditorAutoScaler>();
		AutoScalerSystem->Init( this );
	}

	if(AvatarActor == nullptr)
	{
		SpawnAvatarMeshActor();
	}

	bFirstTick = true;
	bIsActive = true;
}
void FIOSTargetSettingsCustomization::BuildPListSection(IDetailLayoutBuilder& DetailLayout)
{
	// Info.plist category
	IDetailCategoryBuilder& AppManifestCategory = DetailLayout.EditCategory(TEXT("Info.plist"));
	IDetailCategoryBuilder& BundleCategory = DetailLayout.EditCategory(TEXT("Bundle Information"));
	IDetailCategoryBuilder& OrientationCategory = DetailLayout.EditCategory(TEXT("Orientation"));
	IDetailCategoryBuilder& RenderCategory = DetailLayout.EditCategory(TEXT("Rendering"));

	TSharedRef<SPlatformSetupMessage> PlatformSetupMessage = SNew(SPlatformSetupMessage, GameInfoPath)
		.PlatformName(LOCTEXT("iOSPlatformName", "iOS"))
		.OnSetupClicked(this, &FIOSTargetSettingsCustomization::CopySetupFilesIntoProject);

	SetupForPlatformAttribute = PlatformSetupMessage->GetReadyToGoAttribute();

	AppManifestCategory.AddCustomRow(TEXT("Warning"), false)
		.WholeRowWidget
		[
			PlatformSetupMessage
		];

	AppManifestCategory.AddCustomRow(TEXT("Info.plist Hyperlink"), false)
		.WholeRowWidget
		[
			SNew(SBox)
			.HAlign(HAlign_Center)
			[
				SNew(SHyperlinkLaunchURL, TEXT("https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html"))
				.Text(LOCTEXT("ApplePlistPage", "About Information Property List Files"))
				.ToolTipText(LOCTEXT("ApplePlistPageTooltip", "Opens a page that discusses Info.plist"))
			]
		];


	AppManifestCategory.AddCustomRow(TEXT("Info.plist"), false)
		.IsEnabled(SetupForPlatformAttribute)
		.NameContent()
		[
			SNew(SHorizontalBox)
			+ SHorizontalBox::Slot()
			.Padding(FMargin(0, 1, 0, 1))
			.FillWidth(1.0f)
			[
				SNew(STextBlock)
				.Text(LOCTEXT("PlistLabel", "Info.plist"))
				.Font(DetailLayout.GetDetailFont())
			]
		]
		.ValueContent()
		[
			SNew(SHorizontalBox)
			+SHorizontalBox::Slot()
			.AutoWidth()
			[
				SNew(SButton)
				.Text(LOCTEXT("OpenPlistFolderButton", "Open PList Folder"))
				.ToolTipText(LOCTEXT("OpenPlistFolderButton_Tooltip", "Opens the folder containing the plist for the current project in Explorer or Finder"))
				.OnClicked(this, &FIOSTargetSettingsCustomization::OpenPlistFolder)
			]
		];

	// Show properties that are gated by the plist being present and writable
	FSimpleDelegate PlistModifiedDelegate = FSimpleDelegate::CreateRaw(this, &FIOSTargetSettingsCustomization::OnPlistPropertyModified);

#define SETUP_PLIST_PROP(PropName, Category, Tip) \
	{ \
		TSharedRef<IPropertyHandle> PropertyHandle = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UIOSRuntimeSettings, PropName)); \
		PropertyHandle->SetOnPropertyValueChanged(PlistModifiedDelegate); \
		Category.AddProperty(PropertyHandle) \
			.EditCondition(SetupForPlatformAttribute, NULL) \
			.ToolTip(Tip); \
	}

	SETUP_PLIST_PROP(BundleDisplayName, BundleCategory, TEXT("Specifies the the display name for the application. This will be displayed under the icon on the device."));
	SETUP_PLIST_PROP(BundleName, BundleCategory, TEXT("Specifies the the name of the application bundle. This is the short name for the application bundle."));
	SETUP_PLIST_PROP(BundleIdentifier, BundleCategory, TEXT("Specifies the bundle identifier for the application."));
	SETUP_PLIST_PROP(VersionInfo, BundleCategory, TEXT("Specifies the version for the application."));
	SETUP_PLIST_PROP(bSupportsPortraitOrientation, OrientationCategory, TEXT("Supports default portrait orientation. Landscape will not be supported."));
	SETUP_PLIST_PROP(bSupportsUpsideDownOrientation, OrientationCategory, TEXT("Supports upside down portrait orientation. Landscape will not be supported."));
	SETUP_PLIST_PROP(bSupportsLandscapeLeftOrientation, OrientationCategory, TEXT("Supports left landscape orientation. Protrait will not be supported."));
	SETUP_PLIST_PROP(bSupportsLandscapeRightOrientation, OrientationCategory, TEXT("Supports right landscape orientation. Protrait will not be supported."));
	
	SETUP_PLIST_PROP(bSupportsMetal, RenderCategory, TEXT("Whether or not to add support for Metal API (requires IOS8 and A7 processors)."));
	SETUP_PLIST_PROP(bSupportsOpenGLES2, RenderCategory, TEXT("Whether or not to add support for OpenGL ES2 (if this is false, then your game should specify minimum IOS8 version and use \"metal\" instead of \"opengles-2\" in UIRequiredDeviceCapabilities)"));

#undef SETUP_PLIST_PROP
}
void FBodySetupDetails::CustomizeDetails( IDetailLayoutBuilder& DetailBuilder )
{
	// Customize collision section
	{
		if ( DetailBuilder.GetProperty("DefaultInstance")->IsValidHandle() )
		{
			IDetailCategoryBuilder& PhysicsCategory = DetailBuilder.EditCategory("Physics");
			IDetailCategoryBuilder& CollisionCategory = DetailBuilder.EditCategory("Collision");

			TSharedPtr<IPropertyHandle> BodyInstanceHandler = DetailBuilder.GetProperty("DefaultInstance");
			DetailBuilder.HideProperty(BodyInstanceHandler);

			TSharedPtr<IPropertyHandle> CollisionTraceHandler = DetailBuilder.GetProperty("CollisionTraceFlag");
			DetailBuilder.HideProperty(CollisionTraceHandler);

			// add physics properties to physics category
			uint32 NumChildren = 0;
			BodyInstanceHandler->GetNumChildren(NumChildren);

			// Get the objects being customized so we can enable/disable editing of 'Simulate Physics'
			DetailBuilder.GetObjectsBeingCustomized(ObjectsCustomized);

			PhysicsCategory.AddCustomRow(TEXT("Mass"), false)
				.NameContent()
				[
					SNew (STextBlock)
					.Text(NSLOCTEXT("MassInKG", "MassInKG_Name", "Mass in KG"))
					.ToolTipText(NSLOCTEXT("MassInKG", "MassInKG_ToolTip", "Mass of the body in KG"))
					.Font( IDetailLayoutBuilder::GetDetailFont() )
				]
			.ValueContent()
				[
					SNew(SEditableTextBox)
					.Text(this, &FBodySetupDetails::OnGetBodyMass)
					.IsReadOnly(this, &FBodySetupDetails::IsBodyMassReadOnly)
					.Font(IDetailLayoutBuilder::GetDetailFont())
				];

			// add all properties of this now - after adding 
			for (uint32 ChildIndex=0; ChildIndex < NumChildren; ++ChildIndex)
			{
				TSharedPtr<IPropertyHandle> ChildProperty = BodyInstanceHandler->GetChildHandle(ChildIndex);
				FString Category = FObjectEditorUtils::GetCategory(ChildProperty->GetProperty());
				if (ChildProperty->GetProperty()->GetName() == TEXT("bSimulatePhysics"))
				{
					// skip bSimulatePhysics
					// this is because we don't want bSimulatePhysics to show up 
					// phat editor 
					// staitc mesh already hides everything else not interested in
					// so phat editor just should not show this option
					continue;
				}
				if (Category == TEXT("Physics"))
				{
					PhysicsCategory.AddProperty(ChildProperty);
				}
				else if (Category == TEXT("Collision"))
				{
					CollisionCategory.AddProperty(ChildProperty);
				}
			}
		}
	}
}
/**
 * Allocates a widget for this type of MultiBlock.  Override this in derived classes.
 *
 * @return  MultiBlock widget object
 */
TSharedRef< class IMultiBlockBaseWidget > FGroupEndBlock::ConstructWidget() const
{
	return SNew( SGroupMarkerBlock );
}
void FVehicleTransmissionDataCustomization::BuildColumnsHeaderHelper(TSharedRef<class IPropertyHandle> StructPropertyHandle, FDetailWidgetRow& GearsSetup)
{
	
	GearsSetup
	.NameContent()
		[
			SNew(STextBlock)
			.Text(LOCTEXT("GearSetup", "Gear Setup"))
			.Font(IDetailLayoutBuilder::GetDetailFontBold())
		]
	.ValueContent()
		.MaxDesiredWidth(GearColumnsWidth)
		.MinDesiredWidth(GearColumnsWidth)
		[
			SNew(SHorizontalBox)
			+ SHorizontalBox::Slot()
			.FillWidth(0.3333f)
			.VAlign(VAlign_Center)
			[
				SNew(SBox)
				.WidthOverride(RowWidth_Customization)
				.HAlign(HAlign_Left)
				.Content()
				[
					SNew(STextBlock)
					.Text(LOCTEXT("RatioLabel", "Gear Ratio"))
					.Font(IDetailLayoutBuilder::GetDetailFontBold())
				]
			]
			+ SHorizontalBox::Slot()
				.FillWidth(0.3333f)
				.VAlign(VAlign_Center)
				[
					SNew(SBox)
					.HAlign(HAlign_Left)
					.WidthOverride(RowWidth_Customization)
					.Content()
					[
						SNew(STextBlock)
						.Text(LOCTEXT("LowRPMLabel", "Down Ratio"))
						.Font(IDetailLayoutBuilder::GetDetailFontBold())
					]
				]
			+ SHorizontalBox::Slot()
				.FillWidth(0.3333f)
				.VAlign(VAlign_Center)
				[
					SNew(STextBlock)
					.Text(LOCTEXT("HighRPMLabel", "Up Ratio"))
					.Font(IDetailLayoutBuilder::GetDetailFontBold())
				]
			+ SHorizontalBox::Slot()
				.AutoWidth()
				.VAlign(VAlign_Center)
				[
					PropertyCustomizationHelpers::MakeAddButton(FSimpleDelegate::CreateSP(this, &FVehicleTransmissionDataCustomization::AddGear, StructPropertyHandle), LOCTEXT("AddGearToolTip", "Adds a new gear"))
				]
			+ SHorizontalBox::Slot()
				.AutoWidth()
				.VAlign(VAlign_Center)
				[
					PropertyCustomizationHelpers::MakeEmptyButton(FSimpleDelegate::CreateSP(this, &FVehicleTransmissionDataCustomization::EmptyGears, StructPropertyHandle), LOCTEXT("EmptyGearToolTip", "Removes all gears"))
				]
			
		];
}
    BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
    virtual TSharedRef<SWidget> GenerateWidgetForColumn(const FName& ColumnName) override
    {
        // Get info to apply to all columns (color and tooltip)
        FSlateColor ResultColor = FSlateColor::UseForeground();
        FText TooltipText = FText::GetEmpty();
        if(Info->bMiss)
        {
            ResultColor = FLinearColor(0.4f,0.4f,0.65f);
            TooltipText = FText::Format(LOCTEXT("MissToolTipFmt", "Miss: {0}"), GetReasonForMiss(Info->Result.Component.Get(), OwnerDetailsPtr.Pin()->GetCurrentQuery()));
        }
        else if(Info->Result.bBlockingHit && Info->Result.bStartPenetrating)
        {
            ResultColor = FLinearColor(1.f,0.25f,0.25f);
        }


        // Generate widget for column
        if (ColumnName == TEXT("Time"))
        {
            static const FNumberFormattingOptions TimeNumberFormat = FNumberFormattingOptions()
                    .SetMinimumFractionalDigits(3)
                    .SetMaximumFractionalDigits(3);

            return	SNew(STextBlock)
                    .ColorAndOpacity( ResultColor )
                    .ToolTipText( TooltipText )
                    .Text( FText::AsNumber(Info->Result.Time, &TimeNumberFormat) );
        }
        else if (ColumnName == TEXT("Type"))
        {
            FText TypeText = FText::GetEmpty();
            if(Info->bMiss)
            {
                TypeText = LOCTEXT("MissLabel", "Miss");
            }
            else if(Info->Result.bBlockingHit)
            {
                TypeText = LOCTEXT("BlockLabel", "Block");
            }
            else
            {
                TypeText = LOCTEXT("TouchLabel", "Touch");
            }

            return	SNew(STextBlock)
                    .ColorAndOpacity( ResultColor )
                    .ToolTipText( TooltipText )
                    .Text( TypeText );
        }
        else if (ColumnName == TEXT("Component"))
        {
            FText LongName = LOCTEXT("InvalidLabel", "Invalid");
            if(Info->Result.Component.IsValid())
            {
                LongName = FText::FromString(Info->Result.Component.Get()->GetReadableName());
            }

            return	SNew(STextBlock)
                    .ColorAndOpacity( ResultColor )
                    .ToolTipText( TooltipText )
                    .Text( LongName );
        }
        else if (ColumnName == TEXT("Normal"))
        {
            return	SNew(STextBlock)
                    .ColorAndOpacity( ResultColor )
                    .ToolTipText( TooltipText )
                    .Text( FText::FromString(Info->Result.Normal.ToString()) );
        }

        return SNullWidget::NullWidget;
    }
void FLandscapeEditorDetails::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
{
	//FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
	//TSharedPtr<SLevelEditor> LevelEditor = StaticCastSharedPtr<SLevelEditor>(LevelEditorModule.GetFirstLevelEditor());
	//CommandList = LevelEditor->GetLevelEditorActions();

	check(!CommandList.IsValid());
	CommandList = MakeShareable(new FUICommandList);

	auto NameToCommandMap = FLandscapeEditorCommands::Get().NameToCommandMap;

#define MAP_TOOL(ToolSetName) CommandList->MapAction(NameToCommandMap.FindChecked(ToolSetName), FUIAction(FExecuteAction::CreateSP(this, &FLandscapeEditorDetails::OnChangeTool, FName(ToolSetName)), FCanExecuteAction::CreateSP(this, &FLandscapeEditorDetails::IsToolEnabled, FName(ToolSetName)), FIsActionChecked::CreateStatic(&FLandscapeEditorDetails::IsToolActive, FName(ToolSetName))));
	MAP_TOOL("ToolSet_NewLandscape");
	MAP_TOOL("ToolSet_ResizeLandscape");

	MAP_TOOL("ToolSet_Sculpt");
	MAP_TOOL("ToolSet_Paint");
	MAP_TOOL("ToolSet_Smooth");
	MAP_TOOL("ToolSet_Flatten");
	MAP_TOOL("ToolSet_Ramp");
	MAP_TOOL("ToolSet_Erosion");
	MAP_TOOL("ToolSet_HydraErosion");
	MAP_TOOL("ToolSet_Noise");
	MAP_TOOL("ToolSet_Retopologize");
	MAP_TOOL("ToolSet_Visibility");

	MAP_TOOL("ToolSet_Select");
	MAP_TOOL("ToolSet_AddComponent");
	MAP_TOOL("ToolSet_DeleteComponent");
	MAP_TOOL("ToolSet_MoveToLevel");

	MAP_TOOL("ToolSet_Mask");
	MAP_TOOL("ToolSet_CopyPaste");

	MAP_TOOL("ToolSet_Splines");
#undef MAP_TOOL
#define MAP_BRUSH_SET(BrushSetName) CommandList->MapAction(NameToCommandMap.FindChecked(BrushSetName), FUIAction(FExecuteAction::CreateSP(this, &FLandscapeEditorDetails::OnChangeBrushSet, FName(BrushSetName)), FCanExecuteAction::CreateSP(this, &FLandscapeEditorDetails::IsBrushSetEnabled, FName(BrushSetName)), FIsActionChecked::CreateStatic(&FLandscapeEditorDetails::IsBrushSetActive, FName(BrushSetName))));
	MAP_BRUSH_SET("BrushSet_Circle");
	MAP_BRUSH_SET("BrushSet_Alpha");
	MAP_BRUSH_SET("BrushSet_Pattern");
	MAP_BRUSH_SET("BrushSet_Component");
	MAP_BRUSH_SET("BrushSet_Gizmo");
#undef MAP_BRUSH_SET
#define MAP_BRUSH(BrushName) CommandList->MapAction(NameToCommandMap.FindChecked(BrushName), FUIAction(FExecuteAction::CreateSP(this, &FLandscapeEditorDetails::OnChangeBrush, FName(BrushName)), FCanExecuteAction(), FIsActionChecked::CreateSP(this, &FLandscapeEditorDetails::IsBrushActive, FName(BrushName))));
	MAP_BRUSH("Circle_Smooth");
	MAP_BRUSH("Circle_Linear");
	MAP_BRUSH("Circle_Spherical");
	MAP_BRUSH("Circle_Tip");
#undef MAP_BRUSH

	static const FLinearColor BorderColor = FLinearColor(0.2f, 0.2f, 0.2f, 0.2f);
	static const FSlateBrush* BorderStyle =  FEditorStyle::GetBrush("DetailsView.GroupSection");

	IDetailCategoryBuilder& LandscapeEditorCategory = DetailBuilder.EditCategory("LandscapeEditor", TEXT(""), ECategoryPriority::TypeSpecific);

	LandscapeEditorCategory.AddCustomRow("")
	.Visibility(TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateStatic(&FLandscapeEditorDetails::GetTargetLandscapeSelectorVisibility)))
	[
		SNew(SComboButton)
		.OnGetMenuContent_Static(&FLandscapeEditorDetails::GetTargetLandscapeMenu)
		.ButtonContent()
		[
			SNew(STextBlock)
			.Text(GetTargetLandscapeName())
		]
	];

	FToolSelectorBuilder ToolBrushSelectorButtons(CommandList, FMultiBoxCustomization::None);
	{
		FUIAction ToolSelectorUIAction;
		//ToolSelectorUIAction.IsActionVisibleDelegate.BindSP(this, &FLandscapeEditorDetails::GetToolSelectorIsVisible);
		ToolBrushSelectorButtons.AddComboButton(
			ToolSelectorUIAction,
			FOnGetContent::CreateSP(this, &FLandscapeEditorDetails::GetToolSelector),
			LOCTEXT("ToolSelector", "Tool"),
			TAttribute<FText>(this, &FLandscapeEditorDetails::GetCurrentToolName),
			LOCTEXT("ToolSelector.Tooltip", "Select Tool"),
			TAttribute<FSlateIcon>(this, &FLandscapeEditorDetails::GetCurrentToolIcon)
			);

		FUIAction BrushSelectorUIAction;
		BrushSelectorUIAction.IsActionVisibleDelegate.BindSP(this, &FLandscapeEditorDetails::GetBrushSelectorIsVisible);
		ToolBrushSelectorButtons.AddComboButton(
			BrushSelectorUIAction,
			FOnGetContent::CreateSP(this, &FLandscapeEditorDetails::GetBrushSelector),
			LOCTEXT("BrushSelector", "Brush"),
			TAttribute<FText>(this, &FLandscapeEditorDetails::GetCurrentBrushName),
			LOCTEXT("BrushSelector.Tooltip", "Select Brush"),
			TAttribute<FSlateIcon>(this, &FLandscapeEditorDetails::GetCurrentBrushIcon)
			);

		FUIAction BrushFalloffSelectorUIAction;
		BrushFalloffSelectorUIAction.IsActionVisibleDelegate.BindSP(this, &FLandscapeEditorDetails::GetBrushFalloffSelectorIsVisible);
		ToolBrushSelectorButtons.AddComboButton(
			BrushFalloffSelectorUIAction,
			FOnGetContent::CreateSP(this, &FLandscapeEditorDetails::GetBrushFalloffSelector),
			LOCTEXT("BrushFalloffSelector", "Falloff"),
			TAttribute<FText>(this, &FLandscapeEditorDetails::GetCurrentBrushFalloffName),
			LOCTEXT("BrushFalloffSelector.Tooltip", "Select Brush Falloff Type"),
			TAttribute<FSlateIcon>(this, &FLandscapeEditorDetails::GetCurrentBrushFalloffIcon)
			);
	}

	LandscapeEditorCategory.AddCustomRow("")
	.Visibility(TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FLandscapeEditorDetails::GetToolSelectorVisibility)))
	[
		ToolBrushSelectorButtons.MakeWidget()
	];

	// Tools:
	Customization_NewLandscape = MakeShareable(new FLandscapeEditorDetailCustomization_NewLandscape);
	Customization_NewLandscape->CustomizeDetails(DetailBuilder);
	Customization_ResizeLandscape = MakeShareable(new FLandscapeEditorDetailCustomization_ResizeLandscape);
	Customization_ResizeLandscape->CustomizeDetails(DetailBuilder);
	Customization_CopyPaste = MakeShareable(new FLandscapeEditorDetailCustomization_CopyPaste);
	Customization_CopyPaste->CustomizeDetails(DetailBuilder);
	Customization_MiscTools = MakeShareable(new FLandscapeEditorDetailCustomization_MiscTools);
	Customization_MiscTools->CustomizeDetails(DetailBuilder);

	// Brushes:
	Customization_AlphaBrush = MakeShareable(new FLandscapeEditorDetailCustomization_AlphaBrush);
	Customization_AlphaBrush->CustomizeDetails(DetailBuilder);

	// Target Layers:
	Customization_TargetLayers = MakeShareable(new FLandscapeEditorDetailCustomization_TargetLayers);
	Customization_TargetLayers->CustomizeDetails(DetailBuilder);
}
void FEditorLiveStreaming::BroadcastStatusCallback( const FLiveStreamingStatus& Status )
{
	TSharedPtr< SNotificationItem > Notification( NotificationWeakPtr.Pin() );
	if( Notification.IsValid() )
	{
		// Don't bother clobbering existing message with text about web cam starting/stopping, unless we're already broadcasting.
		// We want to make sure people see the persistent text about login state.
		if( SubmittedVideoFrameCount > 0 ||
			( Status.StatusType != FLiveStreamingStatus::EStatusType::WebCamStarted &&
			  Status.StatusType != FLiveStreamingStatus::EStatusType::WebCamStopped &&
			  Status.StatusType != FLiveStreamingStatus::EStatusType::WebCamTextureNotReady &&
			  Status.StatusType != FLiveStreamingStatus::EStatusType::WebCamTextureReady &&
			  Status.StatusType != FLiveStreamingStatus::EStatusType::ChatConnected &&
			  Status.StatusType != FLiveStreamingStatus::EStatusType::ChatDisconnected ) )
		{
			Notification->SetText( Status.CustomStatusDescription );
		}
	}
	else
	{
		// Only spawn a notification if we're actually still trying to broadcast, not if we're stopping broadcasting.  We don't want
		// to revive our notification that we intentionally expired.
		if( bIsBroadcasting )
		{
			FNotificationInfo Info( Status.CustomStatusDescription );
			Info.FadeInDuration = 0.1f;
			Info.FadeOutDuration = 0.5f;
			Info.ExpireDuration = 1.5f;
			Info.bUseThrobber = false;
			Info.bUseSuccessFailIcons = true;
			Info.bUseLargeFont = true;
			Info.bFireAndForget = false;
			Info.bAllowThrottleWhenFrameRateIsLow = false;
			NotificationWeakPtr = FSlateNotificationManager::Get().AddNotification( Info );
		}
	}

	Notification = NotificationWeakPtr.Pin();
	if( Notification.IsValid() )
	{
		SNotificationItem::ECompletionState State = SNotificationItem::CS_Pending;
		if( Status.StatusType == FLiveStreamingStatus::EStatusType::Failure )
		{
			State = SNotificationItem::CS_Fail;
		}
		else if( Status.StatusType == FLiveStreamingStatus::EStatusType::BroadcastStarted ||
				 Status.StatusType == FLiveStreamingStatus::EStatusType::WebCamStarted ||
				 Status.StatusType == FLiveStreamingStatus::EStatusType::ChatConnected )
		{
			State = SNotificationItem::CS_Success;
		}

		Notification->SetCompletionState( State );
	}

	// If the web cam just turned on, then we'll go ahead and show it
	if( Status.StatusType == FLiveStreamingStatus::EStatusType::WebCamTextureReady )
	{	
		bool bIsImageFlippedHorizontally = false;
		bool bIsImageFlippedVertically = false;
		UTexture2D* WebCamTexture = LiveStreamer->GetWebCamTexture( bIsImageFlippedHorizontally, bIsImageFlippedVertically );
		if( ensure( WebCamTexture != nullptr ) )
		{
			IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( TEXT( "MainFrame" ) );
			check( MainFrameModule.IsWindowInitialized() );
			auto RootWindow = MainFrameModule.GetParentWindow();
			check( RootWindow.IsValid() );

			// Allow the user to customize the image mirroring, too!
			const auto& Settings = *GetDefault< UEditorLiveStreamingSettings >();
			if( Settings.bMirrorWebCamImage )
			{
				bIsImageFlippedHorizontally = !bIsImageFlippedHorizontally;
			}

			// How many pixels from the edge of the main frame window to where the broadcast status window appears
			const int WindowBorderPadding = 50;

			// @todo livestream: Currently this window is not created as "topmost".  We don't really want it to be OS-topmost, but we do want it to be the most
			// topmost "regular" window in our application (not on top of tooltips, etc.)

			// Create a window that will show the web cam video feed
			BroadcastStatusWindow = SNew( SWindow )
				.Title( LOCTEXT( "StreamingWindowTitle", "Web Camera" ) )
				.ClientSize( FVector2D( WebCamTexture->GetSizeX(), WebCamTexture->GetSizeY() ) )
				.ScreenPosition( FVector2D( 
					RootWindow->GetRectInScreen().Right - WebCamTexture->GetSizeX() - WindowBorderPadding, 
					RootWindow->GetRectInScreen().Top +  WindowBorderPadding ) )

				// @todo livestream: Ideally the user could freely resize the window, but it gets a bit tricky to preserve the web cam aspect.  Plus, we don't really like how letterboxing/columnboxing looks with this.
				.SizingRule( ESizingRule::FixedSize )

				.AutoCenter( EAutoCenter::None )
				.bDragAnywhere( true )
				.SupportsMaximize( true )
				.SupportsMinimize( true )
				.FocusWhenFirstShown( false )
				.ActivateWhenFirstShown( false )
				.SaneWindowPlacement( false );

			WebCamDynamicImageBrush = MakeShareable( new FSlateDynamicImageBrush( 
				WebCamTexture,
				FVector2D( WebCamTexture->GetSizeX(), WebCamTexture->GetSizeY() ),
				WebCamTexture->GetFName() ) );

			// If the web cam image is coming in flipped, we'll apply mirroring to the Slate brush
			if( bIsImageFlippedHorizontally && bIsImageFlippedVertically )
			{
				WebCamDynamicImageBrush->Mirroring = ESlateBrushMirrorType::Both;
			}
			else if( bIsImageFlippedHorizontally )
			{ 
				WebCamDynamicImageBrush->Mirroring = ESlateBrushMirrorType::Horizontal;
			}
			else if( bIsImageFlippedVertically )
			{ 
				WebCamDynamicImageBrush->Mirroring = ESlateBrushMirrorType::Vertical;
			}

			// @todo livestream: Currently if the user closes the window, the camera is deactivated and it doesn't turn back on unless the broadcast is restarted.  We could allow the camera to be reactivated though.
			BroadcastStatusWindow->SetOnWindowClosed( 
				FOnWindowClosed::CreateStatic( []( const TSharedRef<SWindow>& Window, FEditorLiveStreaming* This ) 
				{
					// User closed the broadcast status window, so go ahead and shut down the web cam
					This->LiveStreamer->StopWebCam();
					This->BroadcastStatusWindow.Reset();
					This->WebCamDynamicImageBrush.Reset();
				}, 
				this ) );

			BroadcastStatusWindow->SetContent( 
				SNew( SImage )
					.Image( WebCamDynamicImageBrush.Get() )
			);

			FSlateApplication::Get().AddWindowAsNativeChild(
				BroadcastStatusWindow.ToSharedRef(), 
				RootWindow.ToSharedRef() );
		}

	}
	else if( Status.StatusType == FLiveStreamingStatus::EStatusType::WebCamTextureNotReady )
	{
		CloseBroadcastStatusWindow();
	}
}
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
	];
}
	/** Overridden from SMultiColumnTableRow.  Generates a widget for this column of the list view. */
	virtual TSharedRef<SWidget> GenerateWidgetForColumn(const FName& ColumnName) override
	{
		if (ColumnName == FbxSceneReimportStaticMesh::CheckBoxSelectionHeaderIdName)
		{
			return SNew(SBox)
				.HAlign(HAlign_Center)
				[
					SNew(SCheckBox)
					.OnCheckStateChanged(this, &SFbxMeshReimportItemTableListViewRow::OnItemCheckChanged)
					.IsChecked(this, &SFbxMeshReimportItemTableListViewRow::IsItemChecked)
					.IsEnabled(!FbxMeshInfo->bOriginalTypeChanged)
				];
		}
		else if (ColumnName == FbxSceneReimportStaticMesh::ClassIconHeaderIdName && SlateBrush != nullptr)
		{
			UClass *IconClass = FbxMeshInfo->GetType();
			const FSlateBrush* ClassIcon = FSlateIconFinder::FindIconBrushForClass(IconClass);
			TSharedRef<SOverlay> IconContent = SNew(SOverlay)
				+ SOverlay::Slot()
				.HAlign(HAlign_Right)
				.VAlign(VAlign_Center)
				[
					SNew(SImage)
					.Image(ClassIcon)
				]
				+ SOverlay::Slot()
				.HAlign(HAlign_Left)
				[
					SNew(SImage)
					.Image(this, &SFbxMeshReimportItemTableListViewRow::GetIconOverlay)
				]
				+ SOverlay::Slot()
				.HAlign(HAlign_Left)
				[
					SNew(SImage)
					.Image(this, &SFbxMeshReimportItemTableListViewRow::GetBrushForOverrideIcon)
				];
				return IconContent;
		}
		else if (ColumnName == FbxSceneReimportStaticMesh::AssetNameHeaderIdName)
		{
			return SNew(STextBlock)
				.Text(FText::FromString(FbxMeshInfo->Name))
				.ToolTipText(FText::FromString(FbxMeshInfo->Name));
		}
		else if (ColumnName == FbxSceneReimportStaticMesh::AssetStatusHeaderIdName)
		{
			return SNew(STextBlock)
				.Text(this, &SFbxMeshReimportItemTableListViewRow::GetAssetStatus)
				.ToolTipText(this, &SFbxMeshReimportItemTableListViewRow::GetAssetStatusTooltip);
				
		}
		else if (ColumnName == FbxSceneReimportStaticMesh::ContentPathHeaderIdName)
		{
			return SNew(STextBlock)
				.Text(this, &SFbxMeshReimportItemTableListViewRow::GetAssetFullName)
				.ColorAndOpacity(this, &SFbxMeshReimportItemTableListViewRow::GetContentPathTextColor)
				.ToolTipText(this, &SFbxMeshReimportItemTableListViewRow::GetAssetFullName);
		}
		else if (ColumnName == FbxSceneReimportStaticMesh::OptionNameHeaderIdName)
		{
			return SNew(STextBlock)
				.Text(this, &SFbxMeshReimportItemTableListViewRow::GetOptionName)
				.ToolTipText(this, &SFbxMeshReimportItemTableListViewRow::GetOptionName);
		}
		else if (ColumnName == FbxSceneBaseListViewColumn::PivotColumnId)
		{
			return SNew(STextBlock)
				.Text(this, &SFbxMeshReimportItemTableListViewRow::GetAssetPivotNodeName)
				.ToolTipText(this, &SFbxMeshReimportItemTableListViewRow::GetAssetPivotNodeName);
		}

		return SNullWidget::NullWidget;
	}
void FInputActionMappingCustomization::CustomizeChildren( TSharedRef<class IPropertyHandle> InStructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils )
{
	TSharedPtr<IPropertyHandle> KeyHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FInputActionKeyMapping, Key));
	TSharedPtr<IPropertyHandle> ShiftHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FInputActionKeyMapping, bShift));
	TSharedPtr<IPropertyHandle> CtrlHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FInputActionKeyMapping, bCtrl));
	TSharedPtr<IPropertyHandle> AltHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FInputActionKeyMapping, bAlt));
	TSharedPtr<IPropertyHandle> CmdHandle = InStructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FInputActionKeyMapping, bCmd));

	TSharedRef<SWidget> RemoveButton = PropertyCustomizationHelpers::MakeDeleteButton(FSimpleDelegate::CreateSP(this, &FInputActionMappingCustomization::RemoveActionMappingButton_OnClick),
		LOCTEXT("RemoveActionMappingToolTip", "Removes Action Mapping"));

	StructBuilder.AddChildContent( LOCTEXT("KeySearchStr", "Key").ToString() )
	[
		SNew(SHorizontalBox)
		+ SHorizontalBox::Slot()
		.Padding(InputConstants::PropertyPadding)
		.AutoWidth()
		[
			SNew( SBox )
			.WidthOverride( InputConstants::TextBoxWidth )
			[
				StructBuilder.GenerateStructValueWidget( KeyHandle.ToSharedRef() )
			]
		]
		+ SHorizontalBox::Slot()
		.Padding(InputConstants::PropertyPadding)
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		.AutoWidth()
		[
			ShiftHandle->CreatePropertyNameWidget()
		]
		+ SHorizontalBox::Slot()
		.Padding(InputConstants::PropertyPadding)
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		.AutoWidth()
		[
			ShiftHandle->CreatePropertyValueWidget()
		]
		+ SHorizontalBox::Slot()
		.Padding(InputConstants::PropertyPadding)
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		.AutoWidth()
		[
			CtrlHandle->CreatePropertyNameWidget()
		]
		+ SHorizontalBox::Slot()
		.Padding(InputConstants::PropertyPadding)
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		.AutoWidth()
		[
			CtrlHandle->CreatePropertyValueWidget()
		]
		+ SHorizontalBox::Slot()
		.Padding(InputConstants::PropertyPadding)
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		.AutoWidth()
		[
			AltHandle->CreatePropertyNameWidget()
		]
		+ SHorizontalBox::Slot()
		.Padding(InputConstants::PropertyPadding)
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		.AutoWidth()
		[
			AltHandle->CreatePropertyValueWidget()
		]
		+ SHorizontalBox::Slot()
		.Padding(InputConstants::PropertyPadding)
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		.AutoWidth()
		[
			CmdHandle->CreatePropertyNameWidget()
		]
		+ SHorizontalBox::Slot()
		.Padding(InputConstants::PropertyPadding)
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		.AutoWidth()
		[
			CmdHandle->CreatePropertyValueWidget()
		]
		+ SHorizontalBox::Slot()
		.Padding(InputConstants::PropertyPadding)
		.HAlign(HAlign_Center)
		.VAlign(VAlign_Center)
		.AutoWidth()
		[
			RemoveButton
		]
	];
}
TSharedRef< SWidget > SDetailNameArea::BuildObjectNameArea( const TArray< TWeakObjectPtr<UObject> >& SelectedObjects )
{
	// Get the common base class of the selected objects
	UClass* BaseClass = NULL;
	for( int32 ObjectIndex = 0; ObjectIndex < SelectedObjects.Num(); ++ObjectIndex )
	{
		TWeakObjectPtr<UObject> ObjectWeakPtr = SelectedObjects[ObjectIndex];
		if( ObjectWeakPtr.IsValid() )
		{
			UClass* ObjClass = ObjectWeakPtr->GetClass();

			if (!BaseClass)
			{
				BaseClass = ObjClass;
			}

			while (!ObjClass->IsChildOf(BaseClass))
			{
				BaseClass = BaseClass->GetSuperClass();
			}
		}
	}

	TSharedRef< SHorizontalBox > ObjectNameArea = SNew( SHorizontalBox );

	if (BaseClass)
	{
		// Get selection icon based on actor(s) classes and add before the selection label
		const FSlateBrush* ActorIcon = FClassIconFinder::FindIconForClass(BaseClass);

		ObjectNameArea->AddSlot()
		.AutoWidth()
		.HAlign(HAlign_Left)
		.VAlign(VAlign_Center)
		.Padding(0,0,6,0)
		[
			SNew(SImage)
			.Image(ActorIcon)
			.ToolTip(FEditorClassUtils::GetTooltip(BaseClass))
		];
	}


	// Add the selected object(s) type name, along with buttons for either opening C++ code or editing blueprints
	const int32 NumSelectedSurfaces = AssetSelectionUtils::GetNumSelectedSurfaces( GWorld );
	if( SelectedObjects.Num() > 0 )
	{
		if ( bShowActorLabel )
		{
			FEditorWidgetsModule& EdWidgetsModule = FModuleManager::LoadModuleChecked<FEditorWidgetsModule>(TEXT("EditorWidgets"));
			TSharedRef<IObjectNameEditableTextBox> ObjectNameBox = EdWidgetsModule.CreateObjectNameEditableTextBox(SelectedObjects);

			ObjectNameArea->AddSlot()
				.AutoWidth()
				.Padding(0, 0, 3, 0)
				[
					SNew(SBox)
					.WidthOverride(200.0f)
					.VAlign(VAlign_Center)
					[
						ObjectNameBox
					]
				];
		}

		const TWeakObjectPtr< UObject > ObjectWeakPtr = SelectedObjects.Num() == 1 ? SelectedObjects[0] : NULL;
		BuildObjectNameAreaSelectionLabel( ObjectNameArea, ObjectWeakPtr, SelectedObjects.Num() );

		if( bShowLockButton )
		{
			ObjectNameArea->AddSlot()
				.HAlign(HAlign_Right)
				.FillWidth(1.0f)
				[
					SNew( SButton )
					.ButtonStyle( FEditorStyle::Get(), "NoBorder" )
					.OnClicked(	OnLockButtonClicked )
					.ToolTipText( LOCTEXT("LockSelectionButton_ToolTip", "Locks the current selection into the Details panel") )
					[
						SNew( SImage )
						.Image( this, &SDetailNameArea::OnGetLockButtonImageResource )
					]
				];
		}
	}
	else
	{
		if ( SelectionTip.Get() && NumSelectedSurfaces == 0 )
		{
			ObjectNameArea->AddSlot()
			.FillWidth( 1.0f )
			.HAlign( HAlign_Center )
			.Padding( 2.0f, 24.0f, 2.0f, 2.0f )
			[
				SNew( STextBlock )
				.Text( LOCTEXT("NoObjectsSelected", "Select an object to view details.") )
			];
		}
		else
		{
			// Fill the empty space
			ObjectNameArea->AddSlot();
		}
	}
	
	return ObjectNameArea;
}
/** Generate a widget for the specified column name */
TSharedRef<SWidget> FPListNodeDictionary::GenerateWidgetForColumn(const FName& ColumnName, int32 InDepth, ITableRow* RowPtr)
{
	TableRow = RowPtr;
	check(TableRow);

	if(ColumnName == "PListKeyColumn")
	{
		return
		SNew(SBorder)
		.BorderImage_Static(&IPListNode::GetOverlayBrushDelegate, AsShared())
		[
			SNew(SOverlay)

			+ SOverlay::Slot()
			[
				SNew(SHorizontalBox)
		
				// Space item representing item expansion
				+ SHorizontalBox::Slot()
				[
					SNew(SSpacer)
					.Size(FVector2D(20 * InDepth, 0))
				]

				+ SHorizontalBox::Slot()
				.FillWidth(1.0f)
				[
					SAssignNew(KeyStringTextBox, SEditableTextBox)
					.Text(bArrayMember ? FText::FromString(FString::FromInt(ArrayIndex)) : FText::FromString(TEXT("dictionary")))
					.IsReadOnly(true)
				]

				// Spacer between type
				+ SHorizontalBox::Slot()
				[
					SNew(SSpacer)
					.Size(FVector2D(30, 0))
				]
			]
		
			// Expander for innards
			+ SOverlay::Slot()
			.HAlign(HAlign_Left)
			[
				SNew(SHorizontalBox)

				+ SHorizontalBox::Slot()
				[
					// Space before expander
					SNew(SSpacer)
					.Size(FVector2D(20 * (InDepth - 1), 0))
				]

				+ SHorizontalBox::Slot()
				[
					SAssignNew(ExpanderArrow, SButton)
					.ButtonStyle( FEditorStyle::Get(), "NoBorder" )
					.ClickMethod( EButtonClickMethod::MouseDown )
					.Visibility( this, &FPListNodeDictionary::GetExpanderVisibility )
					.OnClicked( this, &FPListNodeDictionary::OnArrowClicked )
					.ContentPadding(2.1f)
					.ForegroundColor( FSlateColor::UseForeground() )
					[
						SNew(SImage)
						.Image( this, &FPListNodeDictionary::GetExpanderImage )
						.ColorAndOpacity( FSlateColor::UseForeground() )
					]
				]
			]
		];
	}

	else if(ColumnName == "PListValueTypeColumn")
	{
		return
		SNew(SBorder)
		.BorderImage_Static(&IPListNode::GetOverlayBrushDelegate, AsShared())
		[
			SNew(STextBlock)
			.Text(NSLOCTEXT("PListEditor", "dictionaryValueTypeLabel", "dictionary"))
		];
	}

	else if(ColumnName == "PListValueColumn")
	{
		return
		SNew(SBorder)
		.BorderImage_Static(&IPListNode::GetOverlayBrushDelegate, AsShared())
		[
			SAssignNew(InfoTextWidget, STextBlock)
			.Text(FText::Format(NSLOCTEXT("PListEditor", "NumKeyValuePairsFmt", "[{0} key/value pairs]"), FText::AsNumber(GetNumPairs())))
		];
	}

	// Invalid column name
	else
	{
		return SNew(STextBlock) .Text(NSLOCTEXT("PListEditor", "UnknownColumn", "Unknown Column"));
	}
}
	/**
	 * Construct this widget
	 */
	BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
	void Construct( const FArguments& InArgs )
	{
		FPSAnalyzer = InArgs._FPSAnalyzer;

		ChildSlot
		[
			SNew( SBorder )
			.BorderImage( FEditorStyle::GetBrush("ToolPanel.GroupBorder") )
			.Padding( 2.0f )
			[
				SNew( SVerticalBox )

				+SVerticalBox::Slot()
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text(LOCTEXT("StatisticsLabel", "Statistics"))
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				[
					SNew(STextBlock)
					.Text(this, &SProfilerFPSStatisticsPanel::HandleSampleCount)
				]

				+SVerticalBox::Slot()
					.AutoHeight()
					[
						SNew(STextBlock)
						.Text(this, &SProfilerFPSStatisticsPanel::HandleMinFPS)
					]

				+SVerticalBox::Slot()
					.AutoHeight()
					[
						SNew(STextBlock)
						.Text(this, &SProfilerFPSStatisticsPanel::HandleMaxFPS)
					]

				+SVerticalBox::Slot()
					.AutoHeight()
					[
						SNew(STextBlock)
						.Text(this, &SProfilerFPSStatisticsPanel::HandleAverageFPS)
					]

				+SVerticalBox::Slot()
					.AutoHeight()
					[
						SNew(STextBlock)
						.Text(this, &SProfilerFPSStatisticsPanel::HandleFPS90)
					]

				+SVerticalBox::Slot()
					.AutoHeight()
					[
						SNew(STextBlock)
						.Text(this, &SProfilerFPSStatisticsPanel::HandleFPS60)
					]

				+SVerticalBox::Slot()
					.AutoHeight()
					[
						SNew(STextBlock)
						.Text(this, &SProfilerFPSStatisticsPanel::HandleFPS30)
					]

				+SVerticalBox::Slot()
					.AutoHeight()
					[
						SNew(STextBlock)
						.Text(this, &SProfilerFPSStatisticsPanel::HandleFPS25)
					]

				+SVerticalBox::Slot()
					.AutoHeight()
					[
						SNew(STextBlock)
						.Text(this, &SProfilerFPSStatisticsPanel::HandleFPS20)
					]
			]	
		];
	}
Beispiel #15
0
TSharedRef<SWidget> UUserWidget::RebuildWidget()
{
	// In the event this widget is replaced in memory by the blueprint compiler update
	// the widget won't be properly initialized, so we ensure it's initialized and initialize
	// it if it hasn't been.
	if ( !bInitialized )
	{
		Initialize();
	}

	// Setup the player context on sub user widgets, if we have a valid context
	if (PlayerContext.IsValid())
	{
		WidgetTree->ForEachWidget([&] (UWidget* Widget) {
			if ( UUserWidget* UserWidget = Cast<UUserWidget>(Widget) )
			{
				UserWidget->SetPlayerContext(PlayerContext);
			}
		});
	}

	// Add the first component to the root of the widget surface.
	TSharedRef<SWidget> UserRootWidget = WidgetTree->RootWidget ? WidgetTree->RootWidget->TakeWidget() : TSharedRef<SWidget>(SNew(SSpacer));

	return UserRootWidget;
}
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
	];
}
IDetailPropertyRow& FFoliageTypePaintingCustomization::AddFoliageProperty(
    IDetailCategoryBuilder& Category,
    TSharedPtr<IPropertyHandle>& Property,
    TSharedPtr<IPropertyHandle>& ReapplyProperty,
    const TAttribute<EVisibility>& InVisibility,
    const TAttribute<bool>& InEnabled)
{
    IDetailPropertyRow& PropertyRow = Category.AddProperty(Property);

    if (ReapplyProperty.IsValid())
    {
        TSharedPtr<SWidget> NameWidget;
        TSharedPtr<SWidget> ValueWidget;
        FDetailWidgetRow	Row;
        PropertyRow.GetDefaultWidgets(NameWidget, ValueWidget, Row);

        auto IsEnabled = TAttribute<bool>::Create(TAttribute<bool>::FGetter::CreateSP(this, &FFoliageTypePaintingCustomization::IsReapplyPropertyEnabled, ReapplyProperty));
        ValueWidget->SetEnabled(IsEnabled);
        NameWidget->SetEnabled(IsEnabled);

        PropertyRow.CustomWidget(true)
        .NameContent()
        .MinDesiredWidth(Row.NameWidget.MinWidth)
        .MaxDesiredWidth(Row.NameWidget.MaxWidth)
        [
            SNew(SHorizontalBox)
            +SHorizontalBox::Slot()
            .AutoWidth()
            [
                SNew(SCheckBox)
                .IsChecked(this, &FFoliageTypePaintingCustomization::GetReapplyPropertyState, ReapplyProperty)
                .OnCheckStateChanged(this, &FFoliageTypePaintingCustomization::OnReapplyPropertyStateChanged, ReapplyProperty)
                .Visibility(this, &FFoliageTypePaintingCustomization::GetReapplyModeVisibility)
                .ToolTipText(ReapplyProperty->GetToolTipText())
            ]
            +SHorizontalBox::Slot()
            .AutoWidth()
            [
                NameWidget.ToSharedRef()
            ]
        ]
        .ValueContent()
        .MinDesiredWidth(Row.ValueWidget.MinWidth)
        .MaxDesiredWidth(Row.ValueWidget.MaxWidth)
        [
            ValueWidget.ToSharedRef()
        ];
    }
    else
    {
        if (InEnabled.IsSet())
        {
            PropertyRow.IsEnabled(InEnabled);
        }
    }

    if (InVisibility.IsSet())
    {
        PropertyRow.Visibility(InVisibility);
    }

    return PropertyRow;
}
TSharedRef<SWidget> SCAQueryTableRow::GenerateWidgetForColumn(const FName& ColumnName)
{
	TSharedPtr<SCollisionAnalyzer> OwnerAnalyzerWidget = OwnerAnalyzerWidgetPtr.Pin();

	// GROUP
	if(Item->bIsGroup)
	{
		if (ColumnName == SCollisionAnalyzer::IDColumnName)
		{
			return	SNew(SExpanderArrow, SharedThis(this));
		}
		else if (ColumnName == SCollisionAnalyzer::FrameColumnName && OwnerAnalyzerWidget->GroupBy == EQueryGroupMode::ByFrameNum)
		{
			return	SNew(STextBlock)
					.Font(FCollisionAnalyzerStyle::Get()->GetFontStyle("BoldFont"))
					.Text(FText::AsNumber(Item->FrameNum));
		}
		else if (ColumnName == SCollisionAnalyzer::TagColumnName && OwnerAnalyzerWidget->GroupBy == EQueryGroupMode::ByTag)
		{
			return	SNew(STextBlock)
					.Font(FCollisionAnalyzerStyle::Get()->GetFontStyle("BoldFont"))
					.Text(FText::FromName(Item->GroupName));
		}
		else if (ColumnName == SCollisionAnalyzer::OwnerColumnName && OwnerAnalyzerWidget->GroupBy == EQueryGroupMode::ByOwnerTag)
		{
			return	SNew(STextBlock)
					.Font(FCollisionAnalyzerStyle::Get()->GetFontStyle("BoldFont"))
					.Text(FText::FromName(Item->GroupName));
		}
		else if (ColumnName == SCollisionAnalyzer::TimeColumnName)
		{
			return	SNew(STextBlock)
					.Font(FCollisionAnalyzerStyle::Get()->GetFontStyle("BoldFont"))
					.Text(this, &SCAQueryTableRow::GetTotalTimeText);
		}
	}
	// ITEM
	else
	{
		const int32 QueryId = Item->QueryIndex;
		if(QueryId >= OwnerAnalyzerWidget->Analyzer->Queries.Num())
		{
			return	SNew(STextBlock)
					.Text( LOCTEXT("ErrorMessage", "ERROR") );
		}

		FCAQuery& Query = OwnerAnalyzerWidget->Analyzer->Queries[QueryId];

		if (ColumnName == SCollisionAnalyzer::IDColumnName)
		{	
			return	SNew(STextBlock)
					.Text( FText::AsNumber(QueryId) );
		}
		else if (ColumnName == SCollisionAnalyzer::FrameColumnName)
		{
			return	SNew(STextBlock)
					.Text( FText::AsNumber(Query.FrameNum) );
		}
		else if (ColumnName == SCollisionAnalyzer::TypeColumnName)
		{
			return	SNew(STextBlock)
					.Text(FText::FromString(SCollisionAnalyzer::QueryTypeToString(Query.Type)));
		}
		else if (ColumnName == SCollisionAnalyzer::ShapeColumnName)
		{
			// Leave shape string blank if this is a raycast, it doesn't matter
			FString ShapeString;
			if(Query.Type != ECAQueryType::Raycast)
			{
				ShapeString = SCollisionAnalyzer::QueryShapeToString(Query.Shape);
			}

			return	SNew(STextBlock)
					.Text(FText::FromString(ShapeString));
		}
		else if (ColumnName == SCollisionAnalyzer::ModeColumnName)
		{
			return	SNew(STextBlock)
					.Text(FText::FromString(SCollisionAnalyzer::QueryModeToString(Query.Mode)));
		}
		else if (ColumnName == SCollisionAnalyzer::TagColumnName)
		{
			return	SNew(STextBlock)
					.Text(FText::FromName(Query.Params.TraceTag));
		}
		else if (ColumnName == SCollisionAnalyzer::OwnerColumnName)
		{
			return	SNew(STextBlock)
					.Text(FText::FromName(Query.Params.OwnerTag));
		}
		else if (ColumnName == SCollisionAnalyzer::NumBlockColumnName)
		{
			FHitResult* FirstHit = FHitResult::GetFirstBlockingHit(Query.Results);
			bool bStartPenetrating = (FirstHit != NULL) && FirstHit->bStartPenetrating;
			// Draw number in red if we start penetrating
			return	SNew(STextBlock)
					.Text(FText::AsNumber(FHitResult::GetNumBlockingHits(Query.Results)))
					.ColorAndOpacity(bStartPenetrating ? FLinearColor(1.f,0.25f,0.25f) : FSlateColor::UseForeground() );
		}
		else if (ColumnName == SCollisionAnalyzer::NumTouchColumnName)
		{
			return	SNew(STextBlock)
					.Text(FText::AsNumber(FHitResult::GetNumOverlapHits(Query.Results)));
		}
		else if (ColumnName == SCollisionAnalyzer::TimeColumnName)
		{
			return	SNew(STextBlock)
					.Text(FText::FromString(FString::Printf(TEXT("%.3f"), Query.CPUTime)));
		}
	}

	return SNullWidget::NullWidget;
}
Beispiel #19
0
void FSourceControlModule::ShowLoginDialog(const FSourceControlLoginClosed& InOnSourceControlLoginClosed, ELoginWindowMode::Type InLoginWindowMode, EOnLoginWindowStartup::Type InOnLoginWindowStartup)
{
#if SOURCE_CONTROL_WITH_SLATE
	// Get Active Provider Name
	ActiveProviderName = GetProvider().GetName().ToString();

	// if we are showing a modal version of the dialog & a modeless version already exists, we must destroy the modeless dialog first
	if(InLoginWindowMode == ELoginWindowMode::Modal && SourceControlLoginPtr.IsValid())
	{
		// unhook the delegate so it doesn't fire in this case
		SourceControlLoginWindowPtr->SetOnWindowClosed(FOnWindowClosed());
		SourceControlLoginWindowPtr->RequestDestroyWindow();
		SourceControlLoginWindowPtr = NULL;
		SourceControlLoginPtr = NULL;
	}

	if(SourceControlLoginWindowPtr.IsValid())
	{
		SourceControlLoginWindowPtr->BringToFront();
	}
	else
	{
		// set provider to 'none'.
		// When we open the window, we turn off the fact that source control is available, this solves issues that are present with
		// being a three state modeless system (Accepted settings, disabled, and not yet decided).
		if(InOnLoginWindowStartup == EOnLoginWindowStartup::ResetProviderToNone)
		{
			SetProvider("None");
		}

		// temporarily disable access to source control features
		bTemporarilyDisabled = true;

		// Create the window
		SourceControlLoginWindowPtr = SNew(SWindow)
			.Title( LOCTEXT("SourceControlLoginTitle", "Source Control Login") )
			.HasCloseButton(false)
			.SupportsMaximize(false) 
			.SupportsMinimize(false)
			.SizingRule( ESizingRule::Autosized );

		// Set the closed callback
		SourceControlLoginWindowPtr->SetOnWindowClosed(FOnWindowClosed::CreateRaw(this, &FSourceControlModule::OnSourceControlDialogClosed));

		// Setup the content for the created login window.
		SourceControlLoginWindowPtr->SetContent(
			SNew(SBox)
			.WidthOverride(700.0f)
			[
				SAssignNew(SourceControlLoginPtr, SSourceControlLogin)
				.ParentWindow(SourceControlLoginWindowPtr)
				.OnSourceControlLoginClosed(InOnSourceControlLoginClosed)
			]
			);

		TSharedPtr<SWindow> RootWindow = FGlobalTabmanager::Get()->GetRootWindow();
		if(RootWindow.IsValid())
		{
			if(InLoginWindowMode == ELoginWindowMode::Modal)
			{
				FSlateApplication::Get().AddModalWindow(SourceControlLoginWindowPtr.ToSharedRef(), RootWindow);
			}
			else
			{
				FSlateApplication::Get().AddWindowAsNativeChild(SourceControlLoginWindowPtr.ToSharedRef(), RootWindow.ToSharedRef());
			}
		}
		else
		{
			if(InLoginWindowMode == ELoginWindowMode::Modal)
			{
				FSlateApplication::Get().AddModalWindow(SourceControlLoginWindowPtr.ToSharedRef(), RootWindow);
			}
			else
			{
				FSlateApplication::Get().AddWindow(SourceControlLoginWindowPtr.ToSharedRef());
			}
		}
	}
#else
	STUBBED("FSourceControlModule::ShowLoginDialog - no Slate");
#endif // SOURCE_CONTROL_WITH_SLATE
}
void SPhATPreviewViewportToolBar::Construct(const FArguments& InArgs, TSharedPtr<class SEditorViewport> InRealViewport)
{
	PhATPtr = InArgs._PhATPtr;
	
	static const FName DefaultForegroundName("DefaultForeground");

	this->ChildSlot
	[
		SNew(SBorder)
		.BorderImage(FEditorStyle::GetBrush("NoBorder"))
		// Color and opacity is changed based on whether or not the mouse cursor is hovering over the toolbar area
		.ColorAndOpacity(this, &SViewportToolBar::OnGetColorAndOpacity)
		.ForegroundColor( FEditorStyle::GetSlateColor(DefaultForegroundName) )
		[
			SNew(SHorizontalBox)

			// Camera Type (Perspective/Top/etc...)
			+SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(2.0f, 2.0f)
			[
				SNew(SEditorViewportToolbarMenu)
				.ParentToolBar(SharedThis(this))
				.Label(this, &SPhATPreviewViewportToolBar::GetCameraMenuLabel)
				.LabelIcon(this, &SPhATPreviewViewportToolBar::GetCameraMenuLabelIcon)
				.OnGetMenuContent(this, &SPhATPreviewViewportToolBar::GeneratePerspectiveMenu)
			]

			// View menu (lit, unlit, etc...)
			+ SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(5.0f, 2.0f)
			[
				SNew(SEditorViewportViewMenu, InRealViewport.ToSharedRef(), SharedThis(this))
			]

			+SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(5.0f, 2.0f)
			[
				SNew(SEditorViewportToolbarMenu)
				.ParentToolBar(SharedThis(this))
				.Cursor(EMouseCursor::Default)
				.Label(NSLOCTEXT("PhAT", "ShowMenuTitle_Default", "Show"))
				.OnGetMenuContent(this, &SPhATPreviewViewportToolBar::GenerateShowMenu) 
			]

			+SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(5.0f, 2.0f)
			[
				SNew(SEditorViewportToolbarMenu)
				.ParentToolBar(SharedThis(this))
				.Cursor(EMouseCursor::Default)
				.Label(NSLOCTEXT("PhAT", "ModesMenuTitle_Default", "Modes"))
				.OnGetMenuContent(this, &SPhATPreviewViewportToolBar::GenerateModesMenu) 
			]

			+ SHorizontalBox::Slot()
			.Padding(3.0f, 1.0f)
			.HAlign(HAlign_Right)
			[
				SNew(STransformViewportToolBar)
				.Viewport(InRealViewport)
				.CommandList(InRealViewport->GetCommandList())
			]
		]
	];

	SViewportToolBar::Construct(SViewportToolBar::FArguments());
}
Beispiel #21
0
void UEdGraphSchema::GetContextMenuActions(const UEdGraph* CurrentGraph, const UEdGraphNode* InGraphNode, const UEdGraphPin* InGraphPin, class FMenuBuilder* MenuBuilder, bool bIsDebugging) const
{
#if WITH_EDITOR
	FGraphNodeContextMenuBuilder Context(CurrentGraph, InGraphNode, InGraphPin, MenuBuilder, bIsDebugging);

	if (Context.Node)
	{
		Context.Node->GetContextMenuActions(Context);
	}

	if (InGraphNode)
	{
		// Helper to do the node comment editing
		struct Local
		{
			// Called by the EditableText widget to get the current comment for the node
			static FString GetNodeComment(TWeakObjectPtr<UEdGraphNode> NodeWeakPtr)
			{
				if (UEdGraphNode* SelectedNode = NodeWeakPtr.Get())
				{
					return SelectedNode->NodeComment;
				}
				return FString();
			}

			// Called by the EditableText widget when the user types a new comment for the selected node
			static void OnNodeCommentTextCommitted(const FText& NewText, ETextCommit::Type /*CommitInfo*/, TWeakObjectPtr<UEdGraphNode> NodeWeakPtr)
			{
				// Apply the change to the selected actor
				UEdGraphNode* SelectedNode = NodeWeakPtr.Get();
				FString NewString = NewText.ToString();
				if (SelectedNode && !SelectedNode->NodeComment.Equals( NewString, ESearchCase::CaseSensitive ))
				{
					// send property changed events
					const FScopedTransaction Transaction( LOCTEXT("EditNodeComment", "Change Node Comment") );
					SelectedNode->Modify();
					UProperty* NodeCommentProperty = FindField<UProperty>(SelectedNode->GetClass(), "NodeComment");
					if(NodeCommentProperty != NULL)
					{
						SelectedNode->PreEditChange(NodeCommentProperty);

						SelectedNode->NodeComment = NewString;

						FPropertyChangedEvent NodeCommentPropertyChangedEvent(NodeCommentProperty);
						SelectedNode->PostEditChangeProperty(NodeCommentPropertyChangedEvent);
					}
				}

				FSlateApplication::Get().DismissAllMenus();
			}
		};

		if( !InGraphPin )
		{
			int32 SelectionCount = GetNodeSelectionCount(CurrentGraph);
		
			if( SelectionCount == 1 )
			{
				// Node comment area
				TSharedRef<SHorizontalBox> NodeCommentBox = SNew(SHorizontalBox);

				MenuBuilder->BeginSection("GraphNodeComment", LOCTEXT("NodeCommentMenuHeader", "Node Comment"));
				{
					MenuBuilder->AddWidget(NodeCommentBox, FText::GetEmpty() );
				}
				TWeakObjectPtr<UEdGraphNode> SelectedNodeWeakPtr = InGraphNode;

				FText NodeCommentText;
				if ( UEdGraphNode* SelectedNode = SelectedNodeWeakPtr.Get() )
				{
					NodeCommentText = FText::FromString( SelectedNode->NodeComment );
				}

			const FSlateBrush* NodeIcon = FCoreStyle::Get().GetDefaultBrush();//@TODO: FActorIconFinder::FindIconForActor(SelectedActors(0).Get());


				// Comment label
				NodeCommentBox->AddSlot()
				.VAlign(VAlign_Center)
				.FillWidth( 1.0f )
				[
					SNew(SMultiLineEditableTextBox)
					.Text( NodeCommentText )
					.ToolTipText(LOCTEXT("NodeComment_ToolTip", "Comment for this node"))
					.OnTextCommitted_Static(&Local::OnNodeCommentTextCommitted, SelectedNodeWeakPtr)
					.SelectAllTextWhenFocused( true )
					.RevertTextOnEscape( true )
					.ModiferKeyForNewLine( EModifierKey::Control )
				];
				MenuBuilder->EndSection();
			}
			else if( SelectionCount > 1 )
			{
				struct SCommentUtility
				{
					static void CreateComment(const UEdGraphSchema* Schema, UEdGraph* Graph)
					{
						if( Schema && Graph )
						{
							TSharedPtr<FEdGraphSchemaAction> Action = Schema->GetCreateCommentAction();

							if( Action.IsValid() )
							{
								Action->PerformAction(Graph, NULL, FVector2D());
							}
						}
					}
				};

				MenuBuilder->BeginSection("SchemaActionComment", LOCTEXT("MultiCommentHeader", "Comment Group"));
				MenuBuilder->AddMenuEntry(	LOCTEXT("MultiCommentDesc", "Create Comment from Selection"),
											LOCTEXT("CommentToolTip", "Create a resizable comment box around selection."),
											FSlateIcon(), 
											FUIAction( FExecuteAction::CreateStatic( SCommentUtility::CreateComment, this, const_cast<UEdGraph*>( CurrentGraph ))));
				MenuBuilder->EndSection();
			}
		}
	}
#endif
}
void STranslationWidgetPicker::Construct(const FArguments& InArgs)
{
	// Mimicking a toolbar button look

	// Icon for the picker widget button
	TSharedRef< SWidget > IconWidget =
		SNew(SImage)
		.Image(FEditorStyle::GetBrush("TranslationEditor.TranslationPicker"));

	// Style settings
	FName StyleSet = FEditorStyle::GetStyleSetName();
	FName StyleName = "Toolbar";

	FText ToolTip = LOCTEXT("TranslationPickerTooltip", "Open the Translation Picker");

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

		SNew(SHorizontalBox)

		+ 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
			]

			// Label text
			+ SVerticalBox::Slot().AutoHeight()
				.HAlign(HAlign_Center)	// Center the label text horizontally
				[
					SNew(STextBlock)
					.Text(LOCTEXT("TranslationPicker", "Translation Picker"))
					.TextStyle(FEditorStyle::Get(), FName("ToolBar.Label"))	// Smaller font for tool tip labels
					.ShadowOffset(FVector2D::UnitVector)
				]
		];

	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(FEditorStyle::Get(), "ToolBar.ToggleButton")

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

			// Pass along the block's tool-tip string
			.ToolTip(SNew(SToolTip).Text(ToolTip))
			[
				ButtonContent
			]

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


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

				.Padding(FEditorStyle::Get().GetMargin(CheckboxStyle))
		];
}
//Helper function so we can make neutral and reverse look the same as forward gears
void FVehicleTransmissionDataCustomization::CreateGearUIHelper(FDetailWidgetRow & GearsSetup, FText Label, TSharedRef<IPropertyHandle> GearHandle, EGearType GearType)
{
	uint32 NumChildren = 0;
	GearHandle->GetNumChildren(NumChildren);	//we use num of children to determine if we are dealing with a full gear that has ratio, down, up - or just a single value

	TSharedRef<SWidget> RatioWidget = (NumChildren > 1 ? GearHandle->GetChildHandle("Ratio")->CreatePropertyValueWidget() : GearHandle->CreatePropertyValueWidget());
	TSharedRef<SWidget> DownRatioWidget = (NumChildren > 1 ? GearHandle->GetChildHandle("DownRatio")->CreatePropertyValueWidget() : GearHandle->CreatePropertyValueWidget());
	TSharedRef<SWidget> UpRatioWidget = (NumChildren > 1 ? GearHandle->GetChildHandle("UpRatio")->CreatePropertyValueWidget() : GearHandle->CreatePropertyValueWidget());
	
	RatioWidget->SetEnabled(GearType != NeutralGear);
	switch (GearType)
	{
	case ForwardGear:
		{
			DownRatioWidget->SetEnabled(TAttribute<bool>(this, &FVehicleTransmissionDataCustomization::IsAutomaticEnabled));
			UpRatioWidget->SetEnabled(TAttribute<bool>(this, &FVehicleTransmissionDataCustomization::IsAutomaticEnabled));
			break;
		}
	case ReverseGear:
		{
			DownRatioWidget->SetEnabled(false);
			UpRatioWidget->SetEnabled(false);
			break;
		}
	case NeutralGear:
		{
			DownRatioWidget->SetEnabled(false);
			UpRatioWidget->SetEnabled(TAttribute<bool>(this, &FVehicleTransmissionDataCustomization::IsAutomaticEnabled));
			break;
		}
	}

	TSharedRef<SWidget> RemoveWidget = PropertyCustomizationHelpers::MakeDeleteButton(FSimpleDelegate::CreateSP(this, &FVehicleTransmissionDataCustomization::RemoveGear, GearHandle), LOCTEXT("RemoveGearToolTip", "Removes gear"));
	RemoveWidget->SetEnabled(NumChildren > 1);
	
	GearsSetup
	.NameContent()
	[
		SNew(STextBlock)
		.Text(Label)
		.Font(IDetailLayoutBuilder::GetDetailFont())
	]
	.ValueContent()
		.MaxDesiredWidth(GearColumnsWidth)
		.MinDesiredWidth(GearColumnsWidth)
		[
			SNew(SHorizontalBox)
			+ SHorizontalBox::Slot()
			.FillWidth(0.3333f)
			[
				RatioWidget
			]
			+ SHorizontalBox::Slot()
			.FillWidth(0.3333f)
			.Padding(4.f)
			[
				DownRatioWidget
			]

			+ SHorizontalBox::Slot()
			.FillWidth(0.3333f)
			.Padding(4.f)
			[
				UpRatioWidget
			]

			+ SHorizontalBox::Slot()
			.Padding(4.f)
			.AutoWidth()
			[
				RemoveWidget
			]
		];
}
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();
	}
}
Beispiel #25
0
void SAssetPicker::Construct( const FArguments& InArgs )
{
	BindCommands();

	OnAssetsActivated = InArgs._AssetPickerConfig.OnAssetsActivated;
	OnAssetSelected = InArgs._AssetPickerConfig.OnAssetSelected;
	OnAssetDoubleClicked = InArgs._AssetPickerConfig.OnAssetDoubleClicked;
	OnAssetEnterPressed = InArgs._AssetPickerConfig.OnAssetEnterPressed;
	bPendingFocusNextFrame = InArgs._AssetPickerConfig.bFocusSearchBoxWhenOpened;
	DefaultFilterMenuExpansion = InArgs._AssetPickerConfig.DefaultFilterMenuExpansion;
	SaveSettingsName = InArgs._AssetPickerConfig.SaveSettingsName;
	OnFolderEnteredDelegate = InArgs._AssetPickerConfig.OnFolderEntered;

	if ( InArgs._AssetPickerConfig.bFocusSearchBoxWhenOpened )
	{
		RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SAssetPicker::SetFocusPostConstruct ) );
	}

	for (auto DelegateIt = InArgs._AssetPickerConfig.GetCurrentSelectionDelegates.CreateConstIterator(); DelegateIt; ++DelegateIt)
	{
		if ((*DelegateIt) != NULL)
		{
			(**DelegateIt) = FGetCurrentSelectionDelegate::CreateSP(this, &SAssetPicker::GetCurrentSelection);
		}
	}

	for(auto DelegateIt = InArgs._AssetPickerConfig.SyncToAssetsDelegates.CreateConstIterator(); DelegateIt; ++DelegateIt)
	{
		if((*DelegateIt) != NULL)
		{
			(**DelegateIt) = FSyncToAssetsDelegate::CreateSP(this, &SAssetPicker::SyncToAssets);
		}
	}

	for (auto DelegateIt = InArgs._AssetPickerConfig.SetFilterDelegates.CreateConstIterator(); DelegateIt; ++DelegateIt)
	{
		if ((*DelegateIt) != NULL)
		{
			(**DelegateIt) = FSetARFilterDelegate::CreateSP(this, &SAssetPicker::SetNewBackendFilter);
		}
	}

	TSharedRef<SVerticalBox> VerticalBox = SNew(SVerticalBox);

	ChildSlot
	[
		VerticalBox
	];

	TAttribute< FText > HighlightText;
	EThumbnailLabel::Type ThumbnailLabel = InArgs._AssetPickerConfig.ThumbnailLabel;

	FrontendFilters = MakeShareable(new FAssetFilterCollectionType());

	// Search box
	if (!InArgs._AssetPickerConfig.bAutohideSearchBar)
	{
		TextFilter = MakeShareable( new FFrontendFilter_Text() );
		TextFilter->SetIncludeClassName(InArgs._AssetPickerConfig.Filter.ClassNames.Num() != 1);
		HighlightText = TAttribute< FText >( this, &SAssetPicker::GetHighlightedText );

		OtherDevelopersFilter = MakeShareable( new FFrontendFilter_ShowOtherDevelopers(nullptr) );
		FrontendFilters->Add( OtherDevelopersFilter );

		TSharedRef<SHorizontalBox> HorizontalBox = SNew(SHorizontalBox);

		if(InArgs._AssetPickerConfig.bAddFilterUI)
		{
			// Filter
			HorizontalBox->AddSlot()
			.AutoWidth()
			[
				SNew( SComboButton )
				.ComboButtonStyle( FEditorStyle::Get(), "ContentBrowser.Filters.Style" )
				.ForegroundColor(FLinearColor::White)
				.ToolTipText( LOCTEXT( "AddFilterToolTip", "Add an asset filter." ) )
				.OnGetMenuContent( this, &SAssetPicker::MakeAddFilterMenu )
				.HasDownArrow( true )
				.ContentPadding( FMargin( 1, 0 ) )
				.AddMetaData<FTagMetaData>(FTagMetaData(TEXT("ContentBrowserFiltersCombo")))
				.ButtonContent()
				[
					SNew( STextBlock )
					.TextStyle( FEditorStyle::Get(), "ContentBrowser.Filters.Text" )
					.Text( LOCTEXT( "Filters", "Filters" ) )
				]
			];
		}

		HorizontalBox->AddSlot()
		.FillWidth(1.0f)
		[
			SAssignNew( SearchBoxPtr, SAssetSearchBox )
			.HintText(NSLOCTEXT( "ContentBrowser", "SearchBoxHint", "Search Assets" ))
			.OnTextChanged( this, &SAssetPicker::OnSearchBoxChanged )
			.OnTextCommitted( this, &SAssetPicker::OnSearchBoxCommitted )
			.DelayChangeNotificationsWhileTyping( true )
		];

		HorizontalBox->AddSlot()
		.AutoWidth()
		[
			SNew( SCheckBox )
			.Style( FEditorStyle::Get(), "ToggleButtonCheckbox" )
			.ToolTipText( this, &SAssetPicker::GetShowOtherDevelopersToolTip )
			.OnCheckStateChanged( this, &SAssetPicker::HandleShowOtherDevelopersCheckStateChanged )
			.IsChecked( this, &SAssetPicker::GetShowOtherDevelopersCheckState )
			[
				SNew( SImage )
				.Image( FEditorStyle::GetBrush("ContentBrowser.ColumnViewDeveloperFolderIcon") )
			]
		];

		VerticalBox->AddSlot()
		.AutoHeight()
		.Padding( 0, 0, 0, 1 )
		[
			HorizontalBox
		];
	}

	// "None" button
	if (InArgs._AssetPickerConfig.bAllowNullSelection)
	{
		VerticalBox->AddSlot()
		.AutoHeight()
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
				.AutoHeight()
				[
					SNew(SButton)
						.ButtonStyle( FEditorStyle::Get(), "ContentBrowser.NoneButton" )
						.TextStyle( FEditorStyle::Get(), "ContentBrowser.NoneButtonText" )
						.Text( LOCTEXT("NoneButtonText", "( None )") )
						.ToolTipText( LOCTEXT("NoneButtonTooltip", "Clears the asset selection.") )
						.HAlign(HAlign_Center)
						.VAlign(VAlign_Center)
						.OnClicked(this, &SAssetPicker::OnNoneButtonClicked)
				]

			// Trailing separator
			+ SVerticalBox::Slot()
				.AutoHeight()
				.Padding(0, 0, 0, 4)
				[
					SNew(SSeparator)
						.Orientation(Orient_Horizontal)
				]
		];
	}

	// Asset view
	
	// Break up the incoming filter into a sources data and backend filter.
	CurrentSourcesData.PackagePaths = InArgs._AssetPickerConfig.Filter.PackagePaths;
	CurrentSourcesData.Collections = InArgs._AssetPickerConfig.Collections;
	CurrentBackendFilter = InArgs._AssetPickerConfig.Filter;
	CurrentBackendFilter.PackagePaths.Empty();

	if(InArgs._AssetPickerConfig.bAddFilterUI)
	{
		// Filters
		TArray<UClass*> FilterClassList;
		for(auto Iter = CurrentBackendFilter.ClassNames.CreateIterator(); Iter; ++Iter)
		{
			FName ClassName = (*Iter);
			UClass* FilterClass = FindObject<UClass>(ANY_PACKAGE, *ClassName.ToString());
			if(FilterClass)
			{
				FilterClassList.AddUnique(FilterClass);
			}
		}

		VerticalBox->AddSlot()
		.AutoHeight()
		[
			SAssignNew(FilterListPtr, SFilterList)
			.OnFilterChanged(this, &SAssetPicker::OnFilterChanged)
			.FrontendFilters(FrontendFilters)
			.InitialClassFilters(FilterClassList)
			.ExtraFrontendFilters(InArgs._AssetPickerConfig.ExtraFrontendFilters)
		];
	}

	VerticalBox->AddSlot()
	.FillHeight(1.f)
	[
		SAssignNew(AssetViewPtr, SAssetView)
		.SelectionMode( InArgs._AssetPickerConfig.SelectionMode )
		.OnShouldFilterAsset(InArgs._AssetPickerConfig.OnShouldFilterAsset)
		.OnAssetSelected(InArgs._AssetPickerConfig.OnAssetSelected)
		.OnAssetsActivated(this, &SAssetPicker::HandleAssetsActivated)
		.OnGetAssetContextMenu(InArgs._AssetPickerConfig.OnGetAssetContextMenu)
		.OnGetCustomAssetToolTip(InArgs._AssetPickerConfig.OnGetCustomAssetToolTip)
		.OnVisualizeAssetToolTip(InArgs._AssetPickerConfig.OnVisualizeAssetToolTip)
		.OnAssetToolTipClosing(InArgs._AssetPickerConfig.OnAssetToolTipClosing)
		.AreRealTimeThumbnailsAllowed(this, &SAssetPicker::IsHovered)
		.FrontendFilters(FrontendFilters)
		.InitialSourcesData(CurrentSourcesData)
		.InitialBackendFilter(CurrentBackendFilter)
		.InitialViewType(InArgs._AssetPickerConfig.InitialAssetViewType)
		.InitialAssetSelection(InArgs._AssetPickerConfig.InitialAssetSelection)
		.ThumbnailScale(InArgs._AssetPickerConfig.ThumbnailScale)
		.ShowBottomToolbar(InArgs._AssetPickerConfig.bShowBottomToolbar)
		.OnAssetTagWantsToBeDisplayed(InArgs._AssetPickerConfig.OnAssetTagWantsToBeDisplayed)
		.AllowDragging( InArgs._AssetPickerConfig.bAllowDragging )
		.CanShowClasses( InArgs._AssetPickerConfig.bCanShowClasses )
		.CanShowFolders( InArgs._AssetPickerConfig.bCanShowFolders )
		.FilterRecursivelyWithBackendFilter( false )
		.CanShowRealTimeThumbnails( InArgs._AssetPickerConfig.bCanShowRealTimeThumbnails )
		.CanShowDevelopersFolder( InArgs._AssetPickerConfig.bCanShowDevelopersFolder )
		.PreloadAssetsForContextMenu( InArgs._AssetPickerConfig.bPreloadAssetsForContextMenu )
		.HighlightedText( HighlightText )
		.ThumbnailLabel( ThumbnailLabel )
		.AssetShowWarningText( InArgs._AssetPickerConfig.AssetShowWarningText)
		.AllowFocusOnSync(false)	// Stop the asset view from stealing focus (we're in control of that)
		.OnPathSelected(this, &SAssetPicker::FolderEntered)
	];

	LoadSettings();

	AssetViewPtr->RequestSlowFullListRefresh();
}
TSharedRef<SWidget> FWorldBrowserModule::CreateWorldBrowser()
{
	return SNew(SWorldMainView);
}
TSharedRef<SWidget> UEditableTextBlockComponent::RebuildWidget()
{
	return SNew(SEditableTextBox);
}
TSharedRef<ITableRow> FLightmapCustomNodeBuilder::MakeLightMapListViewWidget(TSharedPtr<FLightmapItem> LightMapItem, const TSharedRef<STableViewBase>& OwnerTable)
{
	if ( !ensure(LightMapItem.IsValid()) )
	{
		return SNew( STableRow<TSharedPtr<FLightmapItem>>, OwnerTable );
	}

	const uint32 ThumbnailResolution = 64;
	const uint32 ThumbnailBoxPadding = 4;
	UObject* LightMapObject = FindObject<UObject>(NULL, *LightMapItem->ObjectPath);
	FAssetData LightMapAssetData(LightMapObject);

	FAssetThumbnailConfig ThumbnailConfig;
	ThumbnailConfig.bAllowFadeIn = true;

	return SNew( STableRow<TSharedPtr<FLightmapItem>>, OwnerTable )
		.Style(FEditorStyle::Get(), "ContentBrowser.AssetListView.TableRow")
		[
			SNew(SHorizontalBox)

			// Viewport
			+SHorizontalBox::Slot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			[
				SNew( SBox )
				.WidthOverride( ThumbnailResolution + ThumbnailBoxPadding * 2 )
				.HeightOverride( ThumbnailResolution + ThumbnailBoxPadding * 2 )
				[
					// Drop shadow border
					SNew(SBorder)
					.Padding(ThumbnailBoxPadding)
					.BorderImage( FEditorStyle::GetBrush("ContentBrowser.ThumbnailShadow") )
					[
						LightMapItem->Thumbnail->MakeThumbnailWidget(ThumbnailConfig)
					]
				]
			]

			+SHorizontalBox::Slot()
			.AutoWidth()
			.Padding(6, 0, 0, 0)
			.VAlign(VAlign_Center)
			[
				SNew(SVerticalBox)

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(0, 1)
				[
					SNew(STextBlock)
					.Font(FEditorStyle::GetFontStyle("ContentBrowser.AssetTileViewNameFont"))
					.Text( FText::FromName(LightMapAssetData.AssetName) )
				]

				+SVerticalBox::Slot()
				.AutoHeight()
				.Padding(0, 1)
				[
					// Class
					SNew(STextBlock)
					.Font(FEditorStyle::GetFontStyle("ContentBrowser.AssetListViewClassFont"))
					.Text(FText::FromName(LightMapAssetData.AssetClass))
				]
			]
		];
}
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 );

	AssetComboButton = SNew(SComboButton)
		.ToolTipText( this, &SPropertyEditorAsset::OnGetToolTip )
		.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( this, &SPropertyEditorAsset::OnGetToolTip )
				.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
		];
	}
}
TSharedPtr<SWidget> SAbilityEditorViewport::MakeViewportToolbar()
{
	return SNew(SAbilityEditorViewportToolBar, m_TabBodyPtr.Pin(), SharedThis(this))
		.Cursor(EMouseCursor::Default)
		.AbilityEditor(m_AbilityEditor.Pin());
}