Skip to content

Instantly share code, notes, and snippets.

@PranavSK
Last active October 6, 2020 18:07
Show Gist options
  • Save PranavSK/1cea39344bd830196b5372bf6be0cdfd to your computer and use it in GitHub Desktop.
Save PranavSK/1cea39344bd830196b5372bf6be0cdfd to your computer and use it in GitHub Desktop.
tool
extends EditorScript
const UE4_ASSETS_PATH: = "res://prefabs"
const UE4_ASSET_EXT: = "FBX"
const MATERIALS_STORE_PATH: = "res://materials"
const MATERIALS_STORE_EXT: = "tres"
const SCENE_STORE_PATH: = "res://prefabs"
const SCENE_STORE_EXT: = "tscn"
const STATIC_MESH_PREFIX: = "SM"
const SKELETAL_MESH_PREFIX: = "SK"
const COLLISION_MESH_PREFIX: = "UCX"
const DIR_ACCESS_ERROR: = "An error occurred when trying to access the path."
var _materials_db: = {}
func _run():
_init_materials_db()
var dir = Directory.new()
if dir.open(UE4_ASSETS_PATH) != OK:
push_error(DIR_ACCESS_ERROR)
return
dir.list_dir_begin(true, false)
print("Processing UE4 assets in %s" % UE4_ASSETS_PATH)
_process_assets_dir(dir, UE4_ASSET_EXT, funcref(self, "_process_asset_path"))
func _init_materials_db() -> void:
print("Initializing Materials Database from %s" % MATERIALS_STORE_PATH)
var material_dir = Directory.new()
if material_dir.open(MATERIALS_STORE_PATH) != OK:
push_error(DIR_ACCESS_ERROR)
return
material_dir.list_dir_begin(true, false)
_process_assets_dir(material_dir, MATERIALS_STORE_EXT, funcref(self, "_init_material"))
func _init_material(path: String):
var mat = load(path)
if not mat and not mat is Material:
push_error("Expected Material at path %s" % path)
return
if not _materials_db.has(mat.resource_name):
print("Loaded material: %s" % path)
_materials_db[mat.resource_name] = mat
func _process_assets_dir(dir: Directory, asset_ext: String, process_func: FuncRef) -> void:
var file_name = dir.get_next()
while (file_name != ""):
var path = dir.get_current_dir() + "/" + file_name
if dir.current_is_dir():
var subDir = Directory.new()
if subDir.open(path) != OK:
push_error(DIR_ACCESS_ERROR)
return
subDir.list_dir_begin(true, false)
print("Processing sub dir: %s" % path)
_process_assets_dir(subDir, asset_ext, process_func)
elif path.get_extension() == asset_ext:
print("Found file: %s" % path)
process_func.call_func(path)
# else:
# print("File %s is disregarded" % path)
file_name = dir.get_next()
func _process_asset_path(path: String) ->void:
var asset = load(path).instance()
var updated_asset = _ue4_to_godot(asset)
var packed_asset = PackedScene.new()
packed_asset.pack(updated_asset)
var scene_save_path = path.get_basename().replace(UE4_ASSETS_PATH, SCENE_STORE_PATH) + "." + SCENE_STORE_EXT
var dir_path = path.get_base_dir()
var dir = Directory.new()
if not dir.dir_exists(dir_path):
dir.make_dir_recursive(dir_path)
print("Saving Scene: %s" % scene_save_path)
ResourceSaver.save(scene_save_path, packed_asset)
func _ue4_to_godot(scene: Spatial) -> Spatial:
match scene.name.rsplit("_", 1)[0]:
STATIC_MESH_PREFIX:
return _fix_static_root(scene)
SKELETAL_MESH_PREFIX:
return _fix_skeletal_root(scene)
_:
return scene
func _fix_static_root(node: Spatial) -> Spatial:
var is_root_static_body = false
for child in node.get_children():
if child.name.rsplit("_", 1)[0] == COLLISION_MESH_PREFIX:
node.remove_child(child)
var new_child = CollisionShape.new()
new_child.shape = child.mesh.create_convex_shape()
new_child.transform = child.transform
new_child.visible = child.visible
node.add_child(new_child)
new_child.set_owner(node)
child = new_child
is_root_static_body = true
if child is MeshInstance:
child.skeleton = ""
_update_mesh_material(child)
child.rotate_x(deg2rad(-90))
if is_root_static_body:
var body = StaticBody.new()
body.name = node.name
body.transform = node.transform
body.visible = node.visible
for child in node.get_children():
node.remove_child(child)
body.add_child(child)
child.set_owner(body)
return body
return node
func _fix_skeletal_root(node: Spatial) -> Spatial:
var skel = node.get_child(0)
for child in skel.get_children():
if child is MeshInstance:
_update_mesh_material(child)
child.rotate_x(deg2rad(-90))
return node
func _update_mesh_material(node: MeshInstance) -> void:
for i in node.get_surface_material_count():
if node.get_surface_material(i):
var material_name = node.get_surface_material(i).resource_name
if not _materials_db.has(material_name):
_update_material_db(node.get_surface_material(i).duplicate(true))
node.set_surface_material(i, _materials_db[material_name])
if node.mesh.surface_get_material(i):
var material_name = node.mesh.surface_get_material(i).resource_name
if not _materials_db.has(material_name):
_update_material_db(node.mesh.surface_get_material(i).duplicate(true))
node.mesh.surface_set_material(i, _materials_db[material_name])
func _update_material_db(material: Material):
var mat_save_path = MATERIALS_STORE_PATH + "/" + material.resource_name + "." + MATERIALS_STORE_EXT
var dir_path = mat_save_path.get_base_dir()
var dir = Directory.new()
if not dir.dir_exists(dir_path):
dir.make_dir_recursive(dir_path)
print("Saving Material: %s" % mat_save_path)
ResourceSaver.save(mat_save_path, material)
_materials_db[material.resource_name] = load(mat_save_path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment