HAxis sos
This commit is contained in:
		| @@ -0,0 +1,128 @@ | ||||
| // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. | ||||
|  | ||||
| #include "PolishBuildingsPrivatePCH.h" | ||||
| #include "BuildingsProxyTool.h" | ||||
| #include "SBuildingsProxyDialog.h" | ||||
| #include "MeshUtilities.h" | ||||
| #include "ContentBrowserModule.h" | ||||
| #include "AssetRegistryModule.h" | ||||
| #include "Engine/StaticMeshActor.h" | ||||
| #include "Engine/StaticMesh.h" | ||||
| #include "Engine/Selection.h" | ||||
|  | ||||
|  | ||||
| #define LOCTEXT_NAMESPACE "BuildingsProxyTool" | ||||
|  | ||||
|  | ||||
| TSharedRef<SWidget> FBuildingsProxyTool::GetWidget() | ||||
| { | ||||
| 	return SNew(SBuildingsProxyDialog, this); | ||||
| } | ||||
|  | ||||
|  | ||||
| FText FBuildingsProxyTool::GetTooltipText() const | ||||
| { | ||||
| 	return LOCTEXT("BuildingsProxyToolTooltip", "Harvest geometry from selected actors and merge them into single mesh."); | ||||
| } | ||||
|  | ||||
|  | ||||
| FString FBuildingsProxyTool::GetDefaultPackageName() const | ||||
| { | ||||
| 	FString PackageName; | ||||
|  | ||||
| 	USelection* SelectedActors = GEditor->GetSelectedActors(); | ||||
|  | ||||
| 	// Iterate through selected actors and find first static mesh asset | ||||
| 	// Use this static mesh path as destination package name for a merged mesh | ||||
| 	for (FSelectionIterator Iter(*SelectedActors); Iter; ++Iter) | ||||
| 	{ | ||||
| 		AActor* Actor = Cast<AActor>(*Iter); | ||||
| 		if (Actor) | ||||
| 		{ | ||||
| 			TInlineComponentArray<UStaticMeshComponent*> SMComponets; | ||||
| 			Actor->GetComponents<UStaticMeshComponent>(SMComponets); | ||||
| 			for (UStaticMeshComponent* Component : SMComponets) | ||||
| 			{ | ||||
| 				if (Component->StaticMesh) | ||||
| 				{ | ||||
| 					PackageName = FPackageName::GetLongPackagePath(Component->StaticMesh->GetOutermost()->GetName()); | ||||
| 					PackageName += FString(TEXT("/PROXY_")) + Component->StaticMesh->GetName(); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (!PackageName.IsEmpty()) | ||||
| 		{ | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (PackageName.IsEmpty()) | ||||
| 	{ | ||||
| 		PackageName = FPackageName::FilenameToLongPackageName(FPaths::GameContentDir() + TEXT("PROXY")); | ||||
| 		PackageName = MakeUniqueObjectName(NULL, UPackage::StaticClass(), *PackageName).ToString(); | ||||
| 	} | ||||
|  | ||||
| 	return PackageName; | ||||
| } | ||||
|  | ||||
|  | ||||
| bool FBuildingsProxyTool::RunMerge(const FString& PackageName) | ||||
| { | ||||
| 	TArray<AActor*> Actors; | ||||
| 	TArray<UObject*> AssetsToSync; | ||||
|  | ||||
| 	//Get the module for the proxy mesh utilities | ||||
| 	IMeshUtilities& MeshUtilities = FModuleManager::Get().LoadModuleChecked<IMeshUtilities>("MeshUtilities"); | ||||
|  | ||||
| 	USelection* SelectedActors = GEditor->GetSelectedActors(); | ||||
| 	for (FSelectionIterator Iter(*SelectedActors); Iter; ++Iter) | ||||
| 	{ | ||||
| 		AActor* Actor = Cast<AActor>(*Iter); | ||||
| 		if (Actor) | ||||
| 		{ | ||||
| 			Actors.Add(Actor); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (Actors.Num()) | ||||
| 	{ | ||||
| 		GWarn->BeginSlowTask(LOCTEXT("BuildingsProxy_CreatingProxy", "Creating Mesh Proxy"), true); | ||||
| 		GEditor->BeginTransaction(LOCTEXT("BuildingsProxy_Create", "Creating Mesh Proxy")); | ||||
|  | ||||
| 		FVector ProxyLocation = FVector::ZeroVector; | ||||
|  | ||||
| 		FCreateProxyDelegate ProxyDelegate; | ||||
| 		ProxyDelegate.BindLambda( | ||||
| 			[]( const FGuid Guid, TArray<UObject*>& InAssetsToSync ) | ||||
| 		{ | ||||
| 			//Update the asset registry that a new static mash and material has been created | ||||
| 			if ( InAssetsToSync.Num() ) | ||||
| 			{ | ||||
| 				FAssetRegistryModule& AssetRegistry = FModuleManager::Get().LoadModuleChecked<FAssetRegistryModule>( "AssetRegistry" ); | ||||
| 				int32 AssetCount = InAssetsToSync.Num(); | ||||
| 				for ( int32 AssetIndex = 0; AssetIndex < AssetCount; AssetIndex++ ) | ||||
| 				{ | ||||
| 					AssetRegistry.AssetCreated( InAssetsToSync[AssetIndex] ); | ||||
| 					GEditor->BroadcastObjectReimported( InAssetsToSync[AssetIndex] ); | ||||
| 				} | ||||
|  | ||||
| 				//Also notify the content browser that the new assets exists | ||||
| 				FContentBrowserModule& ContentBrowserModule = FModuleManager::Get().LoadModuleChecked<FContentBrowserModule>( "ContentBrowser" ); | ||||
| 				ContentBrowserModule.Get().SyncBrowserToAssets( InAssetsToSync, true ); | ||||
| 			} | ||||
| 		} ); | ||||
|  | ||||
| 		FGuid JobGuid = FGuid::NewGuid(); | ||||
| 		MeshUtilities.CreateProxyMesh( Actors, ProxySettings, NULL, PackageName, JobGuid, ProxyDelegate ); | ||||
|  | ||||
| 		GEditor->EndTransaction(); | ||||
| 		GWarn->EndSlowTask(); | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
|  | ||||
| #undef LOCTEXT_NAMESPACE | ||||
| @@ -0,0 +1,25 @@ | ||||
| // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. | ||||
| #pragma once | ||||
|  | ||||
| #include "IPolishBuildingsTool.h" | ||||
|  | ||||
| /** | ||||
| * Mesh Proxy Tool | ||||
| */ | ||||
| class FBuildingsProxyTool : public IPolishBuildingsTool | ||||
| { | ||||
| 	friend class SBuildingsProxyDialog; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	// IMergeActorsTool interface | ||||
| 	virtual TSharedRef<SWidget> GetWidget() override; | ||||
| 	virtual FName GetIconName() const override { return "PolishBuildings.BuildingsProxyTool"; } | ||||
| 	virtual FText GetTooltipText() const override; | ||||
| 	virtual FString GetDefaultPackageName() const override; | ||||
| 	virtual bool RunMerge(const FString& PackageName) override; | ||||
|  | ||||
| private: | ||||
|  | ||||
| 	FMeshProxySettings ProxySettings; | ||||
| }; | ||||
| @@ -0,0 +1,614 @@ | ||||
| // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. | ||||
|  | ||||
| #include "PolishBuildingsPrivatePCH.h" | ||||
| #include "SBuildingsProxyDialog.h" | ||||
| #include "Dialogs/DlgPickAssetPath.h" | ||||
| #include "SNumericEntryBox.h" | ||||
| #include "STextComboBox.h" | ||||
| #include "BuildingsProxyTool/BuildingsProxyTool.h" | ||||
|  | ||||
| #define LOCTEXT_NAMESPACE "SBuildingsProxyDialog" | ||||
|  | ||||
|  | ||||
| void SBuildingsProxyDialog::Construct(const FArguments& InArgs, FBuildingsProxyTool* InTool) | ||||
| { | ||||
| 	Tool = InTool; | ||||
| 	check(Tool != nullptr); | ||||
|  | ||||
| 	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("+X")))); | ||||
| 	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("+Y")))); | ||||
| 	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("+Z")))); | ||||
| 	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("-X")))); | ||||
| 	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("-Y")))); | ||||
| 	CuttingPlaneOptions.Add(MakeShareable(new FString(TEXT("-Z")))); | ||||
|  | ||||
| 	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("64")))); | ||||
| 	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("128")))); | ||||
| 	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("256")))); | ||||
| 	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("512")))); | ||||
| 	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("1024")))); | ||||
| 	TextureResolutionOptions.Add(MakeShareable(new FString(TEXT("2048")))); | ||||
|  | ||||
| 	CreateLayout(); | ||||
| } | ||||
|  | ||||
| BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION | ||||
| void SBuildingsProxyDialog::CreateLayout() | ||||
| { | ||||
| 	int32 TextureResEntryIndex = FindTextureResolutionEntryIndex( Tool->ProxySettings.MaterialSettings.TextureSize.X ); | ||||
| 	int32 LightMapResEntryIndex = FindTextureResolutionEntryIndex( Tool->ProxySettings.LightMapResolution ); | ||||
| 	TextureResEntryIndex = FMath::Max( TextureResEntryIndex, 0 ); | ||||
| 	LightMapResEntryIndex = FMath::Max( LightMapResEntryIndex, 0 ); | ||||
|  | ||||
| 	this->ChildSlot | ||||
| 	[ | ||||
| 		SNew(SVerticalBox) | ||||
| 			 | ||||
| 		+SVerticalBox::Slot() | ||||
| 		.AutoHeight() | ||||
| 		.HAlign(HAlign_Center) | ||||
| 		.VAlign(VAlign_Center) | ||||
| 		.Padding(10) | ||||
| 		[ | ||||
| 			// Simplygon logo | ||||
| 			SNew(SImage) | ||||
| 			.Image(FEditorStyle::GetBrush("BuildingsProxy.SimplygonLogo")) | ||||
| 		] | ||||
| 			 | ||||
| 		+SVerticalBox::Slot() | ||||
| 		.AutoHeight() | ||||
| 		[ | ||||
| 			SNew(SBorder) | ||||
| 			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) | ||||
| 			[ | ||||
| 				// Proxy options | ||||
| 				SNew(SVerticalBox) | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SHorizontalBox) | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("OnScreenSizeLabel", "On Screen Size (pixels)")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 						.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, ScreenSize ) ) ) | ||||
| 					] | ||||
| 					+ SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.HAlign(HAlign_Left) | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(SBox) | ||||
| 						.HAlign(HAlign_Fill) | ||||
| 						.MinDesiredWidth(100.0f) | ||||
| 						.MaxDesiredWidth(100.0f) | ||||
| 						[ | ||||
| 							SNew(SNumericEntryBox<int32>) | ||||
| 							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 							.MinValue(40) | ||||
| 							.MaxValue(1200) | ||||
| 							.MinSliderValue(40) | ||||
| 							.MaxSliderValue(1200) | ||||
| 							.AllowSpin(true) | ||||
| 							.Value(this, &SBuildingsProxyDialog::GetScreenSize) | ||||
| 							.OnValueChanged(this, &SBuildingsProxyDialog::ScreenSizeChanged) | ||||
| 						] | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SHorizontalBox) | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("MergeDistanceLabel", "Merge Distance (pixels)")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 						.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, MergeDistance ) ) ) | ||||
| 					] | ||||
| 					+ SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.HAlign(HAlign_Left) | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(SBox) | ||||
| 						.HAlign(HAlign_Fill) | ||||
| 						.MinDesiredWidth(100.0f) | ||||
| 						.MaxDesiredWidth(100.0f) | ||||
| 						[ | ||||
| 							SNew(SNumericEntryBox<int32>) | ||||
| 							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 							.MinValue(0) | ||||
| 							.MaxValue(300) | ||||
| 							.MinSliderValue(0) | ||||
| 							.MaxSliderValue(300) | ||||
| 							.AllowSpin(true) | ||||
| 							.Value(this, &SBuildingsProxyDialog::GetMergeDistance) | ||||
| 							.OnValueChanged(this, &SBuildingsProxyDialog::MergeDistanceChanged) | ||||
| 						] | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SHorizontalBox) | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("TextureResolutionLabel", "Texture Resolution")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 					+ SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.HAlign(HAlign_Left) | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(STextComboBox) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 						.OptionsSource(&TextureResolutionOptions) | ||||
| 						.InitiallySelectedItem( TextureResolutionOptions[TextureResEntryIndex] ) | ||||
| 						.OnSelectionChanged(this, &SBuildingsProxyDialog::SetTextureResolution) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew( SHorizontalBox ) | ||||
| 					+ SHorizontalBox::Slot() | ||||
| 					.FillWidth( 0.5f ) | ||||
| 					.VAlign( VAlign_Center ) | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text( LOCTEXT( "LightMapResolutionLabel", "LightMap Resolution" ) ) | ||||
| 						.Font( FEditorStyle::GetFontStyle( "StandardDialog.SmallFont" ) ) | ||||
| 						.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, LightMapResolution ) ) ) | ||||
| 					] | ||||
| 					+ SHorizontalBox::Slot() | ||||
| 					.FillWidth( 0.5f ) | ||||
| 					.HAlign( HAlign_Left ) | ||||
| 					.VAlign( VAlign_Center ) | ||||
| 					[ | ||||
| 						SNew( STextComboBox ) | ||||
| 						.Font( FEditorStyle::GetFontStyle( "StandardDialog.SmallFont" ) ) | ||||
| 						.OptionsSource( &TextureResolutionOptions ) | ||||
| 						.InitiallySelectedItem( TextureResolutionOptions[LightMapResEntryIndex] ) | ||||
| 						.OnSelectionChanged( this, &SBuildingsProxyDialog::SetLightMapResolution ) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SHorizontalBox) | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					.Padding(0.0, 0.0, 3.0, 0.0) | ||||
| 					[ | ||||
| 						SNew( STextBlock ) | ||||
| 						.Text( LOCTEXT( "HardAngleLabel", "Hard Edge Angle" ) ) | ||||
| 						.Font( FEditorStyle::GetFontStyle( "StandardDialog.SmallFont" ) ) | ||||
| 						.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, HardAngleThreshold ) ) ) | ||||
| 					] | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.HAlign(HAlign_Left) | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(SBox) | ||||
| 						.HAlign(HAlign_Fill) | ||||
| 						.MinDesiredWidth(100.0f) | ||||
| 						.MaxDesiredWidth(100.0f) | ||||
| 						[ | ||||
| 							SNew(SNumericEntryBox<float>) | ||||
| 							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 							.MinValue(0.f) | ||||
| 							.MaxValue(180.f) | ||||
| 							.MinSliderValue(0.f) | ||||
| 							.MaxSliderValue(180.f) | ||||
| 							.AllowSpin(true) | ||||
| 							.Value(this, &SBuildingsProxyDialog::GetHardAngleThreshold) | ||||
| 							.OnValueChanged(this, &SBuildingsProxyDialog::HardAngleThresholdChanged) | ||||
| 							.IsEnabled(this, &SBuildingsProxyDialog::HardAngleThresholdEnabled) | ||||
| 						] | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked( this, &SBuildingsProxyDialog::GetRecalculateNormals ) | ||||
| 					.OnCheckStateChanged( this, &SBuildingsProxyDialog::SetRecalculateNormals ) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew( STextBlock ) | ||||
| 						.Text( LOCTEXT( "RecalcNormalsLabel", "Recalculate Normals" ) ) | ||||
| 						.Font( FEditorStyle::GetFontStyle( "StandardDialog.SmallFont" ) ) | ||||
| 						.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, bRecalculateNormals ) ) ) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+ SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding( FEditorStyle::GetMargin( "StandardDialog.ContentPadding" ) ) | ||||
| 				[ | ||||
| 					SNew( SCheckBox ) | ||||
| 					.Type( ESlateCheckBoxType::CheckBox ) | ||||
| 					.IsChecked(this, &SBuildingsProxyDialog::GetUseClippingPlane) | ||||
| 					.OnCheckStateChanged(this, &SBuildingsProxyDialog::SetUseClippingPlane) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ClippingPlaneLabel", "Use Clipping Plane")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SHorizontalBox) | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					.FillWidth(0.5f) | ||||
| 					[ | ||||
| 						SNew(SHorizontalBox) | ||||
| 						+SHorizontalBox::Slot() | ||||
| 						.AutoWidth() | ||||
| 						[ | ||||
| 							SNew(SBox) | ||||
| 							.MinDesiredWidth(30) | ||||
| 							[ | ||||
| 								SNullWidget::NullWidget | ||||
| 							] | ||||
| 						] | ||||
| 						+SHorizontalBox::Slot() | ||||
| 						.AutoWidth() | ||||
| 						.HAlign(HAlign_Left) | ||||
| 						[ | ||||
| 							SNew(STextBlock) | ||||
| 							.IsEnabled(this, &SBuildingsProxyDialog::UseClippingPlaneEnabled) | ||||
| 							.Text(LOCTEXT("ClippingAxisLabel", "Clipping Axis")) | ||||
| 							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 							.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, AxisIndex ) ) ) | ||||
| 						] | ||||
| 					] | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.HAlign(HAlign_Left) | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					.Padding(8.0, 0.0, 8.0, 0.0) | ||||
| 					[ | ||||
| 						SNew(STextComboBox) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 						.OptionsSource(&CuttingPlaneOptions) | ||||
| 						.InitiallySelectedItem(CuttingPlaneOptions[0]) | ||||
| 						.OnSelectionChanged(this, &SBuildingsProxyDialog::SetClippingAxis) | ||||
| 						.IsEnabled(this, &SBuildingsProxyDialog::UseClippingPlaneEnabled) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SHorizontalBox) | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					.Padding(0.0, 0.0, 3.0, 0.0) | ||||
| 					[ | ||||
| 						SNew(SHorizontalBox) | ||||
| 						+SHorizontalBox::Slot() | ||||
| 						.AutoWidth() | ||||
| 						[ | ||||
| 							SNew(SBox) | ||||
| 							.MinDesiredWidth(30) | ||||
| 							[ | ||||
| 								SNullWidget::NullWidget | ||||
| 							] | ||||
| 						] | ||||
| 						+SHorizontalBox::Slot() | ||||
| 						.HAlign(HAlign_Left) | ||||
| 						.AutoWidth() | ||||
| 						[ | ||||
| 							SNew(STextBlock) | ||||
| 							.Text(LOCTEXT("PlaneLevelLabel", "Plane level")) | ||||
| 							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 							.IsEnabled(this, &SBuildingsProxyDialog::UseClippingPlaneEnabled) | ||||
| 							.ToolTipText( GetPropertyToolTipText( GET_MEMBER_NAME_CHECKED( FMeshProxySettings, ClippingLevel ) ) ) | ||||
| 						] | ||||
| 					] | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.FillWidth(0.5f) | ||||
| 					.HAlign(HAlign_Left) | ||||
| 					[ | ||||
| 						SNew(SBox) | ||||
| 						.HAlign(HAlign_Fill) | ||||
| 						.MinDesiredWidth(100.0f) | ||||
| 						.MaxDesiredWidth(100.0f) | ||||
| 						[ | ||||
| 							SNew(SNumericEntryBox<float>) | ||||
| 							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 							.Value(this, &SBuildingsProxyDialog::GetClippingLevel) | ||||
| 							.OnValueChanged(this, &SBuildingsProxyDialog::ClippingLevelChanged) | ||||
| 							.IsEnabled(this, &SBuildingsProxyDialog::UseClippingPlaneEnabled) | ||||
| 						] | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SBuildingsProxyDialog::GetExportNormalMap) | ||||
| 					.OnCheckStateChanged(this, &SBuildingsProxyDialog::SetExportNormalMap) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ExportNormalMapLabel", "Export Normal Map")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SBuildingsProxyDialog::GetExportMetallicMap) | ||||
| 					.OnCheckStateChanged(this, &SBuildingsProxyDialog::SetExportMetallicMap) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ExportMetallicMapLabel", "Export Metallic Map")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SBuildingsProxyDialog::GetExportRoughnessMap) | ||||
| 					.OnCheckStateChanged(this, &SBuildingsProxyDialog::SetExportRoughnessMap) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ExportRoughnessMapLabel", "Export Roughness Map")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SBuildingsProxyDialog::GetExportSpecularMap) | ||||
| 					.OnCheckStateChanged(this, &SBuildingsProxyDialog::SetExportSpecularMap) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ExportSpecularMapLabel", "Export Specular Map")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
| 			] | ||||
| 		] | ||||
| 	]; | ||||
| } | ||||
| END_SLATE_FUNCTION_BUILD_OPTIMIZATION | ||||
|  | ||||
| int32 SBuildingsProxyDialog::FindTextureResolutionEntryIndex( int32 InResolution ) const | ||||
| { | ||||
| 	FString ResolutionStr = TTypeToString<int32>::ToString( InResolution ); | ||||
|  | ||||
| 	int32 Result = TextureResolutionOptions.IndexOfByPredicate( [&]( const TSharedPtr<FString>& Entry ) | ||||
| 	{ | ||||
| 		return ( ResolutionStr == *Entry ); | ||||
| 	} ); | ||||
|  | ||||
| 	return Result; | ||||
| } | ||||
|  | ||||
| FText SBuildingsProxyDialog::GetPropertyToolTipText( const FName& PropertyName ) const | ||||
| { | ||||
| 	UProperty* Property = FMeshProxySettings::StaticStruct()->FindPropertyByName( PropertyName ); | ||||
| 	if ( Property ) | ||||
| 	{ | ||||
| 		return Property->GetToolTipText(); | ||||
| 	} | ||||
|  | ||||
| 	return FText::GetEmpty(); | ||||
| } | ||||
|  | ||||
| //Screen size | ||||
| TOptional<int32> SBuildingsProxyDialog::GetScreenSize() const | ||||
| { | ||||
| 	return Tool->ProxySettings.ScreenSize; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::ScreenSizeChanged(int32 NewValue) | ||||
| { | ||||
| 	Tool->ProxySettings.ScreenSize = NewValue; | ||||
| } | ||||
|  | ||||
| //Recalculate normals | ||||
| ECheckBoxState SBuildingsProxyDialog::GetRecalculateNormals() const | ||||
| { | ||||
| 	return Tool->ProxySettings.bRecalculateNormals ? ECheckBoxState::Checked: ECheckBoxState::Unchecked; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::SetRecalculateNormals(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->ProxySettings.bRecalculateNormals = (NewValue == ECheckBoxState::Checked); | ||||
| } | ||||
|  | ||||
| //Hard Angle Threshold | ||||
| bool SBuildingsProxyDialog::HardAngleThresholdEnabled() const | ||||
| { | ||||
| 	if(Tool->ProxySettings.bRecalculateNormals) | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| TOptional<float> SBuildingsProxyDialog::GetHardAngleThreshold() const | ||||
| { | ||||
| 	return Tool->ProxySettings.HardAngleThreshold; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::HardAngleThresholdChanged(float NewValue) | ||||
| { | ||||
| 	Tool->ProxySettings.HardAngleThreshold = NewValue; | ||||
| } | ||||
|  | ||||
| //Merge Distance | ||||
| TOptional<int32> SBuildingsProxyDialog::GetMergeDistance() const | ||||
| { | ||||
| 	return Tool->ProxySettings.MergeDistance; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::MergeDistanceChanged(int32 NewValue) | ||||
| { | ||||
| 	Tool->ProxySettings.MergeDistance = NewValue; | ||||
| } | ||||
|  | ||||
| //Clipping Plane | ||||
| ECheckBoxState SBuildingsProxyDialog::GetUseClippingPlane() const | ||||
| { | ||||
| 	return Tool->ProxySettings.bUseClippingPlane ? ECheckBoxState::Checked: ECheckBoxState::Unchecked; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::SetUseClippingPlane(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->ProxySettings.bUseClippingPlane = (NewValue == ECheckBoxState::Checked); | ||||
| } | ||||
|  | ||||
| bool SBuildingsProxyDialog::UseClippingPlaneEnabled() const | ||||
| { | ||||
| 	if(Tool->ProxySettings.bUseClippingPlane) | ||||
| 	{ | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::SetClippingAxis(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo ) | ||||
| { | ||||
| 	//This is a ugly hack, but it solves the problem for now | ||||
| 	int32 AxisIndex = CuttingPlaneOptions.Find(NewSelection); | ||||
| 	//FMessageDialog::Debugf(*FString::Printf(TEXT("%d"), AxisIndex )); | ||||
| 	if(AxisIndex < 3) | ||||
| 	{ | ||||
| 		Tool->ProxySettings.bPlaneNegativeHalfspace = false; | ||||
| 		Tool->ProxySettings.AxisIndex = AxisIndex; | ||||
| 		return; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		Tool->ProxySettings.bPlaneNegativeHalfspace = true; | ||||
| 		Tool->ProxySettings.AxisIndex = AxisIndex - 3; | ||||
| 		return; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| TOptional<float> SBuildingsProxyDialog::GetClippingLevel() const | ||||
| { | ||||
| 	return Tool->ProxySettings.ClippingLevel; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::ClippingLevelChanged(float NewValue) | ||||
| { | ||||
| 	Tool->ProxySettings.ClippingLevel = NewValue; | ||||
| } | ||||
|  | ||||
| //Texture Resolution | ||||
| void SBuildingsProxyDialog::SetTextureResolution(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo) | ||||
| { | ||||
| 	int32 Resolution = 512; | ||||
| 	TTypeFromString<int32>::FromString(Resolution, **NewSelection); | ||||
| 	FIntPoint TextureSize(Resolution, Resolution); | ||||
| 	 | ||||
| 	Tool->ProxySettings.MaterialSettings.TextureSize = TextureSize; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::SetLightMapResolution( TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo ) | ||||
| { | ||||
| 	int32 Resolution = 256; | ||||
| 	TTypeFromString<int32>::FromString( Resolution, **NewSelection ); | ||||
|  | ||||
| 	Tool->ProxySettings.LightMapResolution = Resolution; | ||||
| } | ||||
|  | ||||
| ECheckBoxState SBuildingsProxyDialog::GetExportNormalMap() const | ||||
| { | ||||
| 	return Tool->ProxySettings.MaterialSettings.bNormalMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::SetExportNormalMap(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->ProxySettings.MaterialSettings.bNormalMap = ( NewValue == ECheckBoxState::Checked ); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SBuildingsProxyDialog::GetExportMetallicMap() const | ||||
| { | ||||
| 	return Tool->ProxySettings.MaterialSettings.bMetallicMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::SetExportMetallicMap(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->ProxySettings.MaterialSettings.bMetallicMap = ( NewValue == ECheckBoxState::Checked ); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SBuildingsProxyDialog::GetExportRoughnessMap() const | ||||
| { | ||||
| 	return Tool->ProxySettings.MaterialSettings.bRoughnessMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::SetExportRoughnessMap(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->ProxySettings.MaterialSettings.bRoughnessMap = ( NewValue == ECheckBoxState::Checked ); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SBuildingsProxyDialog::GetExportSpecularMap() const | ||||
| { | ||||
| 	return Tool->ProxySettings.MaterialSettings.bSpecularMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; | ||||
| } | ||||
|  | ||||
| void SBuildingsProxyDialog::SetExportSpecularMap(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->ProxySettings.MaterialSettings.bSpecularMap = ( NewValue == ECheckBoxState::Checked ); | ||||
| } | ||||
|  | ||||
|  | ||||
| #undef LOCTEXT_NAMESPACE | ||||
| @@ -0,0 +1,75 @@ | ||||
| // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| class FBuildingsProxyTool; | ||||
|  | ||||
| /*----------------------------------------------------------------------------- | ||||
| 	SBuildingsProxyDialog | ||||
| -----------------------------------------------------------------------------*/ | ||||
| class SBuildingsProxyDialog : public SCompoundWidget | ||||
| { | ||||
| public: | ||||
| 	SLATE_BEGIN_ARGS(SBuildingsProxyDialog) | ||||
| 	{ | ||||
| 	} | ||||
| 	SLATE_END_ARGS() | ||||
|  | ||||
| public: | ||||
| 	/** SWidget functions */ | ||||
| 	void Construct(const FArguments& InArgs, FBuildingsProxyTool* InTool); | ||||
|  | ||||
| protected: | ||||
| 	/** ScreenSize accessors */ | ||||
| 	TOptional<int32> GetScreenSize() const; | ||||
| 	void ScreenSizeChanged(int32 NewValue);		//used with editable text block (Simplygon) | ||||
|  | ||||
| 	/** Recalculate Normals accessors */ | ||||
| 	ECheckBoxState GetRecalculateNormals() const; | ||||
| 	void SetRecalculateNormals(ECheckBoxState NewValue); | ||||
|  | ||||
| 	/** Hard Angle Threshold accessors */ | ||||
| 	TOptional<float> GetHardAngleThreshold() const; | ||||
| 	bool HardAngleThresholdEnabled() const; | ||||
| 	void HardAngleThresholdChanged(float NewValue); | ||||
|  | ||||
| 	/** Hole filling accessors */ | ||||
| 	TOptional<int32> GetMergeDistance() const; | ||||
| 	void MergeDistanceChanged(int32 NewValue); | ||||
|  | ||||
| 	/** Clipping Plane accessors */ | ||||
| 	ECheckBoxState GetUseClippingPlane() const; | ||||
| 	void SetUseClippingPlane(ECheckBoxState NewValue); | ||||
| 	bool UseClippingPlaneEnabled() const; | ||||
| 	void SetClippingAxis(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo); | ||||
| 	TOptional<float> GetClippingLevel() const; | ||||
| 	void ClippingLevelChanged(float NewValue); | ||||
|  | ||||
| 	/** TextureResolution accessors */ | ||||
| 	void SetTextureResolution(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo); | ||||
| 	void SetLightMapResolution( TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo ); | ||||
|  | ||||
| 	/** Export material properties acessors **/ | ||||
| 	ECheckBoxState GetExportNormalMap() const; | ||||
| 	void SetExportNormalMap(ECheckBoxState NewValue); | ||||
| 	ECheckBoxState GetExportMetallicMap() const; | ||||
| 	void SetExportMetallicMap(ECheckBoxState NewValue); | ||||
| 	ECheckBoxState GetExportRoughnessMap() const; | ||||
| 	void SetExportRoughnessMap(ECheckBoxState NewValue); | ||||
| 	ECheckBoxState GetExportSpecularMap() const; | ||||
| 	void SetExportSpecularMap(ECheckBoxState NewValue); | ||||
|  | ||||
| private: | ||||
| 	/** Creates the geometry mode controls */ | ||||
| 	void CreateLayout(); | ||||
|  | ||||
| 	int32 FindTextureResolutionEntryIndex( int32 InResolution ) const; | ||||
| 	FText GetPropertyToolTipText( const FName& PropertyName ) const; | ||||
|  | ||||
| private: | ||||
| 	FBuildingsProxyTool* Tool; | ||||
|  | ||||
| 	TArray< TSharedPtr<FString> >	CuttingPlaneOptions; | ||||
| 	TArray< TSharedPtr<FString> >	TextureResolutionOptions; | ||||
| }; | ||||
|  | ||||
							
								
								
									
										162
									
								
								Plugins/PolishBuildings/Source/Private/PolishBuildingsModule.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								Plugins/PolishBuildings/Source/Private/PolishBuildingsModule.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. | ||||
|  | ||||
| #include "PolishBuildingsPrivatePCH.h" | ||||
| #include "SPolishBuildingsToolbar.h" | ||||
| #include "ModuleManager.h" | ||||
| #include "WorkspaceMenuStructureModule.h" | ||||
| #include "PolishBuildingsTool.h" | ||||
| #include "BuildingsProxyTool.h" | ||||
| #include "SDockTab.h" | ||||
|  | ||||
| #define LOCTEXT_NAMESPACE "PolishBuildingsModule" | ||||
|  | ||||
|  | ||||
| static const FName PolishBuildingsTabName = FName("PolishBuildings"); | ||||
|  | ||||
| /** | ||||
|  * Merge Actors module | ||||
|  */ | ||||
| class FPolishBuildingsModule : public IPolishBuildingsModule | ||||
| { | ||||
| public: | ||||
|  | ||||
| 	/** | ||||
| 	 * Called right after the module DLL has been loaded and the module object has been created | ||||
| 	 */ | ||||
| 	virtual void StartupModule() override; | ||||
|  | ||||
| 	/** | ||||
| 	 * Called before the module is unloaded, right before the module object is destroyed. | ||||
| 	 */ | ||||
| 	virtual void ShutdownModule() override; | ||||
|  | ||||
| 	/** | ||||
| 	 * Register an IPolishBuildingsTool with the module, passing ownership to it | ||||
| 	 */ | ||||
| 	virtual bool RegisterPolishBuildingsTool(TUniquePtr<IPolishBuildingsTool> Tool) override; | ||||
|  | ||||
| 	/** | ||||
| 	 * Unregister an IPolishBuildingsTool with the module | ||||
| 	 */ | ||||
| 	virtual bool UnregisterPolishBuildingsTool(IPolishBuildingsTool* Tool) override; | ||||
|  | ||||
|  | ||||
| private: | ||||
|  | ||||
| 	/** Creates the dock tab widget used by the tab manager */ | ||||
| 	TSharedRef<SDockTab> CreatePolishBuildingsTab(const FSpawnTabArgs& Args); | ||||
|  | ||||
| private: | ||||
|  | ||||
| 	/** Pointer to the toolbar widget */ | ||||
| 	TWeakPtr<SPolishBuildingsToolbar> PolishBuildingsToolbarPtr; | ||||
|  | ||||
| 	/** List of registered PolishBuildingsTool instances */ | ||||
| 	TArray<TUniquePtr<IPolishBuildingsTool>> PolishBuildingsTools; | ||||
| }; | ||||
|  | ||||
| IMPLEMENT_MODULE(FPolishBuildingsModule, PolishBuildings); | ||||
|  | ||||
|  | ||||
| TSharedRef<SDockTab> FPolishBuildingsModule::CreatePolishBuildingsTab(const FSpawnTabArgs& Args) | ||||
| { | ||||
| 	// Build array of PolishBuildingsTool raw pointers | ||||
| 	TArray<IPolishBuildingsTool*> ToolsToRegister; | ||||
| 	for (const auto& MergeActorTool : PolishBuildingsTools) | ||||
| 	{ | ||||
| 		check(MergeActorTool.Get() != nullptr); | ||||
| 		ToolsToRegister.Add(MergeActorTool.Get()); | ||||
| 	} | ||||
|  | ||||
| 	// Construct toolbar widget | ||||
| 	TSharedRef<SPolishBuildingsToolbar> PolishBuildingsToolbar = | ||||
| 		SNew(SPolishBuildingsToolbar) | ||||
| 		.ToolsToRegister(ToolsToRegister); | ||||
|  | ||||
| 	// Construct dock tab | ||||
| 	TSharedRef<SDockTab> DockTab = | ||||
| 		SNew(SDockTab) | ||||
| 		.TabRole(ETabRole::NomadTab) | ||||
| 		[ | ||||
| 			PolishBuildingsToolbar | ||||
| 		]; | ||||
|  | ||||
| 	// Keep weak pointer to toolbar widget | ||||
| 	PolishBuildingsToolbarPtr = PolishBuildingsToolbar; | ||||
|  | ||||
| 	return DockTab; | ||||
| } | ||||
|  | ||||
|  | ||||
| void FPolishBuildingsModule::StartupModule() | ||||
| { | ||||
| 	FGlobalTabmanager::Get()->RegisterNomadTabSpawner(PolishBuildingsTabName, FOnSpawnTab::CreateRaw(this, &FPolishBuildingsModule::CreatePolishBuildingsTab)) | ||||
| 		.SetDisplayName(LOCTEXT("TabTitle", "Polish Buildings")) | ||||
| 		.SetTooltipText(LOCTEXT("TooltipText", "Open the Polish Buildings tab.")) | ||||
| 		.SetGroup(WorkspaceMenu::GetMenuStructure().GetLevelEditorCategory()) | ||||
| 		.SetIcon(FSlateIcon(FEditorStyle::GetStyleSetName(), "ClassViewer.TabIcon")); | ||||
| 		// This is still experimental in the editor, so it's added specifically in FMainMenu for now. | ||||
| 		// When no longer experimental, remove the below. | ||||
| 		//.SetAutoGenerateMenuEntry(false); | ||||
|  | ||||
| 	// Register built-in merging tools straight away | ||||
| 	ensure(RegisterPolishBuildingsTool(MakeUnique<FPolishBuildingsTool>())); | ||||
|  | ||||
| 	IMeshUtilities* MeshUtilities = FModuleManager::Get().LoadModulePtr<IMeshUtilities>("MeshUtilities"); | ||||
| 	if (MeshUtilities != nullptr && MeshUtilities->GetMeshMergingInterface() != nullptr) | ||||
| 	{ | ||||
| 		// Only register BuildingsProxyTool if Simplygon is available | ||||
| 		ensure(RegisterPolishBuildingsTool(MakeUnique<FBuildingsProxyTool>())); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void FPolishBuildingsModule::ShutdownModule() | ||||
| { | ||||
| 	if (FSlateApplication::IsInitialized()) | ||||
| 	{ | ||||
| 		FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(PolishBuildingsTabName); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| bool FPolishBuildingsModule::RegisterPolishBuildingsTool(TUniquePtr<IPolishBuildingsTool> Tool) | ||||
| { | ||||
| 	if (Tool.Get() != nullptr && !PolishBuildingsTools.Contains(MoveTemp(Tool))) | ||||
| 	{ | ||||
| 		PolishBuildingsTools.Add(MoveTemp(Tool)); | ||||
| 		 | ||||
| 		// If a tool is added while the toolbar widget is active, update it accordingly | ||||
| 		TSharedPtr<SPolishBuildingsToolbar> PolishBuildingsToolbar = PolishBuildingsToolbarPtr.Pin(); | ||||
| 		if (PolishBuildingsToolbar.IsValid()) | ||||
| 		{ | ||||
| 			PolishBuildingsToolbar->AddTool(Tool.Get()); | ||||
| 		} | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| bool FPolishBuildingsModule::UnregisterPolishBuildingsTool(IPolishBuildingsTool* Tool) | ||||
| { | ||||
| 	if (Tool != nullptr) | ||||
| 	{ | ||||
| 		if (PolishBuildingsTools.RemoveAll([=](const TUniquePtr<IPolishBuildingsTool>& Ptr) { return Ptr.Get() == Tool; }) > 0) | ||||
| 		{ | ||||
| 			TSharedPtr<SPolishBuildingsToolbar> PolishBuildingsToolbar = PolishBuildingsToolbarPtr.Pin(); | ||||
| 			if (PolishBuildingsToolbar.IsValid()) | ||||
| 			{ | ||||
| 				PolishBuildingsToolbar->RemoveTool(Tool); | ||||
| 			} | ||||
|  | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| #undef LOCTEXT_NAMESPACE | ||||
| @@ -0,0 +1,6 @@ | ||||
| // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "UnrealEd.h" | ||||
| #include "IPolishBuildingsModule.h" | ||||
| @@ -0,0 +1,149 @@ | ||||
| // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. | ||||
|  | ||||
| #include "PolishBuildingsPrivatePCH.h" | ||||
| #include "PolishBuildingsTool.h" | ||||
| #include "SPolishBuildingsDialog.h" | ||||
| #include "PropertyEditorModule.h" | ||||
| #include "Engine/TextureLODSettings.h" | ||||
| #include "RawMesh.h" | ||||
| #include "Engine/StaticMeshActor.h" | ||||
| #include "Engine/StaticMesh.h" | ||||
| #include "Engine/Selection.h" | ||||
| #include "SystemSettings.h" | ||||
| #include "Engine/TextureLODSettings.h" | ||||
| #include "ContentBrowserModule.h" | ||||
| #include "AssetRegistryModule.h" | ||||
| #include "ScopedTransaction.h" | ||||
|  | ||||
| #define LOCTEXT_NAMESPACE "PolishBuildingsTool" | ||||
|  | ||||
|  | ||||
| FPolishBuildingsTool::FPolishBuildingsTool() | ||||
| 	: bReplaceSourceActors(false) | ||||
| 	, bExportSpecificLOD(false) | ||||
| 	, ExportLODIndex(0) | ||||
| {} | ||||
|  | ||||
|  | ||||
| TSharedRef<SWidget> FPolishBuildingsTool::GetWidget() | ||||
| { | ||||
| 	return SNew(SPolishBuildingsDialog, this); | ||||
| } | ||||
|  | ||||
|  | ||||
| FText FPolishBuildingsTool::GetTooltipText() const | ||||
| { | ||||
| 	return LOCTEXT("PolishBuildingsToolTooltip", "Harvest geometry from selected actors and merge grouping them by materials."); | ||||
| } | ||||
|  | ||||
|  | ||||
| FString FPolishBuildingsTool::GetDefaultPackageName() const | ||||
| { | ||||
| 	FString PackageName = FPackageName::FilenameToLongPackageName(FPaths::GameContentDir() + TEXT("SM_MERGED")); | ||||
|  | ||||
| 	USelection* SelectedActors = GEditor->GetSelectedActors(); | ||||
| 	// Iterate through selected actors and find first static mesh asset | ||||
| 	// Use this static mesh path as destination package name for a merged mesh | ||||
| 	for (FSelectionIterator Iter(*SelectedActors); Iter; ++Iter) | ||||
| 	{ | ||||
| 		AActor* Actor = Cast<AActor>(*Iter); | ||||
| 		if (Actor) | ||||
| 		{ | ||||
| 			FString ActorName = Actor->GetName(); | ||||
| 			PackageName = FString::Printf(TEXT("%s_%s"), *PackageName, *ActorName); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (PackageName.IsEmpty()) | ||||
| 	{ | ||||
| 		PackageName = MakeUniqueObjectName(NULL, UPackage::StaticClass(), *PackageName).ToString(); | ||||
| 	} | ||||
|  | ||||
| 	return PackageName; | ||||
| } | ||||
|  | ||||
|  | ||||
| bool FPolishBuildingsTool::RunMerge(const FString& PackageName) | ||||
| { | ||||
| 	IMeshUtilities& MeshUtilities = FModuleManager::Get().LoadModuleChecked<IMeshUtilities>("MeshUtilities"); | ||||
| 	USelection* SelectedActors = GEditor->GetSelectedActors(); | ||||
| 	TArray<AActor*> Actors; | ||||
| 	TArray<ULevel*> UniqueLevels; | ||||
| 	for (FSelectionIterator Iter(*SelectedActors); Iter; ++Iter) | ||||
| 	{ | ||||
| 		AActor* Actor = Cast<AActor>(*Iter); | ||||
| 		if (Actor) | ||||
| 		{ | ||||
| 			Actors.Add(Actor); | ||||
| 			UniqueLevels.AddUnique(Actor->GetLevel()); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// This restriction is only for replacement of selected actors with merged mesh actor | ||||
| 	if (UniqueLevels.Num() > 1 && bReplaceSourceActors) | ||||
| 	{ | ||||
| 		FText Message = NSLOCTEXT("UnrealEd", "FailedToPolishBuildingsSublevels_Msg", "The selected actors should be in the same level"); | ||||
| 		OpenMsgDlgInt(EAppMsgType::Ok, Message, NSLOCTEXT("UnrealEd", "FailedToPolishBuildings_Title", "Unable to merge actors")); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	int32 TargetMeshLOD = bExportSpecificLOD ? ExportLODIndex : INDEX_NONE; | ||||
| 	FVector MergedActorLocation; | ||||
| 	TArray<UObject*> AssetsToSync; | ||||
| 	// Merge... | ||||
| 	{ | ||||
| 		FScopedSlowTask SlowTask(0, LOCTEXT("MergingActorsSlowTask", "Merging actors...")); | ||||
| 		SlowTask.MakeDialog(); | ||||
| 		 | ||||
| 		MeshUtilities.MergeActors(Actors, MergingSettings, NULL, PackageName, TargetMeshLOD, AssetsToSync, MergedActorLocation); | ||||
| 	} | ||||
|  | ||||
| 	if (AssetsToSync.Num()) | ||||
| 	{ | ||||
| 		FAssetRegistryModule& AssetRegistry = FModuleManager::Get().LoadModuleChecked<FAssetRegistryModule>("AssetRegistry"); | ||||
| 		int32 AssetCount = AssetsToSync.Num(); | ||||
| 		for (int32 AssetIndex = 0; AssetIndex < AssetCount; AssetIndex++) | ||||
| 		{ | ||||
| 			AssetRegistry.AssetCreated(AssetsToSync[AssetIndex]); | ||||
| 			GEditor->BroadcastObjectReimported(AssetsToSync[AssetIndex]); | ||||
| 		} | ||||
|  | ||||
| 		//Also notify the content browser that the new assets exists | ||||
| 		FContentBrowserModule& ContentBrowserModule = FModuleManager::Get().LoadModuleChecked<FContentBrowserModule>("ContentBrowser"); | ||||
| 		ContentBrowserModule.Get().SyncBrowserToAssets(AssetsToSync, true); | ||||
|  | ||||
| 		// Place new mesh in the world | ||||
| 		if (bReplaceSourceActors) | ||||
| 		{ | ||||
| 			UStaticMesh* MergedMesh = nullptr; | ||||
| 			if (AssetsToSync.FindItemByClass(&MergedMesh)) | ||||
| 			{ | ||||
| 				const FScopedTransaction Transaction(LOCTEXT("PlaceMergedActor", "Place Merged Actor")); | ||||
| 				UniqueLevels[0]->Modify(); | ||||
|  | ||||
| 				UWorld* World = UniqueLevels[0]->OwningWorld; | ||||
| 				FActorSpawnParameters Params; | ||||
| 				Params.OverrideLevel = UniqueLevels[0]; | ||||
| 				FRotator MergedActorRotation(ForceInit); | ||||
| 								 | ||||
| 				AStaticMeshActor* MergedActor = World->SpawnActor<AStaticMeshActor>(MergedActorLocation, MergedActorRotation, Params); | ||||
| 				MergedActor->GetStaticMeshComponent()->StaticMesh = MergedMesh; | ||||
| 				MergedActor->SetActorLabel(AssetsToSync[0]->GetName()); | ||||
|  | ||||
| 				// Remove source actors | ||||
| 				/* | ||||
| 				for (AActor* Actor : Actors) | ||||
| 				{ | ||||
| 					Actor->Destroy(); | ||||
| 				} | ||||
| 				*/ | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
|  | ||||
| #undef LOCTEXT_NAMESPACE | ||||
| @@ -0,0 +1,35 @@ | ||||
| // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. | ||||
| #pragma once | ||||
|  | ||||
| #include "IPolishBuildingsTool.h" | ||||
| #include "MeshUtilities.h" | ||||
|  | ||||
| /** | ||||
|  * Mesh Merging Tool | ||||
|  */ | ||||
| class FPolishBuildingsTool : public IPolishBuildingsTool | ||||
| { | ||||
| 	friend class SPolishBuildingsDialog; | ||||
|  | ||||
| public: | ||||
|  | ||||
| 	FPolishBuildingsTool(); | ||||
|  | ||||
| 	// IPolishBuildingsTool interface | ||||
| 	virtual TSharedRef<SWidget> GetWidget() override; | ||||
| 	virtual FName GetIconName() const override { return "PolishBuildings.PolishBuildingsTool"; } | ||||
| 	virtual FText GetTooltipText() const override; | ||||
| 	virtual FString GetDefaultPackageName() const override; | ||||
| 	virtual bool RunMerge(const FString& PackageName) override; | ||||
|  | ||||
| private: | ||||
|  | ||||
| 	/** Current mesh merging settings */ | ||||
| 	FMeshMergingSettings MergingSettings; | ||||
|  | ||||
| 	/** Whether to replace source actors with a merged actor in the world */ | ||||
| 	bool bReplaceSourceActors; | ||||
|  | ||||
| 	bool bExportSpecificLOD; | ||||
| 	int32 ExportLODIndex; | ||||
| }; | ||||
| @@ -0,0 +1,520 @@ | ||||
| // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. | ||||
|  | ||||
| #include "PolishBuildingsPrivatePCH.h" | ||||
| #include "SPolishBuildingsDialog.h" | ||||
| #include "Dialogs/DlgPickAssetPath.h" | ||||
| #include "STextComboBox.h" | ||||
| #include "RawMesh.h" | ||||
| #include "PolishBuildingsTool/PolishBuildingsTool.h" | ||||
|  | ||||
| #define LOCTEXT_NAMESPACE "SPolishBuildingsDialog" | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////// | ||||
| // SPolishBuildingsDialog | ||||
|  | ||||
| SPolishBuildingsDialog::SPolishBuildingsDialog() | ||||
| { | ||||
| } | ||||
|  | ||||
| BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION | ||||
| void SPolishBuildingsDialog::Construct(const FArguments& InArgs, FPolishBuildingsTool* InTool) | ||||
| { | ||||
| 	Tool = InTool; | ||||
| 	check(Tool != nullptr); | ||||
|  | ||||
| 	// Setup available resolutions for lightmap and merged materials | ||||
| 	const int32 MinTexResolution = 1 << FTextureLODGroup().MinLODMipCount; | ||||
| 	const int32 MaxTexResolution = 1 << FTextureLODGroup().MaxLODMipCount; | ||||
| 	for (int32 TexRes = MinTexResolution; TexRes <= MaxTexResolution; TexRes*=2) | ||||
| 	{ | ||||
| 		LightMapResolutionOptions.Add(MakeShareable(new FString(TTypeToString<int32>::ToString(TexRes)))); | ||||
| 		MergedMaterialResolutionOptions.Add(MakeShareable(new FString(TTypeToString<int32>::ToString(TexRes)))); | ||||
| 	} | ||||
|  | ||||
| 	Tool->MergingSettings.TargetLightMapResolution = FMath::Clamp(Tool->MergingSettings.TargetLightMapResolution, MinTexResolution, MaxTexResolution); | ||||
| 	Tool->MergingSettings.MaterialSettings.TextureSize.X = FMath::Clamp( Tool->MergingSettings.MaterialSettings.TextureSize.X, MinTexResolution, MaxTexResolution ); | ||||
| 	Tool->MergingSettings.MaterialSettings.TextureSize.Y = FMath::Clamp( Tool->MergingSettings.MaterialSettings.TextureSize.Y, MinTexResolution, MaxTexResolution ); | ||||
|  | ||||
| 	// Setup available UV channels for an atlased lightmap | ||||
| 	for (int32 Index = 0; Index < MAX_MESH_TEXTURE_COORDS; Index++) | ||||
| 	{ | ||||
| 		LightMapChannelOptions.Add(MakeShareable(new FString(TTypeToString<int32>::ToString(Index)))); | ||||
| 	} | ||||
|  | ||||
| 	for (int32 Index = 0; Index < MAX_STATIC_MESH_LODS; Index++) | ||||
| 	{ | ||||
| 		ExportLODOptions.Add(MakeShareable(new FString(TTypeToString<int32>::ToString(Index)))); | ||||
| 	} | ||||
|  | ||||
| 	// Create widget layout | ||||
| 	this->ChildSlot | ||||
| 	[ | ||||
| 		SNew(SVerticalBox) | ||||
|  | ||||
| 		+SVerticalBox::Slot() | ||||
| 		.AutoHeight() | ||||
| 		.Padding(0,2,0,0) | ||||
| 		[ | ||||
| 			// Lightmap settings | ||||
| 			SNew(SBorder) | ||||
| 			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) | ||||
| 			[ | ||||
| 				SNew(SVerticalBox) | ||||
| 									 | ||||
| 				// Enable atlasing | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SPolishBuildingsDialog::GetGenerateLightmapUV) | ||||
| 					.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetGenerateLightmapUV) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("AtlasLightmapUVLabel", "Generate Lightmap UVs")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
| 					 | ||||
| 				// Target lightmap channel / Max lightmap resolution | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SHorizontalBox) | ||||
|  | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.AutoWidth() | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.IsEnabled(this, &SPolishBuildingsDialog::IsLightmapChannelEnabled) | ||||
| 						.Text(LOCTEXT("TargetLightMapChannelLabel", "Target Channel:")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
|  | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.AutoWidth() | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					.Padding(4,0,4,0) | ||||
| 					[ | ||||
| 						SNew(STextComboBox) | ||||
| 						.IsEnabled( this, &SPolishBuildingsDialog::IsLightmapChannelEnabled ) | ||||
| 						.OptionsSource(&LightMapChannelOptions) | ||||
| 						.InitiallySelectedItem(LightMapChannelOptions[Tool->MergingSettings.TargetLightMapUVChannel]) | ||||
| 						.OnSelectionChanged(this, &SPolishBuildingsDialog::SetTargetLightMapChannel) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
|  | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.AutoWidth() | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.IsEnabled(this, &SPolishBuildingsDialog::IsLightmapChannelEnabled) | ||||
| 						.Text(LOCTEXT("TargetLightMapResolutionLabel", "Target Resolution:")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 												 | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.AutoWidth() | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					.Padding(4,0,4,0) | ||||
| 					[ | ||||
| 						SNew(STextComboBox) | ||||
| 						.IsEnabled( this, &SPolishBuildingsDialog::IsLightmapChannelEnabled ) | ||||
| 						.OptionsSource(&LightMapResolutionOptions) | ||||
| 						.InitiallySelectedItem(LightMapResolutionOptions[FMath::FloorLog2(Tool->MergingSettings.TargetLightMapResolution)]) | ||||
| 						.OnSelectionChanged(this, &SPolishBuildingsDialog::SetTargetLightMapResolution) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
| 			] | ||||
| 		] | ||||
|  | ||||
| 		// Other merging settings | ||||
| 		+SVerticalBox::Slot() | ||||
| 		.AutoHeight() | ||||
| 		.Padding(0,2,0,0) | ||||
| 		[ | ||||
| 			SNew(SBorder) | ||||
| 			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) | ||||
| 			[ | ||||
| 				SNew(SVerticalBox) | ||||
|  | ||||
| 				// LOD to export | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SHorizontalBox) | ||||
|  | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.AutoWidth() | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(SCheckBox) | ||||
| 						.Type(ESlateCheckBoxType::CheckBox) | ||||
| 						.IsChecked(this, &SPolishBuildingsDialog::GetExportSpecificLODEnabled) | ||||
| 						.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetExportSpecificLODEnabled) | ||||
| 						.Content() | ||||
| 						[ | ||||
| 							SNew(STextBlock) | ||||
| 							.IsEnabled(this, &SPolishBuildingsDialog::IsExportSpecificLODEnabled) | ||||
| 							.Text(LOCTEXT("TargetMeshLODIndexLabel", "Export specific LOD:")) | ||||
| 							.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 						] | ||||
| 					] | ||||
| 					 | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.AutoWidth() | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					.Padding(4,0,4,0) | ||||
| 					[ | ||||
| 						SNew(STextComboBox) | ||||
| 						.IsEnabled(this, &SPolishBuildingsDialog::IsExportSpecificLODEnabled) | ||||
| 						.OptionsSource(&ExportLODOptions) | ||||
| 						.InitiallySelectedItem(ExportLODOptions[Tool->ExportLODIndex]) | ||||
| 						.OnSelectionChanged(this, &SPolishBuildingsDialog::SetExportSpecificLODIndex) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
| 					 | ||||
| 				// Vertex colors | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SPolishBuildingsDialog::GetImportVertexColors) | ||||
| 					.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetImportVertexColors) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ImportVertexColorsLabel", "Import Vertex Colors")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				// Pivot at zero | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SPolishBuildingsDialog::GetPivotPointAtZero) | ||||
| 					.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetPivotPointAtZero) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("PivotPointAtZeroLabel", "Pivot Point At (0,0,0)")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				// Replace source actors | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SPolishBuildingsDialog::GetReplaceSourceActors) | ||||
| 					.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetReplaceSourceActors) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ReplaceSourceActorsLabel", "Replace Source Actors")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
| 				 | ||||
| 				// Merge physics data | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SPolishBuildingsDialog::GetMergePhyisicData) | ||||
| 					.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetMergePhyisicData) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("MergePhysicsDataLabel", "Merge Physics Data")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				// Merge materials | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SPolishBuildingsDialog::GetMergeMaterials) | ||||
| 					.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetMergeMaterials) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("MergeMaterialsLabel", "Merge Materials")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
| 				// Export normal map | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SPolishBuildingsDialog::GetExportNormalMap) | ||||
| 					.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetExportNormalMap) | ||||
| 					.IsEnabled(this, &SPolishBuildingsDialog::IsMaterialMergingEnabled) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ExportNormalMapLabel", "Export Normal Map")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
| 				// Export metallic map | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SPolishBuildingsDialog::GetExportMetallicMap) | ||||
| 					.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetExportMetallicMap) | ||||
| 					.IsEnabled(this, &SPolishBuildingsDialog::IsMaterialMergingEnabled) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ExportMetallicMapLabel", "Export Metallic Map")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
| 				// Export roughness map | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SPolishBuildingsDialog::GetExportRoughnessMap) | ||||
| 					.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetExportRoughnessMap) | ||||
| 					.IsEnabled(this, &SPolishBuildingsDialog::IsMaterialMergingEnabled) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ExportRoughnessMapLabel", "Export Roughness Map")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
| 				// Export specular map | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SCheckBox) | ||||
| 					.Type(ESlateCheckBoxType::CheckBox) | ||||
| 					.IsChecked(this, &SPolishBuildingsDialog::GetExportSpecularMap) | ||||
| 					.OnCheckStateChanged(this, &SPolishBuildingsDialog::SetExportSpecularMap) | ||||
| 					.IsEnabled(this, &SPolishBuildingsDialog::IsMaterialMergingEnabled) | ||||
| 					.Content() | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.Text(LOCTEXT("ExportSpecularMapLabel", "Export Specular Map")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				] | ||||
| 				 | ||||
| 				// Merged texture size | ||||
| 				+SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) | ||||
| 				[ | ||||
| 					SNew(SHorizontalBox) | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.AutoWidth() | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					[ | ||||
| 						SNew(STextBlock) | ||||
| 						.IsEnabled(this, &SPolishBuildingsDialog::IsMaterialMergingEnabled) | ||||
| 						.Text(LOCTEXT("MergedMaterialAtlasResolutionLabel", "Merged Material Atlas Resolution:")) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 												 | ||||
| 					+SHorizontalBox::Slot() | ||||
| 					.AutoWidth() | ||||
| 					.VAlign(VAlign_Center) | ||||
| 					.Padding(4,0,4,0) | ||||
| 					[ | ||||
| 						SNew(STextComboBox) | ||||
| 						.IsEnabled(this, &SPolishBuildingsDialog::IsMaterialMergingEnabled) | ||||
| 						.OptionsSource(&MergedMaterialResolutionOptions) | ||||
| 						.InitiallySelectedItem( MergedMaterialResolutionOptions[FMath::FloorLog2( Tool->MergingSettings.MaterialSettings.TextureSize.X )] ) | ||||
| 						.OnSelectionChanged(this, &SPolishBuildingsDialog::SetMergedMaterialAtlasResolution) | ||||
| 						.Font(FEditorStyle::GetFontStyle("StandardDialog.SmallFont")) | ||||
| 					] | ||||
| 				]														 | ||||
| 			] | ||||
| 		] | ||||
| 	]; | ||||
| } | ||||
| END_SLATE_FUNCTION_BUILD_OPTIMIZATION | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetGenerateLightmapUV() const | ||||
| { | ||||
| 	return (Tool->MergingSettings.bGenerateLightMapUV ? ECheckBoxState::Checked : ECheckBoxState::Unchecked); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetGenerateLightmapUV(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->MergingSettings.bGenerateLightMapUV = (ECheckBoxState::Checked == NewValue); | ||||
| } | ||||
|  | ||||
| bool SPolishBuildingsDialog::IsLightmapChannelEnabled() const | ||||
| { | ||||
| 	return Tool->MergingSettings.bGenerateLightMapUV; | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetTargetLightMapChannel(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo) | ||||
| { | ||||
| 	TTypeFromString<int32>::FromString(Tool->MergingSettings.TargetLightMapUVChannel, **NewSelection); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetTargetLightMapResolution(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo) | ||||
| { | ||||
| 	TTypeFromString<int32>::FromString(Tool->MergingSettings.TargetLightMapResolution, **NewSelection); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetExportSpecificLODEnabled() const | ||||
| { | ||||
| 	return (Tool->bExportSpecificLOD ? ECheckBoxState::Checked : ECheckBoxState::Unchecked); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetExportSpecificLODEnabled(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->bExportSpecificLOD = (NewValue == ECheckBoxState::Checked); | ||||
| } | ||||
|  | ||||
| bool SPolishBuildingsDialog::IsExportSpecificLODEnabled() const | ||||
| { | ||||
| 	return Tool->bExportSpecificLOD; | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetExportSpecificLODIndex(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo) | ||||
| { | ||||
| 	TTypeFromString<int32>::FromString(Tool->ExportLODIndex, **NewSelection); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetImportVertexColors() const | ||||
| { | ||||
| 	return ( Tool->MergingSettings.bBakeVertexData ? ECheckBoxState::Checked : ECheckBoxState::Unchecked ); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetImportVertexColors(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->MergingSettings.bBakeVertexData = ( ECheckBoxState::Checked == NewValue ); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetPivotPointAtZero() const | ||||
| { | ||||
| 	return (Tool->MergingSettings.bPivotPointAtZero ? ECheckBoxState::Checked : ECheckBoxState::Unchecked); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetPivotPointAtZero(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->MergingSettings.bPivotPointAtZero = (ECheckBoxState::Checked == NewValue); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetReplaceSourceActors() const | ||||
| { | ||||
| 	return (Tool->bReplaceSourceActors ? ECheckBoxState::Checked : ECheckBoxState::Unchecked); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetReplaceSourceActors(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->bReplaceSourceActors = (ECheckBoxState::Checked == NewValue); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetMergePhyisicData() const | ||||
| { | ||||
| 	return (Tool->MergingSettings.bMergePhysicsData ? ECheckBoxState::Checked : ECheckBoxState::Unchecked); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetMergePhyisicData(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->MergingSettings.bMergePhysicsData = (ECheckBoxState::Checked == NewValue); | ||||
| } | ||||
|  | ||||
| bool SPolishBuildingsDialog::IsMaterialMergingEnabled() const | ||||
| { | ||||
| 	return Tool->MergingSettings.bMergeMaterials; | ||||
| } | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetMergeMaterials() const | ||||
| { | ||||
| 	return (Tool->MergingSettings.bMergeMaterials ? ECheckBoxState::Checked : ECheckBoxState::Unchecked); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetMergeMaterials(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->MergingSettings.bMergeMaterials = (ECheckBoxState::Checked == NewValue); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetExportNormalMap() const | ||||
| { | ||||
| 	return ( Tool->MergingSettings.MaterialSettings.bNormalMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked ); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetExportNormalMap(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->MergingSettings.MaterialSettings.bNormalMap = ( ECheckBoxState::Checked == NewValue ); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetExportMetallicMap() const | ||||
| { | ||||
| 	return ( Tool->MergingSettings.MaterialSettings.bMetallicMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked ); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetExportMetallicMap(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->MergingSettings.MaterialSettings.bMetallicMap = ( ECheckBoxState::Checked == NewValue ); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetExportRoughnessMap() const | ||||
| { | ||||
| 	return ( Tool->MergingSettings.MaterialSettings.bRoughnessMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked ); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetExportRoughnessMap(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->MergingSettings.MaterialSettings.bRoughnessMap = ( ECheckBoxState::Checked == NewValue ); | ||||
| } | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsDialog::GetExportSpecularMap() const | ||||
| { | ||||
| 	return ( Tool->MergingSettings.MaterialSettings.bSpecularMap ? ECheckBoxState::Checked : ECheckBoxState::Unchecked ); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetExportSpecularMap(ECheckBoxState NewValue) | ||||
| { | ||||
| 	Tool->MergingSettings.MaterialSettings.bSpecularMap = ( ECheckBoxState::Checked == NewValue ); | ||||
| } | ||||
|  | ||||
| void SPolishBuildingsDialog::SetMergedMaterialAtlasResolution(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo) | ||||
| { | ||||
| 	TTypeFromString<int32>::FromString( Tool->MergingSettings.MaterialSettings.TextureSize.X, **NewSelection ); | ||||
| 	TTypeFromString<int32>::FromString( Tool->MergingSettings.MaterialSettings.TextureSize.Y, **NewSelection ); | ||||
| } | ||||
|  | ||||
|  | ||||
| #undef LOCTEXT_NAMESPACE | ||||
| @@ -0,0 +1,86 @@ | ||||
| // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. | ||||
| #pragma once | ||||
|  | ||||
| class FPolishBuildingsTool; | ||||
|  | ||||
| /*----------------------------------------------------------------------------- | ||||
|    SPolishBuildingsDialog | ||||
| -----------------------------------------------------------------------------*/ | ||||
| class SPolishBuildingsDialog : public SCompoundWidget | ||||
| { | ||||
| public: | ||||
| 	SLATE_BEGIN_ARGS(SPolishBuildingsDialog) | ||||
| 	{ | ||||
| 	} | ||||
|  | ||||
| 	SLATE_END_ARGS() | ||||
|  | ||||
| public: | ||||
| 	/** **/ | ||||
| 	SPolishBuildingsDialog(); | ||||
|  | ||||
| 	/** SWidget functions */ | ||||
| 	void Construct(const FArguments& InArgs, FPolishBuildingsTool* InTool); | ||||
|  | ||||
| private: | ||||
|  | ||||
| 	/** Called when the Merge button is clicked */ | ||||
| 	FReply OnMergeClicked(); | ||||
|  | ||||
| 	/**  */ | ||||
| 	ECheckBoxState GetGenerateLightmapUV() const; | ||||
| 	void SetGenerateLightmapUV(ECheckBoxState NewValue); | ||||
|  | ||||
| 	/** Target lightmap channel */ | ||||
| 	bool IsLightmapChannelEnabled() const; | ||||
| 	void SetTargetLightMapChannel(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo); | ||||
| 	void SetTargetLightMapResolution(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo); | ||||
|  | ||||
| 	/**  */ | ||||
| 	ECheckBoxState GetExportSpecificLODEnabled() const; | ||||
| 	void SetExportSpecificLODEnabled(ECheckBoxState NewValue); | ||||
| 	bool IsExportSpecificLODEnabled() const; | ||||
| 	void SetExportSpecificLODIndex(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo); | ||||
| 		 | ||||
| 	/**  */ | ||||
| 	ECheckBoxState GetImportVertexColors() const; | ||||
| 	void SetImportVertexColors(ECheckBoxState NewValue); | ||||
|  | ||||
| 	/**  */ | ||||
| 	ECheckBoxState GetPivotPointAtZero() const; | ||||
| 	void SetPivotPointAtZero(ECheckBoxState NewValue); | ||||
|  | ||||
| 	ECheckBoxState GetReplaceSourceActors() const; | ||||
| 	void SetReplaceSourceActors(ECheckBoxState NewValue); | ||||
|  | ||||
| 	ECheckBoxState GetMergePhyisicData() const; | ||||
| 	void SetMergePhyisicData(ECheckBoxState NewValue); | ||||
| 	 | ||||
| 	/** Material merging */ | ||||
| 	bool IsMaterialMergingEnabled() const; | ||||
| 	ECheckBoxState GetMergeMaterials() const; | ||||
| 	void SetMergeMaterials(ECheckBoxState NewValue); | ||||
|  | ||||
| 	ECheckBoxState GetExportNormalMap() const; | ||||
| 	void SetExportNormalMap(ECheckBoxState NewValue); | ||||
|  | ||||
| 	ECheckBoxState GetExportMetallicMap() const; | ||||
| 	void SetExportMetallicMap(ECheckBoxState NewValue); | ||||
|  | ||||
| 	ECheckBoxState GetExportRoughnessMap() const; | ||||
| 	void SetExportRoughnessMap(ECheckBoxState NewValue); | ||||
|  | ||||
| 	ECheckBoxState GetExportSpecularMap() const; | ||||
| 	void SetExportSpecularMap(ECheckBoxState NewValue); | ||||
|  | ||||
| 	void SetMergedMaterialAtlasResolution(TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo); | ||||
| 	 | ||||
| private: | ||||
|  | ||||
| 	FPolishBuildingsTool* Tool; | ||||
|  | ||||
| 	TArray<TSharedPtr<FString>>	ExportLODOptions; | ||||
| 	TArray<TSharedPtr<FString>>	LightMapResolutionOptions; | ||||
| 	TArray<TSharedPtr<FString>>	LightMapChannelOptions; | ||||
| 	TArray<TSharedPtr<FString>>	MergedMaterialResolutionOptions; | ||||
| }; | ||||
| @@ -0,0 +1,219 @@ | ||||
| // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. | ||||
|  | ||||
| #include "PolishBuildingsPrivatePCH.h" | ||||
| #include "SPolishBuildingsToolbar.h" | ||||
| #include "LevelEditor.h" | ||||
| #include "IDocumentation.h" | ||||
| #include "ContentBrowserModule.h" | ||||
|  | ||||
| #define LOCTEXT_NAMESPACE "SPolishBuildingsToolbar" | ||||
|  | ||||
|  | ||||
| ////////////////////////////////////////////////////////////// | ||||
|  | ||||
| void SPolishBuildingsToolbar::Construct(const FArguments& InArgs) | ||||
| { | ||||
| 	// Important: We use raw bindings here because we are releasing our binding in our destructor (where a weak pointer would be invalid) | ||||
| 	// It's imperative that our delegate is removed in the destructor for the level editor module to play nicely with reloading. | ||||
|  | ||||
| 	FLevelEditorModule& LevelEditor = FModuleManager::GetModuleChecked<FLevelEditorModule>("LevelEditor"); | ||||
| 	LevelEditor.OnActorSelectionChanged().AddRaw(this, &SPolishBuildingsToolbar::OnActorSelectionChanged); | ||||
|  | ||||
| 	RegisteredTools = InArgs._ToolsToRegister; | ||||
|  | ||||
| 	ChildSlot | ||||
| 	[ | ||||
| 		SNew(SVerticalBox) | ||||
|  | ||||
| 		+ SVerticalBox::Slot() | ||||
| 		.AutoHeight() | ||||
| 		.HAlign(HAlign_Left) | ||||
| 		.Padding(0, 0, 0, 0) | ||||
| 		[ | ||||
| 			SAssignNew(ToolbarContainer, SBorder) | ||||
| 			.BorderImage(FEditorStyle::GetBrush("NoBorder")) | ||||
| 			.Padding(FMargin(4, 0, 0, 0)) | ||||
| 		] | ||||
|  | ||||
| 		+ SVerticalBox::Slot() | ||||
| 		.FillHeight(1.0f) | ||||
| 		.Padding(2, 0, 0, 0) | ||||
| 		[ | ||||
| 			SNew(SBorder) | ||||
| 			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder")) | ||||
| 			.Padding(0.f) | ||||
| 			.IsEnabled(this, &SPolishBuildingsToolbar::GetContentEnabledState) | ||||
| 			[ | ||||
| 				SNew(SVerticalBox) | ||||
|  | ||||
| 				+ SVerticalBox::Slot() | ||||
| 				.FillHeight(1.0f) | ||||
| 				.Padding(4, 4, 4, 4) | ||||
| 				[ | ||||
| 					SNew(SScrollBox) | ||||
| 					+SScrollBox::Slot() | ||||
| 					[ | ||||
| 						SAssignNew(InlineContentHolder, SBox) | ||||
| 					] | ||||
| 				] | ||||
|  | ||||
| 				+ SVerticalBox::Slot() | ||||
| 				.AutoHeight() | ||||
| 				.HAlign(HAlign_Right) | ||||
| 				.Padding(4, 4, 10, 4) | ||||
| 				[ | ||||
| 					SNew(SButton) | ||||
| 					.Text(LOCTEXT("PolishBuildings", "Merge Actors")) | ||||
| 					.OnClicked(this, &SPolishBuildingsToolbar::OnPolishBuildingsClicked) | ||||
| 				] | ||||
| 			] | ||||
| 		] | ||||
| 	]; | ||||
|  | ||||
| 	UpdateToolbar(); | ||||
|  | ||||
| 	// Update selected actor state for the first time | ||||
| 	GUnrealEd->UpdateFloatingPropertyWindows(); | ||||
| } | ||||
|  | ||||
|  | ||||
| SPolishBuildingsToolbar::~SPolishBuildingsToolbar() | ||||
| { | ||||
| 	FLevelEditorModule& LevelEditor = FModuleManager::GetModuleChecked<FLevelEditorModule>("LevelEditor"); | ||||
| 	LevelEditor.OnActorSelectionChanged().RemoveAll(this); | ||||
| } | ||||
|  | ||||
|  | ||||
| void SPolishBuildingsToolbar::OnActorSelectionChanged(const TArray<UObject*>& NewSelection, bool bForceRefresh) | ||||
| { | ||||
| 	SelectedObjects = NewSelection; | ||||
| 	bIsContentEnabled = (NewSelection.Num() > 0); | ||||
| } | ||||
|  | ||||
|  | ||||
| void SPolishBuildingsToolbar::OnToolSelectionChanged(const ECheckBoxState NewCheckedState, int32 ToolIndex) | ||||
| { | ||||
| 	if (NewCheckedState == ECheckBoxState::Checked) | ||||
| 	{ | ||||
| 		CurrentlySelectedTool = ToolIndex; | ||||
| 		UpdateInlineContent(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| ECheckBoxState SPolishBuildingsToolbar::OnIsToolSelected(int32 ToolIndex) const | ||||
| { | ||||
| 	return (CurrentlySelectedTool == ToolIndex) ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; | ||||
| } | ||||
|  | ||||
|  | ||||
| FReply SPolishBuildingsToolbar::OnPolishBuildingsClicked() | ||||
| { | ||||
| 	if (CurrentlySelectedTool >= 0 && CurrentlySelectedTool < RegisteredTools.Num()) | ||||
| 	{ | ||||
| 		const FString DefaultPackageName = RegisteredTools[CurrentlySelectedTool]->GetDefaultPackageName(); | ||||
| 		const FString DefaultPath = FPackageName::GetLongPackagePath(DefaultPackageName); | ||||
| 		const FString DefaultName = FPackageName::GetShortName(DefaultPackageName); | ||||
|  | ||||
| 		// Initialize SaveAssetDialog config | ||||
| 		FSaveAssetDialogConfig SaveAssetDialogConfig; | ||||
| 		SaveAssetDialogConfig.DialogTitleOverride = LOCTEXT("CreateMergedActorTitle", "Create Merged Actor"); | ||||
| 		SaveAssetDialogConfig.DefaultPath = DefaultPath; | ||||
| 		SaveAssetDialogConfig.DefaultAssetName = DefaultName; | ||||
| 		SaveAssetDialogConfig.ExistingAssetPolicy = ESaveAssetDialogExistingAssetPolicy::AllowButWarn; | ||||
|  | ||||
| 		FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser"); | ||||
| 		FString SaveObjectPath = ContentBrowserModule.Get().CreateModalSaveAssetDialog(SaveAssetDialogConfig); | ||||
| 		if (!SaveObjectPath.IsEmpty()) | ||||
| 		{ | ||||
| 			const FString PackageName = FPackageName::ObjectPathToPackageName(SaveObjectPath); | ||||
|  | ||||
| 			RegisteredTools[CurrentlySelectedTool]->RunMerge(PackageName); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return FReply::Handled(); | ||||
| } | ||||
|  | ||||
|  | ||||
| bool SPolishBuildingsToolbar::GetContentEnabledState() const | ||||
| { | ||||
| 	return bIsContentEnabled; | ||||
| } | ||||
|  | ||||
|  | ||||
| void SPolishBuildingsToolbar::AddTool(IPolishBuildingsTool* Tool) | ||||
| { | ||||
| 	check(!RegisteredTools.Contains(Tool)); | ||||
| 	RegisteredTools.Add(Tool); | ||||
| 	UpdateToolbar(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void SPolishBuildingsToolbar::RemoveTool(IPolishBuildingsTool* Tool) | ||||
| { | ||||
| 	int32 IndexToRemove = RegisteredTools.Find(Tool); | ||||
| 	if (IndexToRemove != INDEX_NONE) | ||||
| 	{ | ||||
| 		RegisteredTools.RemoveAt(IndexToRemove); | ||||
|  | ||||
| 		if (CurrentlySelectedTool > IndexToRemove) | ||||
| 		{ | ||||
| 			CurrentlySelectedTool--; | ||||
| 		} | ||||
| 		UpdateToolbar(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void SPolishBuildingsToolbar::UpdateToolbar() | ||||
| { | ||||
| 	const ISlateStyle& StyleSet = FEditorStyle::Get(); | ||||
|  | ||||
| 	TSharedRef<SHorizontalBox> HorizontalBox = | ||||
| 		SNew(SHorizontalBox); | ||||
|  | ||||
| 	for (int32 ToolIndex = 0; ToolIndex < RegisteredTools.Num(); ToolIndex++) | ||||
| 	{ | ||||
| 		const IPolishBuildingsTool* Tool = RegisteredTools[ToolIndex]; | ||||
|  | ||||
| 		HorizontalBox->AddSlot() | ||||
| 		.Padding(StyleSet.GetMargin("EditorModesToolbar.SToolBarButtonBlock.Padding")) | ||||
| 		[ | ||||
| 			SNew(SCheckBox) | ||||
| 			.Style(&StyleSet, "EditorModesToolbar.ToggleButton") | ||||
| 			.OnCheckStateChanged(this, &SPolishBuildingsToolbar::OnToolSelectionChanged, ToolIndex) | ||||
| 			.IsChecked(this, &SPolishBuildingsToolbar::OnIsToolSelected, ToolIndex) | ||||
| 			.Padding(StyleSet.GetMargin("EditorModesToolbar.SToolBarButtonBlock.CheckBox.Padding")) | ||||
| 			.ToolTip(IDocumentation::Get()->CreateToolTip(Tool->GetTooltipText(), nullptr, FString(), FString())) | ||||
| 			[ | ||||
| 				SNew(SImage) | ||||
| 				.Image(StyleSet.GetBrush(Tool->GetIconName())) | ||||
| 			] | ||||
| 		]; | ||||
| 	} | ||||
|  | ||||
| 	TSharedRef<SBorder> ToolbarContent = | ||||
| 		SNew(SBorder) | ||||
| 		.Padding(0) | ||||
| 		.BorderImage(StyleSet.GetBrush("NoBorder")) | ||||
| 		[ | ||||
| 			HorizontalBox | ||||
| 		]; | ||||
|  | ||||
| 	ToolbarContainer->SetContent(ToolbarContent); | ||||
|  | ||||
| 	UpdateInlineContent(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void SPolishBuildingsToolbar::UpdateInlineContent() | ||||
| { | ||||
| 	if (CurrentlySelectedTool >= 0 && CurrentlySelectedTool < RegisteredTools.Num()) | ||||
| 	{ | ||||
| 		InlineContentHolder->SetContent(RegisteredTools[CurrentlySelectedTool]->GetWidget()); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| #undef LOCTEXT_NAMESPACE | ||||
| @@ -0,0 +1,83 @@ | ||||
| // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| class IPolishBuildingsTool; | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////// | ||||
| // SPolishBuildingsToolbar | ||||
|  | ||||
| class SPolishBuildingsToolbar : public SCompoundWidget | ||||
| { | ||||
| public: | ||||
|  | ||||
| 	SLATE_BEGIN_ARGS(SPolishBuildingsToolbar) {} | ||||
| 		SLATE_ARGUMENT(TArray<IPolishBuildingsTool*>, ToolsToRegister) | ||||
| 	SLATE_END_ARGS() | ||||
|  | ||||
| 	/** | ||||
| 	 * Construct the widget | ||||
| 	 * | ||||
| 	 * @param	InArgs			A declaration from which to construct the widget | ||||
| 	 */ | ||||
| 	void Construct(const FArguments& InArgs); | ||||
|  | ||||
| 	/** Constructor */ | ||||
| 	SPolishBuildingsToolbar() | ||||
| 		: CurrentlySelectedTool(0) | ||||
| 	{} | ||||
|  | ||||
| 	/** Destructor */ | ||||
| 	virtual ~SPolishBuildingsToolbar(); | ||||
|  | ||||
| 	/** Add a new tool to the toolbar */ | ||||
| 	void AddTool(IPolishBuildingsTool* Tool); | ||||
|  | ||||
| 	/** Remove an existing tool from the toolbar */ | ||||
| 	void RemoveTool(IPolishBuildingsTool* Tool); | ||||
|  | ||||
|  | ||||
| private: | ||||
|  | ||||
| 	/** Called when the level actor selection changes */ | ||||
| 	void OnActorSelectionChanged(const TArray<UObject*>& NewSelection, bool bForceRefresh); | ||||
|  | ||||
| 	/** Called when the currently selected tool changes */ | ||||
| 	void OnToolSelectionChanged(const ECheckBoxState NewCheckedState, int32 ToolIndex); | ||||
|  | ||||
| 	/** Called to determine whether a toolbox widget is selected or not */ | ||||
| 	ECheckBoxState OnIsToolSelected(int32 ToolIndex) const; | ||||
|  | ||||
| 	/** Called when the Merge Actors button is clicked */ | ||||
| 	FReply OnPolishBuildingsClicked(); | ||||
|  | ||||
| 	/** Determine whether the widget content is enabled or not */ | ||||
| 	bool GetContentEnabledState() const; | ||||
|  | ||||
| 	/** Update the toolbar container based on the currently registered tools */ | ||||
| 	void UpdateToolbar(); | ||||
|  | ||||
| 	/** Updates the inline content widget for the current tool */ | ||||
| 	void UpdateInlineContent(); | ||||
|  | ||||
|  | ||||
| private: | ||||
|  | ||||
| 	/** List of registered tool instances */ | ||||
| 	TArray<IPolishBuildingsTool*> RegisteredTools; | ||||
|  | ||||
| 	/** Index of currently selected tool */ | ||||
| 	int32 CurrentlySelectedTool; | ||||
|  | ||||
| 	/** List of currently selected objects */ | ||||
| 	TArray<UObject*> SelectedObjects; | ||||
|  | ||||
| 	/** Whether the merge actors tool panel is enabled or not */ | ||||
| 	bool bIsContentEnabled; | ||||
|  | ||||
| 	/** The container holding the toolbar */ | ||||
| 	TSharedPtr<SBorder> ToolbarContainer; | ||||
|  | ||||
| 	/** Inline content area for different tool modes */ | ||||
| 	TSharedPtr<SBox> InlineContentHolder; | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user