Batch Solver Demo Using Python Scripts

发布于:2024-11-21


Function Description

Batch solving for slice-of-life anime scenes (non-combat simple actions), automating the setup and solving process once clothing is prepared using scripts.

Preparatory Work

Prepare clothing in the UE editor.

● Character and Clothing Setup: Attach the Style3D component to the character blueprint and configure clothing (collision groups, physical property adjustments, etc.).

● Sequencer Setup: Configure the Style3D cache recording track (set up shots, actions, etc.)

scripts (1).zip
5.92 KB
Download

The character blueprint is configured to automatically perform Posefitting at runtime.

Example Python Script Features

● Record clothing cache via script.

● Configure character blueprints and cache recording parameters via script.

Operating Steps

In the script directory, open a terminal.

■ Configure blueprint and sequence cache recording parameters using the script: ue_command_style3d_config.py

■ Control cache generation through scripting: ue_command_style3d_run.py

Run the following command to execute.

(Engine Python path, script name)

ue_style3d_task.py

# -*-coding: utf-8 -*-

# ue ver 5.1.1

import os

import json

# ue Version 5.3.2

# Configuring style3d clothing simulation parameters and cache generation settings in Sequence.

def config_style3d(enginePath, projLuncherPath, scriptPath, frame_start, frame_end, fps, ue_bp_path, ue_map_asset_path, ue_seq_path, save_package_name,

save_package_path, style3d_asset_path, style3d_clothconfig):

ueLogCmds = ('LogSourceControl off,'

'SourceControl off,'

'LogEditorAssetSubsystem off,'

'LogEditorScripting off,'

'LogHttp off,'

'LogUtils off,'

'LogHttpListener off,'

'LogAssetRegistry off,'

'LogFileManager off,'

'LogFeaturePack off,'

'LogUnrealNames off,'

'LogDirectoryWatcher off')

ueCmd = (

"%s %s -LogCmds=\"%s\" -run=pythonscript -script=\"import sys;sys.path.append('%s');\

import style3d_config_garment_cache;\

style3d_config_garment_cache.do_cloth_solution('%d', '%d', '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%f', '%d', '%f')\""

% (

enginePath,

projLuncherPath,

ueLogCmds,

scriptPath,

frame_start,

frame_end,

fps,

ue_bp_path,

ue_map_asset_path,

ue_seq_path,

save_package_name,

save_package_path,

style3d_asset_path,

style3d_clothconfig["record_rate_scale"],

style3d_clothconfig["iterations"],

style3d_clothconfig["air_damping"]

)

)

CmdRet = os.popen(ueCmd).read()

print(CmdRet)

# Start MRQ to render and generate clothing cache.

# The rendered sequence is stored in Saved\MovieRender.

def render_MRQ_seq(enginPath, projPath, map, seq, configPath):

rendercmd = '{0} {1} {2} -game -LevelSequence="{3}" ' \

'-MoviePipelineConfig="{4}" -windowed -resx=2880 -resy=1620 -log -notexturestreaming'.format(enginPath, projPath, map, seq, configPath)

print(rendercmd)

os.system(rendercmd)

# Engine Directory

enginePath = 'E:/UnrealEngine/UE5.3/UE_5.3/Engine/Binaries/Win64/UnrealEditor-Cmd.exe'

# Project Directory

projLuncherPath = 'E:/AutoPatch/UEProject/Style3D_Automation/Demo_zdhgx/Demo_zdhgx.uproject'

# Script Directory

scriptPath = 'E:/AutoPatch/UEProject/Style3D_Automation/scripts'

# Phase1 Setting Style3D

frame_start = 0

frame_end = 300

fps = 30

ue_bp_path = 'MetaHumans/Char1/BP_Char1'

ue_map_asset_path = '/Game/DemoProject/Map/Map_2'

save_cache_path = ''

style3d_clothconfig = {"record_rate_scale": 0.2,"iterations": 300,"air_damping": 0.01}

task_configs = [

{

"ue_seq_path": '/Game/DemoProject/Sequence/Seq_01/Sequence01_Dance03',

"save_cache_name": 'Cache_Seq1',

"style3d_asset_path": '/Game/Style3D/Cloth_02',

"enable": True

},

{

"ue_seq_path": '/Game/DemoProject/Sequence/Seq_02/Sequence02_Dance12',

"save_cache_name": 'Cache_Seq2',

"style3d_asset_path": '/Game/Style3D/Cloth_02',

"enable": True

},

{

"ue_seq_path": '/Game/DemoProject/Sequence/Seq_03/Sequence03_Fitting01',

"save_cache_name": 'Cache_Seq3',

"style3d_asset_path": '/Game/Style3D/Cloth_02',

"enable": True

}

]

# Enable controls whether the task is executed, with True or False.

for task_config in task_configs:

if task_config["enable"]:

# Phase One: Configure Style3D garment assets, solver parameters, and sequence settings.

config_style3d(enginePath, projLuncherPath, scriptPath, frame_start, frame_end, fps, ue_bp_path, ue_map_asset_path, task_config["ue_seq_path"], task_config["save_cache_name"], save_cache_path, task_config["style3d_asset_path"], style3d_clothconfig)

# Phase Two: Render and Generate Clothing Cache

configPath = '/Game/Template/Blueprints/Render/Pending_MoviePipelinePrimaryConfig.Pending_MoviePipelinePrimaryConfig'

render_MRQ_seq(enginePath, projLuncherPath, ue_map_asset_path, task_config["ue_seq_path"], configPath)

#break

ue_command_style3d_config.py

# -*-coding: utf-8 -*-

# ue ver 5.1.1

import os

import unreal as ue

import json

def track_to_dict(track):

