Announcement

Collapse
No announcement yet.

[SOLVED] Images As Planes For Unreal

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    [SOLVED] Images As Planes For Unreal

    I put together a short script that scans a folder and creates a mesh for each image. It links the image to a material and assigns the material to the mesh. It stacks up your images in z-space.
    Code:
    # Images As Planes, for the Unreal Editor
    # Author: Atom
    # This script will scan a folder for image files with a specific file extenstion.
    # A companion mesh will be generated for each file found in the folder.
    # A material will be assigned to the mesh linking the image.
    # (c) 2020 Atom
    # 10/17/20
    
    import unreal
    import os, re, platform
    
    def returnValidUnrealMaterialName(passedItem):
    # Replace any illegal characters for names here.
    s = re.sub("[^0-9a-zA-Z\.]+", "_", passedItem)
    s = s.replace(".","_")
    return s
    
    # Crude width height detection for now.
    # Only supports GIFs, PNGs, and JPGs.
    # Alternately install PIL or dimensions.
    # Or maybe someone can demonstrate how to get the width/height out of an image map?
    def get_image_size(file_path):
    """
    Return (width, height) for a given img file content - no external
    dependencies except the os and struct modules from core
    """
    size = os.path.getsize(file_path)
    #print size
    with open(file_path) as input:
    height = -1
    width = -1
    data = input.read(25)
    #print data
    
    if (size >= 10) and data[:6] in ('GIF87a', 'GIF89a'):
    # GIFs
    w, h = struct.unpack("<HH", data[6:10])
    width = int(w)
    height = int(h)
    elif ((size >= 24) and data.startswith('\211PNG\r\n\032\n')
    and (data[12:16] == 'IHDR')):
    # PNGs
    w, h = struct.unpack(">LL", data[16:24])
    width = int(w)
    size = os.path.getsize(file_path)
    # Weird?
    with open(file_path) as input:
    height = -1
    width = -1
    data = input.read(25)
    print data
    height = int(h)
    elif (size >= 16) and data.startswith('\211PNG\r\n\032\n'):
    # older PNGs?
    w, h = struct.unpack(">LL", data[8:16])
    width = int(w)
    height = int(h)
    elif (size >= 2) and data.startswith('\377\330'):
    # JPEG
    msg = " raised while trying to decode as JPEG."
    input.seek(0)
    input.read(2)
    b = input.read(1)
    try:
    while (b and ord(b) != 0xDA):
    while (ord(b) != 0xFF): b = input.read(1)
    while (ord(b) == 0xFF): b = input.read(1)
    if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
    input.read(3)
    h, w = struct.unpack(">HH", input.read(4))
    break
    else:
    input.read(int(struct.unpack(">H", input.read(2))[0])-2)
    b = input.read(1)
    width = int(w)
    height = int(h)
    except:
    # Unsupported jpeg file type.
    print "Unsupported JPG type."
    pass
    else:
    # Unsupported file extension, extend to suport more file types.
    print "Unsupported file extension."
    pass
    return width, height
    
    def returnFilesLike(passedFolderName, passedFileExtension = ".jpg"):
    result = []
    #print passedFolderName
    for file in os.listdir(passedFolderName):
    if file.endswith(passedFileExtension):
    result.append(os.path.join(passedFolderName,file))
    return result
    
    def importListOfImageMaps(passedList, passedTargetFolder):
    lst_texture2D = []
    data = unreal.AutomatedAssetImportData()
    data.set_editor_property('destination_path', passedTargetFolder) # Unreal game folder.
    data.set_editor_property('filenames', passedList)
    lst_texture2D = unreal.AssetToolsHelpers.get_asset_tools().import_assets_automated(data)
    return lst_texture2D
    
    def createNewImageMapOpaqueMaterial(passedAssetPath, passedMaterialName, passedDiffuseTexture, passedNormalTexture, passedDiffuseColor, passedSpec, passedRough):
    # Create a material.
    assetTools = unreal.AssetToolsHelpers.get_asset_tools()
    mf = unreal.MaterialFactoryNew()
    mat_closure = assetTools.create_asset("M_%s" % passedMaterialName, passedAssetPath, unreal.Material, mf)
    
    # Make a texture diffuse node.
    if passedDiffuseTexture!=None:
    # Add an image node.
    ts_node_diffuse = unreal.MaterialEditingLibrary.create_material_expression(mat_closure,unreal.MaterialExpressionTextureSample,-384,-200)
    ts_node_diffuse.texture = passedDiffuseTexture
    unreal.MaterialEditingLibrary.connect_material_property(ts_node_diffuse, "RGBA", unreal.MaterialProperty.MP_BASE_COLOR)
    else:
    # Add a color constant node.
    ts_node_diffuse = unreal.MaterialEditingLibrary.create_material_expression(mat_closure,unreal.MaterialExpressionConstant3Vector,-384,-200)
    value = unreal.LinearColor(float(passedDiffuseColor[0]),float(passedDiffuseColor[1]),float(passedDiffuseColor[2]),1.0)
    ts_node_diffuse.set_editor_property("constant", value)
    unreal.MaterialEditingLibrary.connect_material_property(ts_node_diffuse, "", unreal.MaterialProperty.MP_BASE_COLOR)
    '''
    # Make a texture normal node.
    if passedNormalTexture!=None:
    ts_node_normal = unreal.MaterialEditingLibrary.create_material_expression(mat_closure,unreal.MaterialExpressionTextureSample,-384,200)
    unreal.MaterialEditingLibrary.connect_material_property(ts_node_normal, "RGB", unreal.MaterialProperty.MP_NORMAL)
    # Change this sampler color sample type to work with normal types.
    ts_node_normal.sampler_type = unreal.MaterialSamplerType.SAMPLERTYPE_NORMAL
    ts_node_normal.texture = passedNormalTexture
    '''
    # Make a constant float node.
    ts_node_roughness = unreal.MaterialEditingLibrary.create_material_expression(mat_closure,unreal.MaterialExpressionConstant,-125,150)
    ts_node_roughness.set_editor_property('R', passedRough)
    unreal.MaterialEditingLibrary.connect_material_property(ts_node_roughness, "", unreal.MaterialProperty.MP_ROUGHNESS)
    
    # Make a constant float node.
    ts_node_specular = unreal.MaterialEditingLibrary.create_material_expression(mat_closure,unreal.MaterialExpressionConstant,-125,50)
    ts_node_specular.set_editor_property('R', passedSpec)
    unreal.MaterialEditingLibrary.connect_material_property(ts_node_specular, "", unreal.MaterialProperty.MP_SPECULAR)
    
    unreal.MaterialEditingLibrary.recompile_material(mat_closure)
    return mat_closure
    
    def imagesToPlanes (passedPath, passedType, passedMaterialPath, passedTexturePath):
    lst_files = returnFilesLike(passedPath, passedType)
    if len(lst_files):
    as_cube = True
    # Collect list of image files associated with this folder.
    lst_textures = importListOfImageMaps(lst_files, texture_path) #should match the length of list_files.
    
    for i,file in enumerate(lst_files):
    depth = i * 25.0
    thickness = 0.002
    w,h = get_image_size(file)
    
    # Create a map file asset for each image in our list.
    local_name = os.path.basename(file)
    local_name_only = os.path.splitext(local_name)[0]
    shader_name = returnValidUnrealMaterialName("%s" % local_name_only)
    mesh_name = returnValidUnrealMaterialName("SM_%s" % local_name_only)
    
    # Defaults for new material.
    reflection_weight = 0.1
    reflection_roughness = 0.23
    diffuse_color = [0.18,0.18,0.18]
    temp_material = createNewImageMapOpaqueMaterial(passedMaterialPath, shader_name, lst_textures[i], None, diffuse_color, reflection_weight, reflection_roughness)
    
    # Make a static mesh plane.
    ell = unreal.EditorLevelLibrary
    eal = unreal.EditorAssetLibrary
    mesh_actor = ell.spawn_actor_from_class(unreal.StaticMeshActor.static_class(), unreal.Vector(depth, 0, 100), unreal.Rotator(0, 0, 0))
    mesh_actor.set_actor_label(mesh_name)
    mesh_comp = mesh_actor.get_component_by_class(unreal.StaticMeshComponent.static_class())
    if as_cube:
    temp_mesh = eal.load_asset("StaticMesh'/Engine/BasicShapes/Cube.Cube'") # Assume asset is created at default scale of 1.0.
    else:
    temp_mesh = eal.load_asset("StaticMesh'/Engine/BasicShapes/Plane.Plane'") # Assume asset is created at default scale of 1.0.
    mesh_comp.set_static_mesh(temp_mesh)
    mesh_comp.set_editor_property("override_materials", [temp_material])
    if w != -1:
    # Guestimate from brief file header review.
    mesh_comp.set_editor_property("relative_scale3d", unreal.Vector(thickness, w*0.001, h*0.001))
    else:
    # Default to 16:9.
    mesh_comp.set_editor_property("relative_scale3d", unreal.Vector(thickness, 1.6, 0.9)) # Set the aspect ratio of image here
    else:
    print"This combination [%s].[%s] produces no results." % (passedPath, passedType)
    
    # Program begins here.
    asset_path = "/Game"
    # Select which disk folder to scan.
    n = 2
    if n==1:
    folder_path = r'F:\Keep\Maps\Bullet_Holes'
    extension = ".png"
    material_path = "%s/Bullet_Holes/Mats" % asset_path
    texture_path = "%s/Bullet_Holes/Tex" % asset_path
    if n==2:
    folder_path = r'F:\Keep\Maps\fur'
    extension = ".jpg"
    material_path = "%s/Fur/Mats" % asset_path
    texture_path = "%s/Fur/Tex" % asset_path
    
    imagesToPlanes (folder_path,extension,material_path,texture_path)
    print "Images To Planes complete."
    Last edited by AtomicPerception; 10-17-2020, 02:01 PM.
Working...
X