// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "Stats/Stats.h" #include "Framework/Commands/UICommandList.h" #include "Engine/World.h" #include "TickableEditorObject.h" #include "WorldBrowserDragDrop.h" #include "Misc/EnumClassFlags.h" #include "Misc/IFilter.h" #include "LevelModel.h" #include "Misc/FilterCollection.h" class FMenuBuilder; class IDetailsView; class UEditorEngine; class UMaterialInterface; typedef IFilter< const FLevelModel* > LevelFilter; typedef TFilterCollection< const FLevelModel* > LevelFilterCollection; enum class EBuildHierarchyMenuFlags { None, ShowGameVisibility = 1 << 0 }; ENUM_CLASS_FLAGS(EBuildHierarchyMenuFlags); /** Interface for non-UI presentation logic for a world. */ class WORLDBROWSER_API FLevelCollectionModel : public TSharedFromThis , public FTickableEditorObject { public: DECLARE_EVENT_OneParam( FLevelCollectionModel, FOnNewItemAdded, TSharedPtr); DECLARE_EVENT( FLevelCollectionModel, FSimpleEvent ); FLevelCollectionModel(); virtual ~FLevelCollectionModel() override; /** FTickableEditorObject interface */ virtual void Tick( float DeltaTime ) override; virtual ETickableTickType GetTickableTickType() const override { return ETickableTickType::Always; } virtual TStatId GetStatId() const override; /** FTickableEditorObject interface */ /** @return Whether level collection is read only now */ bool IsReadOnly() const; /** @return Whether level collection is in PIE/SIE mode */ bool IsSimulating() const; /** @return Current simulation world */ UWorld* GetSimulationWorld() const; /** @return Current editor world */ UWorld* GetWorld(bool bEvenIfPendingKill = false) const { return CurrentWorld.Get(bEvenIfPendingKill); } /** @return Whether current world has world origin rebasing enabled */ bool IsOriginRebasingEnabled() const; /** Current world size */ FIntPoint GetWorldSize() const { return WorldSize; } /** @return Root list of levels in hierarchy */ FLevelModelList& GetRootLevelList(); /** @return All level list managed by this level collection */ const FLevelModelList& GetAllLevels() const; /** @return List of filtered levels */ const FLevelModelList& GetFilteredLevels() const; /** @return Currently selected level list */ const FLevelModelList& GetSelectedLevels() const; /** Adds a filter which restricts the Levels shown in UI */ void AddFilter(const TSharedRef& InFilter); /** Removes a filter which restricted the Levels shown in UI */ void RemoveFilter(const TSharedRef& InFilter); /** @return Whether level filtering is active now */ bool IsFilterActive() const; /** Iterates through level hierarchy with given Visitor */ void IterateHierarchy(FLevelModelVisitor& Visitor); /** Sets selected level list */ void SetSelectedLevels(const FLevelModelList& InList); /** Sets selection to a levels that is currently marked as selected in UWorld */ void SetSelectedLevelsFromWorld(); /** @return Found level model which represents specified level object */ TSharedPtr FindLevelModel(ULevel* InLevel) const; /** @return Found level model with specified level package name */ TSharedPtr FindLevelModel(const FName& PackageName) const; /** Hides level in editor worlds */ void HideLevelsInEditor(const FLevelModelList& InLevelList); /** Shows level in editor worlds */ void ShowLevelsInEditor(const FLevelModelList& InLevelList); /** Toggles the selected levels to a visible state; toggles all other levels to an invisible state */ void ShowInEditorOnlySelectedLevels(); /** Toggles the selected levels to an invisible state; toggles all other levels to a visible state */ void ShowInEditorAllButSelectedLevels(); /** Hides level in game worlds */ void HideLevelsInGame(const FLevelModelList& InLevelList); /** Shows level in game worlds */ void ShowLevelsInGame(const FLevelModelList& InLevelList); /** Toggles the selected levels to a visible state for game worlds; toggles all other levels to an invisible state */ void ShowInGameOnlySelectedLevels(); /** Toggles the selected levels to an invisible state for game worlds; toggles all other levels to a visible state */ void ShowInGameAllButSelectedLevels(); /** Unlocks level in the world */ void UnlockLevels(const FLevelModelList& InLevelList); /** Locks level in the world */ void LockLevels(const FLevelModelList& InLevelList); /** Toggles the selected levels to a locked state; toggles all other levels to an unlocked state */ void LockOnlySelectedLevels(); /** Toggles the selected levels to an unlocked state; toggles all other levels to a locked state */ void LockAllButSelectedLevels(); /** Saves level to disk */ void SaveLevels(const FLevelModelList& InLevelList); /** Loads level from disk */ void LoadLevels(const FLevelModelList& InLevelList); /** Unloads levels from the editor */ virtual void UnloadLevels(const FLevelModelList& InLevelList); /** Translate levels by specified delta */ virtual void TranslateLevels(const FLevelModelList& InLevelList, FVector2D InAbsoluteDelta, bool bSnapDelta = true); /** Snaps translation delta */ virtual FVector2D SnapTranslationDelta(const FLevelModelList& InLevelList, FVector2D InAbsoluteDelta, bool bBoundsSnapping, FVector2D::FReal SnappingValue); /** Updates current translation delta, when user drags levels on minimap */ virtual void UpdateTranslationDelta(const FLevelModelList& InLevelList, FVector2D InTranslationDelta, bool bBoundsSnapping, FVector2D::FReal SnappingValue); /** Attach levels as children to specified level */ void AssignParent(const FLevelModelList& InLevels, TSharedPtr InParent); /** Adds all levels in worlds represented by the supplied world list as sublevels */ virtual void AddExistingLevelsFromAssetData(const TArray& WorldList); /** Create drag drop operation for a selected level models */ virtual TSharedPtr CreateDragDropOp() const; /** Create a drag and drop operation for the specified level models */ virtual TSharedPtr CreateDragDropOp(const FLevelModelList& InLevels) const; /** @return Whether specified level passes all filters */ virtual bool PassesAllFilters(const FLevelModel& InLevelModel) const; /** Builds 'hierarchy' commands menu for a selected levels */ virtual void BuildHierarchyMenu(FMenuBuilder& InMenuBuilder, EBuildHierarchyMenuFlags Flags) const; /** Customize 'File' section in main menu */ virtual void CustomizeFileMainMenu(FMenuBuilder& InMenuBuilder) const; /** @return Player view in the PIE/Simulation world */ virtual bool GetPlayerView(FVector& Location, FRotator& Rotation) const; /** @return Observer view in the Editor/Similuation world */ virtual bool GetObserverView(FVector& Location, FRotator& Rotation) const; /** Compares 2 levels by Z order */ virtual bool CompareLevelsZOrder(TSharedPtr InA, TSharedPtr InB) const; /** Registers level details customizations */ virtual void RegisterDetailsCustomization(class FPropertyEditorModule& PropertyModule, TSharedPtr InDetailsView); /** Unregisters level details customizations */ virtual void UnregisterDetailsCustomization(class FPropertyEditorModule& PropertyModule, TSharedPtr InDetailsView); /** @return Whether this level collection model is a tile world */ virtual bool IsTileWorld() const { return false; }; /** Returns true if this collection model will support folders */ virtual bool HasFolderSupport() const { return false; } /** Rebuilds levels collection */ void PopulateLevelsList(); /** Rebuilds the list of filtered Levels */ void PopulateFilteredLevelsList(); /** Request to update levels cached information */ void RequestUpdateAllLevels(); /** Request to redraw all levels */ void RequestRedrawAllLevels(); /** Updates all levels cached information */ void UpdateAllLevels(); /** Redraws all levels */ void RedrawAllLevels(); /** Updates level actor count for all levels */ void UpdateLevelActorsCount(); /** @return whether exactly one level is selected */ bool IsOneLevelSelected() const; /** @return whether at least one level is selected */ bool AreAnyLevelsSelected() const; /** @return wether all selected levels are user managed */ bool AreAllSelectedLevelsUserManaged() const; /** @return whether all the currently selected levels are loaded */ bool AreAllSelectedLevelsLoaded() const; /** @return whether any of the currently selected levels is loaded */ bool AreAnySelectedLevelsLoaded() const; /** @return whether all the currently selected levels are unloaded */ bool AreAllSelectedLevelsUnloaded() const; /** @return whether any of the currently selected levels is unloaded */ bool AreAnySelectedLevelsUnloaded() const; /** @return whether all the currently selected levels are editable */ bool AreAllSelectedLevelsEditable() const; /** @return whether all the currently selected levels are editable and not persistent */ bool AreAllSelectedLevelsEditableAndNotPersistent() const; /** @return whether all the currently selected levels are editable and visible*/ bool AreAllSelectedLevelsEditableAndVisible() const; /** @return whether any of the currently selected levels is editable */ bool AreAnySelectedLevelsEditable() const; /** @return whether any of the currently selected levels is editable and visible*/ bool AreAnySelectedLevelsEditableAndVisible() const; /** @return Whether game visibility of the selected levels is allowed to be changed. */ bool CanExecuteGameVisibilityCommandsForSelectedLevels() const; /** @return Whether game visibility of levels is allowed to be changed. */ bool CanExecuteGameVisibilityCommands() const; /** @return whether currently only one level selected and it is editable */ bool IsSelectedLevelEditable() const; /** @return whether currently only one level selected and a lighting scenario */ bool IsNewLightingScenarioState(bool bExistingState) const; void SetIsLightingScenario(bool bNewLightingScenario); /** @return whether any of the currently selected levels is dirty */ bool AreAnySelectedLevelsDirty() const; /** @return whether at least one actor is selected */ bool AreActorsSelected() const; /** @return whether any of the currently selected levels can be converted to the specified actor bExternal packaging */ bool CanConvertAnyLevelToExternalActors(bool bExternal) const; /** @return whether moving the selected actors to the selected level is a valid action */ bool IsValidMoveActorsToLevel() const; /** @return whether moving the selected foliage to the selected level is a valid action */ bool IsValidMoveFoliageToLevel() const; /** delegate used to pickup when the selection has changed */ void OnActorSelectionChanged(UObject* obj); /** Sets a flag to re-cache whether the selected actors move to the selected level is valid */ void OnActorOrLevelSelectionChanged(); /** @return whether 'display paths' is enabled */ bool GetDisplayPathsState() const; /** Sets 'display paths', whether to show long package name in level display name */ void SetDisplayPathsState(bool bDisplayPaths); /** @return whether 'display actors count' is enabled */ bool GetDisplayActorsCountState() const; /** Sets 'display actors count', whether to show actors count next to level name */ void SetDisplayActorsCountState(bool bDisplayActorsCount); /** Broadcasts whenever items selection has changed */ FSimpleEvent SelectionChanged; void BroadcastSelectionChanged(); /** Broadcasts whenever items collection has changed */ FSimpleEvent CollectionChanged; void BroadcastCollectionChanged(); /** Broadcasts whenever items hierarchy has changed */ FSimpleEvent HierarchyChanged; void BroadcastHierarchyChanged(); /** Broadcasts before levels are unloaded */ FSimpleEvent PreLevelsUnloaded; void BroadcastPreLevelsUnloaded(); /** Broadcasts after levels are unloaded */ FSimpleEvent PostLevelsUnloaded; void BroadcastPostLevelsUnloaded(); /** Editable world axis length */ static double EditableAxisLength(); /** Editable world bounds */ static FBox EditableWorldArea(); /** */ static void SCCCheckOut(const FLevelModelList& InList); static void SCCCheckIn(const FLevelModelList& InList); static void SCCOpenForAdd(const FLevelModelList& InList); static void SCCHistory(const FLevelModelList& InList); static void SCCRefresh(const FLevelModelList& InList); static void SCCDiffAgainstDepot(const FLevelModelList& InList, UEditorEngine* InEditor); /** @return List of valid level package names from a specified level model list*/ static TArray GetPackageNamesList(const FLevelModelList& InList); /** @return List of valid level package filenames from a specified level model list*/ static TArray GetFilenamesList(const FLevelModelList& InList); /** @return List of valid packages from a specified level model list*/ static TArray GetPackagesList(const FLevelModelList& InList); /** @return List of valid level objects from a specified level model list*/ static TArray GetLevelObjectList(const FLevelModelList& InList); /** @return List of loaded level models from a specified level model list*/ static FLevelModelList GetLoadedLevels(const FLevelModelList& InList); /** @return List of all level models found while traversing hierarchy of specified level models */ static FLevelModelList GetLevelsHierarchy(const FLevelModelList& InList); /** @return Total bounding box of specified level models */ static FBox GetLevelsBoundingBox(const FLevelModelList& InList, bool bIncludeChildren); /** @return Total bounding box of specified visible level models */ static FBox GetVisibleLevelsBoundingBox(const FLevelModelList& InList, bool bIncludeChildren); /** @return The UICommandList supported by this collection */ const TSharedRef GetCommandList() const; /** */ void LoadSettings(); /** */ void SaveSettings(); protected: /** Refreshes current cached data */ void RefreshBrowser_Executed(); /** Load selected levels to the world */ void LoadSelectedLevels_Executed(); /** Unload selected level from the world */ void UnloadSelectedLevels_Executed(); /** Make this Level the Current Level */ void MakeLevelCurrent_Executed(); /** Find selected levels in Content Browser */ void FindInContentBrowser_Executed(); /** Is FindInContentBrowser a valid action */ bool IsValidFindInContentBrowser(); /** Moves the selected actors to this level */ void MoveActorsToSelected_Executed(); /** Moves the selected foliage to this level */ void MoveFoliageToSelected_Executed(); /** Saves selected levels */ void SaveSelectedLevels_Executed(); /** Saves selected level under new name */ void SaveSelectedLevelAs_Executed(); /** Migrate selected levels */ void MigrateSelectedLevels_Executed(); /** Expand selected items hierarchy */ void ExpandSelectedItems_Executed(); /** Check-Out selected levels from SCC */ void OnSCCCheckOut(); /** Mark for Add selected levels from SCC */ void OnSCCOpenForAdd(); /** Check-In selected levels from SCC */ void OnSCCCheckIn(); /** Shows the SCC History of selected levels */ void OnSCCHistory(); /** Refreshes the states selected levels from SCC */ void OnSCCRefresh(); /** Diffs selected levels from with those in the SCC depot */ void OnSCCDiffAgainstDepot(); /** Enable source control features */ void OnSCCConnect() const; /** Selects all levels in the collection view model */ void SelectAllLevels_Executed(); /** De-selects all levels in the collection view model */ void DeselectAllLevels_Executed(); /** Inverts level selection in the collection view model */ void InvertSelection_Executed(); /** Adds the Actors in the selected Levels from the viewport's existing selection */ void SelectActors_Executed(); /** Removes the Actors in the selected Levels from the viewport's existing selection */ void DeselectActors_Executed(); /** Set level `Use External Actors` to bExternal */ void ConvertLevelToExternalActors_Executed(bool bExternal); /** Toggles selected levels to a visible state in the viewports for editor worlds */ void ShowInEditorSelectedLevels_Executed(); /** Toggles selected levels to an invisible state in the viewports for editor worlds */ void HideInEditorSelectedLevels_Executed(); /** Toggles the selected levels to a visible state for editor worlds; toggles all other levels to an invisible state. */ void ShowInEditorOnlySelectedLevels_Executed(); /** Toggles the selected levels to an invisible state for editor worlds; toggles all other levels to a visible state. */ void ShowInEditorAllButSelectedLevels_Executed(); /** Toggles all levels to a visible state in the viewports for editor worlds */ void ShowInEditorAllLevels_Executed(); /** Hides all levels to an invisible state in the viewports for editor worlds */ void HideInEditorAllLevels_Executed(); /** Toggles selected levels to a visible state in the viewports for game worlds */ void ShowInGameSelectedLevels_Executed(); /** Toggles selected levels to an invisible state in the viewports */ void HideInGameSelectedLevels_Executed(); /** Toggles the selected levels to a visible state for game worlds; toggles all other levels to an invisible state. */ void ShowInGameOnlySelectedLevels_Executed(); /** Toggles the selected levels to an invisible state for game worlds; toggles all other levels to a visible state. */ void ShowInGameAllButSelectedLevels_Executed(); /** Toggles all levels to a visible state in the viewports for game worlds */ void ShowInGameAllLevels_Executed(); /** Hides all levels to an invisible state in the viewports for game worlds */ void HideInGameAllLevels_Executed(); /** Locks selected levels */ void LockSelectedLevels_Executed(); /** Unlocks selected levels */ void UnlockSelectedLevels_Executed(); /** Toggles the selected levels to a locked state; toggles all other levels to an unlocked state */ void LockOnlySelectedLevels_Executed(); /** Toggles the selected levels to an unlocked state; toggles all other levels to a locked state */ void LockAllButSelectedLevels_Executed(); /** Locks all levels */ void LockAllLevels_Executed(); /** Unlocks all levels */ void UnlockAllLevels_Executed(); /** Toggle all read-only levels */ void ToggleReadOnlyLevels_Executed(); /** true if the SCC Check-Out option is available */ bool CanExecuteSCCCheckOut() const { return bCanExecuteSCCCheckOut; } /** true if the SCC Check-In option is available */ bool CanExecuteSCCCheckIn() const { return bCanExecuteSCCCheckIn; } /** true if the SCC Mark for Add option is available */ bool CanExecuteSCCOpenForAdd() const { return bCanExecuteSCCOpenForAdd; } /** true if Source Control options are generally available. */ bool CanExecuteSCC() const { return bCanExecuteSCC; } /** Fills MenuBulder with Lock level related commands */ void FillLockSubMenu(FMenuBuilder& MenuBuilder); /** Fills MenuBulder with level visisbility related commands */ void FillEditorVisibilitySubMenu(FMenuBuilder& MenuBuilder); /** Fills MenuBulder with level visisbility related commands */ void FillGameVisibilitySubMenu(FMenuBuilder& MenuBuilder); /** Fills MenuBulder with SCC related commands */ void FillSourceControlSubMenu(FMenuBuilder& MenuBuilder); protected: /** */ virtual void Initialize(UWorld* InWorld); /** */ virtual void BindCommands(); /** Removes the Actors in all read-only Levels from the viewport's existing selection */ void DeselectActorsInAllReadOnlyLevel(const FLevelModelList& InLevelList); /** Removes the Actors in all read-only Levels from the viewport's existing selection */ void DeselectSurfaceInAllReadOnlyLevel(const FLevelModelList& InLevelList); /** Called whenever level collection has been changed */ virtual void OnLevelsCollectionChanged(); /** Called whenever level selection has been changed */ virtual void OnLevelsSelectionChanged(); /** Called whenever level selection has been changed outside of this module, usually via World->SetSelectedLevels */ void OnLevelsSelectionChangedOutside(); /** Called whenever level collection hierarchy has been changed */ virtual void OnLevelsHierarchyChanged(); /** Called before loading specified level models into editor */ virtual void OnPreLoadLevels(const FLevelModelList& InList) {}; /** Called before making visible specified level models */ virtual void OnPreShowLevels(const FLevelModelList& InList) {}; /** Called when level was added to the world */ void OnLevelAddedToWorld(ULevel* InLevel, UWorld* InWorld); /** Called when level was removed from the world */ void OnLevelRemovedFromWorld(ULevel* InLevel, UWorld* InWorld); /** Handler for FEditorSupportDelegates::RedrawAllViewports event */ void OnRedrawAllViewports(); /** Handler for when an actor was added to a level */ void OnLevelActorAdded(AActor* InActor); /** Handler for when an actor was removed from a level */ void OnLevelActorDeleted(AActor* InActor); /** Handler for level filter collection changes */ void OnFilterChanged(); /** Caches the variables for which SCC menu options are available */ void CacheCanExecuteSourceControlVars() const; protected: // The editor world from where we pull our data TWeakObjectPtr CurrentWorld; // Has request to update all levels cached bool bRequestedUpdateAllLevels; // Has request to redraw all levels bool bRequestedRedrawAllLevels; // Has request to update actors count for all levels bool bRequestedUpdateActorsCount; /** The list of commands with bound delegates for the Level collection */ const TSharedRef CommandList; /** The collection of filters used to restrict the Levels shown in UI */ const TSharedRef Filters; /** Levels in the root of hierarchy, persistent levels */ FLevelModelList RootLevelsList; /** All levels found in the world */ FLevelModelList AllLevelsList; /** All levels in a map */ TMap> AllLevelsMap; /** Filtered levels from AllLevels list */ FLevelModelList FilteredLevelsList; /** Currently selected levels */ FLevelModelList SelectedLevelsList; /** Cached value of world size (sum of levels size) */ FIntPoint WorldSize; /** Whether we should show long package names in level display names */ bool bDisplayPaths; /** Whether we should show actors count next to level name */ bool bDisplayActorsCount; /** true if the SCC Check-Out option is available */ mutable bool bCanExecuteSCCCheckOut; /** true if the SCC Check-In option is available */ mutable bool bCanExecuteSCCOpenForAdd; /** true if the SCC Mark for Add option is available */ mutable bool bCanExecuteSCCCheckIn; /** true if Source Control options are generally available. */ mutable bool bCanExecuteSCC; /** Flag for whether the selection of levels or actors has changed */ mutable bool bSelectionHasChanged; /** Guard to avoid recursive level selection updates */ bool bUpdatingLevelsSelection; }; // // Helper struct to temporally make specified UObject immune to dirtying // struct FUnmodifiableObject { FUnmodifiableObject(UObject* InObject) : ImmuneObject(InObject) , bTransient(InObject->HasAnyFlags(RF_Transient)) { if (!bTransient) { ImmuneObject->SetFlags(RF_Transient); } } ~FUnmodifiableObject() { if (!bTransient) { ImmuneObject->ClearFlags(RF_Transient); } } private: UObject* ImmuneObject; bool bTransient; }; /** */ struct FTiledLandscapeImportSettings { FTiledLandscapeImportSettings() : Scale3D(100.f,100.f,100.f) , ComponentsNum(8) , QuadsPerSection(63) , SectionsPerComponent(1) , TilesCoordinatesOffset(0,0) , SizeX(1009) , bFlipYAxis(true) , bEditLayersEnabled(false) {} FVector Scale3D; int32 ComponentsNum; int32 QuadsPerSection; int32 SectionsPerComponent; TArray HeightmapFileList; TArray TileCoordinates; FIntPoint TilesCoordinatesOffset; int32 SizeX; bool bFlipYAxis; bool bEditLayersEnabled; TWeakObjectPtr LandscapeMaterial; // Landscape layers struct LandscapeLayerSettings { LandscapeLayerSettings() : bNoBlendWeight(false) {} FName Name; bool bNoBlendWeight; TMap WeightmapFiles; }; TArray LandscapeLayerSettingsList; };