t = {

'name' : str(track.get_display_name()),

'type' : track.get_class().get_name(),

'sections' : []

}

for section in track.get_sections():

section_range = section.get_range()

t['sections'].append({

'range' : {

'has_start' : section_range.has_start,

'start' : section_range.inclusive_start,

'has_end' : section_range.has_end,

'end' : section_range.exclusive_end,

},

'type': section.get_class().get_name()

})

return t

def do_cloth_solution(frame_start, frame_end, fps, ue_bp_path, ue_map_asset_path, ue_seq_path, save_package_name,

save_package_path, style3d_asset_path, record_rate_scale, iterations, air_damping):

"""

Args:

frame_start: shot start frame num, int32, eg: 950

frame_end: shot end frame num, int32, eg: 1058

fps: shot fps, int32, eg: 25

ue_bp_path: solution used bp asset ue path, string, eg: "/Game/character/hanli_default/BP/bp_hanli_default"

ue_map_asset_path: map asset ue path

ue_seq_path: sequence asset ue path

save_package_name: solution file name for save in ue, string

save_package_path: solution file ue path for save in ue, string

style3d_asset_path: style3d cloth asset path

style3d_clothconfig: { 'record_rate_scale': 0.3,

'iterations': 50,

'air_damping': 0.1,

}

Returns:

solution_finish_path: file ue path of solution finished in ue, string

"""

"""

ue.log_warning("style3d_clothconfigfile_path:" + style3d_clothconfigfile_path)

if ue.EditorAssetLibrary.does_asset_exist(style3d_clothconfigfile_path):

ue.log_warning("have style3d_clothconfigfile_path!")

blueprint_clothconfig_asset = ue.EditorAssetLibrary.load_asset(style3d_clothconfigfile_path)

bp_class = ue.load_object(None, blueprint_clothconfig_asset.generated_class().get_path_name())

bp_cdo = ue.get_default_object(bp_class)

bp_cdo.set_editor_property('new_cache_name', 'hahahaaha')

ue.EditorAssetLibrary.save_asset(style3d_clothconfigfile_path)

"""

# Assuming the Style3D component has been mounted on the Blueprint Actor and the clothing asset has also been attached to the Style3D component, only the cache name and some solver parameters need to be configured here.

if ue.EditorAssetLibrary.does_asset_exist(ue_bp_path):

ue.log_warning("have ue_bp_path: " + ue_bp_path)

bp_asset = ue.load_asset(ue_bp_path)

#style3d_clothconfig_obj = json.loads(style3d_clothconfig)

#style3d_clothconfig_obj = {"record_rate_scale": 0.4,"simulate_time_scale": 1.2,"iterations": 60,"air_damping": 0.2}

subsystem: ue.SubobjectDataSubsystem = ue.get_engine_subsystem(ue.SubobjectDataSubsystem)

root_data_handle: ue.SubobjectDataHandle = subsystem.k2_gather_subobject_data_for_blueprint(context=bp_asset)

objects = []

#get components in blueprint

for handle in root_data_handle:

subobject = subsystem.k2_find_subobject_data_from_handle( handle )

objects.append( ue.SubobjectDataBlueprintFunctionLibrary.get_object( subobject ) )

#remove duplicates

objects = list(dict.fromkeys(objects))

#check if Style3DComponent and update the parameters

for object in objects:

if "Style3DComponent" in str(object):

ue.log_warning("have style3d_component!")

style3d_component = object

#style3d_component.set_editor_property('new_cache_name', save_package_name)

style3d_component.get_editor_property('cache_record_setting').set_editor_property('record_rate_scale', float(record_rate_scale))

style3d_component.get_editor_property('solver_property').set_editor_property('iterations', int(iterations))

style3d_component.get_editor_property('solver_property').set_editor_property('air_damping', float(air_damping))

if ue.EditorAssetLibrary.does_asset_exist(style3d_asset_path):

style3d_asset = ue.load_asset(style3d_asset_path)

style3d_component.set_editor_property('meta_data_asset', style3d_asset)

ue.EditorAssetLibrary.save_asset(ue_bp_path)

else:

ue.log_warning("have not find ue_bp_path!")

# Here, assuming the Style3D cache recording track has already been configured in the Sequence, you just need to set the cache name, start frame, and end frame.

ue.log_warning("ue_seq_path: " + ue_seq_path)

if ue.EditorAssetLibrary.does_asset_exist(ue_seq_path):

ue.log_warning("have ue_seq_path!")

world = ue.EditorLoadingAndSavingUtils.load_map(ue_map_asset_path)

sequence = ue.load_asset(ue_seq_path, ue.LevelSequence)

bindings = sequence.get_bindings()

#ue.log_warning(bindings)

for binding in bindings:

tracks = binding.get_tracks()

for track in tracks:

for section in track.get_sections():

section_class_str = str(section.get_class())

ue.log_warning(section_class_str)

if section_class_str.find("Style3DMovieSceneGarmentCacheSection") != -1:

#section.set_start_frame_seconds(0)

#section.set_end_frame_seconds(100)

section.get_editor_property('params').set_editor_property('garment_cache_name', save_package_name)

#integrate_info = section.get_editor_property('params').get_editor_property('garment_integrate_info')

#style3d_asset_name = integrate_info.get_editor_property('garment_asset_map')['default'].get_editor_property('garment_asset').get_name()

style3d_asset_name = 'test'

ue.LevelSequenceEditorBlueprintLibrary.refresh_current_level_sequence()

ue.EditorAssetLibrary.save_asset(ue_seq_path)

solution_finish_path = '/Game/Style3D/GarmentCache/'# + style3d_asset_name + '/' + save_package_name

return solution_finish_path

Appendix

Unreal Python Study


(Engine Python path, script name)

Submit Feedback