CM3D2 Converter.menu_file
1import bpy 2import math 3import mathutils 4import struct 5from . import common 6from . import compat 7from .translations.pgettext_functions import * 8 9 10 11PROP_OPTS = {'LIBRARY_EDITABLE'} 12 13# New specially handled commands need to have 3 things 14# 1) An enum entry in COMMAND_ENUMS (if it is not already in there) 15# 2) A class decorated with @CM3D2MenuCommand([enum1, [enum2, [...]]], name="{command_name}" ) 16# 3) A collection property to hold that class in OBJECT_PG_CM3D2Menu 17# The decorators will handle the rest 18 19COMMAND_ENUMS = [ 20 ('', "Menu Meta", ''), 21 ('end' , "End" , "description", 'X' , 0), 22 ('name' , "Menu Name" , "description", 'FILE_TEXT' , 3), 23 ('saveitem' , "Menu Category" , "description", 'FILE_TEXT' , 4), 24 ('setumei' , "Menu Description" , "description", 'FILE_TEXT' , 5), 25 ('priority' , "Priority" , "description", 'SORT_DESC' , 6), 26 ('メニューフォルダ' , "Folder" , "description", 'FILE_FOLDER' , 7), 27 ('icon' , "Icon" , "description", 'FILE_IMAGE' , 10), 28 ('icons' , "Icon (Small)" , "description", 'FILE_IMAGE' , 11), # alias of 'icon' 29 ('iconl' , "Icon (Large)" , "Unused" , 'BLANK1' , 12), 30 31 ('', "Item Meta", ''), 32 ('ver' , "Item Version" , "description", 'FILE_TEXT' , 20), 33 ('category' , "Item Category" , "description", 'SORTALPHA' , 21), 34 ('catno' , "Item Category Number" , "description", 'LINENUMBERS_ON' , 22), 35 ('アイテム' , "Item" , "description", 'FILE_3D' , 30), 36 ('アイテム条件' , "Item Conditions" , "description", 'SCRIPTPLUGINS' , 31), 37 ('if' , "Item If" , "description", 'FILE_SCRIPT' , 32), 38 ('アイテムパラメータ' , "Item Parameters" , "description", 'SCRIPTPLUGINS' , 33), 39 ('半脱ぎ' , "Item Half Off" , "description", 'LIBRARY_DATA_INDIRECT', 34), 40 ('リソース参照' , "Item Resource Reference", "description", 'LIBRARY_DATA_INDIRECT', 35), # alias of '半脱ぎ' 41 42 ('', "Item Control", ''), 43 ('set' , "Set" , "Unused" , 'BLANK1' , 40), 44 ('setname' , "Set Name" , "Unused" , 'BLANK1' , 41), 45 ('setslotitem' , "Set Slot Item" , "description", 'FILE_TICK' , 42), 46 ('additem' , "Add Item" , "description", 'ADD' , 43), 47 ('unsetitem' , "Unset Item" , "description", 'REMOVE' , 44), 48 ('nofloory' , "Disable Item Floor" , "description", 'CON_FLOOR' , 45), 49 ('maskitem' , "Mask Item" , "description", 'MOD_MASK' , 46), 50 ('delitem' , "Delete Item" , "description", 'TRASH' , 47), 51 ('node消去' , "Node Hide" , "description", 'HIDE_ON' , 50), 52 ('node表示' , "Node Display" , "description", 'HIDE_OFF' , 51), 53 ('パーツnode消去' , "Parts-Node Hide" , "description", 'VIS_SEL_01' , 52), 54 ('パーツnode表示' , "Parts-Node Display" , "description", 'VIS_SEL_11' , 53), 55 56 ('', "Material Control", ''), 57 ('color' , "Color" , "description", 'COLOR' , 60), 58 ('mancolor' , "Man Color" , "description", 'GHOST_ENABLED' , 61), 59 ('color_set' , "Color-Set" , "description", 'GROUP_VCOL' , 62), 60 ('tex' , "Texture" , "description", 'TEXTURE' , 70), 61 ('テクスチャ変更' , "Texture Change" , "description", 'TEXTURE' , 71), # alias of 'tex' 62 ('テクスチャ乗算' , "Texture Multiplication" , "description", 'FORCE_TEXTURE' , 72), 63 ('テクスチャ合成' , "Texture Composition" , "description", 'NODE_TEXTURE' , 73), 64 ('テクスチャセット合成' , "Texture Set Composition", "description", 'NODE_TEXTURE' , 74), 65 ('マテリアル変更' , "Material Change" , "description", 'MATERIAL' , 80), 66 ('useredit' , "Material Properties" , "description", 'MATERIAL' , 81), 67 ('shader' , "Shader" , "description", 'SHADING_RENDERED' , 90), 68 69 ('', "Maid Control", ''), 70 ('prop' , "Property" , "description", 'PROPERTIES' , 100), 71 ('アタッチポイントの設定' , "Attach Point" , "description", 'HOOK' , 110), 72 ('blendset' , "Face Blend-Set" , "description", 'SHAPEKEY_DATA' , 120), 73 ('paramset' , "Face Parameter-Set" , "description", 'OPTIONS' , 121), 74 ('commenttype' , "Profile Comment Type" , "description", 'TEXT' , 130), 75 ('bonemorph' , "Bone Morph" , "description", 'CONSTRAINT_BONE' , 140), 76 ('length' , "Hair Length" , "description", 'CONSTRAINT_BONE' , 141), 77 ('anime' , "Animation" , "description", 'ANIM' , 150), 78 ('animematerial', "Animation (Material)" , "description", 'ANIM' , 151), 79 ('param2' , "Parameter 2" , "description", 'CON_TRANSFORM' , 160), 80 81 ('', "Misc.", ''), 82 ('setstr' , "Set String" , "Unused" , 'BLANK1' , 170), 83 ('onclickmenu' , "onclickmenu" , "Decorative" , 'NONE' , 200), 84 ('属性追加' , "addattribute" , "Decorative" , 'NONE' , 201) 85] 86 87COMMAND_TYPE_LIST = dict() # filled by the CM3D2MenuCommand decorator 88 89def get_command_enum_info(enum_string, enum_items=COMMAND_ENUMS): 90 if enum_string == '': 91 return None 92 for enum_info in enum_items: 93 if enum_info[0] == enum_string: 94 return enum_info 95 return None 96 97def get_command_enum_name(enum_string, enum_items=COMMAND_ENUMS): 98 if enum_string == '': 99 return '' 100 for enum_info in enum_items: 101 if enum_info[0] == enum_string: 102 return enum_info[1] 103 return enum_string 104 105 106 107 108''' CM3D2 Menu Sub-Classes ''' 109 110@compat.BlRegister() 111class CM3D2MENU_PG_CommandPointer(bpy.types.PropertyGroup): 112 bl_idname = 'CM3D2MenuCommandPointer' 113 114 collection_name = bpy.props.StringProperty(options={'HIDDEN'}) 115 prop_index = bpy.props.IntProperty (options={'HIDDEN'}) 116 117 def dereference(self, data): 118 return getattr(data, self.collection_name)[self.prop_index] 119 120 121@compat.BlRegister() 122class MISCCOMMAND_PG_Param(bpy.types.PropertyGroup): 123 bl_idname = 'CM3D2MenuParam' 124 125 # Really the value should be saved, not the name, but template_list() doesn't like that so they're switched. 126 def _s(self, value): 127 self.name = value 128 129 #name = bpy.props.StringProperty(name="Name", options=PROP_OPTS, get=lambda self : self.value) 130 name = bpy.props.StringProperty(name="Name", default="param", options={'HIDDEN'}) 131 value = bpy.props.StringProperty(name="Slot Name", options={'SKIP_SAVE'}, default="param", set=_s, get=lambda self: self.name) 132 133 134 135 136''' Decorator for CM3D2 Menu Command Classes ''' 137class CM3D2MenuCommand(): 138 def __init__(self, *args, name="{command_name}"): 139 self.name_template = name 140 self.command_enums = set() 141 for command in args: 142 for enum_info in COMMAND_ENUMS: 143 if enum_info[0] == command: 144 self.command_enums.add(enum_info) 145 break 146 continue 147 148 def __call__(self, cls): 149 cls.name_template = self.name_template 150 cls.command_enums = self.command_enums 151 # Associate the class with its command in COMMAND_CLASSES 152 for enum in cls.command_enums: 153 COMMAND_TYPE_LIST[enum[0]] = cls 154 155 # define command property 156 if len(cls.command_enums) > 0: 157 cls.command = bpy.props.EnumProperty( 158 items = cls.command_enums, 159 name = "Command", 160 options = PROP_OPTS, 161 default = next(iter(cls.command_enums))[0], 162 description = "The command of this menu file command-chunk" 163 ) 164 else: 165 cls.command = bpy.props.StringProperty( 166 name = "Command", 167 options = PROP_OPTS, 168 default = "command", 169 description = "The command of this menu file command-chunk" 170 ) 171 172 cls.index = bpy.props.IntProperty(name="Index", options=PROP_OPTS) 173 #cls.initalized = bpy.props.BoolProperty(name="Index", options={'SKIP_SAVE'}, default=False) 174 175 attributes = dir(cls) 176 cls.name_format_attributes = set() 177 for attr in attributes: 178 if "{"+attr+"}" in cls.name_template: 179 cls.name_format_attributes.add(attr) 180 181 def format_name(self): 182 params = { attr : getattr(self, attr) for attr in cls.name_format_attributes } 183 if len(cls.command_enums) > 0: 184 params['command_name'] = get_command_enum_name(self.command, enum_items=cls.command_enums) 185 else: 186 params['command_name'] = get_command_enum_name(self.command) 187 return cls.name_template.format(**params) 188 189 cls.format_name = format_name 190 191 # define name property 192 cls.name = bpy.props.StringProperty( 193 name = "Name" , 194 options = {'HIDDEN', 'SKIP_SAVE'}, 195 get = cls.format_name 196 ) 197 198 # add catch and rethrow for functions 199 def catch_throw_wrap(func, gerund, catch_type, throw_type=None): 200 throw_type = throw_type or catch_type 201 prefix = f_tip_("Error {gerund} {bl_idname}: ", gerund=gerund, bl_idname=cls.bl_idname) + "{message}" 202 def _f(*args, **kwargs): 203 try: 204 return func(*args, **kwargs) 205 except catch_type as e: 206 raise throw_type(prefix.format(message=e.args[0])) 207 return _f 208 209 cls.parse_list = catch_throw_wrap(cls.parse_list, "parsing", ValueError) 210 cls.pack_into = catch_throw_wrap(cls.pack_into , "packing", ValueError) 211 212 return cls 213 214 215 216 217''' CM3D2 Menu Command Classes ''' 218 219@compat.BlRegister() 220@CM3D2MenuCommand('アタッチポイントの設定', name="{command_name} : {point_name}") 221class CM3D2MENU_PG_AttachPointCommand(bpy.types.PropertyGroup): 222 bl_idname = 'CM3D2MenuAttachPointCommand' 223 ''' 224 アタッチポイントの設定 225 ├ point_name(呼び出し名) 226 ├ location.x(座標) 227 ├ location.y(座標) 228 ├ location.z(座標) 229 ├ rotation.x(軸回転角度)[範囲:0±180°] 230 ├ rotation.y(軸回転角度)[範囲:0±180°] 231 └ rotation.z(軸回転角度)[範囲:0±180°] 232 ''' 233 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) 234 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')) 235 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' )) 236 237 def parse_list(self, string_list): 238 self.command = string_list[0] 239 self.point_name = string_list[1] 240 self.location.x = float(string_list[2]) 241 self.location.y = float(string_list[3]) 242 self.location.z = float(string_list[4]) 243 self.rotation.x = float(string_list[5]) * math.pi/180 244 self.rotation.y = float(string_list[6]) * math.pi/180 245 self.rotation.z = float(string_list[7]) * math.pi/180 246 247 def pack_into(self, buffer): 248 buffer = buffer + struct.pack('<B', 1 + 1 + 3 + 3) 249 buffer = common.pack_str(buffer, self.command ) 250 buffer = common.pack_str(buffer, self.point_name) 251 buffer = common.pack_str(buffer, str(self.location.x) ) 252 buffer = common.pack_str(buffer, str(self.location.y) ) 253 buffer = common.pack_str(buffer, str(self.location.z) ) 254 buffer = common.pack_str(buffer, str(self.rotation.x * 180/math.pi)) 255 buffer = common.pack_str(buffer, str(self.rotation.y * 180/math.pi)) 256 buffer = common.pack_str(buffer, str(self.rotation.z * 180/math.pi)) 257 258 return buffer 259 260 def draw(self, context, layout): 261 layout.label(text=self.name) 262 263 col = layout.column() 264 col.alignment = 'RIGHT' 265 col.prop(self, 'command', translate=False) 266 col.label(text=self.command + " ", translate=False) 267 268 col = layout.column() 269 col.prop(self, 'point_name') 270 col.prop(self, 'location' ) 271 col.prop(self, 'rotation' ) 272 273 col = layout.column(align=True) 274 col.operator('cm3d2menu.align_selected_to_attach_point', icon=compat.icon('OBJECT_ORIGIN') ) 275 col.operator('cm3d2menu.align_attach_point_to_selected', icon=compat.icon('ORIENTATION_LOCAL')) 276 277 278@compat.BlRegister() 279@CM3D2MenuCommand('prop', name="{command_name} : {prop_name} = {value}") 280class CM3D2MENU_PG_PropertyCommand(bpy.types.PropertyGroup): 281 bl_idname = 'CM3D2PropertyMenuCommand' 282 ''' 283 prop 284 ├ prop_name 285 └ value 286 ''' 287 prop_name = bpy.props.StringProperty(name="Property Name" , default="prop name", description="Name of the property to set on load" , options=PROP_OPTS) 288 value = bpy.props.FloatProperty (name="Property Value", default=50 , description="Value of the property to set on load", options=PROP_OPTS) 289 290 def parse_list(self, string_list): 291 self.command = string_list[0] 292 self.prop_name = string_list[1] 293 self.value = float(string_list[2]) 294 295 def pack_into(self, buffer): 296 buffer = buffer + struct.pack('<B', 1 + 1 + 1) 297 buffer = common.pack_str(buffer, self.command ) 298 buffer = common.pack_str(buffer, self.prop_name ) 299 buffer = common.pack_str(buffer, str(self.value) ) 300 301 return buffer 302 303 def draw(self, context, layout): 304 col = layout.column() 305 col.alignment = 'RIGHT' 306 col.prop(self, 'command', translate=False) 307 col.label(text=self.command + " ", translate=False) 308 309 col = layout.column() 310 col.label(text=self.command, translate=False) 311 col.prop(self, 'prop_name') 312 col.prop(self, 'value' ) 313 314 315@compat.BlRegister() 316@CM3D2MenuCommand(name="{command_name}") 317class CM3D2MENU_PG_MiscCommand(bpy.types.PropertyGroup): 318 bl_idname = 'CM3D2MenuMiscCommand' 319 ''' 320 command 321 ├ child_0 322 ├ child_1 323 ├ child_2 324 ├ ... 325 ├ child_n-1 326 └ child_n 327 ''' 328 params = bpy.props.CollectionProperty(name="Parameters", options=PROP_OPTS, type=MISCCOMMAND_PG_Param) 329 330 active_index = bpy.props.IntProperty(options={'HIDDEN'}) 331 332 search = bpy.props.BoolProperty(name="Search", default=False, description="Search for suggestions", options=PROP_OPTS) 333 334 def new_param(self): 335 new_param = self.params.add() 336 new_param.value = "newparam" 337 return new_param 338 339 def remove_param(self, index: int): 340 return self.params.remove(index) 341 342 def move_param(self, old_index, new_index): 343 return self.params.move(old_index, new_index) 344 345 def parse_list(self, string_list): 346 self.command = string_list[0] 347 for param in string_list[1:]: 348 new_param = self.params.add() 349 new_param.value = param 350 new_param.name = param 351 352 def pack_into(self, buffer): 353 buffer = buffer + struct.pack('<B', 1 + len(self.params)) 354 buffer = common.pack_str(buffer, self.command) 355 for param in self.params: 356 buffer = common.pack_str(buffer, param.value) 357 return buffer 358 359 def draw(self, context, layout): 360 enum_info = get_command_enum_info(self.command) 361 if enum_info: 362 layout.label(text=enum_info[1], icon=enum_info[3]) 363 364 row = layout.row(align=True) 365 if not compat.IS_LEGACY: 366 row.use_property_split = False 367 if self.search: 368 search_data = bpy.ops.cm3d2menu.command_add.get_rna_type().properties.get('type') 369 row.prop_search(self, 'command', search_data, 'enum_items', text="", translate=True, icon='VIEWZOOM') 370 else: 371 row.prop(self, 'command', text="") 372 row.prop(self, 'search', text='', icon='ZOOM_OUT' if self.search else 'VIEWZOOM') 373 374 375 row = layout.row() 376 row.template_list('UI_UL_list', 'CM3D2MENU_UL_misc_command_children', 377 self, 'params' , 378 self, 'active_index', 379 rows = 3, 380 maxrows = 8, 381 ) 382 sub_col = row.column(align=True) 383 sub_col.operator('cm3d2menu.param_add' , icon='ADD' , text="") 384 sub_col.operator('cm3d2menu.param_remove', icon='REMOVE', text="") 385 #sub_col.separator() 386 #sub_col.menu("OBJECT_MT_cm3d2_menu_context_menu", icon='DOWNARROW_HLT', text="") 387 if self.active_index < len(self.params): 388 sub_col.separator() 389 sub_col.operator("cm3d2menu.param_move", icon='TRIA_UP' , text="").direction = 'UP' 390 sub_col.operator("cm3d2menu.param_move", icon='TRIA_DOWN', text="").direction = 'DOWN' 391 392 393 394 395''' CM3D2 Menu Class ''' 396 397# This generates OBJECT_PG_CM3D2Menu.command_type_collections 398def generate_command_type_collections(cls): 399 prop_example = bpy.props.CollectionProperty(type=bpy.types.PropertyGroup) 400 cls.command_type_collections = {} 401 402 for prop_name in dir(cls): 403 if prop_name == "commands": 404 continue 405 406 prop = getattr(cls, prop_name) 407 command_class = None 408 if type(prop) != type(prop_example): 409 continue 410 if "len" in dir(prop): 411 if len(prop) != len(prop_example) : 412 continue 413 if prop[0] != prop_example[0] : 414 continue 415 command_class = prop[1]["type"] 416 417 # Fix for Blender 2.93 418 elif "function" in dir(prop) and "keywords" in dir(prop) and "type" in prop.keywords.keys(): 419 if prop.function != prop_example.function: 420 continue 421 command_class = prop.keywords["type"] 422 else: 423 continue 424 425 if command_class == CM3D2MENU_PG_CommandPointer: 426 continue 427 428 cls.command_type_collections[command_class.bl_idname] = prop_name 429 #print(cls.bl_idname+".command_type_collections[\""+prop_name+"\"]", "=", prop) 430 431 return cls 432 433@compat.BlRegister() 434@generate_command_type_collections 435class OBJECT_PG_CM3D2Menu(bpy.types.PropertyGroup): 436 bl_idname = 'CM3D2Menu' 437 438 version = bpy.props.IntProperty (name="Version" , options=PROP_OPTS, min=0, step=100 ) 439 path = bpy.props.StringProperty(name="Path" , options=PROP_OPTS, subtype='FILE_PATH') 440 name = bpy.props.StringProperty(name="Name" , options=PROP_OPTS) 441 category = bpy.props.StringProperty(name="Category" , options=PROP_OPTS) 442 description = bpy.props.StringProperty(name="Description", options=PROP_OPTS) 443 444 attach_point_commands = bpy.props.CollectionProperty(type=CM3D2MENU_PG_AttachPointCommand, options={'HIDDEN'}) 445 property_commands = bpy.props.CollectionProperty(type=CM3D2MENU_PG_PropertyCommand , options={'HIDDEN'}) 446 misc_commands = bpy.props.CollectionProperty(type=CM3D2MENU_PG_MiscCommand , options={'HIDDEN'}) 447 448 commands = bpy.props.CollectionProperty(name="Commands", type=CM3D2MENU_PG_CommandPointer, options=PROP_OPTS) 449 active_index = bpy.props.IntProperty(name="Active Command Index", options=PROP_OPTS, default=0) 450 451 # NOTE : This dictionary is generated by @generate_command_type_collections 452 #command_type_collections = { 453 # 'CM3D2MenuAttachPointCommand' : 'attach_point_commands', 454 # 'CM3D2MenuPropertyCommand' : 'property_commands' , 455 # ... 456 # for all Collection Properties (except 'commands') 457 #} 458 459 updated = bpy.props.BoolProperty(options={'HIDDEN', 'SKIP_SAVE'}, default=False) 460 def update(self): 461 for index, command_pointer in enumerate(self.commands): 462 command = command_pointer.dereference(self) 463 command.index = index 464 updated = True 465 466 def get_active_command(self): 467 if len(self.commands) <= self.active_index: 468 return None 469 command_pointer = self.commands[self.active_index] 470 return command_pointer.dereference(self) 471 472 def new_command(self, command: str): 473 command_type = COMMAND_TYPE_LIST.get(command) 474 collection_name = 'misc_commands' 475 if command_type: 476 collection_name = self.command_type_collections.get(command_type.bl_idname) or collection_name 477 478 collection = getattr(self, collection_name) 479 new_command = collection.add() 480 new_command.command = command 481 482 new_pointer = self.commands.add() 483 new_pointer.collection_name = collection_name 484 new_pointer.prop_index = len(collection) - 1 485 486 new_command.index = len(self.commands) - 1 487 488 return new_command 489 490 def remove_command(self, index: int): 491 command_pointer = self.commands[index] 492 command = command_pointer.dereference(self) 493 494 collection_name = self.command_type_collections.get(command.bl_idname) or 'misc_commands' 495 collection = getattr(self, collection_name) 496 497 prop_index = command_pointer.prop_index 498 self.commands.remove(index) 499 self.update() 500 collection.remove(prop_index) 501 502 for i, c in enumerate(collection): 503 self.commands[c.index].prop_index = i 504 505 if self.active_index >= len(self.commands): 506 self.active_index = len(self.commands) - 1 507 508 def move_command(self, old_index, new_index, update=True): 509 self.commands.move(old_index, new_index) 510 self.updated = False 511 if update: 512 self.update() 513 514 def parse_list(self, string_list): 515 command = string_list[0] 516 new_command = self.new_command(command) 517 new_command.parse_list(string_list) 518 519 def unpack_from_file(self, file): 520 if common.read_str(file) != 'CM3D2_MENU': 521 raise IOError("Not a valid CM3D2 .menu file.") 522 523 self.version = struct.unpack('<i', file.read(4))[0] 524 self.path = common.read_str(file) 525 self.name = common.read_str(file) 526 self.category = common.read_str(file) 527 self.description = common.read_str(file) 528 529 struct.unpack('<i', file.read(4))[0] 530 string_list = [] 531 string_list_length = struct.unpack('<B', file.read(1))[0] 532 while string_list_length > 0: 533 string_list.clear() 534 535 for i in range(string_list_length): 536 string_list.append(common.read_str(file)) 537 538 try: 539 self.parse_list(string_list) 540 except ValueError as e: 541 print(e) 542 543 # Check for end of file 544 chunk = file.read(1) 545 if len(chunk) == 0: 546 break 547 string_list_length = struct.unpack('<B', chunk)[0] 548 549 self.update() 550 551 def pack_into_file(self, file): 552 self.update() 553 554 common.write_str(file, 'CM3D2_MENU') 555 556 file.write(struct.pack('<i', self.version )) 557 common.write_str(file, self.path ) 558 common.write_str(file, self.name ) 559 common.write_str(file, self.category ) 560 common.write_str(file, self.description) 561 562 buffer = bytearray() 563 for command_pointer in self.commands: 564 buffer = command_pointer.dereference(self).pack_into(buffer) 565 buffer = buffer + struct.pack('<B', 0x00) 566 567 file.write(struct.pack('<i', len(buffer))) 568 file.write(bytes(buffer)) 569 570 def clear(self): 571 self.property_unset('version' ) 572 self.property_unset('path' ) 573 self.property_unset('name' ) 574 self.property_unset('category' ) 575 self.property_unset('description') 576 577 for prop in self.command_type_collections.values(): 578 self.property_unset(prop) 579 580 self.property_unset('misc_commands') 581 582 self.property_unset('commands' ) 583 self.property_unset('active_index') 584 585 self.property_unset('updated') 586 587 588# Pannel & operators in ./CM3D2 Converter/menu_OBJECT_PT_cm3d2_menu.py 589from . import menu_OBJECT_PT_cm3d2_menu 590 591# メニューを登録する関数 592def import_menu_func(self, context): 593 self.layout.operator(menu_OBJECT_PT_cm3d2_menu.CM3D2MENU_OT_import.bl_idname, text="CM3D2 Menu (.menu)", icon_value=common.kiss_icon()) 594 595# メニューを登録する関数 596def export_menu_func(self, context): 597 self.layout.operator(menu_OBJECT_PT_cm3d2_menu.CM3D2MENU_OT_export.bl_idname, text="CM3D2 Menu (.menu)", icon_value=common.kiss_icon())
PROP_OPTS =
{'LIBRARY_EDITABLE'}
COMMAND_ENUMS =
[('', 'Menu Meta', ''), ('end', 'End', 'description', 'X', 0), ('name', 'Menu Name', 'description', 'FILE_TEXT', 3), ('saveitem', 'Menu Category', 'description', 'FILE_TEXT', 4), ('setumei', 'Menu Description', 'description', 'FILE_TEXT', 5), ('priority', 'Priority', 'description', 'SORT_DESC', 6), ('メニューフォルダ', 'Folder', 'description', 'FILE_FOLDER', 7), ('icon', 'Icon', 'description', 'FILE_IMAGE', 10), ('icons', 'Icon (Small)', 'description', 'FILE_IMAGE', 11), ('iconl', 'Icon (Large)', 'Unused', 'BLANK1', 12), ('', 'Item Meta', ''), ('ver', 'Item Version', 'description', 'FILE_TEXT', 20), ('category', 'Item Category', 'description', 'SORTALPHA', 21), ('catno', 'Item Category Number', 'description', 'LINENUMBERS_ON', 22), ('アイテム', 'Item', 'description', 'FILE_3D', 30), ('アイテム条件', 'Item Conditions', 'description', 'SCRIPTPLUGINS', 31), ('if', 'Item If', 'description', 'FILE_SCRIPT', 32), ('アイテムパラメータ', 'Item Parameters', 'description', 'SCRIPTPLUGINS', 33), ('半脱ぎ', 'Item Half Off', 'description', 'LIBRARY_DATA_INDIRECT', 34), ('リソース参照', 'Item Resource Reference', 'description', 'LIBRARY_DATA_INDIRECT', 35), ('', 'Item Control', ''), ('set', 'Set', 'Unused', 'BLANK1', 40), ('setname', 'Set Name', 'Unused', 'BLANK1', 41), ('setslotitem', 'Set Slot Item', 'description', 'FILE_TICK', 42), ('additem', 'Add Item', 'description', 'ADD', 43), ('unsetitem', 'Unset Item', 'description', 'REMOVE', 44), ('nofloory', 'Disable Item Floor', 'description', 'CON_FLOOR', 45), ('maskitem', 'Mask Item', 'description', 'MOD_MASK', 46), ('delitem', 'Delete Item', 'description', 'TRASH', 47), ('node消去', 'Node Hide', 'description', 'HIDE_ON', 50), ('node表示', 'Node Display', 'description', 'HIDE_OFF', 51), ('パーツnode消去', 'Parts-Node Hide', 'description', 'VIS_SEL_01', 52), ('パーツnode表示', 'Parts-Node Display', 'description', 'VIS_SEL_11', 53), ('', 'Material Control', ''), ('color', 'Color', 'description', 'COLOR', 60), ('mancolor', 'Man Color', 'description', 'GHOST_ENABLED', 61), ('color_set', 'Color-Set', 'description', 'GROUP_VCOL', 62), ('tex', 'Texture', 'description', 'TEXTURE', 70), ('テクスチャ変更', 'Texture Change', 'description', 'TEXTURE', 71), ('テクスチャ乗算', 'Texture Multiplication', 'description', 'FORCE_TEXTURE', 72), ('テクスチャ合成', 'Texture Composition', 'description', 'NODE_TEXTURE', 73), ('テクスチャセット合成', 'Texture Set Composition', 'description', 'NODE_TEXTURE', 74), ('マテリアル変更', 'Material Change', 'description', 'MATERIAL', 80), ('useredit', 'Material Properties', 'description', 'MATERIAL', 81), ('shader', 'Shader', 'description', 'SHADING_RENDERED', 90), ('', 'Maid Control', ''), ('prop', 'Property', 'description', 'PROPERTIES', 100), ('アタッチポイントの設定', 'Attach Point', 'description', 'HOOK', 110), ('blendset', 'Face Blend-Set', 'description', 'SHAPEKEY_DATA', 120), ('paramset', 'Face Parameter-Set', 'description', 'OPTIONS', 121), ('commenttype', 'Profile Comment Type', 'description', 'TEXT', 130), ('bonemorph', 'Bone Morph', 'description', 'CONSTRAINT_BONE', 140), ('length', 'Hair Length', 'description', 'CONSTRAINT_BONE', 141), ('anime', 'Animation', 'description', 'ANIM', 150), ('animematerial', 'Animation (Material)', 'description', 'ANIM', 151), ('param2', 'Parameter 2', 'description', 'CON_TRANSFORM', 160), ('', 'Misc.', ''), ('setstr', 'Set String', 'Unused', 'BLANK1', 170), ('onclickmenu', 'onclickmenu', 'Decorative', 'NONE', 200), ('属性追加', 'addattribute', 'Decorative', 'NONE', 201)]
COMMAND_TYPE_LIST =
{'アタッチポイントの設定': <class 'CM3D2 Converter.menu_file.CM3D2MENU_PG_AttachPointCommand'>, 'prop': <class 'CM3D2 Converter.menu_file.CM3D2MENU_PG_PropertyCommand'>}
def
get_command_enum_info( enum_string, enum_items=[('', 'Menu Meta', ''), ('end', 'End', 'description', 'X', 0), ('name', 'Menu Name', 'description', 'FILE_TEXT', 3), ('saveitem', 'Menu Category', 'description', 'FILE_TEXT', 4), ('setumei', 'Menu Description', 'description', 'FILE_TEXT', 5), ('priority', 'Priority', 'description', 'SORT_DESC', 6), ('メニューフォルダ', 'Folder', 'description', 'FILE_FOLDER', 7), ('icon', 'Icon', 'description', 'FILE_IMAGE', 10), ('icons', 'Icon (Small)', 'description', 'FILE_IMAGE', 11), ('iconl', 'Icon (Large)', 'Unused', 'BLANK1', 12), ('', 'Item Meta', ''), ('ver', 'Item Version', 'description', 'FILE_TEXT', 20), ('category', 'Item Category', 'description', 'SORTALPHA', 21), ('catno', 'Item Category Number', 'description', 'LINENUMBERS_ON', 22), ('アイテム', 'Item', 'description', 'FILE_3D', 30), ('アイテム条件', 'Item Conditions', 'description', 'SCRIPTPLUGINS', 31), ('if', 'Item If', 'description', 'FILE_SCRIPT', 32), ('アイテムパラメータ', 'Item Parameters', 'description', 'SCRIPTPLUGINS', 33), ('半脱ぎ', 'Item Half Off', 'description', 'LIBRARY_DATA_INDIRECT', 34), ('リソース参照', 'Item Resource Reference', 'description', 'LIBRARY_DATA_INDIRECT', 35), ('', 'Item Control', ''), ('set', 'Set', 'Unused', 'BLANK1', 40), ('setname', 'Set Name', 'Unused', 'BLANK1', 41), ('setslotitem', 'Set Slot Item', 'description', 'FILE_TICK', 42), ('additem', 'Add Item', 'description', 'ADD', 43), ('unsetitem', 'Unset Item', 'description', 'REMOVE', 44), ('nofloory', 'Disable Item Floor', 'description', 'CON_FLOOR', 45), ('maskitem', 'Mask Item', 'description', 'MOD_MASK', 46), ('delitem', 'Delete Item', 'description', 'TRASH', 47), ('node消去', 'Node Hide', 'description', 'HIDE_ON', 50), ('node表示', 'Node Display', 'description', 'HIDE_OFF', 51), ('パーツnode消去', 'Parts-Node Hide', 'description', 'VIS_SEL_01', 52), ('パーツnode表示', 'Parts-Node Display', 'description', 'VIS_SEL_11', 53), ('', 'Material Control', ''), ('color', 'Color', 'description', 'COLOR', 60), ('mancolor', 'Man Color', 'description', 'GHOST_ENABLED', 61), ('color_set', 'Color-Set', 'description', 'GROUP_VCOL', 62), ('tex', 'Texture', 'description', 'TEXTURE', 70), ('テクスチャ変更', 'Texture Change', 'description', 'TEXTURE', 71), ('テクスチャ乗算', 'Texture Multiplication', 'description', 'FORCE_TEXTURE', 72), ('テクスチャ合成', 'Texture Composition', 'description', 'NODE_TEXTURE', 73), ('テクスチャセット合成', 'Texture Set Composition', 'description', 'NODE_TEXTURE', 74), ('マテリアル変更', 'Material Change', 'description', 'MATERIAL', 80), ('useredit', 'Material Properties', 'description', 'MATERIAL', 81), ('shader', 'Shader', 'description', 'SHADING_RENDERED', 90), ('', 'Maid Control', ''), ('prop', 'Property', 'description', 'PROPERTIES', 100), ('アタッチポイントの設定', 'Attach Point', 'description', 'HOOK', 110), ('blendset', 'Face Blend-Set', 'description', 'SHAPEKEY_DATA', 120), ('paramset', 'Face Parameter-Set', 'description', 'OPTIONS', 121), ('commenttype', 'Profile Comment Type', 'description', 'TEXT', 130), ('bonemorph', 'Bone Morph', 'description', 'CONSTRAINT_BONE', 140), ('length', 'Hair Length', 'description', 'CONSTRAINT_BONE', 141), ('anime', 'Animation', 'description', 'ANIM', 150), ('animematerial', 'Animation (Material)', 'description', 'ANIM', 151), ('param2', 'Parameter 2', 'description', 'CON_TRANSFORM', 160), ('', 'Misc.', ''), ('setstr', 'Set String', 'Unused', 'BLANK1', 170), ('onclickmenu', 'onclickmenu', 'Decorative', 'NONE', 200), ('属性追加', 'addattribute', 'Decorative', 'NONE', 201)]):
def
get_command_enum_name( enum_string, enum_items=[('', 'Menu Meta', ''), ('end', 'End', 'description', 'X', 0), ('name', 'Menu Name', 'description', 'FILE_TEXT', 3), ('saveitem', 'Menu Category', 'description', 'FILE_TEXT', 4), ('setumei', 'Menu Description', 'description', 'FILE_TEXT', 5), ('priority', 'Priority', 'description', 'SORT_DESC', 6), ('メニューフォルダ', 'Folder', 'description', 'FILE_FOLDER', 7), ('icon', 'Icon', 'description', 'FILE_IMAGE', 10), ('icons', 'Icon (Small)', 'description', 'FILE_IMAGE', 11), ('iconl', 'Icon (Large)', 'Unused', 'BLANK1', 12), ('', 'Item Meta', ''), ('ver', 'Item Version', 'description', 'FILE_TEXT', 20), ('category', 'Item Category', 'description', 'SORTALPHA', 21), ('catno', 'Item Category Number', 'description', 'LINENUMBERS_ON', 22), ('アイテム', 'Item', 'description', 'FILE_3D', 30), ('アイテム条件', 'Item Conditions', 'description', 'SCRIPTPLUGINS', 31), ('if', 'Item If', 'description', 'FILE_SCRIPT', 32), ('アイテムパラメータ', 'Item Parameters', 'description', 'SCRIPTPLUGINS', 33), ('半脱ぎ', 'Item Half Off', 'description', 'LIBRARY_DATA_INDIRECT', 34), ('リソース参照', 'Item Resource Reference', 'description', 'LIBRARY_DATA_INDIRECT', 35), ('', 'Item Control', ''), ('set', 'Set', 'Unused', 'BLANK1', 40), ('setname', 'Set Name', 'Unused', 'BLANK1', 41), ('setslotitem', 'Set Slot Item', 'description', 'FILE_TICK', 42), ('additem', 'Add Item', 'description', 'ADD', 43), ('unsetitem', 'Unset Item', 'description', 'REMOVE', 44), ('nofloory', 'Disable Item Floor', 'description', 'CON_FLOOR', 45), ('maskitem', 'Mask Item', 'description', 'MOD_MASK', 46), ('delitem', 'Delete Item', 'description', 'TRASH', 47), ('node消去', 'Node Hide', 'description', 'HIDE_ON', 50), ('node表示', 'Node Display', 'description', 'HIDE_OFF', 51), ('パーツnode消去', 'Parts-Node Hide', 'description', 'VIS_SEL_01', 52), ('パーツnode表示', 'Parts-Node Display', 'description', 'VIS_SEL_11', 53), ('', 'Material Control', ''), ('color', 'Color', 'description', 'COLOR', 60), ('mancolor', 'Man Color', 'description', 'GHOST_ENABLED', 61), ('color_set', 'Color-Set', 'description', 'GROUP_VCOL', 62), ('tex', 'Texture', 'description', 'TEXTURE', 70), ('テクスチャ変更', 'Texture Change', 'description', 'TEXTURE', 71), ('テクスチャ乗算', 'Texture Multiplication', 'description', 'FORCE_TEXTURE', 72), ('テクスチャ合成', 'Texture Composition', 'description', 'NODE_TEXTURE', 73), ('テクスチャセット合成', 'Texture Set Composition', 'description', 'NODE_TEXTURE', 74), ('マテリアル変更', 'Material Change', 'description', 'MATERIAL', 80), ('useredit', 'Material Properties', 'description', 'MATERIAL', 81), ('shader', 'Shader', 'description', 'SHADING_RENDERED', 90), ('', 'Maid Control', ''), ('prop', 'Property', 'description', 'PROPERTIES', 100), ('アタッチポイントの設定', 'Attach Point', 'description', 'HOOK', 110), ('blendset', 'Face Blend-Set', 'description', 'SHAPEKEY_DATA', 120), ('paramset', 'Face Parameter-Set', 'description', 'OPTIONS', 121), ('commenttype', 'Profile Comment Type', 'description', 'TEXT', 130), ('bonemorph', 'Bone Morph', 'description', 'CONSTRAINT_BONE', 140), ('length', 'Hair Length', 'description', 'CONSTRAINT_BONE', 141), ('anime', 'Animation', 'description', 'ANIM', 150), ('animematerial', 'Animation (Material)', 'description', 'ANIM', 151), ('param2', 'Parameter 2', 'description', 'CON_TRANSFORM', 160), ('', 'Misc.', ''), ('setstr', 'Set String', 'Unused', 'BLANK1', 170), ('onclickmenu', 'onclickmenu', 'Decorative', 'NONE', 200), ('属性追加', 'addattribute', 'Decorative', 'NONE', 201)]):
@compat.BlRegister()
class
CM3D2MENU_PG_CommandPointer111@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]
collection_name: <_PropertyDeferred, <built-in function StringProperty>, {'options': {'HIDDEN'}, 'attr': 'collection_name'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'options': {'HIDDEN'}, 'attr': 'collection_name'}>
prop_index: <_PropertyDeferred, <built-in function IntProperty>, {'options': {'HIDDEN'}, 'attr': 'prop_index'}> =
<_PropertyDeferred, <built-in function IntProperty>, {'options': {'HIDDEN'}, 'attr': 'prop_index'}>
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_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
MISCCOMMAND_PG_Param122@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)
name: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Name', 'default': 'param', 'options': {'HIDDEN'}, 'attr': 'name'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Name', 'default': 'param', 'options': {'HIDDEN'}, 'attr': 'name'}>
value: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Slot Name', 'options': {'SKIP_SAVE'}, 'default': 'param', 'set': <function MISCCOMMAND_PG_Param._s at 0x7f6a0eb4dab0>, 'get': <function MISCCOMMAND_PG_Param.<lambda> at 0x7f6a0eb4db40>, 'attr': 'value'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Slot Name', 'options': {'SKIP_SAVE'}, 'default': 'param', 'set': <function MISCCOMMAND_PG_Param._s>, 'get': <function MISCCOMMAND_PG_Param.<lambda>>, 'attr': 'value'}>
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_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
class
CM3D2MenuCommand:
138class CM3D2MenuCommand(): 139 def __init__(self, *args, name="{command_name}"): 140 self.name_template = name 141 self.command_enums = set() 142 for command in args: 143 for enum_info in COMMAND_ENUMS: 144 if enum_info[0] == command: 145 self.command_enums.add(enum_info) 146 break 147 continue 148 149 def __call__(self, cls): 150 cls.name_template = self.name_template 151 cls.command_enums = self.command_enums 152 # Associate the class with its command in COMMAND_CLASSES 153 for enum in cls.command_enums: 154 COMMAND_TYPE_LIST[enum[0]] = cls 155 156 # define command property 157 if len(cls.command_enums) > 0: 158 cls.command = bpy.props.EnumProperty( 159 items = cls.command_enums, 160 name = "Command", 161 options = PROP_OPTS, 162 default = next(iter(cls.command_enums))[0], 163 description = "The command of this menu file command-chunk" 164 ) 165 else: 166 cls.command = bpy.props.StringProperty( 167 name = "Command", 168 options = PROP_OPTS, 169 default = "command", 170 description = "The command of this menu file command-chunk" 171 ) 172 173 cls.index = bpy.props.IntProperty(name="Index", options=PROP_OPTS) 174 #cls.initalized = bpy.props.BoolProperty(name="Index", options={'SKIP_SAVE'}, default=False) 175 176 attributes = dir(cls) 177 cls.name_format_attributes = set() 178 for attr in attributes: 179 if "{"+attr+"}" in cls.name_template: 180 cls.name_format_attributes.add(attr) 181 182 def format_name(self): 183 params = { attr : getattr(self, attr) for attr in cls.name_format_attributes } 184 if len(cls.command_enums) > 0: 185 params['command_name'] = get_command_enum_name(self.command, enum_items=cls.command_enums) 186 else: 187 params['command_name'] = get_command_enum_name(self.command) 188 return cls.name_template.format(**params) 189 190 cls.format_name = format_name 191 192 # define name property 193 cls.name = bpy.props.StringProperty( 194 name = "Name" , 195 options = {'HIDDEN', 'SKIP_SAVE'}, 196 get = cls.format_name 197 ) 198 199 # add catch and rethrow for functions 200 def catch_throw_wrap(func, gerund, catch_type, throw_type=None): 201 throw_type = throw_type or catch_type 202 prefix = f_tip_("Error {gerund} {bl_idname}: ", gerund=gerund, bl_idname=cls.bl_idname) + "{message}" 203 def _f(*args, **kwargs): 204 try: 205 return func(*args, **kwargs) 206 except catch_type as e: 207 raise throw_type(prefix.format(message=e.args[0])) 208 return _f 209 210 cls.parse_list = catch_throw_wrap(cls.parse_list, "parsing", ValueError) 211 cls.pack_into = catch_throw_wrap(cls.pack_into , "packing", ValueError) 212 213 return cls
@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'))
bl_idname =
'CM3D2MenuAttachPointCommand'
アタッチポイントの設定 ├ point_name(呼び出し名) ├ location.x(座標) ├ location.y(座標) ├ location.z(座標) ├ rotation.x(軸回転角度)[範囲:0±180°] ├ rotation.y(軸回転角度)[範囲:0±180°] └ rotation.z(軸回転角度)[範囲:0±180°]
point_name: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Point Name', 'default': 'Attach Point', 'description': 'Name of the slot to define the attatchment point for', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'point_name'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Point Name', 'default': 'Attach Point', 'description': 'Name of the slot to define the attatchment point for', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'point_name'}>
location: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'Location', 'default': (0, 0, 0), 'description': 'Location of the attatchment relative to the base bone', 'options': {'LIBRARY_EDITABLE'}, 'subtype': 'TRANSLATION', 'attr': 'location'}> =
<_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'Location', 'default': (0, 0, 0), 'description': 'Location of the attatchment relative to the base bone', 'options': {'LIBRARY_EDITABLE'}, 'subtype': 'TRANSLATION', 'attr': 'location'}>
rotation: <_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'Rotation', 'default': (0, 0, 0), 'description': 'Rotation of the attatchment relative to the base bone', 'options': {'LIBRARY_EDITABLE'}, 'subtype': 'EULER', 'attr': 'rotation'}> =
<_PropertyDeferred, <built-in function FloatVectorProperty>, {'name': 'Rotation', 'default': (0, 0, 0), 'description': 'Rotation of the attatchment relative to the base bone', 'options': {'LIBRARY_EDITABLE'}, 'subtype': 'EULER', 'attr': 'rotation'}>
def
draw(self, context, layout):
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'))
command: <_PropertyDeferred, <built-in function EnumProperty>, {'items': {('アタッチポイントの設定', 'Attach Point', 'description', 'HOOK', 110)}, 'name': 'Command', 'options': {'LIBRARY_EDITABLE'}, 'default': 'アタッチポイントの設定', 'description': 'The command of this menu file command-chunk', 'attr': 'command'}> =
<_PropertyDeferred, <built-in function EnumProperty>, {'items': {('アタッチポイントの設定', 'Attach Point', 'description', 'HOOK', 110)}, 'name': 'Command', 'options': {'LIBRARY_EDITABLE'}, 'default': 'アタッチポイントの設定', 'description': 'The command of this menu file command-chunk', 'attr': 'command'}>
index: <_PropertyDeferred, <built-in function IntProperty>, {'name': 'Index', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'index'}> =
<_PropertyDeferred, <built-in function IntProperty>, {'name': 'Index', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'index'}>
def
format_name(self):
182 def format_name(self): 183 params = { attr : getattr(self, attr) for attr in cls.name_format_attributes } 184 if len(cls.command_enums) > 0: 185 params['command_name'] = get_command_enum_name(self.command, enum_items=cls.command_enums) 186 else: 187 params['command_name'] = get_command_enum_name(self.command) 188 return cls.name_template.format(**params)
name: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Name', 'options': {'HIDDEN', 'SKIP_SAVE'}, 'get': <function CM3D2MenuCommand.__call__.<locals>.format_name at 0x7f6a0eb4d990>, 'attr': 'name'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Name', 'options': {'HIDDEN', 'SKIP_SAVE'}, 'get': <function CM3D2MenuCommand.__call__.<locals>.format_name>, 'attr': 'name'}>
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_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()
@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' )
prop_name: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Property Name', 'default': 'prop name', 'description': 'Name of the property to set on load', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'prop_name'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Property Name', 'default': 'prop name', 'description': 'Name of the property to set on load', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'prop_name'}>
value: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Property Value', 'default': 50, 'description': 'Value of the property to set on load', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'value'}> =
<_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Property Value', 'default': 50, 'description': 'Value of the property to set on load', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'value'}>
def
draw(self, context, layout):
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' )
command: <_PropertyDeferred, <built-in function EnumProperty>, {'items': {('prop', 'Property', 'description', 'PROPERTIES', 100)}, 'name': 'Command', 'options': {'LIBRARY_EDITABLE'}, 'default': 'prop', 'description': 'The command of this menu file command-chunk', 'attr': 'command'}> =
<_PropertyDeferred, <built-in function EnumProperty>, {'items': {('prop', 'Property', 'description', 'PROPERTIES', 100)}, 'name': 'Command', 'options': {'LIBRARY_EDITABLE'}, 'default': 'prop', 'description': 'The command of this menu file command-chunk', 'attr': 'command'}>
index: <_PropertyDeferred, <built-in function IntProperty>, {'name': 'Index', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'index'}> =
<_PropertyDeferred, <built-in function IntProperty>, {'name': 'Index', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'index'}>
def
format_name(self):
182 def format_name(self): 183 params = { attr : getattr(self, attr) for attr in cls.name_format_attributes } 184 if len(cls.command_enums) > 0: 185 params['command_name'] = get_command_enum_name(self.command, enum_items=cls.command_enums) 186 else: 187 params['command_name'] = get_command_enum_name(self.command) 188 return cls.name_template.format(**params)
name: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Name', 'options': {'HIDDEN', 'SKIP_SAVE'}, 'get': <function CM3D2MenuCommand.__call__.<locals>.format_name at 0x7f6a0eb4dea0>, 'attr': 'name'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Name', 'options': {'HIDDEN', 'SKIP_SAVE'}, 'get': <function CM3D2MenuCommand.__call__.<locals>.format_name>, 'attr': 'name'}>
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_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()
@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'
bl_idname =
'CM3D2MenuMiscCommand'
command ├ child_0 ├ child_1 ├ child_2 ├ ... ├ child_n-1 └ child_n
params: <_PropertyDeferred, <built-in function CollectionProperty>, {'name': 'Parameters', 'options': {'LIBRARY_EDITABLE'}, 'type': <class 'CM3D2 Converter.menu_file.MISCCOMMAND_PG_Param'>, 'attr': 'params'}> =
<_PropertyDeferred, <built-in function CollectionProperty>, {'name': 'Parameters', 'options': {'LIBRARY_EDITABLE'}, 'type': <class 'CM3D2 Converter.menu_file.MISCCOMMAND_PG_Param'>, 'attr': 'params'}>
active_index: <_PropertyDeferred, <built-in function IntProperty>, {'options': {'HIDDEN'}, 'attr': 'active_index'}> =
<_PropertyDeferred, <built-in function IntProperty>, {'options': {'HIDDEN'}, 'attr': 'active_index'}>
search: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Search', 'default': False, 'description': 'Search for suggestions', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'search'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Search', 'default': False, 'description': 'Search for suggestions', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'search'}>
def
draw(self, context, layout):
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'
command: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Command', 'options': {'LIBRARY_EDITABLE'}, 'default': 'command', 'description': 'The command of this menu file command-chunk', 'attr': 'command'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Command', 'options': {'LIBRARY_EDITABLE'}, 'default': 'command', 'description': 'The command of this menu file command-chunk', 'attr': 'command'}>
index: <_PropertyDeferred, <built-in function IntProperty>, {'name': 'Index', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'index'}> =
<_PropertyDeferred, <built-in function IntProperty>, {'name': 'Index', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'index'}>
def
format_name(self):
182 def format_name(self): 183 params = { attr : getattr(self, attr) for attr in cls.name_format_attributes } 184 if len(cls.command_enums) > 0: 185 params['command_name'] = get_command_enum_name(self.command, enum_items=cls.command_enums) 186 else: 187 params['command_name'] = get_command_enum_name(self.command) 188 return cls.name_template.format(**params)
name: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Name', 'options': {'HIDDEN', 'SKIP_SAVE'}, 'get': <function CM3D2MenuCommand.__call__.<locals>.format_name at 0x7f6a0eb4e200>, 'attr': 'name'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Name', 'options': {'HIDDEN', 'SKIP_SAVE'}, 'get': <function CM3D2MenuCommand.__call__.<locals>.format_name>, 'attr': 'name'}>
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_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
generate_command_type_collections(cls):
399def generate_command_type_collections(cls): 400 prop_example = bpy.props.CollectionProperty(type=bpy.types.PropertyGroup) 401 cls.command_type_collections = {} 402 403 for prop_name in dir(cls): 404 if prop_name == "commands": 405 continue 406 407 prop = getattr(cls, prop_name) 408 command_class = None 409 if type(prop) != type(prop_example): 410 continue 411 if "len" in dir(prop): 412 if len(prop) != len(prop_example) : 413 continue 414 if prop[0] != prop_example[0] : 415 continue 416 command_class = prop[1]["type"] 417 418 # Fix for Blender 2.93 419 elif "function" in dir(prop) and "keywords" in dir(prop) and "type" in prop.keywords.keys(): 420 if prop.function != prop_example.function: 421 continue 422 command_class = prop.keywords["type"] 423 else: 424 continue 425 426 if command_class == CM3D2MENU_PG_CommandPointer: 427 continue 428 429 cls.command_type_collections[command_class.bl_idname] = prop_name 430 #print(cls.bl_idname+".command_type_collections[\""+prop_name+"\"]", "=", prop) 431 432 return cls
@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')
version: <_PropertyDeferred, <built-in function IntProperty>, {'name': 'Version', 'options': {'LIBRARY_EDITABLE'}, 'min': 0, 'step': 100, 'attr': 'version'}> =
<_PropertyDeferred, <built-in function IntProperty>, {'name': 'Version', 'options': {'LIBRARY_EDITABLE'}, 'min': 0, 'step': 100, 'attr': 'version'}>
path: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Path', 'options': {'LIBRARY_EDITABLE'}, 'subtype': 'FILE_PATH', 'attr': 'path'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Path', 'options': {'LIBRARY_EDITABLE'}, 'subtype': 'FILE_PATH', 'attr': 'path'}>
name: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Name', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'name'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Name', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'name'}>
category: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Category', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'category'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Category', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'category'}>
description: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'Description', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'description'}> =
<_PropertyDeferred, <built-in function StringProperty>, {'name': 'Description', 'options': {'LIBRARY_EDITABLE'}, 'attr': 'description'}>
attach_point_commands: <_PropertyDeferred, <built-in function CollectionProperty>, {'type': <class 'CM3D2 Converter.menu_file.CM3D2MENU_PG_AttachPointCommand'>, 'options': {'HIDDEN'}, 'attr': 'attach_point_commands'}> =
<_PropertyDeferred, <built-in function CollectionProperty>, {'type': <class 'CM3D2 Converter.menu_file.CM3D2MENU_PG_AttachPointCommand'>, 'options': {'HIDDEN'}, 'attr': 'attach_point_commands'}>
property_commands: <_PropertyDeferred, <built-in function CollectionProperty>, {'type': <class 'CM3D2 Converter.menu_file.CM3D2MENU_PG_PropertyCommand'>, 'options': {'HIDDEN'}, 'attr': 'property_commands'}> =
<_PropertyDeferred, <built-in function CollectionProperty>, {'type': <class 'CM3D2 Converter.menu_file.CM3D2MENU_PG_PropertyCommand'>, 'options': {'HIDDEN'}, 'attr': 'property_commands'}>
misc_commands: <_PropertyDeferred, <built-in function CollectionProperty>, {'type': <class 'CM3D2 Converter.menu_file.CM3D2MENU_PG_MiscCommand'>, 'options': {'HIDDEN'}, 'attr': 'misc_commands'}> =
<_PropertyDeferred, <built-in function CollectionProperty>, {'type': <class 'CM3D2 Converter.menu_file.CM3D2MENU_PG_MiscCommand'>, 'options': {'HIDDEN'}, 'attr': 'misc_commands'}>
commands: <_PropertyDeferred, <built-in function CollectionProperty>, {'name': 'Commands', 'type': <class 'CM3D2 Converter.menu_file.CM3D2MENU_PG_CommandPointer'>, 'options': {'LIBRARY_EDITABLE'}, 'attr': 'commands'}> =
<_PropertyDeferred, <built-in function CollectionProperty>, {'name': 'Commands', 'type': <class 'CM3D2 Converter.menu_file.CM3D2MENU_PG_CommandPointer'>, 'options': {'LIBRARY_EDITABLE'}, 'attr': 'commands'}>
active_index: <_PropertyDeferred, <built-in function IntProperty>, {'name': 'Active Command Index', 'options': {'LIBRARY_EDITABLE'}, 'default': 0, 'attr': 'active_index'}> =
<_PropertyDeferred, <built-in function IntProperty>, {'name': 'Active Command Index', 'options': {'LIBRARY_EDITABLE'}, 'default': 0, 'attr': 'active_index'}>
updated: <_PropertyDeferred, <built-in function BoolProperty>, {'options': {'HIDDEN', 'SKIP_SAVE'}, 'default': False, 'attr': 'updated'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'options': {'HIDDEN', 'SKIP_SAVE'}, 'default': False, 'attr': 'updated'}>
def
new_command(self, command: str):
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
def
remove_command(self, index: int):
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
def
unpack_from_file(self, file):
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()
def
pack_into_file(self, file):
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))
def
clear(self):
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')
command_type_collections =
{'CM3D2MenuAttachPointCommand': 'attach_point_commands', 'CM3D2MenuMiscCommand': 'misc_commands', 'CM3D2PropertyMenuCommand': 'property_commands'}
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_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