You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
========================== MAJOR FEATURES + CHANGES ========================== Change 2911743 on 2016/03/16 by Allan.Bentham Fix broken tonemapper when using 32bpp encoded HDR. Fixes UE-28359 Cleaned up some ronin integration hacks from ronin. Change 2912053 on 2016/03/16 by Peter.Sauerbrei disable Vulkan in Win32 builds for now #codereview rolando.caloca #jira UE-28465 Change 2914512 on 2016/03/18 by Dmitriy.Dyomin Fixed crash on Nexus5 with Android 4.4.2 when TonemapperFilm is enabled Change 2914944 on 2016/03/18 by Allan.Bentham Fix es2 tonemap flip. Fixes UE-25148 Change 2915248 on 2016/03/18 by Chris.Babcock Updates to support NDK r11 #jira UE-28529 #ue4 #android Change 2919192 on 2016/03/22 by Chris.Babcock NDK level set above 19 forces minSdkVersion to 21 or above to prevent installing on unsupported devices #jira UE-28408 #ue4 #android #codereview Jack.Porter Change 2919591 on 2016/03/23 by Allan.Bentham Merge ronin's Gaussian DoF to 4.11's dof changes. Gaussian DoF will use a single recombine pass with ES31 devices or if no separate translucency is used on SM4+. Added permutation to exclude separate translucency from Gaussian recombine shader when not in use. #codereview martin.mittring Change 2920758 on 2016/03/24 by Dmitriy.Dyomin Fixed: shifting lighting samples octree https://udn.unrealengine.com/questions/276026/lighting-samples-visualization-not-working-with-le.html Change 2920793 on 2016/03/24 by Dmitriy.Dyomin Fixed: When sub-level set to be unloaded but with visbility state set to true, ULevelStreaming::IsStreamingStatePending returns wrong value #jira UE-26426 Change 2920981 on 2016/03/24 by Dmitriy.Dyomin GPU particles support for iOS Metal (A8+ only) #jira UE-11067 #jira UE-28514 #codereview Jack.Porter Change 2921383 on 2016/03/24 by Allan.Bentham Fix inverted image on device when framebuffer fetch/bViewRectSource is not used. #codereview jack.porter Change 2925694 on 2016/03/29 by Dmitriy.Dyomin Fixed: GPU particles and bloom on S7 Mali Change 2927065 on 2016/03/29 by Chris.Babcock Set the DT_SONAME field in linker (stops warning toast) #ue4 #android #codereview Jack.Porter Change 2927375 on 2016/03/30 by Jack.Porter Fixed localization for placement mode Cube, Sphere, Cylinder and Cone Change 2928643 on 2016/03/30 by Jack.Porter Fixed bug introdued by Ronin merge with DepthOfFieldScale setting being locked for BokehDOF #code_review: allan.bentham Change 2932773 on 2016/04/04 by Jack.Porter Reapply android Vulkan version fixes Change 2932853 on 2016/04/05 by Jack.Porter Enable VULKAN_CLEAR_SURFACE_ON_CREATE on Android to prevent assertion Change 2932998 on 2016/04/05 by Jack.Porter Native web browser widget on iOS #jira UEMOB-20 Change 2933420 on 2016/04/05 by Chris.Babcock Removed hard-coded bUseUnityBuild in UBT for Android (contributed by kosz78) #jira UE-29066 #pr #2236 #ue4 #android Change 2934315 on 2016/04/05 by Chris.Babcock Allow Android to act as server with OnlineSubsystemNull (contributed by psychogony) #jira UE-23937 #PR #1820 #ue4 #android #codereview Ryan.Gerleve Change 2935038 on 2016/04/06 by Chris.Babcock Fix OpenGLES31 compile error #ue4 #android #codereview Jack.Porter Change 2936288 on 2016/04/07 by Allan.Bentham Planar reflection captures for mobile. (UE-27426) Added mobile planar reflection flag to material. #codereview jack.porter, daniel.wright Change 2936297 on 2016/04/07 by Allan.Bentham Missed file. Planar reflection captures for mobile. (UE-27426) #codereview jack.porter, daniel.wright Change2937763on 2016/04/08 by Dmitriy.Dyomin Fix InstancedStaticMesh batches for ES2 (contributed by Grimmick) GitHub #2031 #jira UE-26576 #codereview Jack.Porter Change 2937863 on 2016/04/08 by Jack.Porter Merged Ronin CLs 2840392, 2860028 Allow vertex texture fetches on ES2 (requires absolute mip level) Change 2938461 on 2016/04/08 by Chris.Babcock Write Android uninstall batch files #ue4 #android Change 2939679 on 2016/04/11 by Allan.Bentham Remove bStationaryLightUsesCSMForMovableShadows from light component's UI. renamed proxy equivalent and infer its state from Inset Shadows For Movable Objects #codereview jack.porter, daniel.wright Change 2939887 on 2016/04/11 by Chris.Babcock Android ARM64 libraries #jira UEPLAT-1268 #ue4 #android Change 2940125 on 2016/04/11 by Chris.Babcock Added requirements to Arm64 and x86_64 tooltips Change 2941051 on 2016/04/12 by Allan.Bentham Fix for inverted RG channels when using filmic tonemapper with ES2. #codereview jack.porter Change 2942523 on 2016/04/13 by Chris.Babcock Add cxa_demangle build.cs instead of hiding dependency in UEBuildAndroid.cs #ue4 #android #codereview Josh.Adams Change 2942578 on 2016/04/13 by Chris.Babcock Add cxademangle dependency to Core for Android #ue4 #android #codereview Josh.Adams Change 2942997 on 2016/04/13 by Chris.Babcock Run Ant with -quiet first and run again without if there is an error for the log #ue4 #android #codereview Josh.Adams Change 2943320 on 2016/04/14 by Jack.Porter Fixed planar reflection merge errors Change 2943352 on 2016/04/14 by Jack.Porter Fix NAME_VULKAN_ES3_1_ANDROID shader format name #codereview: Rolando.Coloca Change 2943367 on 2016/04/14 by Dmitriy.Dyomin Added cvars to add or strip specific GL extensions from a driver reported extensions string #jira UE-29467 Change 2943425 on 2016/04/14 by Dmitriy.Dyomin Better logging of MobileHDR mode Change 2943461 on 2016/04/14 by Dmitriy.Dyomin Fixing HDR rendering and bloom on Galaxy S7 Change 2943493 on 2016/04/14 by Dmitriy.Dyomin Better HDR fix for devices with ES3 support Change 2943855 on 2016/04/14 by Allan.Bentham Mobile planar reflections. - currently only supports opaque materials #codereview jack.porter Change 2944721 on 2016/04/14 by Chris.Babcock Allow Vulkan-only Android builds #ue4 #android #codereview Allan.Bentham,Jack.Porter Change 2944771 on 2016/04/14 by Dmitriy.Dyomin Fixed: mesh particles crash in ES2 Change 2944827 on 2016/04/15 by Dmitriy.Dyomin Fixed: GPU particles not working on S6 with Android 6.0.1 Change 2944836 on 2016/04/15 by Jack.Porter Disable FX system calls in forward renderer when particles showflag is off Change 2944840 on 2016/04/15 by Jack.Porter Re-enabled non-radial TDeferredLightVS on ES2 for planar and put #if FEATURE_LEVEL >= FEATURE_LEVEL_SM4 around the radial shader code which was tripping up ES2. #codereview: Allan.Bentham, Chris.Babcock, Daniel.Wright Change 2944914 on 2016/04/15 by Jack.Porter Device profiles to detect Galaxy S7 Mali and Adreno variants in Vulkan mode Change 2945020 on 2016/04/15 by Gareth.Martin Cloning changes across from Dev-Landscape to Dev-Mobile due to feature deadline for 4.12. Change 2943560 on 2016/04/14 by Gareth.Martin Added ability to expand landscape bounds #jira UE-28928 #jira UE-25230 Change 2943538 on 2016/04/14 by Gareth.Martin Fix a crash with saving a level >2GB in size. There may still be other crashes with >2GB levels. Change 2943477 on 2016/04/14 by Gareth.Martin Fixed LODFalloff setting on landscape getting reset when using the "Change Landscape Component Size" tool Also moved all the LOD settings together in LandscapeProxy.h because it was messy Change 2942113 on 2016/04/13 by Gareth.Martin Updating comment to clarify behaviour of Foliage Align-To-Normal when Random-Yaw is disabled. Change 2941030 on 2016/04/12 by Gareth.Martin Cleanup and commenting Change 2940994 on 2016/04/12 by Gareth.Martin Implement random scale option for Landscape Grass. #jira UE-25743 Change 2940993 on 2016/04/12 by Gareth.Martin Remove unused BuildFlatTree function from HierarchicalInstancedStaticMeshComponent Change 2940150 on 2016/04/11 by Gareth.Martin Harden UHierarchicalInstancedStaticMeshComponent::UpdateInstanceTransform Change 2940101 on 2016/04/11 by Gareth.Martin Additional checks for bad static mesh when building the HISMC tree Change2945560on 2016/04/15 by Rolando.Caloca DM - Fix for newer Vulkan sdks Change 2945638 on 2016/04/15 by Chris.Babcock Fix permissions on uninstall script on Mac #jira UE-29236 #ue4 #android #lockdown Jack.Porter Change 2945856 on 2016/04/15 by Rolando.Caloca DM - vk - Fix mapped allocations on mobile #lockdown nick.penwarden [CL 2945995 by Chris Babcock in Main branch]
612 lines
21 KiB
C++
612 lines
21 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "PlacementModePrivatePCH.h"
|
|
#include "IPlacementModeModule.h"
|
|
#include "PlacementMode.h"
|
|
#include "AssetToolsModule.h"
|
|
#include "KismetEditorUtilities.h"
|
|
#include "Classes/ActorFactories/ActorFactoryPlanarReflection.h"
|
|
|
|
struct FPlacementCategory : FPlacementCategoryInfo
|
|
{
|
|
FPlacementCategory(const FPlacementCategoryInfo& SourceInfo)
|
|
: FPlacementCategoryInfo(SourceInfo)
|
|
{
|
|
|
|
}
|
|
|
|
FPlacementCategory(FPlacementCategory&& In)
|
|
: FPlacementCategoryInfo(MoveTemp(In))
|
|
, Items(MoveTemp(In.Items))
|
|
{}
|
|
|
|
FPlacementCategory& operator=(FPlacementCategory&& In)
|
|
{
|
|
FPlacementCategoryInfo::operator=(MoveTemp(In));
|
|
Items = MoveTemp(In.Items);
|
|
return *this;
|
|
}
|
|
|
|
TMap<uint32, TSharedPtr<FPlaceableItem>> Items;
|
|
};
|
|
|
|
static TOptional<FLinearColor> GetBasicShapeColorOverride()
|
|
{
|
|
// Get color for basic shapes. It should appear like all the other basic types
|
|
static TOptional<FLinearColor> BasicShapeColorOverride;
|
|
|
|
if( !BasicShapeColorOverride.IsSet() )
|
|
{
|
|
FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));
|
|
TSharedPtr<IAssetTypeActions> AssetTypeActions;
|
|
AssetTypeActions = AssetToolsModule.Get().GetAssetTypeActionsForClass(UClass::StaticClass()).Pin();
|
|
if (AssetTypeActions.IsValid())
|
|
{
|
|
BasicShapeColorOverride = TOptional<FLinearColor>(AssetTypeActions->GetTypeColor());
|
|
}
|
|
}
|
|
return BasicShapeColorOverride;
|
|
}
|
|
|
|
class FPlacementModeModule : public IPlacementModeModule
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Called right after the module's DLL has been loaded and the module object has been created
|
|
*/
|
|
virtual void StartupModule() override
|
|
{
|
|
|
|
TArray< FString > RecentlyPlacedAsStrings;
|
|
GConfig->GetArray(TEXT("PlacementMode"), TEXT("RecentlyPlaced"), RecentlyPlacedAsStrings, GEditorPerProjectIni);
|
|
|
|
//FString ActivePaletteName;
|
|
//GConfig->GetString( TEXT( "PlacementMode" ), TEXT( "ActivePalette" ), ActivePaletteName, GEditorPerProjectIni );
|
|
|
|
for (int Index = 0; Index < RecentlyPlacedAsStrings.Num(); Index++)
|
|
{
|
|
RecentlyPlaced.Add(FActorPlacementInfo(RecentlyPlacedAsStrings[Index]));
|
|
}
|
|
|
|
|
|
FEditorModeRegistry::Get().RegisterMode<FPlacementMode>(
|
|
FBuiltinEditorModes::EM_Placement,
|
|
NSLOCTEXT("PlacementMode", "DisplayName", "Place"),
|
|
FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.PlacementMode", "LevelEditor.PlacementMode.Small"),
|
|
true, 0);
|
|
|
|
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
|
|
AssetRegistryModule.Get().OnAssetRemoved().AddRaw( this, &FPlacementModeModule::OnAssetRemoved );
|
|
AssetRegistryModule.Get().OnAssetRenamed().AddRaw( this, &FPlacementModeModule::OnAssetRenamed );
|
|
|
|
TOptional<FLinearColor> BasicShapeColorOverride = GetBasicShapeColorOverride();
|
|
|
|
|
|
RegisterPlacementCategory(
|
|
FPlacementCategoryInfo(
|
|
NSLOCTEXT( "PlacementMode", "RecentlyPlaced", "Recently Placed" ),
|
|
FBuiltInPlacementCategories::RecentlyPlaced(),
|
|
TEXT("PMRecentlyPlaced"),
|
|
TNumericLimits<int32>::Lowest(),
|
|
false
|
|
)
|
|
);
|
|
|
|
{
|
|
int32 SortOrder = 0;
|
|
FName CategoryName = FBuiltInPlacementCategories::Basic();
|
|
RegisterPlacementCategory(
|
|
FPlacementCategoryInfo(
|
|
NSLOCTEXT( "PlacementMode", "Basic", "Basic" ),
|
|
CategoryName,
|
|
TEXT("PMBasic"),
|
|
10
|
|
)
|
|
);
|
|
|
|
FPlacementCategory* Category = Categories.Find(CategoryName);
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryEmptyActor::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryCharacter::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryPawn::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryPointLight::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryPlayerStart::StaticClass(), SortOrder+=10)) );
|
|
// Cube
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryBasicShape::StaticClass(), FAssetData(LoadObject<UStaticMesh>(nullptr,*UActorFactoryBasicShape::BasicCube.ToString())), FName("ClassThumbnail.Cube"), BasicShapeColorOverride, SortOrder+=10, NSLOCTEXT("PlacementMode", "Cube", "Cube") )) );
|
|
// Sphere
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryBasicShape::StaticClass(), FAssetData(LoadObject<UStaticMesh>(nullptr,*UActorFactoryBasicShape::BasicSphere.ToString())), FName("ClassThumbnail.Sphere"), BasicShapeColorOverride, SortOrder+=10, NSLOCTEXT("PlacementMode", "Sphere", "Sphere") )) );
|
|
// Cylinder
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryBasicShape::StaticClass(), FAssetData(LoadObject<UStaticMesh>(nullptr,*UActorFactoryBasicShape::BasicCylinder.ToString())), FName("ClassThumbnail.Cylinder"), BasicShapeColorOverride, SortOrder+=10, NSLOCTEXT("PlacementMode", "Cylinder", "Cylinder") )) );
|
|
// Cone
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryBasicShape::StaticClass(), FAssetData(LoadObject<UStaticMesh>(nullptr,*UActorFactoryBasicShape::BasicCone.ToString())), FName("ClassThumbnail.Cone"), BasicShapeColorOverride, SortOrder+=10, NSLOCTEXT("PlacementMode", "Cone", "Cone") )) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryTriggerBox::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryTriggerSphere::StaticClass(), SortOrder+=10)) );
|
|
}
|
|
|
|
{
|
|
int32 SortOrder = 0;
|
|
FName CategoryName = FBuiltInPlacementCategories::Lights();
|
|
RegisterPlacementCategory(
|
|
FPlacementCategoryInfo(
|
|
NSLOCTEXT( "PlacementMode", "Lights", "Lights" ),
|
|
CategoryName,
|
|
TEXT("PMLights"),
|
|
20
|
|
)
|
|
);
|
|
|
|
FPlacementCategory* Category = Categories.Find(CategoryName);
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryDirectionalLight::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryPointLight::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactorySpotLight::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactorySkyLight::StaticClass(), SortOrder+=10)) );
|
|
}
|
|
|
|
{
|
|
int32 SortOrder = 0;
|
|
FName CategoryName = FBuiltInPlacementCategories::Visual();
|
|
RegisterPlacementCategory(
|
|
FPlacementCategoryInfo(
|
|
NSLOCTEXT( "PlacementMode", "VisualEffects", "Visual Effects" ),
|
|
CategoryName,
|
|
TEXT("PMVisual"),
|
|
30
|
|
)
|
|
);
|
|
|
|
UActorFactory* PPFactory = GEditor->FindActorFactoryByClassForActorClass( UActorFactoryBoxVolume::StaticClass(), APostProcessVolume::StaticClass() );
|
|
|
|
FPlacementCategory* Category = Categories.Find(CategoryName);
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(PPFactory, FAssetData(APostProcessVolume::StaticClass()), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryAtmosphericFog::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryExponentialHeightFog::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactorySphereReflectionCapture::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryBoxReflectionCapture::StaticClass(), SortOrder+=10)) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryPlanarReflection::StaticClass(), SortOrder += 10)));
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryDeferredDecal::StaticClass(), SortOrder+=10)) );
|
|
}
|
|
|
|
RegisterPlacementCategory(
|
|
FPlacementCategoryInfo(
|
|
NSLOCTEXT( "PlacementMode", "Volumes", "Volumes" ),
|
|
"Volumes",
|
|
TEXT("PMVolumes"),
|
|
40
|
|
)
|
|
);
|
|
|
|
{
|
|
int32 SortOrder = 0;
|
|
FName CategoryName = FBuiltInPlacementCategories::AllClasses();
|
|
RegisterPlacementCategory(
|
|
FPlacementCategoryInfo(
|
|
NSLOCTEXT( "PlacementMode", "AllClasses", "All Classes" ),
|
|
CategoryName,
|
|
TEXT("PMAllClasses"),
|
|
50
|
|
)
|
|
);
|
|
|
|
FPlacementCategory* Category = Categories.Find(CategoryName);
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryEmptyActor::StaticClass())) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryCharacter::StaticClass())) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryPawn::StaticClass())) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryBasicShape::StaticClass(), FAssetData(LoadObject<UStaticMesh>(nullptr, *UActorFactoryBasicShape::BasicCube.ToString())), FName("ClassThumbnail.Cube"), GetBasicShapeColorOverride())) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryBasicShape::StaticClass(), FAssetData(LoadObject<UStaticMesh>(nullptr, *UActorFactoryBasicShape::BasicSphere.ToString())), FName("ClassThumbnail.Sphere"), GetBasicShapeColorOverride())) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryBasicShape::StaticClass(), FAssetData(LoadObject<UStaticMesh>(nullptr, *UActorFactoryBasicShape::BasicCylinder.ToString())), FName("ClassThumbnail.Cylinder"), GetBasicShapeColorOverride())) );
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(*UActorFactoryBasicShape::StaticClass(), FAssetData(LoadObject<UStaticMesh>(nullptr, *UActorFactoryBasicShape::BasicCone.ToString())), FName("ClassThumbnail.Cone"), GetBasicShapeColorOverride())) );
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Called before the module is unloaded, right before the module object is destroyed.
|
|
*/
|
|
virtual void PreUnloadCallback() override
|
|
{
|
|
FEditorModeRegistry::Get().UnregisterMode( FBuiltinEditorModes::EM_Placement );
|
|
|
|
FAssetRegistryModule& AssetRegistryModule = FModuleManager::GetModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
|
|
AssetRegistryModule.Get().OnAssetRemoved().RemoveAll( this );
|
|
AssetRegistryModule.Get().OnAssetRenamed().RemoveAll( this );
|
|
}
|
|
|
|
DECLARE_DERIVED_EVENT( FPlacementModeModule, IPlacementModeModule::FOnRecentlyPlacedChanged, FOnRecentlyPlacedChanged );
|
|
virtual FOnRecentlyPlacedChanged& OnRecentlyPlacedChanged() override { return RecentlyPlacedChanged; }
|
|
|
|
/**
|
|
* Add the specified assets to the recently placed items list
|
|
*/
|
|
virtual void AddToRecentlyPlaced( const TArray< UObject* >& PlacedObjects, UActorFactory* FactoryUsed = NULL ) override
|
|
{
|
|
FString FactoryPath;
|
|
if (FactoryUsed != NULL)
|
|
{
|
|
FactoryPath = FactoryUsed->GetPathName();
|
|
}
|
|
|
|
TArray< UObject* > FilteredPlacedObjects;
|
|
for (UObject* PlacedObject : PlacedObjects)
|
|
{
|
|
// Don't include null placed objects that just have factories.
|
|
if (PlacedObject == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Don't add brush builders to the recently placed.
|
|
if (PlacedObject->IsA(UBrushBuilder::StaticClass()))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
FilteredPlacedObjects.Add(PlacedObject);
|
|
}
|
|
|
|
// Don't change the recently placed if nothing passed the filter.
|
|
if (FilteredPlacedObjects.Num() == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool Changed = false;
|
|
for (int Index = 0; Index < FilteredPlacedObjects.Num(); Index++)
|
|
{
|
|
Changed |= RecentlyPlaced.Remove(FActorPlacementInfo(FilteredPlacedObjects[Index]->GetPathName(), FactoryPath)) > 0;
|
|
}
|
|
|
|
for (int Index = 0; Index < FilteredPlacedObjects.Num(); Index++)
|
|
{
|
|
if (FilteredPlacedObjects[Index] != NULL)
|
|
{
|
|
RecentlyPlaced.Insert(FActorPlacementInfo(FilteredPlacedObjects[Index]->GetPathName(), FactoryPath), 0);
|
|
Changed = true;
|
|
}
|
|
}
|
|
|
|
for (int Index = RecentlyPlaced.Num() - 1; Index >= 20; Index--)
|
|
{
|
|
RecentlyPlaced.RemoveAt(Index);
|
|
Changed = true;
|
|
}
|
|
|
|
if (Changed)
|
|
{
|
|
TArray< FString > RecentlyPlacedAsStrings;
|
|
for (int Index = 0; Index < RecentlyPlaced.Num(); Index++)
|
|
{
|
|
RecentlyPlacedAsStrings.Add(RecentlyPlaced[Index].ToString());
|
|
}
|
|
|
|
GConfig->SetArray(TEXT("PlacementMode"), TEXT("RecentlyPlaced"), RecentlyPlacedAsStrings, GEditorPerProjectIni);
|
|
RecentlyPlacedChanged.Broadcast(RecentlyPlaced);
|
|
}
|
|
}
|
|
|
|
void OnAssetRemoved(const FAssetData& /*InRemovedAssetData*/)
|
|
{
|
|
RecentlyPlacedChanged.Broadcast(RecentlyPlaced);
|
|
}
|
|
|
|
void OnAssetRenamed(const FAssetData& AssetData, const FString& OldObjectPath)
|
|
{
|
|
for (auto& RecentlyPlacedItem : RecentlyPlaced)
|
|
{
|
|
if (RecentlyPlacedItem.ObjectPath == OldObjectPath)
|
|
{
|
|
RecentlyPlacedItem.ObjectPath = AssetData.ObjectPath.ToString();
|
|
break;
|
|
}
|
|
}
|
|
|
|
RecentlyPlacedChanged.Broadcast(RecentlyPlaced);
|
|
}
|
|
|
|
/**
|
|
* Add the specified asset to the recently placed items list
|
|
*/
|
|
virtual void AddToRecentlyPlaced( UObject* Asset, UActorFactory* FactoryUsed = NULL ) override
|
|
{
|
|
TArray< UObject* > Assets;
|
|
Assets.Add( Asset );
|
|
AddToRecentlyPlaced( Assets, FactoryUsed );
|
|
}
|
|
|
|
/**
|
|
* Get a copy of the recently placed items list
|
|
*/
|
|
virtual const TArray< FActorPlacementInfo >& GetRecentlyPlaced() const override
|
|
{
|
|
return RecentlyPlaced;
|
|
}
|
|
|
|
/** @return the event that is broadcast whenever the placement mode enters a placing session */
|
|
DECLARE_DERIVED_EVENT( FPlacementModeModule, IPlacementModeModule::FOnStartedPlacingEvent, FOnStartedPlacingEvent );
|
|
virtual FOnStartedPlacingEvent& OnStartedPlacing() override
|
|
{
|
|
return StartedPlacingEvent;
|
|
}
|
|
virtual void BroadcastStartedPlacing( const TArray< UObject* >& Assets ) override
|
|
{
|
|
StartedPlacingEvent.Broadcast( Assets );
|
|
}
|
|
|
|
/** @return the event that is broadcast whenever the placement mode exits a placing session */
|
|
DECLARE_DERIVED_EVENT( FPlacementModeModule, IPlacementModeModule::FOnStoppedPlacingEvent, FOnStoppedPlacingEvent );
|
|
virtual FOnStoppedPlacingEvent& OnStoppedPlacing() override
|
|
{
|
|
return StoppedPlacingEvent;
|
|
}
|
|
virtual void BroadcastStoppedPlacing( bool bWasSuccessfullyPlaced ) override
|
|
{
|
|
StoppedPlacingEvent.Broadcast( bWasSuccessfullyPlaced );
|
|
}
|
|
|
|
public:
|
|
|
|
virtual bool RegisterPlacementCategory(const FPlacementCategoryInfo& Info)
|
|
{
|
|
if (Categories.Contains(Info.UniqueHandle))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Categories.Add(Info.UniqueHandle, Info);
|
|
return true;
|
|
}
|
|
|
|
virtual const FPlacementCategoryInfo* GetRegisteredPlacementCategory(FName CategoryName) const override
|
|
{
|
|
return Categories.Find(CategoryName);
|
|
}
|
|
|
|
virtual void UnregisterPlacementCategory(FName Handle)
|
|
{
|
|
Categories.Remove(Handle);
|
|
}
|
|
|
|
virtual void GetSortedCategories(TArray<FPlacementCategoryInfo>& OutCategories) const
|
|
{
|
|
TArray<FName> SortedNames;
|
|
Categories.GenerateKeyArray(SortedNames);
|
|
|
|
SortedNames.Sort([&](const FName& A, const FName& B){
|
|
return Categories[A].SortOrder < Categories[B].SortOrder;
|
|
});
|
|
|
|
OutCategories.Reset(Categories.Num());
|
|
for (const FName& Name : SortedNames)
|
|
{
|
|
OutCategories.Add(Categories[Name]);
|
|
}
|
|
}
|
|
|
|
virtual TOptional<FPlacementModeID> RegisterPlaceableItem(FName CategoryName, const TSharedRef<FPlaceableItem>& InItem)
|
|
{
|
|
FPlacementCategory* Category = Categories.Find(CategoryName);
|
|
if (Category && !Category->CustomGenerator)
|
|
{
|
|
FPlacementModeID ID = CreateID(CategoryName);
|
|
Category->Items.Add(ID.UniqueID, InItem);
|
|
return ID;
|
|
}
|
|
return TOptional<FPlacementModeID>();
|
|
}
|
|
|
|
virtual void UnregisterPlaceableItem(FPlacementModeID ID)
|
|
{
|
|
FPlacementCategory* Category = Categories.Find(ID.Category);
|
|
if (Category)
|
|
{
|
|
Category->Items.Remove(ID.UniqueID);
|
|
}
|
|
}
|
|
|
|
virtual void GetItemsForCategory(FName CategoryName, TArray<TSharedPtr<FPlaceableItem>>& OutItems) const
|
|
{
|
|
const FPlacementCategory* Category = Categories.Find(CategoryName);
|
|
if (Category)
|
|
{
|
|
for (auto& Pair : Category->Items)
|
|
{
|
|
OutItems.Add(Pair.Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void GetFilteredItemsForCategory(FName CategoryName, TArray<TSharedPtr<FPlaceableItem>>& OutItems, TFunctionRef<bool(const TSharedPtr<FPlaceableItem>&)> Filter) const
|
|
{
|
|
const FPlacementCategory* Category = Categories.Find(CategoryName);
|
|
if (Category)
|
|
{
|
|
for (auto& Pair : Category->Items)
|
|
{
|
|
if (Filter(Pair.Value))
|
|
{
|
|
OutItems.Add(Pair.Value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void RegenerateItemsForCategory(FName Category) override
|
|
{
|
|
if (Category == FBuiltInPlacementCategories::RecentlyPlaced())
|
|
{
|
|
RefreshRecentlyPlaced();
|
|
}
|
|
else if (Category == FBuiltInPlacementCategories::Volumes())
|
|
{
|
|
RefreshVolumes();
|
|
}
|
|
else if (Category == FBuiltInPlacementCategories::AllClasses())
|
|
{
|
|
RefreshAllPlaceableClasses();
|
|
}
|
|
|
|
// @todo: Broadcast so clients can update dynamic lists?
|
|
}
|
|
|
|
void RefreshRecentlyPlaced()
|
|
{
|
|
FName CategoryName = FBuiltInPlacementCategories::RecentlyPlaced();
|
|
|
|
FPlacementCategory* Category = Categories.Find(CategoryName);
|
|
if (!Category)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Category->Items.Reset();
|
|
|
|
|
|
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>( TEXT( "AssetRegistry" ) );
|
|
|
|
for (const FActorPlacementInfo& RecentlyPlacedItem : RecentlyPlaced)
|
|
{
|
|
UObject* Asset = FindObject<UObject>(nullptr, *RecentlyPlacedItem.ObjectPath);
|
|
|
|
// If asset is pending delete, it will not be marked as RF_Standalone, in which case we skip it
|
|
if (Asset != nullptr && Asset->HasAnyFlags(RF_Standalone))
|
|
{
|
|
FAssetData AssetData = AssetRegistryModule.Get().GetAssetByObjectPath(*RecentlyPlacedItem.ObjectPath);
|
|
|
|
if (AssetData.IsValid())
|
|
{
|
|
UActorFactory* Factory = FindObject<UActorFactory>(nullptr, *RecentlyPlacedItem.Factory);
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(Factory, AssetData) ));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Broadcast?
|
|
}
|
|
|
|
void RefreshVolumes()
|
|
{
|
|
FName CategoryName = FBuiltInPlacementCategories::Volumes();
|
|
|
|
FPlacementCategory* Category = Categories.Find(CategoryName);
|
|
if (!Category)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Category->Items.Reset();
|
|
|
|
// Add loaded classes
|
|
for ( TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt )
|
|
{
|
|
const UClass* Class = *ClassIt;
|
|
|
|
if (!Class->HasAllClassFlags(CLASS_NotPlaceable) &&
|
|
!Class->HasAnyClassFlags(CLASS_Abstract | CLASS_Deprecated | CLASS_NewerVersionExists) &&
|
|
Class->IsChildOf(AVolume::StaticClass()) &&
|
|
Class->ClassGeneratedBy == nullptr )
|
|
{
|
|
UActorFactory* Factory = GEditor->FindActorFactoryByClassForActorClass(UActorFactoryBoxVolume::StaticClass(), Class);
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(Factory, FAssetData(Class)) ));
|
|
}
|
|
}
|
|
|
|
// Broadcast?
|
|
}
|
|
|
|
void RefreshAllPlaceableClasses()
|
|
{
|
|
FName CategoryName = FBuiltInPlacementCategories::AllClasses();
|
|
|
|
// Unregister old stuff
|
|
FPlacementCategory* Category = Categories.Find(CategoryName);
|
|
if (!Category)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Category->Items.Reset();
|
|
|
|
// Make a map of UClasses to ActorFactories that support them
|
|
const TArray< UActorFactory *>& ActorFactories = GEditor->ActorFactories;
|
|
TMap<UClass*, UActorFactory*> ActorFactoryMap;
|
|
for ( int32 FactoryIdx = 0; FactoryIdx < ActorFactories.Num(); ++FactoryIdx )
|
|
{
|
|
UActorFactory* ActorFactory = ActorFactories[FactoryIdx];
|
|
|
|
if ( ActorFactory )
|
|
{
|
|
ActorFactoryMap.Add(ActorFactory->GetDefaultActorClass(FAssetData()), ActorFactory);
|
|
}
|
|
}
|
|
|
|
FAssetData NoAssetData;
|
|
FText UnusedErrorMessage;
|
|
|
|
// Add loaded classes
|
|
for ( TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt )
|
|
{
|
|
// Don't offer skeleton classes
|
|
bool bIsSkeletonClass = FKismetEditorUtilities::IsClassABlueprintSkeleton(*ClassIt);
|
|
|
|
if ( !ClassIt->HasAllClassFlags(CLASS_NotPlaceable) &&
|
|
!ClassIt->HasAnyClassFlags(CLASS_Abstract | CLASS_Deprecated | CLASS_NewerVersionExists) &&
|
|
ClassIt->IsChildOf(AActor::StaticClass()) &&
|
|
( !ClassIt->IsChildOf(ABrush::StaticClass()) || ClassIt->IsChildOf(AVolume::StaticClass()) ) &&
|
|
!bIsSkeletonClass )
|
|
{
|
|
UActorFactory* ActorFactory = ActorFactoryMap.FindRef(*ClassIt);
|
|
|
|
const bool IsVolume = ClassIt->IsChildOf(AVolume::StaticClass());
|
|
|
|
if ( IsVolume )
|
|
{
|
|
ActorFactory = GEditor->FindActorFactoryByClassForActorClass(UActorFactoryBoxVolume::StaticClass(), *ClassIt);
|
|
}
|
|
else if (ActorFactory && !ActorFactory->CanCreateActorFrom(NoAssetData, UnusedErrorMessage))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Category->Items.Add(CreateID(), MakeShareable( new FPlaceableItem(ActorFactory, FAssetData(*ClassIt)) ));
|
|
}
|
|
}
|
|
|
|
// Broadcast?
|
|
}
|
|
|
|
private:
|
|
|
|
uint32 CreateID()
|
|
{
|
|
static uint32 IDCounter = 0;
|
|
uint32 Next = ++IDCounter;
|
|
checkf(Next, TEXT("uint32 overflow. If this occurs, something's gone seriously wrong."))
|
|
return Next;
|
|
}
|
|
|
|
FPlacementModeID CreateID(FName InCategory)
|
|
{
|
|
FPlacementModeID NewID;
|
|
NewID.UniqueID = CreateID();
|
|
NewID.Category = InCategory;
|
|
|
|
|
|
return NewID;
|
|
}
|
|
|
|
private:
|
|
|
|
TMap<FName, FPlacementCategory> Categories;
|
|
|
|
TArray< FActorPlacementInfo > RecentlyPlaced;
|
|
FOnRecentlyPlacedChanged RecentlyPlacedChanged;
|
|
|
|
FOnStartedPlacingEvent StartedPlacingEvent;
|
|
FOnStoppedPlacingEvent StoppedPlacingEvent;
|
|
|
|
TArray< TSharedPtr<FExtender> > ContentPaletteFiltersExtenders;
|
|
TArray< TSharedPtr<FExtender> > PaletteExtenders;
|
|
};
|
|
|
|
IMPLEMENT_MODULE( FPlacementModeModule, PlacementMode );
|
|
|