EActiveTimerReturnType UpdateScrollerState(double InCurrentTime, float InDeltaTime) { if (ScrollerState == EScrollerState::Stop_Wait) { TimeElapsed = 0.0f; ScrollerState = EScrollerState::FadeOff; ScrollBox->SetScrollOffset(ScrollOffset); auto PinnedActiveTimerHandle = ActiveTimerHandle.Pin(); if (PinnedActiveTimerHandle.IsValid()) { UnRegisterActiveTimer(PinnedActiveTimerHandle.ToSharedRef()); } ActiveTimerHandle = RegisterActiveTimer(0, FWidgetActiveTimerDelegate::CreateSP(this, &SAutoTextScrollerImpl::UpdateScrollerState)); } else if (ScrollerState == EScrollerState::Start_Wait) { TimeElapsed = 0.0f; ScrollOffset = 0.0f; ScrollerState = EScrollerState::Scrolling; ScrollBox->SetScrollOffset(ScrollOffset); auto PinnedActiveTimerHandle = ActiveTimerHandle.Pin(); if (PinnedActiveTimerHandle.IsValid()) { UnRegisterActiveTimer(PinnedActiveTimerHandle.ToSharedRef()); } ActiveTimerHandle = RegisterActiveTimer(0, FWidgetActiveTimerDelegate::CreateSP(this, &SAutoTextScrollerImpl::UpdateScrollerState)); } return EActiveTimerReturnType::Continue; }
void SObjectNameEditableTextBox::OnNameTextCommitted(const FText& NewText, ETextCommit::Type InTextCommit) { // Don't apply the change if the TextCommit type is OnCleared - this will only be the case if the keyboard focus was cleared due to // Enter being pressed, in which case we will already have been here once with a TextCommit type of OnEnter. if (InTextCommit != ETextCommit::OnCleared) { FText TrimmedText = FText::TrimPrecedingAndTrailing(NewText); if (!TrimmedText.IsEmpty()) { if (Objects.Num() == 1) { // Apply the change to the selected actor AActor* Actor = Cast<AActor>(Objects[0].Get()); if(Actor != NULL) { const FScopedTransaction Transaction( LOCTEXT("RenameActorTransaction", "Rename Actor") ); if (Actor->IsActorLabelEditable()) { Actor->SetActorLabel(TrimmedText.ToString()); LastCommittedTime = FSlateApplication::Get().GetCurrentTime(); RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SObjectNameEditableTextBox::UpdateHighlightSpringState ) ); } } } else if (Objects.Num() > 1) { const FScopedTransaction Transaction( LOCTEXT("RenameActorsTransaction", "Rename Multiple Actors") ); UserSetCommonName = TrimmedText.ToString(); for (int32 i=0; i<Objects.Num(); i++) { // Apply the change to the selected actor if(Objects[i].IsValid() && Objects[i].Get()->IsA(AActor::StaticClass())) { AActor* Actor = (AActor*)Objects[i].Get(); if (Actor->IsActorLabelEditable()) { Actor->SetActorLabel(TrimmedText.ToString()); LastCommittedTime = FSlateApplication::Get().GetCurrentTime(); RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SObjectNameEditableTextBox::UpdateHighlightSpringState ) ); } } } } } // Remove ourselves from the window focus so we don't get automatically reselected when scrolling around the context menu. TSharedPtr< SWindow > ParentWindow = FSlateApplication::Get().FindWidgetWindow( SharedThis(this) ); if( ParentWindow.IsValid() ) { ParentWindow->SetWidgetToFocusOnActivate( NULL ); } } // Clear Error TextBox->SetError(FText::GetEmpty()); }
FReply SInlineEditableTextBlock::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if( !MouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton) || MouseEvent.IsControlDown() || MouseEvent.IsShiftDown()) { return FReply::Unhandled(); } if(IsSelected.IsBound()) { if(IsSelected.Execute() && !bIsReadOnly.Get() && !ActiveTimerHandle.IsValid()) { RegisterActiveTimer(0.5f, FWidgetActiveTimerDelegate::CreateSP(this, &SInlineEditableTextBlock::TriggerEditMode)); } } else { // The widget is not managed by another widget, so handle the mouse input and enter edit mode if ready. if(HasKeyboardFocus()) { EnterEditingMode(); } return FReply::Handled(); } // Do not handle the mouse input, this will allow for drag and dropping events to trigger. return FReply::Unhandled(); }
void SCreditsScreen::Construct(const FArguments& InArgs) { PreviousScrollPosition = 0.0f; ScrollPixelsPerSecond = 50.0f; bIsPlaying = true; ActiveTimerHandle = RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SCreditsScreen::RollCredits ) ); const FString Version = FEngineVersion::Current().ToString(FEngineBuildSettings::IsPerforceBuild() ? EVersionComponent::Branch : EVersionComponent::Patch); FString CreditsText; FFileHelper::LoadFileToString(CreditsText, *( FPaths::EngineContentDir() + TEXT("Editor/Credits.rt") )); CreditsText.ReplaceInline(TEXT("%VERSION%"), *Version); ChildSlot [ SNew(SOverlay) + SOverlay::Slot() [ SAssignNew(ScrollBox, SScrollBox) .Style( FEditorStyle::Get(), "ScrollBox" ) .OnUserScrolled(this, &SCreditsScreen::HandleUserScrolled) + SScrollBox::Slot() [ SNew(SVerticalBox) + SVerticalBox::Slot() .FillHeight(1.0f) [ SNew(SRichTextBlock) .Text(FText::FromString(CreditsText)) .TextStyle(FEditorStyle::Get(), "Credits.Normal") .DecoratorStyleSet(&FEditorStyle::Get()) .Justification(ETextJustify::Center) + SRichTextBlock::HyperlinkDecorator(TEXT("browser"), this, &SCreditsScreen::OnBrowserLinkClicked) ] ] ] + SOverlay::Slot() .VAlign(VAlign_Bottom) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() [ SNew(SButton) .ButtonStyle(FEditorStyle::Get(), "Credits.Button") .OnClicked(this, &SCreditsScreen::HandleTogglePlayPause) [ SNew(SImage) .Image(this, &SCreditsScreen::GetTogglePlayPauseBrush) ] ] ] ]; }
FReply STutorialButton::HandleButtonClicked() { if (bPendingClickAction) { //There's already a click pending return FReply::Handled(); } RefreshStatus(); if (FEngineAnalytics::IsAvailable()) { TArray<FAnalyticsEventAttribute> EventAttributes; EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Context"), Context.ToString())); EventAttributes.Add(FAnalyticsEventAttribute(TEXT("TimeSinceAlertStarted"), (AlertStartTime != 0.0f && ShouldShowAlert()) ? (FPlatformTime::Seconds() - AlertStartTime) : -1.0f)); EventAttributes.Add(FAnalyticsEventAttribute(TEXT("LaunchedBrowser"), ShouldLaunchBrowser())); FEngineAnalytics::GetProvider().RecordEvent(TEXT("Rocket.Tutorials.ClickedContextButton"), EventAttributes); } bPendingClickAction = true; RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &STutorialButton::HandleButtonClicked_AssetRegistryChecker)); FIntroTutorials& IntroTutorials = FModuleManager::GetModuleChecked<FIntroTutorials>(TEXT("IntroTutorials")); IntroTutorials.AttachWidget(LoadingWidget); return FReply::Handled(); }
void STutorialButton::Construct(const FArguments& InArgs) { Context = InArgs._Context; ContextWindow = InArgs._ContextWindow; bTestAlerts = FParse::Param(FCommandLine::Get(), TEXT("TestTutorialAlerts")); bPendingClickAction = false; bTutorialAvailable = false; bTutorialCompleted = false; bTutorialDismissed = false; AlertStartTime = 0.0f; PulseAnimation.AddCurve(0.0f, TutorialButtonConstants::PulseAnimationLength, ECurveEaseFunction::Linear); RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &STutorialButton::OpenTutorialPostConstruct ) ); IIntroTutorials& IntroTutorials = FModuleManager::LoadModuleChecked<IIntroTutorials>(TEXT("IntroTutorials")); LoadingWidget = IntroTutorials.CreateTutorialsLoadingWidget(ContextWindow); ChildSlot [ SNew(SButton) .AddMetaData<FTagMetaData>(*FString::Printf(TEXT("%s.TutorialLaunchButton"), *Context.ToString())) .ButtonStyle(FEditorStyle::Get(), "TutorialLaunch.Button") .ToolTipText(this, &STutorialButton::GetButtonToolTip) .OnClicked(this, &STutorialButton::HandleButtonClicked) .ContentPadding(0.0f) [ SNew(SBox) .WidthOverride(16) .HeightOverride(16) ] ]; }
FReply STableViewBase::OnTouchMoved( const FGeometry& MyGeometry, const FPointerEvent& InTouchEvent ) { if (bStartedTouchInteraction) { const float ScrollByAmount = InTouchEvent.GetCursorDelta().Y / MyGeometry.Scale; AmountScrolledWhileRightMouseDown += FMath::Abs( ScrollByAmount ); TickScrollDelta -= ScrollByAmount; if (AmountScrolledWhileRightMouseDown > FSlateApplication::Get().GetDragTriggerDistance()) { // Make sure the active timer is registered to update the inertial scroll if ( !bIsScrollingActiveTimerRegistered ) { bIsScrollingActiveTimerRegistered = true; RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &STableViewBase::UpdateInertialScroll)); } const float AmountScrolled = this->ScrollBy( MyGeometry, -ScrollByAmount, EAllowOverscroll::Yes ); // The user has moved the list some amount; they are probably // trying to scroll. From now on, the list assumes the user is scrolling // until they lift their finger. return FReply::Handled().CaptureMouse( AsShared() ); } return FReply::Handled(); } else { return FReply::Handled(); } }
void SEditorViewport::Construct( const FArguments& InArgs ) { ChildSlot [ SAssignNew( ViewportWidget, SViewport ) .ShowEffectWhenDisabled( false ) .EnableGammaCorrection( false ) // Scene rendering handles this .AddMetaData(InArgs.MetaData.Num() > 0 ? InArgs.MetaData[0] : MakeShareable(new FTagMetaData(TEXT("LevelEditorViewport")))) [ SAssignNew( ViewportOverlay, SOverlay ) +SOverlay::Slot() [ SNew( SBorder ) .BorderImage( this, &SEditorViewport::OnGetViewportBorderBrush ) .BorderBackgroundColor( this, &SEditorViewport::OnGetViewportBorderColorAndOpacity ) .Visibility( this, &SEditorViewport::OnGetViewportContentVisibility ) .Padding(0.0f) .ShowEffectWhenDisabled( false ) ] ] ]; TSharedRef<FEditorViewportClient> ViewportClient = MakeEditorViewportClient(); if (!ViewportClient->VisibilityDelegate.IsBound()) { ViewportClient->VisibilityDelegate.BindSP(this, &SEditorViewport::IsVisible); } SceneViewport = MakeShareable( new FSceneViewport( &ViewportClient.Get(), ViewportWidget ) ); ViewportClient->Viewport = SceneViewport.Get(); ViewportWidget->SetViewportInterface(SceneViewport.ToSharedRef()); Client = ViewportClient; if ( Client->IsRealtime() ) { ActiveTimerHandle = RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SEditorViewport::EnsureTick ) ); } CommandList = MakeShareable( new FUICommandList ); // Ensure the commands are registered FEditorViewportCommands::Register(); BindCommands(); TSharedPtr<SWidget> ViewportToolbar = MakeViewportToolbar(); if( ViewportToolbar.IsValid() ) { ViewportOverlay->AddSlot() .VAlign(VAlign_Top) [ ViewportToolbar.ToSharedRef() ]; } PopulateViewportOverlays(ViewportOverlay.ToSharedRef()); }
void SPropertyTableCell::EnteredEditMode() { if (Cell->IsValid()) { // We delay the activation of editing mode till Tick due to mouse related input replies stomping on the focus RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &SPropertyTableCell::TriggerEnterEditingMode)); } }
//------------------------------------------------------------------------------ void SBlueprintSubPalette::RequestRefreshActionsList() { if (!bIsActiveTimerRegistered) { bIsActiveTimerRegistered = true; RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &SBlueprintSubPalette::TriggerRefreshActionsList)); } }
void SEditorViewport::Invalidate() { bInvalidated = true; if (!ActiveTimerHandle.IsValid()) { ActiveTimerHandle = RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &SEditorViewport::EnsureTick)); } }
void SPluginList::SetNeedsRefresh() { if (!bIsActiveTimerRegistered) { bIsActiveTimerRegistered = true; RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &SPluginList::TriggerListRebuild)); } }
void STableViewBase::RequestListRefresh() { if (!bItemsNeedRefresh) { bItemsNeedRefresh = true; RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &STableViewBase::EnsureTickToRefresh)); } ItemsPanel->SetRefreshPending(true); }
void SAnimCompositeEditor::PostUndo() { if (!bIsActiveTimerRegistered) { bIsActiveTimerRegistered = true; RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &SAnimCompositeEditor::TriggerRebuildPanel)); } // when undo or redo happens, we still have to recalculate length, so we can't rely on sequence length changes or not if (CompositeObj->SequenceLength) { CompositeObj->SequenceLength = 0.f; } }
void SProgressBar::SetActiveTimerTickRate(float TickRate) { if (CurrentTickRate != TickRate || !ActiveTimerHandle.IsValid()) { CurrentTickRate = TickRate; TSharedPtr<FActiveTimerHandle> SharedActiveTimerHandle = ActiveTimerHandle.Pin(); if (SharedActiveTimerHandle.IsValid()) { UnRegisterActiveTimer(SharedActiveTimerHandle.ToSharedRef()); } ActiveTimerHandle = RegisterActiveTimer(TickRate, FWidgetActiveTimerDelegate::CreateSP(this, &SProgressBar::ActiveTick)); } }
FReply STableViewBase::OnMouseMove( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if( MouseEvent.IsMouseButtonDown( EKeys::RightMouseButton ) ) { const float ScrollByAmount = MouseEvent.GetCursorDelta().Y / MyGeometry.Scale; // If scrolling with the right mouse button, we need to remember how much we scrolled. // If we did not scroll at all, we will bring up the context menu when the mouse is released. AmountScrolledWhileRightMouseDown += FMath::Abs( ScrollByAmount ); // Has the mouse moved far enough with the right mouse button held down to start capturing // the mouse and dragging the view? if( IsRightClickScrolling() ) { // Make sure the active timer is registered to update the inertial scroll if (!bIsScrollingActiveTimerRegistered) { bIsScrollingActiveTimerRegistered = true; RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &STableViewBase::UpdateInertialScroll)); } TickScrollDelta -= ScrollByAmount; const float AmountScrolled = this->ScrollBy( MyGeometry, -ScrollByAmount, AllowOverscroll ); FReply Reply = FReply::Handled(); // The mouse moved enough that we're now dragging the view. Capture the mouse // so the user does not have to stay within the bounds of the list while dragging. if(this->HasMouseCapture() == false) { Reply.CaptureMouse( AsShared() ).UseHighPrecisionMouseMovement( AsShared() ); SoftwareCursorPosition = MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ); bShowSoftwareCursor = true; } // Check if the mouse has moved. if( AmountScrolled != 0 ) { SoftwareCursorPosition.Y += ScrollByAmount; } return Reply; } } return FReply::Unhandled(); }
void SEditorViewport::OnToggleRealtime() { if (Client->IsRealtime()) { Client->SetRealtime( false ); if ( ActiveTimerHandle.IsValid() ) { UnRegisterActiveTimer( ActiveTimerHandle.Pin().ToSharedRef() ); } } else { Client->SetRealtime( true ); ActiveTimerHandle = RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SEditorViewport::EnsureTick ) ); } }
void SAnimCompositeEditor::OnCompositeChange(class UObject *EditorAnimBaseObj, bool bRebuild) { if ( CompositeObj != nullptr ) { if(bRebuild && !bIsActiveTimerRegistered) { // sometimes crashes because the timer delay but animation still renders, so invalidating here before calling timer CompositeObj->InvalidateRecursiveAsset(); bIsActiveTimerRegistered = true; RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &SAnimCompositeEditor::TriggerRebuildPanel)); } else { CollapseComposite(); } CompositeObj->MarkPackageDirty(); } }
FReply SCreditsScreen::HandleTogglePlayPause() { if ( bIsPlaying ) { bIsPlaying = false; if ( ActiveTimerHandle.IsValid() ) { UnRegisterActiveTimer( ActiveTimerHandle.Pin().ToSharedRef() ); } } else { bIsPlaying = true; if ( !ActiveTimerHandle.IsValid() ) { ActiveTimerHandle = RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SCreditsScreen::RollCredits ) ); } } return FReply::Handled(); }
void SProgressBar::Construct( const FArguments& InArgs ) { check(InArgs._Style); MarqueeOffset = 0.0f; Style = InArgs._Style; SetPercent(InArgs._Percent); BarFillType = InArgs._BarFillType; BackgroundImage = InArgs._BackgroundImage; FillImage = InArgs._FillImage; MarqueeImage = InArgs._MarqueeImage; FillColorAndOpacity = InArgs._FillColorAndOpacity; BorderPadding = InArgs._BorderPadding; CurrentTickRate = 0.0f; MinimumTickRate = InArgs._RefreshRate; ActiveTimerHandle = RegisterActiveTimer(CurrentTickRate, FWidgetActiveTimerDelegate::CreateSP(this, &SProgressBar::ActiveTick)); }
void SEditorViewport::OnToggleStats() { bool bIsEnabled = Client->ShouldShowStats(); Client->SetShowStats( !bIsEnabled ); if( !bIsEnabled ) { // We cannot show stats unless realtime rendering is enabled if ( !Client->IsRealtime() ) { Client->SetRealtime( true ); ActiveTimerHandle = RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SEditorViewport::EnsureTick ) ); } // let the user know how they can enable stats via the console FNotificationInfo Info(LOCTEXT("StatsEnableHint", "Stats display can be toggled via the STAT [type] console command")); Info.ExpireDuration = 3.0f; /* Temporarily remove the link until the page is updated Info.HyperlinkText = LOCTEXT("StatsEnableHyperlink", "Learn more"); Info.Hyperlink = FSimpleDelegate::CreateStatic([](){ IDocumentation::Get()->Open(TEXT("Engine/Basics/ConsoleCommands#statisticscommands")); }); */ FSlateNotificationManager::Get().AddNotification(Info); } }
void SAuthorizingPlugin::Construct(const FArguments& InArgs, const TSharedRef<SWindow>& InParentWindow, const FText& InPluginFriendlyName, const FString& InPluginItemId, const FString& InPluginOfferId, TFunction<void()> InAuthorizedCallback) { CurrentState = EPluginAuthorizationState::Initializing; WaitingTime = 0; ParentWindow = InParentWindow; PluginFriendlyName = InPluginFriendlyName; PluginItemId = InPluginItemId; PluginOfferId = InPluginOfferId; AuthorizedCallback = InAuthorizedCallback; InParentWindow->SetOnWindowClosed(FOnWindowClosed::CreateSP(this, &SAuthorizingPlugin::OnWindowClosed)); bUserInterrupted = true; RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &SAuthorizingPlugin::RefreshStatus)); ChildSlot [ SNew(SBox) .MinDesiredWidth(500) [ SNew(SBorder) .BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) [ SNew(SVerticalBox) + SVerticalBox::Slot() .FillHeight(1.0f) .Padding(10, 30, 10, 20) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) [ SNew(SThrobber) ] + SHorizontalBox::Slot() .AutoWidth() .VAlign(VAlign_Center) .Padding(10, 0) [ SNew(STextBlock) .Text(this, &SAuthorizingPlugin::GetWaitingText) .Font(FSlateFontInfo(FPaths::EngineContentDir() / TEXT("Slate/Fonts/Roboto-Bold.ttf"), 12)) ] ] + SVerticalBox::Slot() .AutoHeight() .HAlign(HAlign_Right) .Padding(10) [ SNew(SButton) .Text(LOCTEXT("CancelText", "Cancel")) .OnClicked(this, &SAuthorizingPlugin::OnCancel) ] ] ] ]; TSharedRef<IPortalServiceLocator> ServiceLocator = GEditor->GetServiceLocator(); PortalWindowService = ServiceLocator->GetServiceRef<IPortalApplicationWindow>(); PortalUserService = ServiceLocator->GetServiceRef<IPortalUser>(); PortalUserLoginService = ServiceLocator->GetServiceRef<IPortalUserLogin>(); }
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(); }
virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override { const float ContentSize = ScrollBox->GetDesiredSize().X; const float Speed = 20.0f; const float StartDelay = 2.0f; const float EndDelay = 2.0f; const float FadeOnDelay = 0.5f; const float FadeOffDelay = 0.5f; TimeElapsed += InDeltaTime; switch (ScrollerState) { case EScrollerState::FadeOn: { FontAlpha = TimeElapsed / FadeOnDelay; if (TimeElapsed >= FadeOnDelay) { FontAlpha = 1.0f; TimeElapsed = 0.0f; ScrollOffset = 0.0f; ScrollerState = EScrollerState::Start; } }break; case EScrollerState::Start: { // Unregister Tick Delegate auto PinnedActiveTimerHandle = ActiveTimerHandle.Pin(); if (PinnedActiveTimerHandle.IsValid()) { UnRegisterActiveTimer(PinnedActiveTimerHandle.ToSharedRef()); } // Check to see if we need to scroll if (ExternalScrollbar->DistanceFromBottom() == 0.0f && ExternalScrollbar->DistanceFromTop() == 0.0f) { // Don't run auto scrolling if text already fits. break; } else { ActiveTimerHandle = RegisterActiveTimer(StartDelay, FWidgetActiveTimerDelegate::CreateSP(this, &SAutoTextScrollerImpl::UpdateScrollerState)); ScrollerState = EScrollerState::Start_Wait; } }break; case EScrollerState::Start_Wait: break; case EScrollerState::Scrolling: { ScrollOffset += Speed * InDeltaTime; if (ExternalScrollbar->DistanceFromBottom()==0.0f) { ScrollOffset = ContentSize; TimeElapsed = 0.0f; ScrollerState = EScrollerState::Stop; } }break; case EScrollerState::Stop: { // Unregister Tick Delegate auto PinnedActiveTimerHandle = ActiveTimerHandle.Pin(); if (PinnedActiveTimerHandle.IsValid()) { UnRegisterActiveTimer(PinnedActiveTimerHandle.ToSharedRef()); } // Check to see if we need to scroll if (ExternalScrollbar->DistanceFromBottom() == 0.0f && ExternalScrollbar->DistanceFromTop() == 0.0f) { // Don't run auto scrolling if text already fits. break; } else { ActiveTimerHandle = RegisterActiveTimer(EndDelay, FWidgetActiveTimerDelegate::CreateSP(this, &SAutoTextScrollerImpl::UpdateScrollerState)); ScrollerState = EScrollerState::Stop_Wait; } }break; case EScrollerState::Stop_Wait: break; case EScrollerState::FadeOff: { FontAlpha = 1.0f - TimeElapsed / FadeOffDelay; if (TimeElapsed >= FadeOffDelay) { FontAlpha = 0.0f; TimeElapsed = 0.0f; ScrollOffset = 0.0f; ScrollerState = EScrollerState::FadeOn; } }break; }; ScrollBox->SetScrollOffset(ScrollOffset); }
/** Construct this widget */ void Construct( const FArguments& InArgs ) { OnCancelClickedDelegate = InArgs._OnCancelClickedDelegate; WeakStack = InArgs._ScopeStack; // This is a temporary widget that needs to be updated over its entire lifespan => has an active timer registered for its entire lifespan RegisterActiveTimer( 0.f, FWidgetActiveTimerDelegate::CreateSP( this, &SSlowTaskWidget::UpdateProgress ) ); TSharedRef<SVerticalBox> VerticalBox = SNew(SVerticalBox) // Construct the main progress bar and text + SVerticalBox::Slot() .AutoHeight() [ SNew(SVerticalBox) + SVerticalBox::Slot() .AutoHeight() .Padding(FMargin(0, 0, 0, 5.f)) .VAlign(VAlign_Center) [ SNew(SBox) .HeightOverride(24.f) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() [ SNew( STextBlock ) .AutoWrapText(true) .Text( this, &SSlowTaskWidget::GetProgressText, 0 ) // The main font size dynamically changes depending on the content .Font( this, &SSlowTaskWidget::GetMainTextFont ) ] + SHorizontalBox::Slot() .Padding(FMargin(5.f, 0, 0, 0)) .AutoWidth() [ SNew( STextBlock ) .Text( this, &SSlowTaskWidget::GetPercentageText ) // The main font size dynamically changes depending on the content .Font( FSlateFontInfo( FPaths::EngineContentDir() / TEXT("Slate/Fonts/Roboto-Light.ttf"), 14, EFontHinting::AutoLight ) ) ] ] ] + SVerticalBox::Slot() .AutoHeight() [ SNew(SBox) .HeightOverride(MainBarHeight) [ SNew(SProgressBar) .BorderPadding(FVector2D::ZeroVector) .Percent( this, &SSlowTaskWidget::GetProgressFraction, 0 ) .BackgroundImage( FEditorStyle::GetBrush("ProgressBar.ThinBackground") ) .FillImage( FEditorStyle::GetBrush("ProgressBar.ThinFill") ) ] ] ] // Secondary progress bars + SVerticalBox::Slot() .Padding(FMargin(0.f, 8.f, 0.f, 0.f)) [ SAssignNew(SecondaryBars, SVerticalBox) ]; if ( OnCancelClickedDelegate.IsBound() ) { VerticalBox->AddSlot() .AutoHeight() .HAlign(HAlign_Center) .Padding(10.0f, 7.0f) [ SNew(SButton) .Text( NSLOCTEXT("FeedbackContextProgress", "Cancel", "Cancel") ) .HAlign(EHorizontalAlignment::HAlign_Center) .OnClicked(this, &SSlowTaskWidget::OnCancel) ]; } SBorder::Construct( SBorder::FArguments() .BorderImage(FEditorStyle::GetBrush("Menu.Background")) .VAlign(VAlign_Center) .Padding(FMargin(FixedPaddingH)) [ SNew(SBox).WidthOverride(FixedWidth) [ VerticalBox ] ] ); // Make sure all our bars are set up UpdateDynamicProgressBars(); }