112 lines
3.8 KiB
Python
112 lines
3.8 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# Credits:
|
|
# Thanks to https://github.com/ShyWolf42/Copy-to-MMD-Visemes
|
|
# Thanks to https://github.com/teamneoneko/Cats-Blender-Plugin
|
|
|
|
|
|
bl_info = {
|
|
"name": "Visemes Converter Tool",
|
|
"author": "Custom",
|
|
"version": (2, 0, 0),
|
|
"blender": (3, 0, 0),
|
|
"location": "View3D > Sidebar > Visemes Tool",
|
|
"description": (
|
|
"Generates VRChat visemes (vrc.v_* + vrc.blink) from MMD blendshapes, "
|
|
"and converts blendshapes from English/VRChat to Japanese MMD format"
|
|
),
|
|
"category": "Rigging",
|
|
}
|
|
|
|
import bpy
|
|
from operators import (
|
|
VRCVIS_OT_AutoDetect,
|
|
VRCVIS_OT_Preview,
|
|
VRCVIS_OT_UpdatePreview,
|
|
VRCVIS_OT_Generate,
|
|
VRCVIS_OT_RemoveAll,
|
|
VRCVIS_OT_Reorder,
|
|
VRCVIS_OT_MMDAutoDetect,
|
|
VRCVIS_OT_MMDConvert,
|
|
VRCVIS_OT_MMDRemove,
|
|
)
|
|
from panels import VRCVIS_PT_Panel, viseme_enum_items
|
|
from utilities.functions import MMD_JP_MAPPING
|
|
from utilities.helpers import _ps, _restore_shapekey_values
|
|
|
|
_CLASSES = [
|
|
VRCVIS_OT_AutoDetect,
|
|
VRCVIS_OT_Preview,
|
|
VRCVIS_OT_UpdatePreview,
|
|
VRCVIS_OT_Generate,
|
|
VRCVIS_OT_RemoveAll,
|
|
VRCVIS_OT_Reorder,
|
|
VRCVIS_OT_MMDAutoDetect,
|
|
VRCVIS_OT_MMDConvert,
|
|
VRCVIS_OT_MMDRemove,
|
|
VRCVIS_PT_Panel,
|
|
]
|
|
|
|
_MMD_PROPS = [f'vrcvis_mmd_{suffix}' for _, suffix, _en, _ in MMD_JP_MAPPING]
|
|
|
|
|
|
def register():
|
|
for cls in _CLASSES:
|
|
bpy.utils.register_class(cls)
|
|
|
|
bpy.types.Scene.vrcvis_mesh = bpy.props.StringProperty(
|
|
name='Mesh', description='Mesh su cui operare', default='')
|
|
bpy.types.Scene.vrcvis_mouth_a = bpy.props.StringProperty(
|
|
name='Mouth A', description='Shape key bocca aperta (あ / A)', default='')
|
|
bpy.types.Scene.vrcvis_mouth_o = bpy.props.StringProperty(
|
|
name='Mouth O', description='Shape key bocca rotonda (お / O)', default='')
|
|
bpy.types.Scene.vrcvis_mouth_ch = bpy.props.StringProperty(
|
|
name='Mouth CH', description='Shape key bocca stretta (い / CH)', default='')
|
|
bpy.types.Scene.vrcvis_blink = bpy.props.StringProperty(
|
|
name='Blink', description='Shape key occhi chiusi (まばたき / Blink)', default='')
|
|
bpy.types.Scene.vrcvis_intensity = bpy.props.FloatProperty(
|
|
name='Intensità', description='Moltiplicatore globale dei pesi',
|
|
default=1.0, min=0.0, max=2.0, step=1)
|
|
bpy.types.Scene.vrcvis_overwrite = bpy.props.BoolProperty(
|
|
name='Sovrascrivi esistenti',
|
|
description='Rigenera le shape key già presenti',
|
|
default=True)
|
|
bpy.types.Scene.vrcvis_preview_active = bpy.props.BoolProperty(
|
|
name='Preview attiva', default=False)
|
|
bpy.types.Scene.vrcvis_preview_viseme = bpy.props.EnumProperty(
|
|
name='Viseme', description='Viseme da mostrare in anteprima',
|
|
items=viseme_enum_items)
|
|
|
|
for jp_name, suffix, _en, _ in MMD_JP_MAPPING:
|
|
setattr(bpy.types.Scene, f'vrcvis_mmd_{suffix}',
|
|
bpy.props.StringProperty(
|
|
name=jp_name,
|
|
description=f'Shape key sorgente per {jp_name}',
|
|
default=''))
|
|
|
|
|
|
def unregister():
|
|
scene = bpy.context.scene if bpy.context else None
|
|
if _ps.active and scene:
|
|
mesh_name = scene.get('vrcvis_mesh', '')
|
|
if mesh_name and mesh_name in bpy.data.objects:
|
|
_restore_shapekey_values(bpy.data.objects[mesh_name])
|
|
_ps.active = False
|
|
|
|
for cls in reversed(_CLASSES):
|
|
bpy.utils.unregister_class(cls)
|
|
|
|
for prop in (
|
|
'vrcvis_mesh', 'vrcvis_mouth_a', 'vrcvis_mouth_o', 'vrcvis_mouth_ch',
|
|
'vrcvis_blink', 'vrcvis_intensity', 'vrcvis_overwrite',
|
|
'vrcvis_preview_active', 'vrcvis_preview_viseme',
|
|
*_MMD_PROPS,
|
|
):
|
|
if hasattr(bpy.types.Scene, prop):
|
|
delattr(bpy.types.Scene, prop)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
register()
|