CM3D2 Converter.misc_DATA_PT_context_arm

   1# 「プロパティ」エリア → 「アーマチュアデータ」タブ
   2import re
   3import struct
   4import math
   5import unicodedata
   6import time
   7import bpy
   8import bmesh
   9import mathutils
  10import os
  11from . import common
  12from . import compat
  13from .translations.pgettext_functions import *
  14
  15
  16# メニュー等に項目追加
  17def menu_func(self, context):
  18    import re
  19    ob = context.active_object
  20    if not ob or ob.type != 'ARMATURE':
  21        return
  22
  23    arm = ob.data
  24    is_boxed = False
  25
  26    bone_data_count = 0
  27    if 'BoneData:0' in arm and 'LocalBoneData:0' in arm:
  28        for key in arm.keys():
  29            if re.search(r'^(Local)?BoneData:\d+$', key):
  30                bone_data_count += 1
  31    enabled_clipboard = False
  32    clipboard = context.window_manager.clipboard
  33    if 'BoneData:' in clipboard and 'LocalBoneData:' in clipboard:
  34        enabled_clipboard = True
  35    if bone_data_count or enabled_clipboard:
  36        if not is_boxed:
  37            box = self.layout.box()
  38            box.label(text="CM3D2用", icon_value=common.kiss_icon())
  39            is_boxed = True
  40
  41        col = box.column(align=True)
  42        row = col.row(align=True)
  43        row.label(text="ボーン情報", icon='CONSTRAINT_BONE')
  44        sub_row = row.row()
  45        sub_row.alignment = 'RIGHT'
  46        if bone_data_count:
  47            sub_row.label(text=str(bone_data_count), icon='CHECKBOX_HLT')
  48        else:
  49            sub_row.label(text="0", icon='CHECKBOX_DEHLT')
  50        row = col.row(align=True)
  51        row.operator('object.copy_armature_bone_data_property', icon='COPYDOWN', text="コピー")
  52        row.operator('object.paste_armature_bone_data_property', icon='PASTEDOWN', text="貼付け")
  53        row.operator('object.remove_armature_bone_data_property', icon='X', text="")
  54
  55    flag = False
  56    for bone in arm.bones:
  57        if not flag and re.search(r'[_ ]([rRlL])[_ ]', bone.name):
  58            flag = True
  59        if not flag and bone.name.count('*') == 1:
  60            if re.search(r'\.([rRlL])$', bone.name):
  61                flag = True
  62        if flag:
  63            if not is_boxed:
  64                box = self.layout.box()
  65                box.label(text="CM3D2用", icon_value=common.kiss_icon())
  66                is_boxed = True
  67
  68            col = box.column(align=True)
  69            col.label(text="ボーン名変換", icon='SORTALPHA')
  70            row = col.row(align=True)
  71            row.operator('armature.decode_cm3d2_bone_names', text="CM3D2 → Blender", icon='BLENDER')
  72            row.operator('armature.encode_cm3d2_bone_names', text="Blender → CM3D2", icon_value=common.kiss_icon())
  73            break
  74        
  75    if bone_data_count:
  76        col = box.column(align=True)
  77        col.label(text="Armature Operators", icon=compat.icon('OUTLINER_OB_ARMATURE'))
  78        col.operator("object.add_cm3d2_twist_bones", text="Connect Twist Bones", icon=compat.icon('CONSTRAINT_BONE'))
  79        col.operator("object.cleanup_scale_bones"  , text="Cleanup Scale Bones", icon=compat.icon('X'              ))
  80        
  81    if 'is T Stance' in arm:
  82        if not is_boxed:
  83            box = self.layout.box()
  84            box.label(text="CM3D2用", icon_value=common.kiss_icon())
  85            is_boxed = True
  86
  87        col = box.column(align=True)
  88        if arm['is T Stance']:
  89            pose_text = "Armature State: Primed"
  90        else:
  91            pose_text = "Armature State: Normal"
  92        col.label(text=pose_text, icon='POSE_HLT')
  93        col.enabled = bpy.ops.poselib.apply_pose.poll()
  94
  95        row = col.row(align=True)
  96        
  97        sub_row = row.row(align=True)
  98        op = sub_row.operator('poselib.apply_pose', icon='ARMATURE_DATA', text="Original")#, depress=(context.scene.frame_current % 2 == arm['is T Stance']))
  99        op.pose_index = arm['is T Stance']
 100        #if context.scene.frame_current % 2 == op.value:
 101        #    sub_row.enabled = False
 102        
 103        sub_row = row.row(align=True)
 104        op = sub_row.operator('poselib.apply_pose', icon=compat.icon('OUTLINER_DATA_ARMATURE'), text="Pose data")#, depress=(context.scene.frame_current % 2 != arm['is T Stance']))
 105        op.pose_index = not arm['is T Stance']
 106        #if context.scene.frame_current % 2 == op.value:
 107        #    sub_row.enabled = False
 108        
 109        row = col.row(align=True)
 110        
 111        sub_row = row.row(align=True)
 112        sub_row.operator_context = 'EXEC_DEFAULT'
 113        op = sub_row.operator('pose.apply_prime_field', icon=compat.icon('FILE_REFRESH'), text="Swap Prime Field")
 114        op.is_swap_prime_field = True
 115
 116
 117@compat.BlRegister()
 118class CNV_OT_decode_cm3d2_bone_names(bpy.types.Operator):
 119    bl_idname = 'armature.decode_cm3d2_bone_names'
 120    bl_label = "ボーン名をCM3D2用→Blender用に変換"
 121    bl_description = "CM3D2で使われてるボーン名をBlenderで左右対称編集できるように変換します"
 122    bl_options = {'REGISTER', 'UNDO'}
 123
 124    @classmethod
 125    def poll(cls, context):
 126        import re
 127        ob = context.active_object
 128        if ob:
 129            if ob.type == 'ARMATURE':
 130                arm = ob.data
 131                for bone in arm.bones:
 132                    if re.search(r'[_ ]([rRlL])[_ ]', bone.name):
 133                        return True
 134        return False
 135
 136    def execute(self, context):
 137        ob = context.active_object
 138        arm = ob.data
 139        convert_count = 0
 140        for bone in arm.bones:
 141            bone_name = common.decode_bone_name(bone.name)
 142            if bone_name != bone.name:
 143                bone.name = bone_name
 144                convert_count += 1
 145        if convert_count == 0:
 146            self.report(type={'WARNING'}, message="変換できる名前が見つかりませんでした")
 147        else:
 148            self.report(type={'INFO'}, message="ボーン名をBlender用に変換しました")
 149        return {'FINISHED'}
 150
 151
 152@compat.BlRegister()
 153class CNV_OT_encode_cm3d2_bone_names(bpy.types.Operator):
 154    bl_idname = 'armature.encode_cm3d2_bone_names'
 155    bl_label = "ボーン名をBlender用→CM3D2用に変換"
 156    bl_description = "CM3D2で使われてるボーン名に元に戻します"
 157    bl_options = {'REGISTER', 'UNDO'}
 158
 159    @classmethod
 160    def poll(cls, context):
 161        import re
 162        ob = context.active_object
 163        if ob:
 164            if ob.type == 'ARMATURE':
 165                arm = ob.data
 166                for bone in arm.bones:
 167                    if bone.name.count('*') == 1 and re.search(r'\.([rRlL])$', bone.name):
 168                        return True
 169        return False
 170
 171    def execute(self, context):
 172        ob = context.active_object
 173        arm = ob.data
 174        convert_count = 0
 175        for bone in arm.bones:
 176            bone_name = common.encode_bone_name(bone.name)
 177            if bone_name != bone.name:
 178                bone.name = bone_name
 179                convert_count += 1
 180        if convert_count == 0:
 181            self.report(type={'WARNING'}, message="変換できる名前が見つかりませんでした")
 182        else:
 183            self.report(type={'INFO'}, message="ボーン名をCM3D2用に戻しました")
 184        return {'FINISHED'}
 185
 186
 187@compat.BlRegister()
 188class CNV_OT_copy_armature_bone_data_property(bpy.types.Operator):
 189    bl_idname = 'object.copy_armature_bone_data_property'
 190    bl_label = "ボーン情報をコピー"
 191    bl_description = "カスタムプロパティのボーン情報をクリップボードにコピーします"
 192    bl_options = {'REGISTER', 'UNDO'}
 193
 194    @classmethod
 195    def poll(cls, context):
 196        ob = context.active_object
 197        if ob:
 198            if ob.type == 'ARMATURE':
 199                arm = ob.data
 200                if 'BoneData:0' in arm and 'LocalBoneData:0' in arm:
 201                    return True
 202        return False
 203
 204    def execute(self, context):
 205        output_text = ""
 206        ob = context.active_object.data
 207        pass_count = 0
 208        if 'BaseBone' in ob:
 209            output_text += "BaseBone:" + ob['BaseBone'] + "\n"
 210        for i in range(99999):
 211            name = "BoneData:" + str(i)
 212            if name in ob:
 213                output_text += "BoneData:" + ob[name] + "\n"
 214            else:
 215                pass_count += 1
 216            if 10 < pass_count:
 217                break
 218        pass_count = 0
 219        for i in range(99999):
 220            name = "LocalBoneData:" + str(i)
 221            if name in ob:
 222                output_text += "LocalBoneData:" + ob[name] + "\n"
 223            else:
 224                pass_count += 1
 225            if 10 < pass_count:
 226                break
 227        context.window_manager.clipboard = output_text
 228        self.report(type={'INFO'}, message="ボーン情報をクリップボードにコピーしました")
 229        return {'FINISHED'}
 230
 231
 232@compat.BlRegister()
 233class CNV_OT_paste_armature_bone_data_property(bpy.types.Operator):
 234    bl_idname = 'object.paste_armature_bone_data_property'
 235    bl_label = "ボーン情報を貼付け"
 236    bl_description = "カスタムプロパティのボーン情報をクリップボードから貼付けます"
 237    bl_options = {'REGISTER', 'UNDO'}
 238
 239    @classmethod
 240    def poll(cls, context):
 241        ob = context.active_object
 242        if ob:
 243            if ob.type == 'ARMATURE':
 244                clipboard = context.window_manager.clipboard
 245                if 'BoneData:' in clipboard and 'LocalBoneData:' in clipboard:
 246                    return True
 247        return False
 248
 249    def execute(self, context):
 250        ob = context.active_object.data
 251        pass_count = 0
 252        for i in range(99999):
 253            name = "BoneData:" + str(i)
 254            if name in ob:
 255                del ob[name]
 256            else:
 257                pass_count += 1
 258            if 10 < pass_count:
 259                break
 260        pass_count = 0
 261        for i in range(99999):
 262            name = "LocalBoneData:" + str(i)
 263            if name in ob:
 264                del ob[name]
 265            else:
 266                pass_count += 1
 267            if 10 < pass_count:
 268                break
 269        bone_data_count = 0
 270        local_bone_data_count = 0
 271        for line in context.window_manager.clipboard.split("\n"):
 272            if line.startswith('BaseBone:'):
 273                ob['BaseBone'] = line[9:]  # len('BaseData:') == 9
 274                continue
 275
 276            if line.startswith('BoneData:'):
 277                if line.count(',') >= 4:
 278                    name = "BoneData:" + str(bone_data_count)
 279                    ob[name] = line[9:]  # len('BoneData:') == 9
 280                    bone_data_count += 1
 281                continue
 282
 283            if line.startswith('LocalBoneData:'):
 284                if line.count(',') == 1:
 285                    name = "LocalBoneData:" + str(local_bone_data_count)
 286                    ob[name] = line[14:]  # len('LocalBoneData:') == 14
 287                    local_bone_data_count += 1
 288
 289        self.report(type={'INFO'}, message="ボーン情報をクリップボードから貼付けました")
 290        return {'FINISHED'}
 291
 292
 293@compat.BlRegister()
 294class CNV_OT_remove_armature_bone_data_property(bpy.types.Operator):
 295    bl_idname = 'object.remove_armature_bone_data_property'
 296    bl_label = "ボーン情報を削除"
 297    bl_description = "カスタムプロパティのボーン情報を全て削除します"
 298    bl_options = {'REGISTER', 'UNDO'}
 299
 300    @classmethod
 301    def poll(cls, context):
 302        ob = context.active_object
 303        if ob:
 304            if ob.type == 'ARMATURE':
 305                arm = ob.data
 306                if 'BoneData:0' in arm and 'LocalBoneData:0' in arm:
 307                    return True
 308        return False
 309
 310    def invoke(self, context, event):
 311        return context.window_manager.invoke_props_dialog(self)
 312
 313    def draw(self, context):
 314        self.layout.label(text="カスタムプロパティのボーン情報を全て削除します", icon='CANCEL')
 315
 316    def execute(self, context):
 317        ob = context.active_object.data
 318        pass_count = 0
 319        if 'BaseBone' in ob:
 320            del ob['BaseBone']
 321        for i in range(99999):
 322            name = "BoneData:" + str(i)
 323            if name in ob:
 324                del ob[name]
 325            else:
 326                pass_count += 1
 327            if 10 < pass_count:
 328                break
 329        pass_count = 0
 330        for i in range(99999):
 331            name = "LocalBoneData:" + str(i)
 332            if name in ob:
 333                del ob[name]
 334            else:
 335                pass_count += 1
 336            if 10 < pass_count:
 337                break
 338        self.report(type={'INFO'}, message="ボーン情報を削除しました")
 339        return {'FINISHED'}
 340
 341
 342
 343
 344
 345
 346"""
 347- - - - - - For Twist Bones - - - - - - 
 348"""
 349@compat.BlRegister()
 350class CNV_OT_add_cm3d2_twist_bones(bpy.types.Operator):
 351    bl_idname      = 'object.add_cm3d2_twist_bones'
 352    bl_label       = "Add CM3D2 Twist Bones"
 353    bl_description = "Adds drivers to armature to automatically set twist-bone positions."
 354    bl_options     = {'REGISTER', 'UNDO'}
 355
 356    scale = bpy.props.FloatProperty(name="Scale", default=5, min=0.1, max=100, soft_min=0.1, soft_max=100, step=100, precision=1, description="The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.")
 357
 358    #is_fix_thigh        = bpy.props.BoolProperty(name="Fix Thigh"       , default=False, description="Fix twist bone values for the thighs in motor-cycle pose")
 359    #is_drive_shape_keys = bpy.props.BoolProperty(name="Drive Shape Keys", default=True, description="Connect sliders to mesh children's shape keys"           )
 360    
 361    fDegPer  = 1.1
 362    fDegPer1 = 0.2 
 363    fRota    = 0.5 
 364                                            
 365    @classmethod
 366    def poll(cls, context):
 367        ob = context.object
 368        if ob:
 369            arm = ob.data
 370        else:
 371            arm = None
 372        has_arm  = arm and isinstance(arm, bpy.types.Armature) and ("Bip01" in arm.bones)
 373        can_edit = (ob and ob.data == arm) or (arm and arm.is_editmode)
 374        return has_arm and can_edit
 375
 376    def invoke(self, context, event):
 377        self.scale = common.preferences().scale
 378        return context.window_manager.invoke_props_dialog(self)
 379
 380    def draw(self, context):
 381        self.layout.prop(self, 'scale'              )
 382        #self.layout.prop(self, 'is_fix_thigh'       )
 383        #self.layout.prop(self, 'is_drive_shape_keys')
 384
 385    def getPoseBone(self, ob, boneName, flip=False):
 386        side = "R" if flip else "L"
 387        
 388        poseBoneList = ob.pose.bones
 389        poseBone = poseBoneList.get(boneName.replace("?",side)) or poseBoneList.get(boneName.replace("?","*")+"."+side)
 390        
 391        if not poseBone:
 392            print("WARNING: Could not find bone \""+boneName+"\"")
 393            return
 394
 395        return poseBone
 396
 397    def driveShapeKey(self, shapekey, data, prop, expression, set_min=None, set_max=None):
 398        if not shapekey:
 399            return
 400        driver = shapekey.driver_add('value').driver
 401        driver.type = 'SCRIPTED'
 402
 403        driver_var = driver.variables.new() if len(driver.variables) < 1 else driver.variables[0]
 404        driver_var.type = 'SINGLE_PROP'
 405        driver_var.name = prop
 406
 407        driver_target = driver_var.targets[0]
 408        driver_target.id_type = 'OBJECT'
 409        driver_target.id = data.id_data
 410        driver_target.data_path = data.path_from_id(prop)
 411
 412        driver.expression = expression
 413
 414        if set_min:
 415            shapekey.slider_min = set_min
 416        if set_max:
 417            shapekey.slider_max = set_max
 418
 419    def driveTwistBone(self, ob, boneName, flip=False, prop='rotation_euler', axes=(1,2,0), expression=("", "", ""), infulencers=()):
 420        bone = self.getPoseBone(ob, boneName, flip=flip)
 421        if not bone:
 422            return
 423        if 'euler' in prop:
 424            bone.rotation_mode = 'XYZ'
 425
 426        args = []
 427        for name in infulencers:
 428            if type(infulencers) == str:
 429                name = infulencers
 430            arg_bone = self.getPoseBone(ob, name, flip=flip)
 431            if arg_bone:
 432                args.append(arg_bone.name)
 433            else:
 434                args.append(name)
 435            if type(infulencers) == str:
 436                break
 437
 438        for i, index in enumerate(axes):
 439            driver = bone.driver_add(prop, index).driver
 440            driver.type = 'SCRIPTED'
 441            driver.use_self = True
 442            if type(expression) == str:
 443                expr = expression
 444            else:
 445                expr = expression[i]
 446            driver.expression = expr.format(*args, axis=['x','y','z'][index], index=index, i=i)
 447
 448    def constrainTwistBone(self, ob, boneName, targetName="", flip='BOTH', type='COPY_ROTATION', space=None, map=None, **kwargs):
 449        if flip == 'BOTH':
 450            const_l = self.constrainTwistBone(ob, boneName, targetName, flip=False, type=type, space=space, map=map, **kwargs)
 451            const_r = self.constrainTwistBone(ob, boneName, targetName, flip=True , type=type, space=space, map=map, **kwargs)
 452            return const_l, const_r
 453
 454        bone   = self.getPoseBone(ob, boneName  , flip=flip)
 455        target = self.getPoseBone(ob, targetName, flip=flip)
 456        if not bone or (not target and targetName):
 457            return None
 458
 459        const = bone.constraints.new(type)
 460        if target:
 461            const.target = ob
 462            const.subtarget = target.name
 463        if space:
 464            const.target_space = space
 465            const.owner_space  = space
 466        if map:
 467            const.map_from = map
 468            const.map_to   = map
 469        for key, val in kwargs.items():
 470            try:
 471                setattr(const, key, val)
 472            except Exception as e:
 473                # TODO : Properly handle drivers in legacy version
 474                self.report(type={'ERROR'}, message=e.args[0])
 475
 476        return const
 477
 478    def execute(self, context):
 479        ob = context.object
 480        arm = ob.data
 481        pre_mode = ob.mode
 482        if pre_mode != 'POSE':
 483            bpy.ops.object.mode_set(mode='POSE')
 484
 485        # TODO : Fix shoulder constraints
 486        # AutoTwist() ... Shoulder : 'TBody.cs' line 2775
 487        self.constrainTwistBone(ob, 'Uppertwist_?', 'Bip01 ? UpperArm',
 488            type  = 'TRANSFORM'                 ,
 489            space = 'LOCAL'                     ,
 490            map   = 'ROTATION'                  ,
 491            use_motion_extrapolate = True       ,
 492            from_rotation_mode = 'SWING_TWIST_Y',
 493            mix_mode_rot       = 'REPLACE'      ,
 494            from_max_y_rot =  1                 ,
 495            to_max_y_rot   = -self.fDegPer
 496        )
 497        self.constrainTwistBone(ob, 'Uppertwist1_?', 'Bip01 ? UpperArm', 
 498            type  = 'TRANSFORM'                 ,
 499            space = 'LOCAL'                     ,
 500            map   = 'ROTATION'                  ,
 501            use_motion_extrapolate = True       ,
 502            from_rotation_mode = 'SWING_TWIST_Y',
 503            mix_mode_rot       = 'REPLACE'      ,
 504            from_max_y_rot = 1                  ,
 505            to_max_y_rot   = 1                  ,
 506            influence      = self.fDegPer1
 507        )
 508        self.constrainTwistBone(ob, 'Kata_?', 'Bip01 ? UpperArm', 
 509            space = 'WORLD',
 510            influence = self.fRota
 511        )
 512
 513        # AutoTwist() ... Wrist : 'TBody.cs' line 2793
 514        self.constrainTwistBone(ob, 'Foretwist_?', 'Bip01 ? Hand',
 515            type  = 'TRANSFORM'                 ,
 516            space = 'LOCAL'                     ,
 517            map   = 'ROTATION'                  ,
 518            use_motion_extrapolate = True       ,
 519            from_rotation_mode = 'SWING_TWIST_Y',
 520            mix_mode_rot       = 'REPLACE'      ,
 521            from_max_y_rot = 1                  ,
 522            to_max_y_rot   = 1
 523        )
 524        self.constrainTwistBone(ob, 'Foretwist1_?',
 525            type  = 'LIMIT_ROTATION',
 526            space = 'LOCAL'         ,
 527            use_limit_x = True      ,
 528            use_limit_y = True      ,
 529            use_limit_z = True      ,
 530        )
 531        self.constrainTwistBone(ob, 'Foretwist1_?', 'Bip01 ? Hand', 
 532            type  = 'TRANSFORM'                 ,
 533            space = 'LOCAL'                     ,
 534            map   = 'ROTATION'                  ,
 535            use_motion_extrapolate = True       ,
 536            from_rotation_mode = 'SWING_TWIST_Y',
 537            mix_mode_rot       = 'REPLACE'      ,
 538            from_max_y_rot = 1                  ,
 539            to_max_y_rot   = 1                  ,
 540            influence      = 0.5
 541        )
 542
 543        # TODO : Fix thigh constraints
 544        # AutoTwist() ... Thigh : 'TBody.cs' line 2813
 545        self.constrainTwistBone(ob, 'momotwist_?', 'Bip01 ? Thigh',
 546            type  = 'TRANSFORM'                 ,
 547            space = 'LOCAL'                     ,
 548            map   = 'ROTATION'                  ,
 549            use_motion_extrapolate = True       ,
 550            from_rotation_mode = 'SWING_TWIST_Y',
 551            mix_mode_rot       = 'REPLACE'      ,
 552            from_max_y_rot =  1                 ,
 553            to_max_y_rot   = -self.fDegPer
 554        )
 555        self.constrainTwistBone(ob, 'momotwist2_?', 'Bip01 ? Thigh',
 556            type  = 'TRANSFORM'                 ,
 557            space = 'LOCAL'                     ,
 558            map   = 'ROTATION'                  ,
 559            use_motion_extrapolate = True       ,
 560            from_rotation_mode = 'SWING_TWIST_Y',
 561            mix_mode_rot       = 'REPLACE'      ,
 562            from_max_y_rot = 1                  ,
 563            to_max_y_rot   = 1                  ,
 564            influence      = 0.7
 565        )
 566
 567
 568        # MoveMomoniku() : 'TBody.cs' line 2841
 569        self.driveTwistBone(ob, 'momoniku_?', flip=False, expression=("", "", "min(0,max(-8, self.id_data.pose.bones['{0}'].matrix.col[2].xyz.dot( (0,0,-1) ) *  10 * (pi/180) ))"), infulencers=('Bip01 ? Thigh'))
 570        self.driveTwistBone(ob, 'momoniku_?', flip=True , expression=("", "", "min(8,max( 0, self.id_data.pose.bones['{0}'].matrix.col[2].xyz.dot( (0,0,-1) ) * -10 * (pi/180) ))"), infulencers=('Bip01 ? Thigh'))
 571        self.constrainTwistBone(ob, 'Hip_?',
 572            type  = 'LIMIT_ROTATION',
 573            space = 'LOCAL'         ,
 574            use_limit_x = True      ,
 575            use_limit_y = True      ,
 576            use_limit_z = True      ,
 577        )
 578        self.constrainTwistBone(ob, 'Hip_?', 'Bip01 ? Thigh', 
 579            space = 'LOCAL_WITH_PARENT', 
 580            influence = 0.67
 581        )
 582        
 583        
 584
 585        bpy.ops.object.mode_set(mode=pre_mode)
 586        
 587        return {'FINISHED'}
 588
 589'''
 590    public void AutoTwist()
 591	{
 592		if (this.boAutoTwistShoulderL && this.Uppertwist_L != null)
 593		{
 594			Quaternion localRotation = this.UpperArmL.localRotation;
 595			float x = (Quaternion.Inverse(this.quaUpperArmL) * localRotation).eulerAngles.x;
 596			this.Uppertwist_L.localRotation = Quaternion.Euler(-0.0174532924f * this.DegPer(x, this.fDegPer), 0f, 0f);
 597			this.Uppertwist1_L.localRotation = Quaternion.Euler(-0.0174532924f * this.DegPer(x, this.fDegPer1), 0f, 0f);
 598			this.Kata_L.localRotation = this.quaKata_L;
 599			this.Kata_L.rotation = Quaternion.Slerp(this.Kata_L.rotation, this.UpperArmL.rotation, this.fRota);
 600		}
 601		if (this.boAutoTwistShoulderR && this.Uppertwist_R != null)
 602		{
 603			Quaternion localRotation2 = this.UpperArmR.localRotation;
 604			float x2 = (Quaternion.Inverse(this.quaUpperArmR) * localRotation2).eulerAngles.x;
 605			this.Uppertwist_R.localRotation = Quaternion.Euler(-0.0174532924f * this.DegPer(x2, this.fDegPer), 0f, 0f);
 606			this.Uppertwist1_R.localRotation = Quaternion.Euler(-0.0174532924f * this.DegPer(x2, 0.2f), 0f, 0f);
 607			this.Kata_R.localRotation = this.quaKata_R;
 608			this.Kata_R.rotation = Quaternion.Slerp(this.Kata_R.rotation, this.Uppertwist_R.rotation, 0.5f);
 609		}
 610		if (this.boAutoTwistWristL && this.Foretwist_L != null)
 611		{
 612			Vector3 fromDirection = this.HandL_MR.localRotation * Vector3.up;
 613			fromDirection.Normalize();
 614			Vector3 toDirection = this.HandL.localRotation * Vector3.up;
 615			toDirection.Normalize();
 616			this.m_fAngleHandL = this.AxisAngleOnAxisPlane(fromDirection, toDirection, new Vector3(1f, 0f, 0f)) * -1f;
 617			this.Foretwist_L.localRotation = Quaternion.AngleAxis(this.m_fAngleHandL, this.Foretwist_L_MR.localRotation * Vector3.left) * this.Foretwist_L_MR.localRotation;
 618			this.Foretwist1_L.localRotation = Quaternion.AngleAxis(this.m_fAngleHandL * 0.5f, this.Foretwist1_L_MR.localRotation * Vector3.left) * this.Foretwist1_L_MR.localRotation;
 619		}
 620		if (this.boAutoTwistWristR && this.Foretwist_R != null)
 621		{
 622			Vector3 fromDirection2 = this.HandR_MR.localRotation * Vector3.up;
 623			fromDirection2.Normalize();
 624			Vector3 toDirection2 = this.HandR.localRotation * Vector3.up;
 625			toDirection2.Normalize();
 626			float num = this.AxisAngleOnAxisPlane(fromDirection2, toDirection2, new Vector3(1f, 0f, 0f)) * -1f;
 627			this.Foretwist_R.localRotation = Quaternion.AngleAxis(num, this.Foretwist_R_MR.localRotation * Vector3.left) * this.Foretwist_R_MR.localRotation;
 628			this.Foretwist1_R.localRotation = Quaternion.AngleAxis(num * 0.5f, this.Foretwist1_R_MR.localRotation * Vector3.left) * this.Foretwist1_R_MR.localRotation;
 629		}
 630		if (this.boAutoTwistThighL && this.momotwist_L != null)
 631		{
 632			Quaternion quaternion = this.Thigh_L.localRotation;
 633			quaternion = Quaternion.Inverse(this.quaThigh_L) * quaternion;
 634			Vector3 vector = quaternion * Vector3.forward;
 635			float num2 = quaternion.eulerAngles.x;
 636			if (vector.z < 0f)
 637			{
 638				num2 = 180f - num2;
 639			}
 640			this.momotwist_L.localRotation = Quaternion.Euler(-0.0174532924f * this.DegPer(num2, this.fDegPer), 0f, 0f) * this.q_momotwist_L;
 641			this.momotwist2_L.localRotation = Quaternion.Euler(0.0174532924f * this.DegPer(num2, 0.7f), 0f, 0f) * this.q_momotwist2_L;
 642		}
 643		if (this.boAutoTwistThighR & this.momotwist_R != null)
 644		{
 645			Quaternion quaternion2 = this.Thigh_R.localRotation;
 646			quaternion2 = Quaternion.Inverse(this.quaThigh_R) * quaternion2;
 647			Vector3 vector2 = quaternion2 * Vector3.forward;
 648			float num3 = quaternion2.eulerAngles.x;
 649			if (vector2.z < 0f)
 650			{
 651				num3 = 180f - num3;
 652			}
 653			this.momotwist_R.localRotation = Quaternion.Euler(-0.0174532924f * this.DegPer(num3, this.fDegPer), 0f, 0f) * this.q_momotwist_R;
 654			this.momotwist2_R.localRotation = Quaternion.Euler(0.0174532924f * this.DegPer(num3, 0.7f), 0f, 0f) * this.q_momotwist2_R;
 655		}
 656	}
 657
 658	public void MoveMomoniku()
 659	{
 660		if (!TBody.boMoveMomoniku || this.momoniku_L == null || this.momoniku_R == null)
 661		{
 662			return;
 663		}
 664		float num = Mathf.Clamp(Vector3.Dot(Vector3.up, this.Thigh_L.up), 0f, 0.8f);
 665		float num2 = Mathf.Clamp(Vector3.Dot(Vector3.up, this.Thigh_R.up), 0f, 0.8f);
 666		this.momoniku_L.localRotation = this.momoniku_L_MR.localRotation;
 667		this.momoniku_R.localRotation = this.momoniku_R_MR.localRotation;
 668		this.momoniku_L.Rotate(0f, 0f, num * 10f);
 669		this.momoniku_R.Rotate(0f, 0f, -num2 * 10f);
 670		this.Hip_L.localRotation = Quaternion.Slerp(this.Hip_L_MR.localRotation, this.Thigh_L.localRotation, 0.67f);
 671		this.Hip_R.localRotation = Quaternion.Slerp(this.Hip_R_MR.localRotation, this.Thigh_R.localRotation, 0.67f);
 672	}
 673'''
 674
 675
 676
 677"""
 678- - - - - - For Bone Sliders - - - - - - 
 679"""
 680def get_axis_index_vector(axis_index, size=3):
 681    vec = mathutils.Vector.Fill(size)
 682    vec[axis_index] = 1
 683    return vec
 684
 685def get_axis_order_matrix(axis_order):
 686    size = len(axis_order)
 687    mat = mathutils.Matrix.Diagonal( [0] * size )
 688    for index, axis_index in enumerate(axis_order):
 689        mat[index][axis_index] = 1
 690    return mathutils.Matrix(mat)
 691
 692def get_vector_axis_index(vec):
 693    length = len(vec)
 694    for axis_index, axis_value in enumerate(vec):
 695        if axis_index == length-1:
 696            return axis_index
 697        else:
 698            axis_value = abs(axis_value)
 699            largest = True
 700            for i in range(axis_index+1, length):
 701                if axis_value < abs(vec[i]):
 702                    largest = False
 703                    break
 704            if largest:
 705                return axis_index
 706
 707def get_matrix_axis_order(mat):
 708    return [ get_vector_axis_index(row) for row in mat ]
 709
 710
 711
 712@compat.BlRegister()
 713class CNV_PG_cm3d2_bone_morph(bpy.types.PropertyGroup):
 714    bl_idname = 'CNV_PG_cm3d2_bone_morph'
 715
 716    scale = bpy.props.FloatProperty(name="Scale", default=5, min=0.1, max=100, soft_min=0.1, soft_max=100, step=100, precision=1, description="The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.")
 717
 718    def __calcMeasurements(self, context):                                               
 719        num    =  1340                         +                   self.sintyou * 4    +      self.DouPer * (1 + self.sintyou * 0.005) + self.KubiScl * 0.5 + self.HeadY * 0.5
 720        num2   =    55 * self.RegFat           + 50              * self.sintyou * 0.5  + 50 * self.DouPer * 0.4
 721        num3   =    55 * self.RegMeet          + 50              * self.sintyou * 0.5  + 50 * self.DouPer * 0.4
 722        num4   =    10 * self.UdeScl   * 0.1                                                             
 723        num5   =     5 * self.ArmL             +  5              * self.sintyou * 1    +  5 * self.UdeScl * 0.5
 724        num6   =    70 * self.Hara             + 50              * self.sintyou * 0.7  + 50 * self.Hara   * self.west * 0.005
 725        num7   =    10 * self.MuneL    * 2                                                                           
 726        num8   =  num7 * self.MuneTare * 0.005                                                                       
 727        num9   =    20 * self.west     * 0.5   + 15 * self.west  * self.sintyou * 0.02 + 15 * self.DouPer * self.west * 0.01
 728        num10  =    10 * self.koshi            +  7 * self.koshi * self.sintyou * 0.04
 729        num11  =     4 * self.kata                        
 730        num13  =    70                         +      self.MuneL                * 0.31 +                    self.west * 0.02      
 731        
 732        num13 -=     5 * (self.MuneS / 100)                
 733        num12  = 38000 + num2 + num3 + num4 + num5 + num6 + num7 + num8 + num9 + num10 + num11
 734        
 735        self.private_height = num   /   10
 736        self.private_weight = num12 / 1000
 737        self.private_bust   = num13
 738        self.private_waist  = 40 + self.west  * 0.25 + self.Hara   * 0.35
 739        self.private_hip    = 65 + self.koshi * 0.3  + self.RegFat * 0.025 + self.RegMeet * 0.025
 740             
 741        if   num13 <   80:
 742            self.private_cup = "A"
 743        elif num13 >= 110:
 744            self.private_cup = "N"
 745        else:
 746            cup_sizes = ['B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M']
 747            self.private_cup = cup_sizes[int((num13 - 80) / 2.5)]
 748
 749        self.private_height = int(self.private_height) * 0.01 / context.scene.unit_settings.scale_length
 750        self.private_weight = int(self.private_weight)        / context.scene.unit_settings.scale_length ** 3
 751        self.private_bust   = int(self.private_bust  ) * 0.01 / context.scene.unit_settings.scale_length
 752        self.private_waist  = int(self.private_waist ) * 0.01 / context.scene.unit_settings.scale_length
 753        self.private_hip    = int(self.private_hip   ) * 0.01 / context.scene.unit_settings.scale_length
 754        self.private_cup = "'" + self.private_cup + "'"
 755
 756        return None
 757
 758    def __calcMune(self, context):
 759        if self.BreastSize >= 0:
 760            self.MuneL = self.BreastSize
 761            self.MuneS = 0
 762        else:
 763            self.MuneL = 0
 764            self.MuneS = (self.BreastSize / -30) * 100
 765        self.__calcMuneTare(context)
 766        return None
 767
 768    def __calcMuneTare(self, context):
 769        if self.MuneTare > self.MuneL:
 770            self.MuneTare = self.MuneL
 771        else:
 772            self.__calcMeasurements(context)
 773
 774    HeadX      = bpy.props.FloatProperty(name="HeadX"     , description="Size of face (left to right)", default=  50, min=   0, max= 100, step=100, precision=0)
 775    HeadY      = bpy.props.FloatProperty(name="HeadY"     , description="Size of face (up and down)"  , default=  50, min=   0, max= 100, step=100, precision=0, update=__calcMeasurements)
 776    DouPer     = bpy.props.FloatProperty(name="DouPer"    , description="Leg length"                  , default=  50, min=-100, max= 500, step=100, precision=0, update=__calcMeasurements)
 777    sintyou    = bpy.props.FloatProperty(name="sintyou"   , description="Height"                      , default=  50, min=-300, max= 100, step=100, precision=0, update=__calcMeasurements)
 778    BreastSize = bpy.props.FloatProperty(name="BreastSize", description="Breast size"                 , default=  50, min= -30, max= 195, step=100, precision=0, update=__calcMune        )
 779    MuneTare   = bpy.props.FloatProperty(name="MuneTare"  , description="Breast sagging level"        , default=  50, min=   0, max= 195, step=100, precision=0, update=__calcMuneTare    )
 780    MuneUpDown = bpy.props.FloatProperty(name="MuneUpDown", description="Position of the nipple"      , default=  10, min= -50, max= 300, step=100, precision=0)
 781    MuneYori   = bpy.props.FloatProperty(name="MuneYori"  , description="Direction of breast"         , default=  40, min= -50, max= 200, step=100, precision=0)
 782    west       = bpy.props.FloatProperty(name="west"      , description="Waist"                       , default=  50, min= -30, max= 100, step=100, precision=0, update=__calcMeasurements)
 783    Hara       = bpy.props.FloatProperty(name="Hara"      , description="Belly"                       , default=  20, min=   0, max= 200, step=100, precision=0, update=__calcMeasurements)
 784    kata       = bpy.props.FloatProperty(name="kata"      , description="Shoulder width"              , default=  50, min=-400, max= 100, step=100, precision=0, update=__calcMeasurements)
 785    ArmL       = bpy.props.FloatProperty(name="ArmL"      , description="Size of arms"                , default=  20, min=   0, max= 100, step=100, precision=0, update=__calcMeasurements)
 786    UdeScl     = bpy.props.FloatProperty(name="UdeScl"    , description="Length of arms"              , default=  50, min=   0, max= 100, step=100, precision=0, update=__calcMeasurements)
 787    KubiScl    = bpy.props.FloatProperty(name="KubiScl"   , description="Length of neck"              , default=  50, min=   0, max= 200, step=100, precision=0, update=__calcMeasurements)
 788    koshi      = bpy.props.FloatProperty(name="koshi"     , description="Hip"                         , default=  50, min=-160, max= 200, step=100, precision=0, update=__calcMeasurements)
 789    RegFat     = bpy.props.FloatProperty(name="RegFat"    , description="Leg thickness"               , default=  40, min=   0, max= 100, step=100, precision=0, update=__calcMeasurements)
 790    RegMeet    = bpy.props.FloatProperty(name="RegMeet"   , description="Leg definition"              , default=  40, min=   0, max= 100, step=100, precision=0, update=__calcMeasurements)
 791    MuneL      = bpy.props.FloatProperty(name="MuneL"     , description="munel shapekey value"        , default=  50, min=   0)
 792    MuneS      = bpy.props.FloatProperty(name="MuneS"     , description="munes shapekey value"        , default=   0, min=   0)
 793
 794    def __measurementSetter(self, value):
 795        self.__calcMeasurements(bpy.context)
 796        return None
 797    
 798    def __newGetter(attr, recalc=False):
 799        def __getter(self):
 800            if recalc:
 801                self.__calcMeasurements(bpy.context)
 802            return getattr(self, attr)
 803        return __getter
 804
 805    private_height  = bpy.props.FloatProperty (name="private_height", options={'HIDDEN'})
 806    private_weight  = bpy.props.FloatProperty (name="private_weight", options={'HIDDEN'})
 807    private_bust    = bpy.props.FloatProperty (name="private_bust"  , options={'HIDDEN'})
 808    private_waist   = bpy.props.FloatProperty (name="private_waist" , options={'HIDDEN'})
 809    private_hip     = bpy.props.FloatProperty (name="private_hip"   , options={'HIDDEN'})
 810    private_cup     = bpy.props.StringProperty(name="private_cup"   , options={'HIDDEN'})
 811                                                     
 812    height   = bpy.props.FloatProperty (name="height", precision=3, unit=compat.unit('LENGTH'), set=__measurementSetter, get=__newGetter('private_height', recalc=True))
 813    weight   = bpy.props.FloatProperty (name="weight", precision=3, unit=compat.unit('MASS'  ), set=__measurementSetter, get=__newGetter('private_weight'))
 814    bust     = bpy.props.FloatProperty (name="bust"  , precision=3, unit=compat.unit('LENGTH'), set=__measurementSetter, get=__newGetter('private_bust'  ))
 815    waist    = bpy.props.FloatProperty (name="waist" , precision=3, unit=compat.unit('LENGTH'), set=__measurementSetter, get=__newGetter('private_waist' ))
 816    hip      = bpy.props.FloatProperty (name="hip"   , precision=3, unit=compat.unit('LENGTH'), set=__measurementSetter, get=__newGetter('private_hip'   ))
 817    cup      = bpy.props.StringProperty(name="cup"   ,                                          set=__measurementSetter, get=__newGetter('private_cup'   ))
 818                                                     
 819    def GetArmature(self, override=None):
 820        override = override or bpy.context.copy()
 821        ob = self.id_data
 822        override.update({
 823            'selected_objects'         : {ob},
 824            'selected_editable_objects': {ob},
 825            'editable_bones'           : {}  ,
 826            'selected_bones'           : {}  ,
 827            'selected_editable_bones'  : {}  ,
 828            'active_object'            : ob  ,
 829            'edit_object'              : ob  ,
 830        })
 831        return self.id_data, override
 832
 833        #armature = override['object']
 834        #if not armature or armature.type != 'ARMATURE':
 835        #    print("ERROR: Active object is not an armature")
 836        #    return None, None
 837        #
 838        #for area in bpy.context.screen.areas:
 839        #    #print(area,area.type)
 840        #    if area.type == 'OUTLINER':
 841        #        override.update({
 842        #            'blend_data': None,
 843        #            'area': area,
 844        #            'scene': bpy.context.scene,
 845        #            'screen': None,
 846        #            'space_data': area.spaces[0],
 847        #            'window': None,
 848        #            'window_manager': None,
 849        #            'object': armature,
 850        #            'active_object': armature,
 851        #            'edit_object': armature,
 852        #        })
 853        #        break
 854        #
 855        #if override['area'].type != 'OUTLINER':
 856        #    print("ERROR: There is no 3D View Present in the current workspace")
 857        #    return None, None
 858        #
 859        #if False:
 860        #    print("\n")
 861        #    for k,v in override.items():
 862        #        print(k)
 863        #    print("\n")
 864        #return armature, override
 865
 866    def GetPoseBone(self, boneName, flip=False, override=None):
 867        context = bpy.context
 868        
 869        side = "L" if flip else "R"
 870        armature, override = self.GetArmature()
 871        if not armature:
 872            return
 873        
 874        poseBoneList = armature.pose.bones
 875        poseBone = poseBoneList.get(boneName.replace("?",side)) or poseBoneList.get(boneName.replace("?","*")+"."+side)
 876
 877        # check if _SCL_ bone needs to be created
 878        if not poseBone and "_SCL_" in boneName:
 879            boneList = armature.data.edit_bones
 880            bpy.ops.object.mode_set(mode='EDIT')
 881            print("Make Scale Bone: "+boneName)
 882            copyBone = boneList.get(boneName.replace("_SCL_","").replace("?",side)) or boneList.get(boneName.replace("_SCL_","").replace("?","*")+"."+side)
 883            if copyBone:
 884                #bpy.ops.armature.select_all(override, action='DESELECT')
 885                #for v in context.selected_bones:
 886                #    v.select = False
 887                #    v.select_head = False
 888                #    v.select_tail = False
 889                #copyBone.select = True
 890                #copyBone.select_head = True
 891                #copyBone.select_tail = True
 892                #boneList.active = copyBone
 893                #bpy.ops.armature.duplicate(override)
 894                new_name = copyBone.basename+"_SCL_" + ("."+side if ("."+side) in copyBone.name else "")
 895                bone = armature.data.edit_bones.new(new_name)
 896                bone.parent = copyBone
 897                bone.head = copyBone.head
 898                bone.tail = copyBone.tail
 899                bone.roll = copyBone.roll
 900                bone.show_wire = True
 901                bone.use_deform = True
 902                copyBone['cm3d2_scl_bone'] = False
 903                bone['cm3d2_scl_bone'] = False
 904                
 905                # rename vertex groups
 906                for child in armature.children:
 907                    if child.type == 'MESH':
 908                        vertexGroup = child.vertex_groups.get(copyBone.name)
 909                        if vertexGroup:
 910                            vertexGroup.name = bone.name
 911        
 912        bpy.ops.object.mode_set(mode='POSE')
 913        poseBone = poseBone or poseBoneList.get(boneName.replace("?", side)) or poseBoneList.get(boneName.replace("?","*")+"."+side)
 914        
 915        if not poseBone:
 916            print("WARNING: Could not find bone \""+boneName+"\"")
 917            return
 918
 919        return poseBone
 920
 921    def GetDrivers(self, data_path, prop):
 922        id_data = self.id_data
 923        drivers = [None, None, None]
 924        if id_data and id_data.animation_data:
 925            for f in id_data.animation_data.drivers:
 926                fName = f.data_path
 927                #print("check",fName, "for", '["%s"].%s' % (data_path, prop))
 928                if '["{path}"].{attr}'.format(path=data_path, attr=prop) in fName:
 929                    #print("VALID!")
 930                    drivers[f.array_index] = f.driver
 931        return drivers
 932
 933
 934    def AddPositionDriver(self, prop, bone, drivers, axis, value, default=50):
 935        value = value-1
 936        if value == 0:
 937            return
 938        
 939        driver = drivers[axis]
 940        prefix = " + "
 941        
 942        if not driver:
 943            driver = bone.driver_add("location", axis).driver
 944            driver.type = 'SCRIPTED'
 945            
 946            parent_length_var = driver.variables.new()
 947            parent_length_var.type = 'SINGLE_PROP'
 948            parent_length_var.name = "parent_length"
 949            
 950            driver_target = parent_length_var.targets[0]
 951            driver_target.id_type = 'ARMATURE'
 952            driver_target.id = bone.parent.bone.id_data if not compat.IS_LEGACY else bone.parent.bone.id_data.data
 953            driver_target.data_path = bone.parent.bone.path_from_id("length")
 954
 955            head_var = driver.variables.new()
 956            head_var.type = 'SINGLE_PROP'
 957            head_var.name = "head"
 958
 959            driver_target = head_var.targets[0]
 960            driver_target.id_type = 'OBJECT'
 961            driver_target.id = bone.id_data
 962            driver_target.data_path = bone.path_from_id("head") + f"[{axis}]"
 963            
 964            if axis == 1: # if y axis, include parent bone's length, because head coords are based on parent's tail
 965                driver.expression = "(parent_length+head)_"
 966            else:
 967                driver.expression = "head_"
 968            prefix = " * ("
 969            
 970            #driver.expression = "-{direction} + {direction}", direction=rest_value
 971
 972        driver_var = driver.variables.get(prop)
 973        if not driver_var:
 974            driver_var = driver.variables.new()
 975            driver_var.type = 'SINGLE_PROP'
 976            driver_var.name = prop
 977
 978            driver_target = driver_var.targets[0]
 979            driver_target.id_type = 'OBJECT'
 980            driver_target.id = bone.id_data
 981            driver_target.data_path = bone.id_data.cm3d2_bone_morph.path_from_id(prop)
 982        
 983        # if prop isn't already a factor
 984        if not prop in driver.expression:
 985            driver.expression = driver.expression[:-1] + prefix + f"({prop}-{default})*{value/(100-default)})"
 986            
 987        return
 988
 989    def AddScaleDriver(self, prop, bone, drivers, axis, value, default=50):
 990        value = value-1
 991        if value == 0:
 992            return
 993        
 994        driver = drivers[axis]
 995        
 996        # if just created
 997        if not driver:
 998            driver = bone.driver_add("scale", axis).driver
 999            driver.type = 'SCRIPTED'
