void FMarginStructCustomization::OnValueCommitted( float NewValue, ETextCommit::Type CommitType, int32 PropertyIndex ) { TWeakPtr<IPropertyHandle> WeakHandlePtr = ChildPropertyHandles[ PropertyIndex ]; WeakHandlePtr.Pin()->SetValue( NewValue ); }
void FDestructibleMeshEditorViewportClient::ImportFBXChunks() { // Get the FBX that we want to import TArray<FString> OpenFilenames; IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); bool bOpened = false; if (DesktopPlatform != NULL) { bOpened = DesktopPlatform->OpenFileDialog( NULL, NSLOCTEXT("UnrealEd", "ImportMatineeSequence", "Import UnrealMatinee Sequence").ToString(), *(FEditorDirectories::Get().GetLastDirectory(ELastDirectory::GENERIC_IMPORT)), TEXT(""), TEXT("FBX document|*.fbx"), EFileDialogFlags::None, OpenFilenames); } if (bOpened) { // Get the filename from dialog FString ImportFilename = OpenFilenames[0]; FString FileName = OpenFilenames[0]; FEditorDirectories::Get().SetLastDirectory(ELastDirectory::GENERIC_IMPORT, FPaths::GetPath(FileName)); // Save path as default for next time. const FString FileExtension = FPaths::GetExtension(FileName); const bool bIsFBX = FCString::Stricmp(*FileExtension, TEXT("FBX")) == 0; if (bIsFBX) { FlushRenderingCommands(); UnFbx::FFbxImporter* FFbxImporter = UnFbx::FFbxImporter::GetInstance(); if (FFbxImporter->ImportFromFile( *ImportFilename, FPaths::GetExtension( ImportFilename ) ) ) { TArray<FbxNode*> FbxMeshArray; FFbxImporter->FillFbxMeshArray(FFbxImporter->Scene->GetRootNode(), FbxMeshArray, FFbxImporter); UFbxStaticMeshImportData* ImportData = NewObject<UFbxStaticMeshImportData>(GetTransientPackage(), NAME_None, RF_NoFlags, NULL); TArray<UStaticMesh*> ChunkMeshes; for (int32 i=0; i < FbxMeshArray.Num(); ++i) { UStaticMesh* TempStaticMesh = NULL; TempStaticMesh = (UStaticMesh*)FFbxImporter->ImportStaticMesh(GetTransientPackage(), FbxMeshArray[i], NAME_None, RF_NoFlags, ImportData, 0); ChunkMeshes.Add(TempStaticMesh); } UDestructibleMesh* DestructibleMesh = DestructibleMeshEditorPtr.Pin()->GetDestructibleMesh(); if (DestructibleMesh) { DestructibleMesh->SetupChunksFromStaticMeshes(ChunkMeshes); } } FFbxImporter->ReleaseScene(); // Update the viewport DestructibleMeshEditorPtr.Pin()->RefreshTool(); DestructibleMeshEditorPtr.Pin()->SetCurrentPreviewDepth(0xFFFFFFFF); // This will get clamped to the max depth } else { // Invalid filename } } #if WITH_APEX #endif // WITH_APEX }
FText FActorInfoColumn::GetTextForItem( TWeakPtr<ITreeItem> TreeItem ) const { auto Item = TreeItem.Pin(); return Item.IsValid() ? FText::FromString(Item->Get(FGetInfo(CurrentMode))) : FText::GetEmpty(); }
static void FillFileMenu( FMenuBuilder& MenuBuilder, TWeakPtr< FAssetEditorToolkit > AssetEditorToolkitWeak ) { auto AssetEditorToolkit( AssetEditorToolkitWeak.Pin().ToSharedRef() ); AssetEditorToolkit->FillDefaultFileMenuCommands( MenuBuilder ); }
/** * Perform an editor build with behavior dependent upon the specified id * * @param Id Action Id specifying what kind of build is requested * * @return true if the build completed successfully; false if it did not (or was manually canceled) */ bool FEditorBuildUtils::EditorBuild( UWorld* InWorld, EBuildOptions::Type Id, const bool bAllowLightingDialog ) { FMessageLog("MapCheck").NewPage(LOCTEXT("MapCheckNewPage", "Map Check")); // Make sure to set this flag to false before ALL builds. GEditor->SetMapBuildCancelled( false ); // Will be set to false if, for some reason, the build does not happen. bool bDoBuild = true; // Indicates whether the persistent level should be dirtied at the end of a build. bool bDirtyPersistentLevel = true; // Stop rendering thread so we're not wasting CPU cycles. StopRenderingThread(); // Hack: These don't initialize properly and if you pick BuildAll right off the // bat when opening a map you will get incorrect values in them. GSwarmDebugOptions.Touch(); // Show option dialog first, before showing the DlgBuildProgress window. FLightingBuildOptions LightingBuildOptions; if ( Id == EBuildOptions::BuildLighting ) { // Retrieve settings from ini. GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildSelected"), LightingBuildOptions.bOnlyBuildSelected, GEditorUserSettingsIni ); GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildCurrentLevel"), LightingBuildOptions.bOnlyBuildCurrentLevel, GEditorUserSettingsIni ); GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildSelectedLevels"),LightingBuildOptions.bOnlyBuildSelectedLevels, GEditorUserSettingsIni ); GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildVisibility"), LightingBuildOptions.bOnlyBuildVisibility, GEditorUserSettingsIni ); GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("UseErrorColoring"), LightingBuildOptions.bUseErrorColoring, GEditorUserSettingsIni ); GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("ShowLightingBuildInfo"), LightingBuildOptions.bShowLightingBuildInfo, GEditorUserSettingsIni ); int32 QualityLevel; GConfig->GetInt( TEXT("LightingBuildOptions"), TEXT("QualityLevel"), QualityLevel, GEditorUserSettingsIni ); QualityLevel = FMath::Clamp<int32>(QualityLevel, Quality_Preview, Quality_Production); LightingBuildOptions.QualityLevel = (ELightingBuildQuality)QualityLevel; } // Show the build progress dialog. SBuildProgressWidget::EBuildType BuildType = SBuildProgressWidget::BUILDTYPE_Geometry; switch (Id) { case EBuildOptions::BuildGeometry: case EBuildOptions::BuildVisibleGeometry: case EBuildOptions::BuildAll: case EBuildOptions::BuildAllOnlySelectedPaths: BuildType = SBuildProgressWidget::BUILDTYPE_Geometry; break; case EBuildOptions::BuildLighting: BuildType = SBuildProgressWidget::BUILDTYPE_Lighting; break; case EBuildOptions::BuildAIPaths: case EBuildOptions::BuildSelectedAIPaths: BuildType = SBuildProgressWidget::BUILDTYPE_Paths; break; case EBuildOptions::BuildHierarchicalLOD: BuildType = SBuildProgressWidget::BUILDTYPE_LODs; break; default: BuildType = SBuildProgressWidget::BUILDTYPE_Unknown; break; } TWeakPtr<class SBuildProgressWidget> BuildProgressWidget = GWarn->ShowBuildProgressWindow(); BuildProgressWidget.Pin()->SetBuildType(BuildType); bool bShouldMapCheck = true; switch( Id ) { case EBuildOptions::BuildGeometry: { // We can't set the busy cursor for all windows, because lighting // needs a cursor for the lighting options dialog. const FScopedBusyCursor BusyCursor; GUnrealEd->Exec( InWorld, TEXT("MAP REBUILD") ); TriggerNavigationBuilder(InWorld, Id); // No need to dirty the persient level if we're building BSP for a sub-level. bDirtyPersistentLevel = false; break; } case EBuildOptions::BuildVisibleGeometry: { // If any levels are hidden, prompt the user about how to proceed bDoBuild = GEditor->WarnAboutHiddenLevels( InWorld, true ); if ( bDoBuild ) { // We can't set the busy cursor for all windows, because lighting // needs a cursor for the lighting options dialog. const FScopedBusyCursor BusyCursor; GUnrealEd->Exec( InWorld, TEXT("MAP REBUILD ALLVISIBLE") ); TriggerNavigationBuilder(InWorld, Id); } break; } case EBuildOptions::BuildLighting: { if( bDoBuild ) { // We can't set the busy cursor for all windows, because lighting // needs a cursor for the lighting options dialog. const FScopedBusyCursor BusyCursor; GUnrealEd->BuildLighting( LightingBuildOptions ); bShouldMapCheck = false; } break; } case EBuildOptions::BuildAIPaths: { bDoBuild = GEditor->WarnAboutHiddenLevels( InWorld, false ); if ( bDoBuild ) { GEditor->ResetTransaction( NSLOCTEXT("UnrealEd", "RebuildNavigation", "Rebuilding Navigation") ); // We can't set the busy cursor for all windows, because lighting // needs a cursor for the lighting options dialog. const FScopedBusyCursor BusyCursor; TriggerNavigationBuilder(InWorld, Id); } break; } case EBuildOptions::BuildHierarchicalLOD: { bDoBuild = GEditor->WarnAboutHiddenLevels( InWorld, false ); if ( bDoBuild ) { GEditor->ResetTransaction( NSLOCTEXT("UnrealEd", "RebuildLOD", "Rebuilding HierarchicalLOD") ); // We can't set the busy cursor for all windows, because lighting // needs a cursor for the lighting options dialog. const FScopedBusyCursor BusyCursor; TriggerHierarchicalLODBuilder(InWorld, Id); } break; } case EBuildOptions::BuildAll: case EBuildOptions::BuildAllSubmit: { bDoBuild = GEditor->WarnAboutHiddenLevels( InWorld, true ); bool bLightingAlreadyRunning = GUnrealEd->WarnIfLightingBuildIsCurrentlyRunning(); if ( bDoBuild && !bLightingAlreadyRunning ) { // We can't set the busy cursor for all windows, because lighting // needs a cursor for the lighting options dialog. const FScopedBusyCursor BusyCursor; GUnrealEd->Exec( InWorld, TEXT("MAP REBUILD ALLVISIBLE") ); // disable this in build all path, it's very slow, it can be painful // they don't have any collision, but make sure it's added first before doing anything { BuildProgressWidget.Pin()->SetBuildType(SBuildProgressWidget::BUILDTYPE_LODs); TriggerHierarchicalLODBuilder(InWorld, Id); } { BuildProgressWidget.Pin()->SetBuildType(SBuildProgressWidget::BUILDTYPE_Paths); TriggerNavigationBuilder(InWorld, Id); } //Do a canceled check before moving on to the next step of the build. if( GEditor->GetMapBuildCancelled() ) { break; } else { BuildProgressWidget.Pin()->SetBuildType(SBuildProgressWidget::BUILDTYPE_Lighting); FLightingBuildOptions LightingOptions; int32 QualityLevel; // Force automated builds to always use production lighting if ( Id == EBuildOptions::BuildAllSubmit ) { QualityLevel = Quality_Production; } else { GConfig->GetInt( TEXT("LightingBuildOptions"), TEXT("QualityLevel"), QualityLevel, GEditorUserSettingsIni); QualityLevel = FMath::Clamp<int32>(QualityLevel, Quality_Preview, Quality_Production); } LightingOptions.QualityLevel = (ELightingBuildQuality)QualityLevel; GUnrealEd->BuildLighting(LightingOptions); bShouldMapCheck = false; } } break; } default: UE_LOG(LogEditorBuildUtils, Warning, TEXT("Invalid build Id")); break; } // Check map for errors (only if build operation happened) if ( bShouldMapCheck && bDoBuild && !GEditor->GetMapBuildCancelled() ) { GUnrealEd->Exec( InWorld, TEXT("MAP CHECK DONTDISPLAYDIALOG") ); } // Re-start the rendering thread after build operations completed. if (GUseThreadedRendering) { StartRenderingThread(); } if ( bDoBuild && InWorld->Scene ) { // Invalidating lighting marked various components as needing a re-register // Propagate the re-registers before rendering the scene to get the latest state InWorld->SendAllEndOfFrameUpdates(); } if ( bDoBuild ) { // Display elapsed build time. UE_LOG(LogEditorBuildUtils, Log, TEXT("Build time %s"), *BuildProgressWidget.Pin()->BuildElapsedTimeText().ToString() ); } // Build completed, hide the build progress dialog. // NOTE: It's important to turn off modalness before hiding the window, otherwise a background // application may unexpectedly be promoted to the foreground, obscuring the editor. GWarn->CloseBuildProgressWindow(); GUnrealEd->RedrawLevelEditingViewports(); if ( bDoBuild ) { if ( bDirtyPersistentLevel ) { InWorld->MarkPackageDirty(); } ULevel::LevelDirtiedEvent.Broadcast(); } // Don't show map check if we cancelled build because it may have some bogus data const bool bBuildCompleted = bDoBuild && !GEditor->GetMapBuildCancelled(); if( bBuildCompleted ) { if (bShouldMapCheck) { FMessageLog("MapCheck").Open( EMessageSeverity::Warning ); } FMessageLog("LightingResults").Notify(LOCTEXT("LightingErrorsNotification", "There were lighting errors."), EMessageSeverity::Error); } return bBuildCompleted; }
void FMaterialEditorViewportClient::Draw(FViewport* InViewport,FCanvas* Canvas) { FEditorViewportClient::Draw(InViewport, Canvas); MaterialEditorPtr.Pin()->DrawMessages(InViewport, Canvas); }
/** * Construct this widget. Called by the SNew() Slate macro. * * @param InArgs Declaration used by the SNew() macro to construct this widget * @param Factory The factory this menu entry represents */ void Construct( const FArguments& InArgs, UFactory* Factory ) { const FName ClassThumbnailBrushOverride = Factory->GetNewAssetThumbnailOverride(); const FSlateBrush* ClassThumbnail = nullptr; if (ClassThumbnailBrushOverride.IsNone()) { ClassThumbnail = FClassIconFinder::FindThumbnailForClass(Factory->GetSupportedClass()); } else { // Instead of getting the override thumbnail directly from the editor style here get it from the // ClassIconFinder since it may have additional styles registered which can be searched by passing // it as a default with no class to search for. ClassThumbnail = FClassIconFinder::FindThumbnailForClass(nullptr, ClassThumbnailBrushOverride); } FAssetToolsModule& AssetToolsModule = FAssetToolsModule::GetModule(); TWeakPtr<IAssetTypeActions> AssetTypeActions = AssetToolsModule.Get().GetAssetTypeActionsForClass(Factory->GetSupportedClass()); FLinearColor AssetColor = FLinearColor::White; if ( AssetTypeActions.IsValid() ) { AssetColor = AssetTypeActions.Pin()->GetTypeColor(); } ChildSlot [ SNew( SHorizontalBox ) +SHorizontalBox::Slot() .Padding( 4, 0, 0, 0 ) .VAlign(VAlign_Center) .AutoWidth() [ SNew( SOverlay ) +SOverlay::Slot() [ SNew( SBox ) .WidthOverride( InArgs._Width + 4 ) .HeightOverride( InArgs._Height + 4 ) [ SNew( SBorder ) .BorderImage( FEditorStyle::GetBrush("AssetThumbnail.AssetBackground") ) .BorderBackgroundColor(AssetColor.CopyWithNewOpacity(0.3f)) .Padding( 2.0f ) .VAlign( VAlign_Center ) .HAlign( HAlign_Center ) [ SNew( SImage ) .Image( ClassThumbnail ) ] ] ] +SOverlay::Slot() .HAlign(HAlign_Fill) .VAlign(VAlign_Bottom) [ SNew( SBorder ) .BorderImage( FEditorStyle::GetBrush("WhiteBrush") ) .BorderBackgroundColor( AssetColor ) .Padding( FMargin(0, FMath::Max(FMath::CeilToFloat(InArgs._Width*0.025f), 3.0f), 0, 0) ) ] ] +SHorizontalBox::Slot() .VAlign(VAlign_Center) .Padding(4, 0, 4, 0) [ SNew( SVerticalBox ) +SVerticalBox::Slot() .Padding(0, 0, 0, 1) .AutoHeight() [ SNew(STextBlock) .Font( FEditorStyle::GetFontStyle("LevelViewportContextMenu.AssetLabel.Text.Font") ) .Text( Factory->GetDisplayName() ) ] ] ]; SetToolTip(IDocumentation::Get()->CreateToolTip(Factory->GetToolTip(), nullptr, Factory->GetToolTipDocumentationPage(), Factory->GetToolTipDocumentationExcerpt())); }
bool FAssetEditorManager::OpenEditorForAssets( const TArray< UObject* >& Assets, const EToolkitMode::Type ToolkitMode, TSharedPtr< IToolkitHost > OpenedFromLevelEditor ) { if( Assets.Num() == 1 ) { return OpenEditorForAsset(Assets[0], ToolkitMode, OpenedFromLevelEditor); } else if (Assets.Num() > 0) { // If any of the assets are already open, remove them from the list of assets to open an editor for TArray<UObject*> AlreadyOpenAssets; for (auto Asset : Assets) { if( FindEditorForAsset(Asset, true) != nullptr ) { AlreadyOpenAssets.Add(Asset); } } // Verify that all the assets are of the same class bool bAssetClassesMatch = true; auto AssetClass = Assets[0]->GetClass(); for (int32 i = 1; i < Assets.Num(); i++) { if (Assets[i]->GetClass() != AssetClass) { bAssetClassesMatch = false; break; } } // If the classes don't match or any of the selected assets are already open, just open each asset in its own editor. if (bAssetClassesMatch && AlreadyOpenAssets.Num() == 0) { FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools")); TWeakPtr<IAssetTypeActions> AssetTypeActions = AssetToolsModule.Get().GetAssetTypeActionsForClass(AssetClass); if (AssetTypeActions.IsValid()) { GWarn->BeginSlowTask(LOCTEXT("OpenEditor", "Opening Editor(s)..."), true); // Determine the appropriate toolkit mode for the asset type auto ActualToolkitMode = ToolkitMode; if (AssetTypeActions.Pin()->ShouldForceWorldCentric()) { // This asset type prefers a specific toolkit mode ActualToolkitMode = EToolkitMode::WorldCentric; if (!OpenedFromLevelEditor.IsValid()) { // We don't have a level editor to spawn in world-centric mode, so we'll find one now // @todo sequencer: We should eventually eliminate this code (incl include dependencies) or change it to not make assumptions about a single level editor OpenedFromLevelEditor = FModuleManager::LoadModuleChecked< FLevelEditorModule >("LevelEditor").GetFirstLevelEditor(); } } if (ActualToolkitMode != EToolkitMode::WorldCentric && OpenedFromLevelEditor.IsValid()) { // @todo toolkit minor: Kind of lame use of a static variable here to prime the new asset editor. This was done to avoid refactoring a few dozen files for a very minor change. FAssetEditorToolkit::SetPreviousWorldCentricToolkitHostForNewAssetEditor(OpenedFromLevelEditor.ToSharedRef()); } // Some assets (like UWorlds) may be destroyed and recreated as part of opening. To protect against this, keep the path to each asset and try to re-find any if they disappear. struct FLocalAssetInfo { TWeakObjectPtr<UObject> WeakAsset; FString AssetPath; FLocalAssetInfo(const TWeakObjectPtr<UObject>& InWeakAsset, const FString& InAssetPath) : WeakAsset(InWeakAsset), AssetPath(InAssetPath) {} }; TArray<FLocalAssetInfo> AssetInfoList; AssetInfoList.Reserve(Assets.Num()); for (auto Asset : Assets) { AssetInfoList.Add(FLocalAssetInfo(Asset, Asset->GetPathName())); } // How to handle multiple assets is left up to the type actions (i.e. open a single shared editor or an editor for each) AssetTypeActions.Pin()->OpenAssetEditor(Assets, ActualToolkitMode == EToolkitMode::WorldCentric ? OpenedFromLevelEditor : TSharedPtr<IToolkitHost>()); // If any assets were destroyed, attempt to find them if they were recreated for (int32 i = 0; i < Assets.Num(); i++) { auto& AssetInfo = AssetInfoList[i]; auto Asset = Assets[i]; if (!AssetInfo.WeakAsset.IsValid() && !AssetInfo.AssetPath.IsEmpty()) { Asset = FindObject<UObject>(nullptr, *AssetInfo.AssetPath); } } //@todo if needed, broadcast the event for every asset. It is possible, however, that a single shared editor was opened by the AssetTypeActions, not an editor for each asset. /*AssetEditorOpenedEvent.Broadcast(Asset);*/ GWarn->EndSlowTask(); } } else { // Asset types don't match or some are already open, so just open individual editors for the unopened ones for (auto Asset : Assets) { if (!AlreadyOpenAssets.Contains(Asset)) { OpenEditorForAsset(Asset, ToolkitMode, OpenedFromLevelEditor); } } } } return true; }
FReply STimelineLabelAnchor::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { if (MouseEvent.GetEffectingButton() == EKeys::RightMouseButton && TimelineOwner.IsValid() && TimelineOwner.Pin()->IsSelected()) { SetIsOpen(!IsOpen()); return FReply::Handled(); } return FReply::Unhandled(); }
TSharedRef< SWidget > FLevelEditorToolBar::GenerateMatineeMenuContent( TSharedRef<FUICommandList> InCommandList, TWeakPtr<SLevelEditor> LevelEditorWeakPtr ) { #define LOCTEXT_NAMESPACE "LevelToolBarMatineeMenu" const bool bShouldCloseWindowAfterMenuSelection = true; FMenuBuilder MenuBuilder( bShouldCloseWindowAfterMenuSelection, InCommandList ); // We can't build a list of Matinees while the current World is a PIE world. FSceneOutlinerInitializationOptions InitOptions; { InitOptions.Mode = ESceneOutlinerMode::ActorPicker; // We hide the header row to keep the UI compact. // @todo: Might be useful to have this sometimes, actually. Ideally the user could summon it. InitOptions.bShowHeaderRow = false; // Only display Matinee actors InitOptions.ActorFilters = MakeShareable( new TFilterCollection< const AActor* const >() ); struct Local { static bool IsMatineeActor( const AActor* const Actor ) { return Actor->IsA( AMatineeActor::StaticClass() ); } }; InitOptions.ActorFilters->Add( MakeShareable( new TDelegateFilter< const AActor* const >( TDelegateFilter< const AActor* const >::FPredicate::CreateStatic( &Local::IsMatineeActor ) ) ) ); } // actor selector to allow the user to choose a Matinee actor FSceneOutlinerModule& SceneOutlinerModule = FModuleManager::LoadModuleChecked<FSceneOutlinerModule>( "SceneOutliner" ); TSharedRef< SWidget > MiniSceneOutliner = SNew( SVerticalBox ) +SVerticalBox::Slot() .AutoHeight() .MaxHeight(400.0f) [ SceneOutlinerModule.CreateSceneOutliner( InitOptions, FOnContextMenuOpening(), //no context menu allowed here FOnActorPicked::CreateStatic( &FLevelEditorToolBar::OnMatineeActorPicked ) ) ]; // Give the scene outliner a border and background const FSlateBrush* BackgroundBrush = FEditorStyle::GetBrush( "Menu.Background" ); TSharedRef< SBorder > RootBorder = SNew( SBorder ) .Padding(3) .BorderImage( BackgroundBrush ) .ForegroundColor( FEditorStyle::GetSlateColor("DefaultForeground") ) // Assign the box panel as the child [ SNew( SVerticalBox ) +SVerticalBox::Slot() .AutoHeight() .Padding( 5 ) .HAlign( HAlign_Center ) [ SNew( STextBlock ) .Text( LOCTEXT( "SelectMatineeActorToEdit", "Select a Matinee actor" ) ) ] +SVerticalBox::Slot() .AutoHeight() .Padding( 2 ) [ MiniSceneOutliner ] ] ; MenuBuilder.BeginSection("LevelEditorNewMatinee", LOCTEXT("MatineeMenuCombo_NewHeading", "New")); { MenuBuilder.AddMenuEntry( FLevelEditorCommands::Get().AddMatinee ); } MenuBuilder.EndSection(); bool bHasAnyMatineeActors = false; TActorIterator<AMatineeActor> MatineeIt( LevelEditorWeakPtr.Pin()->GetWorld() ); bHasAnyMatineeActors = MatineeIt; //Add a heading to separate the existing matinees from the 'Add New Matinee Actor' button MenuBuilder.BeginSection("LevelEditorExistingMatinee", LOCTEXT( "MatineeMenuCombo_ExistingHeading", "Edit Existing Matinee" ) ); { if( bHasAnyMatineeActors ) { MenuBuilder.AddWidget(MiniSceneOutliner, FText::GetEmpty(), false); } } MenuBuilder.EndSection(); #undef LOCTEXT_NAMESPACE return MenuBuilder.MakeWidget(); }
bool FAssetEditorManager::OpenEditorForAsset(UObject* Asset, const EToolkitMode::Type ToolkitMode, TSharedPtr< IToolkitHost > OpenedFromLevelEditor ) { check(Asset); // @todo toolkit minor: When "Edit Here" happens in a different level editor from the one that an asset is already // being edited within, we should decide whether to disallow "Edit Here" in that case, or to close the old asset // editor and summon it in the new level editor, or to just foreground the old level editor (current behavior) const bool bBringToFrontIfOpen = true; // Don't open asset editors for cooked packages if (UPackage* Package = Asset->GetOutermost()) { if (Package->bIsCookedForEditor) { return false; } } AssetEditorRequestOpenEvent.Broadcast(Asset); if( FindEditorForAsset(Asset, bBringToFrontIfOpen) != nullptr ) { // This asset is already open in an editor! (the call to FindEditorForAsset above will bring it to the front) return true; } else { GWarn->BeginSlowTask( LOCTEXT("OpenEditor", "Opening Editor..."), true); } FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools")); TWeakPtr<IAssetTypeActions> AssetTypeActions = AssetToolsModule.Get().GetAssetTypeActionsForClass( Asset->GetClass() ); auto ActualToolkitMode = ToolkitMode; if( AssetTypeActions.IsValid() ) { if( AssetTypeActions.Pin()->ShouldForceWorldCentric() ) { // This asset type prefers a specific toolkit mode ActualToolkitMode = EToolkitMode::WorldCentric; if( !OpenedFromLevelEditor.IsValid() ) { // We don't have a level editor to spawn in world-centric mode, so we'll find one now // @todo sequencer: We should eventually eliminate this code (incl include dependencies) or change it to not make assumptions about a single level editor OpenedFromLevelEditor = FModuleManager::LoadModuleChecked< FLevelEditorModule >( "LevelEditor" ).GetFirstLevelEditor(); } } } if( ActualToolkitMode != EToolkitMode::WorldCentric && OpenedFromLevelEditor.IsValid() ) { // @todo toolkit minor: Kind of lame use of a static variable here to prime the new asset editor. This was done to avoid refactoring a few dozen files for a very minor change. FAssetEditorToolkit::SetPreviousWorldCentricToolkitHostForNewAssetEditor( OpenedFromLevelEditor.ToSharedRef() ); } // Disallow opening an asset editor for classes bool bCanSummonSimpleAssetEditor = !Asset->IsA<UClass>(); if( AssetTypeActions.IsValid() ) { TArray<UObject*> AssetsToEdit; AssetsToEdit.Add(Asset); // Some assets (like UWorlds) may be destroyed and recreated as part of opening. To protect against this, keep the path to the asset and try to re-find it if it disappeared. TWeakObjectPtr<UObject> WeakAsset = Asset; const FString AssetPath = Asset->GetPathName(); AssetTypeActions.Pin()->OpenAssetEditor(AssetsToEdit, ActualToolkitMode == EToolkitMode::WorldCentric ? OpenedFromLevelEditor : TSharedPtr<IToolkitHost>()); // If the Asset was destroyed, attempt to find it if it was recreated if ( !WeakAsset.IsValid() && !AssetPath.IsEmpty() ) { Asset = FindObject<UObject>(nullptr, *AssetPath); } AssetEditorOpenedEvent.Broadcast(Asset); } else if( bCanSummonSimpleAssetEditor ) { // No asset type actions for this asset. Just use a properties editor. FSimpleAssetEditor::CreateEditor(ActualToolkitMode, ActualToolkitMode == EToolkitMode::WorldCentric ? OpenedFromLevelEditor : TSharedPtr<IToolkitHost>(), Asset); } GWarn->EndSlowTask(); return true; }
FText FLevelEditorToolBar::GetOpenGameModeBlueprintLabel(TWeakPtr< SLevelEditor > InLevelEditor) { #define LOCTEXT_NAMESPACE "LevelToolBarViewMenu" if(IsValidGameModeBlueprint(InLevelEditor)) { return FText::Format( LOCTEXT("GameModeEditBlueprint", "GameMode: Edit {GameModeName}"), FText::FromString(InLevelEditor.Pin()->GetWorld()->GetWorldSettings()->DefaultGameMode->ClassGeneratedBy->GetName())); } return LOCTEXT("GameModeCreateBlueprint", "GameMode: Create..."); #undef LOCTEXT_NAMESPACE }
bool FLevelEditorToolBar::IsValidGameModeBlueprint(TWeakPtr< SLevelEditor > InLevelEditor) { AWorldSettings* WorldSettings = InLevelEditor.Pin()->GetWorld()->GetWorldSettings(); return WorldSettings->DefaultGameMode && WorldSettings->DefaultGameMode->ClassGeneratedBy; }
TSharedRef< SWidget > FLevelEditorToolBar::GenerateOpenBlueprintMenuContent( TSharedRef<FUICommandList> InCommandList, TWeakPtr< SLevelEditor > InLevelEditor ) { #define LOCTEXT_NAMESPACE "LevelToolBarViewMenu" struct FBlueprintMenus { /** Generates a sub-level Blueprints sub-menu */ static void MakeSubLevelsMenu(FMenuBuilder& InMenuBuilder, TWeakPtr< SLevelEditor > InLvlEditor) { FSlateIcon EditBP(FEditorStyle::Get().GetStyleSetName(), TEXT("LevelEditor.OpenLevelBlueprint")); InMenuBuilder.BeginSection(NAME_None, LOCTEXT("SubLevelsHeading", "Sub-Level Blueprints")); { UWorld* World = InLvlEditor.Pin()->GetWorld(); for (int32 iLevel = 0; iLevel < World->GetNumLevels(); iLevel++) { ULevel* Level = World->GetLevel(iLevel); if (Level != NULL && Level->GetOutermost() != NULL) { if (!Level->IsPersistentLevel()) { FUIAction UIAction ( FExecuteAction::CreateStatic(&FLevelEditorToolBar::OnOpenSubLevelBlueprint, Level) ); FText DisplayName = FText::Format(LOCTEXT("SubLevelBlueprintItem", "Edit {LevelName}"), FText::FromString(FPaths::GetCleanFilename(Level->GetOutermost()->GetName()))); InMenuBuilder.AddMenuEntry(DisplayName, FText::GetEmpty(), EditBP, UIAction); } } } } InMenuBuilder.EndSection(); } /** Handle BP being selected from popup picker */ static void OnBPSelected(const class FAssetData& AssetData) { UBlueprint* SelectedBP = Cast<UBlueprint>(AssetData.GetAsset()); if(SelectedBP) { FAssetEditorManager::Get().OpenEditorForAsset(SelectedBP); } } /** Generates 'eopn blueprint' sub-menu */ static void MakeOpenClassBPMenu(FMenuBuilder& InMenuBuilder) { FContentBrowserModule& ContentBrowserModule = FModuleManager::Get().LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser")); // Configure filter for asset picker FAssetPickerConfig Config; Config.Filter.ClassNames.Add(UBlueprint::StaticClass()->GetFName()); Config.InitialAssetViewType = EAssetViewType::List; Config.ThumbnailScale = 0; // make thumbnails as small as possible Config.OnAssetSelected = FOnAssetSelected::CreateStatic(&FBlueprintMenus::OnBPSelected); Config.bAllowDragging = false; // Don't show stuff in Engine Config.Filter.PackagePaths.Add("/Game"); Config.Filter.bRecursivePaths = true; TSharedRef<SWidget> Widget = SNew(SBox) .WidthOverride(300.f) .HeightOverride(300.f) [ ContentBrowserModule.Get().CreateAssetPicker(Config) ]; InMenuBuilder.BeginSection(NAME_None, LOCTEXT("BrowseHeader", "Browse")); { InMenuBuilder.AddWidget(Widget, FText::GetEmpty()); } InMenuBuilder.EndSection(); } }; const bool bShouldCloseWindowAfterMenuSelection = true; FMenuBuilder MenuBuilder( bShouldCloseWindowAfterMenuSelection, InCommandList ); MenuBuilder.BeginSection(NAME_None, LOCTEXT("LevelScriptBlueprints", "Level Blueprints")); { MenuBuilder.AddMenuEntry( FLevelEditorCommands::Get().OpenLevelBlueprint ); // If there are any sub-levels, display the sub-menu. A single level means there is only the persistent level UWorld* World = InLevelEditor.Pin()->GetWorld(); if(World->GetNumLevels() > 1) { MenuBuilder.AddSubMenu( LOCTEXT( "SubLevelsSubMenu", "Sub-Levels" ), LOCTEXT( "SubLevelsSubMenu_ToolTip", "Shows available sub-level Blueprints that can be edited." ), FNewMenuDelegate::CreateStatic( &FBlueprintMenus::MakeSubLevelsMenu, InLevelEditor ), FUIAction(), NAME_None, EUserInterfaceActionType::Button, false, FSlateIcon(FEditorStyle::Get().GetStyleSetName(), TEXT("LevelEditor.OpenLevelBlueprint")) ); } } MenuBuilder.EndSection(); MenuBuilder.BeginSection(NAME_None, LOCTEXT("GameBlueprints", "Game Blueprints")); { FSlateIcon EditBPIcon(FEditorStyle::Get().GetStyleSetName(), TEXT("PropertyWindow.Button_Edit")); FSlateIcon NewBPIcon(FEditorStyle::Get().GetStyleSetName(), TEXT("PropertyWindow.Button_AddToArray")); // Game Mode TAttribute<FText>::FGetter DynamicGameModeGetter; DynamicGameModeGetter.BindStatic(&FLevelEditorToolBar::GetOpenGameModeBlueprintLabel, InLevelEditor); TAttribute<FText> DynamicGameModeLabel = TAttribute<FText>::Create(DynamicGameModeGetter); TAttribute<FText>::FGetter DynamicGameModeGetter_Tooltip; DynamicGameModeGetter_Tooltip.BindStatic(&FLevelEditorToolBar::GetOpenGameModeBlueprintTooltip, InLevelEditor); TAttribute<FText> DynamicGameModeTooltip = TAttribute<FText>::Create(DynamicGameModeGetter_Tooltip); MenuBuilder.AddMenuEntry( FLevelEditorCommands::Get().OpenGameModeBlueprint, NAME_None, DynamicGameModeLabel, DynamicGameModeTooltip, IsValidGameModeBlueprint(InLevelEditor)? EditBPIcon : NewBPIcon ); // Game State TAttribute<FText>::FGetter DynamicGameStateGetter; DynamicGameStateGetter.BindStatic(&FLevelEditorToolBar::GetOpenGameStateBlueprintLabel, InLevelEditor); TAttribute<FText> DynamicGameStateLabel = TAttribute<FText>::Create(DynamicGameStateGetter); TAttribute<FText>::FGetter DynamicGameStateGetter_Tooltip; DynamicGameStateGetter_Tooltip.BindStatic(&FLevelEditorToolBar::GetOpenGameStateBlueprintTooltip, InLevelEditor); TAttribute<FText> DynamicGameStateTooltip = TAttribute<FText>::Create(DynamicGameStateGetter_Tooltip); MenuBuilder.AddMenuEntry( FLevelEditorCommands::Get().OpenGameStateBlueprint, NAME_None, DynamicGameStateLabel, DynamicGameStateTooltip, IsValidGameStateBlueprint(InLevelEditor)? EditBPIcon : NewBPIcon ); // Pawn TAttribute<FText>::FGetter DynamicDefaultPawnGetter; DynamicDefaultPawnGetter.BindStatic(&FLevelEditorToolBar::GetOpenPawnBlueprintLabel, InLevelEditor); TAttribute<FText> DynamicDefaultPawnLabel = TAttribute<FText>::Create(DynamicDefaultPawnGetter); TAttribute<FText>::FGetter DynamicDefaultPawnGetter_Tooltip; DynamicDefaultPawnGetter_Tooltip.BindStatic(&FLevelEditorToolBar::GetOpenPawnBlueprintTooltip, InLevelEditor); TAttribute<FText> DynamicDefaultPawnTooltip = TAttribute<FText>::Create(DynamicDefaultPawnGetter_Tooltip); MenuBuilder.AddMenuEntry( FLevelEditorCommands::Get().OpenDefaultPawnBlueprint, NAME_None, DynamicDefaultPawnLabel, DynamicDefaultPawnTooltip, IsValidPawnBlueprint(InLevelEditor)? EditBPIcon : NewBPIcon ); // HUD TAttribute<FText>::FGetter DynamicHUDGetter; DynamicHUDGetter.BindStatic(&FLevelEditorToolBar::GetOpenHUDBlueprintLabel, InLevelEditor); TAttribute<FText> DynamicHUDLabel = TAttribute<FText>::Create(DynamicHUDGetter); TAttribute<FText>::FGetter DynamicHUDGetter_Tooltip; DynamicHUDGetter_Tooltip.BindStatic(&FLevelEditorToolBar::GetOpenHUDBlueprintTooltip, InLevelEditor); TAttribute<FText> DynamicHUDTooltip = TAttribute<FText>::Create(DynamicHUDGetter_Tooltip); MenuBuilder.AddMenuEntry( FLevelEditorCommands::Get().OpenHUDBlueprint, NAME_None, DynamicHUDLabel, DynamicHUDTooltip, IsValidHUDBlueprint(InLevelEditor)? EditBPIcon : NewBPIcon ); // Player Controller TAttribute<FText>::FGetter DynamicPlayerControllerGetter; DynamicPlayerControllerGetter.BindStatic(&FLevelEditorToolBar::GetOpenPlayerControllerBlueprintLabel, InLevelEditor); TAttribute<FText> DynamicPlayerControllerLabel = TAttribute<FText>::Create(DynamicPlayerControllerGetter); TAttribute<FText>::FGetter DynamicPlayerControllerGetter_Tooltip; DynamicPlayerControllerGetter_Tooltip.BindStatic(&FLevelEditorToolBar::GetOpenPlayerControllerBlueprintTooltip, InLevelEditor); TAttribute<FText> DynamicPlayerControllerTooltip = TAttribute<FText>::Create(DynamicPlayerControllerGetter_Tooltip); MenuBuilder.AddMenuEntry( FLevelEditorCommands::Get().OpenPlayerControllerBlueprint, NAME_None, DynamicPlayerControllerLabel, DynamicPlayerControllerTooltip, IsValidPlayerControllerBlueprint(InLevelEditor)? EditBPIcon : NewBPIcon ); } MenuBuilder.EndSection(); MenuBuilder.BeginSection(NAME_None, LOCTEXT("ClassBlueprints", "Class Blueprints")); { // New Class Blueprint... MenuBuilder.AddMenuEntry(FLevelEditorCommands::Get().CreateClassBlueprint, NAME_None, LOCTEXT("NewClassBlueprint", "New Class Blueprint...")); // Open Class Blueprint... FSlateIcon OpenBPIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.OpenClassBlueprint"); MenuBuilder.AddSubMenu( LOCTEXT("OpenClassBlueprintSubMenu", "Open Class Blueprint..."), LOCTEXT("OpenClassBlueprintSubMenu_ToolTip", "Open an existing Class Blueprint in this project"), FNewMenuDelegate::CreateStatic(&FBlueprintMenus::MakeOpenClassBPMenu), false, OpenBPIcon ); } MenuBuilder.EndSection(); #undef LOCTEXT_NAMESPACE return MenuBuilder.MakeWidget(); }
FReply SVisualLoggerTimelinesContainer::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) { if (InKeyEvent.GetKey() == EKeys::A && InKeyEvent.IsLeftControlDown()) { for (TSharedPtr<SLogVisualizerTimeline>& Timeline : TimelineItems) { SetSelectionState(Timeline, true, false); } return FReply::Handled(); } else if (InKeyEvent.GetKey() == EKeys::Platform_Delete && CachedSelectedTimelines.Num() > 0) { TWeakPtr<SLogVisualizerTimeline> NotSelectedOne; for (TSharedPtr<SLogVisualizerTimeline>& CurrentNode : CachedSelectedTimelines) { TSharedPtr<SLogVisualizerTimeline> LastSelected = CachedSelectedTimelines[CachedSelectedTimelines.Num() - 1]; bool bFoundSelectedOne = false; for (TSharedPtr<SLogVisualizerTimeline>& Timeline : TimelineItems) { if (IsNodeSelected(Timeline) == false) { NotSelectedOne = Timeline; } if (LastSelected == Timeline) { if (bFoundSelectedOne && NotSelectedOne.IsValid()) { break; } bFoundSelectedOne = true; } } FVisualLoggerDatabase::Get().RemoveRow(CurrentNode->GetName()); TimelineItems.Remove(CurrentNode); ContainingBorder->RemoveSlot(CurrentNode.ToSharedRef()); } if (NotSelectedOne.IsValid()) { SetSelectionState(NotSelectedOne.Pin(), true, true); } return FReply::Handled(); } else if (InKeyEvent.GetKey() == EKeys::Up || InKeyEvent.GetKey() == EKeys::Down) { TSharedPtr<SLogVisualizerTimeline> PreviousTimeline; TSharedPtr<SLogVisualizerTimeline> LastSelected = CachedSelectedTimelines[CachedSelectedTimelines.Num() - 1]; for (int32 Index = 0; Index < TimelineItems.Num(); ++Index) { auto& CurrentItem = TimelineItems[Index]; if (LastSelected == CurrentItem) { if (InKeyEvent.GetKey() == EKeys::Up && PreviousTimeline.IsValid()) { SetSelectionState(PreviousTimeline, true, true); } else if (InKeyEvent.GetKey() == EKeys::Down) { // let's find next visible time line if (TimelineItems.IsValidIndex(Index + 1)) { for (int32 i = Index + 1; i < TimelineItems.Num(); ++i) { if (TimelineItems[i]->GetVisibility() == EVisibility::Visible) { SetSelectionState(TimelineItems[i], true, true); break; } } } } break; } if (CurrentItem->GetVisibility() == EVisibility::Visible) { PreviousTimeline = CurrentItem; } } return FReply::Handled(); } return FReply::Unhandled(); }
void FMathStructCustomization::OnValueCommitted( NumericType NewValue, ETextCommit::Type CommitType, TWeakPtr<IPropertyHandle> WeakHandlePtr ) { WeakHandlePtr.Pin()->SetValue( NewValue ); }
/** * Builds this MultiBlock widget up from the MultiBlock associated with it */ void SToolBarButtonBlock::BuildMultiBlockWidget(const ISlateStyle* StyleSet, const FName& StyleName) { struct Local { /** Appends the key binding to the end of the provided ToolTip */ static FText AppendKeyBindingToToolTip( const TAttribute<FText> ToolTip, TWeakPtr< const FUICommandInfo> Command ) { TSharedPtr<const FUICommandInfo> CommandPtr = Command.Pin(); if( CommandPtr.IsValid() && CommandPtr->GetActiveChord()->IsValidChord() ) { FFormatNamedArguments Args; Args.Add( TEXT("ToolTipDescription"), ToolTip.Get() ); Args.Add( TEXT("Keybinding"), CommandPtr->GetInputText() ); return FText::Format( NSLOCTEXT("ToolBar", "ToolTip + Keybinding", "{ToolTipDescription} ({Keybinding})"), Args ); } else { return ToolTip.Get(); } } }; TSharedRef< const FMultiBox > MultiBox( OwnerMultiBoxWidget.Pin()->GetMultiBox() ); TSharedRef< const FToolBarButtonBlock > ToolBarButtonBlock = StaticCastSharedRef< const FToolBarButtonBlock >( MultiBlock.ToSharedRef() ); // Allow the block to override the action's label and tool tip string, if desired TAttribute<FText> ActualLabel; if (ToolBarButtonBlock->LabelOverride.IsSet()) { ActualLabel = ToolBarButtonBlock->LabelOverride; } else { ActualLabel = ToolBarButtonBlock->GetAction()->GetLabel(); } // Add this widget to the search list of the multibox if (MultiBlock->GetSearchable()) OwnerMultiBoxWidget.Pin()->AddSearchElement(this->AsWidget(), ActualLabel.Get()); TAttribute<FText> ActualToolTip; if (ToolBarButtonBlock->ToolTipOverride.IsSet()) { ActualToolTip = ToolBarButtonBlock->ToolTipOverride; } else { ActualToolTip = ToolBarButtonBlock->GetAction()->GetDescription(); } // If a key is bound to the command, append it to the tooltip text. TWeakPtr<const FUICommandInfo> Action = ToolBarButtonBlock->GetAction(); ActualToolTip = TAttribute< FText >::Create( TAttribute< FText >::FGetter::CreateStatic( &Local::AppendKeyBindingToToolTip, ActualToolTip, Action ) ); // If we were supplied an image than go ahead and use that, otherwise we use a null widget TSharedRef< SWidget > IconWidget = SNew( SImage ) .Visibility( this, &SToolBarButtonBlock::GetIconVisibility, false ) .Image( this, &SToolBarButtonBlock::GetIconBrush ); TSharedRef< SWidget > SmallIconWidget = SNew( SImage ) .Visibility( this, &SToolBarButtonBlock::GetIconVisibility, true ) .Image( this, &SToolBarButtonBlock::GetSmallIconBrush ); // Create the content for our button TSharedRef< SWidget > ButtonContent = SNew(SHorizontalBox) .AddMetaData<FTagMetaData>(FTagMetaData(TutorialHighlightName)) + SHorizontalBox::Slot() .FillWidth(1) .VAlign(VAlign_Center) [ SNew( SVerticalBox ) // Icon image + SVerticalBox::Slot() .AutoHeight() .HAlign( HAlign_Center ) // Center the icon horizontally, so that large labels don't stretch out the artwork [ IconWidget ] + SVerticalBox::Slot().AutoHeight() .HAlign( HAlign_Center ) [ SmallIconWidget ] // Label text + SVerticalBox::Slot().AutoHeight() .HAlign( HAlign_Center ) // Center the label text horizontally [ SNew( STextBlock ) .Visibility( LabelVisibility ) .Text( ActualLabel ) .TextStyle( StyleSet, ISlateStyle::Join( StyleName, ".Label" ) ) // Smaller font for tool tip labels .ShadowOffset( FVector2D::UnitVector ) ] ]; EMultiBlockLocation::Type BlockLocation = GetMultiBlockLocation(); // What type of UI should we create for this block? EUserInterfaceActionType::Type UserInterfaceType = ToolBarButtonBlock->UserInterfaceActionType; if ( Action.IsValid() ) { // If we have a UICommand, then this is specified in the command. UserInterfaceType = Action.Pin()->GetUserInterfaceType(); } if( UserInterfaceType == EUserInterfaceActionType::Button ) { FName BlockStyle = EMultiBlockLocation::ToName(ISlateStyle::Join( StyleName, ".Button" ), BlockLocation); ChildSlot [ // Create a button SNew( SButton ) .ContentPadding(0) // Use the tool bar item style for this button .ButtonStyle( StyleSet, BlockStyle ) .ForegroundColor( FSlateColor::UseForeground() ) .IsFocusable(bIsFocusable) [ ButtonContent ] // Bind the button's "on clicked" event to our object's method for this .OnClicked( this, &SToolBarButtonBlock::OnClicked ) // Pass along the block's tool-tip string .ToolTip( FMultiBoxSettings::ToolTipConstructor.Execute( ActualToolTip, nullptr, Action.Pin() ) ) ]; } else if( ensure( UserInterfaceType == EUserInterfaceActionType::ToggleButton || UserInterfaceType == EUserInterfaceActionType::RadioButton ) ) { FName BlockStyle = EMultiBlockLocation::ToName(ISlateStyle::Join( StyleName, ".ToggleButton" ), BlockLocation); FName CheckboxStyle = ISlateStyle::Join( StyleName, ".SToolBarButtonBlock.CheckBox.Padding" ); ChildSlot [ // Create a check box SNew( SCheckBox ) // Use the tool bar style for this check box .Style( StyleSet, BlockStyle ) // User will have set the focusable attribute for the block, honor it .IsFocusable( bIsFocusable ) // Pass along the block's tool-tip string .ToolTip( FMultiBoxSettings::ToolTipConstructor.Execute( ActualToolTip, nullptr, Action.Pin() ) ) [ ButtonContent ] // Bind the button's "on checked" event to our object's method for this .OnCheckStateChanged( this, &SToolBarButtonBlock::OnCheckStateChanged ) // Bind the check box's "checked" state to our user interface action .IsChecked( this, &SToolBarButtonBlock::OnIsChecked ) .Padding( StyleSet->GetMargin(CheckboxStyle) ) ]; } ChildSlot.Padding(StyleSet->GetMargin(ISlateStyle::Join( StyleName, ".SToolBarButtonBlock.Padding" ))); // Bind our widget's enabled state to whether or not our action can execute SetEnabled( TAttribute< bool >( this, &SToolBarButtonBlock::IsEnabled ) ); // Bind our widget's visible state to whether or not the button should be visible SetVisibility( TAttribute<EVisibility>(this, &SToolBarButtonBlock::GetBlockVisibility) ); }
/** * Registers general Editor settings. * * @param SettingsModule A reference to the settings module. */ void RegisterGeneralSettings( ISettingsModule& SettingsModule ) { // automation SettingsModule.RegisterSettings("Editor", "General", "AutomationTest", LOCTEXT("AutomationSettingsName", "Automation"), LOCTEXT("AutomationSettingsDescription", "Set up automation test assets."), GetMutableDefault<UAutomationTestSettings>() ); // region & language ISettingsSectionPtr RegionAndLanguageSettingsSection = SettingsModule.RegisterSettings("Editor", "General", "Internationalization", LOCTEXT("InternationalizationSettingsModelName", "Region & Language"), LOCTEXT("InternationalizationSettingsModelDescription", "Configure the editor's behavior to use a language and fit a region's culture."), GetMutableDefault<UInternationalizationSettingsModel>() ); if (RegionAndLanguageSettingsSection.IsValid()) { RegionAndLanguageSettingsSection->OnExport().BindRaw(this, &FEditorSettingsViewerModule::HandleRegionAndLanguageExport); RegionAndLanguageSettingsSection->OnImport().BindRaw(this, &FEditorSettingsViewerModule::HandleRegionAndLanguageImport); RegionAndLanguageSettingsSection->OnSaveDefaults().BindRaw(this, &FEditorSettingsViewerModule::HandleRegionAndLanguageSaveDefaults); RegionAndLanguageSettingsSection->OnResetDefaults().BindRaw(this, &FEditorSettingsViewerModule::HandleRegionAndLanguageResetToDefault); GetMutableDefault<UInternationalizationSettingsModel>()->OnSettingChanged().AddRaw(this, &FEditorSettingsViewerModule::HandleRegionAndLanguageSettingChanged); } // input bindings TWeakPtr<SWidget> InputBindingEditorPanel = FModuleManager::LoadModuleChecked<IInputBindingEditorModule>("InputBindingEditor").CreateInputBindingEditorPanel(); ISettingsSectionPtr InputBindingSettingsSection = SettingsModule.RegisterSettings("Editor", "General", "InputBindings", LOCTEXT("InputBindingsSettingsName", "Keyboard Shortcuts"), LOCTEXT("InputBindingsSettingsDescription", "Configure keyboard shortcuts to quickly invoke operations."), InputBindingEditorPanel.Pin().ToSharedRef() ); if (InputBindingSettingsSection.IsValid()) { InputBindingSettingsSection->OnExport().BindRaw(this, &FEditorSettingsViewerModule::HandleInputBindingsExport); InputBindingSettingsSection->OnImport().BindRaw(this, &FEditorSettingsViewerModule::HandleInputBindingsImport); InputBindingSettingsSection->OnResetDefaults().BindRaw(this, &FEditorSettingsViewerModule::HandleInputBindingsResetToDefault); InputBindingSettingsSection->OnSave().BindRaw(this, &FEditorSettingsViewerModule::HandleInputBindingsSave); } // loading & saving features SettingsModule.RegisterSettings("Editor", "General", "LoadingSaving", LOCTEXT("LoadingSavingSettingsName", "Loading & Saving"), LOCTEXT("LoadingSavingSettingsDescription", "Change how the Editor loads and saves files."), GetMutableDefault<UEditorLoadingSavingSettings>() ); // @todo thomass: proper settings support for source control module GetMutableDefault<UEditorLoadingSavingSettings>()->SccHackInitialize(); // misc unsorted settings SettingsModule.RegisterSettings("Editor", "General", "UserSettings", LOCTEXT("UserSettingsName", "Miscellaneous"), LOCTEXT("UserSettingsDescription", "Customize the behavior, look and feel of the editor."), GetMutableDefault<UEditorPerProjectUserSettings>() ); // experimental features SettingsModule.RegisterSettings("Editor", "General", "Experimental", LOCTEXT("ExperimentalettingsName", "Experimental"), LOCTEXT("ExperimentalSettingsDescription", "Enable and configure experimental Editor features."), GetMutableDefault<UEditorExperimentalSettings>() ); }
//------------------------------------------------------------------------------ static void EditorCommandLineUtilsImpl::RunAssetDiffCommand(TSharedPtr<SWindow> MainEditorWindow, bool bIsRunningProjBrowser, FString CommandArgs) { // if the editor is running the project browser, then the user has to first // select a project (and then the editor will re-launch with this command). if (bIsRunningProjBrowser) { // @TODO: can we run without loading a project? return; } // static so it exists past this function, but doesn't get instantiated // until this function is called static FFauxStandaloneToolManager FauxStandaloneToolManager(MainEditorWindow); TMap<FString, FString> Params; TArray<FString> Tokens; TArray<FString> Switches; UCommandlet::ParseCommandLine(*CommandArgs, Tokens, Switches, Params); if (Switches.Contains("h") || Switches.Contains("?") || Switches.Contains("help")) { RaiseEditorMessageBox(LOCTEXT("DiffCommandHelp", "Diff/Merge Command-Line Help"), DiffCommandHelpTxt, /*bExitOnClose =*/true); return; } if (Switches.Contains("echo")) { RaiseEditorMessageBox(LOCTEXT("DiffCommandHelp", "Passed Command Arguments"), FText::FromString(CommandArgs), /*bExitOnClose =*/true); return; } const int32 FilesNeededForDiff = 2; const int32 FilesNeededForMerge = 4; const int32 MaxFilesNeeded = FilesNeededForMerge; FMergeAsset MergeAssets[MaxFilesNeeded] = { FMergeAsset(TEXT("MergeTool-Left")), FMergeAsset(TEXT("MergeTool-Right")), FMergeAsset(TEXT("MergeTool-Base")), FMergeAsset(TEXT("MergeTool-Merge")), }; FMergeAsset& LeftAsset = MergeAssets[0]; FMergeAsset& ThierAsset = LeftAsset; FMergeAsset& RightAsset = MergeAssets[1]; FMergeAsset& OurAsset = RightAsset; FMergeAsset& BaseAsset = MergeAssets[2]; FMergeAsset& MergeResult = MergeAssets[3]; //-------------------------------------- // Parse file paths from command-line //-------------------------------------- FCommandLineErrorReporter ErrorReporter(DiffCommandSwitch, CommandArgs); int32 ParsedFileCount = 0; for (int32 FileIndex = 0; FileIndex < Tokens.Num() && ParsedFileCount < MaxFilesNeeded; ++FileIndex) { FString& FilePath = Tokens[FileIndex]; FMergeAsset& MergeAsset = MergeAssets[ParsedFileCount]; if (MergeAsset.SetSourceFile(FilePath, ErrorReporter)) { ++ParsedFileCount; } } //-------------------------------------- // Verify file count //-------------------------------------- const bool bWantsMerge = (ParsedFileCount > FilesNeededForDiff); if (ParsedFileCount < FilesNeededForDiff) { ErrorReporter.ReportFatalError(LOCTEXT("TooFewParamsTitle", "Too Few Parameters"), LOCTEXT("TooFewParamsError", "At least two files are needed (for a diff).")); } else if (bWantsMerge && (ParsedFileCount < FilesNeededForMerge)) { ErrorReporter.ReportFatalError(LOCTEXT("TooFewParamsTitle", "Too Few Parameters"), LOCTEXT("TooFewMergeParamsError", "To merge, at least two files are needed.")); } else if (Tokens.Num() > FilesNeededForMerge) { ErrorReporter.ReportFatalError(LOCTEXT("TooManyParamsTitle", "Too Many Parameters"), FText::Format( LOCTEXT("TooManyParamsError", "There were too many command arguments supplied. The maximum files needed are {0} (for merging)"), FText::AsNumber(FilesNeededForMerge) )); } //-------------------------------------- // Load diff/merge asset files //-------------------------------------- bool bLoadSuccess = true; if (bWantsMerge) { bLoadSuccess &= ThierAsset.Load(ErrorReporter); bLoadSuccess &= OurAsset.Load(ErrorReporter); bLoadSuccess &= BaseAsset.Load(ErrorReporter); } else { bLoadSuccess &= LeftAsset.Load(ErrorReporter); bLoadSuccess &= RightAsset.Load(ErrorReporter); } //-------------------------------------- // Verify asset types //-------------------------------------- IAssetTools& AssetTools = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools").Get(); if (bLoadSuccess) { if (LeftAsset.GetClass() != RightAsset.GetClass()) { ErrorReporter.ReportFatalError(LOCTEXT("TypeMismatchTitle", "Asset Type Mismatch"), LOCTEXT("TypeMismatchError", "Cannot compare files of different asset types.")); } else if (bWantsMerge) { UClass* AssetClass = OurAsset.GetClass(); TWeakPtr<IAssetTypeActions> AssetActions = AssetTools.GetAssetTypeActionsForClass(AssetClass); if (AssetClass != BaseAsset.GetClass()) { ErrorReporter.ReportFatalError(LOCTEXT("TypeMismatchTitle", "Asset Type Mismatch"), LOCTEXT("MergeTypeMismatchError", "Cannot merge files of different asset types.")); } else if(!AssetActions.IsValid() || !AssetActions.Pin()->CanMerge()) { ErrorReporter.ReportFatalError(LOCTEXT("CannotMergeTitle", "Cannot Merge"), FText::Format(LOCTEXT("CannotMergeError", "{0} asset files can not be merged."), FText::FromName(AssetClass->GetFName()))); } } } //-------------------------------------- // Preform diff/merge //-------------------------------------- if (bLoadSuccess && !ErrorReporter.HasBlockingError()) { if (bWantsMerge) { // unlike with diff'ing, for merging we rely on asset editors for // merging, and those windows get childed to the main window (so it // needs to be visible) // // @TODO: get it so asset editor windows can be shown standalone FauxStandaloneToolManager.Disable(); RunAssetMerge(BaseAsset, ThierAsset, OurAsset, MergeResult); } else { AssetTools.DiffAssets(LeftAsset.GetAssetObj(), RightAsset.GetAssetObj(), LeftAsset.GetRevisionInfo(), RightAsset.GetRevisionInfo()); } } }
void STutorialRoot::LaunchTutorial(UEditorTutorial* InTutorial, IIntroTutorials::ETutorialStartType InStartType, TWeakPtr<SWindow> InNavigationWindow, FSimpleDelegate InOnTutorialClosed, FSimpleDelegate InOnTutorialExited) { if(InTutorial != nullptr) { CurrentTutorial = InTutorial; // we force a restart if this tutorial was completed if (GetDefault<UTutorialStateSettings>()->HaveCompletedTutorial(CurrentTutorial) && (InStartType == IIntroTutorials::ETutorialStartType::TST_CONTINUE)) { InStartType = IIntroTutorials::ETutorialStartType::TST_RESTART; } bool bHaveSeenTutorial = false; switch (InStartType) { case IIntroTutorials::ETutorialStartType::TST_RESTART: CurrentTutorialStage = 0; break; case IIntroTutorials::ETutorialStartType::TST_LASTSTAGE: CurrentTutorialStage = FMath::Max(0, (CurrentTutorial->Stages.Num() - 1)); break; default: case IIntroTutorials::ETutorialStartType::TST_CONTINUE: CurrentTutorialStage = GetDefault<UTutorialStateSettings>()->GetProgress(CurrentTutorial, bHaveSeenTutorial); break; } // check if we should be launching this tutorial for an asset editor if(InTutorial->AssetToUse.IsValid()) { TArray<FString> AssetPaths; AssetPaths.Add(InTutorial->AssetToUse.AssetLongPathname); FAssetEditorManager::Get().OpenEditorsForAssets(AssetPaths); UObject* Asset = InTutorial->AssetToUse.ResolveObject(); if(Asset != nullptr) { TSharedPtr<IToolkit> Toolkit = FToolkitManager::Get().FindEditorForAsset( Asset ); if(Toolkit.IsValid()) { InNavigationWindow = FSlateApplication::Get().FindWidgetWindow(Toolkit->GetToolkitHost()->GetParentWidget()); // make sure we have a valid tutorial overlay if(InNavigationWindow.IsValid()) { MaybeAddOverlay(InNavigationWindow.Pin().ToSharedRef()); } } } } CurrentTutorialStartTime = FPlatformTime::Seconds(); // launch tutorial for all windows we wrap - any tutorial can display over any window for(auto& TutorialWidget : TutorialWidgets) { if(TutorialWidget.Value.IsValid()) { bool bIsNavigationWindow = false; if (!InNavigationWindow.IsValid()) { bIsNavigationWindow = TutorialWidget.Value.Pin()->IsNavigationVisible(); } else { bIsNavigationWindow = (TutorialWidget.Value.Pin()->GetParentWindow() == InNavigationWindow.Pin()); } TutorialWidget.Value.Pin()->LaunchTutorial(bIsNavigationWindow, InOnTutorialClosed, InOnTutorialExited); } } if (CurrentTutorial != nullptr) { CurrentTutorial->HandleTutorialLaunched(); } if (CurrentTutorial != nullptr && CurrentTutorialStage < CurrentTutorial->Stages.Num()) { CurrentTutorial->HandleTutorialStageStarted(CurrentTutorial->Stages[CurrentTutorialStage].Name); } } }