Hi there! I have been building a script to import point data from a JSON file generated in Houdini. It seems to work great for bringing the points in (with some small snags), but if I wanted to modify the points and send them back out, UE only recognizes foliage points which were created with the foliage tool, not the python-generated ones.
I HAVE A FEELING that it is because I’m attaching the points to the wrong world_context_object in the InstancedFoliageActor.add_instances() function… but I haven’t been able to sort that out properly.
Specifically when I use the unreal.InstancedFoliageActor.get_instance_transforms() function, it only returns points created with the foliage tool. Even though I can adjust ones brought in with JSON using that as well. The points DO delete when I use the remove_all_instances() function, they register when I switch to Foliage mode and look at the foliage used, but I don’t know how to access their transforms which I need.
I’ve attached the different scripts below. I’m not sure if the problem is in the import or the export, but I suspect import because the export script is pretty straightforward so far.
Before it is suggested, I’m also testing Houdini Engine but this JSON method is needed for a more specific problem. Thank you for any help!
The JSON structure being imported:
{
"oakTree/master/geo/oakTree0001": {
"name": "oakTree0001",
"index": 0,
"tag": "Trees",
"unreal_transforms": [
[
[239108.4531, -35297.6211, 2450.9072],
[0.0013, -0.0257, -0.4446, 0.8953],
[1.5956, 1.5956, 1.5956]
], [
[-148679.1406, -24746.959, 2714.4912],
[-0.0146, -0.014, -0.9997, -0.0128],
[1.6463, 1.6463, 1.6463]
]
]
}
}
The python function for importing from JSON:
def import_and_layout_foliage_from_JSON(json_file, asset_path='/Game', import_meshes=False, import_source=0, delete_existing=1, layout=True):
sel, sel_class = get_first_selected_level_object()
if sel_class == 'InstancedFoliageActor':
data = read_JSON(json_file)
if data is not None:
# Remove existing instances of ANY foliage in object if enabled.
foliage_meshes_existing = sel.get_used_foliage_types()
if delete_existing==2 and layout:
for mesh in foliage_meshes_existing:
sel.remove_all_instances(sel, mesh)
# Process each JSON entry and create foliage from it.
for path_key in data.keys():
in_data = data[path_key]
name_key = in_data['name']
assets_to_create = name_key
filename_key = None
transform_list = in_data['unreal_transforms']
if 'filename' in in_data:
filename_key = in_data['filename']
if import_meshes and len(filename_key):
assets_to_create = import_static_meshes(asset_path=asset_path+'/'+path_key, filepaths=[filename_key], import_source=import_source, combine_meshes=True)
foliage_meshes_new = create_foliage_instanced_static_meshes(asset_path=asset_path+'/'+path_key, assets_to_create=[assets_to_create], create_foliage_folder=True)
# Remove existing instances of SELECTED foliage in object if enabled.
if delete_existing==1 and layout:
for mesh in foliage_meshes_new:
sel.remove_all_instances(sel, mesh)
# Add new instances
if layout:
point_array = unreal.Array(unreal.Transform)
for point_list in transform_list:
transform = unreal.Transform()
trans_list = point_list[0]
rotate_list = point_list[1]
scale_list = point_list[2]
transform.set_editor_property('translation', trans_list)
transform.set_editor_property('rotation', rotate_list)
transform.set_editor_property('scale3d', scale_list)
point_array.append(transform)
sel.add_instances(sel, foliage_meshes_new[0], point_array)
else:
unreal.log_error(
'''The selected object is not of the class InstancedFoliageActor. Create terrain,
add foliage, and select the foliage in the viewport then try again.'''
)
The beginning of the python function for exporting to JSON:
def export_to_JSON():
"""
Returns a dictionary containing the transform data of the foliage when you select
foliage (InstancedFoliageActor) created on terrain and run the function.
"""
sel, sel_class = get_first_selected_level_object()
houdini_dict = {}
if sel_class == 'InstancedFoliageActor':
fol_types = sel.get_used_foliage_types()
for fol_type in fol_types:
unreal.log(fol_type)
fol_transforms = sel.get_instance_transforms(fol_type)
unreal.log(fol_transforms)
return houdini_dict
else:
unreal.log_error(
"""The selected object is not of the class InstancedFoliageActor. Create terrain,
add foliage, and select the foliage then try again."""
)