Create centralized method for identifying bones
- also fixes an issue where VRM bones would never be identified due to the names having "_" in them.
This commit is contained in:
@@ -18,6 +18,7 @@ from bpy.utils import register_class
|
|||||||
from ..core.logging_setup import logger
|
from ..core.logging_setup import logger
|
||||||
from ..core.translations import t
|
from ..core.translations import t
|
||||||
from ..core.dictionaries import bone_names
|
from ..core.dictionaries import bone_names
|
||||||
|
from .dictionaries import reverse_bone_lookup, bone_names
|
||||||
|
|
||||||
class ProgressTracker:
|
class ProgressTracker:
|
||||||
"""Universal progress tracking for Avatar Toolkit operations"""
|
"""Universal progress tracking for Avatar Toolkit operations"""
|
||||||
@@ -412,6 +413,19 @@ def simplify_bonename(name: str) -> str:
|
|||||||
"""Simplify bone name by removing spaces, underscores, dots and converting to lowercase"""
|
"""Simplify bone name by removing spaces, underscores, dots and converting to lowercase"""
|
||||||
return name.lower().translate(dict.fromkeys(map(ord, u" _.")))
|
return name.lower().translate(dict.fromkeys(map(ord, u" _.")))
|
||||||
|
|
||||||
|
|
||||||
|
def identify_bones(arm_data: bpy.types.Armature, context: bpy.types.Context) -> Dict[str,str]:
|
||||||
|
"""Identify bone names in an armature based on our reverse dictionary, so there is no confusion to what a bone is.
|
||||||
|
Essentially makes a dictionary of keys from dictionaries.bone_names like "hips", and the corosponding value is the bone that can be mapped to that key."""
|
||||||
|
returned: Dict[str,str] = {}
|
||||||
|
for bone in arm_data.bones:
|
||||||
|
|
||||||
|
simplified_name = simplify_bonename(bone.name)
|
||||||
|
|
||||||
|
if simplified_name in reverse_bone_lookup:
|
||||||
|
returned[reverse_bone_lookup[simplified_name]] = bone.name
|
||||||
|
return returned
|
||||||
|
|
||||||
def duplicate_bone_chain(bones: List[EditBone]) -> List[EditBone]:
|
def duplicate_bone_chain(bones: List[EditBone]) -> List[EditBone]:
|
||||||
"""Duplicate a chain of bones while preserving hierarchy"""
|
"""Duplicate a chain of bones while preserving hierarchy"""
|
||||||
new_bones: List[EditBone] = []
|
new_bones: List[EditBone] = []
|
||||||
|
|||||||
+28
-18
@@ -1,8 +1,8 @@
|
|||||||
# GPL Licence
|
# GPL Licence
|
||||||
|
|
||||||
|
|
||||||
# Bone names from https://github.com/triazo/immersive_scaler/
|
# 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...
|
# Note from @989onan: Please make sure to make your names are lowercase in this array, or it will never find a match. I banged my head metaphorically till I figured that out...
|
||||||
|
# Note2: Remove all "_", ".", and " " (space) from your values array or it will also not ever find a match!!!!
|
||||||
# Taken from Tuxedo/Cats
|
# Taken from Tuxedo/Cats
|
||||||
bone_names = {
|
bone_names = {
|
||||||
# Right side bones
|
# Right side bones
|
||||||
@@ -254,26 +254,26 @@ bone_names = {
|
|||||||
|
|
||||||
# Add VRM bone name variations
|
# Add VRM bone name variations
|
||||||
bone_names.update({
|
bone_names.update({
|
||||||
'hips': bone_names['hips'] + ['j_bip_c_hips', 'j_hips', 'vrm_hips'],
|
'hips': bone_names['hips'] + ['jbipchips', 'jhips', 'vrmhips'],
|
||||||
'spine': bone_names['spine'] + ['j_bip_c_spine', 'j_spine', 'vrm_spine'],
|
'spine': bone_names['spine'] + ['jbipcspine', 'jspine', 'vrmspine'],
|
||||||
'chest': bone_names['chest'] + ['j_bip_c_chest', 'j_chest', 'vrm_chest'],
|
'chest': bone_names['chest'] + ['jbipcchest', 'jchest', 'vrmchest'],
|
||||||
'upper_chest': bone_names['upper_chest'] + ['j_bip_c_upper_chest', 'j_upper_chest', 'vrm_upperchest'],
|
'upper_chest': bone_names['upperchest'] + ['jbipcupperchest', 'jupperchest', 'vrmupperchest'],
|
||||||
'neck': bone_names['neck'] + ['j_bip_c_neck', 'j_neck', 'vrm_neck'],
|
'neck': bone_names['neck'] + ['jbipcneck', 'jneck', 'vrmneck'],
|
||||||
'head': bone_names['head'] + ['j_bip_c_head', 'j_head', 'vrm_head'],
|
'head': bone_names['head'] + ['jbipchead', 'jhead', 'vrmhead'],
|
||||||
|
|
||||||
# VRM specific finger naming
|
# VRM specific finger naming
|
||||||
'thumb_0_l': bone_names['thumb_0_l'] + ['thumb_metacarpal_l', 'j_thumb1_l'],
|
'thumb_0_l': bone_names['thumb_0_l'] + ['thumbmetacarpall', 'jthumb1l'],
|
||||||
'index_0_l': bone_names['index_0_l'] + ['index_metacarpal_l', 'j_index1_l'],
|
'index_0_l': bone_names['index_0_l'] + ['indexmetacarpall', 'jindex1l'],
|
||||||
'middle_0_l': bone_names['middle_0_l'] + ['middle_metacarpal_l', 'j_middle1_l'],
|
'middle_0_l': bone_names['middle_0_l'] + ['middlemetacarpall', 'jmiddle1l'],
|
||||||
'ring_0_l': bone_names['ring_0_l'] + ['ring_metacarpal_l', 'j_ring1_l'],
|
'ring_0_l': bone_names['ring_0_l'] + ['ringmetacarpall', 'jring1l'],
|
||||||
'pinkie_0_l': bone_names['pinkie_0_l'] + ['little_metacarpal_l', 'j_little1_l'],
|
'pinkie_0_l': bone_names['pinkie_0_l'] + ['littlemetacarpall', 'jlittle1l'],
|
||||||
|
|
||||||
# Mirror for right side
|
# Mirror for right side
|
||||||
'thumb_0_r': bone_names['thumb_0_r'] + ['thumb_metacarpal_r', 'j_thumb1_r'],
|
'thumb_0_r': bone_names['thumb_0_r'] + ['thumbmetacarpalr', 'jthumb1r'],
|
||||||
'index_0_r': bone_names['index_0_r'] + ['index_metacarpal_r', 'j_index1_r'],
|
'index_0_r': bone_names['index_0_r'] + ['indexmetacarpalr', 'jindex1r'],
|
||||||
'middle_0_r': bone_names['middle_0_r'] + ['middle_metacarpal_r', 'j_middle1_r'],
|
'middle_0_r': bone_names['middle_0_r'] + ['middlemetacarpalr', 'jmiddle1r'],
|
||||||
'ring_0_r': bone_names['ring_0_r'] + ['ring_metacarpal_r', 'j_ring1_r'],
|
'ring_0_r': bone_names['ring_0_r'] + ['ringmetacarpalr', 'jring1r'],
|
||||||
'pinkie_0_r': bone_names['pinkie_0_r'] + ['little_metacarpal_r', 'j_little1_r']
|
'pinkie_0_r': bone_names['pinkie_0_r'] + ['littlemetacarpalr', 'jlittle1r']
|
||||||
})
|
})
|
||||||
|
|
||||||
# array taken from cats
|
# array taken from cats
|
||||||
@@ -354,3 +354,13 @@ resonite_translations = {
|
|||||||
'thumb_2_r': "thumb2.R",
|
'thumb_2_r': "thumb2.R",
|
||||||
'thumb_3_r': "thumb3.R"
|
'thumb_3_r': "thumb3.R"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Create reverse lookup dictionary (conversion/translation)
|
||||||
|
reverse_bone_lookup = {}
|
||||||
|
for preferred_name, name_list in bone_names.items():
|
||||||
|
for name in name_list:
|
||||||
|
reverse_bone_lookup[name] = preferred_name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+10
-18
@@ -3,14 +3,15 @@ import bpy
|
|||||||
import bpy_extras
|
import bpy_extras
|
||||||
from numpy import double
|
from numpy import double
|
||||||
from typing import Set, Dict
|
from typing import Set, Dict
|
||||||
|
import re
|
||||||
|
|
||||||
from .common import get_active_armature, simplify_bonename, validate_armature, ProgressTracker
|
from .common import get_active_armature, simplify_bonename, validate_armature, ProgressTracker, identify_bones
|
||||||
from bpy.types import Context, Operator
|
from bpy.types import Context, Operator
|
||||||
from ..core.translations import t
|
from ..core.translations import t
|
||||||
from ..core.dictionaries import bone_names, resonite_translations
|
from ..core.dictionaries import bone_names, resonite_translations
|
||||||
from ..core.logging_setup import logger
|
from ..core.logging_setup import logger
|
||||||
|
|
||||||
import re
|
|
||||||
from .resonite_loader import resonite_animx, resonite_types
|
from .resonite_loader import resonite_animx, resonite_types
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@@ -64,30 +65,21 @@ class AvatarToolkit_OT_ConvertResonite(Operator):
|
|||||||
untranslated_bones: Set[str] = set()
|
untranslated_bones: Set[str] = set()
|
||||||
simplified_names: Dict[str, str] = {}
|
simplified_names: Dict[str, str] = {}
|
||||||
|
|
||||||
# Create reverse lookup dictionary
|
|
||||||
reverse_bone_lookup = {}
|
|
||||||
for preferred_name, name_list in bone_names.items():
|
|
||||||
for name in name_list:
|
|
||||||
reverse_bone_lookup[name] = preferred_name
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
context.view_layer.objects.active = armature
|
context.view_layer.objects.active = armature
|
||||||
bpy.ops.object.mode_set(mode='EDIT')
|
bpy.ops.object.mode_set(mode='EDIT')
|
||||||
bpy.ops.object.mode_set(mode='OBJECT')
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
arm_data: bpy.types.Armature = armature.data
|
||||||
# Cache simplified bone names
|
# Cache simplified bone names
|
||||||
for bone in armature.data.bones:
|
for bone in arm_data.bones:
|
||||||
simplified_names[bone.name] = simplify_bonename(bone.name)
|
bone.name = re.compile(re.escape("<noik>"), re.IGNORECASE).sub("", bone.name)
|
||||||
|
|
||||||
total_bones = len(armature.data.bones)
|
total_bones = len(arm_data.bones)
|
||||||
with ProgressTracker(context, total_bones, t("Tools.convert_resonite.operation")) as progress:
|
with ProgressTracker(context, total_bones, t("Tools.convert_resonite.operation")) as progress:
|
||||||
for bone in armature.data.bones:
|
for key_simple,bone_name in identify_bones(arm_data,context).items():
|
||||||
# Remove any existing "<noik>" tags
|
|
||||||
bone.name = re.compile(re.escape("<noik>"), re.IGNORECASE).sub("", bone.name)
|
|
||||||
simplified_name = simplified_names[bone.name]
|
|
||||||
|
|
||||||
if simplified_name in reverse_bone_lookup and reverse_bone_lookup[simplified_name] in resonite_translations:
|
if key_simple in resonite_translations:
|
||||||
new_name = resonite_translations[reverse_bone_lookup[simplified_name]]
|
new_name = resonite_translations[key_simple]
|
||||||
logger.debug(f"Translating bone: {bone.name} -> {new_name}")
|
logger.debug(f"Translating bone: {bone.name} -> {new_name}")
|
||||||
bone.name = new_name
|
bone.name = new_name
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user