Last active
July 2, 2023 04:30
-
-
Save QaDeS/15ffb60242c4a1654bea7e3c2c87208d to your computer and use it in GitHub Desktop.
PoC: Just set the Dir to a folder of exported Mixamo FBX and have Characters and Animations imported automatically. Feedback welcome!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@tool | |
extends Node3D | |
@export_dir var dir : | |
set(value): | |
perform_import(value) | |
@export var bone_map : BoneMap | |
@export var create_Animation_tree : bool = false | |
@export var hip : String = "Hips" | |
@export var loops = [ | |
"idle", | |
"walk", | |
"strafe" | |
] | |
const extensions = ["fbx"] | |
func perform_import(path): | |
#clear_children() | |
var player = AnimationPlayer.new() | |
add_child(player, true) | |
player.set_owner(self) | |
var lib = AnimationLibrary.new() | |
var files = DirAccess.get_files_at(path) | |
var skin : Node3D | |
for file in files: | |
if not extensions.has(file.get_extension()): continue | |
var node : Node3D = ResourceLoader.load(path + "/" + file).instantiate() | |
var has_mesh = !node.find_children("", "MeshInstance3D").is_empty() | |
if has_mesh: | |
skin = add_skin(node, file.get_basename()) | |
player.root_node = skin.get_path() | |
add_anim(node, file.get_basename(), lib) | |
if skin: | |
var skel = skin.find_children("", "Skeleton3D", true, false)[0] | |
remap_bones(skel, lib) | |
var res = ResourceSaver.save(lib, path + ".tres") | |
player.add_animation_library(path.get_basename().get_file(), lib) | |
func clear_children(): | |
for child in get_children(): | |
remove_child(child) | |
func bone_name(name : String) -> String: | |
return name.split("_")[-1] | |
func remap_bones(skel : Skeleton3D, lib : AnimationLibrary): | |
var mapping = {} | |
for i in skel.get_bone_count(): | |
var name = skel.get_bone_name(i) | |
var pname = name | |
if bone_map: | |
pname = bone_map.get_skeleton_bone_name(name) | |
mapping[bone_name(pname)] = name | |
#print(mapping) | |
for name in lib.get_animation_list(): | |
var anim = lib.get_animation(name) | |
for track in anim.get_track_count(): | |
var track_name = bone_name(anim.track_get_path(track)) | |
anim.track_set_path(track, skel.name + ":" + mapping.get(track_name, track_name)) | |
func add_skin(n:Node3D, name:String): | |
var node = n.get_child(0).duplicate() | |
node.name = name | |
add_child(node) | |
node.set_owner(self) | |
var skel : Skeleton3D = node.find_children("", "Skeleton3D", true, false)[0] | |
var old_roots = skel.get_parentless_bones() | |
skel.add_bone("Root") | |
var root = skel.find_bone("Root") | |
for bone in old_roots: | |
skel.set_bone_parent(bone, root) | |
return node | |
func add_anim(node, name, lib: AnimationLibrary): | |
var player : AnimationPlayer = node.find_child("AnimationPlayer").duplicate() | |
for anim_name in player.get_animation_list(): | |
var anim : Animation = player.get_animation(anim_name).duplicate(true) | |
for track in range(anim.get_track_count()): | |
var t = anim.track_get_path(track) | |
var sub = t.get_name(t.get_name_count() - 1) | |
var type = anim.track_get_type(track) | |
for loop in loops: | |
if name.contains(loop): | |
anim.loop_mode = Animation.LoopMode.LOOP_LINEAR | |
if sub.ends_with(hip) and type == Animation.TrackType.TYPE_POSITION_3D: | |
anim.track_set_path(track, NodePath("Root")) | |
var first = Vector3(anim.track_get_key_value(track, 0)) | |
for key in range(anim.track_get_key_count(track)): | |
var value : Vector3 = anim.track_get_key_value(track, key) | |
value -= first | |
anim.track_set_key_value(track, key, value) | |
lib.add_animation(name, anim) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment