Files
Andron666 9c38e93fa4 part7
2022-12-05 20:31:35 +05:00

1544 lines
60 KiB
C++

/*
* Copyright (c) <2021> Side Effects Software Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. The name of Side Effects Software may not be used to endorse or
* promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "HoudiniEngineEditor.h"
#include "HoudiniEngineEditorPrivatePCH.h"
#include "HoudiniEngineEditorUtils.h"
#include "HoudiniEngineStyle.h"
#include "HoudiniRuntimeSettings.h"
#include "HoudiniEngine.h"
#include "HoudiniAsset.h"
#include "HoudiniAssetBroker.h"
#include "HoudiniAssetActorFactory.h"
#include "HoudiniAssetActor.h"
#include "HoudiniAssetComponent.h"
#include "HoudiniAssetComponentDetails.h"
#include "HoudiniInput.h"
#include "HoudiniOutput.h"
#include "HoudiniParameter.h"
#include "HoudiniEngineUtils.h"
#include "HoudiniEngineCommands.h"
#include "HoudiniRuntimeSettingsDetails.h"
#include "HoudiniSplineComponentVisualizer.h"
#include "HoudiniHandleComponentVisualizer.h"
#include "AssetTypeActions_HoudiniAsset.h"
#include "HoudiniGeoPartObject.h"
#include "HoudiniPDGAssetLink.h"
#include "HoudiniPackageParams.h"
#include "Modules/ModuleManager.h"
#include "Interfaces/IPluginManager.h"
#include "HAL/PlatformFileManager.h"
#include "Misc/MessageDialog.h"
#include "Misc/Paths.h"
#include "AssetRegistryModule.h"
#include "PropertyEditorModule.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "LevelEditor.h"
#include "Templates/SharedPointer.h"
#include "Framework/Application/SlateApplication.h"
#include "HAL/ConsoleManager.h"
#include "Editor/UnrealEdEngine.h"
#include "Editor.h"
#include "UnrealEdGlobals.h"
#include "Engine/Selection.h"
#include "Widgets/Input/SCheckBox.h"
#include "Logging/LogMacros.h"
#define LOCTEXT_NAMESPACE HOUDINI_LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FHoudiniEngineEditor, HoudiniEngineEditor);
DEFINE_LOG_CATEGORY(LogHoudiniEngineEditor);
FHoudiniEngineEditor *
FHoudiniEngineEditor::HoudiniEngineEditorInstance = nullptr;
FHoudiniEngineEditor &
FHoudiniEngineEditor::Get()
{
return *HoudiniEngineEditorInstance;
}
bool
FHoudiniEngineEditor::IsInitialized()
{
return FHoudiniEngineEditor::HoudiniEngineEditorInstance != nullptr;
}
FHoudiniEngineEditor::FHoudiniEngineEditor()
{
}
void FHoudiniEngineEditor::StartupModule()
{
HOUDINI_LOG_MESSAGE(TEXT("Starting the Houdini Engine Editor module."));
// Create style set.
FHoudiniEngineStyle::Initialize();
// Initilizes various resources used by our editor UI widgets
InitializeWidgetResource();
// Register asset type actions.
RegisterAssetTypeActions();
// Register asset brokers.
RegisterAssetBrokers();
// Register component visualizers.
RegisterComponentVisualizers();
// Register detail presenters.
RegisterDetails();
// Register actor factories.
RegisterActorFactories();
// Extends the file menu.
ExtendMenu();
// Extend the World Outliner Menu
AddLevelViewportMenuExtender();
// Adds the custom console commands
RegisterConsoleCommands();
// Register global undo / redo callbacks.
//RegisterForUndo();
//RegisterPlacementModeExtensions();
// Register for any FEditorDelegates that we are interested in, such as
// PreSaveWorld and PreBeginPIE, for HoudiniStaticMesh -> UStaticMesh builds
RegisterEditorDelegates();
// Store the instance.
FHoudiniEngineEditor::HoudiniEngineEditorInstance = this;
HOUDINI_LOG_MESSAGE(TEXT("Houdini Engine Editor module startup complete."));
}
void FHoudiniEngineEditor::ShutdownModule()
{
HOUDINI_LOG_MESSAGE(TEXT("Shutting down the Houdini Engine Editor module."));
// Deregister editor delegates
UnregisterEditorDelegates();
// Deregister console commands
UnregisterConsoleCommands();
// Remove the level viewport Menu extender
RemoveLevelViewportMenuExtender();
// Unregister asset type actions.
UnregisterAssetTypeActions();
// Unregister asset brokers.
//UnregisterAssetBrokers();
// Unregister detail presenters.
UnregisterDetails();
// Unregister our component visualizers.
//UnregisterComponentVisualizers();
// Unregister global undo / redo callbacks.
//UnregisterForUndo();
//UnregisterPlacementModeExtensions();
// Unregister the styleset
FHoudiniEngineStyle::Shutdown();
HOUDINI_LOG_MESSAGE(TEXT("Houdini Engine Editor module shutdown complete."));
}
FString
FHoudiniEngineEditor::GetHoudiniEnginePluginDir()
{
FString EnginePluginDir = FPaths::EnginePluginsDir() / TEXT("Runtime/HoudiniEngine");
if (FPaths::DirectoryExists(EnginePluginDir))
return EnginePluginDir;
FString ProjectPluginDir = FPaths::ProjectPluginsDir() / TEXT("Runtime/HoudiniEngine");
if (FPaths::DirectoryExists(ProjectPluginDir))
return ProjectPluginDir;
TSharedPtr<IPlugin> HoudiniPlugin = IPluginManager::Get().FindPlugin(TEXT("HoudiniEngine"));
FString PluginBaseDir = HoudiniPlugin.IsValid() ? HoudiniPlugin->GetBaseDir() : EnginePluginDir;
if (FPaths::DirectoryExists(PluginBaseDir))
return PluginBaseDir;
HOUDINI_LOG_WARNING(TEXT("Could not find the Houdini Engine plugin's directory"));
return EnginePluginDir;
}
void
FHoudiniEngineEditor::RegisterDetails()
{
FPropertyEditorModule & PropertyModule = FModuleManager::LoadModuleChecked< FPropertyEditorModule >("PropertyEditor");
// Register details presenter for our component type and runtime settings.
PropertyModule.RegisterCustomClassLayout(
TEXT("HoudiniAssetComponent"),
FOnGetDetailCustomizationInstance::CreateStatic(&FHoudiniAssetComponentDetails::MakeInstance));
PropertyModule.RegisterCustomClassLayout(
TEXT("HoudiniRuntimeSettings"),
FOnGetDetailCustomizationInstance::CreateStatic(&FHoudiniRuntimeSettingsDetails::MakeInstance));
}
void
FHoudiniEngineEditor::UnregisterDetails()
{
if (FModuleManager::Get().IsModuleLoaded("PropertyEditor"))
{
FPropertyEditorModule & PropertyModule =
FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyModule.UnregisterCustomClassLayout(TEXT("HoudiniAssetComponent"));
PropertyModule.UnregisterCustomClassLayout(TEXT("HoudiniRuntimeSettings"));
}
}
void
FHoudiniEngineEditor::RegisterComponentVisualizers()
{
if (GUnrealEd)
{
// Register Houdini spline visualizer
SplineComponentVisualizer = MakeShareable<FComponentVisualizer>(new FHoudiniSplineComponentVisualizer);
if (SplineComponentVisualizer.IsValid())
{
GUnrealEd->RegisterComponentVisualizer(UHoudiniSplineComponent::StaticClass()->GetFName(), SplineComponentVisualizer);
SplineComponentVisualizer->OnRegister();
}
// Register Houdini handle visualizer
HandleComponentVisualizer = MakeShareable<FComponentVisualizer>(new FHoudiniHandleComponentVisualizer);
if (HandleComponentVisualizer.IsValid())
{
GUnrealEd->RegisterComponentVisualizer(UHoudiniHandleComponent::StaticClass()->GetFName(), HandleComponentVisualizer);
HandleComponentVisualizer->OnRegister();
}
}
}
void
FHoudiniEngineEditor::UnregisterComponentVisualizers()
{
if (GUnrealEd)
{
// Unregister Houdini spline visualizer
if(SplineComponentVisualizer.IsValid())
GUnrealEd->UnregisterComponentVisualizer(UHoudiniSplineComponent::StaticClass()->GetFName());
// Unregister Houdini handle visualizer
if (HandleComponentVisualizer.IsValid())
GUnrealEd->UnregisterComponentVisualizer(UHoudiniHandleComponent::StaticClass()->GetFName());
}
}
void
FHoudiniEngineEditor::RegisterAssetTypeAction(IAssetTools & AssetTools, TSharedRef< IAssetTypeActions > Action)
{
AssetTools.RegisterAssetTypeActions(Action);
AssetTypeActions.Add(Action);
}
void
FHoudiniEngineEditor::RegisterAssetTypeActions()
{
// Create and register asset type actions for Houdini asset.
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked< FAssetToolsModule >("AssetTools").Get();
RegisterAssetTypeAction(AssetTools, MakeShareable(new FAssetTypeActions_HoudiniAsset()));
}
void
FHoudiniEngineEditor::UnregisterAssetTypeActions()
{
// Unregister asset type actions we have previously registered.
if (FModuleManager::Get().IsModuleLoaded("AssetTools"))
{
IAssetTools & AssetTools = FModuleManager::GetModuleChecked< FAssetToolsModule >("AssetTools").Get();
for (int32 Index = 0; Index < AssetTypeActions.Num(); ++Index)
AssetTools.UnregisterAssetTypeActions(AssetTypeActions[Index].ToSharedRef());
AssetTypeActions.Empty();
}
}
void
FHoudiniEngineEditor::RegisterAssetBrokers()
{
// Create and register broker for Houdini asset.
HoudiniAssetBroker = MakeShareable(new FHoudiniAssetBroker());
FComponentAssetBrokerage::RegisterBroker( HoudiniAssetBroker, UHoudiniAssetComponent::StaticClass(), true, true );
}
void
FHoudiniEngineEditor::UnregisterAssetBrokers()
{
if (UObjectInitialized())
{
// Unregister broker.
FComponentAssetBrokerage::UnregisterBroker( HoudiniAssetBroker );
}
}
void
FHoudiniEngineEditor::RegisterActorFactories()
{
if (GEditor)
{
UHoudiniAssetActorFactory * HoudiniAssetActorFactory =
NewObject< UHoudiniAssetActorFactory >(GetTransientPackage(), UHoudiniAssetActorFactory::StaticClass());
GEditor->ActorFactories.Add(HoudiniAssetActorFactory);
}
}
void
FHoudiniEngineEditor::BindMenuCommands()
{
HEngineCommands = MakeShareable(new FUICommandList);
FHoudiniEngineCommands::Register();
const FHoudiniEngineCommands& Commands = FHoudiniEngineCommands::Get();
// Session
HEngineCommands->MapAction(
Commands._CreateSession,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::CreateSession(); }),
FCanExecuteAction::CreateLambda([]() { return !FHoudiniEngineCommands::IsSessionValid(); }));
HEngineCommands->MapAction(
Commands._ConnectSession,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::ConnectSession(); }),
FCanExecuteAction::CreateLambda([]() { return !FHoudiniEngineCommands::IsSessionValid(); }));
HEngineCommands->MapAction(
Commands._StopSession,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::StopSession(); }),
FCanExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::IsSessionValid(); }));
HEngineCommands->MapAction(
Commands._RestartSession,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::RestartSession(); }),
FCanExecuteAction::CreateLambda([]() { return true; }));
HEngineCommands->MapAction(
Commands._OpenSessionSync,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::OpenSessionSync(); }),
FCanExecuteAction::CreateLambda([]() { return !FHoudiniEngineCommands::IsSessionSyncProcessValid(); }));
HEngineCommands->MapAction(
Commands._CloseSessionSync,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::CloseSessionSync(); }),
FCanExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::IsSessionSyncProcessValid(); }));
HEngineCommands->MapAction(
Commands._ViewportSyncNone,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::SetViewportSync(0); }),
FCanExecuteAction::CreateLambda([]() { return true; }),
FIsActionChecked::CreateLambda([]() { return (FHoudiniEngineCommands::GetViewportSync() == 0); })
);
HEngineCommands->MapAction(
Commands._ViewportSyncHoudini,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::SetViewportSync(1); }),
FCanExecuteAction::CreateLambda([]() { return true; }),
FIsActionChecked::CreateLambda([]() { return (FHoudiniEngineCommands::GetViewportSync() == 1); })
);
HEngineCommands->MapAction(
Commands._ViewportSyncUnreal,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::SetViewportSync(2); }),
FCanExecuteAction::CreateLambda([]() { return true; }),
FIsActionChecked::CreateLambda([]() { return (FHoudiniEngineCommands::GetViewportSync() == 2); })
);
HEngineCommands->MapAction(
Commands._ViewportSyncBoth,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::SetViewportSync(3); }),
FCanExecuteAction::CreateLambda([]() { return true; }),
FIsActionChecked::CreateLambda([]() { return (FHoudiniEngineCommands::GetViewportSync() == 3); })
);
// PDG commandlet
HEngineCommands->MapAction(
Commands._IsPDGCommandletEnabled,
FExecuteAction::CreateLambda([]() { FHoudiniEngineCommands::SetPDGCommandletEnabled(!FHoudiniEngineCommands::IsPDGCommandletEnabled()); }),
FCanExecuteAction::CreateLambda([]() { return true; }),
FIsActionChecked::CreateLambda([]() { return FHoudiniEngineCommands::IsPDGCommandletEnabled(); })
);
HEngineCommands->MapAction(
Commands._StartPDGCommandlet,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::StartPDGCommandlet(); }),
FCanExecuteAction::CreateLambda([]()
{
return FHoudiniEngineCommands::IsPDGCommandletEnabled() && !FHoudiniEngineCommands::IsPDGCommandletRunningOrConnected();
})
);
HEngineCommands->MapAction(
Commands._StopPDGCommandlet,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::StopPDGCommandlet(); }),
FCanExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::IsPDGCommandletRunningOrConnected(); }));
// Plugin
HEngineCommands->MapAction(
Commands._InstallInfo,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::ShowInstallInfo(); }),
FCanExecuteAction::CreateLambda([]() { return false; }));
HEngineCommands->MapAction(
Commands._PluginSettings,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::ShowPluginSettings(); }),
FCanExecuteAction::CreateLambda([]() { return true; }));
// Files
HEngineCommands->MapAction(
Commands._OpenInHoudini,
FExecuteAction::CreateLambda([](){ return FHoudiniEngineCommands::OpenInHoudini(); }),
FCanExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::IsSessionValid(); }));
HEngineCommands->MapAction(
Commands._SaveHIPFile,
FExecuteAction::CreateLambda([](){ return FHoudiniEngineCommands::SaveHIPFile(); }),
FCanExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::IsSessionValid(); }));
HEngineCommands->MapAction(
Commands._CleanUpTempFolder,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::CleanUpTempFolder(); }),
FCanExecuteAction::CreateLambda([]() { return true; }));
// Help and support
HEngineCommands->MapAction(
Commands._ReportBug,
FExecuteAction::CreateLambda([](){ return FHoudiniEngineCommands::ReportBug(); }),
FCanExecuteAction::CreateLambda([]() { return true; }));
HEngineCommands->MapAction(
Commands._OnlineDoc,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::OnlineDocumentation(); }),
FCanExecuteAction::CreateLambda([]() { return true; }));
HEngineCommands->MapAction(
Commands._OnlineForum,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::OnlineForum(); }),
FCanExecuteAction::CreateLambda([]() { return true; }));
// Actions
HEngineCommands->MapAction(
Commands._CookAll,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::RecookAllAssets(); }),
FCanExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::IsSessionValid(); }));
HEngineCommands->MapAction(
Commands._CookSelected,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::RecookSelection(); }),
FCanExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::IsSessionValid(); }));
HEngineCommands->MapAction(
Commands._RebuildAll,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::RebuildAllAssets(); }),
FCanExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::IsSessionValid(); }));
HEngineCommands->MapAction(
Commands._RebuildSelected,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::RebuildSelection(); }),
FCanExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::IsSessionValid(); }));
HEngineCommands->MapAction(
Commands._BakeAll,
FExecuteAction::CreateLambda([](){ return FHoudiniEngineCommands::BakeAllAssets(); }),
FCanExecuteAction::CreateLambda([](){ return true; }));
HEngineCommands->MapAction(
Commands._BakeSelected,
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::BakeSelection(); }),
FCanExecuteAction::CreateLambda([]() { return true; }));
HEngineCommands->MapAction(
Commands._RefineAll,
FExecuteAction::CreateLambda([]() { FHoudiniEngineCommands::RefineHoudiniProxyMeshesToStaticMeshes(false); }),
FCanExecuteAction::CreateLambda([]() { return true; }));
HEngineCommands->MapAction(
Commands._RefineSelected,
FExecuteAction::CreateLambda([]() { FHoudiniEngineCommands::RefineHoudiniProxyMeshesToStaticMeshes(true); }),
FCanExecuteAction::CreateLambda([]() { return true; }));
HEngineCommands->MapAction(
Commands._PauseAssetCooking,
FExecuteAction::CreateLambda([](){ return FHoudiniEngineCommands::PauseAssetCooking(); }),
FCanExecuteAction::CreateLambda([](){ return FHoudiniEngineCommands::IsSessionValid(); }),
FIsActionChecked::CreateLambda([](){ return FHoudiniEngineCommands::IsAssetCookingPaused(); }));
// Non menu command (used for shortcuts only)
// Append the command to the editor module
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked< FLevelEditorModule >("LevelEditor");
LevelEditorModule.GetGlobalLevelEditorActions()->Append(HEngineCommands.ToSharedRef());
}
void
FHoudiniEngineEditor::ExtendMenu()
{
if (IsRunningCommandlet())
return;
// We need to add/bind the UI Commands to their functions first
BindMenuCommands();
MainMenuExtender = MakeShareable(new FExtender);
// Extend File menu, we will add Houdini section.
MainMenuExtender->AddMenuExtension(
"FileLoadAndSave",
EExtensionHook::After,
HEngineCommands,
FMenuExtensionDelegate::CreateRaw(this, &FHoudiniEngineEditor::AddHoudiniFileMenuExtension));
MainMenuExtender->AddMenuBarExtension(
"Edit",
EExtensionHook::After,
HEngineCommands,
FMenuBarExtensionDelegate::CreateRaw(this, &FHoudiniEngineEditor::AddHoudiniEditorMenu));
// Add our menu extender
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MainMenuExtender);
}
void
FHoudiniEngineEditor::AddHoudiniFileMenuExtension(FMenuBuilder & MenuBuilder)
{
MenuBuilder.BeginSection("Houdini", LOCTEXT("HoudiniLabel", "Houdini Engine"));
// Icons used by the commands are defined in the HoudiniEngineStyle
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._OpenInHoudini);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._SaveHIPFile);
//MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._ReportBug);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._CleanUpTempFolder);
//MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._BakeAll);
//MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._PauseAssetCooking);
//MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._RestartSession);
//MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._RefineAll);
MenuBuilder.EndSection();
}
void
FHoudiniEngineEditor::AddHoudiniEditorMenu(FMenuBarBuilder& MenuBarBuilder)
{
// View
MenuBarBuilder.AddPullDownMenu(
LOCTEXT("HoudiniLabel", "Houdini Engine"),
LOCTEXT("HoudiniMenu_ToolTip", "Open the Houdini Engine menu"),
FNewMenuDelegate::CreateRaw(this, &FHoudiniEngineEditor::AddHoudiniMainMenuExtension),
"View");
}
void
FHoudiniEngineEditor::AddHoudiniMainMenuExtension(FMenuBuilder & MenuBuilder)
{
/*
MenuBuilder.BeginSection("Houdini", LOCTEXT("HoudiniLabel", "Houdini Engine"));
// Icons used by the commands are defined in the HoudiniEngineStyle
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._OpenInHoudini);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._SaveHIPFile);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._ReportBug);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._CleanUpTempFolder);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._BakeAll);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._PauseAssetCooking);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._RestartSession);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._RefineAll);
MenuBuilder.EndSection();
*/
MenuBuilder.BeginSection("Session", LOCTEXT("SessionLabel", "Session"));
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._CreateSession);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._ConnectSession);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._StopSession);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._RestartSession);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._OpenSessionSync);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._CloseSessionSync);
// Viewport sync menu
struct FLocalMenuBuilder
{
static void FillViewportSyncMenu(FMenuBuilder& InSubMenuBuilder)
{
InSubMenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._ViewportSyncNone);
InSubMenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._ViewportSyncHoudini);
InSubMenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._ViewportSyncUnreal);
InSubMenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._ViewportSyncBoth);
}
};
MenuBuilder.AddSubMenu(
LOCTEXT("SyncViewport", "Sync Viewport"),
LOCTEXT("SyncViewport_ToolTip", "Sync Viewport"),
FNewMenuDelegate::CreateStatic(&FLocalMenuBuilder::FillViewportSyncMenu),
false,
FSlateIcon(FHoudiniEngineStyle::GetStyleSetName(), "HoudiniEngine._SyncViewport"));
MenuBuilder.EndSection();
MenuBuilder.BeginSection("PDG", LOCTEXT("PDGLabel", "PDG"));
struct FLocalPDGMenuBuilder
{
static void FillPDGMenu(FMenuBuilder& InSubMenuBuilder)
{
InSubMenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._IsPDGCommandletEnabled);
InSubMenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._StartPDGCommandlet);
InSubMenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._StopPDGCommandlet);
}
};
MenuBuilder.AddSubMenu(
LOCTEXT("PDGSubMenu", "Work Item Import Settings"),
LOCTEXT("PDGSubmenu_ToolTip", "PDG Work Item Import Settings"),
FNewMenuDelegate::CreateStatic(&FLocalPDGMenuBuilder::FillPDGMenu),
false,
FSlateIcon(FHoudiniEngineStyle::GetStyleSetName(), "HoudiniEngine.PDGLink"));
MenuBuilder.EndSection();
MenuBuilder.BeginSection("Plugin", LOCTEXT("PluginLabel", "Plugin"));
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._InstallInfo);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._PluginSettings);
MenuBuilder.EndSection();
MenuBuilder.BeginSection("File", LOCTEXT("FileLabel", "File"));
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._OpenInHoudini);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._SaveHIPFile);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._CleanUpTempFolder);
MenuBuilder.EndSection();
MenuBuilder.BeginSection("Help", LOCTEXT("HelpLabel", "Help And Support"));
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._OnlineDoc);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._OnlineForum);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._ReportBug);
MenuBuilder.EndSection();
MenuBuilder.BeginSection("Actions", LOCTEXT("ActionsLabel", "Actions"));
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._CookAll);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._CookSelected);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._RebuildAll);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._RebuildSelected);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._BakeAll);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._BakeSelected);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._RefineAll);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._RefineSelected);
MenuBuilder.AddMenuEntry(FHoudiniEngineCommands::Get()._PauseAssetCooking);
MenuBuilder.EndSection();
}
void
FHoudiniEngineEditor::RegisterForUndo()
{
/*
if (GUnrealEd)
GUnrealEd->RegisterForUndo(this);
*/
}
void
FHoudiniEngineEditor::UnregisterForUndo()
{
/*
if (GUnrealEd)
GUnrealEd->UnregisterForUndo(this);
*/
}
void
FHoudiniEngineEditor::RegisterPlacementModeExtensions()
{
// Load custom houdini tools
/*
const UHoudiniRuntimeSettings * HoudiniRuntimeSettings = GetDefault< UHoudiniRuntimeSettings >();
check(HoudiniRuntimeSettings);
if (HoudiniRuntimeSettings->bHidePlacementModeHoudiniTools)
return;
FPlacementCategoryInfo Info(
LOCTEXT("HoudiniCategoryName", "Houdini Engine"),
"HoudiniEngine",
TEXT("PMHoudiniEngine"),
25
);
Info.CustomGenerator = []() -> TSharedRef<SWidget> { return SNew(SHoudiniToolPalette); };
IPlacementModeModule::Get().RegisterPlacementCategory(Info);
*/
}
void
FHoudiniEngineEditor::UnregisterPlacementModeExtensions()
{
/*
if (IPlacementModeModule::IsAvailable())
{
IPlacementModeModule::Get().UnregisterPlacementCategory("HoudiniEngine");
}
HoudiniTools.Empty();
*/
}
void
FHoudiniEngineEditor::InitializeWidgetResource()
{
// Choice labels for all the input types
//TArray<TSharedPtr<FString>> InputTypeChoiceLabels;
InputTypeChoiceLabels.Reset();
InputTypeChoiceLabels.Add(MakeShareable(new FString(UHoudiniInput::InputTypeToString(EHoudiniInputType::Geometry))));
InputTypeChoiceLabels.Add(MakeShareable(new FString(UHoudiniInput::InputTypeToString(EHoudiniInputType::Curve))));
InputTypeChoiceLabels.Add(MakeShareable(new FString(UHoudiniInput::InputTypeToString(EHoudiniInputType::Asset))));
InputTypeChoiceLabels.Add(MakeShareable(new FString(UHoudiniInput::InputTypeToString(EHoudiniInputType::Landscape))));
InputTypeChoiceLabels.Add(MakeShareable(new FString(UHoudiniInput::InputTypeToString(EHoudiniInputType::World))));
InputTypeChoiceLabels.Add(MakeShareable(new FString(UHoudiniInput::InputTypeToString(EHoudiniInputType::Skeletal))));
BlueprintInputTypeChoiceLabels.Reset();
BlueprintInputTypeChoiceLabels.Add(MakeShareable(new FString(UHoudiniInput::InputTypeToString(EHoudiniInputType::Geometry))));
BlueprintInputTypeChoiceLabels.Add(MakeShareable(new FString(UHoudiniInput::InputTypeToString(EHoudiniInputType::Curve))));
// Choice labels for all Houdini curve types
HoudiniCurveTypeChoiceLabels.Reset();
HoudiniCurveTypeChoiceLabels.Add(MakeShareable(new FString(FHoudiniEngineEditorUtils::HoudiniCurveTypeToString(EHoudiniCurveType::Polygon))));
HoudiniCurveTypeChoiceLabels.Add(MakeShareable(new FString(FHoudiniEngineEditorUtils::HoudiniCurveTypeToString(EHoudiniCurveType::Nurbs))));
HoudiniCurveTypeChoiceLabels.Add(MakeShareable(new FString(FHoudiniEngineEditorUtils::HoudiniCurveTypeToString(EHoudiniCurveType::Bezier))));
HoudiniCurveTypeChoiceLabels.Add(MakeShareable(new FString(FHoudiniEngineEditorUtils::HoudiniCurveTypeToString(EHoudiniCurveType::Points))));
// Choice labels for all Houdini curve methods
HoudiniCurveMethodChoiceLabels.Reset();
HoudiniCurveMethodChoiceLabels.Add(MakeShareable(new FString(FHoudiniEngineEditorUtils::HoudiniCurveMethodToString(EHoudiniCurveMethod::CVs))));
HoudiniCurveMethodChoiceLabels.Add(MakeShareable(new FString(FHoudiniEngineEditorUtils::HoudiniCurveMethodToString(EHoudiniCurveMethod::Breakpoints))));
HoudiniCurveMethodChoiceLabels.Add(MakeShareable(new FString(FHoudiniEngineEditorUtils::HoudiniCurveMethodToString(EHoudiniCurveMethod::Freehand))));
// Choice labels for all Houdini ramp parameter interpolation methods
HoudiniParameterRampInterpolationLabels.Reset();
HoudiniParameterRampInterpolationLabels.Add(MakeShareable(new FString(UHoudiniParameter::GetStringFromHoudiniInterpMethod(EHoudiniRampInterpolationType::CONSTANT))));
HoudiniParameterRampInterpolationLabels.Add(MakeShareable(new FString(UHoudiniParameter::GetStringFromHoudiniInterpMethod(EHoudiniRampInterpolationType::LINEAR))));
HoudiniParameterRampInterpolationLabels.Add(MakeShareable(new FString(UHoudiniParameter::GetStringFromHoudiniInterpMethod(EHoudiniRampInterpolationType::CATMULL_ROM))));
HoudiniParameterRampInterpolationLabels.Add(MakeShareable(new FString(UHoudiniParameter::GetStringFromHoudiniInterpMethod(EHoudiniRampInterpolationType::MONOTONE_CUBIC))));
HoudiniParameterRampInterpolationLabels.Add(MakeShareable(new FString(UHoudiniParameter::GetStringFromHoudiniInterpMethod(EHoudiniRampInterpolationType::BEZIER))));
HoudiniParameterRampInterpolationLabels.Add(MakeShareable(new FString(UHoudiniParameter::GetStringFromHoudiniInterpMethod(EHoudiniRampInterpolationType::BSPLINE))));
HoudiniParameterRampInterpolationLabels.Add(MakeShareable(new FString(UHoudiniParameter::GetStringFromHoudiniInterpMethod(EHoudiniRampInterpolationType::HERMITE))));
// Choice labels for all Houdini curve output export types
HoudiniCurveOutputExportTypeLabels.Reset();
HoudiniCurveOutputExportTypeLabels.Add(MakeShareable(new FString(TEXT("Unreal Spline"))));
HoudiniCurveOutputExportTypeLabels.Add(MakeShareable(new FString(TEXT("Houdini Spline"))));
// Choice labels for all Unreal curve output curve types
//(for temporary, we need to figure out a way to access the output curve's info later)
UnrealCurveOutputCurveTypeLabels.Reset();
UnrealCurveOutputCurveTypeLabels.Add(MakeShareable(new FString(TEXT("Linear"))));
UnrealCurveOutputCurveTypeLabels.Add(MakeShareable(new FString(TEXT("Curve"))));
// Option labels for all landscape outputs bake options
HoudiniLandscapeOutputBakeOptionLabels.Reset();
HoudiniLandscapeOutputBakeOptionLabels.Add(MakeShareable(new FString(TEXT("To Current Level"))));
HoudiniLandscapeOutputBakeOptionLabels.Add(MakeShareable(new FString(TEXT("To Image"))));
HoudiniLandscapeOutputBakeOptionLabels.Add(MakeShareable(new FString(TEXT("To New World"))));
// Option labels for Houdini Engine PDG bake options
HoudiniEnginePDGBakeTypeOptionLabels.Reset();
HoudiniEnginePDGBakeTypeOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromHoudiniEngineBakeOption(EHoudiniEngineBakeOption::ToActor))));
HoudiniEnginePDGBakeTypeOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromHoudiniEngineBakeOption(EHoudiniEngineBakeOption::ToBlueprint))));
// Option labels for Houdini Engine bake options
HoudiniEngineBakeTypeOptionLabels.Reset();
HoudiniEngineBakeTypeOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromHoudiniEngineBakeOption(EHoudiniEngineBakeOption::ToActor))));
HoudiniEngineBakeTypeOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromHoudiniEngineBakeOption(EHoudiniEngineBakeOption::ToBlueprint))));
HoudiniEngineBakeTypeOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromHoudiniEngineBakeOption(EHoudiniEngineBakeOption::ToFoliage))));
HoudiniEngineBakeTypeOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromHoudiniEngineBakeOption(EHoudiniEngineBakeOption::ToWorldOutliner))));
// Option labels for Houdini Engine PDG bake options
HoudiniEnginePDGBakeSelectionOptionLabels.Reset();
HoudiniEnginePDGBakeSelectionOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromPDGBakeTargetOption(EPDGBakeSelectionOption::All))));
HoudiniEnginePDGBakeSelectionOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromPDGBakeTargetOption(EPDGBakeSelectionOption::SelectedNetwork))));
HoudiniEnginePDGBakeSelectionOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromPDGBakeTargetOption(EPDGBakeSelectionOption::SelectedNode))));
HoudiniEnginePDGBakePackageReplaceModeOptionLabels.Reset();
HoudiniEnginePDGBakePackageReplaceModeOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromPDGBakePackageReplaceModeOption(EPDGBakePackageReplaceModeOption::ReplaceExistingAssets))));
HoudiniEnginePDGBakePackageReplaceModeOptionLabels.Add(MakeShareable(new FString(FHoudiniEngineEditor::GetStringFromPDGBakePackageReplaceModeOption(EPDGBakePackageReplaceModeOption::CreateNewAssets))));
static FString IconsDir = FHoudiniEngineUtils::GetHoudiniEnginePluginDir() / TEXT("Resources/Icons/");
// Houdini Logo Brush
FString Icon128FilePath = IconsDir + TEXT("icon_houdini_logo_128");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*Icon128FilePath))
{
const FName BrushName(*Icon128FilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniLogoBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// Houdini Engine Logo Brush
FString HEIcon128FilePath = IconsDir + TEXT("icon_hengine_logo_128");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*HEIcon128FilePath))
{
const FName BrushName(*HEIcon128FilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineLogoBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// Houdini Engine Banner
FString HoudiniEngineUIIconFilePath = GetHoudiniEnginePluginDir() / TEXT("Resources/hengine_banner_d.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*HoudiniEngineUIIconFilePath))
{
const FName BrushName(*HoudiniEngineUIIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// Rebuild Icon Brush
FString HoudiniEngineUIRebuildIconFilePath = IconsDir + TEXT("rebuild_all16x16.png");
//FString HoudiniEngineUIRebuildIconFilePath = GetHoudiniEnginePluginDir() / TEXT("Resources/hengine_reload_icon.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*HoudiniEngineUIRebuildIconFilePath))
{
const FName BrushName(*HoudiniEngineUIRebuildIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIRebuildIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// Recook Icon Brush
//FString HoudiniEngineUIRecookIconFilePath = GetHoudiniEnginePluginDir() / TEXT("Resources/hengine_recook_icon.png");
FString HoudiniEngineUIRecookIconFilePath = IconsDir + TEXT("cook_all16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*HoudiniEngineUIRecookIconFilePath))
{
const FName BrushName(*HoudiniEngineUIRecookIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIRecookIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// Reset Parameters Icon Brush
//FString HoudiniEngineUIResetParametersIconFilePath = GetHoudiniEnginePluginDir() / TEXT("Resources/hengine_resetparameters_icon.png");
FString HoudiniEngineUIResetParametersIconFilePath = IconsDir + TEXT("reset_parameters16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*HoudiniEngineUIResetParametersIconFilePath))
{
const FName BrushName(*HoudiniEngineUIResetParametersIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIResetParametersIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// Bake
FString BakeIconFilePath = IconsDir + TEXT("bake_all16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*BakeIconFilePath))
{
const FName BrushName(*BakeIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIBakeIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// CookLog
FString CookLogIconFilePath = IconsDir + TEXT("cook_log16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*CookLogIconFilePath))
{
const FName BrushName(*CookLogIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUICookLogIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// AssetHelp
FString AssetHelpIconFilePath = IconsDir + TEXT("asset_help16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*AssetHelpIconFilePath))
{
const FName BrushName(*AssetHelpIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIAssetHelpIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// PDG Asset Link
// PDG
FString PDGIconFilePath = IconsDir + TEXT("pdg_link16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*PDGIconFilePath))
{
const FName BrushName(*PDGIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIPDGIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// PDG Cancel
// PDGCancel
FString PDGCancelIconFilePath = IconsDir + TEXT("pdg_cancel16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*PDGCancelIconFilePath))
{
const FName BrushName(*PDGCancelIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIPDGCancelIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// PDG Dirty All
// PDGDirtyAll
FString PDGDirtyAllIconFilePath = IconsDir + TEXT("pdg_dirty_all16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*PDGDirtyAllIconFilePath))
{
const FName BrushName(*PDGDirtyAllIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIPDGDirtyAllIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// PDG Dirty Node
// PDGDirtyNode
FString PDGDirtyNodeIconFilePath = IconsDir + TEXT("pdg_dirty_node16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*PDGDirtyNodeIconFilePath))
{
const FName BrushName(*PDGDirtyNodeIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIPDGDirtyNodeIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// PDG Pause
// PDGReset
FString PDGPauseIconFilePath = IconsDir + TEXT("pdg_pause16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*PDGPauseIconFilePath))
{
const FName BrushName(*PDGPauseIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIPDGPauseIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// PDG Reset
// PDGReset
FString PDGResetIconFilePath = IconsDir + TEXT("pdg_reset16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*PDGResetIconFilePath))
{
const FName BrushName(*PDGResetIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIPDGResetIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
// PDG Refresh
// PDGRefresh
FString PDGRefreshIconFilePath = IconsDir + TEXT("pdg_refresh16x16.png");
if (FSlateApplication::IsInitialized() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*PDGRefreshIconFilePath))
{
const FName BrushName(*PDGRefreshIconFilePath);
const FIntPoint Size = FSlateApplication::Get().GetRenderer()->GenerateDynamicImageResource(BrushName);
if (Size.X > 0 && Size.Y > 0)
{
static const int32 ProgressIconSize = 32;
HoudiniEngineUIPDGRefreshIconBrush = MakeShareable(new FSlateDynamicImageBrush(
BrushName, FVector2D(ProgressIconSize, ProgressIconSize)));
}
}
}
void
FHoudiniEngineEditor::AddLevelViewportMenuExtender()
{
FLevelEditorModule& LevelEditorModule = FModuleManager::Get().LoadModuleChecked<FLevelEditorModule>("LevelEditor");
auto& MenuExtenders = LevelEditorModule.GetAllLevelViewportContextMenuExtenders();
MenuExtenders.Add(FLevelEditorModule::FLevelViewportMenuExtender_SelectedActors::CreateRaw(this, &FHoudiniEngineEditor::GetLevelViewportContextMenuExtender));
LevelViewportExtenderHandle = MenuExtenders.Last().GetHandle();
}
void
FHoudiniEngineEditor::RemoveLevelViewportMenuExtender()
{
if (LevelViewportExtenderHandle.IsValid())
{
FLevelEditorModule* LevelEditorModule = FModuleManager::Get().GetModulePtr<FLevelEditorModule>("LevelEditor");
if (LevelEditorModule)
{
typedef FLevelEditorModule::FLevelViewportMenuExtender_SelectedActors DelegateType;
LevelEditorModule->GetAllLevelViewportContextMenuExtenders().RemoveAll(
[=](const DelegateType& In) { return In.GetHandle() == LevelViewportExtenderHandle; });
}
}
}
TSharedRef<FExtender>
FHoudiniEngineEditor::GetLevelViewportContextMenuExtender(const TSharedRef<FUICommandList> CommandList, const TArray<AActor*> InActors)
{
TSharedRef<FExtender> Extender = MakeShareable(new FExtender);
// Build an array of the HoudiniAssets corresponding to the selected actors
TArray< TWeakObjectPtr< UHoudiniAsset > > HoudiniAssets;
TArray< TWeakObjectPtr< AHoudiniAssetActor > > HoudiniAssetActors;
for (auto CurrentActor : InActors)
{
AHoudiniAssetActor * HoudiniAssetActor = Cast<AHoudiniAssetActor>(CurrentActor);
if (!HoudiniAssetActor || HoudiniAssetActor->IsPendingKill())
continue;
HoudiniAssetActors.Add(HoudiniAssetActor);
UHoudiniAssetComponent* HoudiniAssetComponent = HoudiniAssetActor->GetHoudiniAssetComponent();
if (!HoudiniAssetComponent || HoudiniAssetComponent->IsPendingKill())
continue;
HoudiniAssets.AddUnique(HoudiniAssetComponent->GetHoudiniAsset());
}
if (HoudiniAssets.Num() > 0)
{
// Add the Asset menu extension
if (AssetTypeActions.Num() > 0)
{
// Add the menu extensions via our HoudiniAssetTypeActions
FAssetTypeActions_HoudiniAsset * HATA = static_cast<FAssetTypeActions_HoudiniAsset*>(AssetTypeActions[0].Get());
if (HATA)
Extender = HATA->AddLevelEditorMenuExtenders(HoudiniAssets);
}
}
if (HoudiniAssetActors.Num() > 0)
{
// Add some actor menu extensions
FLevelEditorModule& LevelEditor = FModuleManager::GetModuleChecked<FLevelEditorModule>(TEXT("LevelEditor"));
TSharedRef<FUICommandList> LevelEditorCommandBindings = LevelEditor.GetGlobalLevelEditorActions();
Extender->AddMenuExtension(
"ActorControl",
EExtensionHook::After,
LevelEditorCommandBindings,
FMenuExtensionDelegate::CreateLambda([this, HoudiniAssetActors](FMenuBuilder& MenuBuilder)
{
MenuBuilder.AddMenuEntry(
NSLOCTEXT("HoudiniAssetLevelViewportContextActions", "HoudiniActor_Recentre", "Recentre selected"),
NSLOCTEXT("HoudiniAssetLevelViewportContextActions", "HoudiniActor_RecentreTooltip", "Recentres the selected Houdini Asset Actors pivots to their input/cooked static mesh average centre."),
FSlateIcon(FHoudiniEngineStyle::GetStyleSetName(), "HoudiniEngine.HoudiniEngineLogo"),
FUIAction(
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::RecentreSelection(); }),
FCanExecuteAction::CreateLambda([=] { return (HoudiniAssetActors.Num() > 0); })
)
);
MenuBuilder.AddMenuEntry(
NSLOCTEXT("HoudiniAssetLevelViewportContextActions", "HoudiniActor_Recook", "Recook selected"),
NSLOCTEXT("HoudiniAssetLevelViewportContextActions", "HoudiniActor_RecookTooltip", "Forces a recook on the selected Houdini Asset Actors."),
FSlateIcon(FHoudiniEngineStyle::GetStyleSetName(), "HoudiniEngine._CookSelected"),
FUIAction(
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::RecookSelection(); }),
FCanExecuteAction::CreateLambda([=] { return (HoudiniAssetActors.Num() > 0); })
)
);
MenuBuilder.AddMenuEntry(
NSLOCTEXT("HoudiniAssetLevelViewportContextActions", "HoudiniActor_Rebuild", "Rebuild selected"),
NSLOCTEXT("HoudiniAssetLevelViewportContextActions", "HoudiniActor_RebuildTooltip", "Rebuilds selected Houdini Asset Actors in the current level."),
FSlateIcon(FHoudiniEngineStyle::GetStyleSetName(), "HoudiniEngine._RebuildSelected"),
FUIAction(
FExecuteAction::CreateLambda([]() { return FHoudiniEngineCommands::RebuildSelection(); }),
FCanExecuteAction::CreateLambda([=] { return (HoudiniAssetActors.Num() > 0); })
)
);
MenuBuilder.AddMenuEntry(
NSLOCTEXT("HoudiniAssetLevelViewportContextActions", "HoudiniActor_Refine_ProxyMeshes", "Refine Houdini Proxy Meshes"),
NSLOCTEXT("HoudiniAssetLevelViewportContextActions", "HoudiniActor_Refine_ProxyMeshesTooltip", "Build and replace Houdini Proxy Meshes with Static Meshes."),
FSlateIcon(FHoudiniEngineStyle::GetStyleSetName(), "HoudiniEngine._RefineSelected"),
FUIAction(
FExecuteAction::CreateLambda([]() { FHoudiniEngineCommands::RefineHoudiniProxyMeshesToStaticMeshes(true); }),
FCanExecuteAction::CreateLambda([=] { return (HoudiniAssetActors.Num() > 0); })
)
);
})
);
}
return Extender;
}
void
FHoudiniEngineEditor::RegisterConsoleCommands()
{
// Register corresponding console commands
static FAutoConsoleCommand CCmdOpen = FAutoConsoleCommand(
TEXT("Houdini.Open"),
TEXT("Open the scene in Houdini."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::OpenInHoudini));
static FAutoConsoleCommand CCmdSave = FAutoConsoleCommand(
TEXT("Houdini.Save"),
TEXT("Save the current Houdini scene to a hip file."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::SaveHIPFile));
static FAutoConsoleCommand CCmdBake = FAutoConsoleCommand(
TEXT("Houdini.BakeAll"),
TEXT("Bakes and replaces with blueprints all Houdini Asset Actors in the current level."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::BakeAllAssets));
static FAutoConsoleCommand CCmdClean = FAutoConsoleCommand(
TEXT("Houdini.Clean"),
TEXT("Cleans up unused/unreferenced Houdini Engine temporary files."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::CleanUpTempFolder));
static FAutoConsoleCommand CCmdPause = FAutoConsoleCommand(
TEXT("Houdini.Pause"),
TEXT("Pauses Houdini Engine Asset cooking."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::PauseAssetCooking));
// Additional console only commands
static FAutoConsoleCommand CCmdCookAll = FAutoConsoleCommand(
TEXT("Houdini.CookAll"),
TEXT("Re-cooks all Houdini Engine Asset Actors in the current level."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::RecookAllAssets));
static FAutoConsoleCommand CCmdRebuildAll = FAutoConsoleCommand(
TEXT("Houdini.RebuildAll"),
TEXT("Rebuilds all Houdini Engine Asset Actors in the current level."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::RebuildAllAssets));
static FAutoConsoleCommand CCmdCookSelec = FAutoConsoleCommand(
TEXT("Houdini.Cook"),
TEXT("Re-cooks selected Houdini Asset Actors in the current level."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::RecookSelection));
static FAutoConsoleCommand CCmdRebuildSelec = FAutoConsoleCommand(
TEXT("Houdini.Rebuild"),
TEXT("Rebuilds selected Houdini Asset Actors in the current level."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::RebuildSelection));
static FAutoConsoleCommand CCmdBakeSelec = FAutoConsoleCommand(
TEXT("Houdini.Bake"),
TEXT("Bakes and replaces with blueprints selected Houdini Asset Actors in the current level."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::BakeSelection));
static FAutoConsoleCommand CCmdRestartSession = FAutoConsoleCommand(
TEXT("Houdini.RestartSession"),
TEXT("Restart the current Houdini Session."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::RestartSession));
/*
IConsoleManager &ConsoleManager = IConsoleManager::Get();
const TCHAR *CommandName = TEXT("HoudiniEngine.RefineHoudiniProxyMeshesToStaticMeshes");
IConsoleCommand *Command = ConsoleManager.RegisterConsoleCommand(
CommandName,
TEXT("Builds and replaces all Houdini proxy meshes with UStaticMeshes."),
FConsoleCommandDelegate::CreateLambda([]() { FHoudiniEngineCommands::RefineHoudiniProxyMeshesToStaticMeshes(false); }));
if (Command)
{
ConsoleCommands.Add(Command);
}
else
{
HOUDINI_LOG_ERROR(TEXT("Failed to register the '%s' console command."), CommandName);
}
*/
static FAutoConsoleCommand CCmdRefine = FAutoConsoleCommand(
TEXT("Houdini.RefineAll"),
TEXT("Builds and replaces all Houdini proxy meshes with UStaticMeshes."),
FConsoleCommandDelegate::CreateLambda([]() { FHoudiniEngineCommands::RefineHoudiniProxyMeshesToStaticMeshes(false); }));
static FAutoConsoleCommand CCmdOpenSessionSync = FAutoConsoleCommand(
TEXT("Houdini.OpenSessionSync"),
TEXT("Stops the current session, opens Houdini and automnatically start and connect a Session Sync."),
FConsoleCommandDelegate::CreateStatic(&FHoudiniEngineCommands::OpenSessionSync));
}
void
FHoudiniEngineEditor::UnregisterConsoleCommands()
{
IConsoleManager &ConsoleManager = IConsoleManager::Get();
for (IConsoleCommand *Command : ConsoleCommands)
{
if (Command)
{
ConsoleManager.UnregisterConsoleObject(Command);
}
}
ConsoleCommands.Empty();
}
void
FHoudiniEngineEditor::RegisterEditorDelegates()
{
PreSaveWorldEditorDelegateHandle = FEditorDelegates::PreSaveWorld.AddLambda([](uint32 SaveFlags, UWorld* World)
{
// Skip if this is a game world or an autosave, only refine meshes when the user manually saves
if (!World->IsGameWorld() && (SaveFlags & ESaveFlags::SAVE_FromAutosave) == 0)
{
const bool bSelectedOnly = false;
const bool bSilent = false;
const bool bRefineAll = false;
const bool bOnPreSaveWorld = true;
UWorld * const OnPreSaveWorld = World;
const bool bOnPreBeginPIE = false;
FHoudiniEngineCommands::RefineHoudiniProxyMeshesToStaticMeshes(bSelectedOnly, bSilent, bRefineAll, bOnPreSaveWorld, OnPreSaveWorld, bOnPreBeginPIE);
}
if (!World->IsGameWorld())
{
UWorld * const OnPreSaveWorld = World;
FDelegateHandle& OnPostSaveWorldHandle = FHoudiniEngineEditor::Get().GetOnPostSaveWorldOnceHandle();
if (OnPostSaveWorldHandle.IsValid())
{
if (FEditorDelegates::PostSaveWorld.Remove(OnPostSaveWorldHandle))
OnPostSaveWorldHandle.Reset();
}
// Save all dirty temporary cook package OnPostSaveWorld
OnPostSaveWorldHandle = FEditorDelegates::PostSaveWorld.AddLambda([OnPreSaveWorld](uint32 InSaveFlags, UWorld* InWorld, bool bInSuccess)
{
if (OnPreSaveWorld && OnPreSaveWorld != InWorld)
return;
FHoudiniEngineEditorUtils::SaveAllHoudiniTemporaryCookData(InWorld);
FDelegateHandle& OnPostSaveWorldHandle = FHoudiniEngineEditor::Get().GetOnPostSaveWorldOnceHandle();
if (OnPostSaveWorldHandle.IsValid())
{
if (FEditorDelegates::PostSaveWorld.Remove(OnPostSaveWorldHandle))
OnPostSaveWorldHandle.Reset();
}
});
}
});
PreBeginPIEEditorDelegateHandle = FEditorDelegates::PreBeginPIE.AddLambda([](const bool bIsSimulating)
{
const bool bSelectedOnly = false;
const bool bSilent = false;
const bool bRefineAll = false;
const bool bOnPreSaveWorld = false;
UWorld * const OnPreSaveWorld = nullptr;
const bool bOnPreBeginPIE = true;
FHoudiniEngineCommands::RefineHoudiniProxyMeshesToStaticMeshes(bSelectedOnly, bSilent, bRefineAll, bOnPreSaveWorld, OnPreSaveWorld, bOnPreBeginPIE);
});
OnDeleteActorsBegin = FEditorDelegates::OnDeleteActorsBegin.AddLambda([this](){ this->HandleOnDeleteActorsBegin(); });
OnDeleteActorsEnd = FEditorDelegates::OnDeleteActorsEnd.AddLambda([this](){ this-> HandleOnDeleteActorsEnd(); });
}
void
FHoudiniEngineEditor::UnregisterEditorDelegates()
{
if (PreSaveWorldEditorDelegateHandle.IsValid())
FEditorDelegates::PreSaveWorld.Remove(PreSaveWorldEditorDelegateHandle);
if (PreBeginPIEEditorDelegateHandle.IsValid())
FEditorDelegates::PreBeginPIE.Remove(PreBeginPIEEditorDelegateHandle);
if (OnDeleteActorsBegin.IsValid())
FEditorDelegates::OnDeleteActorsBegin.Remove(OnDeleteActorsBegin);
if (OnDeleteActorsEnd.IsValid())
FEditorDelegates::OnDeleteActorsEnd.Remove(OnDeleteActorsEnd);
}
FString
FHoudiniEngineEditor::GetStringFromHoudiniEngineBakeOption(const EHoudiniEngineBakeOption & BakeOption)
{
FString Str;
switch (BakeOption)
{
case EHoudiniEngineBakeOption::ToActor:
Str = "Actor";
break;
case EHoudiniEngineBakeOption::ToBlueprint:
Str = "Blueprint";
break;
case EHoudiniEngineBakeOption::ToFoliage:
Str = "Foliage";
break;
case EHoudiniEngineBakeOption::ToWorldOutliner:
Str = "World Outliner";
break;
}
return Str;
}
FString
FHoudiniEngineEditor::GetStringFromPDGBakeTargetOption(const EPDGBakeSelectionOption& BakeOption)
{
FString Str;
switch (BakeOption)
{
case EPDGBakeSelectionOption::All:
Str = "All Outputs";
break;
case EPDGBakeSelectionOption::SelectedNetwork:
Str = "Selected Network (All Outputs)";
break;
case EPDGBakeSelectionOption::SelectedNode:
Str = "Selected Node (All Outputs)";
break;
}
return Str;
}
FString
FHoudiniEngineEditor::GetStringFromPDGBakePackageReplaceModeOption(const EPDGBakePackageReplaceModeOption & InOption)
{
FString Str;
switch (InOption)
{
case EPDGBakePackageReplaceModeOption::CreateNewAssets:
Str = "Create New Assets";
break;
case EPDGBakePackageReplaceModeOption::ReplaceExistingAssets:
Str = "Replace Existing Assets";
break;
}
return Str;
}
const EHoudiniEngineBakeOption
FHoudiniEngineEditor::StringToHoudiniEngineBakeOption(const FString & InString)
{
if (InString == "Actor")
return EHoudiniEngineBakeOption::ToActor;
if (InString == "Blueprint")
return EHoudiniEngineBakeOption::ToBlueprint;
if (InString == "Foliage")
return EHoudiniEngineBakeOption::ToFoliage;
if (InString == "World Outliner")
return EHoudiniEngineBakeOption::ToWorldOutliner;
return EHoudiniEngineBakeOption::ToActor;
}
const EPDGBakeSelectionOption
FHoudiniEngineEditor::StringToPDGBakeSelectionOption(const FString& InString)
{
if (InString == "All Outputs")
return EPDGBakeSelectionOption::All;
if (InString == "Selected Network (All Outputs)")
return EPDGBakeSelectionOption::SelectedNetwork;
if (InString == "Selected Node (All Outputs)")
return EPDGBakeSelectionOption::SelectedNode;
return EPDGBakeSelectionOption::All;
}
const EPDGBakePackageReplaceModeOption
FHoudiniEngineEditor::StringToPDGBakePackageReplaceModeOption(const FString & InString)
{
if (InString == "Create New Assets")
return EPDGBakePackageReplaceModeOption::CreateNewAssets;
if (InString == "Replace Existing Assets")
return EPDGBakePackageReplaceModeOption::ReplaceExistingAssets;
return EPDGBakePackageReplaceModeOption::ReplaceExistingAssets;
}
const EPackageReplaceMode
FHoudiniEngineEditor::PDGBakePackageReplaceModeToPackageReplaceMode(const EPDGBakePackageReplaceModeOption& InReplaceMode)
{
EPackageReplaceMode Mode;
switch (InReplaceMode)
{
case EPDGBakePackageReplaceModeOption::CreateNewAssets:
Mode = EPackageReplaceMode::CreateNewAssets;
break;
case EPDGBakePackageReplaceModeOption::ReplaceExistingAssets:
Mode = EPackageReplaceMode::ReplaceExistingAssets;
break;
default:
{
Mode = FHoudiniPackageParams::GetDefaultReplaceMode();
HOUDINI_LOG_WARNING(TEXT("Unsupported value for EPDGBakePackageReplaceModeOption %d, using "
"FHoudiniPackageParams::GetDefaultReplaceMode() for resulting EPackageReplaceMode %d"),
InReplaceMode, Mode);
}
}
return Mode;
}
void
FHoudiniEngineEditor::HandleOnDeleteActorsBegin()
{
if (!GEditor)
return;
TArray<AHoudiniAssetActor*> AssetActorsWithTempPDGOutput;
// Iterate over all selected actors
for(FSelectionIterator It(GEditor->GetSelectedActorIterator()); It; ++It)
{
AActor* SelectedActor = Cast<AActor>(*It);
if (IsValid(SelectedActor))
{
// If the class is a AHoudiniAssetActor check if it has temporary PDG outputs
AHoudiniAssetActor* AssetActor = Cast<AHoudiniAssetActor>(SelectedActor);
if (IsValid(AssetActor))
{
UHoudiniPDGAssetLink* AssetLink = AssetActor->GetPDGAssetLink();
if (IsValid(AssetLink) && AssetLink->HasTemporaryOutputs())
{
AssetActorsWithTempPDGOutput.Add(AssetActor);
}
}
}
}
if (AssetActorsWithTempPDGOutput.Num() > 0)
{
const FText DialogTitle = LOCTEXT(
"PDGAssetLink_DeleteWithTemporaryOutputs_Title",
"Warning: PDG Asset Link(s) With Temporary Outputs");
const EAppReturnType::Type Choice = FMessageDialog::Open(
EAppMsgType::YesNo,
EAppReturnType::No,
LOCTEXT(
"PDGAssetLink_DeleteWithTemporaryOutputs",
"One or more PDG Asset Links in the selection still have temporary outputs. Are you sure you want to "
"delete these PDG Asset Links and their actors?"),
&DialogTitle);
const bool bKeepAssetLinkActors = (Choice == EAppReturnType::No);
for (AHoudiniAssetActor* AssetActor : AssetActorsWithTempPDGOutput)
{
if (bKeepAssetLinkActors)
{
GEditor->SelectActor(AssetActor, false, false);
ActorsToReselectOnDeleteActorsEnd.Add(AssetActor);
}
}
}
}
void
FHoudiniEngineEditor::HandleOnDeleteActorsEnd()
{
if (!GEditor)
return;
for (AActor* Actor : ActorsToReselectOnDeleteActorsEnd)
{
if (IsValid(Actor))
GEditor->SelectActor(Actor, true, false);
}
GEditor->NoteSelectionChange();
ActorsToReselectOnDeleteActorsEnd.Empty();
}
#undef LOCTEXT_NAMESPACE