Skip to content
Open
19 changes: 19 additions & 0 deletions Source/PrefabricatorEditor/Private/PrefabEditorCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Framework/Commands/UIAction.h"
#include "Framework/Commands/UICommandList.h"
#include "UObject/Object.h"
#include "PrefabricatorEditorModule.h"

#define LOCTEXT_NAMESPACE "ContentBrowser"

Expand All @@ -30,6 +31,24 @@ void FPrefabricatorCommands::RegisterCommands() {
FExecuteAction::CreateStatic(&FPrefabTools::CreatePrefab),
FCanExecuteAction::CreateStatic(&FPrefabTools::CanCreatePrefab)
);

UI_COMMAND(AllowOnlyPrefabSelection, "Select Only Prefabs", "Allow only prefabs to be selected", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::NumPadOne));

LevelMenuActionList->MapAction(
AllowOnlyPrefabSelection
, FExecuteAction::CreateStatic(&FPrefabTools::SetAllowOnlyPrefabSelection)
, FCanExecuteAction()
, FIsActionChecked::CreateStatic(&FPrefabTools::GetAllowOnlyPrefabSelection)
);


UI_COMMAND(CreatePrefabZeroPivot, "Create Prefab On Zero Oirgin", "Create New prefab on Zeroed pivot", EUserInterfaceActionType::Button, FInputChord(EKeys::NumPadTwo));

LevelMenuActionList->MapAction(
CreatePrefabZeroPivot
, FExecuteAction::CreateStatic(&FPrefabTools::CreatePrefabOnZeroPivot)
, FCanExecuteAction::CreateStatic(&FPrefabTools::CanCreatePrefab)
);
}


Expand Down
21 changes: 20 additions & 1 deletion Source/PrefabricatorEditor/Private/PrefabricatorEditorModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,20 @@
#include "PropertyEditorModule.h"
#include "ThumbnailRendering/ThumbnailManager.h"
#include "UnrealEdGlobals.h"

#include "Engine/Selection.h"
#include "Prefab/PrefabActor.h"
#define LOCTEXT_NAMESPACE "PrefabricatorEditorModule"



