FBX Imported ready
This commit is contained in:
parent
7aaa2683f3
commit
57e34021c7
|
@ -0,0 +1,141 @@
|
|||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
|
||||
#include "FBXExporterPreparatorCommandlet.h"
|
||||
#include "GameFramework/WorldSettings.h"
|
||||
#include "UObject/MetaData.h"
|
||||
//#include "CommandletPluginPrivate.h"
|
||||
|
||||
UFBXExporterPreparatorCommandlet::UFBXExporterPreparatorCommandlet()
|
||||
{
|
||||
IsClient = false;
|
||||
IsEditor = false;
|
||||
IsServer = false;
|
||||
LogToConsole = true;
|
||||
}
|
||||
#if WITH_EDITORONLY_DATA
|
||||
|
||||
bool UFBXExporterPreparatorCommandlet::ParseParams(const FString& InParams)
|
||||
{
|
||||
Params = InParams;
|
||||
ParseCommandLine(*Params, Tokens, Switches);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UFBXExporterPreparatorCommandlet::LoadWorld(FAssetData &AssetData)
|
||||
{
|
||||
FString SeedMap;
|
||||
FParse::Value( *Params, TEXT("SourceMap="), SeedMap);
|
||||
UE_LOG(LogTemp, Display, TEXT("DANIEL: %s"), *SeedMap);
|
||||
|
||||
MapObjectLibrary = UObjectLibrary::CreateLibrary(UWorld::StaticClass(), false, GIsEditor);
|
||||
MapObjectLibrary->AddToRoot();
|
||||
MapObjectLibrary->LoadAssetDataFromPath(*SeedMap);
|
||||
MapObjectLibrary->LoadAssetsFromAssetData();
|
||||
MapObjectLibrary->GetAssetDataList(AssetDatas);
|
||||
|
||||
if (AssetDatas.Num() > 0)
|
||||
{
|
||||
AssetData = AssetDatas.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
void UFBXExporterPreparatorCommandlet::AddMeshesToWorld()
|
||||
{
|
||||
TArray<FString> CmdLineDirEntries;
|
||||
|
||||
const FString CookDirPrefix = TEXT("MESHESDIR=");
|
||||
for (int32 SwitchIdx = 0; SwitchIdx < Switches.Num(); SwitchIdx++)
|
||||
{
|
||||
const FString& Switch = Switches[SwitchIdx];
|
||||
if (Switch.StartsWith(CookDirPrefix))
|
||||
{
|
||||
FString DirToCook = Switch.Right(Switch.Len() - 10);
|
||||
|
||||
// Allow support for -COOKDIR=Dir1+Dir2+Dir3 as well as -COOKDIR=Dir1 -COOKDIR=Dir2
|
||||
for (int32 PlusIdx = DirToCook.Find(TEXT("+")); PlusIdx != INDEX_NONE; PlusIdx = DirToCook.Find(TEXT("+")))
|
||||
{
|
||||
FString DirName = DirToCook.Left(PlusIdx);
|
||||
|
||||
// The dir may be contained within quotes
|
||||
DirName = DirName.TrimQuotes();
|
||||
FPaths::NormalizeDirectoryName(DirName);
|
||||
CmdLineDirEntries.Add(DirName);
|
||||
|
||||
DirToCook = DirToCook.Right(DirToCook.Len() - (PlusIdx + 1));
|
||||
DirToCook = DirToCook.TrimQuotes();
|
||||
UE_LOG(LogTemp, Display, TEXT("DANIEL: %s"), *DirName);
|
||||
}
|
||||
|
||||
// The dir may be contained within quotes
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
AssetsObjectLibrary = UObjectLibrary::CreateLibrary(UStaticMesh::StaticClass(), false, GIsEditor);
|
||||
AssetsObjectLibrary->AddToRoot();
|
||||
AssetsObjectLibrary->LoadAssetDataFromPaths(CmdLineDirEntries);
|
||||
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)
|
||||
{
|
||||
MeshAsset = CastChecked<UStaticMesh>(MapAsset.GetAsset());
|
||||
MeshActor = World->SpawnActor<AStaticMeshActor>(AStaticMeshActor::StaticClass(),
|
||||
initialVector,
|
||||
initialRotator);
|
||||
MeshActor->GetStaticMeshComponent()->SetStaticMesh(CastChecked<UStaticMesh>(MeshAsset));
|
||||
}
|
||||
World->MarkPackageDirty();
|
||||
|
||||
}
|
||||
|
||||
bool UFBXExporterPreparatorCommandlet::SaveWorld(FAssetData &AssetData)
|
||||
{
|
||||
FString DestPath;
|
||||
FParse::Value( *Params, TEXT("DestMapPath="), DestPath);
|
||||
FString WorldName;
|
||||
FParse::Value( *Params, TEXT("DestMapName="), 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();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
int32 UFBXExporterPreparatorCommandlet::Main(const FString &ParamsIn)
|
||||
{
|
||||
ParseParams(ParamsIn);
|
||||
FAssetData AssetData;
|
||||
LoadWorld(AssetData);
|
||||
World = CastChecked<UWorld>(AssetData.GetAsset());
|
||||
AddMeshesToWorld();
|
||||
SaveWorld(AssetData);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,107 @@
|
|||
// 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 <OpenDriveActor.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 "FBXExporterPreparatorCommandlet.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UFBXExporterPreparatorCommandlet
|
||||
: public UCommandlet
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** Default constructor. */
|
||||
UFBXExporterPreparatorCommandlet();
|
||||
#if WITH_EDITORONLY_DATA
|
||||
|
||||
/**
|
||||
* Parses the command line parameters
|
||||
* @param InParams - The parameters to parse
|
||||
*/
|
||||
bool ParseParams(const FString& InParams);
|
||||
|
||||
/**
|
||||
* 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 MoveMeshes(const FString &SrcPath, const TArray<FString> &DestPath);
|
||||
|
||||
/**
|
||||
* Loads a UWorld object from a given path into a asset data structure.
|
||||
* @param SrcPath - Folder in which the world is located.
|
||||
* @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();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
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()
|
||||
bool bOverrideMaterials;
|
||||
|
||||
//UProperties are necesary or else the GC will eat everything up
|
||||
UPROPERTY()
|
||||
FString MapName;
|
||||
|
||||
UPROPERTY()
|
||||
UObjectLibrary* MapObjectLibrary;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<FAssetData> AssetDatas;
|
||||
|
||||
UPROPERTY()
|
||||
UWorld* World;
|
||||
|
||||
UPROPERTY()
|
||||
UObjectLibrary* AssetsObjectLibrary;
|
||||
|
||||
UPROPERTY()
|
||||
TArray<FAssetData> MapContents;
|
||||
|
||||
/** All commandline tokens */
|
||||
TArray<FString> Tokens;
|
||||
/** All commandline switches */
|
||||
TArray<FString> Switches;
|
||||
/** All commandline params */
|
||||
FString Params;
|
||||
};
|
|
@ -0,0 +1,125 @@
|
|||
#! /bin/bash
|
||||
|
||||
# ==============================================================================
|
||||
# -- Set up environment --------------------------------------------------------
|
||||
# ==============================================================================
|
||||
|
||||
source $(dirname "$0")/Environment.sh
|
||||
|
||||
if [ ! -d "${UE4_ROOT}" ]; then
|
||||
fatal_error "UE4_ROOT is not defined, or points to a non-existant directory, please set this environment variable."
|
||||
else
|
||||
log "Using Unreal Engine at '$UE4_ROOT'"
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# -- Parse arguments -----------------------------------------------------------
|
||||
# ==============================================================================
|
||||
|
||||
DOC_STRING="Build and packs CarlaUE4's ExportedMaps"
|
||||
|
||||
USAGE_STRING="Usage: $0 [--help] [-d|--dir] <outdir> [-f|--file] <filename> [-p|--maps] <maps_to_cook>"
|
||||
|
||||
OUTPUT_DIRECTORY=""
|
||||
FILE_NAME=""
|
||||
PATHS_TO_COOK=""
|
||||
|
||||
OPTS=`getopt -o h --long help,dir:,file:,maps: -n 'parse-options' -- "$@"`
|
||||
|
||||
if [ $? != 0 ] ; then echo "$USAGE_STRING" ; exit 2; fi
|
||||
|
||||
eval set -- "$OPTS"
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
--dir )
|
||||
OUTPUT_DIRECTORY="$2"
|
||||
shift 2;;
|
||||
--file )
|
||||
FILE_NAME="$2"
|
||||
shift 2;;
|
||||
--maps )
|
||||
MAP_TO_COOK="$2"
|
||||
shift 2;;
|
||||
--help )
|
||||
echo "$DOC_STRING"
|
||||
echo "$USAGE_STRING"
|
||||
exit 1
|
||||
;;
|
||||
* )
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "${OUTPUT_DIRECTORY}" ]; then
|
||||
OUTPUT_DIRECTORY="${PWD}/ExportedMaps"
|
||||
fi
|
||||
if [ -z "${FILE_NAME}" ]; then
|
||||
FILE_NAME="CookedExportedMaps"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# -- Package project -----------------------------------------------------------
|
||||
# ==============================================================================
|
||||
|
||||
REPOSITORY_TAG=$(get_git_repository_version)
|
||||
|
||||
BUILD_FOLDER=${OUTPUT_DIRECTORY}
|
||||
|
||||
log "Packaging user content from version '$REPOSITORY_TAG'."
|
||||
|
||||
#rm -Rf ${BUILD_FOLDER}
|
||||
mkdir -p ${BUILD_FOLDER}
|
||||
|
||||
pushd "${CARLAUE4_ROOT_FOLDER}" > /dev/null
|
||||
|
||||
log "Current project directory: '${PWD}'"
|
||||
|
||||
${UE4_ROOT}/Engine/Binaries/Linux/UE4Editor "${PWD}/CarlaUE4.uproject" -run=cook -cooksinglepackage -Map=${MAP_TO_COOK} -targetplatform="LinuxNoEditor" -OutputDir="${BUILD_FOLDER}/Cooked"
|
||||
|
||||
popd >/dev/null
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# -- Zip the project -----------------------------------------------------------
|
||||
# ==============================================================================
|
||||
|
||||
DESTINATION=${BUILD_FOLDER}/${FILE_NAME}.tar.gz
|
||||
SOURCE=${BUILD_FOLDER}/Cooked
|
||||
|
||||
pushd "${SOURCE}" >/dev/null
|
||||
|
||||
log "Packaging build."
|
||||
|
||||
#rm -Rf ./Engine
|
||||
rm -Rf ./CarlaUE4/Metadata
|
||||
rm -Rf ./CarlaUE4/Plugins
|
||||
#@TODO: Instead of this hardcoded path, we need to pick the ${MAPS_TO_COOK} path
|
||||
#rm -Rf ./CarlaUE4/${MAPS_TO_COOK_But_instead_of_"game"_the_folder_is_content}.uexp
|
||||
#rm -Rf ./CarlaUE4/${MAPS_TO_COOK_But_instead_of_"game"_the_folder_is_content}.umap
|
||||
#rm -Rf ./CarlaUE4/Content/Carla/Maps/BaseMap/TEMPMAP.uexp
|
||||
#rm -Rf ./CarlaUE4/Content/Carla/Maps/BaseMap/TEMPMAP.umap
|
||||
|
||||
rm ./CarlaUE4/AssetRegistry.bin
|
||||
|
||||
tar -czvf ${DESTINATION} *
|
||||
|
||||
popd > /dev/null
|
||||
|
||||
# ==============================================================================
|
||||
# -- Remove intermediate files and return everything to normal------------------
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
log "Removing intermediate build."
|
||||
|
||||
rm -Rf ${BUILD_FOLDER}/Cooked
|
||||
|
||||
# ==============================================================================
|
||||
# -- ...and we are done --------------------------------------------------------
|
||||
# ==============================================================================
|
||||
|
||||
log "ExportedMaps created at ${DESTINATION}"
|
||||
log "Success!"
|
|
@ -13,6 +13,7 @@ import json
|
|||
import subprocess
|
||||
import shutil
|
||||
import argparse
|
||||
import re
|
||||
|
||||
|
||||
if os.name == 'nt':
|
||||
|
@ -24,20 +25,38 @@ elif os.name == 'posix':
|
|||
def main():
|
||||
try:
|
||||
args = parse_arguments()
|
||||
import_all_fbx_in_folder(args.folder)
|
||||
folder_list = []
|
||||
import_all_fbx_in_folder(args.folder, folder_list)
|
||||
finally:
|
||||
print('\ndone.')
|
||||
|
||||
|
||||
def import_all_fbx_in_folder(fbx_folder):
|
||||
def import_all_fbx_in_folder(fbx_folder, folder_list):
|
||||
dirname = os.getcwd()
|
||||
fbx_place = os.path.join(dirname, "..", fbx_folder)
|
||||
for file in os.listdir(fbx_place):
|
||||
if file.endswith(".PropRegistry.json"):
|
||||
with open(os.path.join(dirname, "..", fbx_folder, file)) as json_file:
|
||||
data = json.load(json_file)
|
||||
import_assets_commandlet(data, fbx_folder)
|
||||
|
||||
# This will take all the fbx registerd in the provided json files
|
||||
# and place it inside unreal in the provided path (by the json file)
|
||||
import_assets_commandlet(data, fbx_folder, folder_list)
|
||||
# This part will just gather all the folders in which an fbx has been placed
|
||||
if(len(folder_list)>0):
|
||||
final_list = ""
|
||||
for folder in folder_list:
|
||||
if folder not in final_list:
|
||||
final_list += folder + "+"
|
||||
final_list = final_list[:-1]
|
||||
print(final_list)
|
||||
#Destination map (the one that will be cooked)
|
||||
dest_map_path = "/Game/Carla/Maps/BaseMap"
|
||||
dest_map_name = "TEMPMAP"
|
||||
# This should be a folder, because the commandlet will take anything inside.
|
||||
# It is better if there is only one map inside
|
||||
src_map_folder = "/Game/Carla/Maps/EmptyMap"
|
||||
prepare_cook_commandlet(final_list, src_map_folder, dest_map_path, dest_map_name)
|
||||
launch_bash_script("BuildTools/ExportFBX.sh", "--maps=%s/%s" % (dest_map_path, dest_map_name))
|
||||
|
||||
def parse_arguments():
|
||||
argparser = argparse.ArgumentParser(
|
||||
|
@ -50,12 +69,17 @@ def parse_arguments():
|
|||
help='FBX containing folder')
|
||||
return argparser.parse_args()
|
||||
|
||||
def prepare_cook_commandlet(folder_list, source_map, dest_map_path, dest_map_name):
|
||||
commandlet_name = "FBXExporterPreparator"
|
||||
commandlet_arguments = "-MeshesDir=%s -SourceMap=%s -DestMapPath=%s -DestMapName=%s" % (folder_list, source_map, dest_map_path, dest_map_name)
|
||||
invoke_commandlet(commandlet_name, commandlet_arguments)
|
||||
|
||||
def import_assets_commandlet(json_data, fbx_folder):
|
||||
|
||||
def import_assets_commandlet(json_data, fbx_folder, folder_list):
|
||||
importfile = "importsetting.json"
|
||||
if os.path.exists(importfile):
|
||||
os.remove(importfile)
|
||||
generate_json(json_data, fbx_folder, importfile)
|
||||
populate_json_and_data(json_data, fbx_folder, importfile, folder_list)
|
||||
dirname = os.getcwd()
|
||||
commandlet_name = "ImportAssets"
|
||||
import_settings = os.path.join(dirname, importfile)
|
||||
|
@ -73,8 +97,13 @@ def invoke_commandlet(name, arguments):
|
|||
full_command = "%s %s -run=%s %s" % (editor_path, uproject_path, name, arguments)
|
||||
subprocess.check_call([full_command], shell=True)
|
||||
|
||||
def launch_bash_script(script_path, arguments):
|
||||
dirname = os.getcwd()
|
||||
full_command = "%s %s" % (os.path.join(dirname, script_path), arguments)
|
||||
print("Executing: " + full_command)
|
||||
subprocess.check_call([full_command], shell=True)
|
||||
|
||||
def generate_json(json_data, fbx_folder, json_file):
|
||||
def populate_json_and_data(json_data, fbx_folder, json_file, folder_list):
|
||||
with open(json_file, "w+") as fh:
|
||||
import_groups = []
|
||||
file_names = []
|
||||
|
@ -104,12 +133,18 @@ def generate_json(json_data, fbx_folder, json_file):
|
|||
import_groups.append({
|
||||
"ImportSettings": import_settings,
|
||||
"FactoryName": "FbxFactory",
|
||||
"DestinationPath": os.path.dirname(prop["path"]),
|
||||
"DestinationPath": prop["path"],
|
||||
"bReplaceExisting": "true",
|
||||
"FileNames": file_names
|
||||
})
|
||||
#second_folder = os.path.dirname(prop["path"]).split("/Game")[1].split("/")[1]
|
||||
#folder_list.append("/Game/" + second_folder)
|
||||
folder_list.append(prop["path"])
|
||||
fh.write(json.dumps({"ImportGroups": import_groups}))
|
||||
fh.close()
|
||||
#result = re.search('/Game(.*)', os.path.dirname(prop["path"]))
|
||||
|
||||
#print(result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in New Issue