1000            driver.expression = "(1)"
1001
1002        driver_var = driver.variables.get(prop) 
1003        if not driver_var:
1004            driver_var = driver.variables.new()
1005            driver_var.type = 'SINGLE_PROP'
1006            driver_var.name = prop
1007
1008            driver_target = driver_var.targets[0]
1009            driver_target.id_type = 'OBJECT'
1010            driver_target.id = bone.id_data
1011            driver_target.data_path = bone.id_data.cm3d2_bone_morph.path_from_id(prop)
1012        
1013        # if prop isn't already a factor
1014        if not prop in driver.expression:
1015            driver.expression = driver.expression[:-1] + f" + ({prop}-{default})*{value/(100-default)})"
1016 
1017        return
1018
1019    def SetPosition(self, prop, boneName, x, y, z, default=50):
1020        # Check if object has this property
1021        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1022        #    if ONLY_FIX_SETTINGS:
1023        #        return
1024        #x = (1-x)+1
1025        #y = (1-y)+1
1026        #z = (1-z)+1
1027
1028        #loc.x, loc.y, loc.z = loc.z, -loc.x, loc.y
1029        #x, y, z = z, x, y
1030
1031        vec = mathutils.Vector((x, y, z))
1032        vec = compat.convert_cm_to_bl_slider_space(vec)
1033
1034        pose_bone = self.GetPoseBone(boneName)
1035        if pose_bone:                                                       
1036            #rest_pos = pose_bone.bone.head_local + (pose_bone.bone.head_local - pose_bone.bone.parent.head_local) 
1037            #rest_pos = compat.mul(pose_bone.bone.matrix_local.inverted(), rest_pos)
1038            #vec = mathutils.Vector((x, y, z))# * self.scale
1039            #if pose_bone.parent:
1040            #    vec = compat.convert_cm_to_bl_bone_space(vec)
1041            #    vec = compat.mul(pose_bone.parent.bone.matrix_local, vec)
1042            #else:
1043            #    vec = compat.convert_cm_to_bl_space(vec)
1044            #vec = compat.mul(pose_bone.bone.matrix_local.inverted(), vec)
1045
1046            pose_bone.bone.use_local_location = False
1047            drivers = self.GetDrivers(pose_bone.name,'location')
1048                                                        
1049            self.AddPositionDriver(prop, pose_bone, drivers, 0, vec[0], default=default)
1050            self.AddPositionDriver(prop, pose_bone, drivers, 1, vec[1], default=default)
1051            self.AddPositionDriver(prop, pose_bone, drivers, 2, vec[2], default=default)
1052                                                                   
1053        # repeat for left side
1054        if '?' in boneName:
1055            pose_bone = self.GetPoseBone(boneName, flip=True)
1056            if pose_bone:
1057                #rest_pos = pose_bone.bone.head_local + pose_bone.bone.head
1058                #rest_pos = compat.mul(pose_bone.bone.matrix_local.inverted(), rest_pos)
1059                #vec = mathutils.Vector((x, y, z))# * self.scale
1060                #if pose_bone.parent:
1061                #    vec = compat.convert_cm_to_bl_bone_space(vec)
1062                #    vec = compat.mul(pose_bone.parent.bone.matrix_local, vec)
1063                #else:
1064                #    vec = compat.convert_cm_to_bl_space(vec)
1065                #vec = compat.mul(pose_bone.bone.matrix_local.inverted(), vec)
1066                
1067                pose_bone.bone.use_local_location = False
1068                drivers = self.GetDrivers(pose_bone.name,'location')
1069
1070                vec[2] = (1-vec[2])+1 # mirror z axis
1071                
1072                self.AddPositionDriver(prop, pose_bone, drivers, 0, vec[0], default=default)
1073                self.AddPositionDriver(prop, pose_bone, drivers, 1, vec[1], default=default)
1074                self.AddPositionDriver(prop, pose_bone, drivers, 2, vec[2], default=default)
1075                                                                            
1076        return
1077
1078    def SetScale(self, prop, boneName, x, y, z, default=50):
1079        # Check if object has this property
1080        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1081        #    if ONLY_FIX_SETTINGS:
1082        #        return
1083
1084        #x, y, z = z, abs(-x), y
1085
1086        mat = mathutils.Matrix.Diagonal((x, y, z)).to_4x4()
1087        mat = compat.convert_cm_to_bl_bone_rotation(mat)
1088        x, y, z = -mat.to_scale()
1089
1090        bone = self.GetPoseBone(boneName)
1091        if bone:
1092            drivers = self.GetDrivers(bone.name,'scale')
1093            
1094            self.AddScaleDriver(prop, bone, drivers, 0, x, default=default)
1095            self.AddScaleDriver(prop, bone, drivers, 1, y, default=default)
1096            self.AddScaleDriver(prop, bone, drivers, 2, z, default=default)
1097        
1098        # repeat for left side
1099        if '?' in boneName:
1100            bone = self.GetPoseBone(boneName, flip=True)
1101            if bone:
1102                drivers = self.GetDrivers(bone.name,'scale')
1103                
1104                self.AddScaleDriver(prop, bone, drivers, 0, x, default=default)
1105                self.AddScaleDriver(prop, bone, drivers, 1, y, default=default)
1106                self.AddScaleDriver(prop, bone, drivers, 2, z, default=default)
1107        
1108        return
1109
1110
1111@compat.BlRegister()
1112class CNV_PG_cm3d2_wide_slider(bpy.types.PropertyGroup):
1113    bl_idname = 'CNV_PG_cm3d2_wide_slider'
1114
1115    scale = bpy.props.FloatProperty(name="Scale", default=5, min=0.1, max=100, soft_min=0.1, soft_max=100, step=100, precision=1, description="The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.")
1116
1117    empty  = bpy.props.EnumProperty(items=[('EMPTY','-',"This property never has a value")], name="Empty", description="This property never has a value")
1118    
1119    enable_all = bpy.props.BoolProperty(name="Enable All", description="Enable all sliders, even ones without a GUI in-game", default=False)
1120
1121    HIPPOS     = bpy.props.FloatVectorProperty(name="HIPPOS"    , description="Hips Position"         , default=(0,0,0), min=-100, max= 200, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1122    THIPOS     = bpy.props.FloatVectorProperty(name="THIPOS"    , description="Legs Position"         , default=(0,0,0), min=-100, max= 200, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1123    MTWPOS     = bpy.props.FloatVectorProperty(name="MTWPOS"    , description="Thigh Position"        , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1124    MMNPOS     = bpy.props.FloatVectorProperty(name="MMNPOS"    , description="Rear Thigh Position"   , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1125    THI2POS    = bpy.props.FloatVectorProperty(name="THI2POS"   , description="Knee Position"         , default=(0,0,0), min=-100, max= 200, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1126    SKTPOS     = bpy.props.FloatVectorProperty(name="SKTPOS"    , description="Skirt Position"        , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1127    SPIPOS     = bpy.props.FloatVectorProperty(name="SPIPOS"    , description="Lower Abdomen Position", default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1128    S0APOS     = bpy.props.FloatVectorProperty(name="S0APOS"    , description="Upper Abdomen Position", default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1129    S1POS      = bpy.props.FloatVectorProperty(name="S1POS"     , description="Lower Chest Position"  , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1130    S1APOS     = bpy.props.FloatVectorProperty(name="S1APOS"    , description="Upper Chest Position"  , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1131    MUNEPOS    = bpy.props.FloatVectorProperty(name="MUNEPOS"   , description="Breasts Position"      , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1132    MUNESUBPOS = bpy.props.FloatVectorProperty(name="MUNESUBPOS", description="Breasts Sub-Position"  , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1133    NECKPOS    = bpy.props.FloatVectorProperty(name="NECKPOS"   , description="Neck Position"         , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1134    CLVPOS     = bpy.props.FloatVectorProperty(name="CLVPOS"    , description="Clavicle Position"     , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1135                                                                                                
1136    PELSCL     = bpy.props.FloatVectorProperty(name="PELSCL"    , description="Pelvis Scale"          , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1137    HIPSCL     = bpy.props.FloatVectorProperty(name="HIPSCL"    , description="Hips Scale"            , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1138    THISCL     = bpy.props.FloatVectorProperty(name="THISCL"    , description="Legs Scale"            , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1139    MTWSCL     = bpy.props.FloatVectorProperty(name="MTWSCL"    , description="Thigh Scale"           , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1140    MMNSCL     = bpy.props.FloatVectorProperty(name="MMNSCL"    , description="Rear Thigh Scale"      , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1141    THISCL2    = bpy.props.FloatVectorProperty(name="THISCL2"   , description="Knee Scale"            , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1142    CALFSCL    = bpy.props.FloatVectorProperty(name="CALFSCL"   , description="Calf Scale"            , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1143    FOOTSCL    = bpy.props.FloatVectorProperty(name="FOOTSCL"   , description="Foot Scale"            , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1144    SKTSCL     = bpy.props.FloatVectorProperty(name="SKTSCL"    , description="Skirt Scale"           , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1145    SPISCL     = bpy.props.FloatVectorProperty(name="SPISCL"    , description="Lower Abdomen Scale"   , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1146    S0ASCL     = bpy.props.FloatVectorProperty(name="S0ASCL"    , description="Upper Abdomen Scale"   , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1147    S1_SCL     = bpy.props.FloatVectorProperty(name="S1_SCL"    , description="Lower Chest Scale"     , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1148    S1ASCL     = bpy.props.FloatVectorProperty(name="S1ASCL"    , description="Upper Chest Scale"     , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1149    S1ABASESCL = bpy.props.FloatVectorProperty(name="S1ABASESCL", description="Upper Torso Scale"     , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1150    MUNESCL    = bpy.props.FloatVectorProperty(name="MUNESCL"   , description="Breasts Scale"         , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1151    MUNESUBSCL = bpy.props.FloatVectorProperty(name="MUNESUBSCL", description="Breasts Sub-Scale"     , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1152    NECKSCL    = bpy.props.FloatVectorProperty(name="NECKSCL"   , description="Neck Scale"            , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1153    CLVSCL     = bpy.props.FloatVectorProperty(name="CLVSCL"    , description="Clavicle Scale"        , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1154    KATASCL    = bpy.props.FloatVectorProperty(name="KATASCL"   , description="Shoulders Scale"       , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1155    UPARMSCL   = bpy.props.FloatVectorProperty(name="UPARMSCL"  , description="Upper Arm Scale"       , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1156    FARMSCL    = bpy.props.FloatVectorProperty(name="FARMSCL"   , description="Forearm Scale"         , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1157    HANDSCL    = bpy.props.FloatVectorProperty(name="HANDSCL"   , description="Hand Scale"            , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1158                                                                                                                                        
1159                                                                                                                                        
1160    def GetArmature(self, override=None):
1161        return CNV_PG_cm3d2_bone_morph.GetArmature(self, override=override)
1162    
1163    def GetPoseBone(self, boneName, flip=False, override=None):
1164        return CNV_PG_cm3d2_bone_morph.GetPoseBone(self, boneName, flip=flip, override=override)
1165
1166    def GetDrivers(self, data_path, prop):
1167        return CNV_PG_cm3d2_bone_morph.GetDrivers(self, data_path, prop)
1168
1169
1170    def AddPositionDriver(self, prop, index, bone, drivers, axis, value):
1171        if value == 0:
1172            return
1173              
1174        driver = drivers[axis]
1175
1176        if not driver:
1177            driver = bone.driver_add("location",axis).driver
1178            driver.type = 'SCRIPTED'
1179            driver.expression = "0"
1180
1181        prop_var = prop + f"_{index}_"
1182        driver_var = driver.variables.get(prop_var) 
1183        if not driver_var:
1184            driver_var = driver.variables.new()
1185            driver_var.type = 'SINGLE_PROP'
1186            driver_var.name = prop_var
1187
1188            driver_target = driver_var.targets[0]
1189            driver_target.id_type = 'OBJECT'
1190            driver_target.id = bone.id_data
1191            driver_target.data_path = bone.id_data.cm3d2_wide_slider.path_from_id(prop) + f"[{index}]"
1192
1193              
1194        # if prop isn't already a factor
1195        if not prop_var in driver.expression:
1196            driver.expression = driver.expression + f" + {prop_var}*{value}"
1197                
1198        return
1199              
1200              
1201    def AddScaleDriver(self, prop, index, bone, drivers, axis):
1202        if index < 0:
1203            return
1204              
1205        driver = drivers[axis]
1206        if not driver:
1207            driver = bone.driver_add("scale", axis).driver
1208            driver.type = 'SCRIPTED'
1209            driver.expression = "1"
1210        
1211        prop_var = f"{prop}_{index}_"
1212        driver_var = driver.variables.get(prop_var) 
1213        if not driver_var:
1214            driver_var = driver.variables.new()
1215            driver_var.type = 'SINGLE_PROP'
1216            driver_var.name = prop_var
1217
1218            driver_target = driver_var.targets[0]
1219            driver_target.id_type = 'OBJECT'
1220            driver_target.id = bone.id_data
1221            driver_target.data_path = bone.id_data.cm3d2_wide_slider.path_from_id(prop) + f"[{index}]"
1222
1223              
1224        # if prop isn't already a factor
1225        if not prop_var in driver.expression:
1226            driver.expression = driver.expression + f" * {prop_var}"
1227                
1228        return
1229              
1230                      
1231    def AddVectorProperty(self, object, prop, value=None, default=0.0, min=-100, max=200):
1232        #value = value or [default, default, default]
1233        #object[prop] = not RESET_SETTINGS and object.get(prop) or value
1234        #object['_RNA_UI'][prop] = {
1235        #    "description": "",
1236        #    "default": default,
1237        #    "min": min,
1238        #    "max": max,
1239        #    "soft_min": min,
1240        #    "soft_max": max,
1241        #}     
1242        return
1243    
1244              
1245    def SetPosition(self, prop, boneName, ux, uy, uz, axisOrder=[0,1,2], axisFlip=None):
1246        # Check if object has this property
1247        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1248        #    self.AddVectorProperty(bpy.context.object, prop)
1249        #    if ONLY_FIX_SETTINGS:
1250        #        return
1251
1252        mat = get_axis_order_matrix(axisOrder).to_4x4()
1253        mat.translation = mathutils.Vector((ux, uy, uz)) * self.scale
1254        mat = compat.convert_cm_to_bl_bone_space(mat)
1255        uVec = mat.to_translation()
1256        axisOrder = get_matrix_axis_order(mat.to_3x3())
1257
1258        if axisFlip != None:
1259            flipVec = get_axis_index_vector(axisFlip)
1260            flipVec = compat.convert_cm_to_bl_bone_space(flipVec)
1261            axisFlip = get_vector_axis_index(flipVec)
1262        
1263        ##ux, uy, uz = uz*5, ux*5, -uy*5
1264        ##axisFlip = axisOrder[axisFlip] if axisFlip else None
1265        #axisFlip = 1 if axisFlip == 0 else ( 2 if axisFlip == 1 else (0 if axisFlip == 2 else None) )
1266        ##axisFlip = axisOrder[axisFlip] if axisFlip else None
1267        #axisOrder[0], axisOrder[1], axisOrder[2] = axisOrder[2], axisOrder[0], axisOrder[1]
1268        ##axisFlip = axisOrder[axisFlip] if axisFlip != None else None
1269        
1270        bone = self.GetPoseBone(boneName)
1271        if bone:
1272            bone.bone.use_local_location = False
1273            drivers = self.GetDrivers(bone.name,'location')
1274        
1275            self.AddPositionDriver(prop, axisOrder[0], bone, drivers, 0, uVec[0])
1276            self.AddPositionDriver(prop, axisOrder[1], bone, drivers, 1, uVec[1])
1277            self.AddPositionDriver(prop, axisOrder[2], bone, drivers, 2, uVec[2])
1278        
1279        # repeat for left side
1280        if '?' in boneName:
1281            bone = self.GetPoseBone(boneName, flip=True)
1282            if bone:
1283                bone.bone.use_local_location = False
1284                drivers = self.GetDrivers(bone.name,'location')
1285
1286                if axisFlip != None:
1287                    print(axisFlip)
1288                    uVec[axisFlip] *= -1
1289                
1290                #if   axisFlip == 0:
1291                #    ux = -ux
1292                #elif axisFlip == 1:
1293                #    uy = -uy
1294                #elif axisFlip == 2:
1295                #    uz = -uz
1296                
1297                self.AddPositionDriver(prop, axisOrder[0], bone, drivers, 0, uVec[0])
1298                self.AddPositionDriver(prop, axisOrder[1], bone, drivers, 1, uVec[1])
1299                self.AddPositionDriver(prop, axisOrder[2], bone, drivers, 2, uVec[2])
1300                                                                             
1301        return
1302
1303
1304    def SetScale(self, prop, boneName, axisOrder=[0,1,2]):
1305        # Check if object has this property
1306        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1307        #    self.AddVectorProperty(bpy.context.object, prop, default=1.0, min=0.1, max=3.0)
1308        #    if ONLY_FIX_SETTINGS:
1309        #        return
1310
1311        # x, y, z = x, z, y
1312        #axisOrder[0], axisOrder[1], axisOrder[2] = axisOrder[0], axisOrder[2], axisOrder[1]
1313        
1314        axisMat = get_axis_order_matrix(axisOrder).to_4x4()
1315        axisMat = compat.convert_cm_to_bl_bone_rotation(axisMat)
1316        #axisMat = compat.convert_cm_to_bl_bone_space(axisMat)
1317        axisOrder = get_matrix_axis_order(axisMat)
1318        
1319        bone = self.GetPoseBone(boneName)
1320        if bone:
1321            drivers = self.GetDrivers(bone.name,'scale')
1322            
1323            self.AddScaleDriver(prop, axisOrder[0], bone, drivers, 2)
1324            self.AddScaleDriver(prop, axisOrder[1], bone, drivers, 1)
1325            self.AddScaleDriver(prop, axisOrder[2], bone, drivers, 0)
1326        
1327        # repeat for left side
1328        if '?' in boneName:
1329            bone = self.GetPoseBone(boneName, True)
1330            if bone:
1331                drivers = self.GetDrivers(bone.name,'scale')
1332
1333                self.AddScaleDriver(prop, axisOrder[0], bone, drivers, 2)
1334                self.AddScaleDriver(prop, axisOrder[1], bone, drivers, 1)
1335                self.AddScaleDriver(prop, axisOrder[2], bone, drivers, 0)
1336        
1337        return
1338
1339
1340@compat.BlRegister()
1341class CNV_OT_add_cm3d2_body_sliders(bpy.types.Operator):
1342    bl_idname      = 'object.add_cm3d2_body_sliders'
1343    bl_label       = "Add CM3D2 Body Sliders"
1344    bl_description = "Adds drivers to armature to enable body sliders."
1345    bl_options     = {'REGISTER', 'UNDO'}
1346
1347    scale = bpy.props.FloatProperty(name="Scale", default=5, min=0.1, max=100, soft_min=0.1, soft_max=100, step=100, precision=1, description="The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.")
1348
1349    is_fix_thigh        = bpy.props.BoolProperty(name="Fix Thigh"       , default=False, description="Fix twist bone values for the thighs in motor-cycle pose")
1350    is_drive_shape_keys = bpy.props.BoolProperty(name="Drive Shape Keys", default=True, description="Connect sliders to mesh children's shape keys"           )
1351    
1352    @classmethod
1353    def poll(cls, context):
1354        ob = context.object
1355        if ob:
1356            arm = ob.data
1357        else:
1358            arm = None
1359        has_arm  = arm and isinstance(arm, bpy.types.Armature) and ("Bip01" in arm.bones)
1360        can_edit = (ob and ob.data == arm) or (arm and arm.is_editmode)
1361        return has_arm and can_edit
1362
1363    def invoke(self, context, event):
1364        self.scale = common.preferences().scale
1365        return context.window_manager.invoke_props_dialog(self)
1366
1367    def draw(self, context):
1368        self.layout.prop(self, 'scale'              )
1369        #self.layout.prop(self, 'is_fix_thigh'       )
1370        self.layout.prop(self, 'is_drive_shape_keys')
1371
1372    def driveShapeKey(self, shapekey, data, prop, expression, set_min=None, set_max=None):
1373        if not shapekey:
1374            return
1375        driver = shapekey.driver_add('value').driver
1376        driver.type = 'SCRIPTED'
1377
1378        driver_var = driver.variables.new() if len(driver.variables) < 1 else driver.variables[0]
1379        driver_var.type = 'SINGLE_PROP'
1380        driver_var.name = prop
1381
1382        driver_target = driver_var.targets[0]
1383        driver_target.id_type = 'OBJECT'
1384        driver_target.id = data.id_data
1385        driver_target.data_path = data.path_from_id(prop)
1386
1387        driver.expression = expression
1388
1389        if set_min:
1390            shapekey.slider_min = set_min
1391        if set_max:
1392            shapekey.slider_max = set_max
1393
1394    def driveTwistBone(self, bone, prop='rotation_euler', axis=0, expression=""):
1395        if not bone:
1396            return
1397        driver = bone.driver_add(prop, axis).driver
1398        driver.type = 'SCRIPTED'
1399        driver.use_self = True
1400
1401        driver.expression = expression
1402
1403    def execute(self, context):
1404        ob = context.object
1405        arm = ob.data
1406        pre_mode = ob.mode
1407        #if pre_mode != 'EDIT':
1408        #    override = context.copy()
1409        #    override['active_object'] = ob
1410        #    bpy.ops.object.mode_set(override, mode='EDIT')
1411
1412        morph   = ob.cm3d2_bone_morph
1413        sliders = ob.cm3d2_wide_slider
1414
1415        morph.scale   = self.scale
1416        sliders.scale = self.scale
1417
1418
1419
1420        #BoneMorph.SetPosition("KubiScl", "Bip01 Neck"        , 0.95, 1   , 1   , 1.05, 1   , 1   )
1421        #BoneMorph.SetPosition("KubiScl", "Bip01 Head"        , 0.8 , 1   , 1   , 1.2 , 1   , 1   )
1422        #BoneMorph.SetScale   ("UdeScl" , "Bip01 ? UpperArm"  , 0.85, 1   , 1   , 1.15, 1   , 1   )
1423        #BoneMorph.SetScale   ("EyeSclX", "Eyepos_L"          , 1   , 1   , 0.92, 1   , 1   , 1.08)
1424        #BoneMorph.SetScale   ("EyeSclX", "Eyepos_R"          , 1   , 1   , 0.92, 1   , 1   , 1.08)
1425        #BoneMorph.SetScale   ("EyeSclY", "Eyepos_L"          , 1   , 0.92, 1   , 1   , 1.08, 1   )
1426        #BoneMorph.SetScale   ("EyeSclY", "Eyepos_R"          , 1   , 0.92, 1   , 1   , 1.08, 1   )
1427        #BoneMorph.SetPosition("EyePosX", "Eyepos_R"          , 1   , 1   , 0.9 , 1   , 1   , 1.1 )
1428        #BoneMorph.SetPosition("EyePosX", "Eyepos_L"          , 1   , 1   , 0.9 , 1   , 1   , 1.1 )
1429        #BoneMorph.SetPosition("EyePosY", "Eyepos_R"          , 1   , 0.93, 1   , 1   , 1.07, 1   )
1430        #BoneMorph.SetPosition("EyePosY", "Eyepos_L"          , 1   , 0.93, 1   , 1   , 1.07, 1   )
1431        #BoneMorph.SetScale   ("HeadX"  , "Bip01 Head"        , 1   , 0.9 , 0.8 , 1   , 1.1 , 1.2 )
1432        #BoneMorph.SetScale   ("HeadY"  , "Bip01 Head"        , 0.8 , 0.9 , 1   , 1.2 , 1.1 , 1   )
1433        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine"       , 1   , 1   , 0.94, 1   , 1   , 1.06)
1434        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine0a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1435        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine1"      , 0.88, 1   , 1   , 1.12, 1   , 1   )
1436        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine1a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1437        #BoneMorph.SetPosition("DouPer" , "Bip01 Neck"        , 1.03, 1   , 1   , 0.97, 1   , 1   )
1438        #BoneMorph.SetPosition("DouPer" , "Bip01 ? Calf"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1439        #BoneMorph.SetPosition("DouPer" , "Bip01 ? Foot"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1440        #BoneMorph.SetScale   ("DouPer" , "Bip01 ? Thigh_SCL_", 0.87, 1   , 1   , 1.13, 1   , 1   )
1441        #BoneMorph.SetScale   ("DouPer" , "momotwist_?"       , 0.87, 1   , 1   , 1.13, 1   , 1   )
1442        #BoneMorph.SetScale   ("DouPer" , "Bip01 ? Calf_SCL_" , 0.87, 1   , 1   , 1.13, 1   , 1   )
1443        #BoneMorph.SetScale   ("DouPer" , "Bip01 ? UpperArm"  , 0.98, 1   , 1   , 1.02, 1   , 1   )
1444        #BoneMorph.SetPosition("sintyou", "Bip01 Spine"       , 1   , 1   , 0.85, 1   , 1   , 1.15)
1445        #BoneMorph.SetPosition("sintyou", "Bip01 Spine0a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1446        #BoneMorph.SetPosition("sintyou", "Bip01 Spine1"      , 0.88, 1   , 1   , 1.12, 1   , 1   )
1447        #BoneMorph.SetPosition("sintyou", "Bip01 Spine1a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1448        #BoneMorph.SetPosition("sintyou", "Bip01 Neck"        , 0.97, 1   , 1   , 1.03, 1   , 1   )
1449        #BoneMorph.SetPosition("sintyou", "Bip01 Head"        , 0.9 , 1   , 1   , 1.1 , 1   , 1   )
1450        #BoneMorph.SetPosition("sintyou", "Bip01 ? Calf"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1451        #BoneMorph.SetPosition("sintyou", "Bip01 ? Foot"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1452        #BoneMorph.SetScale   ("sintyou", "Bip01 ? UpperArm"  , 0.9 , 1   , 1   , 1.1 , 1   , 1   )
1453        #BoneMorph.SetScale   ("sintyou", "Bip01 ? Thigh_SCL_", 0.87, 1   , 1   , 1.13, 1   , 1   )
1454        #BoneMorph.SetScale   ("sintyou", "momotwist_?"       , 0.87, 1   , 1   , 1.13, 1   , 1   )
1455        #BoneMorph.SetScale   ("sintyou", "Bip01 ? Calf_SCL_" , 0.87, 1   , 1   , 1.13, 1   , 1   )
1456        #BoneMorph.SetScale   ("koshi"  , "Bip01 Pelvis_SCL_" , 1   , 0.8 , 0.92, 1   , 1.2 , 1.08)
1457        #BoneMorph.SetScale   ("koshi"  , "Bip01 Spine_SCL_"  , 1   , 1   , 1   , 1   , 1   , 1   )
1458        #BoneMorph.SetScale   ("koshi"  , "Hip_?"             , 1   , 0.96, 0.9 , 1   , 1.04, 1.1 )
1459        #BoneMorph.SetScale   ("koshi"  , "Skirt"             , 1   , 0.85, 0.88, 1   , 1.2 , 1.12)
1460        #BoneMorph.SetPosition("kata"   , "Bip01 ? Clavicle"  , 0.98, 1   , 0.5 , 1.02, 1   , 1.5 )
1461        #BoneMorph.SetScale   ("kata"   , "Bip01 Spine1a_SCL_", 1   , 1   , 0.95, 1   , 1   , 1.05)
1462        #BoneMorph.SetScale   ("west"   , "Bip01 Spine_SCL_"  , 1   , 0.95, 0.9 , 1   , 1.05, 1.1 )
1463        #BoneMorph.SetScale   ("west"   , "Bip01 Spine0a_SCL_", 1   , 0.85, 0.7 , 1   , 1.15, 1.3 )
1464        #BoneMorph.SetScale   ("west"   , "Bip01 Spine1_SCL_" , 1   , 0.9 , 0.85, 1   , 1.1 , 1.15)
1465        #BoneMorph.SetScale   ("west"   , "Bip01 Spine1a_SCL_", 1   , 0.95, 0.95, 1   , 1.05, 1.05)
1466        #BoneMorph.SetScale   ("west"   , "Skirt"             , 1   , 0.92, 0.88, 1   , 1.08, 1.12)
1467
1468
1469
1470        morph.SetPosition("KubiScl", "Bip01 Neck"         , 1.05, 1   , 1   )
1471        morph.SetPosition("KubiScl", "Bip01 Head"         , 1.2 , 1   , 1   )
1472                                                                      
1473        morph.SetScale   ("UdeScl" , "Bip01 ? UpperArm"   , 1.15, 1   , 1   )
1474                                                                      
1475        morph.SetScale   ("HeadX"  , "Bip01 Head"         , 1   , 1.1 , 1.2 )
1476        morph.SetScale   ("HeadY"  , "Bip01 Head"         , 1.2 , 1.1 , 1   )
1477        
1478        morph.SetPosition("sintyou", "Bip01 Spine"        , 1   , 1   , 1.15)
1479        morph.SetPosition("sintyou", "Bip01 Spine0a"      , 1.12, 1   , 1   )
1480        morph.SetPosition("sintyou", "Bip01 Spine1"       , 1.12, 1   , 1   )
1481        morph.SetPosition("sintyou", "Bip01 Spine1a"      , 1.12, 1   , 1   )
1482        morph.SetPosition("sintyou", "Bip01 Neck"         , 1.03, 1   , 1   )
1483        morph.SetPosition("sintyou", "Bip01 Head"         , 1.1 , 1   , 1   )
1484        morph.SetPosition("sintyou", "Bip01 ? Calf"       , 1.13, 1   , 1   )
1485        morph.SetPosition("sintyou", "Bip01 ? Foot"       , 1.13, 1   , 1   )
1486        morph.SetScale   ("sintyou", "Bip01 ? UpperArm"   , 1.1 , 1   , 1   )
1487        morph.SetScale   ("sintyou", "Bip01 ? Thigh_SCL_" , 1.13, 1   , 1   )
1488        morph.SetScale   ("sintyou", "momotwist_?"        , 1.13, 1   , 1   )
1489        morph.SetScale   ("sintyou", "Bip01 ? Calf_SCL_"  , 1.13, 1   , 1   )
1490                                                                            
1491        # for DouPer, any bone not a thigh or a decendant of one, it's values are inverted
1492        morph.SetPosition("DouPer" , "Bip01 Spine"        , 1, 1, (1-1.06)+1)
1493        morph.SetPosition("DouPer" , "Bip01 Spine0a"      , (1-1.12)+1, 1, 1)
1494        morph.SetPosition("DouPer" , "Bip01 Spine1"       , (1-1.12)+1, 1, 1)
1495        morph.SetPosition("DouPer" , "Bip01 Spine1a"      , (1-1.12)+1, 1, 1)
1496        morph.SetPosition("DouPer" , "Bip01 Neck"         , (1-0.97)+1, 1, 1)
1497        morph.SetScale   ("DouPer" , "Bip01 ? UpperArm"   , (1-1.02)+1, 1, 1)
1498        morph.SetPosition("DouPer" , "Bip01 ? Calf"       ,       1.13, 1, 1)
1499        morph.SetPosition("DouPer" , "Bip01 ? Foot"       ,       1.13, 1, 1)
1500        morph.SetScale   ("DouPer" , "Bip01 ? Thigh_SCL_" ,       1.13, 1, 1)
1501        morph.SetScale   ("DouPer" , "momotwist_?"        ,       1.13, 1, 1)
1502        morph.SetScale   ("DouPer" , "Bip01 ? Calf_SCL_"  ,       1.13, 1, 1)
1503
1504        # This has some issues            
1505        morph.SetScale   ("koshi"  , "Bip01 Pelvis_SCL_"  , 1   , 1.2 , 1.08)
1506        morph.SetScale   ("koshi"  , "Bip01 Spine_SCL_"   , 1   , 1   , 1   )
1507        morph.SetScale   ("koshi"  , "Hip_?"              , 1   , 1.04, 1.1 )
1508        morph.SetScale   ("koshi"  , "Skirt"              , 1   , 1.2 , 1.12)
1509                                     
1510        #morph.SetPosition("kata"   , "Bip01 ? Clavicle"   , 1.02, 1   , 1.5, default=0)
1511        morph.SetPosition("kata"   , "Bip01 ? Clavicle"   , 1.02, 1   , 1.5 , default=50)
1512        morph.SetScale   ("kata"   , "Bip01 Spine1a_SCL_" , 1   , 1   , 1.05, default=50)
1513                                        
1514        morph.SetScale   ("west"   , "Bip01 Spine_SCL_"   , 1   , 1.05, 1.1 )
1515        morph.SetScale   ("west"   , "Bip01 Spine0a_SCL_" , 1   , 1.15, 1.3 )
1516        morph.SetScale   ("west"   , "Bip01 Spine1_SCL_"  , 1   , 1.1 , 1.15)
1517        morph.SetScale   ("west"   , "Bip01 Spine1a_SCL_" , 1   , 1.05, 1.05)
1518        morph.SetScale   ("west"   , "Skirt"              , 1   , 1.08, 1.12)
1519        
1520        # WideSlider functions MUST be called AFTER all BoneMorph calls
1521        sliders.SetPosition("THIPOS"    , "Bip01 ? Thigh"     ,  0    ,  0.001,  0.001, axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1522        sliders.SetPosition("THI2POS"   , "Bip01 ? Thigh_SCL_",  0.001,  0.001,  0.001, axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1523        sliders.SetPosition("HIPPOS"    , "Hip_?"             ,  0.001,  0.001,  0.001, axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1524        sliders.SetPosition("MTWPOS"    , "momotwist_?"       ,  0.1  ,  0.1  , -0.1  , axisFlip=2                     ) #axisFlip=2 #axisFlip=2
1525        sliders.SetPosition("MMNPOS"    , "momoniku_?"        ,  0.1  ,  0.1  , -0.1  , axisFlip=1                     ) #axisFlip=1 #axisFlip=1
1526        sliders.SetPosition("SKTPOS"    , "Skirt"             , -0.1  , -0.1  ,  0.1  ,             axisOrder=[2, 1, 0]) #           #          
1527        sliders.SetPosition("SPIPOS"    , "Bip01 Spine"       , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1528        sliders.SetPosition("S0APOS"    , "Bip01 Spine0a"     , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1529        sliders.SetPosition("S1POS"     , "Bip01 Spine1"      , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1530        sliders.SetPosition("S1APOS"    , "Bip01 Spine1a"     , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1531        sliders.SetPosition("NECKPOS"   , "Bip01 Neck"        , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1532        sliders.SetPosition("CLVPOS"    , "Bip01 ? Clavicle"  , -0.1  ,  0.1  , -0.1  , axisFlip=2                     ) #axisFlip=2 #axisFlip=2
1533        sliders.SetPosition("MUNESUBPOS", "Mune_?_sub"        , -0.1  ,  0.1  ,  0.1  , axisFlip=1, axisOrder=[2, 1, 0]) #axisFlip=1 #axisFlip=2
1534        sliders.SetPosition("MUNEPOS"   , "Mune_?"            ,  0.1  , -0.1  , -0.1  , axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1535                                                                                                                                     
1536        sliders.SetScale   ("THISCL"    , "Bip01 ? Thigh"     , axisOrder=[0, 1, -1])
1537        sliders.SetScale   ("MTWSCL"    , "momotwist_?"       )
1538        sliders.SetScale   ("MMNSCL"    , "momoniku_?"        )
1539        sliders.SetScale   ("PELSCL"    , "Bip01 Pelvis_SCL_" )
1540        sliders.SetScale   ("THISCL2"   , "Bip01 ? Thigh_SCL_")#, axisOrder=[0, 1, -1])
1541        sliders.SetScale   ("CALFSCL"   , "Bip01 ? Calf"      )#, axisOrder=[0, 1, -1])
1542        sliders.SetScale   ("FOOTSCL"   , "Bip01 ? Foot"      )
1543        sliders.SetScale   ("SKTSCL"    , "Skirt"             )
1544        sliders.SetScale   ("SPISCL"    , "Bip01 Spine_SCL_"  )
1545        sliders.SetScale   ("S0ASCL"    , "Bip01 Spine0a_SCL_")
1546        sliders.SetScale   ("S1_SCL"    , "Bip01 Spine1_SCL_" )
1547        sliders.SetScale   ("S1ASCL"    , "Bip01 Spine1a_SCL_")
1548        sliders.SetScale   ("S1ABASESCL", "Bip01 Spine1a"     )#, axisOrder=[0, 1, -1]))
1549        sliders.SetScale   ("KATASCL"   , "Kata_?"            )
1550        sliders.SetScale   ("UPARMSCL"  , "Bip01 ? UpperArm"  )
1551        sliders.SetScale   ("FARMSCL"   , "Bip01 ? Forearm"   )
1552        sliders.SetScale   ("HANDSCL"   , "Bip01 ? Hand"      )
1553        sliders.SetScale   ("CLVSCL"    , "Bip01 ? Clavicle"  )
1554        sliders.SetScale   ("MUNESCL"   , "Mune_?"            )
1555        sliders.SetScale   ("MUNESUBSCL", "Mune_?_sub"        )
1556        sliders.SetScale   ("NECKSCL"   , "Bip01 Neck_SCL_"   )
1557        sliders.SetScale   ("HIPSCL"    , "Hip_?"             )
1558        sliders.SetScale   ("PELSCL"    , "Hip_?"             ) # hips are also scaled with pelvis
1559        
1560        if self.is_fix_thigh:
1561            bone = morph.GetPoseBone("momoniku_?")
1562            bone.rotation_quaternion[0] = 0.997714
1563            bone.rotation_quaternion[3] = -0.06758
1564            bone = morph.GetPoseBone("momoniku_?", flip=True)
1565            bone.rotation_quaternion[0] = 0.997714
1566            bone.rotation_quaternion[3] = 0.06758
1567            
1568        if self.is_drive_shape_keys:
1569            for child in ob.children:
1570                if child.type == 'MESH':
1571                    sks = child.data.shape_keys.key_blocks
1572                    self.driveShapeKey(sks.get('arml'    ), morph, 'ArmL'    , "ArmL     * 0.01")
1573                    self.driveShapeKey(sks.get('hara'    ), morph, 'Hara'    , "Hara     * 0.01")
1574                    self.driveShapeKey(sks.get('munel'   ), morph, 'MuneL'   , "MuneL    * 0.01", set_max=2)
1575                    self.driveShapeKey(sks.get('munes'   ), morph, 'MuneS'   , "MuneS    * 0.01")
1576                    self.driveShapeKey(sks.get('munetare'), morph, 'MuneTare', "MuneTare * 0.01", set_max=2)
1577                    self.driveShapeKey(sks.get('regfat'  ), morph, 'RegFat'  , "RegFat   * 0.01")
1578                    self.driveShapeKey(sks.get('regmeet' ), morph, 'RegMeet' , "RegMeet  * 0.01")
1579
1580        if True:
1581            bones = ob.pose.bones
1582            Mune_L = bones.get('Mune_L') or bones.get('Mune_*.L')
1583            Mune_R = bones.get('Mune_R') or bones.get('Mune_*.R')
1584            if Mune_L:
1585                Mune_L.rotation_mode = 'XYZ'
1586            if Mune_R:                  
1587                Mune_R.rotation_mode = 'XYZ'
1588            
1589            self.driveTwistBone(Mune_R, axis=0, expression="-(self.id_data.cm3d2_bone_morph.MuneUpDown-50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00060")
1590            self.driveTwistBone(Mune_L, axis=0, expression="+(self.id_data.cm3d2_bone_morph.MuneUpDown-50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00060")
1591            self.driveTwistBone(Mune_R, axis=2, expression="-(self.id_data.cm3d2_bone_morph.MuneYori  -50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00025")
1592            self.driveTwistBone(Mune_L, axis=2, expression="-(self.id_data.cm3d2_bone_morph.MuneYori  -50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00025")
1593
1594
1595
1596        
1597
1598        bpy.ops.object.mode_set(mode=pre_mode)
1599        
1600        return {'FINISHED'}
1601
1602
1603
1604@compat.BlRegister()
1605class DATA_PT_cm3d2_sliders(bpy.types.Panel):
1606    bl_space_type  = 'PROPERTIES'
1607    bl_region_type = 'WINDOW'
1608    bl_context     = 'data'
1609    bl_label       = 'CM3D2 Sliders'
1610    bl_idname      = 'DATA_PT_cm3d2_sliders'
1611
1612    @classmethod
1613    def poll(cls, context):
1614        ob = context.object
1615        if ob:
1616            arm = ob.data
1617        else:
1618            arm = None
1619        return arm and isinstance(arm, bpy.types.Armature) and ("Bip01" in arm.bones)
1620
1621    def draw(self, context):
1622        ob = context.object
1623        if ob:
1624            arm = ob.data
1625        else:
1626            arm = None
1627
1628        morph = ob.cm3d2_bone_morph
1629        self.layout.alignment = 'RIGHT'
1630        if compat.IS_LEGACY:
1631            flow = self.layout.column_flow(align=True)
1632        else:
1633            flow = self.layout.grid_flow(row_major=True, columns=2, align=True)
1634            flow.use_property_split    = True
1635            flow.use_property_decorate = False
1636        flow.prop(morph, 'height', text="Height", emboss=False)
1637        flow.prop(morph, 'weight', text="Weight", emboss=False)
1638        flow.prop(morph, 'bust'  , text="Bust"  , emboss=False)
1639        flow.prop(morph, 'cup'   , text="Cup"   , emboss=False)
1640        flow.prop(morph, 'waist' , text="Waist" , emboss=False)
1641        flow.prop(morph, 'hip'   , text="Hip"   , emboss=False)
1642                                
1643        row = self.layout.row()
1644        #row.enabled = bpy.ops.object.add_cm3d2_body_sliders.poll(context.copy())
1645        op = row.operator("object.add_cm3d2_body_sliders", text="Connect Sliders"    , icon=compat.icon('CONSTRAINT_BONE'))
1646        
1647        row = self.layout.row()
1648        #row.enabled = bpy.ops.object.cleanup_scale_bones.poll(context.copy())
1649        op = row.operator("object.cleanup_scale_bones"   , text="Cleanup Scale Bones", icon=compat.icon('X'              ))
1650
1651
1652
1653
1654@compat.BlRegister()
1655class DATA_PT_cm3d2_body_sliders(bpy.types.Panel):
1656    bl_space_type  = 'PROPERTIES'
1657    bl_region_type = 'WINDOW'
1658    bl_context     = 'data'
1659    bl_label       = 'Body Sliders'
1660    bl_idname      = 'DATA_PT_cm3d2_body_sliders'
1661    bl_parent_id   = 'DATA_PT_cm3d2_sliders'
1662    bl_options     = {'DEFAULT_CLOSED'}
1663
1664    @classmethod
1665    def poll(cls, context):
1666        return context.object and True
1667
1668    def draw(self, context):
1669        morph = context.object.cm3d2_bone_morph
1670        self.layout.operator('object.save_cm3d2_body_sliders_to_menu', icon=compat.icon('COPYDOWN'))
1671
1672        if compat.IS_LEGACY:
1673            flow = self.layout.column_flow(columns=1)
1674        else:
1675            self.layout.use_property_split = True
1676            flow = self.layout.column_flow()
1677        flow.scale_x = 0.5
1678        col = flow.column(align=True); col.prop(morph, 'HeadX'     , text="Face Width"  , slider=True)
1679        pass;                          col.prop(morph, 'HeadY'     , text="Face Height" , slider=True)
1680        col = flow.column(align=True); col.prop(morph, 'DouPer'    , text="Leg Length"  , slider=True)
1681        pass;                          col.prop(morph, 'sintyou'   , text="Height"      , slider=True)
1682        col = flow.column(align=True); col.prop(morph, 'BreastSize', text="Breast Size" , slider=True)
1683        pass;                          col.prop(morph, 'MuneTare'  , text="Breast Sag"  , slider=True)
1684        pass;                          col.prop(morph, 'MuneUpDown', text="Breast Pitch", slider=True)
1685        pass;                          col.prop(morph, 'MuneYori'  , text="Breast Yaw"  , slider=True)
1686        col = flow.column(align=True); col.prop(morph, 'west'      , text="Waist"       , slider=True)
1687        pass;                          col.prop(morph, 'Hara'      , text="Belly"       , slider=True)
1688        pass;                          col.prop(morph, 'kata'      , text="Shoulders"   , slider=True)
1689        pass;                          col.prop(morph, 'ArmL'      , text="Arm Size"    , slider=True)
1690        pass;                          col.prop(morph, 'UdeScl'    , text="Arm Length"  , slider=True)
1691        pass;                          col.prop(morph, 'KubiScl'   , text="Neck Length" , slider=True)
1692        col = flow.column(align=True); col.prop(morph, 'koshi'     , text="Hip"         , slider=True)
1693        pass;                          col.prop(morph, 'RegFat'    , text="Leg Fat"     , slider=True)
1694        pass;                          col.prop(morph, 'RegMeet'   , text="Leg Meat"    , slider=True)
1695                                       
1696
1697@compat.BlRegister()
1698class DATA_PT_cm3d2_wide_sliders(bpy.types.Panel):
1699    bl_space_type  = 'PROPERTIES'
1700    bl_region_type = 'WINDOW'
1701    bl_context     = 'data'
1702    bl_label       = 'Wide Sliders'
1703    bl_idname      = 'DATA_PT_cm3d2_wide_sliders'
1704    bl_parent_id   = 'DATA_PT_cm3d2_sliders'
1705    bl_options     = {'DEFAULT_CLOSED'}
1706
1707    @classmethod
1708    def poll(cls, context):
1709        return context.object and True
1710
1711    def draw(self, context):
1712        sliders = context.object.cm3d2_wide_slider
1713        
1714        if not compat.IS_LEGACY:
1715            self.layout.use_property_split = True
1716
1717        row = self.layout.row()
1718        if not compat.IS_LEGACY:
1719            row.use_property_decorate = False
1720        row.prop(sliders, "enable_all", text="Enable All Sliders")
1721
1722        if compat.IS_LEGACY:
1723            flow = self.layout.column_flow(columns=2)
1724        else:
1725            flow = self.layout.grid_flow(row_major=True)
1726        flow.scale_x = 0.5
1727
1728        def _transform_prop(name, pos_prop=None, scl_prop=None, pos_enabled=(True, True, True), scl_enabled=(True, True, True)):
1729            #lab = flow.row(align=True)
1730            #lab.alignment = 'RIGHT'
1731            #lab.label(text=name)
1732            #sub = lab.column()
1733            #sub.label(text=name)
1734            #sub.alignment = 'RIGHT'
1735            
1736            tab = flow.column()#align=True)
1737            #tab.alignment = 'LEFT'
1738            #tab.label(text=name)
1739
1740            col = tab.column(align=True)
1741            
1742            global used_name
1743            used_name = False
1744            def _vec_prop(type_name, prop_id, enabled_axes, axis_names):
1745                global used_name
1746                #vec = tab.row(align=True)
1747                #vec.label(text=type_name)
1748                #col = vec.column(align=True)
1749                for i in range(0, 3):
1750                    is_enabled  = enabled_axes[i] or sliders.enable_all
1751                    is_disabled = enabled_axes[i] == None
1752
1753                    if i == 0 and compat.IS_LEGACY:
1754                        if not used_name:
1755                            col.label(text=name)
1756                            used_name = True
1757                            
1758
1759                    row = col.row(align=True)
1760                    row.enabled = not is_disabled and is_enabled
1761                    
1762                    axis_name = axis_names[i]
1763                    if i == 0:
1764                        if compat.IS_LEGACY:
1765                            axis_name = axis_name + " " + type_name
1766                        else:
1767                            axis_name = type_name + " " + axis_name
1768                        if not used_name:
1769                            axis_name = name + " " + axis_name
1770                            used_name = True
1771
1772                    row.prop(
1773                        sliders                                , 
1774                        prop_id if not is_disabled else "empty", 
1775                        text   = axis_name                     , 
1776                        slider = not is_disabled               ,
1777                        emboss = not is_disabled               ,
1778                        index  = -1 if is_disabled else i      ,
1779                    )
1780
1781            if pos_prop:
1782                _vec_prop(iface_("Position"), pos_prop, pos_enabled, ("X", "Y", "Z"))
1783            if scl_prop:
1784                _vec_prop(iface_("Scale"   ), scl_prop, scl_enabled, ("X", "Y", "Z"))
1785
1786
1787        _transform_prop("Pelvis"       , None        , "PELSCL"                                                                           )
1788        _transform_prop("Hips"         , "HIPPOS"    , "HIPSCL"                                                                           )
1789        _transform_prop("Legs"         , "THIPOS"    , "THISCL"    , pos_enabled=(True , None , True ), scl_enabled=(True , True , None ) )
1790        _transform_prop("Thigh"        , "MTWPOS"    , "MTWSCL"                                                                           )
1791        _transform_prop("Rear Thigh"   , "MMNPOS"    , "MMNSCL"                                                                           )
1792        _transform_prop("Knee"         , "THI2POS"   , "THISCL2"                                      , scl_enabled=(True , True , False) )
1793        _transform_prop("Calf"         , None        , "CALFSCL"                                      , scl_enabled=(True , True , False) )
1794        _transform_prop("Foot"         , None        , "FOOTSCL"                                                                          )
1795        _transform_prop("Skirt"        , "SKTPOS"    , "SKTSCL"    , pos_enabled=(False, False, True )                                    )
1796        _transform_prop("Lower Abdomen", "SPIPOS"    , "SPISCL"    , pos_enabled=(True , False, True )                                    )
1797        _transform_prop("Upper Abdomen", "S0APOS"    , "S0ASCL"    , pos_enabled=(True , True , False)                                    )
1798        _transform_prop("Lower Chest"  , "S1POS"     , "S1_SCL"    , pos_enabled=(True , True , False)                                    )
1799        _transform_prop("Upper Chest"  , "S1APOS"    , "S1ASCL"    , pos_enabled=(True , True , False)                                    )
1800        _transform_prop("Upper Torso"  , None        , "S1ABASESCL"                                   , scl_enabled=(True , True , False) )
1801        _transform_prop("Breasts"      , "MUNEPOS"   , "MUNESCL"                                                                          )
1802        _transform_prop("Breasts Sub"  , "MUNESUBPOS", "MUNESUBSCL"                                                                       )
1803        _transform_prop("Neck"         , "NECKPOS"   , "NECKSCL"                                                                          )
1804        _transform_prop("Clavicle"     , "CLVPOS"    , "CLVSCL"                                                                           )
1805        _transform_prop("Shoulders"    , None        , "KATASCL"                                                                          )
1806        _transform_prop("Upper Arm"    , None        , "UPARMSCL"                                                                         )
1807        _transform_prop("Forearm"      , None        , "FARMSCL"                                                                          )
1808        _transform_prop("Hand"         , None        , "HANDSCL"                                                                          )              
1809
1810                                                           
1811
1812
1813@compat.BlRegister()
1814class CNV_OT_cleanup_scale_bones(bpy.types.Operator):
1815    bl_idname      = 'object.cleanup_scale_bones'
1816    bl_label       = "Cleanup Scale Bones"
1817    bl_description = "Remove scale bones from the active armature object"
1818    bl_options     = {'REGISTER', 'UNDO'}
1819
1820    scale = bpy.props.FloatProperty(name="Scale", default=5, min=0.1, max=100, soft_min=0.1, soft_max=100, step=100, precision=1, description="The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.")
1821
1822    is_keep_bones_with_children = bpy.props.BoolProperty(name="Keep bones with children", default=True, description="Will not remove scale bones that have children (for custom scale bones)")
1823    
1824    @classmethod
1825    def poll(cls, context):
1826        ob = context.object
1827        if ob:
1828            arm = ob.data
1829        else:
1830            arm = None
1831        has_arm  = arm and isinstance(arm, bpy.types.Armature)
1832        has_scl = False
1833        if has_arm:
1834            for bone in arm.edit_bones:
1835                if '_SCL_' in bone.name:
1836                    has_scl = True
1837                    break
1838        return has_arm and has_scl
1839
1840    def invoke(self, context, event):
1841        return context.window_manager.invoke_props_dialog(self)
1842
1843    def draw(self, context):
1844        self.layout.prop(self, 'is_keep_bones_with_children')
1845
1846    def execute(self, context):
1847        ob = context.object
1848        arm = ob.data
1849
1850        edit_bones = arm.edit_bones
1851        deleted_bones = {}
1852        for bone in edit_bones:
1853            if not '_SCL_' in bone.name:
1854                continue
1855            if self.is_keep_bones_with_children and len(bone.children) > 0:
1856                continue
1857            parent = edit_bones.get(bone.name.replace("_SCL_","")) or bone.parent
1858            if parent:
1859                parent['cm3d2_scl_bone'] = True
1860                deleted_bones[bone.name] = parent.name
1861                edit_bones.remove(bone)
1862
1863        for child in ob.children:
1864            vgroups = child.vertex_groups
1865            if vgroups and len(vgroups) > 0:
1866                for old_name, new_name in deleted_bones.items():
1867                    old_vgroup = vgroups.get(old_name)
1868                    if old_vgroup:
1869                        old_vgroup.name = new_name
1870
1871        return {'FINISHED'}
1872
1873
1874@compat.BlRegister()
1875class CNV_OT_save_cm3d2_body_sliders_to_menu(bpy.types.Operator):
1876    bl_idname      = 'object.save_cm3d2_body_sliders_to_menu'
1877    bl_label       = "Save CM3D2 Body Sliders to Menu"
1878    bl_description = "Remove scale bones from the active armature object"
1879    bl_options     = {'REGISTER', 'UNDO'}
1880
1881    is_overwrite = bpy.props.BoolProperty(name="Overwrite Existing", default=True)
1882
1883    @classmethod
1884    def poll(cls, context):
1885        ob = context.object
1886        if ob:
1887            arm = ob.data
1888        else:
1889            arm = None
1890        has_arm  = arm and isinstance(arm, bpy.types.Armature)
1891        return has_arm
1892
1893    def invoke(self, context, event):
1894        return context.window_manager.invoke_props_dialog(self)
1895
1896    def draw(self, context):
1897        self.layout.prop(self, 'is_overwrite')
1898        if self.is_overwrite:
1899            self.layout.label(text="Any existing data will be overwritten", icon=compat.icon('ERROR'))
1900
1901    def execute(self, context):
1902        ob = context.object
1903        menu_file_data = ob.cm3d2_menu
1904        morph = ob.cm3d2_bone_morph
1905
1906        def add_menu_prop_command(prop_name):
1907            menu_file_data.parse_list(
1908                ["prop",
1909                    prop_name,
1910                    str(int( getattr(morph, prop_name) ))
1911                ]
1912            )
1913
1914        if self.is_overwrite:
1915            menu_file_data.clear()
1916
1917            menu_file_data.version     = 1000
1918            menu_file_data.path        = os.path.relpath(bpy.data.filepath, start=bpy.path.abspath("//.."))
1919            menu_file_data.name        = f'{ob.name} {data_("Body")}'
1920            menu_file_data.category    = "set_body"
1921            menu_file_data.description = data_("Generated in blender using body sliders")
1922                                                                                            
1923            menu_file_data.parse_list(["メニューフォルダ", "system"                                 ])                               
1924            menu_file_data.parse_list(["category", "set_body"                               ])
1925            menu_file_data.parse_list(["priority", "100"                                    ])
1926            menu_file_data.parse_list(["icons"   , "_i_set_body_1_.tex"                     ])
1927            menu_file_data.parse_list([data_("属性追加")    , data_("クリックしても選択状態にしない")                        ])                      
1928            menu_file_data.parse_list(["name"    , menu_file_data.name                      ])
1929            menu_file_data.parse_list(["setumei" , data_("Generated in blender using body sliders")])
1930
1931        add_menu_prop_command('HeadX'     )
1932        add_menu_prop_command('HeadY'     )
1933        add_menu_prop_command('DouPer'    )
1934        add_menu_prop_command('sintyou'   )
1935        add_menu_prop_command('BreastSize')
1936        add_menu_prop_command('MuneTare'  )
1937        add_menu_prop_command('MuneUpDown')
1938        add_menu_prop_command('MuneYori'  )
1939        add_menu_prop_command('west'      )
1940        add_menu_prop_command('Hara'      )
1941        add_menu_prop_command('kata'      )
1942        add_menu_prop_command('ArmL'      )
1943        add_menu_prop_command('UdeScl'    )
1944        add_menu_prop_command('KubiScl'   )
1945        add_menu_prop_command('koshi'     )
1946        add_menu_prop_command('RegFat'    )
1947        add_menu_prop_command('RegMeet'   )
1948
1949        self.report(type={'INFO'}, message="Successfully saved properties to menu file data in Properties > Object Tab > CM3D2 Menu File")
1950
1951        return {'FINISHED'}
@compat.BlRegister()
class CNV_OT_decode_cm3d2_bone_names(bpy_types.Operator):
118@compat.BlRegister()
119class CNV_OT_decode_cm3d2_bone_names(bpy.types.Operator):
120    bl_idname = 'armature.decode_cm3d2_bone_names'
121    bl_label = "ボーン名をCM3D2用→Blender用に変換"
122    bl_description = "CM3D2で使われてるボーン名をBlenderで左右対称編集できるように変換します"
123    bl_options = {'REGISTER', 'UNDO'}
124
125    @classmethod
126    def poll(cls, context):
127        import re
128        ob = context.active_object
129        if ob:
130            if ob.type == 'ARMATURE':
131                arm = ob.data
132                for bone in arm.bones:
133                    if re.search(r'[_ ]([rRlL])[_ ]', bone.name):
134                        return True
135        return False
136
137    def execute(self, context):
138        ob = context.active_object
139        arm = ob.data
140        convert_count = 0
141        for bone in arm.bones:
142            bone_name = common.decode_bone_name(bone.name)
143            if bone_name != bone.name:
144                bone.name = bone_name
145                convert_count += 1
146        if convert_count == 0:
147            self.report(type={'WARNING'}, message="変換できる名前が見つかりませんでした")
148        else:
149            self.report(type={'INFO'}, message="ボーン名をBlender用に変換しました")
150        return {'FINISHED'}
bl_idname = 'armature.decode_cm3d2_bone_names'
bl_label = 'ボーン名をCM3D2用→Blender用に変換'
bl_description = 'CM3D2で使われてるボーン名をBlenderで左右対称編集できるように変換します'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
125    @classmethod
126    def poll(cls, context):
127        import re
128        ob = context.active_object
129        if ob:
130            if ob.type == 'ARMATURE':
131                arm = ob.data
132                for bone in arm.bones:
133                    if re.search(r'[_ ]([rRlL])[_ ]', bone.name):
134                        return True
135        return False
def execute(self, context):
137    def execute(self, context):
138        ob = context.active_object
139        arm = ob.data
140        convert_count = 0
141        for bone in arm.bones:
142            bone_name = common.decode_bone_name(bone.name)
143            if bone_name != bone.name:
144                bone.name = bone_name
145                convert_count += 1
146        if convert_count == 0:
147            self.report(type={'WARNING'}, message="変換できる名前が見つかりませんでした")
148        else:
149            self.report(type={'INFO'}, message="ボーン名をBlender用に変換しました")
150        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("ARMATURE_OT_decode_cm3d2_bone_names")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CNV_OT_encode_cm3d2_bone_names(bpy_types.Operator):
153@compat.BlRegister()
154class CNV_OT_encode_cm3d2_bone_names(bpy.types.Operator):
155    bl_idname = 'armature.encode_cm3d2_bone_names'
156    bl_label = "ボーン名をBlender用→CM3D2用に変換"
157    bl_description = "CM3D2で使われてるボーン名に元に戻します"
158    bl_options = {'REGISTER', 'UNDO'}
159
160    @classmethod
161    def poll(cls, context):
162        import re
163        ob = context.active_object
164        if ob:
165            if ob.type == 'ARMATURE':
166                arm = ob.data
167                for bone in arm.bones:
168                    if bone.name.count('*') == 1 and re.search(r'\.([rRlL])$', bone.name):
169                        return True
170        return False
171
172    def execute(self, context):
173        ob = context.active_object
174        arm = ob.data
175        convert_count = 0
176        for bone in arm.bones:
177            bone_name = common.encode_bone_name(bone.name)
178            if bone_name != bone.name:
179                bone.name = bone_name
180                convert_count += 1
181        if convert_count == 0:
182            self.report(type={'WARNING'}, message="変換できる名前が見つかりませんでした")
183        else:
184            self.report(type={'INFO'}, message="ボーン名をCM3D2用に戻しました")
185        return {'FINISHED'}
bl_idname = 'armature.encode_cm3d2_bone_names'
bl_label = 'ボーン名をBlender用→CM3D2用に変換'
bl_description = 'CM3D2で使われてるボーン名に元に戻します'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
160    @classmethod
161    def poll(cls, context):
162        import re
163        ob = context.active_object
164        if ob:
165            if ob.type == 'ARMATURE':
166                arm = ob.data
167                for bone in arm.bones:
168                    if bone.name.count('*') == 1 and re.search(r'\.([rRlL])$', bone.name):
169                        return True
170        return False
def execute(self, context):
172    def execute(self, context):
173        ob = context.active_object
174        arm = ob.data
175        convert_count = 0
176        for bone in arm.bones:
177            bone_name = common.encode_bone_name(bone.name)
178            if bone_name != bone.name:
179                bone.name = bone_name
180                convert_count += 1
181        if convert_count == 0:
182            self.report(type={'WARNING'}, message="変換できる名前が見つかりませんでした")
183        else:
184            self.report(type={'INFO'}, message="ボーン名をCM3D2用に戻しました")
185        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("ARMATURE_OT_encode_cm3d2_bone_names")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CNV_OT_copy_armature_bone_data_property(bpy_types.Operator):
188@compat.BlRegister()
189class CNV_OT_copy_armature_bone_data_property(bpy.types.Operator):
190    bl_idname = 'object.copy_armature_bone_data_property'
191    bl_label = "ボーン情報をコピー"
192    bl_description = "カスタムプロパティのボーン情報をクリップボードにコピーします"
193    bl_options = {'REGISTER', 'UNDO'}
194
195    @classmethod
196    def poll(cls, context):
197        ob = context.active_object
198        if ob:
199            if ob.type == 'ARMATURE':
200                arm = ob.data
201                if 'BoneData:0' in arm and 'LocalBoneData:0' in arm:
202                    return True
203        return False
204
205    def execute(self, context):
206        output_text = ""
207        ob = context.active_object.data
208        pass_count = 0
209        if 'BaseBone' in ob:
210            output_text += "BaseBone:" + ob['BaseBone'] + "\n"
211        for i in range(99999):
212            name = "BoneData:" + str(i)
213            if name in ob:
214                output_text += "BoneData:" + ob[name] + "\n"
215            else:
216                pass_count += 1
217            if 10 < pass_count:
218                break
219        pass_count = 0
220        for i in range(99999):
221            name = "LocalBoneData:" + str(i)
222            if name in ob:
223                output_text += "LocalBoneData:" + ob[name] + "\n"
224            else:
225                pass_count += 1
226            if 10 < pass_count:
227                break
228        context.window_manager.clipboard = output_text
229        self.report(type={'INFO'}, message="ボーン情報をクリップボードにコピーしました")
230        return {'FINISHED'}
bl_idname = 'object.copy_armature_bone_data_property'
bl_label = 'ボーン情報をコピー'
bl_description = 'カスタムプロパティのボーン情報をクリップボードにコピーします'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
195    @classmethod
196    def poll(cls, context):
197        ob = context.active_object
198        if ob:
199            if ob.type == 'ARMATURE':
200                arm = ob.data
201                if 'BoneData:0' in arm and 'LocalBoneData:0' in arm:
202                    return True
203        return False
def execute(self, context):
205    def execute(self, context):
206        output_text = ""
207        ob = context.active_object.data
208        pass_count = 0
209        if 'BaseBone' in ob:
210            output_text += "BaseBone:" + ob['BaseBone'] + "\n"
211        for i in range(99999):
212            name = "BoneData:" + str(i)
213            if name in ob:
214                output_text += "BoneData:" + ob[name] + "\n"
215            else:
216                pass_count += 1
217            if 10 < pass_count:
218                break
219        pass_count = 0
220        for i in range(99999):
221            name = "LocalBoneData:" + str(i)
222            if name in ob:
223                output_text += "LocalBoneData:" + ob[name] + "\n"
224            else:
225                pass_count += 1
226            if 10 < pass_count:
227                break
228        context.window_manager.clipboard = output_text
229        self.report(type={'INFO'}, message="ボーン情報をクリップボードにコピーしました")
230        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("OBJECT_OT_copy_armature_bone_data_property")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CNV_OT_paste_armature_bone_data_property(bpy_types.Operator):
233@compat.BlRegister()
234class CNV_OT_paste_armature_bone_data_property(bpy.types.Operator):
235    bl_idname = 'object.paste_armature_bone_data_property'
236    bl_label = "ボーン情報を貼付け"
237    bl_description = "カスタムプロパティのボーン情報をクリップボードから貼付けます"
238    bl_options = {'REGISTER', 'UNDO'}
239
240    @classmethod
241    def poll(cls, context):
242        ob = context.active_object
243        if ob:
244            if ob.type == 'ARMATURE':
245                clipboard = context.window_manager.clipboard
246                if 'BoneData:' in clipboard and 'LocalBoneData:' in clipboard:
247                    return True
248        return False
249
250    def execute(self, context):
251        ob = context.active_object.data
252        pass_count = 0
253        for i in range(99999):
254            name = "BoneData:" + str(i)
255            if name in ob:
256                del ob[name]
257            else:
258                pass_count += 1
259            if 10 < pass_count:
260                break
261        pass_count = 0
262        for i in range(99999):
263            name = "LocalBoneData:" + str(i)
264            if name in ob:
265                del ob[name]
266            else:
267                pass_count += 1
268            if 10 < pass_count:
269                break
270        bone_data_count = 0
271        local_bone_data_count = 0
272        for line in context.window_manager.clipboard.split("\n"):
273            if line.startswith('BaseBone:'):
274                ob['BaseBone'] = line[9:]  # len('BaseData:') == 9
275                continue
276
277            if line.startswith('BoneData:'):
278                if line.count(',') >= 4:
279                    name = "BoneData:" + str(bone_data_count)
280                    ob[name] = line[9:]  # len('BoneData:') == 9
281                    bone_data_count += 1
282                continue
283
284            if line.startswith('LocalBoneData:'):
285                if line.count(',') == 1:
286                    name = "LocalBoneData:" + str(local_bone_data_count)
287                    ob[name] = line[14:]  # len('LocalBoneData:') == 14
288                    local_bone_data_count += 1
289
290        self.report(type={'INFO'}, message="ボーン情報をクリップボードから貼付けました")
291        return {'FINISHED'}
bl_idname = 'object.paste_armature_bone_data_property'
bl_label = 'ボーン情報を貼付け'
bl_description = 'カスタムプロパティのボーン情報をクリップボードから貼付けます'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
240    @classmethod
241    def poll(cls, context):
242        ob = context.active_object
243        if ob:
244            if ob.type == 'ARMATURE':
245                clipboard = context.window_manager.clipboard
246                if 'BoneData:' in clipboard and 'LocalBoneData:' in clipboard:
247                    return True
248        return False
def execute(self, context):
250    def execute(self, context):
251        ob = context.active_object.data
252        pass_count = 0
253        for i in range(99999):
254            name = "BoneData:" + str(i)
255            if name in ob:
256                del ob[name]
257            else:
258                pass_count += 1
259            if 10 < pass_count:
260                break
261        pass_count = 0
262        for i in range(99999):
263            name = "LocalBoneData:" + str(i)
264            if name in ob:
265                del ob[name]
266            else:
267                pass_count += 1
268            if 10 < pass_count:
269                break
270        bone_data_count = 0
271        local_bone_data_count = 0
272        for line in context.window_manager.clipboard.split("\n"):
273            if line.startswith('BaseBone:'):
274                ob['BaseBone'] = line[9:]  # len('BaseData:') == 9
275                continue
276
277            if line.startswith('BoneData:'):
278                if line.count(',') >= 4:
279                    name = "BoneData:" + str(bone_data_count)
280                    ob[name] = line[9:]  # len('BoneData:') == 9
281                    bone_data_count += 1
282                continue
283
284            if line.startswith('LocalBoneData:'):
285                if line.count(',') == 1:
286                    name = "LocalBoneData:" + str(local_bone_data_count)
287                    ob[name] = line[14:]  # len('LocalBoneData:') == 14
288                    local_bone_data_count += 1
289
290        self.report(type={'INFO'}, message="ボーン情報をクリップボードから貼付けました")
291        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("OBJECT_OT_paste_armature_bone_data_property")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CNV_OT_remove_armature_bone_data_property(bpy_types.Operator):
294@compat.BlRegister()
295class CNV_OT_remove_armature_bone_data_property(bpy.types.Operator):
296    bl_idname = 'object.remove_armature_bone_data_property'
297    bl_label = "ボーン情報を削除"
298    bl_description = "カスタムプロパティのボーン情報を全て削除します"
299    bl_options = {'REGISTER', 'UNDO'}
300
301    @classmethod
302    def poll(cls, context):
303        ob = context.active_object
304        if ob:
305            if ob.type == 'ARMATURE':
306                arm = ob.data
307                if 'BoneData:0' in arm and 'LocalBoneData:0' in arm:
308                    return True
309        return False
310
311    def invoke(self, context, event):
312        return context.window_manager.invoke_props_dialog(self)
313
314    def draw(self, context):
315        self.layout.label(text="カスタムプロパティのボーン情報を全て削除します", icon='CANCEL')
316
317    def execute(self, context):
318        ob = context.active_object.data
319        pass_count = 0
320        if 'BaseBone' in ob:
321            del ob['BaseBone']
322        for i in range(99999):
323            name = "BoneData:" + str(i)
324            if name in ob:
325                del ob[name]
326            else:
327                pass_count += 1
328            if 10 < pass_count:
329                break
330        pass_count = 0
331        for i in range(99999):
332            name = "LocalBoneData:" + str(i)
333            if name in ob:
334                del ob[name]
335            else:
336                pass_count += 1
337            if 10 < pass_count:
338                break
339        self.report(type={'INFO'}, message="ボーン情報を削除しました")
340        return {'FINISHED'}
bl_idname = 'object.remove_armature_bone_data_property'
bl_label = 'ボーン情報を削除'
bl_description = 'カスタムプロパティのボーン情報を全て削除します'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
301    @classmethod
302    def poll(cls, context):
303        ob = context.active_object
304        if ob:
305            if ob.type == 'ARMATURE':
306                arm = ob.data
307                if 'BoneData:0' in arm and 'LocalBoneData:0' in arm:
308                    return True
309        return False
def invoke(self, context, event):
311    def invoke(self, context, event):
312        return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
314    def draw(self, context):
315        self.layout.label(text="カスタムプロパティのボーン情報を全て削除します", icon='CANCEL')
def execute(self, context):
317    def execute(self, context):
318        ob = context.active_object.data
319        pass_count = 0
320        if 'BaseBone' in ob:
321            del ob['BaseBone']
322        for i in range(99999):
323            name = "BoneData:" + str(i)
324            if name in ob:
325                del ob[name]
326            else:
327                pass_count += 1
328            if 10 < pass_count:
329                break
330        pass_count = 0
331        for i in range(99999):
332            name = "LocalBoneData:" + str(i)
333            if name in ob:
334                del ob[name]
335            else:
336                pass_count += 1
337            if 10 < pass_count:
338                break
339        self.report(type={'INFO'}, message="ボーン情報を削除しました")
340        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("OBJECT_OT_remove_armature_bone_data_property")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CNV_OT_add_cm3d2_twist_bones(bpy_types.Operator):
350@compat.BlRegister()
351class CNV_OT_add_cm3d2_twist_bones(bpy.types.Operator):
352    bl_idname      = 'object.add_cm3d2_twist_bones'
353    bl_label       = "Add CM3D2 Twist Bones"
354    bl_description = "Adds drivers to armature to automatically set twist-bone positions."
355    bl_options     = {'REGISTER', 'UNDO'}
356
357    scale = bpy.props.FloatProperty(name="Scale", default=5, min=0.1, max=100, soft_min=0.1, soft_max=100, step=100, precision=1, description="The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.")
358
359    #is_fix_thigh        = bpy.props.BoolProperty(name="Fix Thigh"       , default=False, description="Fix twist bone values for the thighs in motor-cycle pose")
360    #is_drive_shape_keys = bpy.props.BoolProperty(name="Drive Shape Keys", default=True, description="Connect sliders to mesh children's shape keys"           )
361    
362    fDegPer  = 1.1
363    fDegPer1 = 0.2 
364    fRota    = 0.5 
365                                            
366    @classmethod
367    def poll(cls, context):
368        ob = context.object
369        if ob:
370            arm = ob.data
371        else:
372            arm = None
373        has_arm  = arm and isinstance(arm, bpy.types.Armature) and ("Bip01" in arm.bones)
374        can_edit = (ob and ob.data == arm) or (arm and arm.is_editmode)
375        return has_arm and can_edit
376
377    def invoke(self, context, event):
378        self.scale = common.preferences().scale
379        return context.window_manager.invoke_props_dialog(self)
380
381    def draw(self, context):
382        self.layout.prop(self, 'scale'              )
383        #self.layout.prop(self, 'is_fix_thigh'       )
384        #self.layout.prop(self, 'is_drive_shape_keys')
385
386    def getPoseBone(self, ob, boneName, flip=False):
387        side = "R" if flip else "L"
388        
389        poseBoneList = ob.pose.bones
390        poseBone = poseBoneList.get(boneName.replace("?",side)) or poseBoneList.get(boneName.replace("?","*")+"."+side)
391        
392        if not poseBone:
393            print("WARNING: Could not find bone \""+boneName+"\"")
394            return
395
396        return poseBone
397
398    def driveShapeKey(self, shapekey, data, prop, expression, set_min=None, set_max=None):
399        if not shapekey:
400            return
401        driver = shapekey.driver_add('value').driver
402        driver.type = 'SCRIPTED'
403
404        driver_var = driver.variables.new() if len(driver.variables) < 1 else driver.variables[0]
405        driver_var.type = 'SINGLE_PROP'
406        driver_var.name = prop
407
408        driver_target = driver_var.targets[0]
409        driver_target.id_type = 'OBJECT'
410        driver_target.id = data.id_data
411        driver_target.data_path = data.path_from_id(prop)
412
413        driver.expression = expression
414
415        if set_min:
416            shapekey.slider_min = set_min
417        if set_max:
418            shapekey.slider_max = set_max
419
420    def driveTwistBone(self, ob, boneName, flip=False, prop='rotation_euler', axes=(1,2,0), expression=("", "", ""), infulencers=()):
421        bone = self.getPoseBone(ob, boneName, flip=flip)
422        if not bone:
423            return
424        if 'euler' in prop:
425            bone.rotation_mode = 'XYZ'
426
427        args = []
428        for name in infulencers:
429            if type(infulencers) == str:
430                name = infulencers
431            arg_bone = self.getPoseBone(ob, name, flip=flip)
432            if arg_bone:
433                args.append(arg_bone.name)
434            else:
435                args.append(name)
436            if type(infulencers) == str:
437                break
438
439        for i, index in enumerate(axes):
440            driver = bone.driver_add(prop, index).driver
441            driver.type = 'SCRIPTED'
442            driver.use_self = True
443            if type(expression) == str:
444                expr = expression
445            else:
446                expr = expression[i]
447            driver.expression = expr.format(*args, axis=['x','y','z'][index], index=index, i=i)
448
449    def constrainTwistBone(self, ob, boneName, targetName="", flip='BOTH', type='COPY_ROTATION', space=None, map=None, **kwargs):
450        if flip == 'BOTH':
451            const_l = self.constrainTwistBone(ob, boneName, targetName, flip=False, type=type, space=space, map=map, **kwargs)
452            const_r = self.constrainTwistBone(ob, boneName, targetName, flip=True , type=type, space=space, map=map, **kwargs)
453            return const_l, const_r
454
455        bone   = self.getPoseBone(ob, boneName  , flip=flip)
456        target = self.getPoseBone(ob, targetName, flip=flip)
457        if not bone or (not target and targetName):
458            return None
459
460        const = bone.constraints.new(type)
461        if target:
462            const.target = ob
463            const.subtarget = target.name
464        if space:
465            const.target_space = space
466            const.owner_space  = space
467        if map:
468            const.map_from = map
469            const.map_to   = map
470        for key, val in kwargs.items():
471            try:
472                setattr(const, key, val)
473            except Exception as e:
474                # TODO : Properly handle drivers in legacy version
475                self.report(type={'ERROR'}, message=e.args[0])
476
477        return const
478
479    def execute(self, context):
480        ob = context.object
481        arm = ob.data
482        pre_mode = ob.mode
483        if pre_mode != 'POSE':
484            bpy.ops.object.mode_set(mode='POSE')
485
486        # TODO : Fix shoulder constraints
487        # AutoTwist() ... Shoulder : 'TBody.cs' line 2775
488        self.constrainTwistBone(ob, 'Uppertwist_?', 'Bip01 ? UpperArm',
489            type  = 'TRANSFORM'                 ,
490            space = 'LOCAL'                     ,
491            map   = 'ROTATION'                  ,
492            use_motion_extrapolate = True       ,
493            from_rotation_mode = 'SWING_TWIST_Y',
494            mix_mode_rot       = 'REPLACE'      ,
495            from_max_y_rot =  1                 ,
496            to_max_y_rot   = -self.fDegPer
497        )
498        self.constrainTwistBone(ob, 'Uppertwist1_?', 'Bip01 ? UpperArm', 
499            type  = 'TRANSFORM'                 ,
500            space = 'LOCAL'                     ,
501            map   = 'ROTATION'                  ,
502            use_motion_extrapolate = True       ,
503            from_rotation_mode = 'SWING_TWIST_Y',
504            mix_mode_rot       = 'REPLACE'      ,
505            from_max_y_rot = 1                  ,
506            to_max_y_rot   = 1                  ,
507            influence      = self.fDegPer1
508        )
509        self.constrainTwistBone(ob, 'Kata_?', 'Bip01 ? UpperArm', 
510            space = 'WORLD',
511            influence = self.fRota
512        )
513
514        # AutoTwist() ... Wrist : 'TBody.cs' line 2793
515        self.constrainTwistBone(ob, 'Foretwist_?', 'Bip01 ? Hand',
516            type  = 'TRANSFORM'                 ,
517            space = 'LOCAL'                     ,
518            map   = 'ROTATION'                  ,
519            use_motion_extrapolate = True       ,
520            from_rotation_mode = 'SWING_TWIST_Y',
521            mix_mode_rot       = 'REPLACE'      ,
522            from_max_y_rot = 1                  ,
523            to_max_y_rot   = 1
524        )
525        self.constrainTwistBone(ob, 'Foretwist1_?',
526            type  = 'LIMIT_ROTATION',
527            space = 'LOCAL'         ,
528            use_limit_x = True      ,
529            use_limit_y = True      ,
530            use_limit_z = True      ,
531        )
532        self.constrainTwistBone(ob, 'Foretwist1_?', 'Bip01 ? Hand', 
533            type  = 'TRANSFORM'                 ,
534            space = 'LOCAL'                     ,
535            map   = 'ROTATION'                  ,
536            use_motion_extrapolate = True       ,
537            from_rotation_mode = 'SWING_TWIST_Y',
538            mix_mode_rot       = 'REPLACE'      ,
539            from_max_y_rot = 1                  ,
540            to_max_y_rot   = 1                  ,
541            influence      = 0.5
542        )
543
544        # TODO : Fix thigh constraints
545        # AutoTwist() ... Thigh : 'TBody.cs' line 2813
546        self.constrainTwistBone(ob, 'momotwist_?', 'Bip01 ? Thigh',
547            type  = 'TRANSFORM'                 ,
548            space = 'LOCAL'                     ,
549            map   = 'ROTATION'                  ,
550            use_motion_extrapolate = True       ,
551            from_rotation_mode = 'SWING_TWIST_Y',
552            mix_mode_rot       = 'REPLACE'      ,
553            from_max_y_rot =  1                 ,
554            to_max_y_rot   = -self.fDegPer
555        )
556        self.constrainTwistBone(ob, 'momotwist2_?', 'Bip01 ? Thigh',
557            type  = 'TRANSFORM'                 ,
558            space = 'LOCAL'                     ,
559            map   = 'ROTATION'                  ,
560            use_motion_extrapolate = True       ,
561            from_rotation_mode = 'SWING_TWIST_Y',
562            mix_mode_rot       = 'REPLACE'      ,
563            from_max_y_rot = 1                  ,
564            to_max_y_rot   = 1                  ,
565            influence      = 0.7
566        )
567
568
569        # MoveMomoniku() : 'TBody.cs' line 2841
570        self.driveTwistBone(ob, 'momoniku_?', flip=False, expression=("", "", "min(0,max(-8, self.id_data.pose.bones['{0}'].matrix.col[2].xyz.dot( (0,0,-1) ) *  10 * (pi/180) ))"), infulencers=('Bip01 ? Thigh'))
571        self.driveTwistBone(ob, 'momoniku_?', flip=True , expression=("", "", "min(8,max( 0, self.id_data.pose.bones['{0}'].matrix.col[2].xyz.dot( (0,0,-1) ) * -10 * (pi/180) ))"), infulencers=('Bip01 ? Thigh'))
572        self.constrainTwistBone(ob, 'Hip_?',
573            type  = 'LIMIT_ROTATION',
574            space = 'LOCAL'         ,
575            use_limit_x = True      ,
576            use_limit_y = True      ,
577            use_limit_z = True      ,
578        )
579        self.constrainTwistBone(ob, 'Hip_?', 'Bip01 ? Thigh', 
580            space = 'LOCAL_WITH_PARENT', 
581            influence = 0.67
582        )
583        
584        
585
586        bpy.ops.object.mode_set(mode=pre_mode)
587        
588        return {'FINISHED'}
bl_idname = 'object.add_cm3d2_twist_bones'
bl_label = 'Add CM3D2 Twist Bones'
bl_description = 'Adds drivers to armature to automatically set twist-bone positions.'
bl_options = {'REGISTER', 'UNDO'}
scale: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}>
fDegPer = 1.1
fDegPer1 = 0.2
fRota = 0.5
@classmethod
def poll(cls, context):
366    @classmethod
367    def poll(cls, context):
368        ob = context.object
369        if ob:
370            arm = ob.data
371        else:
372            arm = None
373        has_arm  = arm and isinstance(arm, bpy.types.Armature) and ("Bip01" in arm.bones)
374        can_edit = (ob and ob.data == arm) or (arm and arm.is_editmode)
375        return has_arm and can_edit
def invoke(self, context, event):
377    def invoke(self, context, event):
378        self.scale = common.preferences().scale
379        return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
381    def draw(self, context):
382        self.layout.prop(self, 'scale'              )
383        #self.layout.prop(self, 'is_fix_thigh'       )
384        #self.layout.prop(self, 'is_drive_shape_keys')
def getPoseBone(self, ob, boneName, flip=False):
386    def getPoseBone(self, ob, boneName, flip=False):
387        side = "R" if flip else "L"
388        
389        poseBoneList = ob.pose.bones
390        poseBone = poseBoneList.get(boneName.replace("?",side)) or poseBoneList.get(boneName.replace("?","*")+"."+side)
391        
392        if not poseBone:
393            print("WARNING: Could not find bone \""+boneName+"\"")
394            return
395
396        return poseBone
def driveShapeKey(self, shapekey, data, prop, expression, set_min=None, set_max=None):
398    def driveShapeKey(self, shapekey, data, prop, expression, set_min=None, set_max=None):
399        if not shapekey:
400            return
401        driver = shapekey.driver_add('value').driver
402        driver.type = 'SCRIPTED'
403
404        driver_var = driver.variables.new() if len(driver.variables) < 1 else driver.variables[0]
405        driver_var.type = 'SINGLE_PROP'
406        driver_var.name = prop
407
408        driver_target = driver_var.targets[0]
409        driver_target.id_type = 'OBJECT'
410        driver_target.id = data.id_data
411        driver_target.data_path = data.path_from_id(prop)
412
413        driver.expression = expression
414
415        if set_min:
416            shapekey.slider_min = set_min
417        if set_max:
418            shapekey.slider_max = set_max
def driveTwistBone( self, ob, boneName, flip=False, prop='rotation_euler', axes=(1, 2, 0), expression=('', '', ''), infulencers=()):
420    def driveTwistBone(self, ob, boneName, flip=False, prop='rotation_euler', axes=(1,2,0), expression=("", "", ""), infulencers=()):
421        bone = self.getPoseBone(ob, boneName, flip=flip)
422        if not bone:
423            return
424        if 'euler' in prop:
425            bone.rotation_mode = 'XYZ'
426
427        args = []
428        for name in infulencers:
429            if type(infulencers) == str:
430                name = infulencers
431            arg_bone = self.getPoseBone(ob, name, flip=flip)
432            if arg_bone:
433                args.append(arg_bone.name)
434            else:
435                args.append(name)
436            if type(infulencers) == str:
437                break
438
439        for i, index in enumerate(axes):
440            driver = bone.driver_add(prop, index).driver
441            driver.type = 'SCRIPTED'
442            driver.use_self = True
443            if type(expression) == str:
444                expr = expression
445            else:
446                expr = expression[i]
447            driver.expression = expr.format(*args, axis=['x','y','z'][index], index=index, i=i)
def constrainTwistBone( self, ob, boneName, targetName='', flip='BOTH', type='COPY_ROTATION', space=None, map=None, **kwargs):
449    def constrainTwistBone(self, ob, boneName, targetName="", flip='BOTH', type='COPY_ROTATION', space=None, map=None, **kwargs):
450        if flip == 'BOTH':
451            const_l = self.constrainTwistBone(ob, boneName, targetName, flip=False, type=type, space=space, map=map, **kwargs)
452            const_r = self.constrainTwistBone(ob, boneName, targetName, flip=True , type=type, space=space, map=map, **kwargs)
453            return const_l, const_r
454
455        bone   = self.getPoseBone(ob, boneName  , flip=flip)
456        target = self.getPoseBone(ob, targetName, flip=flip)
457        if not bone or (not target and targetName):
458            return None
459
460        const = bone.constraints.new(type)
461        if target:
462            const.target = ob
463            const.subtarget = target.name
464        if space:
465            const.target_space = space
466            const.owner_space  = space
467        if map:
468            const.map_from = map
469            const.map_to   = map
470        for key, val in kwargs.items():
471            try:
472                setattr(const, key, val)
473            except Exception as e:
474                # TODO : Properly handle drivers in legacy version
475                self.report(type={'ERROR'}, message=e.args[0])
476
477        return const
def execute(self, context):
479    def execute(self, context):
480        ob = context.object
481        arm = ob.data
482        pre_mode = ob.mode
483        if pre_mode != 'POSE':
484            bpy.ops.object.mode_set(mode='POSE')
485
486        # TODO : Fix shoulder constraints
487        # AutoTwist() ... Shoulder : 'TBody.cs' line 2775
488        self.constrainTwistBone(ob, 'Uppertwist_?', 'Bip01 ? UpperArm',
489            type  = 'TRANSFORM'                 ,
490            space = 'LOCAL'                     ,
491            map   = 'ROTATION'                  ,
492            use_motion_extrapolate = True       ,
493            from_rotation_mode = 'SWING_TWIST_Y',
494            mix_mode_rot       = 'REPLACE'      ,
495            from_max_y_rot =  1                 ,
496            to_max_y_rot   = -self.fDegPer
497        )
498        self.constrainTwistBone(ob, 'Uppertwist1_?', 'Bip01 ? UpperArm', 
499            type  = 'TRANSFORM'                 ,
500            space = 'LOCAL'                     ,
501            map   = 'ROTATION'                  ,
502            use_motion_extrapolate = True       ,
503            from_rotation_mode = 'SWING_TWIST_Y',
504            mix_mode_rot       = 'REPLACE'      ,
505            from_max_y_rot = 1                  ,
506            to_max_y_rot   = 1                  ,
507            influence      = self.fDegPer1
508        )
509        self.constrainTwistBone(ob, 'Kata_?', 'Bip01 ? UpperArm', 
510            space = 'WORLD',
511            influence = self.fRota
512        )
513
514        # AutoTwist() ... Wrist : 'TBody.cs' line 2793
515        self.constrainTwistBone(ob, 'Foretwist_?', 'Bip01 ? Hand',
516            type  = 'TRANSFORM'                 ,
517            space = 'LOCAL'                     ,
518            map   = 'ROTATION'                  ,
519            use_motion_extrapolate = True       ,
520            from_rotation_mode = 'SWING_TWIST_Y',
521            mix_mode_rot       = 'REPLACE'      ,
522            from_max_y_rot = 1                  ,
523            to_max_y_rot   = 1
524        )
525        self.constrainTwistBone(ob, 'Foretwist1_?',
526            type  = 'LIMIT_ROTATION',
527            space = 'LOCAL'         ,
528            use_limit_x = True      ,
529            use_limit_y = True      ,
530            use_limit_z = True      ,
531        )
532        self.constrainTwistBone(ob, 'Foretwist1_?', 'Bip01 ? Hand', 
533            type  = 'TRANSFORM'                 ,
534            space = 'LOCAL'                     ,
535            map   = 'ROTATION'                  ,
536            use_motion_extrapolate = True       ,
537            from_rotation_mode = 'SWING_TWIST_Y',
538            mix_mode_rot       = 'REPLACE'      ,
539            from_max_y_rot = 1                  ,
540            to_max_y_rot   = 1                  ,
541            influence      = 0.5
542        )
543
544        # TODO : Fix thigh constraints
545        # AutoTwist() ... Thigh : 'TBody.cs' line 2813
546        self.constrainTwistBone(ob, 'momotwist_?', 'Bip01 ? Thigh',
547            type  = 'TRANSFORM'                 ,
548            space = 'LOCAL'                     ,
549            map   = 'ROTATION'                  ,
550            use_motion_extrapolate = True       ,
551            from_rotation_mode = 'SWING_TWIST_Y',
552            mix_mode_rot       = 'REPLACE'      ,
553            from_max_y_rot =  1                 ,
554            to_max_y_rot   = -self.fDegPer
555        )
556        self.constrainTwistBone(ob, 'momotwist2_?', 'Bip01 ? Thigh',
557            type  = 'TRANSFORM'                 ,
558            space = 'LOCAL'                     ,
559            map   = 'ROTATION'                  ,
560            use_motion_extrapolate = True       ,
561            from_rotation_mode = 'SWING_TWIST_Y',
562            mix_mode_rot       = 'REPLACE'      ,
563            from_max_y_rot = 1                  ,
564            to_max_y_rot   = 1                  ,
565            influence      = 0.7
566        )
567
568
569        # MoveMomoniku() : 'TBody.cs' line 2841
570        self.driveTwistBone(ob, 'momoniku_?', flip=False, expression=("", "", "min(0,max(-8, self.id_data.pose.bones['{0}'].matrix.col[2].xyz.dot( (0,0,-1) ) *  10 * (pi/180) ))"), infulencers=('Bip01 ? Thigh'))
571        self.driveTwistBone(ob, 'momoniku_?', flip=True , expression=("", "", "min(8,max( 0, self.id_data.pose.bones['{0}'].matrix.col[2].xyz.dot( (0,0,-1) ) * -10 * (pi/180) ))"), infulencers=('Bip01 ? Thigh'))
572        self.constrainTwistBone(ob, 'Hip_?',
573            type  = 'LIMIT_ROTATION',
574            space = 'LOCAL'         ,
575            use_limit_x = True      ,
576            use_limit_y = True      ,
577            use_limit_z = True      ,
578        )
579        self.constrainTwistBone(ob, 'Hip_?', 'Bip01 ? Thigh', 
580            space = 'LOCAL_WITH_PARENT', 
581            influence = 0.67
582        )
583        
584        
585
586        bpy.ops.object.mode_set(mode=pre_mode)
587        
588        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("OBJECT_OT_add_cm3d2_twist_bones")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
def get_axis_index_vector(axis_index, size=3):
681def get_axis_index_vector(axis_index, size=3):
682    vec = mathutils.Vector.Fill(size)
683    vec[axis_index] = 1
684    return vec
def get_axis_order_matrix(axis_order):
686def get_axis_order_matrix(axis_order):
687    size = len(axis_order)
688    mat = mathutils.Matrix.Diagonal( [0] * size )
689    for index, axis_index in enumerate(axis_order):
690        mat[index][axis_index] = 1
691    return mathutils.Matrix(mat)
def get_vector_axis_index(vec):
693def get_vector_axis_index(vec):
694    length = len(vec)
695    for axis_index, axis_value in enumerate(vec):
696        if axis_index == length-1:
697            return axis_index
698        else:
699            axis_value = abs(axis_value)
700            largest = True
701            for i in range(axis_index+1, length):
702                if axis_value < abs(vec[i]):
703                    largest = False
704                    break
705            if largest:
706                return axis_index
def get_matrix_axis_order(mat):
708def get_matrix_axis_order(mat):
709    return [ get_vector_axis_index(row) for row in mat ]
@compat.BlRegister()
class CNV_PG_cm3d2_bone_morph(bpy_types.PropertyGroup):
 713@compat.BlRegister()
 714class CNV_PG_cm3d2_bone_morph(bpy.types.PropertyGroup):
 715    bl_idname = 'CNV_PG_cm3d2_bone_morph'
 716
 717    scale = bpy.props.FloatProperty(name="Scale", default=5, min=0.1, max=100, soft_min=0.1, soft_max=100, step=100, precision=1, description="The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.")
 718
 719    def __calcMeasurements(self, context):                                               
 720        num    =  1340                         +                   self.sintyou * 4    +      self.DouPer * (1 + self.sintyou * 0.005) + self.KubiScl * 0.5 + self.HeadY * 0.5
 721        num2   =    55 * self.RegFat           + 50              * self.sintyou * 0.5  + 50 * self.DouPer * 0.4
 722        num3   =    55 * self.RegMeet          + 50              * self.sintyou * 0.5  + 50 * self.DouPer * 0.4
 723        num4   =    10 * self.UdeScl   * 0.1                                                             
 724        num5   =     5 * self.ArmL             +  5              * self.sintyou * 1    +  5 * self.UdeScl * 0.5
 725        num6   =    70 * self.Hara             + 50              * self.sintyou * 0.7  + 50 * self.Hara   * self.west * 0.005
 726        num7   =    10 * self.MuneL    * 2                                                                           
 727        num8   =  num7 * self.MuneTare * 0.005                                                                       
 728        num9   =    20 * self.west     * 0.5   + 15 * self.west  * self.sintyou * 0.02 + 15 * self.DouPer * self.west * 0.01
 729        num10  =    10 * self.koshi            +  7 * self.koshi * self.sintyou * 0.04
 730        num11  =     4 * self.kata                        
 731        num13  =    70                         +      self.MuneL                * 0.31 +                    self.west * 0.02      
 732        
 733        num13 -=     5 * (self.MuneS / 100)                
 734        num12  = 38000 + num2 + num3 + num4 + num5 + num6 + num7 + num8 + num9 + num10 + num11
 735        
 736        self.private_height = num   /   10
 737        self.private_weight = num12 / 1000
 738        self.private_bust   = num13
 739        self.private_waist  = 40 + self.west  * 0.25 + self.Hara   * 0.35
 740        self.private_hip    = 65 + self.koshi * 0.3  + self.RegFat * 0.025 + self.RegMeet * 0.025
 741             
 742        if   num13 <   80:
 743            self.private_cup = "A"
 744        elif num13 >= 110:
 745            self.private_cup = "N"
 746        else:
 747            cup_sizes = ['B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M']
 748            self.private_cup = cup_sizes[int((num13 - 80) / 2.5)]
 749
 750        self.private_height = int(self.private_height) * 0.01 / context.scene.unit_settings.scale_length
 751        self.private_weight = int(self.private_weight)        / context.scene.unit_settings.scale_length ** 3
 752        self.private_bust   = int(self.private_bust  ) * 0.01 / context.scene.unit_settings.scale_length
 753        self.private_waist  = int(self.private_waist ) * 0.01 / context.scene.unit_settings.scale_length
 754        self.private_hip    = int(self.private_hip   ) * 0.01 / context.scene.unit_settings.scale_length
 755        self.private_cup = "'" + self.private_cup + "'"
 756
 757        return None
 758
 759    def __calcMune(self, context):
 760        if self.BreastSize >= 0:
 761            self.MuneL = self.BreastSize
 762            self.MuneS = 0
 763        else:
 764            self.MuneL = 0
 765            self.MuneS = (self.BreastSize / -30) * 100
 766        self.__calcMuneTare(context)
 767        return None
 768
 769    def __calcMuneTare(self, context):
 770        if self.MuneTare > self.MuneL:
 771            self.MuneTare = self.MuneL
 772        else:
 773            self.__calcMeasurements(context)
 774
 775    HeadX      = bpy.props.FloatProperty(name="HeadX"     , description="Size of face (left to right)", default=  50, min=   0, max= 100, step=100, precision=0)
 776    HeadY      = bpy.props.FloatProperty(name="HeadY"     , description="Size of face (up and down)"  , default=  50, min=   0, max= 100, step=100, precision=0, update=__calcMeasurements)
 777    DouPer     = bpy.props.FloatProperty(name="DouPer"    , description="Leg length"                  , default=  50, min=-100, max= 500, step=100, precision=0, update=__calcMeasurements)
 778    sintyou    = bpy.props.FloatProperty(name="sintyou"   , description="Height"                      , default=  50, min=-300, max= 100, step=100, precision=0, update=__calcMeasurements)
 779    BreastSize = bpy.props.FloatProperty(name="BreastSize", description="Breast size"                 , default=  50, min= -30, max= 195, step=100, precision=0, update=__calcMune        )
 780    MuneTare   = bpy.props.FloatProperty(name="MuneTare"  , description="Breast sagging level"        , default=  50, min=   0, max= 195, step=100, precision=0, update=__calcMuneTare    )
 781    MuneUpDown = bpy.props.FloatProperty(name="MuneUpDown", description="Position of the nipple"      , default=  10, min= -50, max= 300, step=100, precision=0)
 782    MuneYori   = bpy.props.FloatProperty(name="MuneYori"  , description="Direction of breast"         , default=  40, min= -50, max= 200, step=100, precision=0)
 783    west       = bpy.props.FloatProperty(name="west"      , description="Waist"                       , default=  50, min= -30, max= 100, step=100, precision=0, update=__calcMeasurements)
 784    Hara       = bpy.props.FloatProperty(name="Hara"      , description="Belly"                       , default=  20, min=   0, max= 200, step=100, precision=0, update=__calcMeasurements)
 785    kata       = bpy.props.FloatProperty(name="kata"      , description="Shoulder width"              , default=  50, min=-400, max= 100, step=100, precision=0, update=__calcMeasurements)
 786    ArmL       = bpy.props.FloatProperty(name="ArmL"      , description="Size of arms"                , default=  20, min=   0, max= 100, step=100, precision=0, update=__calcMeasurements)
 787    UdeScl     = bpy.props.FloatProperty(name="UdeScl"    , description="Length of arms"              , default=  50, min=   0, max= 100, step=100, precision=0, update=__calcMeasurements)
 788    KubiScl    = bpy.props.FloatProperty(name="KubiScl"   , description="Length of neck"              , default=  50, min=   0, max= 200, step=100, precision=0, update=__calcMeasurements)
 789    koshi      = bpy.props.FloatProperty(name="koshi"     , description="Hip"                         , default=  50, min=-160, max= 200, step=100, precision=0, update=__calcMeasurements)
 790    RegFat     = bpy.props.FloatProperty(name="RegFat"    , description="Leg thickness"               , default=  40, min=   0, max= 100, step=100, precision=0, update=__calcMeasurements)
 791    RegMeet    = bpy.props.FloatProperty(name="RegMeet"   , description="Leg definition"              , default=  40, min=   0, max= 100, step=100, precision=0, update=__calcMeasurements)
 792    MuneL      = bpy.props.FloatProperty(name="MuneL"     , description="munel shapekey value"        , default=  50, min=   0)
 793    MuneS      = bpy.props.FloatProperty(name="MuneS"     , description="munes shapekey value"        , default=   0, min=   0)
 794
 795    def __measurementSetter(self, value):
 796        self.__calcMeasurements(bpy.context)
 797        return None
 798    
 799    def __newGetter(attr, recalc=False):
 800        def __getter(self):
 801            if recalc:
 802                self.__calcMeasurements(bpy.context)
 803            return getattr(self, attr)
 804        return __getter
 805
 806    private_height  = bpy.props.FloatProperty (name="private_height", options={'HIDDEN'})
 807    private_weight  = bpy.props.FloatProperty (name="private_weight", options={'HIDDEN'})
 808    private_bust    = bpy.props.FloatProperty (name="private_bust"  , options={'HIDDEN'})
 809    private_waist   = bpy.props.FloatProperty (name="private_waist" , options={'HIDDEN'})
 810    private_hip     = bpy.props.FloatProperty (name="private_hip"   , options={'HIDDEN'})
 811    private_cup     = bpy.props.StringProperty(name="private_cup"   , options={'HIDDEN'})
 812                                                     
 813    height   = bpy.props.FloatProperty (name="height", precision=3, unit=compat.unit('LENGTH'), set=__measurementSetter, get=__newGetter('private_height', recalc=True))
 814    weight   = bpy.props.FloatProperty (name="weight", precision=3, unit=compat.unit('MASS'  ), set=__measurementSetter, get=__newGetter('private_weight'))
 815    bust     = bpy.props.FloatProperty (name="bust"  , precision=3, unit=compat.unit('LENGTH'), set=__measurementSetter, get=__newGetter('private_bust'  ))
 816    waist    = bpy.props.FloatProperty (name="waist" , precision=3, unit=compat.unit('LENGTH'), set=__measurementSetter, get=__newGetter('private_waist' ))
 817    hip      = bpy.props.FloatProperty (name="hip"   , precision=3, unit=compat.unit('LENGTH'), set=__measurementSetter, get=__newGetter('private_hip'   ))
 818    cup      = bpy.props.StringProperty(name="cup"   ,                                          set=__measurementSetter, get=__newGetter('private_cup'   ))
 819                                                     
 820    def GetArmature(self, override=None):
 821        override = override or bpy.context.copy()
 822        ob = self.id_data
 823        override.update({
 824            'selected_objects'         : {ob},
 825            'selected_editable_objects': {ob},
 826            'editable_bones'           : {}  ,
 827            'selected_bones'           : {}  ,
 828            'selected_editable_bones'  : {}  ,
 829            'active_object'            : ob  ,
 830            'edit_object'              : ob  ,
 831        })
 832        return self.id_data, override
 833
 834        #armature = override['object']
 835        #if not armature or armature.type != 'ARMATURE':
 836        #    print("ERROR: Active object is not an armature")
 837        #    return None, None
 838        #
 839        #for area in bpy.context.screen.areas:
 840        #    #print(area,area.type)
 841        #    if area.type == 'OUTLINER':
 842        #        override.update({
 843        #            'blend_data': None,
 844        #            'area': area,
 845        #            'scene': bpy.context.scene,
 846        #            'screen': None,
 847        #            'space_data': area.spaces[0],
 848        #            'window': None,
 849        #            'window_manager': None,
 850        #            'object': armature,
 851        #            'active_object': armature,
 852        #            'edit_object': armature,
 853        #        })
 854        #        break
 855        #
 856        #if override['area'].type != 'OUTLINER':
 857        #    print("ERROR: There is no 3D View Present in the current workspace")
 858        #    return None, None
 859        #
 860        #if False:
 861        #    print("\n")
 862        #    for k,v in override.items():
 863        #        print(k)
 864        #    print("\n")
 865        #return armature, override
 866
 867    def GetPoseBone(self, boneName, flip=False, override=None):
 868        context = bpy.context
 869        
 870        side = "L" if flip else "R"
 871        armature, override = self.GetArmature()
 872        if not armature:
 873            return
 874        
 875        poseBoneList = armature.pose.bones
 876        poseBone = poseBoneList.get(boneName.replace("?",side)) or poseBoneList.get(boneName.replace("?","*")+"."+side)
 877
 878        # check if _SCL_ bone needs to be created
 879        if not poseBone and "_SCL_" in boneName:
 880            boneList = armature.data.edit_bones
 881            bpy.ops.object.mode_set(mode='EDIT')
 882            print("Make Scale Bone: "+boneName)
 883            copyBone = boneList.get(boneName.replace("_SCL_","").replace("?",side)) or boneList.get(boneName.replace("_SCL_","").replace("?","*")+"."+side)
 884            if copyBone:
 885                #bpy.ops.armature.select_all(override, action='DESELECT')
 886                #for v in context.selected_bones:
 887                #    v.select = False
 888                #    v.select_head = False
 889                #    v.select_tail = False
 890                #copyBone.select = True
 891                #copyBone.select_head = True
 892                #copyBone.select_tail = True
 893                #boneList.active = copyBone
 894                #bpy.ops.armature.duplicate(override)
 895                new_name = copyBone.basename+"_SCL_" + ("."+side if ("."+side) in copyBone.name else "")
 896                bone = armature.data.edit_bones.new(new_name)
 897                bone.parent = copyBone
 898                bone.head = copyBone.head
 899                bone.tail = copyBone.tail
 900                bone.roll = copyBone.roll
 901                bone.show_wire = True
 902                bone.use_deform = True
 903                copyBone['cm3d2_scl_bone'] = False
 904                bone['cm3d2_scl_bone'] = False
 905                
 906                # rename vertex groups
 907                for child in armature.children:
 908                    if child.type == 'MESH':
 909                        vertexGroup = child.vertex_groups.get(copyBone.name)
 910                        if vertexGroup:
 911                            vertexGroup.name = bone.name
 912        
 913        bpy.ops.object.mode_set(mode='POSE')
 914        poseBone = poseBone or poseBoneList.get(boneName.replace("?", side)) or poseBoneList.get(boneName.replace("?","*")+"."+side)
 915        
 916        if not poseBone:
 917            print("WARNING: Could not find bone \""+boneName+"\"")
 918            return
 919
 920        return poseBone
 921
 922    def GetDrivers(self, data_path, prop):
 923        id_data = self.id_data
 924        drivers = [None, None, None]
 925        if id_data and id_data.animation_data:
 926            for f in id_data.animation_data.drivers:
 927                fName = f.data_path
 928                #print("check",fName, "for", '["%s"].%s' % (data_path, prop))
 929                if '["{path}"].{attr}'.format(path=data_path, attr=prop) in fName:
 930                    #print("VALID!")
 931                    drivers[f.array_index] = f.driver
 932        return drivers
 933
 934
 935    def AddPositionDriver(self, prop, bone, drivers, axis, value, default=50):
 936        value = value-1
 937        if value == 0:
 938            return
 939        
 940        driver = drivers[axis]
 941        prefix = " + "
 942        
 943        if not driver:
 944            driver = bone.driver_add("location", axis).driver
 945            driver.type = 'SCRIPTED'
 946            
 947            parent_length_var = driver.variables.new()
 948            parent_length_var.type = 'SINGLE_PROP'
 949            parent_length_var.name = "parent_length"
 950            
 951            driver_target = parent_length_var.targets[0]
 952            driver_target.id_type = 'ARMATURE'
 953            driver_target.id = bone.parent.bone.id_data if not compat.IS_LEGACY else bone.parent.bone.id_data.data
 954            driver_target.data_path = bone.parent.bone.path_from_id("length")
 955
 956            head_var = driver.variables.new()
 957            head_var.type = 'SINGLE_PROP'
 958            head_var.name = "head"
 959
 960            driver_target = head_var.targets[0]
 961            driver_target.id_type = 'OBJECT'
 962            driver_target.id = bone.id_data
 963            driver_target.data_path = bone.path_from_id("head") + f"[{axis}]"
 964            
 965            if axis == 1: # if y axis, include parent bone's length, because head coords are based on parent's tail
 966                driver.expression = "(parent_length+head)_"
 967            else:
 968                driver.expression = "head_"
 969            prefix = " * ("
 970            
 971            #driver.expression = "-{direction} + {direction}", direction=rest_value
 972
 973        driver_var = driver.variables.get(prop)
 974        if not driver_var:
 975            driver_var = driver.variables.new()
 976            driver_var.type = 'SINGLE_PROP'
 977            driver_var.name = prop
 978
 979            driver_target = driver_var.targets[0]
 980            driver_target.id_type = 'OBJECT'
 981            driver_target.id = bone.id_data
 982            driver_target.data_path = bone.id_data.cm3d2_bone_morph.path_from_id(prop)
 983        
 984        # if prop isn't already a factor
 985        if not prop in driver.expression:
 986            driver.expression = driver.expression[:-1] + prefix + f"({prop}-{default})*{value/(100-default)})"
 987            
 988        return
 989
 990    def AddScaleDriver(self, prop, bone, drivers, axis, value, default=50):
 991        value = value-1
 992        if value == 0:
 993            return
 994        
 995        driver = drivers[axis]
 996        
 997        # if just created
 998        if not driver:
 999            driver = bone.driver_add("scale", axis).driver
1000            driver.type = 'SCRIPTED'
1001            driver.expression = "(1)"
1002
1003        driver_var = driver.variables.get(prop) 
1004        if not driver_var:
1005            driver_var = driver.variables.new()
1006            driver_var.type = 'SINGLE_PROP'
1007            driver_var.name = prop
1008
1009            driver_target = driver_var.targets[0]
1010            driver_target.id_type = 'OBJECT'
1011            driver_target.id = bone.id_data
1012            driver_target.data_path = bone.id_data.cm3d2_bone_morph.path_from_id(prop)
1013        
1014        # if prop isn't already a factor
1015        if not prop in driver.expression:
1016            driver.expression = driver.expression[:-1] + f" + ({prop}-{default})*{value/(100-default)})"
1017 
1018        return
1019
1020    def SetPosition(self, prop, boneName, x, y, z, default=50):
1021        # Check if object has this property
1022        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1023        #    if ONLY_FIX_SETTINGS:
1024        #        return
1025        #x = (1-x)+1
1026        #y = (1-y)+1
1027        #z = (1-z)+1
1028
1029        #loc.x, loc.y, loc.z = loc.z, -loc.x, loc.y
1030        #x, y, z = z, x, y
1031
1032        vec = mathutils.Vector((x, y, z))
1033        vec = compat.convert_cm_to_bl_slider_space(vec)
1034
1035        pose_bone = self.GetPoseBone(boneName)
1036        if pose_bone:                                                       
1037            #rest_pos = pose_bone.bone.head_local + (pose_bone.bone.head_local - pose_bone.bone.parent.head_local) 
1038            #rest_pos = compat.mul(pose_bone.bone.matrix_local.inverted(), rest_pos)
1039            #vec = mathutils.Vector((x, y, z))# * self.scale
1040            #if pose_bone.parent:
1041            #    vec = compat.convert_cm_to_bl_bone_space(vec)
1042            #    vec = compat.mul(pose_bone.parent.bone.matrix_local, vec)
1043            #else:
1044            #    vec = compat.convert_cm_to_bl_space(vec)
1045            #vec = compat.mul(pose_bone.bone.matrix_local.inverted(), vec)
1046
1047            pose_bone.bone.use_local_location = False
1048            drivers = self.GetDrivers(pose_bone.name,'location')
1049                                                        
1050            self.AddPositionDriver(prop, pose_bone, drivers, 0, vec[0], default=default)
1051            self.AddPositionDriver(prop, pose_bone, drivers, 1, vec[1], default=default)
1052            self.AddPositionDriver(prop, pose_bone, drivers, 2, vec[2], default=default)
1053                                                                   
1054        # repeat for left side
1055        if '?' in boneName:
1056            pose_bone = self.GetPoseBone(boneName, flip=True)
1057            if pose_bone:
1058                #rest_pos = pose_bone.bone.head_local + pose_bone.bone.head
1059                #rest_pos = compat.mul(pose_bone.bone.matrix_local.inverted(), rest_pos)
1060                #vec = mathutils.Vector((x, y, z))# * self.scale
1061                #if pose_bone.parent:
1062                #    vec = compat.convert_cm_to_bl_bone_space(vec)
1063                #    vec = compat.mul(pose_bone.parent.bone.matrix_local, vec)
1064                #else:
1065                #    vec = compat.convert_cm_to_bl_space(vec)
1066                #vec = compat.mul(pose_bone.bone.matrix_local.inverted(), vec)
1067                
1068                pose_bone.bone.use_local_location = False
1069                drivers = self.GetDrivers(pose_bone.name,'location')
1070
1071                vec[2] = (1-vec[2])+1 # mirror z axis
1072                
1073                self.AddPositionDriver(prop, pose_bone, drivers, 0, vec[0], default=default)
1074                self.AddPositionDriver(prop, pose_bone, drivers, 1, vec[1], default=default)
1075                self.AddPositionDriver(prop, pose_bone, drivers, 2, vec[2], default=default)
1076                                                                            
1077        return
1078
1079    def SetScale(self, prop, boneName, x, y, z, default=50):
1080        # Check if object has this property
1081        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1082        #    if ONLY_FIX_SETTINGS:
1083        #        return
1084
1085        #x, y, z = z, abs(-x), y
1086
1087        mat = mathutils.Matrix.Diagonal((x, y, z)).to_4x4()
1088        mat = compat.convert_cm_to_bl_bone_rotation(mat)
1089        x, y, z = -mat.to_scale()
1090
1091        bone = self.GetPoseBone(boneName)
1092        if bone:
1093            drivers = self.GetDrivers(bone.name,'scale')
1094            
1095            self.AddScaleDriver(prop, bone, drivers, 0, x, default=default)
1096            self.AddScaleDriver(prop, bone, drivers, 1, y, default=default)
1097            self.AddScaleDriver(prop, bone, drivers, 2, z, default=default)
1098        
1099        # repeat for left side
1100        if '?' in boneName:
1101            bone = self.GetPoseBone(boneName, flip=True)
1102            if bone:
1103                drivers = self.GetDrivers(bone.name,'scale')
1104                
1105                self.AddScaleDriver(prop, bone, drivers, 0, x, default=default)
1106                self.AddScaleDriver(prop, bone, drivers, 1, y, default=default)
1107                self.AddScaleDriver(prop, bone, drivers, 2, z, default=default)
1108        
1109        return
bl_idname = 'CNV_PG_cm3d2_bone_morph'
scale: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}>
HeadX: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'HeadX', 'description': 'Size of face (left to right)', 'default': 50, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'attr': 'HeadX'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'HeadX', 'description': 'Size of face (left to right)', 'default': 50, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'attr': 'HeadX'}>
HeadY: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'HeadY', 'description': 'Size of face (up and down)', 'default': 50, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'HeadY'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'HeadY', 'description': 'Size of face (up and down)', 'default': 50, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'HeadY'}>
DouPer: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'DouPer', 'description': 'Leg length', 'default': 50, 'min': -100, 'max': 500, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'DouPer'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'DouPer', 'description': 'Leg length', 'default': 50, 'min': -100, 'max': 500, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'DouPer'}>
sintyou: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'sintyou', 'description': 'Height', 'default': 50, 'min': -300, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'sintyou'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'sintyou', 'description': 'Height', 'default': 50, 'min': -300, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'sintyou'}>
BreastSize: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'BreastSize', 'description': 'Breast size', 'default': 50, 'min': -30, 'max': 195, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMune at 0x7f6a0eb66290>, 'attr': 'BreastSize'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'BreastSize', 'description': 'Breast size', 'default': 50, 'min': -30, 'max': 195, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMune>, 'attr': 'BreastSize'}>
MuneTare: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'MuneTare', 'description': 'Breast sagging level', 'default': 50, 'min': 0, 'max': 195, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMuneTare at 0x7f6a0eb66320>, 'attr': 'MuneTare'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'MuneTare', 'description': 'Breast sagging level', 'default': 50, 'min': 0, 'max': 195, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMuneTare>, 'attr': 'MuneTare'}>
MuneUpDown: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'MuneUpDown', 'description': 'Position of the nipple', 'default': 10, 'min': -50, 'max': 300, 'step': 100, 'precision': 0, 'attr': 'MuneUpDown'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'MuneUpDown', 'description': 'Position of the nipple', 'default': 10, 'min': -50, 'max': 300, 'step': 100, 'precision': 0, 'attr': 'MuneUpDown'}>
MuneYori: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'MuneYori', 'description': 'Direction of breast', 'default': 40, 'min': -50, 'max': 200, 'step': 100, 'precision': 0, 'attr': 'MuneYori'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'MuneYori', 'description': 'Direction of breast', 'default': 40, 'min': -50, 'max': 200, 'step': 100, 'precision': 0, 'attr': 'MuneYori'}>
west: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'west', 'description': 'Waist', 'default': 50, 'min': -30, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'west'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'west', 'description': 'Waist', 'default': 50, 'min': -30, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'west'}>
Hara: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Hara', 'description': 'Belly', 'default': 20, 'min': 0, 'max': 200, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'Hara'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Hara', 'description': 'Belly', 'default': 20, 'min': 0, 'max': 200, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'Hara'}>
kata: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'kata', 'description': 'Shoulder width', 'default': 50, 'min': -400, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'kata'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'kata', 'description': 'Shoulder width', 'default': 50, 'min': -400, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'kata'}>
ArmL: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'ArmL', 'description': 'Size of arms', 'default': 20, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'ArmL'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'ArmL', 'description': 'Size of arms', 'default': 20, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'ArmL'}>
UdeScl: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'UdeScl', 'description': 'Length of arms', 'default': 50, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'UdeScl'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'UdeScl', 'description': 'Length of arms', 'default': 50, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'UdeScl'}>
KubiScl: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'KubiScl', 'description': 'Length of neck', 'default': 50, 'min': 0, 'max': 200, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'KubiScl'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'KubiScl', 'description': 'Length of neck', 'default': 50, 'min': 0, 'max': 200, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'KubiScl'}>
koshi: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'koshi', 'description': 'Hip', 'default': 50, 'min': -160, 'max': 200, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'koshi'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'koshi', 'description': 'Hip', 'default': 50, 'min': -160, 'max': 200, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'koshi'}>
RegFat: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'RegFat', 'description': 'Leg thickness', 'default': 40, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'RegFat'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'RegFat', 'description': 'Leg thickness', 'default': 40, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'RegFat'}>
RegMeet: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'RegMeet', 'description': 'Leg definition', 'default': 40, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements at 0x7f6a0eb66200>, 'attr': 'RegMeet'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'RegMeet', 'description': 'Leg definition', 'default': 40, 'min': 0, 'max': 100, 'step': 100, 'precision': 0, 'update': <function CNV_PG_cm3d2_bone_morph.__calcMeasurements>, 'attr': 'RegMeet'}>
MuneL: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'MuneL', 'description': 'munel shapekey value', 'default': 50, 'min': 0, 'attr': 'MuneL'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'MuneL', 'description': 'munel shapekey value', 'default': 50, 'min': 0, 'attr': 'MuneL'}>
MuneS: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'MuneS', 'description': 'munes shapekey value', 'default': 0, 'min': 0, 'attr': 'MuneS'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'MuneS', 'description': 'munes shapekey value', 'default': 0, 'min': 0, 'attr': 'MuneS'}>
private_height: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'private_height', 'options': {'HIDDEN'}, 'attr': 'private_height'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'private_height', 'options': {'HIDDEN'}, 'attr': 'private_height'}>
private_weight: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'private_weight', 'options': {'HIDDEN'}, 'attr': 'private_weight'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'private_weight', 'options': {'HIDDEN'}, 'attr': 'private_weight'}>
private_bust: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'private_bust', 'options': {'HIDDEN'}, 'attr': 'private_bust'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'private_bust', 'options': {'HIDDEN'}, 'attr': 'private_bust'}>
private_waist: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'private_waist', 'options': {'HIDDEN'}, 'attr': 'private_waist'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'private_waist', 'options': {'HIDDEN'}, 'attr': 'private_waist'}>
private_hip: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'private_hip', 'options': {'HIDDEN'}, 'attr': 'private_hip'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'private_hip', 'options': {'HIDDEN'}, 'attr': 'private_hip'}>
private_cup: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'private_cup', 'options': {'HIDDEN'}, 'attr': 'private_cup'}> = <_PropertyDeferred, <built-in function StringProperty>, {'name': 'private_cup', 'options': {'HIDDEN'}, 'attr': 'private_cup'}>
height: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'height', 'precision': 3, 'unit': 'LENGTH', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter at 0x7f6a0eb663b0>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter at 0x7f6a0eb664d0>, 'attr': 'height'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'height', 'precision': 3, 'unit': 'LENGTH', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter>, 'attr': 'height'}>
weight: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'weight', 'precision': 3, 'unit': 'MASS', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter at 0x7f6a0eb663b0>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter at 0x7f6a0eb66560>, 'attr': 'weight'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'weight', 'precision': 3, 'unit': 'MASS', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter>, 'attr': 'weight'}>
bust: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'bust', 'precision': 3, 'unit': 'LENGTH', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter at 0x7f6a0eb663b0>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter at 0x7f6a0eb665f0>, 'attr': 'bust'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'bust', 'precision': 3, 'unit': 'LENGTH', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter>, 'attr': 'bust'}>
waist: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'waist', 'precision': 3, 'unit': 'LENGTH', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter at 0x7f6a0eb663b0>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter at 0x7f6a0eb66680>, 'attr': 'waist'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'waist', 'precision': 3, 'unit': 'LENGTH', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter>, 'attr': 'waist'}>
hip: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'hip', 'precision': 3, 'unit': 'LENGTH', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter at 0x7f6a0eb663b0>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter at 0x7f6a0eb66710>, 'attr': 'hip'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'hip', 'precision': 3, 'unit': 'LENGTH', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter>, 'attr': 'hip'}>
cup: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'cup', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter at 0x7f6a0eb663b0>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter at 0x7f6a0eb667a0>, 'attr': 'cup'}> = <_PropertyDeferred, <built-in function StringProperty>, {'name': 'cup', 'set': <function CNV_PG_cm3d2_bone_morph.__measurementSetter>, 'get': <function CNV_PG_cm3d2_bone_morph.__newGetter.<locals>.__getter>, 'attr': 'cup'}>
def GetArmature(self, override=None):
820    def GetArmature(self, override=None):
821        override = override or bpy.context.copy()
822        ob = self.id_data
823        override.update({
824            'selected_objects'         : {ob},
825            'selected_editable_objects': {ob},
826            'editable_bones'           : {}  ,
827            'selected_bones'           : {}  ,
828            'selected_editable_bones'  : {}  ,
829            'active_object'            : ob  ,
830            'edit_object'              : ob  ,
831        })
832        return self.id_data, override
833
834        #armature = override['object']
835        #if not armature or armature.type != 'ARMATURE':
836        #    print("ERROR: Active object is not an armature")
837        #    return None, None
838        #
839        #for area in bpy.context.screen.areas:
840        #    #print(area,area.type)
841        #    if area.type == 'OUTLINER':
842        #        override.update({
843        #            'blend_data': None,
844        #            'area': area,
845        #            'scene': bpy.context.scene,
846        #            'screen': None,
847        #            'space_data': area.spaces[0],
848        #            'window': None,
849        #            'window_manager': None,
850        #            'object': armature,
851        #            'active_object': armature,
852        #            'edit_object': armature,
853        #        })
854        #        break
855        #
856        #if override['area'].type != 'OUTLINER':
857        #    print("ERROR: There is no 3D View Present in the current workspace")
858        #    return None, None
859        #
860        #if False:
861        #    print("\n")
862        #    for k,v in override.items():
863        #        print(k)
864        #    print("\n")
865        #return armature, override
def GetPoseBone(self, boneName, flip=False, override=None):
867    def GetPoseBone(self, boneName, flip=False, override=None):
868        context = bpy.context
869        
870        side = "L" if flip else "R"
871        armature, override = self.GetArmature()
872        if not armature:
873            return
874        
875        poseBoneList = armature.pose.bones
876        poseBone = poseBoneList.get(boneName.replace("?",side)) or poseBoneList.get(boneName.replace("?","*")+"."+side)
877
878        # check if _SCL_ bone needs to be created
879        if not poseBone and "_SCL_" in boneName:
880            boneList = armature.data.edit_bones
881            bpy.ops.object.mode_set(mode='EDIT')
882            print("Make Scale Bone: "+boneName)
883            copyBone = boneList.get(boneName.replace("_SCL_","").replace("?",side)) or boneList.get(boneName.replace("_SCL_","").replace("?","*")+"."+side)
884            if copyBone:
885                #bpy.ops.armature.select_all(override, action='DESELECT')
886                #for v in context.selected_bones:
887                #    v.select = False
888                #    v.select_head = False
889                #    v.select_tail = False
890                #copyBone.select = True
891                #copyBone.select_head = True
892                #copyBone.select_tail = True
893                #boneList.active = copyBone
894                #bpy.ops.armature.duplicate(override)
895                new_name = copyBone.basename+"_SCL_" + ("."+side if ("."+side) in copyBone.name else "")
896                bone = armature.data.edit_bones.new(new_name)
897                bone.parent = copyBone
898                bone.head = copyBone.head
899                bone.tail = copyBone.tail
900                bone.roll = copyBone.roll
901                bone.show_wire = True
902                bone.use_deform = True
903                copyBone['cm3d2_scl_bone'] = False
904                bone['cm3d2_scl_bone'] = False
905                
906                # rename vertex groups
907                for child in armature.children:
908                    if child.type == 'MESH':
909                        vertexGroup = child.vertex_groups.get(copyBone.name)
910                        if vertexGroup:
911                            vertexGroup.name = bone.name
912        
913        bpy.ops.object.mode_set(mode='POSE')
914        poseBone = poseBone or poseBoneList.get(boneName.replace("?", side)) or poseBoneList.get(boneName.replace("?","*")+"."+side)
915        
916        if not poseBone:
917            print("WARNING: Could not find bone \""+boneName+"\"")
918            return
919
920        return poseBone
def GetDrivers(self, data_path, prop):
922    def GetDrivers(self, data_path, prop):
923        id_data = self.id_data
924        drivers = [None, None, None]
925        if id_data and id_data.animation_data:
926            for f in id_data.animation_data.drivers:
927                fName = f.data_path
928                #print("check",fName, "for", '["%s"].%s' % (data_path, prop))
929                if '["{path}"].{attr}'.format(path=data_path, attr=prop) in fName:
930                    #print("VALID!")
931                    drivers[f.array_index] = f.driver
932        return drivers
def AddPositionDriver(self, prop, bone, drivers, axis, value, default=50):
935    def AddPositionDriver(self, prop, bone, drivers, axis, value, default=50):
936        value = value-1
937        if value == 0:
938            return
939        
940        driver = drivers[axis]
941        prefix = " + "
942        
943        if not driver:
944            driver = bone.driver_add("location", axis).driver
945            driver.type = 'SCRIPTED'
946            
947            parent_length_var = driver.variables.new()
948            parent_length_var.type = 'SINGLE_PROP'
949            parent_length_var.name = "parent_length"
950            
951            driver_target = parent_length_var.targets[0]
952            driver_target.id_type = 'ARMATURE'
953            driver_target.id = bone.parent.bone.id_data if not compat.IS_LEGACY else bone.parent.bone.id_data.data
954            driver_target.data_path = bone.parent.bone.path_from_id("length")
955
956            head_var = driver.variables.new()
957            head_var.type = 'SINGLE_PROP'
958            head_var.name = "head"
959
960            driver_target = head_var.targets[0]
961            driver_target.id_type = 'OBJECT'
962            driver_target.id = bone.id_data
963            driver_target.data_path = bone.path_from_id("head") + f"[{axis}]"
964            
965            if axis == 1: # if y axis, include parent bone's length, because head coords are based on parent's tail
966                driver.expression = "(parent_length+head)_"
967            else:
968                driver.expression = "head_"
969            prefix = " * ("
970            
971            #driver.expression = "-{direction} + {direction}", direction=rest_value
972
973        driver_var = driver.variables.get(prop)
974        if not driver_var:
975            driver_var = driver.variables.new()
976            driver_var.type = 'SINGLE_PROP'
977            driver_var.name = prop
978
979            driver_target = driver_var.targets[0]
980            driver_target.id_type = 'OBJECT'
981            driver_target.id = bone.id_data
982            driver_target.data_path = bone.id_data.cm3d2_bone_morph.path_from_id(prop)
983        
984        # if prop isn't already a factor
985        if not prop in driver.expression:
986            driver.expression = driver.expression[:-1] + prefix + f"({prop}-{default})*{value/(100-default)})"
987            
988        return
def AddScaleDriver(self, prop, bone, drivers, axis, value, default=50):
 990    def AddScaleDriver(self, prop, bone, drivers, axis, value, default=50):
 991        value = value-1
 992        if value == 0:
 993            return
 994        
 995        driver = drivers[axis]
 996        
 997        # if just created
 998        if not driver:
 999            driver = bone.driver_add("scale", axis).driver
1000            driver.type = 'SCRIPTED'
1001            driver.expression = "(1)"
1002
1003        driver_var = driver.variables.get(prop) 
1004        if not driver_var:
1005            driver_var = driver.variables.new()
1006            driver_var.type = 'SINGLE_PROP'
1007            driver_var.name = prop
1008
1009            driver_target = driver_var.targets[0]
1010            driver_target.id_type = 'OBJECT'
1011            driver_target.id = bone.id_data
1012            driver_target.data_path = bone.id_data.cm3d2_bone_morph.path_from_id(prop)
1013        
1014        # if prop isn't already a factor
1015        if not prop in driver.expression:
1016            driver.expression = driver.expression[:-1] + f" + ({prop}-{default})*{value/(100-default)})"
1017 
1018        return
def SetPosition(self, prop, boneName, x, y, z, default=50):
1020    def SetPosition(self, prop, boneName, x, y, z, default=50):
1021        # Check if object has this property
1022        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1023        #    if ONLY_FIX_SETTINGS:
1024        #        return
1025        #x = (1-x)+1
1026        #y = (1-y)+1
1027        #z = (1-z)+1
1028
1029        #loc.x, loc.y, loc.z = loc.z, -loc.x, loc.y
1030        #x, y, z = z, x, y
1031
1032        vec = mathutils.Vector((x, y, z))
1033        vec = compat.convert_cm_to_bl_slider_space(vec)
1034
1035        pose_bone = self.GetPoseBone(boneName)
1036        if pose_bone:                                                       
1037            #rest_pos = pose_bone.bone.head_local + (pose_bone.bone.head_local - pose_bone.bone.parent.head_local) 
1038            #rest_pos = compat.mul(pose_bone.bone.matrix_local.inverted(), rest_pos)
1039            #vec = mathutils.Vector((x, y, z))# * self.scale
1040            #if pose_bone.parent:
1041            #    vec = compat.convert_cm_to_bl_bone_space(vec)
1042            #    vec = compat.mul(pose_bone.parent.bone.matrix_local, vec)
1043            #else:
1044            #    vec = compat.convert_cm_to_bl_space(vec)
1045            #vec = compat.mul(pose_bone.bone.matrix_local.inverted(), vec)
1046
1047            pose_bone.bone.use_local_location = False
1048            drivers = self.GetDrivers(pose_bone.name,'location')
1049                                                        
1050            self.AddPositionDriver(prop, pose_bone, drivers, 0, vec[0], default=default)
1051            self.AddPositionDriver(prop, pose_bone, drivers, 1, vec[1], default=default)
1052            self.AddPositionDriver(prop, pose_bone, drivers, 2, vec[2], default=default)
1053                                                                   
1054        # repeat for left side
1055        if '?' in boneName:
1056            pose_bone = self.GetPoseBone(boneName, flip=True)
1057            if pose_bone:
1058                #rest_pos = pose_bone.bone.head_local + pose_bone.bone.head
1059                #rest_pos = compat.mul(pose_bone.bone.matrix_local.inverted(), rest_pos)
1060                #vec = mathutils.Vector((x, y, z))# * self.scale
1061                #if pose_bone.parent:
1062                #    vec = compat.convert_cm_to_bl_bone_space(vec)
1063                #    vec = compat.mul(pose_bone.parent.bone.matrix_local, vec)
1064                #else:
1065                #    vec = compat.convert_cm_to_bl_space(vec)
1066                #vec = compat.mul(pose_bone.bone.matrix_local.inverted(), vec)
1067                
1068                pose_bone.bone.use_local_location = False
1069                drivers = self.GetDrivers(pose_bone.name,'location')
1070
1071                vec[2] = (1-vec[2])+1 # mirror z axis
1072                
1073                self.AddPositionDriver(prop, pose_bone, drivers, 0, vec[0], default=default)
1074                self.AddPositionDriver(prop, pose_bone, drivers, 1, vec[1], default=default)
1075                self.AddPositionDriver(prop, pose_bone, drivers, 2, vec[2], default=default)
1076                                                                            
1077        return
def SetScale(self, prop, boneName, x, y, z, default=50):
1079    def SetScale(self, prop, boneName, x, y, z, default=50):
1080        # Check if object has this property
1081        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1082        #    if ONLY_FIX_SETTINGS:
1083        #        return
1084
1085        #x, y, z = z, abs(-x), y
1086
1087        mat = mathutils.Matrix.Diagonal((x, y, z)).to_4x4()
1088        mat = compat.convert_cm_to_bl_bone_rotation(mat)
1089        x, y, z = -mat.to_scale()
1090
1091        bone = self.GetPoseBone(boneName)
1092        if bone:
1093            drivers = self.GetDrivers(bone.name,'scale')
1094            
1095            self.AddScaleDriver(prop, bone, drivers, 0, x, default=default)
1096            self.AddScaleDriver(prop, bone, drivers, 1, y, default=default)
1097            self.AddScaleDriver(prop, bone, drivers, 2, z, default=default)
1098        
1099        # repeat for left side
1100        if '?' in boneName:
1101            bone = self.GetPoseBone(boneName, flip=True)
1102            if bone:
1103                drivers = self.GetDrivers(bone.name,'scale')
1104                
1105                self.AddScaleDriver(prop, bone, drivers, 0, x, default=default)
1106                self.AddScaleDriver(prop, bone, drivers, 1, y, default=default)
1107                self.AddScaleDriver(prop, bone, drivers, 2, z, default=default)
1108        
1109        return
bl_rna = <bpy_struct, Struct("CNV_PG_cm3d2_bone_morph")>
Inherited Members
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CNV_PG_cm3d2_wide_slider(bpy_types.PropertyGroup):
1112@compat.BlRegister()
1113class CNV_PG_cm3d2_wide_slider(bpy.types.PropertyGroup):
1114    bl_idname = 'CNV_PG_cm3d2_wide_slider'
1115
1116    scale = bpy.props.FloatProperty(name="Scale", default=5, min=0.1, max=100, soft_min=0.1, soft_max=100, step=100, precision=1, description="The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.")
1117
1118    empty  = bpy.props.EnumProperty(items=[('EMPTY','-',"This property never has a value")], name="Empty", description="This property never has a value")
1119    
1120    enable_all = bpy.props.BoolProperty(name="Enable All", description="Enable all sliders, even ones without a GUI in-game", default=False)
1121
1122    HIPPOS     = bpy.props.FloatVectorProperty(name="HIPPOS"    , description="Hips Position"         , default=(0,0,0), min=-100, max= 200, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1123    THIPOS     = bpy.props.FloatVectorProperty(name="THIPOS"    , description="Legs Position"         , default=(0,0,0), min=-100, max= 200, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1124    MTWPOS     = bpy.props.FloatVectorProperty(name="MTWPOS"    , description="Thigh Position"        , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1125    MMNPOS     = bpy.props.FloatVectorProperty(name="MMNPOS"    , description="Rear Thigh Position"   , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1126    THI2POS    = bpy.props.FloatVectorProperty(name="THI2POS"   , description="Knee Position"         , default=(0,0,0), min=-100, max= 200, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1127    SKTPOS     = bpy.props.FloatVectorProperty(name="SKTPOS"    , description="Skirt Position"        , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1128    SPIPOS     = bpy.props.FloatVectorProperty(name="SPIPOS"    , description="Lower Abdomen Position", default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1129    S0APOS     = bpy.props.FloatVectorProperty(name="S0APOS"    , description="Upper Abdomen Position", default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1130    S1POS      = bpy.props.FloatVectorProperty(name="S1POS"     , description="Lower Chest Position"  , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1131    S1APOS     = bpy.props.FloatVectorProperty(name="S1APOS"    , description="Upper Chest Position"  , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1132    MUNEPOS    = bpy.props.FloatVectorProperty(name="MUNEPOS"   , description="Breasts Position"      , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1133    MUNESUBPOS = bpy.props.FloatVectorProperty(name="MUNESUBPOS", description="Breasts Sub-Position"  , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1134    NECKPOS    = bpy.props.FloatVectorProperty(name="NECKPOS"   , description="Neck Position"         , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1135    CLVPOS     = bpy.props.FloatVectorProperty(name="CLVPOS"    , description="Clavicle Position"     , default=(0,0,0), min=-1.0, max= 1.0, precision=2, subtype=compat.subtype('XYZ'        ), unit='NONE')
1136                                                                                                
1137    PELSCL     = bpy.props.FloatVectorProperty(name="PELSCL"    , description="Pelvis Scale"          , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1138    HIPSCL     = bpy.props.FloatVectorProperty(name="HIPSCL"    , description="Hips Scale"            , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1139    THISCL     = bpy.props.FloatVectorProperty(name="THISCL"    , description="Legs Scale"            , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1140    MTWSCL     = bpy.props.FloatVectorProperty(name="MTWSCL"    , description="Thigh Scale"           , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1141    MMNSCL     = bpy.props.FloatVectorProperty(name="MMNSCL"    , description="Rear Thigh Scale"      , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1142    THISCL2    = bpy.props.FloatVectorProperty(name="THISCL2"   , description="Knee Scale"            , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1143    CALFSCL    = bpy.props.FloatVectorProperty(name="CALFSCL"   , description="Calf Scale"            , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1144    FOOTSCL    = bpy.props.FloatVectorProperty(name="FOOTSCL"   , description="Foot Scale"            , default=(1,1,1), min= 0.1, max= 2.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1145    SKTSCL     = bpy.props.FloatVectorProperty(name="SKTSCL"    , description="Skirt Scale"           , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1146    SPISCL     = bpy.props.FloatVectorProperty(name="SPISCL"    , description="Lower Abdomen Scale"   , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1147    S0ASCL     = bpy.props.FloatVectorProperty(name="S0ASCL"    , description="Upper Abdomen Scale"   , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1148    S1_SCL     = bpy.props.FloatVectorProperty(name="S1_SCL"    , description="Lower Chest Scale"     , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1149    S1ASCL     = bpy.props.FloatVectorProperty(name="S1ASCL"    , description="Upper Chest Scale"     , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1150    S1ABASESCL = bpy.props.FloatVectorProperty(name="S1ABASESCL", description="Upper Torso Scale"     , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1151    MUNESCL    = bpy.props.FloatVectorProperty(name="MUNESCL"   , description="Breasts Scale"         , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1152    MUNESUBSCL = bpy.props.FloatVectorProperty(name="MUNESUBSCL", description="Breasts Sub-Scale"     , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1153    NECKSCL    = bpy.props.FloatVectorProperty(name="NECKSCL"   , description="Neck Scale"            , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1154    CLVSCL     = bpy.props.FloatVectorProperty(name="CLVSCL"    , description="Clavicle Scale"        , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1155    KATASCL    = bpy.props.FloatVectorProperty(name="KATASCL"   , description="Shoulders Scale"       , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1156    UPARMSCL   = bpy.props.FloatVectorProperty(name="UPARMSCL"  , description="Upper Arm Scale"       , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1157    FARMSCL    = bpy.props.FloatVectorProperty(name="FARMSCL"   , description="Forearm Scale"         , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1158    HANDSCL    = bpy.props.FloatVectorProperty(name="HANDSCL"   , description="Hand Scale"            , default=(1,1,1), min= 0.1, max= 3.0, precision=2, subtype=compat.subtype('XYZ_LENGTH' ), unit='NONE')
1159                                                                                                                                        
1160                                                                                                                                        
1161    def GetArmature(self, override=None):
1162        return CNV_PG_cm3d2_bone_morph.GetArmature(self, override=override)
1163    
1164    def GetPoseBone(self, boneName, flip=False, override=None):
1165        return CNV_PG_cm3d2_bone_morph.GetPoseBone(self, boneName, flip=flip, override=override)
1166
1167    def GetDrivers(self, data_path, prop):
1168        return CNV_PG_cm3d2_bone_morph.GetDrivers(self, data_path, prop)
1169
1170
1171    def AddPositionDriver(self, prop, index, bone, drivers, axis, value):
1172        if value == 0:
1173            return
1174              
1175        driver = drivers[axis]
1176
1177        if not driver:
1178            driver = bone.driver_add("location",axis).driver
1179            driver.type = 'SCRIPTED'
1180            driver.expression = "0"
1181
1182        prop_var = prop + f"_{index}_"
1183        driver_var = driver.variables.get(prop_var) 
1184        if not driver_var:
1185            driver_var = driver.variables.new()
1186            driver_var.type = 'SINGLE_PROP'
1187            driver_var.name = prop_var
1188
1189            driver_target = driver_var.targets[0]
1190            driver_target.id_type = 'OBJECT'
1191            driver_target.id = bone.id_data
1192            driver_target.data_path = bone.id_data.cm3d2_wide_slider.path_from_id(prop) + f"[{index}]"
1193
1194              
1195        # if prop isn't already a factor
1196        if not prop_var in driver.expression:
1197            driver.expression = driver.expression + f" + {prop_var}*{value}"
1198                
1199        return
1200              
1201              
1202    def AddScaleDriver(self, prop, index, bone, drivers, axis):
1203        if index < 0:
1204            return
1205              
1206        driver = drivers[axis]
1207        if not driver:
1208            driver = bone.driver_add("scale", axis).driver
1209            driver.type = 'SCRIPTED'
1210            driver.expression = "1"
1211        
1212        prop_var = f"{prop}_{index}_"
1213        driver_var = driver.variables.get(prop_var) 
1214        if not driver_var:
1215            driver_var = driver.variables.new()
1216            driver_var.type = 'SINGLE_PROP'
1217            driver_var.name = prop_var
1218
1219            driver_target = driver_var.targets[0]
1220            driver_target.id_type = 'OBJECT'
1221            driver_target.id = bone.id_data
1222            driver_target.data_path = bone.id_data.cm3d2_wide_slider.path_from_id(prop) + f"[{index}]"
1223
1224              
1225        # if prop isn't already a factor
1226        if not prop_var in driver.expression:
1227            driver.expression = driver.expression + f" * {prop_var}"
1228                
1229        return
1230              
1231                      
1232    def AddVectorProperty(self, object, prop, value=None, default=0.0, min=-100, max=200):
1233        #value = value or [default, default, default]
1234        #object[prop] = not RESET_SETTINGS and object.get(prop) or value
1235        #object['_RNA_UI'][prop] = {
1236        #    "description": "",
1237        #    "default": default,
1238        #    "min": min,
1239        #    "max": max,
1240        #    "soft_min": min,
1241        #    "soft_max": max,
1242        #}     
1243        return
1244    
1245              
1246    def SetPosition(self, prop, boneName, ux, uy, uz, axisOrder=[0,1,2], axisFlip=None):
1247        # Check if object has this property
1248        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1249        #    self.AddVectorProperty(bpy.context.object, prop)
1250        #    if ONLY_FIX_SETTINGS:
1251        #        return
1252
1253        mat = get_axis_order_matrix(axisOrder).to_4x4()
1254        mat.translation = mathutils.Vector((ux, uy, uz)) * self.scale
1255        mat = compat.convert_cm_to_bl_bone_space(mat)
1256        uVec = mat.to_translation()
1257        axisOrder = get_matrix_axis_order(mat.to_3x3())
1258
1259        if axisFlip != None:
1260            flipVec = get_axis_index_vector(axisFlip)
1261            flipVec = compat.convert_cm_to_bl_bone_space(flipVec)
1262            axisFlip = get_vector_axis_index(flipVec)
1263        
1264        ##ux, uy, uz = uz*5, ux*5, -uy*5
1265        ##axisFlip = axisOrder[axisFlip] if axisFlip else None
1266        #axisFlip = 1 if axisFlip == 0 else ( 2 if axisFlip == 1 else (0 if axisFlip == 2 else None) )
1267        ##axisFlip = axisOrder[axisFlip] if axisFlip else None
1268        #axisOrder[0], axisOrder[1], axisOrder[2] = axisOrder[2], axisOrder[0], axisOrder[1]
1269        ##axisFlip = axisOrder[axisFlip] if axisFlip != None else None
1270        
1271        bone = self.GetPoseBone(boneName)
1272        if bone:
1273            bone.bone.use_local_location = False
1274            drivers = self.GetDrivers(bone.name,'location')
1275        
1276            self.AddPositionDriver(prop, axisOrder[0], bone, drivers, 0, uVec[0])
1277            self.AddPositionDriver(prop, axisOrder[1], bone, drivers, 1, uVec[1])
1278            self.AddPositionDriver(prop, axisOrder[2], bone, drivers, 2, uVec[2])
1279        
1280        # repeat for left side
1281        if '?' in boneName:
1282            bone = self.GetPoseBone(boneName, flip=True)
1283            if bone:
1284                bone.bone.use_local_location = False
1285                drivers = self.GetDrivers(bone.name,'location')
1286
1287                if axisFlip != None:
1288                    print(axisFlip)
1289                    uVec[axisFlip] *= -1
1290                
1291                #if   axisFlip == 0:
1292                #    ux = -ux
1293                #elif axisFlip == 1:
1294                #    uy = -uy
1295                #elif axisFlip == 2:
1296                #    uz = -uz
1297                
1298                self.AddPositionDriver(prop, axisOrder[0], bone, drivers, 0, uVec[0])
1299                self.AddPositionDriver(prop, axisOrder[1], bone, drivers, 1, uVec[1])
1300                self.AddPositionDriver(prop, axisOrder[2], bone, drivers, 2, uVec[2])
1301                                                                             
1302        return
1303
1304
1305    def SetScale(self, prop, boneName, axisOrder=[0,1,2]):
1306        # Check if object has this property
1307        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1308        #    self.AddVectorProperty(bpy.context.object, prop, default=1.0, min=0.1, max=3.0)
1309        #    if ONLY_FIX_SETTINGS:
1310        #        return
1311
1312        # x, y, z = x, z, y
1313        #axisOrder[0], axisOrder[1], axisOrder[2] = axisOrder[0], axisOrder[2], axisOrder[1]
1314        
1315        axisMat = get_axis_order_matrix(axisOrder).to_4x4()
1316        axisMat = compat.convert_cm_to_bl_bone_rotation(axisMat)
1317        #axisMat = compat.convert_cm_to_bl_bone_space(axisMat)
1318        axisOrder = get_matrix_axis_order(axisMat)
1319        
1320        bone = self.GetPoseBone(boneName)
1321        if bone:
1322            drivers = self.GetDrivers(bone.name,'scale')
1323            
1324            self.AddScaleDriver(prop, axisOrder[0], bone, drivers, 2)
1325            self.AddScaleDriver(prop, axisOrder[1], bone, drivers, 1)
1326            self.AddScaleDriver(prop, axisOrder[2], bone, drivers, 0)
1327        
1328        # repeat for left side
1329        if '?' in boneName:
1330            bone = self.GetPoseBone(boneName, True)
1331            if bone:
1332                drivers = self.GetDrivers(bone.name,'scale')
1333
1334                self.AddScaleDriver(prop, axisOrder[0], bone, drivers, 2)
1335                self.AddScaleDriver(prop, axisOrder[1], bone, drivers, 1)
1336                self.AddScaleDriver(prop, axisOrder[2], bone, drivers, 0)
1337        
1338        return
bl_idname = 'CNV_PG_cm3d2_wide_slider'
scale: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}>
empty: <_PropertyDeferred, <built-in function EnumProperty>, {'items': [('EMPTY', '-', 'This property never has a value')], 'name': 'Empty', 'description': 'This property never has a value', 'attr': 'empty'}> = <_PropertyDeferred, <built-in function EnumProperty>, {'items': [('EMPTY', '-', 'This property never has a value')], 'name': 'Empty', 'description': 'This property never has a value', 'attr': 'empty'}>
enable_all: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Enable All', 'description': 'Enable all sliders, even ones without a GUI in-game', 'default': False, 'attr': 'enable_all'}> = <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Enable All', 'description': 'Enable all sliders, even ones without a GUI in-game', 'default': False, 'attr': 'enable_all'}>
HIPPOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'HIPPOS', 'description': 'Hips Position', 'default': (0, 0, 0), 'min': -100, 'max': 200, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'HIPPOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'HIPPOS', 'description': 'Hips Position', 'default': (0, 0, 0), 'min': -100, 'max': 200, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'HIPPOS'}>
THIPOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'THIPOS', 'description': 'Legs Position', 'default': (0, 0, 0), 'min': -100, 'max': 200, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'THIPOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'THIPOS', 'description': 'Legs Position', 'default': (0, 0, 0), 'min': -100, 'max': 200, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'THIPOS'}>
MTWPOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MTWPOS', 'description': 'Thigh Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'MTWPOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MTWPOS', 'description': 'Thigh Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'MTWPOS'}>
MMNPOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MMNPOS', 'description': 'Rear Thigh Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'MMNPOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MMNPOS', 'description': 'Rear Thigh Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'MMNPOS'}>
THI2POS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'THI2POS', 'description': 'Knee Position', 'default': (0, 0, 0), 'min': -100, 'max': 200, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'THI2POS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'THI2POS', 'description': 'Knee Position', 'default': (0, 0, 0), 'min': -100, 'max': 200, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'THI2POS'}>
SKTPOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'SKTPOS', 'description': 'Skirt Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'SKTPOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'SKTPOS', 'description': 'Skirt Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'SKTPOS'}>
SPIPOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'SPIPOS', 'description': 'Lower Abdomen Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'SPIPOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'SPIPOS', 'description': 'Lower Abdomen Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'SPIPOS'}>
S0APOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S0APOS', 'description': 'Upper Abdomen Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'S0APOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S0APOS', 'description': 'Upper Abdomen Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'S0APOS'}>
S1POS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S1POS', 'description': 'Lower Chest Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'S1POS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S1POS', 'description': 'Lower Chest Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'S1POS'}>
S1APOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S1APOS', 'description': 'Upper Chest Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'S1APOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S1APOS', 'description': 'Upper Chest Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'S1APOS'}>
MUNEPOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MUNEPOS', 'description': 'Breasts Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'MUNEPOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MUNEPOS', 'description': 'Breasts Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'MUNEPOS'}>
MUNESUBPOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MUNESUBPOS', 'description': 'Breasts Sub-Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'MUNESUBPOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MUNESUBPOS', 'description': 'Breasts Sub-Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'MUNESUBPOS'}>
NECKPOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'NECKPOS', 'description': 'Neck Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'NECKPOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'NECKPOS', 'description': 'Neck Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'NECKPOS'}>
CLVPOS: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'CLVPOS', 'description': 'Clavicle Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'CLVPOS'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'CLVPOS', 'description': 'Clavicle Position', 'default': (0, 0, 0), 'min': -1.0, 'max': 1.0, 'precision': 2, 'subtype': 'XYZ', 'unit': 'NONE', 'attr': 'CLVPOS'}>
PELSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'PELSCL', 'description': 'Pelvis Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'PELSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'PELSCL', 'description': 'Pelvis Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'PELSCL'}>
HIPSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'HIPSCL', 'description': 'Hips Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'HIPSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'HIPSCL', 'description': 'Hips Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'HIPSCL'}>
THISCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'THISCL', 'description': 'Legs Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'THISCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'THISCL', 'description': 'Legs Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'THISCL'}>
MTWSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MTWSCL', 'description': 'Thigh Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'MTWSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MTWSCL', 'description': 'Thigh Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'MTWSCL'}>
MMNSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MMNSCL', 'description': 'Rear Thigh Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'MMNSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MMNSCL', 'description': 'Rear Thigh Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'MMNSCL'}>
THISCL2: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'THISCL2', 'description': 'Knee Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'THISCL2'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'THISCL2', 'description': 'Knee Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'THISCL2'}>
CALFSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'CALFSCL', 'description': 'Calf Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'CALFSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'CALFSCL', 'description': 'Calf Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'CALFSCL'}>
FOOTSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'FOOTSCL', 'description': 'Foot Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'FOOTSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'FOOTSCL', 'description': 'Foot Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 2.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'FOOTSCL'}>
SKTSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'SKTSCL', 'description': 'Skirt Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'SKTSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'SKTSCL', 'description': 'Skirt Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'SKTSCL'}>
SPISCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'SPISCL', 'description': 'Lower Abdomen Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'SPISCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'SPISCL', 'description': 'Lower Abdomen Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'SPISCL'}>
S0ASCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S0ASCL', 'description': 'Upper Abdomen Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'S0ASCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S0ASCL', 'description': 'Upper Abdomen Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'S0ASCL'}>
S1_SCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S1_SCL', 'description': 'Lower Chest Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'S1_SCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S1_SCL', 'description': 'Lower Chest Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'S1_SCL'}>
S1ASCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S1ASCL', 'description': 'Upper Chest Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'S1ASCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S1ASCL', 'description': 'Upper Chest Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'S1ASCL'}>
S1ABASESCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S1ABASESCL', 'description': 'Upper Torso Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'S1ABASESCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'S1ABASESCL', 'description': 'Upper Torso Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'S1ABASESCL'}>
MUNESCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MUNESCL', 'description': 'Breasts Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'MUNESCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MUNESCL', 'description': 'Breasts Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'MUNESCL'}>
MUNESUBSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MUNESUBSCL', 'description': 'Breasts Sub-Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'MUNESUBSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'MUNESUBSCL', 'description': 'Breasts Sub-Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'MUNESUBSCL'}>
NECKSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'NECKSCL', 'description': 'Neck Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'NECKSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'NECKSCL', 'description': 'Neck Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'NECKSCL'}>
CLVSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'CLVSCL', 'description': 'Clavicle Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'CLVSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'CLVSCL', 'description': 'Clavicle Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'CLVSCL'}>
KATASCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'KATASCL', 'description': 'Shoulders Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'KATASCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'KATASCL', 'description': 'Shoulders Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'KATASCL'}>
UPARMSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'UPARMSCL', 'description': 'Upper Arm Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'UPARMSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'UPARMSCL', 'description': 'Upper Arm Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'UPARMSCL'}>
FARMSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'FARMSCL', 'description': 'Forearm Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'FARMSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'FARMSCL', 'description': 'Forearm Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'FARMSCL'}>
HANDSCL: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'HANDSCL', 'description': 'Hand Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'HANDSCL'}> = <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'HANDSCL', 'description': 'Hand Scale', 'default': (1, 1, 1), 'min': 0.1, 'max': 3.0, 'precision': 2, 'subtype': 'XYZ_LENGTH', 'unit': 'NONE', 'attr': 'HANDSCL'}>
def GetArmature(self, override=None):
1161    def GetArmature(self, override=None):
1162        return CNV_PG_cm3d2_bone_morph.GetArmature(self, override=override)
def GetPoseBone(self, boneName, flip=False, override=None):
1164    def GetPoseBone(self, boneName, flip=False, override=None):
1165        return CNV_PG_cm3d2_bone_morph.GetPoseBone(self, boneName, flip=flip, override=override)
def GetDrivers(self, data_path, prop):
1167    def GetDrivers(self, data_path, prop):
1168        return CNV_PG_cm3d2_bone_morph.GetDrivers(self, data_path, prop)
def AddPositionDriver(self, prop, index, bone, drivers, axis, value):
1171    def AddPositionDriver(self, prop, index, bone, drivers, axis, value):
1172        if value == 0:
1173            return
1174              
1175        driver = drivers[axis]
1176
1177        if not driver:
1178            driver = bone.driver_add("location",axis).driver
1179            driver.type = 'SCRIPTED'
1180            driver.expression = "0"
1181
1182        prop_var = prop + f"_{index}_"
1183        driver_var = driver.variables.get(prop_var) 
1184        if not driver_var:
1185            driver_var = driver.variables.new()
1186            driver_var.type = 'SINGLE_PROP'
1187            driver_var.name = prop_var
1188
1189            driver_target = driver_var.targets[0]
1190            driver_target.id_type = 'OBJECT'
1191            driver_target.id = bone.id_data
1192            driver_target.data_path = bone.id_data.cm3d2_wide_slider.path_from_id(prop) + f"[{index}]"
1193
1194              
1195        # if prop isn't already a factor
1196        if not prop_var in driver.expression:
1197            driver.expression = driver.expression + f" + {prop_var}*{value}"
1198                
1199        return
def AddScaleDriver(self, prop, index, bone, drivers, axis):
1202    def AddScaleDriver(self, prop, index, bone, drivers, axis):
1203        if index < 0:
1204            return
1205              
1206        driver = drivers[axis]
1207        if not driver:
1208            driver = bone.driver_add("scale", axis).driver
1209            driver.type = 'SCRIPTED'
1210            driver.expression = "1"
1211        
1212        prop_var = f"{prop}_{index}_"
1213        driver_var = driver.variables.get(prop_var) 
1214        if not driver_var:
1215            driver_var = driver.variables.new()
1216            driver_var.type = 'SINGLE_PROP'
1217            driver_var.name = prop_var
1218
1219            driver_target = driver_var.targets[0]
1220            driver_target.id_type = 'OBJECT'
1221            driver_target.id = bone.id_data
1222            driver_target.data_path = bone.id_data.cm3d2_wide_slider.path_from_id(prop) + f"[{index}]"
1223
1224              
1225        # if prop isn't already a factor
1226        if not prop_var in driver.expression:
1227            driver.expression = driver.expression + f" * {prop_var}"
1228                
1229        return
def AddVectorProperty(self, object, prop, value=None, default=0.0, min=-100, max=200):
1232    def AddVectorProperty(self, object, prop, value=None, default=0.0, min=-100, max=200):
1233        #value = value or [default, default, default]
1234        #object[prop] = not RESET_SETTINGS and object.get(prop) or value
1235        #object['_RNA_UI'][prop] = {
1236        #    "description": "",
1237        #    "default": default,
1238        #    "min": min,
1239        #    "max": max,
1240        #    "soft_min": min,
1241        #    "soft_max": max,
1242        #}     
1243        return
def SetPosition(self, prop, boneName, ux, uy, uz, axisOrder=[0, 1, 2], axisFlip=None):
1246    def SetPosition(self, prop, boneName, ux, uy, uz, axisOrder=[0,1,2], axisFlip=None):
1247        # Check if object has this property
1248        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1249        #    self.AddVectorProperty(bpy.context.object, prop)
1250        #    if ONLY_FIX_SETTINGS:
1251        #        return
1252
1253        mat = get_axis_order_matrix(axisOrder).to_4x4()
1254        mat.translation = mathutils.Vector((ux, uy, uz)) * self.scale
1255        mat = compat.convert_cm_to_bl_bone_space(mat)
1256        uVec = mat.to_translation()
1257        axisOrder = get_matrix_axis_order(mat.to_3x3())
1258
1259        if axisFlip != None:
1260            flipVec = get_axis_index_vector(axisFlip)
1261            flipVec = compat.convert_cm_to_bl_bone_space(flipVec)
1262            axisFlip = get_vector_axis_index(flipVec)
1263        
1264        ##ux, uy, uz = uz*5, ux*5, -uy*5
1265        ##axisFlip = axisOrder[axisFlip] if axisFlip else None
1266        #axisFlip = 1 if axisFlip == 0 else ( 2 if axisFlip == 1 else (0 if axisFlip == 2 else None) )
1267        ##axisFlip = axisOrder[axisFlip] if axisFlip else None
1268        #axisOrder[0], axisOrder[1], axisOrder[2] = axisOrder[2], axisOrder[0], axisOrder[1]
1269        ##axisFlip = axisOrder[axisFlip] if axisFlip != None else None
1270        
1271        bone = self.GetPoseBone(boneName)
1272        if bone:
1273            bone.bone.use_local_location = False
1274            drivers = self.GetDrivers(bone.name,'location')
1275        
1276            self.AddPositionDriver(prop, axisOrder[0], bone, drivers, 0, uVec[0])
1277            self.AddPositionDriver(prop, axisOrder[1], bone, drivers, 1, uVec[1])
1278            self.AddPositionDriver(prop, axisOrder[2], bone, drivers, 2, uVec[2])
1279        
1280        # repeat for left side
1281        if '?' in boneName:
1282            bone = self.GetPoseBone(boneName, flip=True)
1283            if bone:
1284                bone.bone.use_local_location = False
1285                drivers = self.GetDrivers(bone.name,'location')
1286
1287                if axisFlip != None:
1288                    print(axisFlip)
1289                    uVec[axisFlip] *= -1
1290                
1291                #if   axisFlip == 0:
1292                #    ux = -ux
1293                #elif axisFlip == 1:
1294                #    uy = -uy
1295                #elif axisFlip == 2:
1296                #    uz = -uz
1297                
1298                self.AddPositionDriver(prop, axisOrder[0], bone, drivers, 0, uVec[0])
1299                self.AddPositionDriver(prop, axisOrder[1], bone, drivers, 1, uVec[1])
1300                self.AddPositionDriver(prop, axisOrder[2], bone, drivers, 2, uVec[2])
1301                                                                             
1302        return
def SetScale(self, prop, boneName, axisOrder=[0, 1, 2]):
1305    def SetScale(self, prop, boneName, axisOrder=[0,1,2]):
1306        # Check if object has this property
1307        #if not bpy.context.object.get(prop) or ONLY_FIX_SETTINGS:
1308        #    self.AddVectorProperty(bpy.context.object, prop, default=1.0, min=0.1, max=3.0)
1309        #    if ONLY_FIX_SETTINGS:
1310        #        return
1311
1312        # x, y, z = x, z, y
1313        #axisOrder[0], axisOrder[1], axisOrder[2] = axisOrder[0], axisOrder[2], axisOrder[1]
1314        
1315        axisMat = get_axis_order_matrix(axisOrder).to_4x4()
1316        axisMat = compat.convert_cm_to_bl_bone_rotation(axisMat)
1317        #axisMat = compat.convert_cm_to_bl_bone_space(axisMat)
1318        axisOrder = get_matrix_axis_order(axisMat)
1319        
1320        bone = self.GetPoseBone(boneName)
1321        if bone:
1322            drivers = self.GetDrivers(bone.name,'scale')
1323            
1324            self.AddScaleDriver(prop, axisOrder[0], bone, drivers, 2)
1325            self.AddScaleDriver(prop, axisOrder[1], bone, drivers, 1)
1326            self.AddScaleDriver(prop, axisOrder[2], bone, drivers, 0)
1327        
1328        # repeat for left side
1329        if '?' in boneName:
1330            bone = self.GetPoseBone(boneName, True)
1331            if bone:
1332                drivers = self.GetDrivers(bone.name,'scale')
1333
1334                self.AddScaleDriver(prop, axisOrder[0], bone, drivers, 2)
1335                self.AddScaleDriver(prop, axisOrder[1], bone, drivers, 1)
1336                self.AddScaleDriver(prop, axisOrder[2], bone, drivers, 0)
1337        
1338        return
bl_rna = <bpy_struct, Struct("CNV_PG_cm3d2_wide_slider")>
Inherited Members
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CNV_OT_add_cm3d2_body_sliders(bpy_types.Operator):
1341@compat.BlRegister()
1342class CNV_OT_add_cm3d2_body_sliders(bpy.types.Operator):
1343    bl_idname      = 'object.add_cm3d2_body_sliders'
1344    bl_label       = "Add CM3D2 Body Sliders"
1345    bl_description = "Adds drivers to armature to enable body sliders."
1346    bl_options     = {'REGISTER', 'UNDO'}
1347
1348    scale = bpy.props.FloatProperty(name="Scale", default=5, min=0.1, max=100, soft_min=0.1, soft_max=100, step=100, precision=1, description="The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.")
1349
1350    is_fix_thigh        = bpy.props.BoolProperty(name="Fix Thigh"       , default=False, description="Fix twist bone values for the thighs in motor-cycle pose")
1351    is_drive_shape_keys = bpy.props.BoolProperty(name="Drive Shape Keys", default=True, description="Connect sliders to mesh children's shape keys"           )
1352    
1353    @classmethod
1354    def poll(cls, context):
1355        ob = context.object
1356        if ob:
1357            arm = ob.data
1358        else:
1359            arm = None
1360        has_arm  = arm and isinstance(arm, bpy.types.Armature) and ("Bip01" in arm.bones)
1361        can_edit = (ob and ob.data == arm) or (arm and arm.is_editmode)
1362        return has_arm and can_edit
1363
1364    def invoke(self, context, event):
1365        self.scale = common.preferences().scale
1366        return context.window_manager.invoke_props_dialog(self)
1367
1368    def draw(self, context):
1369        self.layout.prop(self, 'scale'              )
1370        #self.layout.prop(self, 'is_fix_thigh'       )
1371        self.layout.prop(self, 'is_drive_shape_keys')
1372
1373    def driveShapeKey(self, shapekey, data, prop, expression, set_min=None, set_max=None):
1374        if not shapekey:
1375            return
1376        driver = shapekey.driver_add('value').driver
1377        driver.type = 'SCRIPTED'
1378
1379        driver_var = driver.variables.new() if len(driver.variables) < 1 else driver.variables[0]
1380        driver_var.type = 'SINGLE_PROP'
1381        driver_var.name = prop
1382
1383        driver_target = driver_var.targets[0]
1384        driver_target.id_type = 'OBJECT'
1385        driver_target.id = data.id_data
1386        driver_target.data_path = data.path_from_id(prop)
1387
1388        driver.expression = expression
1389
1390        if set_min:
1391            shapekey.slider_min = set_min
1392        if set_max:
1393            shapekey.slider_max = set_max
1394
1395    def driveTwistBone(self, bone, prop='rotation_euler', axis=0, expression=""):
1396        if not bone:
1397            return
1398        driver = bone.driver_add(prop, axis).driver
1399        driver.type = 'SCRIPTED'
1400        driver.use_self = True
1401
1402        driver.expression = expression
1403
1404    def execute(self, context):
1405        ob = context.object
1406        arm = ob.data
1407        pre_mode = ob.mode
1408        #if pre_mode != 'EDIT':
1409        #    override = context.copy()
1410        #    override['active_object'] = ob
1411        #    bpy.ops.object.mode_set(override, mode='EDIT')
1412
1413        morph   = ob.cm3d2_bone_morph
1414        sliders = ob.cm3d2_wide_slider
1415
1416        morph.scale   = self.scale
1417        sliders.scale = self.scale
1418
1419
1420
1421        #BoneMorph.SetPosition("KubiScl", "Bip01 Neck"        , 0.95, 1   , 1   , 1.05, 1   , 1   )
1422        #BoneMorph.SetPosition("KubiScl", "Bip01 Head"        , 0.8 , 1   , 1   , 1.2 , 1   , 1   )
1423        #BoneMorph.SetScale   ("UdeScl" , "Bip01 ? UpperArm"  , 0.85, 1   , 1   , 1.15, 1   , 1   )
1424        #BoneMorph.SetScale   ("EyeSclX", "Eyepos_L"          , 1   , 1   , 0.92, 1   , 1   , 1.08)
1425        #BoneMorph.SetScale   ("EyeSclX", "Eyepos_R"          , 1   , 1   , 0.92, 1   , 1   , 1.08)
1426        #BoneMorph.SetScale   ("EyeSclY", "Eyepos_L"          , 1   , 0.92, 1   , 1   , 1.08, 1   )
1427        #BoneMorph.SetScale   ("EyeSclY", "Eyepos_R"          , 1   , 0.92, 1   , 1   , 1.08, 1   )
1428        #BoneMorph.SetPosition("EyePosX", "Eyepos_R"          , 1   , 1   , 0.9 , 1   , 1   , 1.1 )
1429        #BoneMorph.SetPosition("EyePosX", "Eyepos_L"          , 1   , 1   , 0.9 , 1   , 1   , 1.1 )
1430        #BoneMorph.SetPosition("EyePosY", "Eyepos_R"          , 1   , 0.93, 1   , 1   , 1.07, 1   )
1431        #BoneMorph.SetPosition("EyePosY", "Eyepos_L"          , 1   , 0.93, 1   , 1   , 1.07, 1   )
1432        #BoneMorph.SetScale   ("HeadX"  , "Bip01 Head"        , 1   , 0.9 , 0.8 , 1   , 1.1 , 1.2 )
1433        #BoneMorph.SetScale   ("HeadY"  , "Bip01 Head"        , 0.8 , 0.9 , 1   , 1.2 , 1.1 , 1   )
1434        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine"       , 1   , 1   , 0.94, 1   , 1   , 1.06)
1435        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine0a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1436        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine1"      , 0.88, 1   , 1   , 1.12, 1   , 1   )
1437        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine1a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1438        #BoneMorph.SetPosition("DouPer" , "Bip01 Neck"        , 1.03, 1   , 1   , 0.97, 1   , 1   )
1439        #BoneMorph.SetPosition("DouPer" , "Bip01 ? Calf"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1440        #BoneMorph.SetPosition("DouPer" , "Bip01 ? Foot"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1441        #BoneMorph.SetScale   ("DouPer" , "Bip01 ? Thigh_SCL_", 0.87, 1   , 1   , 1.13, 1   , 1   )
1442        #BoneMorph.SetScale   ("DouPer" , "momotwist_?"       , 0.87, 1   , 1   , 1.13, 1   , 1   )
1443        #BoneMorph.SetScale   ("DouPer" , "Bip01 ? Calf_SCL_" , 0.87, 1   , 1   , 1.13, 1   , 1   )
1444        #BoneMorph.SetScale   ("DouPer" , "Bip01 ? UpperArm"  , 0.98, 1   , 1   , 1.02, 1   , 1   )
1445        #BoneMorph.SetPosition("sintyou", "Bip01 Spine"       , 1   , 1   , 0.85, 1   , 1   , 1.15)
1446        #BoneMorph.SetPosition("sintyou", "Bip01 Spine0a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1447        #BoneMorph.SetPosition("sintyou", "Bip01 Spine1"      , 0.88, 1   , 1   , 1.12, 1   , 1   )
1448        #BoneMorph.SetPosition("sintyou", "Bip01 Spine1a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1449        #BoneMorph.SetPosition("sintyou", "Bip01 Neck"        , 0.97, 1   , 1   , 1.03, 1   , 1   )
1450        #BoneMorph.SetPosition("sintyou", "Bip01 Head"        , 0.9 , 1   , 1   , 1.1 , 1   , 1   )
1451        #BoneMorph.SetPosition("sintyou", "Bip01 ? Calf"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1452        #BoneMorph.SetPosition("sintyou", "Bip01 ? Foot"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1453        #BoneMorph.SetScale   ("sintyou", "Bip01 ? UpperArm"  , 0.9 , 1   , 1   , 1.1 , 1   , 1   )
1454        #BoneMorph.SetScale   ("sintyou", "Bip01 ? Thigh_SCL_", 0.87, 1   , 1   , 1.13, 1   , 1   )
1455        #BoneMorph.SetScale   ("sintyou", "momotwist_?"       , 0.87, 1   , 1   , 1.13, 1   , 1   )
1456        #BoneMorph.SetScale   ("sintyou", "Bip01 ? Calf_SCL_" , 0.87, 1   , 1   , 1.13, 1   , 1   )
1457        #BoneMorph.SetScale   ("koshi"  , "Bip01 Pelvis_SCL_" , 1   , 0.8 , 0.92, 1   , 1.2 , 1.08)
1458        #BoneMorph.SetScale   ("koshi"  , "Bip01 Spine_SCL_"  , 1   , 1   , 1   , 1   , 1   , 1   )
1459        #BoneMorph.SetScale   ("koshi"  , "Hip_?"             , 1   , 0.96, 0.9 , 1   , 1.04, 1.1 )
1460        #BoneMorph.SetScale   ("koshi"  , "Skirt"             , 1   , 0.85, 0.88, 1   , 1.2 , 1.12)
1461        #BoneMorph.SetPosition("kata"   , "Bip01 ? Clavicle"  , 0.98, 1   , 0.5 , 1.02, 1   , 1.5 )
1462        #BoneMorph.SetScale   ("kata"   , "Bip01 Spine1a_SCL_", 1   , 1   , 0.95, 1   , 1   , 1.05)
1463        #BoneMorph.SetScale   ("west"   , "Bip01 Spine_SCL_"  , 1   , 0.95, 0.9 , 1   , 1.05, 1.1 )
1464        #BoneMorph.SetScale   ("west"   , "Bip01 Spine0a_SCL_", 1   , 0.85, 0.7 , 1   , 1.15, 1.3 )
1465        #BoneMorph.SetScale   ("west"   , "Bip01 Spine1_SCL_" , 1   , 0.9 , 0.85, 1   , 1.1 , 1.15)
1466        #BoneMorph.SetScale   ("west"   , "Bip01 Spine1a_SCL_", 1   , 0.95, 0.95, 1   , 1.05, 1.05)
1467        #BoneMorph.SetScale   ("west"   , "Skirt"             , 1   , 0.92, 0.88, 1   , 1.08, 1.12)
1468
1469
1470
1471        morph.SetPosition("KubiScl", "Bip01 Neck"         , 1.05, 1   , 1   )
1472        morph.SetPosition("KubiScl", "Bip01 Head"         , 1.2 , 1   , 1   )
1473                                                                      
1474        morph.SetScale   ("UdeScl" , "Bip01 ? UpperArm"   , 1.15, 1   , 1   )
1475                                                                      
1476        morph.SetScale   ("HeadX"  , "Bip01 Head"         , 1   , 1.1 , 1.2 )
1477        morph.SetScale   ("HeadY"  , "Bip01 Head"         , 1.2 , 1.1 , 1   )
1478        
1479        morph.SetPosition("sintyou", "Bip01 Spine"        , 1   , 1   , 1.15)
1480        morph.SetPosition("sintyou", "Bip01 Spine0a"      , 1.12, 1   , 1   )
1481        morph.SetPosition("sintyou", "Bip01 Spine1"       , 1.12, 1   , 1   )
1482        morph.SetPosition("sintyou", "Bip01 Spine1a"      , 1.12, 1   , 1   )
1483        morph.SetPosition("sintyou", "Bip01 Neck"         , 1.03, 1   , 1   )
1484        morph.SetPosition("sintyou", "Bip01 Head"         , 1.1 , 1   , 1   )
1485        morph.SetPosition("sintyou", "Bip01 ? Calf"       , 1.13, 1   , 1   )
1486        morph.SetPosition("sintyou", "Bip01 ? Foot"       , 1.13, 1   , 1   )
1487        morph.SetScale   ("sintyou", "Bip01 ? UpperArm"   , 1.1 , 1   , 1   )
1488        morph.SetScale   ("sintyou", "Bip01 ? Thigh_SCL_" , 1.13, 1   , 1   )
1489        morph.SetScale   ("sintyou", "momotwist_?"        , 1.13, 1   , 1   )
1490        morph.SetScale   ("sintyou", "Bip01 ? Calf_SCL_"  , 1.13, 1   , 1   )
1491                                                                            
1492        # for DouPer, any bone not a thigh or a decendant of one, it's values are inverted
1493        morph.SetPosition("DouPer" , "Bip01 Spine"        , 1, 1, (1-1.06)+1)
1494        morph.SetPosition("DouPer" , "Bip01 Spine0a"      , (1-1.12)+1, 1, 1)
1495        morph.SetPosition("DouPer" , "Bip01 Spine1"       , (1-1.12)+1, 1, 1)
1496        morph.SetPosition("DouPer" , "Bip01 Spine1a"      , (1-1.12)+1, 1, 1)
1497        morph.SetPosition("DouPer" , "Bip01 Neck"         , (1-0.97)+1, 1, 1)
1498        morph.SetScale   ("DouPer" , "Bip01 ? UpperArm"   , (1-1.02)+1, 1, 1)
1499        morph.SetPosition("DouPer" , "Bip01 ? Calf"       ,       1.13, 1, 1)
1500        morph.SetPosition("DouPer" , "Bip01 ? Foot"       ,       1.13, 1, 1)
1501        morph.SetScale   ("DouPer" , "Bip01 ? Thigh_SCL_" ,       1.13, 1, 1)
1502        morph.SetScale   ("DouPer" , "momotwist_?"        ,       1.13, 1, 1)
1503        morph.SetScale   ("DouPer" , "Bip01 ? Calf_SCL_"  ,       1.13, 1, 1)
1504
1505        # This has some issues            
1506        morph.SetScale   ("koshi"  , "Bip01 Pelvis_SCL_"  , 1   , 1.2 , 1.08)
1507        morph.SetScale   ("koshi"  , "Bip01 Spine_SCL_"   , 1   , 1   , 1   )
1508        morph.SetScale   ("koshi"  , "Hip_?"              , 1   , 1.04, 1.1 )
1509        morph.SetScale   ("koshi"  , "Skirt"              , 1   , 1.2 , 1.12)
1510                                     
1511        #morph.SetPosition("kata"   , "Bip01 ? Clavicle"   , 1.02, 1   , 1.5, default=0)
1512        morph.SetPosition("kata"   , "Bip01 ? Clavicle"   , 1.02, 1   , 1.5 , default=50)
1513        morph.SetScale   ("kata"   , "Bip01 Spine1a_SCL_" , 1   , 1   , 1.05, default=50)
1514                                        
1515        morph.SetScale   ("west"   , "Bip01 Spine_SCL_"   , 1   , 1.05, 1.1 )
1516        morph.SetScale   ("west"   , "Bip01 Spine0a_SCL_" , 1   , 1.15, 1.3 )
1517        morph.SetScale   ("west"   , "Bip01 Spine1_SCL_"  , 1   , 1.1 , 1.15)
1518        morph.SetScale   ("west"   , "Bip01 Spine1a_SCL_" , 1   , 1.05, 1.05)
1519        morph.SetScale   ("west"   , "Skirt"              , 1   , 1.08, 1.12)
1520        
1521        # WideSlider functions MUST be called AFTER all BoneMorph calls
1522        sliders.SetPosition("THIPOS"    , "Bip01 ? Thigh"     ,  0    ,  0.001,  0.001, axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1523        sliders.SetPosition("THI2POS"   , "Bip01 ? Thigh_SCL_",  0.001,  0.001,  0.001, axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1524        sliders.SetPosition("HIPPOS"    , "Hip_?"             ,  0.001,  0.001,  0.001, axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1525        sliders.SetPosition("MTWPOS"    , "momotwist_?"       ,  0.1  ,  0.1  , -0.1  , axisFlip=2                     ) #axisFlip=2 #axisFlip=2
1526        sliders.SetPosition("MMNPOS"    , "momoniku_?"        ,  0.1  ,  0.1  , -0.1  , axisFlip=1                     ) #axisFlip=1 #axisFlip=1
1527        sliders.SetPosition("SKTPOS"    , "Skirt"             , -0.1  , -0.1  ,  0.1  ,             axisOrder=[2, 1, 0]) #           #          
1528        sliders.SetPosition("SPIPOS"    , "Bip01 Spine"       , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1529        sliders.SetPosition("S0APOS"    , "Bip01 Spine0a"     , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1530        sliders.SetPosition("S1POS"     , "Bip01 Spine1"      , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1531        sliders.SetPosition("S1APOS"    , "Bip01 Spine1a"     , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1532        sliders.SetPosition("NECKPOS"   , "Bip01 Neck"        , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1533        sliders.SetPosition("CLVPOS"    , "Bip01 ? Clavicle"  , -0.1  ,  0.1  , -0.1  , axisFlip=2                     ) #axisFlip=2 #axisFlip=2
1534        sliders.SetPosition("MUNESUBPOS", "Mune_?_sub"        , -0.1  ,  0.1  ,  0.1  , axisFlip=1, axisOrder=[2, 1, 0]) #axisFlip=1 #axisFlip=2
1535        sliders.SetPosition("MUNEPOS"   , "Mune_?"            ,  0.1  , -0.1  , -0.1  , axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1536                                                                                                                                     
1537        sliders.SetScale   ("THISCL"    , "Bip01 ? Thigh"     , axisOrder=[0, 1, -1])
1538        sliders.SetScale   ("MTWSCL"    , "momotwist_?"       )
1539        sliders.SetScale   ("MMNSCL"    , "momoniku_?"        )
1540        sliders.SetScale   ("PELSCL"    , "Bip01 Pelvis_SCL_" )
1541        sliders.SetScale   ("THISCL2"   , "Bip01 ? Thigh_SCL_")#, axisOrder=[0, 1, -1])
1542        sliders.SetScale   ("CALFSCL"   , "Bip01 ? Calf"      )#, axisOrder=[0, 1, -1])
1543        sliders.SetScale   ("FOOTSCL"   , "Bip01 ? Foot"      )
1544        sliders.SetScale   ("SKTSCL"    , "Skirt"             )
1545        sliders.SetScale   ("SPISCL"    , "Bip01 Spine_SCL_"  )
1546        sliders.SetScale   ("S0ASCL"    , "Bip01 Spine0a_SCL_")
1547        sliders.SetScale   ("S1_SCL"    , "Bip01 Spine1_SCL_" )
1548        sliders.SetScale   ("S1ASCL"    , "Bip01 Spine1a_SCL_")
1549        sliders.SetScale   ("S1ABASESCL", "Bip01 Spine1a"     )#, axisOrder=[0, 1, -1]))
1550        sliders.SetScale   ("KATASCL"   , "Kata_?"            )
1551        sliders.SetScale   ("UPARMSCL"  , "Bip01 ? UpperArm"  )
1552        sliders.SetScale   ("FARMSCL"   , "Bip01 ? Forearm"   )
1553        sliders.SetScale   ("HANDSCL"   , "Bip01 ? Hand"      )
1554        sliders.SetScale   ("CLVSCL"    , "Bip01 ? Clavicle"  )
1555        sliders.SetScale   ("MUNESCL"   , "Mune_?"            )
1556        sliders.SetScale   ("MUNESUBSCL", "Mune_?_sub"        )
1557        sliders.SetScale   ("NECKSCL"   , "Bip01 Neck_SCL_"   )
1558        sliders.SetScale   ("HIPSCL"    , "Hip_?"             )
1559        sliders.SetScale   ("PELSCL"    , "Hip_?"             ) # hips are also scaled with pelvis
1560        
1561        if self.is_fix_thigh:
1562            bone = morph.GetPoseBone("momoniku_?")
1563            bone.rotation_quaternion[0] = 0.997714
1564            bone.rotation_quaternion[3] = -0.06758
1565            bone = morph.GetPoseBone("momoniku_?", flip=True)
1566            bone.rotation_quaternion[0] = 0.997714
1567            bone.rotation_quaternion[3] = 0.06758
1568            
1569        if self.is_drive_shape_keys:
1570            for child in ob.children:
1571                if child.type == 'MESH':
1572                    sks = child.data.shape_keys.key_blocks
1573                    self.driveShapeKey(sks.get('arml'    ), morph, 'ArmL'    , "ArmL     * 0.01")
1574                    self.driveShapeKey(sks.get('hara'    ), morph, 'Hara'    , "Hara     * 0.01")
1575                    self.driveShapeKey(sks.get('munel'   ), morph, 'MuneL'   , "MuneL    * 0.01", set_max=2)
1576                    self.driveShapeKey(sks.get('munes'   ), morph, 'MuneS'   , "MuneS    * 0.01")
1577                    self.driveShapeKey(sks.get('munetare'), morph, 'MuneTare', "MuneTare * 0.01", set_max=2)
1578                    self.driveShapeKey(sks.get('regfat'  ), morph, 'RegFat'  , "RegFat   * 0.01")
1579                    self.driveShapeKey(sks.get('regmeet' ), morph, 'RegMeet' , "RegMeet  * 0.01")
1580
1581        if True:
1582            bones = ob.pose.bones
1583            Mune_L = bones.get('Mune_L') or bones.get('Mune_*.L')
1584            Mune_R = bones.get('Mune_R') or bones.get('Mune_*.R')
1585            if Mune_L:
1586                Mune_L.rotation_mode = 'XYZ'
1587            if Mune_R:                  
1588                Mune_R.rotation_mode = 'XYZ'
1589            
1590            self.driveTwistBone(Mune_R, axis=0, expression="-(self.id_data.cm3d2_bone_morph.MuneUpDown-50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00060")
1591            self.driveTwistBone(Mune_L, axis=0, expression="+(self.id_data.cm3d2_bone_morph.MuneUpDown-50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00060")
1592            self.driveTwistBone(Mune_R, axis=2, expression="-(self.id_data.cm3d2_bone_morph.MuneYori  -50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00025")
1593            self.driveTwistBone(Mune_L, axis=2, expression="-(self.id_data.cm3d2_bone_morph.MuneYori  -50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00025")
1594
1595
1596
1597        
1598
1599        bpy.ops.object.mode_set(mode=pre_mode)
1600        
1601        return {'FINISHED'}
bl_idname = 'object.add_cm3d2_body_sliders'
bl_label = 'Add CM3D2 Body Sliders'
bl_description = 'Adds drivers to armature to enable body sliders.'
bl_options = {'REGISTER', 'UNDO'}
scale: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}>
is_fix_thigh: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Fix Thigh', 'default': False, 'description': 'Fix twist bone values for the thighs in motor-cycle pose', 'attr': 'is_fix_thigh'}> = <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Fix Thigh', 'default': False, 'description': 'Fix twist bone values for the thighs in motor-cycle pose', 'attr': 'is_fix_thigh'}>
is_drive_shape_keys: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Drive Shape Keys', 'default': True, 'description': "Connect sliders to mesh children's shape keys", 'attr': 'is_drive_shape_keys'}> = <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Drive Shape Keys', 'default': True, 'description': "Connect sliders to mesh children's shape keys", 'attr': 'is_drive_shape_keys'}>
@classmethod
def poll(cls, context):
1353    @classmethod
1354    def poll(cls, context):
1355        ob = context.object
1356        if ob:
1357            arm = ob.data
1358        else:
1359            arm = None
1360        has_arm  = arm and isinstance(arm, bpy.types.Armature) and ("Bip01" in arm.bones)
1361        can_edit = (ob and ob.data == arm) or (arm and arm.is_editmode)
1362        return has_arm and can_edit
def invoke(self, context, event):
1364    def invoke(self, context, event):
1365        self.scale = common.preferences().scale
1366        return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
1368    def draw(self, context):
1369        self.layout.prop(self, 'scale'              )
1370        #self.layout.prop(self, 'is_fix_thigh'       )
1371        self.layout.prop(self, 'is_drive_shape_keys')
def driveShapeKey(self, shapekey, data, prop, expression, set_min=None, set_max=None):
1373    def driveShapeKey(self, shapekey, data, prop, expression, set_min=None, set_max=None):
1374        if not shapekey:
1375            return
1376        driver = shapekey.driver_add('value').driver
1377        driver.type = 'SCRIPTED'
1378
1379        driver_var = driver.variables.new() if len(driver.variables) < 1 else driver.variables[0]
1380        driver_var.type = 'SINGLE_PROP'
1381        driver_var.name = prop
1382
1383        driver_target = driver_var.targets[0]
1384        driver_target.id_type = 'OBJECT'
1385        driver_target.id = data.id_data
1386        driver_target.data_path = data.path_from_id(prop)
1387
1388        driver.expression = expression
1389
1390        if set_min:
1391            shapekey.slider_min = set_min
1392        if set_max:
1393            shapekey.slider_max = set_max
def driveTwistBone(self, bone, prop='rotation_euler', axis=0, expression=''):
1395    def driveTwistBone(self, bone, prop='rotation_euler', axis=0, expression=""):
1396        if not bone:
1397            return
1398        driver = bone.driver_add(prop, axis).driver
1399        driver.type = 'SCRIPTED'
1400        driver.use_self = True
1401
1402        driver.expression = expression
def execute(self, context):
1404    def execute(self, context):
1405        ob = context.object
1406        arm = ob.data
1407        pre_mode = ob.mode
1408        #if pre_mode != 'EDIT':
1409        #    override = context.copy()
1410        #    override['active_object'] = ob
1411        #    bpy.ops.object.mode_set(override, mode='EDIT')
1412
1413        morph   = ob.cm3d2_bone_morph
1414        sliders = ob.cm3d2_wide_slider
1415
1416        morph.scale   = self.scale
1417        sliders.scale = self.scale
1418
1419
1420
1421        #BoneMorph.SetPosition("KubiScl", "Bip01 Neck"        , 0.95, 1   , 1   , 1.05, 1   , 1   )
1422        #BoneMorph.SetPosition("KubiScl", "Bip01 Head"        , 0.8 , 1   , 1   , 1.2 , 1   , 1   )
1423        #BoneMorph.SetScale   ("UdeScl" , "Bip01 ? UpperArm"  , 0.85, 1   , 1   , 1.15, 1   , 1   )
1424        #BoneMorph.SetScale   ("EyeSclX", "Eyepos_L"          , 1   , 1   , 0.92, 1   , 1   , 1.08)
1425        #BoneMorph.SetScale   ("EyeSclX", "Eyepos_R"          , 1   , 1   , 0.92, 1   , 1   , 1.08)
1426        #BoneMorph.SetScale   ("EyeSclY", "Eyepos_L"          , 1   , 0.92, 1   , 1   , 1.08, 1   )
1427        #BoneMorph.SetScale   ("EyeSclY", "Eyepos_R"          , 1   , 0.92, 1   , 1   , 1.08, 1   )
1428        #BoneMorph.SetPosition("EyePosX", "Eyepos_R"          , 1   , 1   , 0.9 , 1   , 1   , 1.1 )
1429        #BoneMorph.SetPosition("EyePosX", "Eyepos_L"          , 1   , 1   , 0.9 , 1   , 1   , 1.1 )
1430        #BoneMorph.SetPosition("EyePosY", "Eyepos_R"          , 1   , 0.93, 1   , 1   , 1.07, 1   )
1431        #BoneMorph.SetPosition("EyePosY", "Eyepos_L"          , 1   , 0.93, 1   , 1   , 1.07, 1   )
1432        #BoneMorph.SetScale   ("HeadX"  , "Bip01 Head"        , 1   , 0.9 , 0.8 , 1   , 1.1 , 1.2 )
1433        #BoneMorph.SetScale   ("HeadY"  , "Bip01 Head"        , 0.8 , 0.9 , 1   , 1.2 , 1.1 , 1   )
1434        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine"       , 1   , 1   , 0.94, 1   , 1   , 1.06)
1435        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine0a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1436        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine1"      , 0.88, 1   , 1   , 1.12, 1   , 1   )
1437        #BoneMorph.SetPosition("DouPer" , "Bip01 Spine1a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1438        #BoneMorph.SetPosition("DouPer" , "Bip01 Neck"        , 1.03, 1   , 1   , 0.97, 1   , 1   )
1439        #BoneMorph.SetPosition("DouPer" , "Bip01 ? Calf"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1440        #BoneMorph.SetPosition("DouPer" , "Bip01 ? Foot"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1441        #BoneMorph.SetScale   ("DouPer" , "Bip01 ? Thigh_SCL_", 0.87, 1   , 1   , 1.13, 1   , 1   )
1442        #BoneMorph.SetScale   ("DouPer" , "momotwist_?"       , 0.87, 1   , 1   , 1.13, 1   , 1   )
1443        #BoneMorph.SetScale   ("DouPer" , "Bip01 ? Calf_SCL_" , 0.87, 1   , 1   , 1.13, 1   , 1   )
1444        #BoneMorph.SetScale   ("DouPer" , "Bip01 ? UpperArm"  , 0.98, 1   , 1   , 1.02, 1   , 1   )
1445        #BoneMorph.SetPosition("sintyou", "Bip01 Spine"       , 1   , 1   , 0.85, 1   , 1   , 1.15)
1446        #BoneMorph.SetPosition("sintyou", "Bip01 Spine0a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1447        #BoneMorph.SetPosition("sintyou", "Bip01 Spine1"      , 0.88, 1   , 1   , 1.12, 1   , 1   )
1448        #BoneMorph.SetPosition("sintyou", "Bip01 Spine1a"     , 0.88, 1   , 1   , 1.12, 1   , 1   )
1449        #BoneMorph.SetPosition("sintyou", "Bip01 Neck"        , 0.97, 1   , 1   , 1.03, 1   , 1   )
1450        #BoneMorph.SetPosition("sintyou", "Bip01 Head"        , 0.9 , 1   , 1   , 1.1 , 1   , 1   )
1451        #BoneMorph.SetPosition("sintyou", "Bip01 ? Calf"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1452        #BoneMorph.SetPosition("sintyou", "Bip01 ? Foot"      , 0.87, 1   , 1   , 1.13, 1   , 1   )
1453        #BoneMorph.SetScale   ("sintyou", "Bip01 ? UpperArm"  , 0.9 , 1   , 1   , 1.1 , 1   , 1   )
1454        #BoneMorph.SetScale   ("sintyou", "Bip01 ? Thigh_SCL_", 0.87, 1   , 1   , 1.13, 1   , 1   )
1455        #BoneMorph.SetScale   ("sintyou", "momotwist_?"       , 0.87, 1   , 1   , 1.13, 1   , 1   )
1456        #BoneMorph.SetScale   ("sintyou", "Bip01 ? Calf_SCL_" , 0.87, 1   , 1   , 1.13, 1   , 1   )
1457        #BoneMorph.SetScale   ("koshi"  , "Bip01 Pelvis_SCL_" , 1   , 0.8 , 0.92, 1   , 1.2 , 1.08)
1458        #BoneMorph.SetScale   ("koshi"  , "Bip01 Spine_SCL_"  , 1   , 1   , 1   , 1   , 1   , 1   )
1459        #BoneMorph.SetScale   ("koshi"  , "Hip_?"             , 1   , 0.96, 0.9 , 1   , 1.04, 1.1 )
1460        #BoneMorph.SetScale   ("koshi"  , "Skirt"             , 1   , 0.85, 0.88, 1   , 1.2 , 1.12)
1461        #BoneMorph.SetPosition("kata"   , "Bip01 ? Clavicle"  , 0.98, 1   , 0.5 , 1.02, 1   , 1.5 )
1462        #BoneMorph.SetScale   ("kata"   , "Bip01 Spine1a_SCL_", 1   , 1   , 0.95, 1   , 1   , 1.05)
1463        #BoneMorph.SetScale   ("west"   , "Bip01 Spine_SCL_"  , 1   , 0.95, 0.9 , 1   , 1.05, 1.1 )
1464        #BoneMorph.SetScale   ("west"   , "Bip01 Spine0a_SCL_", 1   , 0.85, 0.7 , 1   , 1.15, 1.3 )
1465        #BoneMorph.SetScale   ("west"   , "Bip01 Spine1_SCL_" , 1   , 0.9 , 0.85, 1   , 1.1 , 1.15)
1466        #BoneMorph.SetScale   ("west"   , "Bip01 Spine1a_SCL_", 1   , 0.95, 0.95, 1   , 1.05, 1.05)
1467        #BoneMorph.SetScale   ("west"   , "Skirt"             , 1   , 0.92, 0.88, 1   , 1.08, 1.12)
1468
1469
1470
1471        morph.SetPosition("KubiScl", "Bip01 Neck"         , 1.05, 1   , 1   )
1472        morph.SetPosition("KubiScl", "Bip01 Head"         , 1.2 , 1   , 1   )
1473                                                                      
1474        morph.SetScale   ("UdeScl" , "Bip01 ? UpperArm"   , 1.15, 1   , 1   )
1475                                                                      
1476        morph.SetScale   ("HeadX"  , "Bip01 Head"         , 1   , 1.1 , 1.2 )
1477        morph.SetScale   ("HeadY"  , "Bip01 Head"         , 1.2 , 1.1 , 1   )
1478        
1479        morph.SetPosition("sintyou", "Bip01 Spine"        , 1   , 1   , 1.15)
1480        morph.SetPosition("sintyou", "Bip01 Spine0a"      , 1.12, 1   , 1   )
1481        morph.SetPosition("sintyou", "Bip01 Spine1"       , 1.12, 1   , 1   )
1482        morph.SetPosition("sintyou", "Bip01 Spine1a"      , 1.12, 1   , 1   )
1483        morph.SetPosition("sintyou", "Bip01 Neck"         , 1.03, 1   , 1   )
1484        morph.SetPosition("sintyou", "Bip01 Head"         , 1.1 , 1   , 1   )
1485        morph.SetPosition("sintyou", "Bip01 ? Calf"       , 1.13, 1   , 1   )
1486        morph.SetPosition("sintyou", "Bip01 ? Foot"       , 1.13, 1   , 1   )
1487        morph.SetScale   ("sintyou", "Bip01 ? UpperArm"   , 1.1 , 1   , 1   )
1488        morph.SetScale   ("sintyou", "Bip01 ? Thigh_SCL_" , 1.13, 1   , 1   )
1489        morph.SetScale   ("sintyou", "momotwist_?"        , 1.13, 1   , 1   )
1490        morph.SetScale   ("sintyou", "Bip01 ? Calf_SCL_"  , 1.13, 1   , 1   )
1491                                                                            
1492        # for DouPer, any bone not a thigh or a decendant of one, it's values are inverted
1493        morph.SetPosition("DouPer" , "Bip01 Spine"        , 1, 1, (1-1.06)+1)
1494        morph.SetPosition("DouPer" , "Bip01 Spine0a"      , (1-1.12)+1, 1, 1)
1495        morph.SetPosition("DouPer" , "Bip01 Spine1"       , (1-1.12)+1, 1, 1)
1496        morph.SetPosition("DouPer" , "Bip01 Spine1a"      , (1-1.12)+1, 1, 1)
1497        morph.SetPosition("DouPer" , "Bip01 Neck"         , (1-0.97)+1, 1, 1)
1498        morph.SetScale   ("DouPer" , "Bip01 ? UpperArm"   , (1-1.02)+1, 1, 1)
1499        morph.SetPosition("DouPer" , "Bip01 ? Calf"       ,       1.13, 1, 1)
1500        morph.SetPosition("DouPer" , "Bip01 ? Foot"       ,       1.13, 1, 1)
1501        morph.SetScale   ("DouPer" , "Bip01 ? Thigh_SCL_" ,       1.13, 1, 1)
1502        morph.SetScale   ("DouPer" , "momotwist_?"        ,       1.13, 1, 1)
1503        morph.SetScale   ("DouPer" , "Bip01 ? Calf_SCL_"  ,       1.13, 1, 1)
1504
1505        # This has some issues            
1506        morph.SetScale   ("koshi"  , "Bip01 Pelvis_SCL_"  , 1   , 1.2 , 1.08)
1507        morph.SetScale   ("koshi"  , "Bip01 Spine_SCL_"   , 1   , 1   , 1   )
1508        morph.SetScale   ("koshi"  , "Hip_?"              , 1   , 1.04, 1.1 )
1509        morph.SetScale   ("koshi"  , "Skirt"              , 1   , 1.2 , 1.12)
1510                                     
1511        #morph.SetPosition("kata"   , "Bip01 ? Clavicle"   , 1.02, 1   , 1.5, default=0)
1512        morph.SetPosition("kata"   , "Bip01 ? Clavicle"   , 1.02, 1   , 1.5 , default=50)
1513        morph.SetScale   ("kata"   , "Bip01 Spine1a_SCL_" , 1   , 1   , 1.05, default=50)
1514                                        
1515        morph.SetScale   ("west"   , "Bip01 Spine_SCL_"   , 1   , 1.05, 1.1 )
1516        morph.SetScale   ("west"   , "Bip01 Spine0a_SCL_" , 1   , 1.15, 1.3 )
1517        morph.SetScale   ("west"   , "Bip01 Spine1_SCL_"  , 1   , 1.1 , 1.15)
1518        morph.SetScale   ("west"   , "Bip01 Spine1a_SCL_" , 1   , 1.05, 1.05)
1519        morph.SetScale   ("west"   , "Skirt"              , 1   , 1.08, 1.12)
1520        
1521        # WideSlider functions MUST be called AFTER all BoneMorph calls
1522        sliders.SetPosition("THIPOS"    , "Bip01 ? Thigh"     ,  0    ,  0.001,  0.001, axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1523        sliders.SetPosition("THI2POS"   , "Bip01 ? Thigh_SCL_",  0.001,  0.001,  0.001, axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1524        sliders.SetPosition("HIPPOS"    , "Hip_?"             ,  0.001,  0.001,  0.001, axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1525        sliders.SetPosition("MTWPOS"    , "momotwist_?"       ,  0.1  ,  0.1  , -0.1  , axisFlip=2                     ) #axisFlip=2 #axisFlip=2
1526        sliders.SetPosition("MMNPOS"    , "momoniku_?"        ,  0.1  ,  0.1  , -0.1  , axisFlip=1                     ) #axisFlip=1 #axisFlip=1
1527        sliders.SetPosition("SKTPOS"    , "Skirt"             , -0.1  , -0.1  ,  0.1  ,             axisOrder=[2, 1, 0]) #           #          
1528        sliders.SetPosition("SPIPOS"    , "Bip01 Spine"       , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1529        sliders.SetPosition("S0APOS"    , "Bip01 Spine0a"     , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1530        sliders.SetPosition("S1POS"     , "Bip01 Spine1"      , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1531        sliders.SetPosition("S1APOS"    , "Bip01 Spine1a"     , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1532        sliders.SetPosition("NECKPOS"   , "Bip01 Neck"        , -0.1  ,  0.1  ,  0.1                                   ) #           #          
1533        sliders.SetPosition("CLVPOS"    , "Bip01 ? Clavicle"  , -0.1  ,  0.1  , -0.1  , axisFlip=2                     ) #axisFlip=2 #axisFlip=2
1534        sliders.SetPosition("MUNESUBPOS", "Mune_?_sub"        , -0.1  ,  0.1  ,  0.1  , axisFlip=1, axisOrder=[2, 1, 0]) #axisFlip=1 #axisFlip=2
1535        sliders.SetPosition("MUNEPOS"   , "Mune_?"            ,  0.1  , -0.1  , -0.1  , axisFlip=2, axisOrder=[1, 2, 0]) #axisFlip=2 #axisFlip=0
1536                                                                                                                                     
1537        sliders.SetScale   ("THISCL"    , "Bip01 ? Thigh"     , axisOrder=[0, 1, -1])
1538        sliders.SetScale   ("MTWSCL"    , "momotwist_?"       )
1539        sliders.SetScale   ("MMNSCL"    , "momoniku_?"        )
1540        sliders.SetScale   ("PELSCL"    , "Bip01 Pelvis_SCL_" )
1541        sliders.SetScale   ("THISCL2"   , "Bip01 ? Thigh_SCL_")#, axisOrder=[0, 1, -1])
1542        sliders.SetScale   ("CALFSCL"   , "Bip01 ? Calf"      )#, axisOrder=[0, 1, -1])
1543        sliders.SetScale   ("FOOTSCL"   , "Bip01 ? Foot"      )
1544        sliders.SetScale   ("SKTSCL"    , "Skirt"             )
1545        sliders.SetScale   ("SPISCL"    , "Bip01 Spine_SCL_"  )
1546        sliders.SetScale   ("S0ASCL"    , "Bip01 Spine0a_SCL_")
1547        sliders.SetScale   ("S1_SCL"    , "Bip01 Spine1_SCL_" )
1548        sliders.SetScale   ("S1ASCL"    , "Bip01 Spine1a_SCL_")
1549        sliders.SetScale   ("S1ABASESCL", "Bip01 Spine1a"     )#, axisOrder=[0, 1, -1]))
1550        sliders.SetScale   ("KATASCL"   , "Kata_?"            )
1551        sliders.SetScale   ("UPARMSCL"  , "Bip01 ? UpperArm"  )
1552        sliders.SetScale   ("FARMSCL"   , "Bip01 ? Forearm"   )
1553        sliders.SetScale   ("HANDSCL"   , "Bip01 ? Hand"      )
1554        sliders.SetScale   ("CLVSCL"    , "Bip01 ? Clavicle"  )
1555        sliders.SetScale   ("MUNESCL"   , "Mune_?"            )
1556        sliders.SetScale   ("MUNESUBSCL", "Mune_?_sub"        )
1557        sliders.SetScale   ("NECKSCL"   , "Bip01 Neck_SCL_"   )
1558        sliders.SetScale   ("HIPSCL"    , "Hip_?"             )
1559        sliders.SetScale   ("PELSCL"    , "Hip_?"             ) # hips are also scaled with pelvis
1560        
1561        if self.is_fix_thigh:
1562            bone = morph.GetPoseBone("momoniku_?")
1563            bone.rotation_quaternion[0] = 0.997714
1564            bone.rotation_quaternion[3] = -0.06758
1565            bone = morph.GetPoseBone("momoniku_?", flip=True)
1566            bone.rotation_quaternion[0] = 0.997714
1567            bone.rotation_quaternion[3] = 0.06758
1568            
1569        if self.is_drive_shape_keys:
1570            for child in ob.children:
1571                if child.type == 'MESH':
1572                    sks = child.data.shape_keys.key_blocks
1573                    self.driveShapeKey(sks.get('arml'    ), morph, 'ArmL'    , "ArmL     * 0.01")
1574                    self.driveShapeKey(sks.get('hara'    ), morph, 'Hara'    , "Hara     * 0.01")
1575                    self.driveShapeKey(sks.get('munel'   ), morph, 'MuneL'   , "MuneL    * 0.01", set_max=2)
1576                    self.driveShapeKey(sks.get('munes'   ), morph, 'MuneS'   , "MuneS    * 0.01")
1577                    self.driveShapeKey(sks.get('munetare'), morph, 'MuneTare', "MuneTare * 0.01", set_max=2)
1578                    self.driveShapeKey(sks.get('regfat'  ), morph, 'RegFat'  , "RegFat   * 0.01")
1579                    self.driveShapeKey(sks.get('regmeet' ), morph, 'RegMeet' , "RegMeet  * 0.01")
1580
1581        if True:
1582            bones = ob.pose.bones
1583            Mune_L = bones.get('Mune_L') or bones.get('Mune_*.L')
1584            Mune_R = bones.get('Mune_R') or bones.get('Mune_*.R')
1585            if Mune_L:
1586                Mune_L.rotation_mode = 'XYZ'
1587            if Mune_R:                  
1588                Mune_R.rotation_mode = 'XYZ'
1589            
1590            self.driveTwistBone(Mune_R, axis=0, expression="-(self.id_data.cm3d2_bone_morph.MuneUpDown-50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00060")
1591            self.driveTwistBone(Mune_L, axis=0, expression="+(self.id_data.cm3d2_bone_morph.MuneUpDown-50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00060")
1592            self.driveTwistBone(Mune_R, axis=2, expression="-(self.id_data.cm3d2_bone_morph.MuneYori  -50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00025")
1593            self.driveTwistBone(Mune_L, axis=2, expression="-(self.id_data.cm3d2_bone_morph.MuneYori  -50) * self.id_data.cm3d2_bone_morph.MuneL * (pi/180) * 0.00025")
1594
1595
1596
1597        
1598
1599        bpy.ops.object.mode_set(mode=pre_mode)
1600        
1601        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("OBJECT_OT_add_cm3d2_body_sliders")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class DATA_PT_cm3d2_sliders(bpy_types.Panel):
1605@compat.BlRegister()
1606class DATA_PT_cm3d2_sliders(bpy.types.Panel):
1607    bl_space_type  = 'PROPERTIES'
1608    bl_region_type = 'WINDOW'
1609    bl_context     = 'data'
1610    bl_label       = 'CM3D2 Sliders'
1611    bl_idname      = 'DATA_PT_cm3d2_sliders'
1612
1613    @classmethod
1614    def poll(cls, context):
1615        ob = context.object
1616        if ob:
1617            arm = ob.data
1618        else:
1619            arm = None
1620        return arm and isinstance(arm, bpy.types.Armature) and ("Bip01" in arm.bones)
1621
1622    def draw(self, context):
1623        ob = context.object
1624        if ob:
1625            arm = ob.data
1626        else:
1627            arm = None
1628
1629        morph = ob.cm3d2_bone_morph
1630        self.layout.alignment = 'RIGHT'
1631        if compat.IS_LEGACY:
1632            flow = self.layout.column_flow(align=True)
1633        else:
1634            flow = self.layout.grid_flow(row_major=True, columns=2, align=True)
1635            flow.use_property_split    = True
1636            flow.use_property_decorate = False
1637        flow.prop(morph, 'height', text="Height", emboss=False)
1638        flow.prop(morph, 'weight', text="Weight", emboss=False)
1639        flow.prop(morph, 'bust'  , text="Bust"  , emboss=False)
1640        flow.prop(morph, 'cup'   , text="Cup"   , emboss=False)
1641        flow.prop(morph, 'waist' , text="Waist" , emboss=False)
1642        flow.prop(morph, 'hip'   , text="Hip"   , emboss=False)
1643                                
1644        row = self.layout.row()
1645        #row.enabled = bpy.ops.object.add_cm3d2_body_sliders.poll(context.copy())
1646        op = row.operator("object.add_cm3d2_body_sliders", text="Connect Sliders"    , icon=compat.icon('CONSTRAINT_BONE'))
1647        
1648        row = self.layout.row()
1649        #row.enabled = bpy.ops.object.cleanup_scale_bones.poll(context.copy())
1650        op = row.operator("object.cleanup_scale_bones"   , text="Cleanup Scale Bones", icon=compat.icon('X'              ))
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'data'
bl_label = 'CM3D2 Sliders'
bl_idname = 'DATA_PT_cm3d2_sliders'
@classmethod
def poll(cls, context):
1613    @classmethod
1614    def poll(cls, context):
1615        ob = context.object
1616        if ob:
1617            arm = ob.data
1618        else:
1619            arm = None
1620        return arm and isinstance(arm, bpy.types.Armature) and ("Bip01" in arm.bones)
def draw(self, context):
1622    def draw(self, context):
1623        ob = context.object
1624        if ob:
1625            arm = ob.data
1626        else:
1627            arm = None
1628
1629        morph = ob.cm3d2_bone_morph
1630        self.layout.alignment = 'RIGHT'
1631        if compat.IS_LEGACY:
1632            flow = self.layout.column_flow(align=True)
1633        else:
1634            flow = self.layout.grid_flow(row_major=True, columns=2, align=True)
1635            flow.use_property_split    = True
1636            flow.use_property_decorate = False
1637        flow.prop(morph, 'height', text="Height", emboss=False)
1638        flow.prop(morph, 'weight', text="Weight", emboss=False)
1639        flow.prop(morph, 'bust'  , text="Bust"  , emboss=False)
1640        flow.prop(morph, 'cup'   , text="Cup"   , emboss=False)
1641        flow.prop(morph, 'waist' , text="Waist" , emboss=False)
1642        flow.prop(morph, 'hip'   , text="Hip"   , emboss=False)
1643                                
1644        row = self.layout.row()
1645        #row.enabled = bpy.ops.object.add_cm3d2_body_sliders.poll(context.copy())
1646        op = row.operator("object.add_cm3d2_body_sliders", text="Connect Sliders"    , icon=compat.icon('CONSTRAINT_BONE'))
1647        
1648        row = self.layout.row()
1649        #row.enabled = bpy.ops.object.cleanup_scale_bones.poll(context.copy())
1650        op = row.operator("object.cleanup_scale_bones"   , text="Cleanup Scale Bones", icon=compat.icon('X'              ))
bl_rna = <bpy_struct, Struct("DATA_PT_cm3d2_sliders")>
Inherited Members
bpy_types._GenericUI
is_extended
append
prepend
remove
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class DATA_PT_cm3d2_body_sliders(bpy_types.Panel):
1655@compat.BlRegister()
1656class DATA_PT_cm3d2_body_sliders(bpy.types.Panel):
1657    bl_space_type  = 'PROPERTIES'
1658    bl_region_type = 'WINDOW'
1659    bl_context     = 'data'
1660    bl_label       = 'Body Sliders'
1661    bl_idname      = 'DATA_PT_cm3d2_body_sliders'
1662    bl_parent_id   = 'DATA_PT_cm3d2_sliders'
1663    bl_options     = {'DEFAULT_CLOSED'}
1664
1665    @classmethod
1666    def poll(cls, context):
1667        return context.object and True
1668
1669    def draw(self, context):
1670        morph = context.object.cm3d2_bone_morph
1671        self.layout.operator('object.save_cm3d2_body_sliders_to_menu', icon=compat.icon('COPYDOWN'))
1672
1673        if compat.IS_LEGACY:
1674            flow = self.layout.column_flow(columns=1)
1675        else:
1676            self.layout.use_property_split = True
1677            flow = self.layout.column_flow()
1678        flow.scale_x = 0.5
1679        col = flow.column(align=True); col.prop(morph, 'HeadX'     , text="Face Width"  , slider=True)
1680        pass;                          col.prop(morph, 'HeadY'     , text="Face Height" , slider=True)
1681        col = flow.column(align=True); col.prop(morph, 'DouPer'    , text="Leg Length"  , slider=True)
1682        pass;                          col.prop(morph, 'sintyou'   , text="Height"      , slider=True)
1683        col = flow.column(align=True); col.prop(morph, 'BreastSize', text="Breast Size" , slider=True)
1684        pass;                          col.prop(morph, 'MuneTare'  , text="Breast Sag"  , slider=True)
1685        pass;                          col.prop(morph, 'MuneUpDown', text="Breast Pitch", slider=True)
1686        pass;                          col.prop(morph, 'MuneYori'  , text="Breast Yaw"  , slider=True)
1687        col = flow.column(align=True); col.prop(morph, 'west'      , text="Waist"       , slider=True)
1688        pass;                          col.prop(morph, 'Hara'      , text="Belly"       , slider=True)
1689        pass;                          col.prop(morph, 'kata'      , text="Shoulders"   , slider=True)
1690        pass;                          col.prop(morph, 'ArmL'      , text="Arm Size"    , slider=True)
1691        pass;                          col.prop(morph, 'UdeScl'    , text="Arm Length"  , slider=True)
1692        pass;                          col.prop(morph, 'KubiScl'   , text="Neck Length" , slider=True)
1693        col = flow.column(align=True); col.prop(morph, 'koshi'     , text="Hip"         , slider=True)
1694        pass;                          col.prop(morph, 'RegFat'    , text="Leg Fat"     , slider=True)
1695        pass;                          col.prop(morph, 'RegMeet'   , text="Leg Meat"    , slider=True)
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'data'
bl_label = 'Body Sliders'
bl_idname = 'DATA_PT_cm3d2_body_sliders'
bl_parent_id = 'DATA_PT_cm3d2_sliders'
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
1665    @classmethod
1666    def poll(cls, context):
1667        return context.object and True
def draw(self, context):
1669    def draw(self, context):
1670        morph = context.object.cm3d2_bone_morph
1671        self.layout.operator('object.save_cm3d2_body_sliders_to_menu', icon=compat.icon('COPYDOWN'))
1672
1673        if compat.IS_LEGACY:
1674            flow = self.layout.column_flow(columns=1)
1675        else:
1676            self.layout.use_property_split = True
1677            flow = self.layout.column_flow()
1678        flow.scale_x = 0.5
1679        col = flow.column(align=True); col.prop(morph, 'HeadX'     , text="Face Width"  , slider=True)
1680        pass;                          col.prop(morph, 'HeadY'     , text="Face Height" , slider=True)
1681        col = flow.column(align=True); col.prop(morph, 'DouPer'    , text="Leg Length"  , slider=True)
1682        pass;                          col.prop(morph, 'sintyou'   , text="Height"      , slider=True)
1683        col = flow.column(align=True); col.prop(morph, 'BreastSize', text="Breast Size" , slider=True)
1684        pass;                          col.prop(morph, 'MuneTare'  , text="Breast Sag"  , slider=True)
1685        pass;                          col.prop(morph, 'MuneUpDown', text="Breast Pitch", slider=True)
1686        pass;                          col.prop(morph, 'MuneYori'  , text="Breast Yaw"  , slider=True)
1687        col = flow.column(align=True); col.prop(morph, 'west'      , text="Waist"       , slider=True)
1688        pass;                          col.prop(morph, 'Hara'      , text="Belly"       , slider=True)
1689        pass;                          col.prop(morph, 'kata'      , text="Shoulders"   , slider=True)
1690        pass;                          col.prop(morph, 'ArmL'      , text="Arm Size"    , slider=True)
1691        pass;                          col.prop(morph, 'UdeScl'    , text="Arm Length"  , slider=True)
1692        pass;                          col.prop(morph, 'KubiScl'   , text="Neck Length" , slider=True)
1693        col = flow.column(align=True); col.prop(morph, 'koshi'     , text="Hip"         , slider=True)
1694        pass;                          col.prop(morph, 'RegFat'    , text="Leg Fat"     , slider=True)
1695        pass;                          col.prop(morph, 'RegMeet'   , text="Leg Meat"    , slider=True)
bl_rna = <bpy_struct, Struct("DATA_PT_cm3d2_body_sliders")>
Inherited Members
bpy_types._GenericUI
is_extended
append
prepend
remove
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class DATA_PT_cm3d2_wide_sliders(bpy_types.Panel):
1698@compat.BlRegister()
1699class DATA_PT_cm3d2_wide_sliders(bpy.types.Panel):
1700    bl_space_type  = 'PROPERTIES'
1701    bl_region_type = 'WINDOW'
1702    bl_context     = 'data'
1703    bl_label       = 'Wide Sliders'
1704    bl_idname      = 'DATA_PT_cm3d2_wide_sliders'
1705    bl_parent_id   = 'DATA_PT_cm3d2_sliders'
1706    bl_options     = {'DEFAULT_CLOSED'}
1707
1708    @classmethod
1709    def poll(cls, context):
1710        return context.object and True
1711
1712    def draw(self, context):
1713        sliders = context.object.cm3d2_wide_slider
1714        
1715        if not compat.IS_LEGACY:
1716            self.layout.use_property_split = True
1717
1718        row = self.layout.row()
1719        if not compat.IS_LEGACY:
1720            row.use_property_decorate = False
1721        row.prop(sliders, "enable_all", text="Enable All Sliders")
1722
1723        if compat.IS_LEGACY:
1724            flow = self.layout.column_flow(columns=2)
1725        else:
1726            flow = self.layout.grid_flow(row_major=True)
1727        flow.scale_x = 0.5
1728
1729        def _transform_prop(name, pos_prop=None, scl_prop=None, pos_enabled=(True, True, True), scl_enabled=(True, True, True)):
1730            #lab = flow.row(align=True)
1731            #lab.alignment = 'RIGHT'
1732            #lab.label(text=name)
1733            #sub = lab.column()
1734            #sub.label(text=name)
1735            #sub.alignment = 'RIGHT'
1736            
1737            tab = flow.column()#align=True)
1738            #tab.alignment = 'LEFT'
1739            #tab.label(text=name)
1740
1741            col = tab.column(align=True)
1742            
1743            global used_name
1744            used_name = False
1745            def _vec_prop(type_name, prop_id, enabled_axes, axis_names):
1746                global used_name
1747                #vec = tab.row(align=True)
1748                #vec.label(text=type_name)
1749                #col = vec.column(align=True)
1750                for i in range(0, 3):
1751                    is_enabled  = enabled_axes[i] or sliders.enable_all
1752                    is_disabled = enabled_axes[i] == None
1753
1754                    if i == 0 and compat.IS_LEGACY:
1755                        if not used_name:
1756                            col.label(text=name)
1757                            used_name = True
1758                            
1759
1760                    row = col.row(align=True)
1761                    row.enabled = not is_disabled and is_enabled
1762                    
1763                    axis_name = axis_names[i]
1764                    if i == 0:
1765                        if compat.IS_LEGACY:
1766                            axis_name = axis_name + " " + type_name
1767                        else:
1768                            axis_name = type_name + " " + axis_name
1769                        if not used_name:
1770                            axis_name = name + " " + axis_name
1771                            used_name = True
1772
1773                    row.prop(
1774                        sliders                                , 
1775                        prop_id if not is_disabled else "empty", 
1776                        text   = axis_name                     , 
1777                        slider = not is_disabled               ,
1778                        emboss = not is_disabled               ,
1779                        index  = -1 if is_disabled else i      ,
1780                    )
1781
1782            if pos_prop:
1783                _vec_prop(iface_("Position"), pos_prop, pos_enabled, ("X", "Y", "Z"))
1784            if scl_prop:
1785                _vec_prop(iface_("Scale"   ), scl_prop, scl_enabled, ("X", "Y", "Z"))
1786
1787
1788        _transform_prop("Pelvis"       , None        , "PELSCL"                                                                           )
1789        _transform_prop("Hips"         , "HIPPOS"    , "HIPSCL"                                                                           )
1790        _transform_prop("Legs"         , "THIPOS"    , "THISCL"    , pos_enabled=(True , None , True ), scl_enabled=(True , True , None ) )
1791        _transform_prop("Thigh"        , "MTWPOS"    , "MTWSCL"                                                                           )
1792        _transform_prop("Rear Thigh"   , "MMNPOS"    , "MMNSCL"                                                                           )
1793        _transform_prop("Knee"         , "THI2POS"   , "THISCL2"                                      , scl_enabled=(True , True , False) )
1794        _transform_prop("Calf"         , None        , "CALFSCL"                                      , scl_enabled=(True , True , False) )
1795        _transform_prop("Foot"         , None        , "FOOTSCL"                                                                          )
1796        _transform_prop("Skirt"        , "SKTPOS"    , "SKTSCL"    , pos_enabled=(False, False, True )                                    )
1797        _transform_prop("Lower Abdomen", "SPIPOS"    , "SPISCL"    , pos_enabled=(True , False, True )                                    )
1798        _transform_prop("Upper Abdomen", "S0APOS"    , "S0ASCL"    , pos_enabled=(True , True , False)                                    )
1799        _transform_prop("Lower Chest"  , "S1POS"     , "S1_SCL"    , pos_enabled=(True , True , False)                                    )
1800        _transform_prop("Upper Chest"  , "S1APOS"    , "S1ASCL"    , pos_enabled=(True , True , False)                                    )
1801        _transform_prop("Upper Torso"  , None        , "S1ABASESCL"                                   , scl_enabled=(True , True , False) )
1802        _transform_prop("Breasts"      , "MUNEPOS"   , "MUNESCL"                                                                          )
1803        _transform_prop("Breasts Sub"  , "MUNESUBPOS", "MUNESUBSCL"                                                                       )
1804        _transform_prop("Neck"         , "NECKPOS"   , "NECKSCL"                                                                          )
1805        _transform_prop("Clavicle"     , "CLVPOS"    , "CLVSCL"                                                                           )
1806        _transform_prop("Shoulders"    , None        , "KATASCL"                                                                          )
1807        _transform_prop("Upper Arm"    , None        , "UPARMSCL"                                                                         )
1808        _transform_prop("Forearm"      , None        , "FARMSCL"                                                                          )
1809        _transform_prop("Hand"         , None        , "HANDSCL"                                                                          )              
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'data'
bl_label = 'Wide Sliders'
bl_idname = 'DATA_PT_cm3d2_wide_sliders'
bl_parent_id = 'DATA_PT_cm3d2_sliders'
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
1708    @classmethod
1709    def poll(cls, context):
1710        return context.object and True
def draw(self, context):
1712    def draw(self, context):
1713        sliders = context.object.cm3d2_wide_slider
1714        
1715        if not compat.IS_LEGACY:
1716            self.layout.use_property_split = True
1717
1718        row = self.layout.row()
1719        if not compat.IS_LEGACY:
1720            row.use_property_decorate = False
1721        row.prop(sliders, "enable_all", text="Enable All Sliders")
1722
1723        if compat.IS_LEGACY:
1724            flow = self.layout.column_flow(columns=2)
1725        else:
1726            flow = self.layout.grid_flow(row_major=True)
1727        flow.scale_x = 0.5
1728
1729        def _transform_prop(name, pos_prop=None, scl_prop=None, pos_enabled=(True, True, True), scl_enabled=(True, True, True)):
1730            #lab = flow.row(align=True)
1731            #lab.alignment = 'RIGHT'
1732            #lab.label(text=name)
1733            #sub = lab.column()
1734            #sub.label(text=name)
1735            #sub.alignment = 'RIGHT'
1736            
1737            tab = flow.column()#align=True)
1738            #tab.alignment = 'LEFT'
1739            #tab.label(text=name)
1740
1741            col = tab.column(align=True)
1742            
1743            global used_name
1744            used_name = False
1745            def _vec_prop(type_name, prop_id, enabled_axes, axis_names):
1746                global used_name
1747                #vec = tab.row(align=True)
1748                #vec.label(text=type_name)
1749                #col = vec.column(align=True)
1750                for i in range(0, 3):
1751                    is_enabled  = enabled_axes[i] or sliders.enable_all
1752                    is_disabled = enabled_axes[i] == None
1753
1754                    if i == 0 and compat.IS_LEGACY:
1755                        if not used_name:
1756                            col.label(text=name)
1757                            used_name = True
1758                            
1759
1760                    row = col.row(align=True)
1761                    row.enabled = not is_disabled and is_enabled
1762                    
1763                    axis_name = axis_names[i]
1764                    if i == 0:
1765                        if compat.IS_LEGACY:
1766                            axis_name = axis_name + " " + type_name
1767                        else:
1768                            axis_name = type_name + " " + axis_name
1769                        if not used_name:
1770                            axis_name = name + " " + axis_name
1771                            used_name = True
1772
1773                    row.prop(
1774                        sliders                                , 
1775                        prop_id if not is_disabled else "empty", 
1776                        text   = axis_name                     , 
1777                        slider = not is_disabled               ,
1778                        emboss = not is_disabled               ,
1779                        index  = -1 if is_disabled else i      ,
1780                    )
1781
1782            if pos_prop:
1783                _vec_prop(iface_("Position"), pos_prop, pos_enabled, ("X", "Y", "Z"))
1784            if scl_prop:
1785                _vec_prop(iface_("Scale"   ), scl_prop, scl_enabled, ("X", "Y", "Z"))
1786
1787
1788        _transform_prop("Pelvis"       , None        , "PELSCL"                                                                           )
1789        _transform_prop("Hips"         , "HIPPOS"    , "HIPSCL"                                                                           )
1790        _transform_prop("Legs"         , "THIPOS"    , "THISCL"    , pos_enabled=(True , None , True ), scl_enabled=(True , True , None ) )
1791        _transform_prop("Thigh"        , "MTWPOS"    , "MTWSCL"                                                                           )
1792        _transform_prop("Rear Thigh"   , "MMNPOS"    , "MMNSCL"                                                                           )
1793        _transform_prop("Knee"         , "THI2POS"   , "THISCL2"                                      , scl_enabled=(True , True , False) )
1794        _transform_prop("Calf"         , None        , "CALFSCL"                                      , scl_enabled=(True , True , False) )
1795        _transform_prop("Foot"         , None        , "FOOTSCL"                                                                          )
1796        _transform_prop("Skirt"        , "SKTPOS"    , "SKTSCL"    , pos_enabled=(False, False, True )                                    )
1797        _transform_prop("Lower Abdomen", "SPIPOS"    , "SPISCL"    , pos_enabled=(True , False, True )                                    )
1798        _transform_prop("Upper Abdomen", "S0APOS"    , "S0ASCL"    , pos_enabled=(True , True , False)                                    )
1799        _transform_prop("Lower Chest"  , "S1POS"     , "S1_SCL"    , pos_enabled=(True , True , False)                                    )
1800        _transform_prop("Upper Chest"  , "S1APOS"    , "S1ASCL"    , pos_enabled=(True , True , False)                                    )
1801        _transform_prop("Upper Torso"  , None        , "S1ABASESCL"                                   , scl_enabled=(True , True , False) )
1802        _transform_prop("Breasts"      , "MUNEPOS"   , "MUNESCL"                                                                          )
1803        _transform_prop("Breasts Sub"  , "MUNESUBPOS", "MUNESUBSCL"                                                                       )
1804        _transform_prop("Neck"         , "NECKPOS"   , "NECKSCL"                                                                          )
1805        _transform_prop("Clavicle"     , "CLVPOS"    , "CLVSCL"                                                                           )
1806        _transform_prop("Shoulders"    , None        , "KATASCL"                                                                          )
1807        _transform_prop("Upper Arm"    , None        , "UPARMSCL"                                                                         )
1808        _transform_prop("Forearm"      , None        , "FARMSCL"                                                                          )
1809        _transform_prop("Hand"         , None        , "HANDSCL"                                                                          )              
bl_rna = <bpy_struct, Struct("DATA_PT_cm3d2_wide_sliders")>
Inherited Members
bpy_types._GenericUI
is_extended
append
prepend
remove
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CNV_OT_cleanup_scale_bones(bpy_types.Operator):
1814@compat.BlRegister()
1815class CNV_OT_cleanup_scale_bones(bpy.types.Operator):
1816    bl_idname      = 'object.cleanup_scale_bones'
1817    bl_label       = "Cleanup Scale Bones"
1818    bl_description = "Remove scale bones from the active armature object"
1819    bl_options     = {'REGISTER', 'UNDO'}
1820
1821    scale = bpy.props.FloatProperty(name="Scale", default=5, min=0.1, max=100, soft_min=0.1, soft_max=100, step=100, precision=1, description="The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.")
1822
1823    is_keep_bones_with_children = bpy.props.BoolProperty(name="Keep bones with children", default=True, description="Will not remove scale bones that have children (for custom scale bones)")
1824    
1825    @classmethod
1826    def poll(cls, context):
1827        ob = context.object
1828        if ob:
1829            arm = ob.data
1830        else:
1831            arm = None
1832        has_arm  = arm and isinstance(arm, bpy.types.Armature)
1833        has_scl = False
1834        if has_arm:
1835            for bone in arm.edit_bones:
1836                if '_SCL_' in bone.name:
1837                    has_scl = True
1838                    break
1839        return has_arm and has_scl
1840
1841    def invoke(self, context, event):
1842        return context.window_manager.invoke_props_dialog(self)
1843
1844    def draw(self, context):
1845        self.layout.prop(self, 'is_keep_bones_with_children')
1846
1847    def execute(self, context):
1848        ob = context.object
1849        arm = ob.data
1850
1851        edit_bones = arm.edit_bones
1852        deleted_bones = {}
1853        for bone in edit_bones:
1854            if not '_SCL_' in bone.name:
1855                continue
1856            if self.is_keep_bones_with_children and len(bone.children) > 0:
1857                continue
1858            parent = edit_bones.get(bone.name.replace("_SCL_","")) or bone.parent
1859            if parent:
1860                parent['cm3d2_scl_bone'] = True
1861                deleted_bones[bone.name] = parent.name
1862                edit_bones.remove(bone)
1863
1864        for child in ob.children:
1865            vgroups = child.vertex_groups
1866            if vgroups and len(vgroups) > 0:
1867                for old_name, new_name in deleted_bones.items():
1868                    old_vgroup = vgroups.get(old_name)
1869                    if old_vgroup:
1870                        old_vgroup.name = new_name
1871
1872        return {'FINISHED'}
bl_idname = 'object.cleanup_scale_bones'
bl_label = 'Cleanup Scale Bones'
bl_description = 'Remove scale bones from the active armature object'
bl_options = {'REGISTER', 'UNDO'}
scale: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}>
is_keep_bones_with_children: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Keep bones with children', 'default': True, 'description': 'Will not remove scale bones that have children (for custom scale bones)', 'attr': 'is_keep_bones_with_children'}> = <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Keep bones with children', 'default': True, 'description': 'Will not remove scale bones that have children (for custom scale bones)', 'attr': 'is_keep_bones_with_children'}>
@classmethod
def poll(cls, context):
1825    @classmethod
1826    def poll(cls, context):
1827        ob = context.object
1828        if ob:
1829            arm = ob.data
1830        else:
1831            arm = None
1832        has_arm  = arm and isinstance(arm, bpy.types.Armature)
1833        has_scl = False
1834        if has_arm:
1835            for bone in arm.edit_bones:
1836                if '_SCL_' in bone.name:
1837                    has_scl = True
1838                    break
1839        return has_arm and has_scl
def invoke(self, context, event):
1841    def invoke(self, context, event):
1842        return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
1844    def draw(self, context):
1845        self.layout.prop(self, 'is_keep_bones_with_children')
def execute(self, context):
1847    def execute(self, context):
1848        ob = context.object
1849        arm = ob.data
1850
1851        edit_bones = arm.edit_bones
1852        deleted_bones = {}
1853        for bone in edit_bones:
1854            if not '_SCL_' in bone.name:
1855                continue
1856            if self.is_keep_bones_with_children and len(bone.children) > 0:
1857                continue
1858            parent = edit_bones.get(bone.name.replace("_SCL_","")) or bone.parent
1859            if parent:
1860                parent['cm3d2_scl_bone'] = True
1861                deleted_bones[bone.name] = parent.name
1862                edit_bones.remove(bone)
1863
1864        for child in ob.children:
1865            vgroups = child.vertex_groups
1866            if vgroups and len(vgroups) > 0:
1867                for old_name, new_name in deleted_bones.items():
1868                    old_vgroup = vgroups.get(old_name)
1869                    if old_vgroup:
1870                        old_vgroup.name = new_name
1871
1872        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("OBJECT_OT_cleanup_scale_bones")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CNV_OT_save_cm3d2_body_sliders_to_menu(bpy_types.Operator):
1875@compat.BlRegister()
1876class CNV_OT_save_cm3d2_body_sliders_to_menu(bpy.types.Operator):
1877    bl_idname      = 'object.save_cm3d2_body_sliders_to_menu'
1878    bl_label       = "Save CM3D2 Body Sliders to Menu"
1879    bl_description = "Remove scale bones from the active armature object"
1880    bl_options     = {'REGISTER', 'UNDO'}
1881
1882    is_overwrite = bpy.props.BoolProperty(name="Overwrite Existing", default=True)
1883
1884    @classmethod
1885    def poll(cls, context):
1886        ob = context.object
1887        if ob:
1888            arm = ob.data
1889        else:
1890            arm = None
1891        has_arm  = arm and isinstance(arm, bpy.types.Armature)
1892        return has_arm
1893
1894    def invoke(self, context, event):
1895        return context.window_manager.invoke_props_dialog(self)
1896
1897    def draw(self, context):
1898        self.layout.prop(self, 'is_overwrite')
1899        if self.is_overwrite:
1900            self.layout.label(text="Any existing data will be overwritten", icon=compat.icon('ERROR'))
1901
1902    def execute(self, context):
1903        ob = context.object
1904        menu_file_data = ob.cm3d2_menu
1905        morph = ob.cm3d2_bone_morph
1906
1907        def add_menu_prop_command(prop_name):
1908            menu_file_data.parse_list(
1909                ["prop",
1910                    prop_name,
1911                    str(int( getattr(morph, prop_name) ))
1912                ]
1913            )
1914
1915        if self.is_overwrite:
1916            menu_file_data.clear()
1917
1918            menu_file_data.version     = 1000
1919            menu_file_data.path        = os.path.relpath(bpy.data.filepath, start=bpy.path.abspath("//.."))
1920            menu_file_data.name        = f'{ob.name} {data_("Body")}'
1921            menu_file_data.category    = "set_body"
1922            menu_file_data.description = data_("Generated in blender using body sliders")
1923                                                                                            
1924            menu_file_data.parse_list(["メニューフォルダ", "system"                                 ])                               
1925            menu_file_data.parse_list(["category", "set_body"                               ])
1926            menu_file_data.parse_list(["priority", "100"                                    ])
1927            menu_file_data.parse_list(["icons"   , "_i_set_body_1_.tex"                     ])
1928            menu_file_data.parse_list([data_("属性追加")    , data_("クリックしても選択状態にしない")                        ])                      
1929            menu_file_data.parse_list(["name"    , menu_file_data.name                      ])
1930            menu_file_data.parse_list(["setumei" , data_("Generated in blender using body sliders")])
1931
1932        add_menu_prop_command('HeadX'     )
1933        add_menu_prop_command('HeadY'     )
1934        add_menu_prop_command('DouPer'    )
1935        add_menu_prop_command('sintyou'   )
1936        add_menu_prop_command('BreastSize')
1937        add_menu_prop_command('MuneTare'  )
1938        add_menu_prop_command('MuneUpDown')
1939        add_menu_prop_command('MuneYori'  )
1940        add_menu_prop_command('west'      )
1941        add_menu_prop_command('Hara'      )
1942        add_menu_prop_command('kata'      )
1943        add_menu_prop_command('ArmL'      )
1944        add_menu_prop_command('UdeScl'    )
1945        add_menu_prop_command('KubiScl'   )
1946        add_menu_prop_command('koshi'     )
1947        add_menu_prop_command('RegFat'    )
1948        add_menu_prop_command('RegMeet'   )
1949
1950        self.report(type={'INFO'}, message="Successfully saved properties to menu file data in Properties > Object Tab > CM3D2 Menu File")
1951
1952        return {'FINISHED'}
bl_idname = 'object.save_cm3d2_body_sliders_to_menu'
bl_label = 'Save CM3D2 Body Sliders to Menu'
bl_description = 'Remove scale bones from the active armature object'
bl_options = {'REGISTER', 'UNDO'}
is_overwrite: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Overwrite Existing', 'default': True, 'attr': 'is_overwrite'}> = <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Overwrite Existing', 'default': True, 'attr': 'is_overwrite'}>
@classmethod
def poll(cls, context):
1884    @classmethod
1885    def poll(cls, context):
1886        ob = context.object
1887        if ob:
1888            arm = ob.data
1889        else:
1890            arm = None
1891        has_arm  = arm and isinstance(arm, bpy.types.Armature)
1892        return has_arm
def invoke(self, context, event):
1894    def invoke(self, context, event):
1895        return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
1897    def draw(self, context):
1898        self.layout.prop(self, 'is_overwrite')
1899        if self.is_overwrite:
1900            self.layout.label(text="Any existing data will be overwritten", icon=compat.icon('ERROR'))
def execute(self, context):
1902    def execute(self, context):
1903        ob = context.object
1904        menu_file_data = ob.cm3d2_menu
1905        morph = ob.cm3d2_bone_morph
1906
1907        def add_menu_prop_command(prop_name):
1908            menu_file_data.parse_list(
1909                ["prop",
1910                    prop_name,
1911                    str(int( getattr(morph, prop_name) ))
1912                ]
1913            )
1914
1915        if self.is_overwrite:
1916            menu_file_data.clear()
1917
1918            menu_file_data.version     = 1000
1919            menu_file_data.path        = os.path.relpath(bpy.data.filepath, start=bpy.path.abspath("//.."))
1920            menu_file_data.name        = f'{ob.name} {data_("Body")}'
1921            menu_file_data.category    = "set_body"
1922            menu_file_data.description = data_("Generated in blender using body sliders")
1923                                                                                            
1924            menu_file_data.parse_list(["メニューフォルダ", "system"                                 ])                               
1925            menu_file_data.parse_list(["category", "set_body"                               ])
1926            menu_file_data.parse_list(["priority", "100"                                    ])
1927            menu_file_data.parse_list(["icons"   , "_i_set_body_1_.tex"                     ])
1928            menu_file_data.parse_list([data_("属性追加")    , data_("クリックしても選択状態にしない")                        ])                      
1929            menu_file_data.parse_list(["name"    , menu_file_data.name                      ])
1930            menu_file_data.parse_list(["setumei" , data_("Generated in blender using body sliders")])
1931
1932        add_menu_prop_command('HeadX'     )
1933        add_menu_prop_command('HeadY'     )
1934        add_menu_prop_command('DouPer'    )
1935        add_menu_prop_command('sintyou'   )
1936        add_menu_prop_command('BreastSize')
1937        add_menu_prop_command('MuneTare'  )
1938        add_menu_prop_command('MuneUpDown')
1939        add_menu_prop_command('MuneYori'  )
1940        add_menu_prop_command('west'      )
1941        add_menu_prop_command('Hara'      )
1942        add_menu_prop_command('kata'      )
1943        add_menu_prop_command('ArmL'      )
1944        add_menu_prop_command('UdeScl'    )
1945        add_menu_prop_command('KubiScl'   )
1946        add_menu_prop_command('koshi'     )
1947        add_menu_prop_command('RegFat'    )
1948        add_menu_prop_command('RegMeet'   )
1949
1950        self.report(type={'INFO'}, message="Successfully saved properties to menu file data in Properties > Object Tab > CM3D2 Menu File")
1951
1952        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("OBJECT_OT_save_cm3d2_body_sliders_to_menu")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data