Added Resonite Tools

- Added Resonite translation with automatic <NOIK> marking. If this doesn't work, please improve the dictionary, or hook it along with others into a better translation layer to deal with identifying body parts
- Added Resonite export, which simply exports the model with the proper settings as a GLB/GLTF for more graceful importing and editing within the game.
This commit is contained in:
989onan
2024-07-04 16:38:31 -04:00
parent bbd0d0bd9f
commit 4808d288e2
7 changed files with 315 additions and 12 deletions
+18
View File
@@ -1,6 +1,8 @@
import bpy
import numpy as np
from .dictionaries import bone_names
from typing import List, Optional
from bpy.types import Object, ShapeKey, Mesh, Context
from functools import lru_cache
@@ -39,3 +41,19 @@ def has_shapekeys(mesh_obj: Object) -> bool:
@lru_cache(maxsize=None)
def _get_shape_key_co(shape_key: ShapeKey) -> np.ndarray:
return np.array([v.co for v in shape_key.data])
def simplify_bonename(n):
return n.lower().translate(dict.fromkeys(map(ord, u" _.")))
def get_armature(context, armature_name=None) -> Optional[Object]:
if armature_name:
obj = bpy.data.objects[armature_name]
if obj.type == "ARMATURE":
return obj
else:
return None
if context.view_layer.objects.active:
obj = context.view_layer.objects.active
if obj.type == "ARMATURE":
return obj
return next((obj for obj in context.view_layer.objects if obj.type == 'ARMATURE'), None)
+112
View File
@@ -0,0 +1,112 @@
# GPL Licence
# Bone names from https://github.com/triazo/immersive_scaler/
# Note from @989onan: Please make sure to make your names are lowercase in this array. I banged my head metaphorically till I figured that out...
# Taken from Tuxedo/Cats
bone_names = {
"right_shoulder": ["rightshoulder", "shoulderr", "rshoulder"],
"right_arm": ["rightarm", "armr", "rarm", "upperarmr", "rupperarm", "rightupperarm", "upperarmright", "uparmr", "ruparm"],
"right_elbow": ["rightelbow", "elbowr", "relbow", "lowerarmr", "rightlowerarm", "lowerarmr","rlowerarm", "lowerarmright", "lowarmr", "rlowarm", "forearmr","rforearm"],
"right_wrist": ["rightwrist", "wristr", "rwrist", "handr", "righthand", "rhand"],
#hand l fingers
"pinkie_0_r": ["littlefinger0r","pinkie0r","rpinkie0","pinkiemetacarpalr"],
"pinkie_1_r": ["littlefinger1r","pinkie1r","rpinkie1","pinkieproximalr"],
"pinkie_2_r": ["littlefinger2r","pinkie2r","rpinkie2","pinkieintermediater"],
"pinkie_3_r": ["littlefinger3r","pinkie3r","rpinkie3","pinkiedistalr"],
"ring_0_r": ["ringfinger0r","ring0r","rring0","ringmetacarpalr"],
"ring_1_r": ["ringfinger1r","ring1r","rring1","ringproximalr"],
"ring_2_r": ["ringfinger2r","ring2r","rring2","ringintermediater"],
"ring_3_r": ["ringfinger3r","ring3r","rring3","ringdistalr"],
"middle_0_r": ["middlefinger0r","middle0r","rmiddle0","middlemetacarpalr"],
"middle_1_r": ["middlefinger1r","middle1r","rmiddle1","middleproximalr"],
"middle_2_r": ["middlefinger2r","middle2r","rmiddle2","middleintermediater"],
"middle_3_r": ["middlefinger3r","middle3r","rmiddle3","middledistalr"],
"index_0_r": ["indexfinger0r","index0r","rindex0","indexmetacarpalr"],
"index_1_r": ["indexfinger1r","index1r","rindex1","indexproximalr"],
"index_2_r": ["indexfinger2r","index2r","rindex2","indexintermediater"],
"index_3_r": ["indexfinger3r","index3r","rindex3","indexdistalr"],
"thumb_0_r": ["thumb0r","rthumb0","thumbmetacarpalr"],
"thumb_1_r": ['thumb1r',"rthumb1","thumbproximalr"],
"thumb_2_r": ['thumb2r',"rthumb2","thumbintermediater"],
"thumb_3_r": ['thumb3r',"rthumb3","thumbdistalr"],
"right_leg": ["rightleg", "legr", "rleg", "upperlegr", "rupperleg", "thighr", "rightupperleg", "upperlegright", "uplegr", "rupleg"],
"right_knee": ["rightknee", "kneer", "rknee", "lowerlegr", "calfr", "rlowerleg", "rcalf", "rightlowerleg", "lowerlegright", "lowlegr", "rlowleg"],
"right_ankle": ["rightankle", "ankler", "rankle", "footright", "footr", "rfoot", "rightfoot", "rightfeet", "feetright", "rfeet", "feetr"],
"right_toe": ["righttoe", "toeright", "toer", "rtoe", "toesr", "rtoes"],
"left_shoulder": ["leftshoulder", "shoulderl", "lshoulder"],
"left_arm": ["leftarm", "arml", "rarm", "upperarml", "lupperarm", "leftupperarm", "upperarmleft", "uparml", "luparm"],
"left_elbow": ["leftelbow", "elbowl", "lelbow", "lowerarml", "leftlowerarm", "lowerarmleft", "lowerarml", "llowerarm", "lowarml", "llowarm", "forearml","lforearm"],
"left_wrist": ["leftwrist", "wristl", "lwrist", "handl", "lefthand", "lhand"],
#hand l fingers
"pinkie_0_l": ["pinkiefinger0l","pinkie0l","lpinkie0","pinkiemetacarpall"],
"pinkie_1_l": ["littlefinger1l","pinkie1l","lpinkie1","pinkieproximall"],
"pinkie_2_l": ["littlefinger2l","pinkie2l","lpinkie2","pinkieintermediatel"],
"pinkie_3_l": ["littlefinger3l","pinkie3l","lpinkie3","pinkiedistall"],
"ring_0_l": ["ringfinger0l","ring0l","lring0","ringmetacarpall"],
"ring_1_l": ["ringfinger1l","ring1l","lring1","ringproximall"],
"ring_2_l": ["ringfinger2l","ring2l","lring2","ringintermediatel"],
"ring_3_l": ["ringfinger3l","ring3l","lring3","ringdistall"],
"middle_0_l": ["middlefinger0l","middle_0l","lmiddle0","middlemetacarpall"],
"middle_1_l": ["middlefinger1l","middle_1l","lmiddle1","middleproximall"],
"middle_2_l": ["middlefinger2l","middle_2l","lmiddle2","middleintermediatel"],
"middle_3_l": ["middlefinger3l","middle_3l","lmiddle3","middledistall"],
"index_0_l": ["indexfinger0l","index0l","lindex0","indexmetacarpall"],
"index_1_l": ["indexfinger1l","index1l","lindex1","indexproximall"],
"index_2_l": ["indexfinger2l","index2l","lindex2","indexintermediatel"],
"index_3_l": ["indexfinger3l","index3l","lindex3","indexdistall"],
"thumb_0_l": ["thumb0l","lthumb0","thumbmetacarpall"],
"thumb_1_l": ['thumb1l',"lthumb1","thumbproximall"],
"thumb_2_l": ['thumb2l',"lthumb2","thumbintermediatel"],
"thumb_3_l": ['thumb3l',"lthumb3","thumbdistall"],
"left_leg": ["leftleg", "legl", "lleg", "upperlegl", "lupperleg", "thighl", "leftupperleg", "upperlegleft", "uplegl", "lupleg"],
"left_knee": ["leftknee", "kneel", "lknee", "lowerlegl", "llowerleg", "calfl", "lcalf", "leftlowerleg", "lowerlegleft", 'lowlegl', 'llowleg'],
"left_ankle": ["leftankle", "anklel", "rankle", "footleft", "footl", "lfoot", "leftfoot", "leftfeet", "feetleft", "lfeet", "feetl"],
"left_toe": ["lefttoe", "toeleft", "toel", "ltoe", "toesl", "ltoes"],
"hips": ["pelvis", "hips", "hip"],
"spine": ["torso", "spine"],
"chest": ["chest"],
"upper_chest": ["upperchest", "chestupper"],
"neck": ["neck"],
"head": ["head", "cabeza"],
"left_eye": ["eyeleft", "lefteye", "eyel", "leye"],
"right_eye": ["eyeright", "righteye", "eyer", "reye"],
}
# array taken from cats
dont_delete_these_main_bones = [
'Hips', 'Spine', 'Chest', 'Upper Chest', 'Neck', 'Head',
'Left leg', 'Left knee', 'Left ankle', 'Left toe',
'Right leg', 'Right knee', 'Right ankle', 'Right toe',
'Left shoulder', 'Left arm', 'Left elbow', 'Left wrist',
'Right shoulder', 'Right arm', 'Right elbow', 'Right wrist',
'LeftEye', 'RightEye', 'Eye_L', 'Eye_R',
'Left leg 2', 'Right leg 2',
'Thumb0_L', 'Thumb1_L', 'Thumb2_L',
'IndexFinger1_L', 'IndexFinger2_L', 'IndexFinger3_L',
'MiddleFinger1_L', 'MiddleFinger2_L', 'MiddleFinger3_L',
'RingFinger1_L', 'RingFinger2_L', 'RingFinger3_L',
'LittleFinger1_L', 'LittleFinger2_L', 'LittleFinger3_L',
'Thumb0_R', 'Thumb1_R', 'Thumb2_R',
'IndexFinger1_R', 'IndexFinger2_R', 'IndexFinger3_R',
'MiddleFinger1_R', 'MiddleFinger2_R', 'MiddleFinger3_R',
'RingFinger1_R', 'RingFinger2_R', 'RingFinger3_R',
'LittleFinger1_R', 'LittleFinger2_R', 'LittleFinger3_R',
]
+35
View File
@@ -0,0 +1,35 @@
import bpy
from typing import List, Optional
from .common import get_armature
from bpy.types import Object, ShapeKey, Mesh, Context, Operator
from functools import lru_cache
from ..core.register import register_wrap
@register_wrap
class ExportResonite(Operator):
bl_idname = 'avatar_toolkit.export_resonite'
bl_label = "Export to Resonite"
bl_description = "Export a GLB with all animations and materials. For animation data see: "
bl_options = {'REGISTER', 'UNDO'}
filepath: bpy.props.StringProperty()
@classmethod
def poll(cls, context: Context):
if get_armature(context) is None:
return False
return True
def execute(self, context: Context):
#settings stolen from cats.
bpy.ops.export_scene.gltf('INVOKE_AREA',
export_image_format = 'WEBP',
export_image_quality = 75,
export_materials = 'EXPORT',
export_animations = True,
export_animation_mode = 'ACTIONS',
export_nla_strips_merged_animation_name = 'Animation',
export_nla_strips = True)
return {'FINISHED'}