Working on new commandlet that unifies importing of props and maps
This commit is contained in:
parent
808e2c2e12
commit
8a2a86bb32
|
@ -0,0 +1,229 @@
|
|||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "CookAssetsCommandlet.h"
|
||||
#include "GameFramework/WorldSettings.h"
|
||||
#include "UObject/MetaData.h"
|
||||
// #include "CommandletPluginPrivate.h"
|
||||
|
||||
UCookAssetsCommandlet::UCookAssetsCommandlet()
|
||||
{
|
||||
IsClient = false;
|
||||
IsEditor = true;
|
||||
IsServer = false;
|
||||
LogToConsole = true;
|
||||
|
||||
// #endif
|
||||
}
|
||||
// #if WITH_EDITORONLY_DATA
|
||||
|
||||
FPackageParams UCookAssetsCommandlet::ParseParams(const FString &InParams) const
|
||||
{
|
||||
TArray<FString> Tokens;
|
||||
TArray<FString> Params;
|
||||
TMap<FString, FString> ParamVals;
|
||||
|
||||
ParseCommandLine(*InParams, Tokens, Params);
|
||||
|
||||
FPackageParams PackageParams;
|
||||
FParse::Value(*InParams, TEXT("PackageName="), PackageParams.Name);
|
||||
PackageParams.bUseCarlaMapMaterials = Params.Contains(TEXT("use-carla-map-materials"));
|
||||
|
||||
return PackageParams;
|
||||
}
|
||||
|
||||
void UCookAssetsCommandlet::MoveMeshesToMap(const FString &SrcPath, const TArray<FString> &DestPath)
|
||||
{}
|
||||
|
||||
void UCookAssetsCommandlet::LoadWorld(FAssetData &AssetData)
|
||||
{
|
||||
FString BaseMap = TEXT("/Game/Carla/Maps/BaseMap");
|
||||
|
||||
AssetsObjectLibrary = UObjectLibrary::CreateLibrary(UWorld::StaticClass(), false, GIsEditor);
|
||||
AssetsObjectLibrary->AddToRoot();
|
||||
AssetsObjectLibrary->LoadAssetDataFromPath(*BaseMap);
|
||||
AssetsObjectLibrary->LoadAssetsFromAssetData();
|
||||
AssetsObjectLibrary->GetAssetDataList(AssetDatas);
|
||||
|
||||
if (AssetDatas.Num() > 0)
|
||||
{
|
||||
AssetData = AssetDatas.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
void UCookAssetsCommandlet::AddMeshesToWorld(
|
||||
const TArray<FString> &AssetsPaths,
|
||||
bool bUseCarlaMaterials)
|
||||
{
|
||||
|
||||
AssetsObjectLibrary = UObjectLibrary::CreateLibrary(UStaticMesh::StaticClass(), false, GIsEditor);
|
||||
AssetsObjectLibrary->AddToRoot();
|
||||
AssetsObjectLibrary->LoadAssetDataFromPaths(AssetsPaths);
|
||||
AssetsObjectLibrary->LoadAssetsFromAssetData();
|
||||
|
||||
const FTransform zeroTransform = FTransform();
|
||||
FVector initialVector = FVector(0, 0, 0);
|
||||
FRotator initialRotator = FRotator(0, 180, 0);
|
||||
FActorSpawnParameters SpawnInfo;
|
||||
|
||||
MapContents.Empty();
|
||||
AssetsObjectLibrary->GetAssetDataList(MapContents);
|
||||
UStaticMesh *MeshAsset;
|
||||
AStaticMeshActor *MeshActor;
|
||||
for (auto MapAsset : MapContents)
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("Add Assets"));
|
||||
MeshAsset = CastChecked<UStaticMesh>(MapAsset.GetAsset());
|
||||
MeshActor = World->SpawnActor<AStaticMeshActor>(AStaticMeshActor::StaticClass(),
|
||||
initialVector,
|
||||
initialRotator);
|
||||
MeshActor->GetStaticMeshComponent()->SetStaticMesh(CastChecked<UStaticMesh>(MeshAsset));
|
||||
|
||||
if (bUseCarlaMaterials)
|
||||
{
|
||||
// FString AssetName;
|
||||
// MapAsset.AssetName.ToString(AssetName);
|
||||
// if (AssetName.Contains("MarkingNode"))
|
||||
// {
|
||||
// MeshActor->GetStaticMeshComponent()->SetMaterial(0,
|
||||
// MarkingNodeMaterial);
|
||||
// MeshActor->GetStaticMeshComponent()->SetMaterial(1,
|
||||
// MarkingNodeMaterialAux);
|
||||
// }
|
||||
// else if (AssetName.Contains("RoadNode"))
|
||||
// {
|
||||
// MeshActor->GetStaticMeshComponent()->SetMaterial(0,
|
||||
// RoadNodeMaterial);
|
||||
// } else if (AssetName.Contains("Terrain"))
|
||||
// {
|
||||
// MeshActor->GetStaticMeshComponent()->SetMaterial(0,
|
||||
// TerrainNodeMaterial);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
World->MarkPackageDirty();
|
||||
}
|
||||
|
||||
bool UCookAssetsCommandlet::SaveWorld(FAssetData &AssetData, FString &DestPath, FString &WorldName)
|
||||
{
|
||||
FString PackageName = DestPath + "/" + WorldName;
|
||||
UPackage *Package = AssetData.GetPackage();
|
||||
Package->SetFolderName(*DestPath);
|
||||
Package->FullyLoad();
|
||||
Package->MarkPackageDirty();
|
||||
FAssetRegistryModule::AssetCreated(World);
|
||||
|
||||
// Renaming stuff for the map
|
||||
World->Rename(*WorldName, World->GetOuter());
|
||||
FAssetRegistryModule::AssetRenamed(World, *PackageName);
|
||||
World->MarkPackageDirty();
|
||||
World->GetOuter()->MarkPackageDirty();
|
||||
|
||||
// Filling the map stuff (Code only applied for maps)
|
||||
// AOpenDriveActor *OpenWorldActor =
|
||||
//
|
||||
// CastChecked<AOpenDriveActor>(World->SpawnActor(AOpenDriveActor::StaticClass(),
|
||||
// new FVector(), NULL));
|
||||
// OpenWorldActor->BuildRoutes(WorldName);
|
||||
// OpenWorldActor->AddSpawners();
|
||||
|
||||
// Saving the package
|
||||
FString PackageFileName = FPackageName::LongPackageNameToFilename(PackageName,
|
||||
FPackageName::GetMapPackageExtension());
|
||||
return UPackage::SavePackage(Package, World, EObjectFlags::RF_Public | EObjectFlags::RF_Standalone,
|
||||
*PackageFileName, GError, nullptr, true, true, SAVE_NoError);
|
||||
}
|
||||
|
||||
FAssetsPaths UCookAssetsCommandlet::GetAssetsPathFromPackage(const FString &PackageName) const
|
||||
{
|
||||
|
||||
FString PackageConfigPath = FPaths::ProjectContentDir() + PackageName + TEXT("/Config/");
|
||||
FString PackageJsonFilePath = PackageConfigPath + PackageName + TEXT(".Package.json");
|
||||
|
||||
FAssetsPaths AssetsPaths;
|
||||
|
||||
// Get All Maps Path
|
||||
FString MapsFileJsonContent;
|
||||
if (FFileHelper::LoadFileToString(MapsFileJsonContent, *PackageJsonFilePath))
|
||||
{
|
||||
TSharedPtr<FJsonObject> JsonParsed;
|
||||
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(MapsFileJsonContent);
|
||||
if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
|
||||
{
|
||||
// Add Maps Path
|
||||
auto MapsJsonArray = JsonParsed->GetArrayField(TEXT("maps"));
|
||||
|
||||
for (auto &MapJsonValue : MapsJsonArray)
|
||||
{
|
||||
TSharedPtr<FJsonObject> MapJsonObject = MapJsonValue->AsObject();
|
||||
|
||||
FString MapAssetPath = MapJsonObject->GetStringField(TEXT("path"));
|
||||
bool bUseCarlaMaterials = MapJsonObject->GetBoolField(TEXT("use_carla_materials"));
|
||||
|
||||
// AssetsPaths.MapsPaths.Add(TPair<FString, bool>(MapAssetPath,
|
||||
// bUseCarlaMaterials));
|
||||
}
|
||||
|
||||
// Add Props Path
|
||||
auto PropJsonArray = JsonParsed->GetArrayField(TEXT("props"));
|
||||
|
||||
for (auto &PropJsonValue : PropJsonArray)
|
||||
{
|
||||
TSharedPtr<FJsonObject> PropJsonObject = PropJsonValue->AsObject();
|
||||
|
||||
FString PropAssetPath = PropJsonObject->GetStringField(TEXT("path"));
|
||||
|
||||
AssetsPaths.PropsPaths.Add(PropAssetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
return AssetsPaths;
|
||||
}
|
||||
|
||||
int32 UCookAssetsCommandlet::Main(const FString &Params)
|
||||
{
|
||||
FPackageParams PackageParams = ParseParams(Params);
|
||||
UE_LOG(LogTemp, Log, TEXT("Call to Cook Assets Commandlet"));
|
||||
UE_LOG(LogTemp, Log, TEXT("Package Name: %s"), *PackageParams.Name);
|
||||
|
||||
// Get Props and Maps Path
|
||||
UE_LOG(LogTemp, Log, TEXT("------ GET ASSETS PATH ------"));
|
||||
FAssetsPaths AssetsPaths = GetAssetsPathFromPackage(PackageParams.Name);
|
||||
|
||||
// Load World
|
||||
|
||||
UE_LOG(LogTemp, Log, TEXT("------ ADDING MAPS ------"));
|
||||
|
||||
FString RoadsPath = TEXT("/Game/Carla/Static/Road/") + PackageParams.Name;
|
||||
FString MarkingLinePath = TEXT("/Game/Carla/Static/RoadLines/") + PackageParams.Name;
|
||||
FString TerrainPath = TEXT("/Game/Carla/Static/Terrain/") + PackageParams.Name;
|
||||
|
||||
TArray<FString> DataPath = {RoadsPath, MarkingLinePath, TerrainPath};
|
||||
// DataPath.Add(RoadsPath);
|
||||
// DataPath.Add(MarkingLinePath);
|
||||
// DataPath.Add(TerrainPath);
|
||||
|
||||
UE_LOG(LogTemp, Log, TEXT("------ ADDING MAPS TO WORLD ------"));
|
||||
// for (auto Map : AssetsPaths.MapsPaths) {
|
||||
// FAssetData AssetData;
|
||||
// LoadWorld(AssetData);
|
||||
// World = CastChecked<UWorld>(AssetData.GetAsset());
|
||||
// AddMeshesToWorld(Map.Key, Map.Value);
|
||||
// }
|
||||
|
||||
UE_LOG(LogTemp, Log, TEXT("------ ADDING PROPS TO WORLD ------"));
|
||||
FAssetData AssetData;
|
||||
LoadWorld(AssetData);
|
||||
World = CastChecked<UWorld>(AssetData.GetAsset());
|
||||
// Add props in a single base map
|
||||
AddMeshesToWorld(AssetsPaths.PropsPaths, false);
|
||||
|
||||
UE_LOG(LogTemp, Log, TEXT("------ SAVING BASEMAP WORLD ------"));
|
||||
FString WorldDestPath = TEXT("/Game/") + PackageParams.Name + "/Maps/MapName";
|
||||
FString MapName("MapName");
|
||||
SaveWorld(AssetData, WorldDestPath, MapName);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// #endif
|
|
@ -0,0 +1,123 @@
|
|||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
#pragma once
|
||||
|
||||
#include "Commandlets/Commandlet.h"
|
||||
#include <Engine/World.h>
|
||||
#include <UObject/Package.h>
|
||||
#include <Misc/PackageName.h>
|
||||
#include "CoreMinimal.h"
|
||||
#include <Runtime/Engine/Classes/Engine/ObjectLibrary.h>
|
||||
#include "Carla/OpenDrive/OpenDriveActor.h"
|
||||
#include "Containers/Map.h"
|
||||
|
||||
#if WITH_EDITORONLY_DATA
|
||||
#include <Developer/AssetTools/Public/IAssetTools.h>
|
||||
#include <Developer/AssetTools/Public/AssetToolsModule.h>
|
||||
#include <AssetRegistry/Public/AssetRegistryModule.h>
|
||||
#endif // WITH_EDITORONLY_DATA
|
||||
#include <Runtime/Engine/Classes/Engine/StaticMeshActor.h>
|
||||
#include "CookAssetsCommandlet.generated.h"
|
||||
|
||||
USTRUCT()
|
||||
struct CARLA_API FPackageParams
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
FString Name;
|
||||
|
||||
bool bUseCarlaMapMaterials;
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct CARLA_API FAssetsPaths
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
TPair<TArray<FString>, bool> MapsPaths;
|
||||
|
||||
TArray<FString> PropsPaths;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UCookAssetsCommandlet
|
||||
: public UCommandlet
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor. */
|
||||
UCookAssetsCommandlet();
|
||||
#if WITH_EDITORONLY_DATA
|
||||
|
||||
/**
|
||||
* Parses the command line parameters
|
||||
* @param InParams - The parameters to parse
|
||||
*/
|
||||
FPackageParams ParseParams(const FString &InParams) const;
|
||||
|
||||
/**
|
||||
* Move meshes from one folder to another. It only works with StaticMeshes
|
||||
* @param SrcPath - Source folder from which the StaticMeshes will be obtained
|
||||
* @param DestPath - Posible folder in which the Meshes will be ordered
|
||||
*following
|
||||
* the semantic segmentation. It follows ROAD_INDEX, MARKINGLINE_INDEX,
|
||||
*TERRAIN_INDEX
|
||||
* for the position in which each path will be stored.
|
||||
*/
|
||||
void MoveMeshesToMap(const FString &SrcPath, const TArray<FString> &DestPath);
|
||||
|
||||
/**
|
||||
* Loads a UWorld object from a given path into a asset data structure.
|
||||
* @param AssetData - Structure in which the loaded UWorld will be saved.
|
||||
*/
|
||||
void LoadWorld(FAssetData &AssetData);
|
||||
|
||||
/**
|
||||
* Add StaticMeshes from a folder into the World loaded as UPROPERTY.
|
||||
* @param SrcPath - Array containing the folders from which the Assets will be
|
||||
*loaded
|
||||
* @param bMaterialWorkaround - Flag that will trigger a change in the
|
||||
*materials to fix a known bug
|
||||
* in RoadRunner.
|
||||
*/
|
||||
void AddMeshesToWorld(const TArray<FString> &AssetsPaths, bool bUseCarlaMaterials);
|
||||
|
||||
/**
|
||||
* Save a given Asset containing a World into a given path with a given name.
|
||||
* @param AssetData - Contains all the info about the World to be saved
|
||||
* @param DestPath - Path in which the asset will be saved.
|
||||
* @param WorldName - Name for the saved world.
|
||||
*/
|
||||
bool SaveWorld(FAssetData &AssetData, FString &DestPath, FString &WorldName);
|
||||
|
||||
/**
|
||||
* Get Path of all the Assets contained in the package to cook
|
||||
* @param PackageName - The name of the package to cook
|
||||
*/
|
||||
FAssetsPaths GetAssetsPathFromPackage(const FString &PackageName) const;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Main method and entry of the commandlet
|
||||
* @param Params - Parameters of the commandlet.
|
||||
*/
|
||||
virtual int32 Main(const FString &Params) override;
|
||||
|
||||
#endif // WITH_EDITORONLY_DATA
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY()
|
||||
UObjectLibrary *AssetsObjectLibrary;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<FAssetData> AssetDatas;
|
||||
|
||||
UPROPERTY()
|
||||
UWorld *World;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<FAssetData> MapContents;
|
||||
};
|
|
@ -14,6 +14,9 @@ import json
|
|||
import ntpath
|
||||
import subprocess
|
||||
|
||||
# Global variables
|
||||
IMPORT_SETTING_FILENAME = "importsetting.json"
|
||||
|
||||
# Returns a list with the paths of each package's json files that has been found recursively in the input folder
|
||||
def get_packages_json_list(folder):
|
||||
json_files = []
|
||||
|
@ -38,7 +41,7 @@ def invoke_commandlet(name, arguments):
|
|||
|
||||
# Creates the PROPS and MAPS import_setting.json file needed as an argument for using the ImportAssets commandlet
|
||||
def generate_import_setting_file(package_name, json_dirname, props, maps):
|
||||
importfile = os.path.join(os.getcwd(), "importsetting.json")
|
||||
importfile = os.path.join(os.getcwd(), IMPORT_SETTING_FILENAME)
|
||||
if os.path.exists(importfile):
|
||||
os.remove(importfile)
|
||||
|
||||
|
@ -93,45 +96,44 @@ def generate_import_setting_file(package_name, json_dirname, props, maps):
|
|||
fh.close()
|
||||
return importfile
|
||||
|
||||
# Creates the PackageName.Props.json file for the package
|
||||
def generate_prop_file(package_name, props):
|
||||
# Creates the PackageName.Package.json file for the package
|
||||
def generate_package_file(package_name, props, maps):
|
||||
output_json = {}
|
||||
|
||||
output_json["props"] = []
|
||||
for prop in props:
|
||||
name = prop["name"]
|
||||
size = prop["size"]
|
||||
|
||||
fbx_name = ntpath.basename(prop["source"]).replace(".fbx", "")
|
||||
path = os.path.join("Game", package_name, "Static", prop["tag"], prop["name"], fbx_name)
|
||||
path = "/" + "/".join(["Game", package_name, "Static", prop["tag"], prop["name"]])
|
||||
|
||||
output_json["props"].append({
|
||||
"name": name,
|
||||
"path": path,
|
||||
"size": size,
|
||||
"path": path
|
||||
})
|
||||
|
||||
prop_file_path = os.path.join(os.getcwd(), "..", "Unreal", "CarlaUE4", "Content", package_name, "Config")
|
||||
if not os.path.exists(prop_file_path):
|
||||
try:
|
||||
os.makedirs(prop_file_path)
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
with open(os.path.join(prop_file_path, package_name + ".Props.json"), 'w+') as fh:
|
||||
json.dump(output_json, fh)
|
||||
|
||||
# Creates the PackageName.Package.json file for the package
|
||||
def generate_package_file(package_name, props):
|
||||
output_json = {}
|
||||
output_json["maps"] = []
|
||||
output_json["props"] = []
|
||||
for map in maps:
|
||||
fbx_name = ntpath.basename(map["source"]).replace(".fbx", "")
|
||||
path = "/" + "/".join(["Game", package_name, "Maps", map["name"], fbx_name])
|
||||
use_carla_materials = map["use_carla_materials"] if "use_carla_materials" in map else False
|
||||
output_json["maps"].append( {
|
||||
"name" : map["name"],
|
||||
"path" : path,
|
||||
"use_carla_materials": use_carla_materials
|
||||
})
|
||||
|
||||
prop_json_dir = os.path.join(os.getcwd(), "..", "Unreal", "CarlaUE4", "Content", package_name, "Config")
|
||||
package_config_path = os.path.join(os.getcwd(), "..", "Unreal", "CarlaUE4", "Content", package_name, "Config")
|
||||
if not os.path.exists(package_config_path):
|
||||
try:
|
||||
os.makedirs(package_config_path)
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.EEXISTS:
|
||||
raise
|
||||
|
||||
output_json["props"].append(os.path.join(prop_json_dir, package_name + ".Props.json"))
|
||||
|
||||
with open(os.path.join(prop_json_dir, package_name + ".Package.json"), 'w+') as fh:
|
||||
with open(os.path.join(package_config_path, package_name + ".Package.json"), "w+") as fh:
|
||||
json.dump(output_json, fh)
|
||||
|
||||
|
||||
|
@ -142,16 +144,13 @@ def import_assets(package_name, json_dirname, props, maps):
|
|||
# Import Props
|
||||
import_setting_file = generate_import_setting_file(package_name, json_dirname, props, maps)
|
||||
commandlet_arguments = "-importSettings=\"%s\" -AllowCommandletRendering -nosourcecontrol -replaceexisting" % import_setting_file
|
||||
# invoke_commandlet(commandlet_name, commandlet_arguments)
|
||||
invoke_commandlet(commandlet_name, commandlet_arguments)
|
||||
os.remove(import_setting_file)
|
||||
|
||||
# TODO: Move maps XODR files if any
|
||||
|
||||
# Create files
|
||||
generate_prop_file (package_name, props)
|
||||
generate_package_file (package_name, props)
|
||||
|
||||
# Clean up
|
||||
# Create package file
|
||||
generate_package_file (package_name, props, maps)
|
||||
|
||||
|
||||
def import_assets_from_json_list(json_list):
|
||||
|
@ -167,6 +166,13 @@ def import_assets_from_json_list(json_list):
|
|||
|
||||
import_assets(package_name, dirname, props, maps)
|
||||
|
||||
prepare_cook_commandlet(package_name)
|
||||
|
||||
def prepare_cook_commandlet(package_name):
|
||||
commandlet_name = "CookAssets"
|
||||
commandlet_arguments = "-PackageName=%s" % package_name
|
||||
|
||||
invoke_commandlet(commandlet_name, commandlet_arguments)
|
||||
|
||||
def main():
|
||||
import_folder = os.path.join(os.getcwd(), "..", "Import")
|
||||
|
|
Loading…
Reference in New Issue