class FPrefabricatorEditorModule : public IPrefabricatorEditorModule
{
FPrefabDetailsExtend PrefabActorDetailsExtender;
FDelegateHandle SelectionDelegateHandle;

virtual void StartupModule() override
{
SelectionDelegateHandle = USelection::SelectObjectEvent.AddRaw(this, &FPrefabricatorEditorModule::OnSelectionChanged);
FPrefabEditorStyle::Initialize();
FPrefabricatorCommands::Register();

Expand Down Expand Up @@ -129,6 +132,22 @@ class FPrefabricatorEditorModule : public IPrefabricatorEditorModule
TSharedPtr<IComponentAssetBroker> PrefabAssetBroker;
TArray< TSharedPtr<IAssetTypeActions> > CreatedAssetTypeActions;
EAssetTypeCategories::Type PrefabricatorAssetCategoryBit;

void OnSelectionChanged(UObject* Object)
{
if(FPrefabTools::GetAllowOnlyPrefabSelection())
{
APrefabActor* Prefab = Cast<APrefabActor>(Object);

if (!Prefab)
{
GEditor->GetSelectedActors()->BeginBatchSelectOperation();
GEditor->GetSelectedActors()->Select(Object, false);
GEditor->GetSelectedActors()->EndBatchSelectOperation(false);
}
}

}
};

IMPLEMENT_MODULE(FPrefabricatorEditorModule, PrefabricatorEditor)
Expand Down
2 changes: 2 additions & 0 deletions Source/PrefabricatorEditor/Private/UI/EditorUIExtender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ void FEditorUIExtender::Extend()

MenuBuilder.BeginSection("Prefabricator-Prefabs", LOCTEXT("PrefabHeader", "Prefabs"));
MenuBuilder.AddMenuEntry(FPrefabricatorCommands::Get().CreatePrefab);
MenuBuilder.AddMenuEntry(FPrefabricatorCommands::Get().CreatePrefabZeroPivot);
MenuBuilder.AddMenuEntry(FPrefabricatorCommands::Get().AllowOnlyPrefabSelection);
MenuBuilder.EndSection();

MenuBuilder.BeginSection("Prefabricator-Randomization", LOCTEXT("RandomizationHeader", "Randomization"));
Expand Down
3 changes: 2 additions & 1 deletion Source/PrefabricatorEditor/Public/PrefabEditorCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class PREFABRICATOREDITOR_API FPrefabricatorCommands : public TCommands<FPrefabr

TSharedPtr<FUICommandInfo> CreatePrefab;
TSharedPtr<class FUICommandList> LevelMenuActionList;

TSharedPtr< FUICommandInfo > AllowOnlyPrefabSelection;
TSharedPtr<FUICommandInfo> CreatePrefabZeroPivot;
};


Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
class PREFABRICATOREDITOR_API IPrefabricatorEditorModule : public IModuleInterface
{

public:

/**
Expand All @@ -42,5 +41,4 @@ class PREFABRICATOREDITOR_API IPrefabricatorEditorModule : public IModuleInterfa
virtual EAssetTypeCategories::Type GetPrefabricatorAssetCategoryBit() const = 0;
virtual FPrefabDetailsExtend& GetPrefabActorDetailsExtender() = 0;
virtual void UpgradePrefabAssets() = 0;
};

};
34 changes: 19 additions & 15 deletions Source/PrefabricatorRuntime/Private/Asset/PrefabricatorAsset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@ FVector FPrefabricatorAssetUtils::FindPivot(const TArray<AActor*>& InActors)
Bounds += ActorBounds;
}

switch (GetDefault< UPrefabricatorSettings>()->PivotPosition)
{
case EPrefabricatorPivotPosition::ExtremeLeft:
Pivot = Bounds.GetCenter() - Bounds.GetExtent();
break;
case EPrefabricatorPivotPosition::ExtremeRight:
Pivot = Bounds.GetCenter() + Bounds.GetExtent();
break;
case EPrefabricatorPivotPosition::Center:
Pivot = Bounds.GetCenter();
break;
default:;
switch (GetDefault< UPrefabricatorSettings>()->PivotPosition)
{
case EPrefabricatorPivotPosition::ExtremeLeft:
Pivot = Bounds.GetCenter() - Bounds.GetExtent();
break;
case EPrefabricatorPivotPosition::ExtremeRight:
Pivot = Bounds.GetCenter() + Bounds.GetExtent();
break;
case EPrefabricatorPivotPosition::Center:
Pivot = Bounds.GetCenter();
break;
default:;
}
Pivot.Z = Bounds.Min.Z;
}
Expand Down Expand Up @@ -95,7 +95,7 @@ UPrefabricatorAsset* UPrefabricatorAssetCollection::GetPrefabAsset(const FPrefab

FRandomStream Random;
Random.Initialize(InConfig.Seed);

TSoftObjectPtr<UPrefabricatorAsset> PrefabAssetPtr;

if (TotalWeight == 0) {
Expand All @@ -116,11 +116,15 @@ UPrefabricatorAsset* UPrefabricatorAssetCollection::GetPrefabAsset(const FPrefab
}
StartRange = EndRange;
}
if (!bFound) {
if (PrefabAssetPtr.IsNull()) {
PrefabAssetPtr = Prefabs.Last().PrefabAsset;
}
}
return PrefabAssetPtr.LoadSynchronous();

if (!PrefabAssetPtr.IsNull()) {
return PrefabAssetPtr.LoadSynchronous();
}
return nullptr;
}

void UPrefabricatorEventListener::PostSpawn_Implementation(APrefabActor* Prefab)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void UPrefabComponent::PostEditChangeProperty(struct FPropertyChangedEvent& e)
}
}
}

Super::PostEditChangeProperty(e);
}
#endif // WITH_EDITOR

141 changes: 138 additions & 3 deletions Source/PrefabricatorRuntime/Private/Prefab/PrefabTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "Serialization/ObjectAndNameAsStringProxyArchive.h"
#include "Serialization/ObjectReader.h"
#include "Serialization/ObjectWriter.h"
#include "PrefabricatorSettings.h"

DEFINE_LOG_CATEGORY_STATIC(LogPrefabTools, Log, All);

Expand Down Expand Up @@ -93,6 +94,22 @@ void FPrefabTools::IterateChildrenRecursive(APrefabActor* Prefab, TFunction<void
}
}

void FPrefabTools::SetAllowOnlyPrefabSelection()
{
auto* Settings = GetMutableDefault<UPrefabricatorSettings>();

// Toggle 'allow select translucent'
Settings->bSelectOnlyPrefabs = !Settings->bSelectOnlyPrefabs;
#if WITH_EDITOR
Settings->PostEditChange();
#endif
}

bool FPrefabTools::GetAllowOnlyPrefabSelection()
{
return GetDefault<UPrefabricatorSettings>()->bSelectOnlyPrefabs;
}

bool FPrefabTools::CanCreatePrefab()
{
return GetNumSelectedActors() > 0;
Expand Down Expand Up @@ -133,7 +150,16 @@ namespace {
}

}
void FPrefabTools::CreatePrefabFromActors(const TArray<AActor*>& InActors)

void FPrefabTools::CreatePrefabOnZeroPivot()
{
TArray<AActor*> SelectedActors;
GetSelectedActors(SelectedActors);

CreatePrefabFromActorsOnZeroPivot(SelectedActors);
}

void FPrefabTools::CreatePrefabFromActorsOnZeroPivot(const TArray<AActor*>& InActors)
{
TArray<AActor*> Actors;
SanitizePrefabActorsForCreation(InActors, Actors);
Expand All @@ -152,10 +178,68 @@ void FPrefabTools::CreatePrefabFromActors(const TArray<AActor*>& InActors)
Service->BeginTransaction(LOCTEXT("TransLabel_CreatePrefab", "Create Prefab"));
}


UWorld* World = Actors[0]->GetWorld();

FVector Pivot = FPrefabricatorAssetUtils::FindPivot(Actors);
APrefabActor* PrefabActor = World->SpawnActor<APrefabActor>(Pivot, FRotator::ZeroRotator);
FVector Pivot = FVector::ZeroVector;

TArray<FTransform> OriginalActorTransforms;

for (AActor* A : Actors)
{
OriginalActorTransforms.Add(A->GetTransform());
FBox BB = A->GetComponentsBoundingBox();

A->SetActorRotation(FRotator::ZeroRotator);
}

{
float LowestZ = MAX_flt;
FBox Bounds(EForceInit::ForceInit);
for (AActor* Actor : Actors)
{
FBox ActorBounds = FPrefabTools::GetPrefabBounds(Actor, false);
Bounds += ActorBounds;
}

Pivot = Bounds.GetCenter();
Pivot.Z = Bounds.Min.Z;
}

FVector RelativePosition = Pivot;

FActorSpawnParameters SpanParams;
SpanParams.bNoFail = true;

APrefabActor* PrefabActorTemp = World->SpawnActor<APrefabActor>(RelativePosition, FRotator::ZeroRotator, SpanParams);
PrefabActorTemp->GetRootComponent()->SetMobility(EComponentMobility::Static);

//attach to dummy
for (AActor* A : Actors)
{
A->DetachFromActor(FDetachmentTransformRules(EDetachmentRule::KeepWorld, true));
A->AttachToActor(PrefabActorTemp, FAttachmentTransformRules(EAttachmentRule::KeepWorld, true));

FTransform RT = A->GetRootComponent()->GetRelativeTransform();

FVector RelLoc = RT.GetLocation();
}

//move to world origin
PrefabActorTemp->SetActorLocation(FVector::ZeroVector);

//detach from dummy.
for (int32 Idx = 0; Idx < Actors.Num(); Idx++)
{
Actors[Idx]->DetachFromActor(FDetachmentTransformRules(EDetachmentRule::KeepWorld, true));
}

//we don't need it anymore.
PrefabActorTemp->Destroy(true, true);

Pivot = FVector::ZeroVector;

APrefabActor* PrefabActor = World->SpawnActor<APrefabActor>(FVector::ZeroVector, FRotator::ZeroRotator);

// Find the compatible mobility for the prefab actor
EComponentMobility::Type Mobility = FPrefabricatorAssetUtils::FindMobility(Actors);
Expand All @@ -167,6 +251,11 @@ void FPrefabTools::CreatePrefabFromActors(const TArray<AActor*>& InActors)
ParentActors(PrefabActor, Actor);
}

for (int32 Idx = 0; Idx < Actors.Num(); Idx++)
{
Actors[Idx]->SetActorRotation(OriginalActorTransforms[Idx].GetRotation());
}

if (Service.IsValid()) {
Service->EndTransaction();
}
Expand All @@ -175,6 +264,52 @@ void FPrefabTools::CreatePrefabFromActors(const TArray<AActor*>& InActors)

SelectPrefabActor(PrefabActor);

PrefabActor->SetActorLocation(RelativePosition);
}

void FPrefabTools::CreatePrefabFromActors(const TArray<AActor*>& InActors)
{
TArray<AActor*> Actors;
SanitizePrefabActorsForCreation(InActors, Actors);

if (Actors.Num() == 0) {
return;
}

UPrefabricatorAsset* PrefabAsset = CreatePrefabAsset();
if (!PrefabAsset) {
return;
}

TSharedPtr<IPrefabricatorService> Service = FPrefabricatorService::Get();
if (Service.IsValid()) {
Service->BeginTransaction(LOCTEXT("TransLabel_CreatePrefab", "Create Prefab"));
}


UWorld* World = Actors[0]->GetWorld();

FVector Pivot = FPrefabricatorAssetUtils::FindPivot(Actors);

APrefabActor* PrefabActor = World->SpawnActor<APrefabActor>(Pivot, FRotator::ZeroRotator);

// Find the compatible mobility for the prefab actor
EComponentMobility::Type Mobility = FPrefabricatorAssetUtils::FindMobility(Actors);
PrefabActor->GetRootComponent()->SetMobility(Mobility);

PrefabActor->PrefabComponent->PrefabAssetInterface = PrefabAsset;
// Attach the actors to the prefab
for (AActor* Actor : Actors) {
ParentActors(PrefabActor, Actor);
}

if (Service.IsValid()) {
Service->EndTransaction();
}

SaveStateToPrefabAsset(PrefabActor);

SelectPrefabActor(PrefabActor);
}

void FPrefabTools::AssignAssetUserData(AActor* InActor, const FGuid& InItemID, APrefabActor* Prefab)
Expand Down
9 changes: 8 additions & 1 deletion Source/PrefabricatorRuntime/Public/Prefab/PrefabTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ class PREFABRICATORRUNTIME_API FPrefabTools {
public:
static bool CanCreatePrefab();
static void CreatePrefab();
static void CreatePrefabFromActors(const TArray<AActor*>& Actors);
static void CreatePrefabFromActors(const TArray<AActor*>& InActors);

static void CreatePrefabOnZeroPivot();
static void CreatePrefabFromActorsOnZeroPivot(const TArray<AActor*>& Actors);

static void AssignAssetUserData(AActor* InActor, const FGuid& InItemID, APrefabActor* Prefab);

static void SaveStateToPrefabAsset(APrefabActor* PrefabActor);
Expand All @@ -43,6 +47,9 @@ class PREFABRICATORRUNTIME_API FPrefabTools {
static int32 GetRandomSeed(const FRandomStream& Random);

static void IterateChildrenRecursive(APrefabActor* Actor, TFunction<void(AActor*)> Visit);

static void SetAllowOnlyPrefabSelection();
static bool GetAllowOnlyPrefabSelection();
};

class PREFABRICATORRUNTIME_API FPrefabVersionControl {
Expand Down
3 changes: 3 additions & 0 deletions Source/PrefabricatorRuntime/Public/PrefabricatorSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class PREFABRICATORRUNTIME_API UPrefabricatorSettings : public UDeveloperSetting
UPROPERTY(EditAnywhere, BlueprintReadOnly, config, Category = "Settings")
bool bAllowDynamicUpdate;

UPROPERTY(EditAnywhere, BlueprintReadOnly, config, Category = "Settings")
bool bSelectOnlyPrefabs;

public:
UPrefabricatorSettings();

Expand Down