bpy.types
Access to internal Blender types
class
Object:
@compat.BlRegister()
@CM3D2MenuCommand('アタッチポイントの設定', name='{command_name} : {point_name}')
class
CM3D2MENU_PG_AttachPointCommand220@compat.BlRegister() 221@CM3D2MenuCommand('アタッチポイントの設定', name="{command_name} : {point_name}") 222class CM3D2MENU_PG_AttachPointCommand(bpy.types.PropertyGroup): 223 bl_idname = 'CM3D2MenuAttachPointCommand' 224 ''' 225 アタッチポイントの設定 226 ├ point_name(呼び出し名) 227 ├ location.x(座標) 228 ├ location.y(座標) 229 ├ location.z(座標) 230 ├ rotation.x(軸回転角度)[範囲:0±180°] 231 ├ rotation.y(軸回転角度)[範囲:0±180°] 232 └ rotation.z(軸回転角度)[範囲:0±180°] 233 ''' 234 point_name = bpy.props.StringProperty (name="Point Name", default="Attach Point", description="Name of the slot to define the attatchment point for" , options=PROP_OPTS) 235 location = bpy.props.FloatVectorProperty(name="Location" , default=(0, 0, 0) , description="Location of the attatchment relative to the base bone", options=PROP_OPTS, subtype=compat.subtype('TRANSLATION')) 236 rotation = bpy.props.FloatVectorProperty(name="Rotation" , default=(0, 0, 0) , description="Rotation of the attatchment relative to the base bone", options=PROP_OPTS, subtype=compat.subtype('EULER' )) 237 238 def parse_list(self, string_list): 239 self.command = string_list[0] 240 self.point_name = string_list[1] 241 self.location.x = float(string_list[2]) 242 self.location.y = float(string_list[3]) 243 self.location.z = float(string_list[4]) 244 self.rotation.x = float(string_list[5]) * math.pi/180 245 self.rotation.y = float(string_list[6]) * math.pi/180 246 self.rotation.z = float(string_list[7]) * math.pi/180 247 248 def pack_into(self, buffer): 249 buffer = buffer + struct.pack('<B', 1 + 1 + 3 + 3) 250 buffer = common.pack_str(buffer, self.command ) 251 buffer = common.pack_str(buffer, self.point_name) 252 buffer = common.pack_str(buffer, str(self.location.x) ) 253 buffer = common.pack_str(buffer, str(self.location.y) ) 254 buffer = common.pack_str(buffer, str(self.location.z) ) 255 buffer = common.pack_str(buffer, str(self.rotation.x * 180/math.pi)) 256 buffer = common.pack_str(buffer, str(self.rotation.y * 180/math.pi)) 257 buffer = common.pack_str(buffer, str(self.rotation.z * 180/math.pi)) 258 259 return buffer 260 261 def draw(self, context, layout): 262 layout.label(text=self.name) 263 264 col = layout.column() 265 col.alignment = 'RIGHT' 266 col.prop(self, 'command', translate=False) 267 col.label(text=self.command + " ", translate=False) 268 269 col = layout.column() 270 col.prop(self, 'point_name') 271 col.prop(self, 'location' ) 272 col.prop(self, 'rotation' ) 273 274 col = layout.column(align=True) 275 col.operator('cm3d2menu.align_selected_to_attach_point', icon=compat.icon('OBJECT_ORIGIN') ) 276 col.operator('cm3d2menu.align_attach_point_to_selected', icon=compat.icon('ORIENTATION_LOCAL'))
CM3D2MENU_PG_AttachPointCommand
command: CM3D2 Converter.menu_file.CM3D2MENU_PG_AttachPointCommand.command_enum =
'アタッチポイントの設定'
Command
The command of this menu file command-chunkInherited Members
111@compat.BlRegister() 112class CM3D2MENU_PG_CommandPointer(bpy.types.PropertyGroup): 113 bl_idname = 'CM3D2MenuCommandPointer' 114 115 collection_name = bpy.props.StringProperty(options={'HIDDEN'}) 116 prop_index = bpy.props.IntProperty (options={'HIDDEN'}) 117 118 def dereference(self, data): 119 return getattr(data, self.collection_name)[self.prop_index]
CM3D2MENU_PG_CommandPointer
Inherited Members
@compat.BlRegister()
@CM3D2MenuCommand(name='{command_name}')
class
CM3D2MENU_PG_MiscCommand316@compat.BlRegister() 317@CM3D2MenuCommand(name="{command_name}") 318class CM3D2MENU_PG_MiscCommand(bpy.types.PropertyGroup): 319 bl_idname = 'CM3D2MenuMiscCommand' 320 ''' 321 command 322 ├ child_0 323 ├ child_1 324 ├ child_2 325 ├ ... 326 ├ child_n-1 327 └ child_n 328 ''' 329 params = bpy.props.CollectionProperty(name="Parameters", options=PROP_OPTS, type=MISCCOMMAND_PG_Param) 330 331 active_index = bpy.props.IntProperty(options={'HIDDEN'}) 332 333 search = bpy.props.BoolProperty(name="Search", default=False, description="Search for suggestions", options=PROP_OPTS) 334 335 def new_param(self): 336 new_param = self.params.add() 337 new_param.value = "newparam" 338 return new_param 339 340 def remove_param(self, index: int): 341 return self.params.remove(index) 342 343 def move_param(self, old_index, new_index): 344 return self.params.move(old_index, new_index) 345 346 def parse_list(self, string_list): 347 self.command = string_list[0] 348 for param in string_list[1:]: 349 new_param = self.params.add() 350 new_param.value = param 351 new_param.name = param 352 353 def pack_into(self, buffer): 354 buffer = buffer + struct.pack('<B', 1 + len(self.params)) 355 buffer = common.pack_str(buffer, self.command) 356 for param in self.params: 357 buffer = common.pack_str(buffer, param.value) 358 return buffer 359 360 def draw(self, context, layout): 361 enum_info = get_command_enum_info(self.command) 362 if enum_info: 363 layout.label(text=enum_info[1], icon=enum_info[3]) 364 365 row = layout.row(align=True) 366 if not compat.IS_LEGACY: 367 row.use_property_split = False 368 if self.search: 369 search_data = bpy.ops.cm3d2menu.command_add.get_rna_type().properties.get('type') 370 row.prop_search(self, 'command', search_data, 'enum_items', text="", translate=True, icon='VIEWZOOM') 371 else: 372 row.prop(self, 'command', text="") 373 row.prop(self, 'search', text='', icon='ZOOM_OUT' if self.search else 'VIEWZOOM') 374 375 376 row = layout.row() 377 row.template_list('UI_UL_list', 'CM3D2MENU_UL_misc_command_children', 378 self, 'params' , 379 self, 'active_index', 380 rows = 3, 381 maxrows = 8, 382 ) 383 sub_col = row.column(align=True) 384 sub_col.operator('cm3d2menu.param_add' , icon='ADD' , text="") 385 sub_col.operator('cm3d2menu.param_remove', icon='REMOVE', text="") 386 #sub_col.separator() 387 #sub_col.menu("OBJECT_MT_cm3d2_menu_context_menu", icon='DOWNARROW_HLT', text="") 388 if self.active_index < len(self.params): 389 sub_col.separator() 390 sub_col.operator("cm3d2menu.param_move", icon='TRIA_UP' , text="").direction = 'UP' 391 sub_col.operator("cm3d2menu.param_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
CM3D2MENU_PG_MiscCommand
Inherited Members
@compat.BlRegister()
@CM3D2MenuCommand('prop', name='{command_name} : {prop_name} = {value}')
class
CM3D2MENU_PG_PropertyCommand279@compat.BlRegister() 280@CM3D2MenuCommand('prop', name="{command_name} : {prop_name} = {value}") 281class CM3D2MENU_PG_PropertyCommand(bpy.types.PropertyGroup): 282 bl_idname = 'CM3D2PropertyMenuCommand' 283 ''' 284 prop 285 ├ prop_name 286 └ value 287 ''' 288 prop_name = bpy.props.StringProperty(name="Property Name" , default="prop name", description="Name of the property to set on load" , options=PROP_OPTS) 289 value = bpy.props.FloatProperty (name="Property Value", default=50 , description="Value of the property to set on load", options=PROP_OPTS) 290 291 def parse_list(self, string_list): 292 self.command = string_list[0] 293 self.prop_name = string_list[1] 294 self.value = float(string_list[2]) 295 296 def pack_into(self, buffer): 297 buffer = buffer + struct.pack('<B', 1 + 1 + 1) 298 buffer = common.pack_str(buffer, self.command ) 299 buffer = common.pack_str(buffer, self.prop_name ) 300 buffer = common.pack_str(buffer, str(self.value) ) 301 302 return buffer 303 304 def draw(self, context, layout): 305 col = layout.column() 306 col.alignment = 'RIGHT' 307 col.prop(self, 'command', translate=False) 308 col.label(text=self.command + " ", translate=False) 309 310 col = layout.column() 311 col.label(text=self.command, translate=False) 312 col.prop(self, 'prop_name') 313 col.prop(self, 'value' )
CM3D2MENU_PG_PropertyCommand
12@compat.BlRegister() 13class CM3D2MENU_UL_command_list(bpy.types.UIList): 14 bl_idname = 'CM3D2MENU_UL_command_list' 15 bl_options = {'DEFAULT_CLOSED'} 16 bl_region_type = 'WINDOW' 17 bl_space_type = 'PROPERTIES' 18 # The draw_item function is called for each item of the collection that is visible in the list. 19 # data is the RNA object containing the collection, 20 # item is the current drawn item of the collection, 21 # icon is the "computed" icon for the item (as an integer, because some objects like materials or textures 22 # have custom icons ID, which are not available as enum items). 23 # active_data is the RNA object containing the active property for the collection (i.e. integer pointing to the 24 # active item of the collection). 25 # active_propname is the name of the active property (use 'getattr(active_data, active_propname)'). 26 # index is index of the current item in the collection. 27 # flt_flag is the result of the filtering process for this item. 28 # Note: as index and flt_flag are optional arguments, you do not have to use/declare them here if you don't 29 # need them. 30 def draw_item(self, context, layout, data, item, icon, active_data, active_propname): 31 command_prop = item.dereference(data) 32 # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code. 33 if self.layout_type in {'DEFAULT', 'COMPACT'}: 34 # You should always start your row layout by a label (icon + text), or a non-embossed text field, 35 # this will also make the row easily selectable in the list! The later also enables ctrl-click rename. 36 # We use icon_value of label, as our given icon is an integer value, not an enum ID. 37 # Note "data" names should never be translated! 38 if command_prop: 39 command_enum_info = menu_file.get_command_enum_info(command_prop.command) 40 icon = 'NONE' 41 if command_enum_info: 42 icon = compat.icon(command_enum_info[3]) 43 layout.label(text=command_prop.name, icon=icon) 44 else: 45 layout.label(text="", translate=False, icon_value=icon) 46 # 'GRID' layout type should be as compact as possible (typically a single icon!). 47 elif self.layout_type in {'GRID'}: 48 layout.alignment = 'CENTER' 49 layout.label(text="", icon_value=icon)
CM3D2MENU_UL_command_list
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
CNV_PG_cm3d2_bone_morph
scale: float =
5.0
Scale
The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.Inherited Members
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
CNV_PG_cm3d2_wide_slider
empty: CM3D2 Converter.misc_DATA_PT_context_arm.CNV_PG_cm3d2_wide_slider.empty_enum =
'EMPTY'
Empty
This property never has a value
scale: float =
5.0
Scale
The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.Inherited Members
- CM3D2 Converter.misc_DATA_PT_context_arm
- CALFSCL
- CLVPOS
- CLVSCL
- FARMSCL
- FOOTSCL
- HANDSCL
- HIPPOS
- HIPSCL
- KATASCL
- MMNPOS
- MMNSCL
- MTWPOS
- MTWSCL
- MUNEPOS
- MUNESCL
- MUNESUBPOS
- MUNESUBSCL
- NECKPOS
- NECKSCL
- PELSCL
- S0APOS
- S0ASCL
- S1ABASESCL
- S1APOS
- S1ASCL
- S1POS
- S1_SCL
- SKTPOS
- SKTSCL
- SPIPOS
- SPISCL
- THI2POS
- THIPOS
- THISCL
- THISCL2
- UPARMSCL
- empty
- enable_all
- scale
1286@compat.BlRegister() 1287class CNV_SelectorItem(bpy.types.PropertyGroup): 1288 bl_label = "CNV_SelectorItem" 1289 bl_region_type = 'WINDOW' 1290 bl_space_type = 'PROPERTIES' 1291 1292 name = bpy.props.StringProperty (name="Name" , default="Unknown") 1293 value = bpy.props.BoolProperty (name="Value" , default=True ) 1294 index = bpy.props.IntProperty (name="Index" , default=-1 ) 1295 preferred = bpy.props.BoolProperty (name="Prefered", default=True ) 1296 icon = bpy.props.StringProperty (name="Icon" , default='NONE' ) 1297 1298 filter0 = bpy.props.BoolProperty (name="Filter 0", default=False ) 1299 filter1 = bpy.props.BoolProperty (name="Filter 1", default=False ) 1300 filter2 = bpy.props.BoolProperty (name="Filter 2", default=False ) 1301 filter3 = bpy.props.BoolProperty (name="Filter 3", default=False )
CNV_SelectorItem
27@compat.BlRegister() 28class CNV_UL_modifier_selector(common.CNV_UL_generic_selector): 29 bl_label = 'CNV_UL_modifier_selector' 30 bl_options = {'DEFAULT_CLOSED'} 31 bl_region_type = 'WINDOW' 32 bl_space_type = 'PROPERTIES' 33 34 # Constants (flags) 35 # Be careful not to shadow FILTER_ITEM! 36 #bitflag_forced_true = 1 << 0 37 #bitflag_forced_false = 1 << 1 38 #force_values = False 39 #did_force_values = False 40 41 force_values = bpy.props.BoolProperty( 42 name="force_values", 43 default=False, 44 options=set(), 45 ) 46 47 did_force_values = bpy.props.BoolProperty( 48 name="force_values", 49 default=False, 50 options=set(), 51 ) 52 53 # This allows us to have mutually exclusive options, which are also all disable-able! 54 def _gen_force_values(self, context): 55 setattr(self, "force_values", True) 56 setattr(self, "did_force_values", False) 57 print("SET TRUE force_values =", self.force_values) 58 59 def _gen_visible_update(name1, name2): 60 def _u(self, context): 61 self._gen_force_values(context) 62 if (getattr(self, name1)): 63 setattr(self, name2, False) 64 return _u 65 use_filter_viewport_visible = bpy.props.BoolProperty( 66 name="Viewport", 67 default=False, 68 options=set(), 69 description="Only enable modifiers visible in viewport", 70 update=_gen_visible_update("use_filter_viewport_visible", "use_filter_renderer_visible"), 71 ) 72 use_filter_renderer_visible = bpy.props.BoolProperty( 73 name="Renderer", 74 default=False, 75 options=set(), 76 description="Only enable modifiers visible in renderer", 77 update=_gen_visible_update("use_filter_renderer_visible", "use_filter_viewport_visible"), 78 ) 79 use_filter_reversed_visible = bpy.props.BoolProperty( 80 name="Reverse Visible Filter", 81 default=False, 82 options=set(), 83 description="Reverse the selected visible-in filter", 84 update=_gen_force_values 85 ) 86 87 88 use_filter_name_reverse = bpy.props.BoolProperty( 89 name="Reverse Name", 90 default=False, 91 options=set(), 92 description="Reverse name filtering", 93 ) 94 95 def _gen_order_update(name1, name2): 96 def _u(self, ctxt): 97 if (getattr(self, name1)): 98 setattr(self, name2, False) 99 return _u 100 use_order_name = bpy.props.BoolProperty( 101 name="Name", default=False, options=set(), 102 description="Sort groups by their name (case-insensitive)", 103 update=_gen_order_update("use_order_name", "use_order_importance"), 104 ) 105 use_filter_orderby_invert = bpy.props.BoolProperty( 106 name="Order by Invert", 107 default=False, 108 options=set(), 109 description="Invert the sort by order" 110 ) 111 112 113 def draw_filter(self, context, layout): 114 row = layout.row() 115 row.label(text="Visible in:") 116 subrow = row.row(align=True) 117 subrow.prop(self, "use_filter_viewport_visible", toggle=True) 118 subrow.prop(self, "use_filter_renderer_visible", toggle=True) 119 icon = 'ZOOM_OUT' if self.use_filter_reversed_visible else 'ZOOM_IN' 120 icon = compat.icon(icon) 121 subrow.prop(self, "use_filter_reversed_visible", text="", icon=icon) 122 123 super(CNV_UL_modifier_selector, self).draw_filter(context, layout) 124 125 def filter_items(self, context, data, propname): 126 flt_flags, flt_neworder = super(CNV_UL_modifier_selector, self).filter_items(context, data, propname) 127 items = getattr(data, propname) 128 129 if getattr(self, 'did_force_values'): 130 setattr(self,'force_values', False) 131 setattr(self, 'did_force_values', getattr(self, 'force_values')) 132 133 print("CHECK force_values = ", getattr(self, 'force_values')) 134 135 if self.use_filter_viewport_visible or self.use_filter_renderer_visible or getattr(self, 'force_values'): 136 137 if not self.use_filter_reversed_visible: 138 in_flag = self.bitflag_forced_true 139 out_flag = ~(self.bitflag_forced_false | self.bitflag_soft_filter) 140 else: 141 in_flag = self.bitflag_forced_false | self.bitflag_soft_filter 142 out_flag = ~self.bitflag_forced_true 143 144 for index, item in enumerate(items): 145 if getattr(self, 'force_values'): 146 flt_flags[index] |= self.bitflag_forced_value 147 148 if self.use_filter_viewport_visible and item.filter0: 149 flt_flags[index] |= in_flag 150 flt_flags[index] &= out_flag 151 elif self.use_filter_renderer_visible and item.filter1: 152 flt_flags[index] |= in_flag 153 flt_flags[index] &= out_flag 154 elif not self.use_filter_viewport_visible and not self.use_filter_renderer_visible: 155 pass 156 else: 157 flt_flags[index] |= ~out_flag 158 flt_flags[index] &= ~in_flag 159 160 return flt_flags, flt_neworder
CNV_UL_modifier_selector
851@compat.BlRegister() 852class CNV_UL_vgroups_selector(bpy.types.UIList): 853 bl_label = "Vertex Groups Selector" 854 bl_options = {'DEFAULT_CLOSED'} 855 bl_region_type = 'WINDOW' 856 bl_space_type = 'PROPERTIES' 857 858 # Constants (flags) 859 # Be careful not to shadow FILTER_ITEM! 860 VGROUP_EMPTY = 1 << 1 861 VGROUP_DEFORM = 1 << 0 862 863 armature = None 864 local_bone_names = None 865 cached_values = {} 866 867 expanded_layout = False 868 869 # Custom properties, saved with .blend file. 870 use_filter_name_reverse = bpy.props.BoolProperty( 871 name="Reverse Name", 872 default=False, 873 options=set(), 874 description="Reverse name filtering", 875 ) 876 use_filter_deform = bpy.props.BoolProperty( 877 name="Only Deform", 878 default=False, 879 options=set(), 880 description="Only show deforming vertex groups", 881 ) 882 use_filter_deform_reverse = bpy.props.BoolProperty( 883 name="Other", 884 default=False, 885 options=set(), 886 description="Only show non-deforming vertex groups", 887 ) 888 use_filter_empty = bpy.props.BoolProperty( 889 name="Filter Empty", 890 default=False, 891 options=set(), 892 description="Whether to filter empty vertex groups", 893 ) 894 use_filter_empty_reverse = bpy.props.BoolProperty( 895 name="Reverse Empty", 896 default=False, 897 options=set(), 898 description="Reverse empty filtering", 899 ) 900 901 # This allows us to have mutually exclusive options, which are also all disable-able! 902 def _gen_order_update(name1, name2): 903 def _u(self, ctxt): 904 if (getattr(self, name1)): 905 setattr(self, name2, False) 906 return _u 907 use_order_name = bpy.props.BoolProperty( 908 name="Name", default=False, options=set(), 909 description="Sort groups by their name (case-insensitive)", 910 update=_gen_order_update("use_order_name", "use_order_importance"), 911 ) 912 use_order_importance = bpy.props.BoolProperty( 913 name="Importance", 914 default=False, 915 options=set(), 916 description="Sort groups by their average weight in the mesh", 917 update=_gen_order_update("use_order_importance", "use_order_name"), 918 ) 919 use_filter_orderby_invert = bpy.props.BoolProperty( 920 name="Order by Invert", 921 default=False, 922 options=set(), 923 description="Invert the sort by order" 924 ) 925 926 # Usual draw item function. 927 def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag): 928 # Just in case, we do not use it here! 929 self.use_filter_invert = False 930 931 # assert(isinstance(item, bpy.types.VertexGroup) 932 #vgroup = getattr(data, 'matched_vgroups')[item.index] 933 if self.layout_type in {'DEFAULT', 'COMPACT'}: 934 # Here we use one feature of new filtering feature: it can pass data to draw_item, through flt_flag 935 # parameter, which contains exactly what filter_items set in its filter list for this item! 936 # In this case, we show empty groups grayed out. 937 cached_value = self.cached_values.get(item.name, None) 938 if (cached_value != None) and (cached_value != item.value): 939 item.preferred = item.value 940 941 if self.use_filter_deform: 942 item.value = bool(flt_flag & self.VGROUP_DEFORM) and item.preferred 943 else: 944 item.value = item.preferred 945 946 self.cached_values[item.name] = item.value 947 948 if flt_flag & (self.VGROUP_EMPTY | self.VGROUP_DEFORM): 949 col = layout.column() 950 col.enabled = False 951 col.alignment = 'LEFT' 952 col.prop(item, "value", text=item.name, emboss=False, icon_value=icon) 953 else: 954 layout.prop(item, "value", text=item.name, icon_value=icon) 955 956 icon = 'RADIOBUT_ON' if item.preferred else 'RADIOBUT_OFF' 957 layout.prop(item, "preferred", text="", icon=compat.icon(icon), emboss=False) 958 elif self.layout_type in {'GRID'}: 959 layout.alignment = 'CENTER' 960 if flt_flag & self.VGROUP_EMPTY: 961 layout.enabled = False 962 layout.label(text="", icon_value=icon) 963 964 def draw_filter(self, context, layout): 965 # Nothing much to say here, it's usual UI code... 966 row = layout.row() 967 if not self.expanded_layout: 968 layout.active = True 969 layout.enabled = True 970 row.active = True 971 row.enabled = True 972 self.expanded_layout = True 973 974 subrow = row.row(align=True) 975 subrow.prop(self, "filter_name", text="") 976 icon = 'ZOOM_OUT' if self.use_filter_name_reverse else 'ZOOM_IN' 977 subrow.prop(self, "use_filter_name_reverse", text="", icon=icon) 978 979 subrow = row.row(align=True) 980 subrow.prop(self, "use_filter_deform", toggle=True) 981 icon = 'ZOOM_OUT' if self.use_filter_deform_reverse else 'ZOOM_IN' 982 subrow.prop(self, "use_filter_deform_reverse", text="", icon=icon) 983 984 #subrow = row.row(align=True) 985 #subrow.prop(self, "use_filter_empty", toggle=True) 986 #icon = 'ZOOM_OUT' if self.use_filter_empty_reverse else 'ZOOM_IN' 987 #subrow.prop(self, "use_filter_empty_reverse", text="", icon=icon) 988 989 row = layout.row(align=True) 990 row.label(text="Order by:") 991 row.prop(self, "use_order_name", toggle=True) 992 #row.prop(self, "use_order_importance", toggle=True) 993 icon = 'TRIA_UP' if self.use_filter_orderby_invert else 'TRIA_DOWN' 994 row.prop(self, "use_filter_orderby_invert", text="", icon=icon) 995 996 def filter_items_empty_vgroups(self, context, vgroups): 997 # This helper function checks vgroups to find out whether they are empty, and what's their average weights. 998 # TODO: This should be RNA helper actually (a vgroup prop like "raw_data: ((vidx, vweight), etc.)"). 999 # Too slow for python! 1000 obj_data = context.active_object.data 1001 ret = {vg.index: [True, 0.0] for vg in vgroups} 1002 if hasattr(obj_data, "vertices"): # Mesh data 1003 if obj_data.is_editmode: 1004 import bmesh 1005 bm = bmesh.from_edit_mesh(obj_data) 1006 # only ever one deform weight layer 1007 dvert_lay = bm.verts.layers.deform.active 1008 fact = 1 / len(bm.verts) 1009 if dvert_lay: 1010 for v in bm.verts: 1011 for vg_idx, vg_weight in v[dvert_lay].items(): 1012 ret[vg_idx][0] = False 1013 ret[vg_idx][1] += vg_weight * fact 1014 else: 1015 fact = 1 / len(obj_data.vertices) 1016 for v in obj_data.vertices: 1017 for vg in v.groups: 1018 ret[vg.group][0] = False 1019 ret[vg.group][1] += vg.weight * fact 1020 elif hasattr(obj_data, "points"): # Lattice data 1021 # XXX no access to lattice editdata? 1022 fact = 1 / len(obj_data.points) 1023 for v in obj_data.points: 1024 for vg in v.groups: 1025 ret[vg.group][0] = False 1026 ret[vg.group][1] += vg.weight * fact 1027 return ret 1028 1029 def filter_items(self, context, data, propname): 1030 # This function gets the collection property (as the usual tuple (data, propname)), and must return two lists: 1031 # * The first one is for filtering, it must contain 32bit integers were self.bitflag_filter_item marks the 1032 # matching item as filtered (i.e. to be shown), and 31 other bits are free for custom needs. Here we use the 1033 # first one to mark VGROUP_EMPTY. 1034 # * The second one is for reordering, it must return a list containing the new indices of the items (which 1035 # gives us a mapping org_idx -> new_idx). 1036 # Please note that the default UI_UL_list defines helper functions for common tasks (see its doc for more info). 1037 # If you do not make filtering and/or ordering, return empty list(s) (this will be more efficient than 1038 # returning full lists doing nothing!). 1039 items = getattr(data, propname) 1040 1041 if self.armature == None: 1042 target_ob, source_ob = common.get_target_and_source_ob(context) 1043 armature_ob = target_ob.find_armature() or source_ob.find_armature() 1044 self.armature = armature_ob and armature_ob.data or False 1045 1046 if not self.local_bone_names: 1047 target_ob, source_ob = common.get_target_and_source_ob(context) 1048 bone_data_ob = (target_ob.get("LocalBoneData:0") and target_ob) or (source_ob.get("LocalBoneData:0") and source_ob) or None 1049 if bone_data_ob: 1050 local_bone_data = model_export.CNV_OT_export_cm3d2_model.local_bone_data_parser(model_export.CNV_OT_export_cm3d2_model.indexed_data_generator(bone_data_ob, prefix="LocalBoneData:")) 1051 self.local_bone_names = [ bone['name'] for bone in local_bone_data ] 1052 1053 if not self.cached_values: 1054 self.cached_values = { item.name: item.value for item in items } 1055 #vgroups = [ getattr(data, 'matched_vgroups')[item.index][0] for item in items ] 1056 helper_funcs = bpy.types.UI_UL_list 1057 1058 # Default return values. 1059 flt_flags = [] 1060 flt_neworder = [] 1061 1062 # Pre-compute of vgroups data, CPU-intensive. :/ 1063 #vgroups_empty = self.filter_items_empty_vgroups(context, vgroups) 1064 1065 # Filtering by name 1066 if self.filter_name: 1067 flt_flags = helper_funcs.filter_items_by_name(self.filter_name, self.bitflag_filter_item, items, "name", 1068 reverse=self.use_filter_name_reverse) 1069 if not flt_flags: 1070 flt_flags = [self.bitflag_filter_item] * len(items) 1071 1072 for idx, vg in enumerate(items): 1073 # Filter by deform. 1074 if self.use_filter_deform: 1075 flt_flags[idx] |= self.VGROUP_DEFORM 1076 if self.use_filter_deform: 1077 if self.armature and self.armature.get(vg.name): 1078 if not self.use_filter_deform_reverse: 1079 flt_flags[idx] &= ~self.VGROUP_DEFORM 1080 elif bone_data_ob and (vg.name in self.local_bone_names): 1081 if not self.use_filter_deform_reverse: 1082 flt_flags[idx] &= ~self.VGROUP_DEFORM 1083 elif self.use_filter_deform_reverse or (not self.armature and not self.local_bone_names): 1084 flt_flags[idx] &= ~self.VGROUP_DEFORM 1085 else: 1086 flt_flags[idx] &= ~self.VGROUP_DEFORM 1087 1088 # Filter by emptiness. 1089 #if vgroups_empty[vg.index][0]: 1090 # flt_flags[idx] |= self.VGROUP_EMPTY 1091 # if self.use_filter_empty and self.use_filter_empty_reverse: 1092 # flt_flags[idx] &= ~self.bitflag_filter_item 1093 #elif self.use_filter_empty and not self.use_filter_empty_reverse: 1094 # flt_flags[idx] &= ~self.bitflag_filter_item 1095 1096 # Reorder by name or average weight. 1097 if self.use_order_name: 1098 flt_neworder = helper_funcs.sort_items_by_name(vgroups, "name") 1099 #elif self.use_order_importance: 1100 # _sort = [(idx, vgroups_empty[vg.index][1]) for idx, vg in enumerate(vgroups)] 1101 # flt_neworder = helper_funcs.sort_items_helper(_sort, lambda e: e[1], True) 1102 1103 return flt_flags, flt_neworder
CNV_UL_vgroups_selector
122@compat.BlRegister() 123class MISCCOMMAND_PG_Param(bpy.types.PropertyGroup): 124 bl_idname = 'CM3D2MenuParam' 125 126 # Really the value should be saved, not the name, but template_list() doesn't like that so they're switched. 127 def _s(self, value): 128 self.name = value 129 130 #name = bpy.props.StringProperty(name="Name", options=PROP_OPTS, get=lambda self : self.value) 131 name = bpy.props.StringProperty(name="Name", default="param", options={'HIDDEN'}) 132 value = bpy.props.StringProperty(name="Slot Name", options={'SKIP_SAVE'}, default="param", set=_s, get=lambda self: self.name)
MISCCOMMAND_PG_Param
Inherited Members
@compat.BlRegister()
@generate_command_type_collections
class
OBJECT_PG_CM3D2Menu434@compat.BlRegister() 435@generate_command_type_collections 436class OBJECT_PG_CM3D2Menu(bpy.types.PropertyGroup): 437 bl_idname = 'CM3D2Menu' 438 439 version = bpy.props.IntProperty (name="Version" , options=PROP_OPTS, min=0, step=100 ) 440 path = bpy.props.StringProperty(name="Path" , options=PROP_OPTS, subtype='FILE_PATH') 441 name = bpy.props.StringProperty(name="Name" , options=PROP_OPTS) 442 category = bpy.props.StringProperty(name="Category" , options=PROP_OPTS) 443 description = bpy.props.StringProperty(name="Description", options=PROP_OPTS) 444 445 attach_point_commands = bpy.props.CollectionProperty(type=CM3D2MENU_PG_AttachPointCommand, options={'HIDDEN'}) 446 property_commands = bpy.props.CollectionProperty(type=CM3D2MENU_PG_PropertyCommand , options={'HIDDEN'}) 447 misc_commands = bpy.props.CollectionProperty(type=CM3D2MENU_PG_MiscCommand , options={'HIDDEN'}) 448 449 commands = bpy.props.CollectionProperty(name="Commands", type=CM3D2MENU_PG_CommandPointer, options=PROP_OPTS) 450 active_index = bpy.props.IntProperty(name="Active Command Index", options=PROP_OPTS, default=0) 451 452 # NOTE : This dictionary is generated by @generate_command_type_collections 453 #command_type_collections = { 454 # 'CM3D2MenuAttachPointCommand' : 'attach_point_commands', 455 # 'CM3D2MenuPropertyCommand' : 'property_commands' , 456 # ... 457 # for all Collection Properties (except 'commands') 458 #} 459 460 updated = bpy.props.BoolProperty(options={'HIDDEN', 'SKIP_SAVE'}, default=False) 461 def update(self): 462 for index, command_pointer in enumerate(self.commands): 463 command = command_pointer.dereference(self) 464 command.index = index 465 updated = True 466 467 def get_active_command(self): 468 if len(self.commands) <= self.active_index: 469 return None 470 command_pointer = self.commands[self.active_index] 471 return command_pointer.dereference(self) 472 473 def new_command(self, command: str): 474 command_type = COMMAND_TYPE_LIST.get(command) 475 collection_name = 'misc_commands' 476 if command_type: 477 collection_name = self.command_type_collections.get(command_type.bl_idname) or collection_name 478 479 collection = getattr(self, collection_name) 480 new_command = collection.add() 481 new_command.command = command 482 483 new_pointer = self.commands.add() 484 new_pointer.collection_name = collection_name 485 new_pointer.prop_index = len(collection) - 1 486 487 new_command.index = len(self.commands) - 1 488 489 return new_command 490 491 def remove_command(self, index: int): 492 command_pointer = self.commands[index] 493 command = command_pointer.dereference(self) 494 495 collection_name = self.command_type_collections.get(command.bl_idname) or 'misc_commands' 496 collection = getattr(self, collection_name) 497 498 prop_index = command_pointer.prop_index 499 self.commands.remove(index) 500 self.update() 501 collection.remove(prop_index) 502 503 for i, c in enumerate(collection): 504 self.commands[c.index].prop_index = i 505 506 if self.active_index >= len(self.commands): 507 self.active_index = len(self.commands) - 1 508 509 def move_command(self, old_index, new_index, update=True): 510 self.commands.move(old_index, new_index) 511 self.updated = False 512 if update: 513 self.update() 514 515 def parse_list(self, string_list): 516 command = string_list[0] 517 new_command = self.new_command(command) 518 new_command.parse_list(string_list) 519 520 def unpack_from_file(self, file): 521 if common.read_str(file) != 'CM3D2_MENU': 522 raise IOError("Not a valid CM3D2 .menu file.") 523 524 self.version = struct.unpack('<i', file.read(4))[0] 525 self.path = common.read_str(file) 526 self.name = common.read_str(file) 527 self.category = common.read_str(file) 528 self.description = common.read_str(file) 529 530 struct.unpack('<i', file.read(4))[0] 531 string_list = [] 532 string_list_length = struct.unpack('<B', file.read(1))[0] 533 while string_list_length > 0: 534 string_list.clear() 535 536 for i in range(string_list_length): 537 string_list.append(common.read_str(file)) 538 539 try: 540 self.parse_list(string_list) 541 except ValueError as e: 542 print(e) 543 544 # Check for end of file 545 chunk = file.read(1) 546 if len(chunk) == 0: 547 break 548 string_list_length = struct.unpack('<B', chunk)[0] 549 550 self.update() 551 552 def pack_into_file(self, file): 553 self.update() 554 555 common.write_str(file, 'CM3D2_MENU') 556 557 file.write(struct.pack('<i', self.version )) 558 common.write_str(file, self.path ) 559 common.write_str(file, self.name ) 560 common.write_str(file, self.category ) 561 common.write_str(file, self.description) 562 563 buffer = bytearray() 564 for command_pointer in self.commands: 565 buffer = command_pointer.dereference(self).pack_into(buffer) 566 buffer = buffer + struct.pack('<B', 0x00) 567 568 file.write(struct.pack('<i', len(buffer))) 569 file.write(bytes(buffer)) 570 571 def clear(self): 572 self.property_unset('version' ) 573 self.property_unset('path' ) 574 self.property_unset('name' ) 575 self.property_unset('category' ) 576 self.property_unset('description') 577 578 for prop in self.command_type_collections.values(): 579 self.property_unset(prop) 580 581 self.property_unset('misc_commands') 582 583 self.property_unset('commands' ) 584 self.property_unset('active_index') 585 586 self.property_unset('updated')