Skip to content

Instantly share code, notes, and snippets.

@cmaher
Last active November 21, 2021 17:42
Show Gist options
  • Save cmaher/1a80c983f6e8f753c6692f36a45a21fa to your computer and use it in GitHub Desktop.
Save cmaher/1a80c983f6e8f753c6692f36a45a21fa to your computer and use it in GitHub Desktop.
Add a weapon bone to synty models
import sys
import argparse
import pathlib
import subprocess
import os
import time
from mathutils import Vector
import math
try:
import bpy
except ImportError:
bpy = None
def add_bone(parent_bone, new_bone):
bpy.ops.object.editmode_toggle()
armature = bpy.context.active_object
bones = armature.data.edit_bones
right_hand = bones[parent_bone]
wep_bone = bones.new(new_bone)
wep_bone.head = right_hand.tail
wep_bone.tail = wep_bone.head + Vector([0, 0.01, 0])
wep_bone.parent = right_hand
bpy.ops.object.editmode_toggle()
# first, convert the FBX files to binary (https://www.autodesk.com/developer-network/platform-technologies/fbx-converter-archives)
# adapted from https://gist.github.com/wojtossfm/cd0808a35753341036fef8efec7704ce
# blender --python synty_weapon.py -- <directory_of_meshes> <output_directory>
# When importing into unreal, remember to import normals
def main_blender(raw_args):
parser = argparse.ArgumentParser()
parser.add_argument('fbx')
parser.add_argument('outdir')
args = parser.parse_args(raw_args)
# In the future I want this to support processing a directory (all files from it)
# but for now they end up with altered names so that is why this does them only one per invocation
target = pathlib.Path(args.fbx)
if target.is_dir():
files = [path for path in target.iterdir() if path.suffix == '.fbx' and not path.stem.endswith('_fixed')]
else:
files = [target]
for filepath in files:
inpath = str(filepath)
file_name = "SKO" + filepath.stem.removeprefix("SK") + ".fbx"
outpath = str(os.path.join(args.outdir, file_name))
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
bpy.ops.import_scene.fbx(filepath=inpath, use_anim=False, ignore_leaf_bones=False, force_connect_children=True, automatic_bone_orientation=False, use_custom_normals=False)
bpy.ops.object.posemode_toggle()
bpy.ops.pose.transforms_clear()
bpy.ops.object.posemode_toggle()
bpy.context.active_object.rotation_euler = Vector([0,0,0])
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True, properties=True)
bpy.context.active_object.rotation_euler = Vector([math.radians(90), 0, 0])
# Add the weapon bone
add_bone("Hand_R", "Weapon_R")
add_bone("Hand_L", "Weapon_L")
bpy.ops.export_scene.fbx(filepath=outpath, add_leaf_bones=False, bake_anim=False, apply_unit_scale=True, mesh_smooth_type="EDGE")
def main():
try:
raw_args = sys.argv[sys.argv.index('--') + 1:]
except ValueError:
raw_args = []
main_blender(raw_args)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment