UE 4エディタPythonプログラミング3-コンテンツブラウザ操作


普段コンテンツブラウザで実行している資産操作は、Pythonスクリプトでも実行できます
資産とディレクトリの保存
# coding: utf-8

import unreal

def saveAsset():
    unreal.EditorAssetLibrary.save_asset(#     
        '/Game/Textures/TX_LightSpotMove', only_if_is_dirty=False)

def saveDirectory():
    unreal.EditorAssetLibrary.save_directory(#     
        '/Game', only_if_is_dirty=False, recursive=True)

def getPackageFromPath():
    return unreal.load_package('/Game/Textures/TX_LightSpotMove')#         

def getAllDirtyPackage():
    packages = unreal.Array(unreal.Package)
    for x in unreal.EditorLoadingAndSavingUtils.get_dirty_content_packages():
        packages.append(x)
    for x in unreal.EditorLoadingAndSavingUtils.get_dirty_map_packages():  # map        
        packages.append(x)
    return packages

def saveAllDirtyPackages(show_dialog=False):
    if show_dialog:
        unreal.EditorLoadingAndSavingUtils.save_dirty_packages_with_dialog(
            save_map_packages=True, save_content_packages=True)
    else:
        unreal.EditorLoadingAndSavingUtils.save_dirty_packages(
            save_map_packages=True, save_content_packages=True)

def savePackages(packages=[], show_dialog=False):
    if show_dialog:
        unreal.EditorLoadingAndSavingUtils.save_packages_with_dialog(#      
            packages, only_dirty=False)
    else:
        unreal.EditorLoadingAndSavingUtils.save_packages(
            packages, only_dirty=False)

作成、コピー、名前変更、削除
フォルダの場合:
# coding: utf-8

import unreal

def createDirectory():
    unreal.EditorAssetLibrary.make_directory('/Game/MyNewDirectory')

def duplicateDirectory():
    return unreal.EditorAssetLibrary.duplicate_directory(
        '/Game/MyNewDirectory', '/Game/MyNewDirectory_Duplicated')

def deleteDirectory():
    unreal.EditorAssetLibrary.delete_directory('/Game/MyNewDirectory')

def directoryExist():
    print(unreal.EditorAssetLibrary.does_directory_exist('/Game/MyNewDirectory'))
    print(unreal.EditorAssetLibrary.does_directory_exist(
        '/Game/MyNewDirectory_Duplicated'))

def renameDirectory():
    unreal.EditorAssetLibrary.rename_directory(
        '/Game/MyNewDirectory_Duplicated', '/Game/MyNewDirectory_Renamed')

単一資産の場合:
# coding: utf-8

import unreal

def duplicateAsset():
    return unreal.EditorAssetLibrary.duplicate_asset(
        '/Game/StaticMesh/c', '/Game/StaticMesh/c_Duplicate')

def deleteAsset():
    unreal.EditorAssetLibrary.delete_asset('/Game/StaticMesh/c_Duplicate')

def assetExist():
    print(unreal.EditorAssetLibrary.does_asset_exist('/Game/StaticMesh/c'))
    print(unreal.EditorAssetLibrary.does_asset_exist(
        '/Game/StaticMesh/c_Duplicate'))

def renameAsset():
    unreal.EditorAssetLibrary.rename_asset(
        '/Game/StaticMesh/c', '/Game/StaticMesh/c_Renamed')

def duplicateAssetDialog(show_diaglog=True):
    if show_diaglog:
        unreal.AssetToolsHelpers.get_asset_tools().duplicate_asset_with_dialog(
            'c_Duplicate',                               # asset_name
            '/Game/StaticMesh',                         # package_path
            unreal.load_asset('/Game/StaticMesh/c'))  # original_object
    else:
        unreal.AssetToolsHelpers.get_asset_tools().duplicate_asset(
            'c_Duplicate',
            '/Game/StaticMesh',
            unreal.load_asset('/Game/StaticMesh/c'))

def renameAssetDialog(show_diaglog=True):
    first_rename_data = unreal.AssetRenameData(unreal.load_asset(
        '/Game/StaticMesh/c'), '/Game/StaticMesh', 'c_Renamed')
    second_rename_data = unreal.AssetRenameData(unreal.load_asset(
        '/Game/StaticMesh/c_Duplicate'), '/Game/StaticMesh', 'c_Duplicate_Renamed')

    if show_diaglog:
        unreal.AssetToolsHelpers.get_asset_tools().rename_assets_with_dialog(
            [first_rename_data, second_rename_data])
    else:
        unreal.AssetToolsHelpers.get_asset_tools().rename_assets(
            [first_rename_data, second_rename_data])

フォルダの色を変更
フォルダの色を変更するには、プロファイルを変更することで完了します.まず、C++を使用してプロファイルを変更します.
UFUNCTION(BlueprintCallable, Category = "Unreal Python")
static void SetFolderColor(FString folderPath, FLinearColor Color)
{
     
	GConfig->SetString(TEXT("PathColor"), *folderPath, *Color.ToString(), GEditorPerProjectIni);
}

Pythonを使用してC++関数を呼び出します.
# coding: utf-8

import unreal

def getGradientColor(x):
    return (0, 1, 1, 1)

def generateColoredDirectories():
    for x in range(100, 400):
        dir_path = '/Game/PythonGenerated/'+str(x)
        linear_color = getGradientColor(x)
        unreal.ZFunctions.set_folder_color(dir_path, linear_color)
        unreal.EditorAssetLibrary.make_directory(dir_path)

特定のアセットのエディタを開く
現在、Pythonでは特定のリソースの編集ウィンドウを開く機能しかなく、閉じる機能はC++C+:
#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
// (    C#       "UnrealEd"     )
#include "Editor/UnrealEd/Public/Toolkits/AssetEditorManager.h"
#include "ZFunctions.generated.h"

UCLASS()
class TEMP_SCRIPT_API UZFunctions : public UBlueprintFunctionLibrary
{
     
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable,Category="Unreal Python")
	static void CloseEditorForAssets(TArray<UObject*> Assets)
	{
     
		FAssetEditorManager& AssetEditorManager = FAssetEditorManager::Get();
		for (UObject* Asset : Assets)
		{
     
			AssetEditorManager.CloseAllEditorsForAsset(Asset);
		}
	}

	UFUNCTION(BlueprintCallable, Category = "Unreal Python")
	static TArray<UObject*> GetAssetsOpenedInEditor()
	{
     
		FAssetEditorManager& AssetEditorManager = FAssetEditorManager::Get();
		return AssetEditorManager.GetAllEditedAssets();
	}
};

Python:
# coding: utf-8

import unreal

#    Python          
def openAssets():
    assets = [unreal.load_asset('/Game/Textures/Colours'),
              unreal.load_asset('/Game/SkeletalMeshes/Character'),
              unreal.load_asset('/Game/Sounds/kof')]
    unreal.AssetToolsHelpers.get_asset_tools().open_editor_for_assets(assets)

def getAllOpenedAssets():
    return unreal.ZFunctions.get_assets_opened_in_editor()

def closeAssets():
    assets = getAllOpenedAssets()#        
    unreal.ZFunctions.close_editor_for_assets(assets)#   

資産の選択
選択した資産もC++で実現し、Pythonを使用してC++を呼び出します.C++コードは次のとおりです.
#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Editor/ContentBrowser/Public/ContentBrowserModule.h"// "ContentBrowser"
#include "Editor/ContentBrowser/Private/SContentBrowser.h"// "ContentBrowser"
#include "Runtime/AssetRegistry/Public/AssetRegistryModule.h"// "AssetRegistry"
#include "ZFunctions.generated.h"

UCLASS()
class TEMP_SCRIPT_API UZFunctions : public UBlueprintFunctionLibrary
{
     
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable, Category = "Unreal Python")
		static TArray<FString> GetSelectedAssets()
	{
     
		FContentBrowserModule& ContentBrowserModule = 
			FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");

		TArray<FAssetData> SelectedAssets;
		ContentBrowserModule.Get().GetSelectedAssets(SelectedAssets);

		TArray<FString> Result;
		for (auto& AssetData : SelectedAssets)
		{
     
			Result.Add(AssetData.PackageName.ToString());
		}
		return Result;
	}

	UFUNCTION(BlueprintCallable, Category = "Unreal Python")
		static void SetSelectedAssets(TArray<FString> Paths)
	{
     
		FContentBrowserModule& ContentBrowserModule =
			FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");
		FAssetRegistryModule& AssetRegistryModule =
			FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");

		TArray<FName> PathsName;
		for (auto Path : Paths)
		{
     
			PathsName.Add(*Path);
		}

		FARFilter AssetFilter;
		AssetFilter.PackageNames = PathsName;

		TArray<FAssetData> AssetDatas;
		AssetRegistryModule.Get().GetAssets(AssetFilter, AssetDatas);
		ContentBrowserModule.Get().SyncBrowserToAssets(AssetDatas);
	}

	UFUNCTION(BlueprintCallable, Category = "Unreal Python")
		static TArray<FString> GetSelectedFolders()
	{
     
		FContentBrowserModule& ContentBrowserModule =
			FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");

		TArray<FString> SelectedFolders;
		ContentBrowserModule.Get().GetSelectedFolders(SelectedFolders);//                !
		return SelectedFolders;
	}



	UFUNCTION(BlueprintCallable, Category = "Unreal Python")
		static void SetSelectedFolders(TArray<FString> Paths)
	{
     
		FContentBrowserModule& ContentBrowserModule =
			FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");

		TArray<FString> SelectedFolders;
		ContentBrowserModule.Get().SyncBrowserToFolders(Paths);
	}
};

Python:
# coding: utf-8

import unreal

def showAssetsInContentBrowers():
    '''         '''
    paths = ['/Game/Textures/Colours', '/Game/SkeletalMeshes/Character']
    unreal.EditorAssetLibrary.sync_browser_to_objects(paths)  #        

def getSelectedAssets():
    return unreal.ZFunctions.get_selected_assets()

def setSelectedAssets():
    '''   C++           '''
    paths = ['/Game/Textures/Colours', '/Game/SkeletalMeshes/Character']
    return unreal.ZFunctions.set_selected_assets(paths)

def getSelectedFolders():
    return unreal.ZFunctions.get_selected_folders()

def setSelectedFolders():
    paths = ['/Game/Textures', '/Game/SkeletalMeshes']
    return unreal.ZFunctions.set_selected_folders(paths)

資産の作成
# coding: utf-8

import unreal

def createGenericAsset(asset_path='', unique_name=True, asset_class=None, asset_factory=None):
    # 1、            
    if unique_name:
        asset_path, asset_name = unreal.AssetToolsHelpers.get_asset_tools(
        ).create_unique_asset_name(
            base_package_name=asset_path,  #   
            suffix='')                     #   
    # 2、    
    if not unreal.EditorAssetLibrary.does_asset_exist(asset_path=asset_path):
        #        ,         
        path = asset_path.rsplit('/', 1)[0]
        name = asset_path.rsplit('/', 1)[1]
        return unreal.AssetToolsHelpers.get_asset_tools().create_asset(
            asset_name=name,
            package_path=path,
            asset_class=asset_class,
            factory=asset_factory
        )
    return unreal.load_asset(asset_path)

def createGenericAsset_EXAMPLE():
    base_path = '/Game/GenericAssets/'
    generic_assets = [
        [base_path+'sequence',   unreal.LevelSequence,  unreal.LevelSequenceFactoryNew()],
        [base_path+'material',   unreal.Material,       unreal.MaterialFactoryNew()],
        [base_path+'world',      unreal.World,           unreal.WorldFactory()],
        [base_path+'particle',   unreal.ParticleSystem, unreal.ParticleSystemFactoryNew()],
        [base_path+'flipbook',   unreal.PaperFlipbook,  unreal.PaperFlipbookFactory()],
        [base_path+'data_table', unreal.DataTable,      unreal.DataTableFactory()]#     
    ]
    for asset in generic_assets:
        print createGenericAsset(asset[0], True, asset[1], asset[2])