CM3D2 Converter.menu_OBJECT_PT_cm3d2_menu

  1import bpy
  2import math
  3import mathutils
  4import struct
  5from . import common
  6from . import compat
  7from . import menu_file
  8
  9''' CM3D2 Menu / Object Panel Classes '''
 10
 11@compat.BlRegister()
 12class CM3D2MENU_UL_command_list(bpy.types.UIList):
 13    bl_idname      = 'CM3D2MENU_UL_command_list'
 14    bl_options     = {'DEFAULT_CLOSED'}
 15    bl_region_type = 'WINDOW'
 16    bl_space_type  = 'PROPERTIES'
 17    # The draw_item function is called for each item of the collection that is visible in the list.
 18    #   data is the RNA object containing the collection,
 19    #   item is the current drawn item of the collection,
 20    #   icon is the "computed" icon for the item (as an integer, because some objects like materials or textures
 21    #   have custom icons ID, which are not available as enum items).
 22    #   active_data is the RNA object containing the active property for the collection (i.e. integer pointing to the
 23    #   active item of the collection).
 24    #   active_propname is the name of the active property (use 'getattr(active_data, active_propname)').
 25    #   index is index of the current item in the collection.
 26    #   flt_flag is the result of the filtering process for this item.
 27    #   Note: as index and flt_flag are optional arguments, you do not have to use/declare them here if you don't
 28    #         need them.
 29    def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
 30        command_prop = item.dereference(data)
 31        # draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
 32        if self.layout_type in {'DEFAULT', 'COMPACT'}:
 33            # You should always start your row layout by a label (icon + text), or a non-embossed text field,
 34            # this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
 35            # We use icon_value of label, as our given icon is an integer value, not an enum ID.
 36            # Note "data" names should never be translated!
 37            if command_prop:
 38                command_enum_info = menu_file.get_command_enum_info(command_prop.command)
 39                icon = 'NONE'
 40                if command_enum_info:
 41                    icon = compat.icon(command_enum_info[3])
 42                layout.label(text=command_prop.name, icon=icon)
 43            else:
 44                layout.label(text="", translate=False, icon_value=icon)
 45        # 'GRID' layout type should be as compact as possible (typically a single icon!).
 46        elif self.layout_type in {'GRID'}:
 47            layout.alignment = 'CENTER'
 48            layout.label(text="", icon_value=icon)
 49
 50
 51@compat.BlRegister()
 52class OBJECT_PT_cm3d2_menu(bpy.types.Panel):
 53    bl_space_type  = 'PROPERTIES'
 54    bl_region_type = 'WINDOW'
 55    bl_context     = 'object'
 56    bl_label       = 'CM3D2 Menu'
 57    bl_idname      = 'OBJECT_PT_cm3d2_menu'
 58
 59    @classmethod
 60    def poll(cls, context):
 61        ob = context.object
 62        if ob:
 63            return True
 64        return False
 65
 66    def draw(self, context):
 67        ob = context.object
 68
 69        row = self.layout.row(align=True)
 70        row.operator('cm3d2menu.import', text="Import CM3D2 Menu File", icon=compat.icon('IMPORT'))
 71        row.operator('cm3d2menu.export', text="Export CM3D2 Menu File", icon=compat.icon('EXPORT'))
 72
 73        cm3d2_menu = ob.cm3d2_menu
 74        active_command = cm3d2_menu.get_active_command()
 75        
 76        col = self.layout.column()
 77        col.prop(cm3d2_menu, 'version'    , translate=False)
 78        col.prop(cm3d2_menu, 'path'       , translate=False)
 79        col.prop(cm3d2_menu, 'name'       , translate=False)
 80        col.prop(cm3d2_menu, 'category'   , translate=False)
 81        col.prop(cm3d2_menu, 'description', translate=False, expand=True)
 82
 83        row = self.layout.row()
 84        row.template_list('CM3D2MENU_UL_command_list', '',
 85            cm3d2_menu, 'commands'    ,
 86            cm3d2_menu, 'active_index',
 87        )
 88        sub_col = row.column(align=True)
 89        sub_col.operator('cm3d2menu.command_add'   , icon='ADD'   , text="")
 90        sub_col.operator('cm3d2menu.command_remove', icon='REMOVE', text="")
 91        #sub_col.separator()
 92        #sub_col.menu("OBJECT_MT_cm3d2_menu_context_menu", icon='DOWNARROW_HLT', text="")
 93        if active_command:
 94            sub_col.separator()
 95            sub_col.operator("cm3d2menu.command_move", icon='TRIA_UP'  , text="").direction = 'UP'  
 96            sub_col.operator("cm3d2menu.command_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
 97        
 98        if active_command:
 99            box = self.layout.box()
100            if not compat.IS_LEGACY:
101                box.use_property_split = True
102            cm3d2_menu.get_active_command().draw(context, box)
103
104
105
106
107''' CM3D2 Menu Operators '''
108
109@compat.BlRegister()
110class CM3D2MENU_OT_import(bpy.types.Operator):
111    bl_idname      = 'cm3d2menu.import'
112    bl_label       = "Import CM3D2 Menu File"
113    bl_description = "Open a .menu file"
114    bl_options     = {'REGISTER', 'UNDO'}
115
116    filepath     = bpy.props.StringProperty(subtype='FILE_PATH')
117    filename_ext = '.menu'
118    filter_glob  = bpy.props.StringProperty(default='*.menu', options={'HIDDEN'})
119
120    @classmethod
121    def poll(cls, context):
122        ob = context.object
123        if ob and ob in context.editable_objects:
124            return True
125        return False
126
127    def invoke(self, context, event):  # type: (bpy.types.Context, Any) -> set
128        prefs = common.preferences()
129        if prefs.menu_import_path:
130            self.filepath = prefs.menu_import_path
131        else:
132            self.filepath = prefs.menu_default_path
133
134        context.window_manager.fileselect_add(self)
135        return {'RUNNING_MODAL'}
136
137    def execute(self, context):
138        ob = context.object
139        try:
140            file = open(self.filepath, 'rb')
141            ob.cm3d2_menu.clear()
142            ob.cm3d2_menu.unpack_from_file(file)
143        except IOError as e:
144            self.report(type={'ERROR'}, message=e.args[0])
145            return {'CANCELLED'}
146        return {'FINISHED'}
147        
148
149@compat.BlRegister()
150class CM3D2MENU_OT_export(bpy.types.Operator):
151    bl_idname      = 'cm3d2menu.export'
152    bl_label       = "Export CM3D2 Menu File"
153    bl_description = "Writes the active CM3D2Menu to a .menu file"
154    bl_options     = {'REGISTER', 'UNDO'}
155
156    filepath     = bpy.props.StringProperty(subtype='FILE_PATH')
157    filename_ext = '.menu'
158    filter_glob  = bpy.props.StringProperty(default='*.menu', options={'HIDDEN'})
159
160    is_backup = bpy.props.BoolProperty(name="Backup", default=True, description="Will backup overwritten files.")
161
162    @classmethod
163    def poll(cls, context):
164        ob = context.object
165        if ob and len(ob.cm3d2_menu.commands):
166            return True
167        return False
168
169    def invoke(self, context, event):  # type: (bpy.types.Context, Any) -> set
170        prefs = common.preferences()
171        if prefs.menu_import_path:
172            self.filepath = prefs.menu_import_path
173        else:
174            self.filepath = prefs.menu_default_path
175
176        context.window_manager.fileselect_add(self)
177        return {'RUNNING_MODAL'}
178
179    def draw(self, context):
180        box = self.layout.box()
181        box.prop(self, 'is_backup', icon='FILE_BACKUP')
182
183    def execute(self, context):
184        ob = context.object
185        try:
186            file = common.open_temporary(self.filepath, 'wb', is_backup=self.is_backup)
187            ob.cm3d2_menu.pack_into_file(file)
188        except IOError as e:
189            self.report(type={'ERROR'}, message=e.args[0])
190            return {'CANCELLED'}
191        self.report(type={'INFO'}, message="Successfully exported to .menu file")
192        return {'FINISHED'}
193
194
195@compat.BlRegister()
196class CM3D2MENU_OT_command_add(bpy.types.Operator):
197    bl_idname      = 'cm3d2menu.command_add'
198    bl_label       = "Add Command"
199    bl_description = "Adds a new CM3D2MenuCommand to the active CM3D2Menu"
200    bl_options     = {'REGISTER', 'UNDO'}
201
202    command_type_enums = menu_file.COMMAND_ENUMS.copy()
203    command_type_enums.append( ('NONE', 'Custom', 'Some other manually entered miscillaneous command', 'GREASEPENCIL', -1) )
204    type = bpy.props.EnumProperty(items=command_type_enums, name="Type", default='NONE')
205    
206    string = bpy.props.StringProperty(name="String", default="newcommand")
207
208    @classmethod
209    def poll(cls, context):
210        ob = context.object
211        if ob:
212            return True
213        return False
214
215    def invoke(self, context, event):
216        return context.window_manager.invoke_props_dialog(self)
217    
218    def draw(self, context):
219        self.layout.prop(self, 'type')
220        if self.type == 'NONE':
221            self.layout.prop(self, 'string')
222    
223    def execute(self, context):
224        ob = context.object
225        cm3d2_menu = ob.cm3d2_menu
226        if self.type != 'NONE':
227            self.string = self.type
228
229        cm3d2_menu.new_command(self.string)
230        cm3d2_menu.active_index = len(cm3d2_menu.commands) - 1
231
232        return {'FINISHED'}
233
234
235@compat.BlRegister()
236class CM3D2MENU_OT_command_remove(bpy.types.Operator):
237    bl_idname      = 'cm3d2menu.command_remove'
238    bl_label       = "Remove Command"
239    bl_description = "Removes the active CM3D2MenuCommand from the active CM3D2Menu"
240    bl_options     = {'REGISTER', 'UNDO'}
241
242    @classmethod
243    def poll(cls, context):
244        ob = context.object
245        if ob and len(ob.cm3d2_menu.commands) - ob.cm3d2_menu.active_index > 0:
246            return True
247        return False
248
249    def execute(self, context):
250        ob = context.object
251        cm3d2_menu = ob.cm3d2_menu
252        cm3d2_menu.remove_command(cm3d2_menu.active_index)
253        if cm3d2_menu.active_index >= len(cm3d2_menu.commands):
254            cm3d2_menu.active_index = len(cm3d2_menu.commands) - 1
255
256        return {'FINISHED'}
257
258
259@compat.BlRegister()
260class CM3D2MENU_OT_command_move(bpy.types.Operator):
261    bl_idname      = 'cm3d2menu.command_move'
262    bl_label       = "Move Command"
263    bl_description = "Moves the active CM3D2MenuCommand up/down in the list"
264    bl_options     = {'REGISTER', 'UNDO'}
265
266    items = [
267        ('UP'  , "Up"  , "Move the active CM3D2MenuCommand up in the list"  ),
268        ('DOWN', "Down", "Move the active CM3D2MenuCommand down in the list"),
269    ]
270    direction = bpy.props.EnumProperty(items=items, name="Direction")
271
272    @classmethod
273    def poll(cls, context):
274        ob = context.object
275        if ob and len(ob.cm3d2_menu.commands) - ob.cm3d2_menu.active_index > 0:
276            return True
277        return False
278
279    def execute(self, context):
280        ob = context.object
281        cm3d2_menu = ob.cm3d2_menu
282
283        new_index = cm3d2_menu.active_index - 1 if self.direction == 'UP' else cm3d2_menu.active_index + 1
284        if new_index >= len(cm3d2_menu.commands):
285            new_index = len(cm3d2_menu.commands) - 1
286        elif new_index < 0:
287            new_index = 0
288
289        cm3d2_menu.move_command(cm3d2_menu.active_index, new_index)
290        cm3d2_menu.active_index = new_index
291
292        return {'FINISHED'}
293
294
295
296
297''' CM3D2 Menu Command Operators '''
298
299# For menu_file.CM3D2MENU_PG_AttachPointCommand
300
301@compat.BlRegister()
302class CM3D2MENU_OT_align_selected_to_attach_point(bpy.types.Operator):
303    bl_idname      = 'cm3d2menu.align_selected_to_attach_point'
304    bl_label       = "Align Selected to Attach Point"
305    bl_description = "Align other selected objects to the active object's active CM3D2 attach point"
306    bl_options     = {'REGISTER', 'UNDO'}
307
308    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.")
309
310    @classmethod
311    def poll(cls, context):
312        ob = context.object
313        arm_ob = None
314        if ob.type == 'ARMATURE':
315            arm_ob = ob
316        else:
317            arm_ob = ob.find_armature()
318        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
319            arm_ob = ob.parent
320
321        if arm_ob and arm_ob.type == 'ARMATURE':
322            active_command = ob.cm3d2_menu.get_active_command()
323            if type(active_command) != menu_file.CM3D2MENU_PG_AttachPointCommand:
324                return False
325        
326        selection = None
327        try:
328            selection = context.selected_editable_objects
329        except:
330            return False
331
332        if not selection or len(selection) < 1:
333            return False
334
335        for selected in selection:
336            if selected != arm_ob and selected != ob:
337                return True
338
339        return False
340
341    def invoke(self, context, event):
342        self.scale = common.preferences().scale
343        return context.window_manager.invoke_props_dialog(self)
344
345    def draw(self, context):
346        self.layout.prop(self, 'scale')
347
348    def execute(self, context):
349        ob = context.object
350        if ob.type == 'ARMATURE':
351            arm_ob = ob
352        else:
353            arm_ob = ob.find_armature()
354        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
355            arm_ob = ob.parent
356        selection = context.selected_editable_objects
357        
358        attach_point = ob.cm3d2_menu.get_active_command()
359        attach_mat = attach_point.rotation.to_matrix().to_4x4()
360        attach_mat.translation = attach_point.location.copy() * self.scale
361
362        attach_basis = compat.convert_cm_to_bl_space(attach_mat)
363        attach_basis = compat.convert_cm_to_bl_bone_rotation(attach_basis)
364
365        for selected in selection:
366            if selected == arm_ob or selected == ob:
367                continue
368            const = selected.constraints.get("CM3D2 Attachment")
369            if not const:
370                const = selected.constraints.new("CHILD_OF")
371                const.name = "CM3D2 Attachment"
372            const.target = arm_ob
373            selected.matrix_basis = attach_basis
374    
375        return {'FINISHED'}
376
377
378@compat.BlRegister()
379class CM3D2MENU_OT_align_attach_point_to_selected(bpy.types.Operator):
380    bl_idname      = 'cm3d2menu.align_attach_point_to_selected'
381    bl_label       = "Align Attach Point to Selected"
382    bl_description = "Align the active CM3D2Menu's active attach point to the first other selected object"
383    bl_options     = {'REGISTER', 'UNDO'}
384
385    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.")
386
387    @classmethod
388    def poll(cls, context):
389        ob = context.object
390        arm_ob = None
391        if ob.type == 'ARMATURE':
392            arm_ob = ob
393        else:
394            arm_ob = ob.find_armature()
395        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
396            arm_ob = ob.parent
397
398        if arm_ob and arm_ob.type == 'ARMATURE':
399            active_command = ob.cm3d2_menu.get_active_command()
400            if type(active_command) != menu_file.CM3D2MENU_PG_AttachPointCommand:
401                return False
402        
403        selection = None
404        try:
405            selection = context.selected_objects
406        except:
407            return False
408
409        if not selection or len(selection) < 1:
410            return False
411
412        for selected in selection:
413            if selected != arm_ob and selected != ob:
414                return True
415
416        return False
417
418    def invoke(self, context, event):
419        self.scale = common.preferences().scale
420        return context.window_manager.invoke_props_dialog(self)
421
422    def draw(self, context):
423        self.layout.prop(self, 'scale')
424
425    def execute(self, context):
426        ob = context.object
427        if ob.type == 'ARMATURE':
428            arm_ob = ob
429        else:
430            arm_ob = ob.find_armature()
431        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
432            arm_ob = ob.parent
433        selection = context.selected_objects
434        
435        attach_point = ob.cm3d2_menu.get_active_command()
436
437
438        for selected in selection:
439            if selected == arm_ob or selected == ob:
440                continue
441            mat = compat.mul(arm_ob.matrix_world.inverted(), selected.matrix_world)
442            mat = compat.convert_bl_to_cm_space(mat)
443            mat = compat.convert_bl_to_cm_bone_rotation(mat)
444
445            attach_point.location = mat.translation * (1/self.scale)
446            attach_point.rotation = mat.to_euler()
447    
448        return {'FINISHED'}
449
450
451
452# For menu_file.CM3D2MENU_PG_MiscCommand
453
454@compat.BlRegister()
455class CM3D2MENU_OT_param_add(bpy.types.Operator):
456    bl_idname      = 'cm3d2menu.param_add'
457    bl_label       = "Add Parameter"
458    bl_description = "Adds a new CM3D2MenuParam to the active CM3D2MenuCommand"
459    bl_options     = {'REGISTER', 'UNDO'}
460
461    @classmethod
462    def poll(cls, context):
463        ob = context.object
464        if ob and ob.cm3d2_menu:
465            misc_command = ob.cm3d2_menu.get_active_command()
466            if type(misc_command) == menu_file.CM3D2MENU_PG_MiscCommand:
467                return True
468        return False
469   
470    def execute(self, context):
471        ob = context.object
472        cm3d2_menu = ob.cm3d2_menu
473        misc_command = ob.cm3d2_menu.get_active_command()
474        misc_command.new_param()
475        misc_command.active_index = len(misc_command.params) - 1
476
477        return {'FINISHED'}
478
479
480@compat.BlRegister()
481class CM3D2MENU_OT_param_remove(bpy.types.Operator):
482    bl_idname      = 'cm3d2menu.param_remove'
483    bl_label       = "Remove Parameter"
484    bl_description = "Removes the active CM3D2MenuParam from the active CM3D2MenuCommand"
485    bl_options     = {'REGISTER', 'UNDO'}
486
487    @classmethod
488    def poll(cls, context):
489        ob = context.object
490        if not ob or not ob.cm3d2_menu:
491            return False
492
493        misc_command = ob.cm3d2_menu.get_active_command()
494        if type(misc_command) != menu_file.CM3D2MENU_PG_MiscCommand:
495            return False
496        
497        if len(misc_command.params) - misc_command.active_index <= 0:
498            return False
499            
500        return True
501
502    def execute(self, context):
503        ob = context.object
504        cm3d2_menu = ob.cm3d2_menu
505        misc_command = ob.cm3d2_menu.get_active_command()
506        misc_command.remove_param(misc_command.active_index)
507        if misc_command.active_index >= len(misc_command.params):
508            misc_command.active_index = len(misc_command.params) - 1
509
510        return {'FINISHED'}
511
512
513@compat.BlRegister()
514class CM3D2MENU_OT_param_move(bpy.types.Operator):
515    bl_idname      = 'cm3d2menu.param_move'
516    bl_label       = "Move Parameter"
517    bl_description = "Moves the active CM3D2MenuParameter up/down in the list"
518    bl_options     = {'REGISTER', 'UNDO'}
519
520    items = [
521        ('UP'  , "Up"  , "Move the active CM3D2MenuCommand up in the list"  ),
522        ('DOWN', "Down", "Move the active CM3D2MenuCommand down in the list"),
523    ]
524    direction = bpy.props.EnumProperty(items=items, name="Direction")
525
526    @classmethod
527    def poll(cls, context):
528        ob = context.object
529        if not ob or not ob.cm3d2_menu:
530            return False
531
532        misc_command = ob.cm3d2_menu.get_active_command()
533        if type(misc_command) != menu_file.CM3D2MENU_PG_MiscCommand:
534            return False
535        
536        if len(misc_command.params) - misc_command.active_index <= 0:
537            return False
538
539        return True
540
541    def execute(self, context):
542        ob = context.object
543        cm3d2_menu = ob.cm3d2_menu
544        misc_command = ob.cm3d2_menu.get_active_command()
545
546        new_index = misc_command.active_index - 1 if self.direction == 'UP' else misc_command.active_index + 1
547        if new_index >= len(misc_command.params):
548            new_index = len(misc_command.params) - 1
549        elif new_index < 0:
550            new_index = 0
551
552        misc_command.move_param(misc_command.active_index, new_index)
553        misc_command.active_index = new_index
554
555        return {'FINISHED'}
@compat.BlRegister()
class CM3D2MENU_UL_command_list(bpy_types.UIList):
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)
bl_idname = 'CM3D2MENU_UL_command_list'
bl_options = {'DEFAULT_CLOSED'}
bl_region_type = 'WINDOW'
bl_space_type = 'PROPERTIES'
def draw_item( self, context, layout, data, item, icon, active_data, active_propname):
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)
bl_rna = <bpy_struct, Struct("CM3D2MENU_UL_command_list")>
Inherited Members
bpy_types._GenericUI
is_extended
append
prepend
remove
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class OBJECT_PT_cm3d2_menu(bpy_types.Panel):
 52@compat.BlRegister()
 53class OBJECT_PT_cm3d2_menu(bpy.types.Panel):
 54    bl_space_type  = 'PROPERTIES'
 55    bl_region_type = 'WINDOW'
 56    bl_context     = 'object'
 57    bl_label       = 'CM3D2 Menu'
 58    bl_idname      = 'OBJECT_PT_cm3d2_menu'
 59
 60    @classmethod
 61    def poll(cls, context):
 62        ob = context.object
 63        if ob:
 64            return True
 65        return False
 66
 67    def draw(self, context):
 68        ob = context.object
 69
 70        row = self.layout.row(align=True)
 71        row.operator('cm3d2menu.import', text="Import CM3D2 Menu File", icon=compat.icon('IMPORT'))
 72        row.operator('cm3d2menu.export', text="Export CM3D2 Menu File", icon=compat.icon('EXPORT'))
 73
 74        cm3d2_menu = ob.cm3d2_menu
 75        active_command = cm3d2_menu.get_active_command()
 76        
 77        col = self.layout.column()
 78        col.prop(cm3d2_menu, 'version'    , translate=False)
 79        col.prop(cm3d2_menu, 'path'       , translate=False)
 80        col.prop(cm3d2_menu, 'name'       , translate=False)
 81        col.prop(cm3d2_menu, 'category'   , translate=False)
 82        col.prop(cm3d2_menu, 'description', translate=False, expand=True)
 83
 84        row = self.layout.row()
 85        row.template_list('CM3D2MENU_UL_command_list', '',
 86            cm3d2_menu, 'commands'    ,
 87            cm3d2_menu, 'active_index',
 88        )
 89        sub_col = row.column(align=True)
 90        sub_col.operator('cm3d2menu.command_add'   , icon='ADD'   , text="")
 91        sub_col.operator('cm3d2menu.command_remove', icon='REMOVE', text="")
 92        #sub_col.separator()
 93        #sub_col.menu("OBJECT_MT_cm3d2_menu_context_menu", icon='DOWNARROW_HLT', text="")
 94        if active_command:
 95            sub_col.separator()
 96            sub_col.operator("cm3d2menu.command_move", icon='TRIA_UP'  , text="").direction = 'UP'  
 97            sub_col.operator("cm3d2menu.command_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
 98        
 99        if active_command:
100            box = self.layout.box()
101            if not compat.IS_LEGACY:
102                box.use_property_split = True
103            cm3d2_menu.get_active_command().draw(context, box)
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'object'
bl_label = 'CM3D2 Menu'
bl_idname = 'OBJECT_PT_cm3d2_menu'
@classmethod
def poll(cls, context):
60    @classmethod
61    def poll(cls, context):
62        ob = context.object
63        if ob:
64            return True
65        return False
def draw(self, context):
 67    def draw(self, context):
 68        ob = context.object
 69
 70        row = self.layout.row(align=True)
 71        row.operator('cm3d2menu.import', text="Import CM3D2 Menu File", icon=compat.icon('IMPORT'))
 72        row.operator('cm3d2menu.export', text="Export CM3D2 Menu File", icon=compat.icon('EXPORT'))
 73
 74        cm3d2_menu = ob.cm3d2_menu
 75        active_command = cm3d2_menu.get_active_command()
 76        
 77        col = self.layout.column()
 78        col.prop(cm3d2_menu, 'version'    , translate=False)
 79        col.prop(cm3d2_menu, 'path'       , translate=False)
 80        col.prop(cm3d2_menu, 'name'       , translate=False)
 81        col.prop(cm3d2_menu, 'category'   , translate=False)
 82        col.prop(cm3d2_menu, 'description', translate=False, expand=True)
 83
 84        row = self.layout.row()
 85        row.template_list('CM3D2MENU_UL_command_list', '',
 86            cm3d2_menu, 'commands'    ,
 87            cm3d2_menu, 'active_index',
 88        )
 89        sub_col = row.column(align=True)
 90        sub_col.operator('cm3d2menu.command_add'   , icon='ADD'   , text="")
 91        sub_col.operator('cm3d2menu.command_remove', icon='REMOVE', text="")
 92        #sub_col.separator()
 93        #sub_col.menu("OBJECT_MT_cm3d2_menu_context_menu", icon='DOWNARROW_HLT', text="")
 94        if active_command:
 95            sub_col.separator()
 96            sub_col.operator("cm3d2menu.command_move", icon='TRIA_UP'  , text="").direction = 'UP'  
 97            sub_col.operator("cm3d2menu.command_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
 98        
 99        if active_command:
100            box = self.layout.box()
101            if not compat.IS_LEGACY:
102                box.use_property_split = True
103            cm3d2_menu.get_active_command().draw(context, box)
bl_rna = <bpy_struct, Struct("OBJECT_PT_cm3d2_menu")>
Inherited Members
bpy_types._GenericUI
is_extended
append
prepend
remove
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CM3D2MENU_OT_import(bpy_types.Operator):
110@compat.BlRegister()
111class CM3D2MENU_OT_import(bpy.types.Operator):
112    bl_idname      = 'cm3d2menu.import'
113    bl_label       = "Import CM3D2 Menu File"
114    bl_description = "Open a .menu file"
115    bl_options     = {'REGISTER', 'UNDO'}
116
117    filepath     = bpy.props.StringProperty(subtype='FILE_PATH')
118    filename_ext = '.menu'
119    filter_glob  = bpy.props.StringProperty(default='*.menu', options={'HIDDEN'})
120
121    @classmethod
122    def poll(cls, context):
123        ob = context.object
124        if ob and ob in context.editable_objects:
125            return True
126        return False
127
128    def invoke(self, context, event):  # type: (bpy.types.Context, Any) -> set
129        prefs = common.preferences()
130        if prefs.menu_import_path:
131            self.filepath = prefs.menu_import_path
132        else:
133            self.filepath = prefs.menu_default_path
134
135        context.window_manager.fileselect_add(self)
136        return {'RUNNING_MODAL'}
137
138    def execute(self, context):
139        ob = context.object
140        try:
141            file = open(self.filepath, 'rb')
142            ob.cm3d2_menu.clear()
143            ob.cm3d2_menu.unpack_from_file(file)
144        except IOError as e:
145            self.report(type={'ERROR'}, message=e.args[0])
146            return {'CANCELLED'}
147        return {'FINISHED'}
bl_idname = 'cm3d2menu.import'
bl_label = 'Import CM3D2 Menu File'
bl_description = 'Open a .menu file'
bl_options = {'REGISTER', 'UNDO'}
filepath: <_PropertyDeferred, <built-in function StringProperty>, {'subtype': 'FILE_PATH', 'attr': 'filepath'}> = <_PropertyDeferred, <built-in function StringProperty>, {'subtype': 'FILE_PATH', 'attr': 'filepath'}>
filename_ext = '.menu'
filter_glob: <_PropertyDeferred, <built-in function StringProperty>, {'default': '*.menu', 'options': {'HIDDEN'}, 'attr': 'filter_glob'}> = <_PropertyDeferred, <built-in function StringProperty>, {'default': '*.menu', 'options': {'HIDDEN'}, 'attr': 'filter_glob'}>
@classmethod
def poll(cls, context):
121    @classmethod
122    def poll(cls, context):
123        ob = context.object
124        if ob and ob in context.editable_objects:
125            return True
126        return False
def invoke(self, context, event):
128    def invoke(self, context, event):  # type: (bpy.types.Context, Any) -> set
129        prefs = common.preferences()
130        if prefs.menu_import_path:
131            self.filepath = prefs.menu_import_path
132        else:
133            self.filepath = prefs.menu_default_path
134
135        context.window_manager.fileselect_add(self)
136        return {'RUNNING_MODAL'}
def execute(self, context):
138    def execute(self, context):
139        ob = context.object
140        try:
141            file = open(self.filepath, 'rb')
142            ob.cm3d2_menu.clear()
143            ob.cm3d2_menu.unpack_from_file(file)
144        except IOError as e:
145            self.report(type={'ERROR'}, message=e.args[0])
146            return {'CANCELLED'}
147        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("CM3D2MENU_OT_import")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CM3D2MENU_OT_export(bpy_types.Operator):
150@compat.BlRegister()
151class CM3D2MENU_OT_export(bpy.types.Operator):
152    bl_idname      = 'cm3d2menu.export'
153    bl_label       = "Export CM3D2 Menu File"
154    bl_description = "Writes the active CM3D2Menu to a .menu file"
155    bl_options     = {'REGISTER', 'UNDO'}
156
157    filepath     = bpy.props.StringProperty(subtype='FILE_PATH')
158    filename_ext = '.menu'
159    filter_glob  = bpy.props.StringProperty(default='*.menu', options={'HIDDEN'})
160
161    is_backup = bpy.props.BoolProperty(name="Backup", default=True, description="Will backup overwritten files.")
162
163    @classmethod
164    def poll(cls, context):
165        ob = context.object
166        if ob and len(ob.cm3d2_menu.commands):
167            return True
168        return False
169
170    def invoke(self, context, event):  # type: (bpy.types.Context, Any) -> set
171        prefs = common.preferences()
172        if prefs.menu_import_path:
173            self.filepath = prefs.menu_import_path
174        else:
175            self.filepath = prefs.menu_default_path
176
177        context.window_manager.fileselect_add(self)
178        return {'RUNNING_MODAL'}
179
180    def draw(self, context):
181        box = self.layout.box()
182        box.prop(self, 'is_backup', icon='FILE_BACKUP')
183
184    def execute(self, context):
185        ob = context.object
186        try:
187            file = common.open_temporary(self.filepath, 'wb', is_backup=self.is_backup)
188            ob.cm3d2_menu.pack_into_file(file)
189        except IOError as e:
190            self.report(type={'ERROR'}, message=e.args[0])
191            return {'CANCELLED'}
192        self.report(type={'INFO'}, message="Successfully exported to .menu file")
193        return {'FINISHED'}
bl_idname = 'cm3d2menu.export'
bl_label = 'Export CM3D2 Menu File'
bl_description = 'Writes the active CM3D2Menu to a .menu file'
bl_options = {'REGISTER', 'UNDO'}
filepath: <_PropertyDeferred, <built-in function StringProperty>, {'subtype': 'FILE_PATH', 'attr': 'filepath'}> = <_PropertyDeferred, <built-in function StringProperty>, {'subtype': 'FILE_PATH', 'attr': 'filepath'}>
filename_ext = '.menu'
filter_glob: <_PropertyDeferred, <built-in function StringProperty>, {'default': '*.menu', 'options': {'HIDDEN'}, 'attr': 'filter_glob'}> = <_PropertyDeferred, <built-in function StringProperty>, {'default': '*.menu', 'options': {'HIDDEN'}, 'attr': 'filter_glob'}>
is_backup: <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Backup', 'default': True, 'description': 'Will backup overwritten files.', 'attr': 'is_backup'}> = <_PropertyDeferred, <built-in function BoolProperty>, {'name': 'Backup', 'default': True, 'description': 'Will backup overwritten files.', 'attr': 'is_backup'}>
@classmethod
def poll(cls, context):
163    @classmethod
164    def poll(cls, context):
165        ob = context.object
166        if ob and len(ob.cm3d2_menu.commands):
167            return True
168        return False
def invoke(self, context, event):
170    def invoke(self, context, event):  # type: (bpy.types.Context, Any) -> set
171        prefs = common.preferences()
172        if prefs.menu_import_path:
173            self.filepath = prefs.menu_import_path
174        else:
175            self.filepath = prefs.menu_default_path
176
177        context.window_manager.fileselect_add(self)
178        return {'RUNNING_MODAL'}
def draw(self, context):
180    def draw(self, context):
181        box = self.layout.box()
182        box.prop(self, 'is_backup', icon='FILE_BACKUP')
def execute(self, context):
184    def execute(self, context):
185        ob = context.object
186        try:
187            file = common.open_temporary(self.filepath, 'wb', is_backup=self.is_backup)
188            ob.cm3d2_menu.pack_into_file(file)
189        except IOError as e:
190            self.report(type={'ERROR'}, message=e.args[0])
191            return {'CANCELLED'}
192        self.report(type={'INFO'}, message="Successfully exported to .menu file")
193        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("CM3D2MENU_OT_export")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CM3D2MENU_OT_command_add(bpy_types.Operator):
196@compat.BlRegister()
197class CM3D2MENU_OT_command_add(bpy.types.Operator):
198    bl_idname      = 'cm3d2menu.command_add'
199    bl_label       = "Add Command"
200    bl_description = "Adds a new CM3D2MenuCommand to the active CM3D2Menu"
201    bl_options     = {'REGISTER', 'UNDO'}
202
203    command_type_enums = menu_file.COMMAND_ENUMS.copy()
204    command_type_enums.append( ('NONE', 'Custom', 'Some other manually entered miscillaneous command', 'GREASEPENCIL', -1) )
205    type = bpy.props.EnumProperty(items=command_type_enums, name="Type", default='NONE')
206    
207    string = bpy.props.StringProperty(name="String", default="newcommand")
208
209    @classmethod
210    def poll(cls, context):
211        ob = context.object
212        if ob:
213            return True
214        return False
215
216    def invoke(self, context, event):
217        return context.window_manager.invoke_props_dialog(self)
218    
219    def draw(self, context):
220        self.layout.prop(self, 'type')
221        if self.type == 'NONE':
222            self.layout.prop(self, 'string')
223    
224    def execute(self, context):
225        ob = context.object
226        cm3d2_menu = ob.cm3d2_menu
227        if self.type != 'NONE':
228            self.string = self.type
229
230        cm3d2_menu.new_command(self.string)
231        cm3d2_menu.active_index = len(cm3d2_menu.commands) - 1
232
233        return {'FINISHED'}
bl_idname = 'cm3d2menu.command_add'
bl_label = 'Add Command'
bl_description = 'Adds a new CM3D2MenuCommand to the active CM3D2Menu'
bl_options = {'REGISTER', 'UNDO'}
command_type_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), ('NONE', 'Custom', 'Some other manually entered miscillaneous command', 'GREASEPENCIL', -1)]
type: <_PropertyDeferred, <built-in function EnumProperty>, {'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), ('NONE', 'Custom', 'Some other manually entered miscillaneous command', 'GREASEPENCIL', -1)], 'name': 'Type', 'default': 'NONE', 'attr': 'type'}> = <_PropertyDeferred, <built-in function EnumProperty>, {'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), ('NONE', 'Custom', 'Some other manually entered miscillaneous command', 'GREASEPENCIL', -1)], 'name': 'Type', 'default': 'NONE', 'attr': 'type'}>
string: <_PropertyDeferred, <built-in function StringProperty>, {'name': 'String', 'default': 'newcommand', 'attr': 'string'}> = <_PropertyDeferred, <built-in function StringProperty>, {'name': 'String', 'default': 'newcommand', 'attr': 'string'}>
@classmethod
def poll(cls, context):
209    @classmethod
210    def poll(cls, context):
211        ob = context.object
212        if ob:
213            return True
214        return False
def invoke(self, context, event):
216    def invoke(self, context, event):
217        return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
219    def draw(self, context):
220        self.layout.prop(self, 'type')
221        if self.type == 'NONE':
222            self.layout.prop(self, 'string')
def execute(self, context):
224    def execute(self, context):
225        ob = context.object
226        cm3d2_menu = ob.cm3d2_menu
227        if self.type != 'NONE':
228            self.string = self.type
229
230        cm3d2_menu.new_command(self.string)
231        cm3d2_menu.active_index = len(cm3d2_menu.commands) - 1
232
233        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("CM3D2MENU_OT_command_add")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CM3D2MENU_OT_command_remove(bpy_types.Operator):
236@compat.BlRegister()
237class CM3D2MENU_OT_command_remove(bpy.types.Operator):
238    bl_idname      = 'cm3d2menu.command_remove'
239    bl_label       = "Remove Command"
240    bl_description = "Removes the active CM3D2MenuCommand from the active CM3D2Menu"
241    bl_options     = {'REGISTER', 'UNDO'}
242
243    @classmethod
244    def poll(cls, context):
245        ob = context.object
246        if ob and len(ob.cm3d2_menu.commands) - ob.cm3d2_menu.active_index > 0:
247            return True
248        return False
249
250    def execute(self, context):
251        ob = context.object
252        cm3d2_menu = ob.cm3d2_menu
253        cm3d2_menu.remove_command(cm3d2_menu.active_index)
254        if cm3d2_menu.active_index >= len(cm3d2_menu.commands):
255            cm3d2_menu.active_index = len(cm3d2_menu.commands) - 1
256
257        return {'FINISHED'}
bl_idname = 'cm3d2menu.command_remove'
bl_label = 'Remove Command'
bl_description = 'Removes the active CM3D2MenuCommand from the active CM3D2Menu'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
243    @classmethod
244    def poll(cls, context):
245        ob = context.object
246        if ob and len(ob.cm3d2_menu.commands) - ob.cm3d2_menu.active_index > 0:
247            return True
248        return False
def execute(self, context):
250    def execute(self, context):
251        ob = context.object
252        cm3d2_menu = ob.cm3d2_menu
253        cm3d2_menu.remove_command(cm3d2_menu.active_index)
254        if cm3d2_menu.active_index >= len(cm3d2_menu.commands):
255            cm3d2_menu.active_index = len(cm3d2_menu.commands) - 1
256
257        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("CM3D2MENU_OT_command_remove")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CM3D2MENU_OT_command_move(bpy_types.Operator):
260@compat.BlRegister()
261class CM3D2MENU_OT_command_move(bpy.types.Operator):
262    bl_idname      = 'cm3d2menu.command_move'
263    bl_label       = "Move Command"
264    bl_description = "Moves the active CM3D2MenuCommand up/down in the list"
265    bl_options     = {'REGISTER', 'UNDO'}
266
267    items = [
268        ('UP'  , "Up"  , "Move the active CM3D2MenuCommand up in the list"  ),
269        ('DOWN', "Down", "Move the active CM3D2MenuCommand down in the list"),
270    ]
271    direction = bpy.props.EnumProperty(items=items, name="Direction")
272
273    @classmethod
274    def poll(cls, context):
275        ob = context.object
276        if ob and len(ob.cm3d2_menu.commands) - ob.cm3d2_menu.active_index > 0:
277            return True
278        return False
279
280    def execute(self, context):
281        ob = context.object
282        cm3d2_menu = ob.cm3d2_menu
283
284        new_index = cm3d2_menu.active_index - 1 if self.direction == 'UP' else cm3d2_menu.active_index + 1
285        if new_index >= len(cm3d2_menu.commands):
286            new_index = len(cm3d2_menu.commands) - 1
287        elif new_index < 0:
288            new_index = 0
289
290        cm3d2_menu.move_command(cm3d2_menu.active_index, new_index)
291        cm3d2_menu.active_index = new_index
292
293        return {'FINISHED'}
bl_idname = 'cm3d2menu.command_move'
bl_label = 'Move Command'
bl_description = 'Moves the active CM3D2MenuCommand up/down in the list'
bl_options = {'REGISTER', 'UNDO'}
items = [('UP', 'Up', 'Move the active CM3D2MenuCommand up in the list'), ('DOWN', 'Down', 'Move the active CM3D2MenuCommand down in the list')]
direction: <_PropertyDeferred, <built-in function EnumProperty>, {'items': [('UP', 'Up', 'Move the active CM3D2MenuCommand up in the list'), ('DOWN', 'Down', 'Move the active CM3D2MenuCommand down in the list')], 'name': 'Direction', 'attr': 'direction'}> = <_PropertyDeferred, <built-in function EnumProperty>, {'items': [('UP', 'Up', 'Move the active CM3D2MenuCommand up in the list'), ('DOWN', 'Down', 'Move the active CM3D2MenuCommand down in the list')], 'name': 'Direction', 'attr': 'direction'}>
@classmethod
def poll(cls, context):
273    @classmethod
274    def poll(cls, context):
275        ob = context.object
276        if ob and len(ob.cm3d2_menu.commands) - ob.cm3d2_menu.active_index > 0:
277            return True
278        return False
def execute(self, context):
280    def execute(self, context):
281        ob = context.object
282        cm3d2_menu = ob.cm3d2_menu
283
284        new_index = cm3d2_menu.active_index - 1 if self.direction == 'UP' else cm3d2_menu.active_index + 1
285        if new_index >= len(cm3d2_menu.commands):
286            new_index = len(cm3d2_menu.commands) - 1
287        elif new_index < 0:
288            new_index = 0
289
290        cm3d2_menu.move_command(cm3d2_menu.active_index, new_index)
291        cm3d2_menu.active_index = new_index
292
293        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("CM3D2MENU_OT_command_move")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CM3D2MENU_OT_align_selected_to_attach_point(bpy_types.Operator):
302@compat.BlRegister()
303class CM3D2MENU_OT_align_selected_to_attach_point(bpy.types.Operator):
304    bl_idname      = 'cm3d2menu.align_selected_to_attach_point'
305    bl_label       = "Align Selected to Attach Point"
306    bl_description = "Align other selected objects to the active object's active CM3D2 attach point"
307    bl_options     = {'REGISTER', 'UNDO'}
308
309    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.")
310
311    @classmethod
312    def poll(cls, context):
313        ob = context.object
314        arm_ob = None
315        if ob.type == 'ARMATURE':
316            arm_ob = ob
317        else:
318            arm_ob = ob.find_armature()
319        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
320            arm_ob = ob.parent
321
322        if arm_ob and arm_ob.type == 'ARMATURE':
323            active_command = ob.cm3d2_menu.get_active_command()
324            if type(active_command) != menu_file.CM3D2MENU_PG_AttachPointCommand:
325                return False
326        
327        selection = None
328        try:
329            selection = context.selected_editable_objects
330        except:
331            return False
332
333        if not selection or len(selection) < 1:
334            return False
335
336        for selected in selection:
337            if selected != arm_ob and selected != ob:
338                return True
339
340        return False
341
342    def invoke(self, context, event):
343        self.scale = common.preferences().scale
344        return context.window_manager.invoke_props_dialog(self)
345
346    def draw(self, context):
347        self.layout.prop(self, 'scale')
348
349    def execute(self, context):
350        ob = context.object
351        if ob.type == 'ARMATURE':
352            arm_ob = ob
353        else:
354            arm_ob = ob.find_armature()
355        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
356            arm_ob = ob.parent
357        selection = context.selected_editable_objects
358        
359        attach_point = ob.cm3d2_menu.get_active_command()
360        attach_mat = attach_point.rotation.to_matrix().to_4x4()
361        attach_mat.translation = attach_point.location.copy() * self.scale
362
363        attach_basis = compat.convert_cm_to_bl_space(attach_mat)
364        attach_basis = compat.convert_cm_to_bl_bone_rotation(attach_basis)
365
366        for selected in selection:
367            if selected == arm_ob or selected == ob:
368                continue
369            const = selected.constraints.get("CM3D2 Attachment")
370            if not const:
371                const = selected.constraints.new("CHILD_OF")
372                const.name = "CM3D2 Attachment"
373            const.target = arm_ob
374            selected.matrix_basis = attach_basis
375    
376        return {'FINISHED'}
bl_idname = 'cm3d2menu.align_selected_to_attach_point'
bl_label = 'Align Selected to Attach Point'
bl_description = "Align other selected objects to the active object's active CM3D2 attach point"
bl_options = {'REGISTER', 'UNDO'}
scale: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}>
@classmethod
def poll(cls, context):
311    @classmethod
312    def poll(cls, context):
313        ob = context.object
314        arm_ob = None
315        if ob.type == 'ARMATURE':
316            arm_ob = ob
317        else:
318            arm_ob = ob.find_armature()
319        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
320            arm_ob = ob.parent
321
322        if arm_ob and arm_ob.type == 'ARMATURE':
323            active_command = ob.cm3d2_menu.get_active_command()
324            if type(active_command) != menu_file.CM3D2MENU_PG_AttachPointCommand:
325                return False
326        
327        selection = None
328        try:
329            selection = context.selected_editable_objects
330        except:
331            return False
332
333        if not selection or len(selection) < 1:
334            return False
335
336        for selected in selection:
337            if selected != arm_ob and selected != ob:
338                return True
339
340        return False
def invoke(self, context, event):
342    def invoke(self, context, event):
343        self.scale = common.preferences().scale
344        return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
346    def draw(self, context):
347        self.layout.prop(self, 'scale')
def execute(self, context):
349    def execute(self, context):
350        ob = context.object
351        if ob.type == 'ARMATURE':
352            arm_ob = ob
353        else:
354            arm_ob = ob.find_armature()
355        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
356            arm_ob = ob.parent
357        selection = context.selected_editable_objects
358        
359        attach_point = ob.cm3d2_menu.get_active_command()
360        attach_mat = attach_point.rotation.to_matrix().to_4x4()
361        attach_mat.translation = attach_point.location.copy() * self.scale
362
363        attach_basis = compat.convert_cm_to_bl_space(attach_mat)
364        attach_basis = compat.convert_cm_to_bl_bone_rotation(attach_basis)
365
366        for selected in selection:
367            if selected == arm_ob or selected == ob:
368                continue
369            const = selected.constraints.get("CM3D2 Attachment")
370            if not const:
371                const = selected.constraints.new("CHILD_OF")
372                const.name = "CM3D2 Attachment"
373            const.target = arm_ob
374            selected.matrix_basis = attach_basis
375    
376        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("CM3D2MENU_OT_align_selected_to_attach_point")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CM3D2MENU_OT_align_attach_point_to_selected(bpy_types.Operator):
379@compat.BlRegister()
380class CM3D2MENU_OT_align_attach_point_to_selected(bpy.types.Operator):
381    bl_idname      = 'cm3d2menu.align_attach_point_to_selected'
382    bl_label       = "Align Attach Point to Selected"
383    bl_description = "Align the active CM3D2Menu's active attach point to the first other selected object"
384    bl_options     = {'REGISTER', 'UNDO'}
385
386    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.")
387
388    @classmethod
389    def poll(cls, context):
390        ob = context.object
391        arm_ob = None
392        if ob.type == 'ARMATURE':
393            arm_ob = ob
394        else:
395            arm_ob = ob.find_armature()
396        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
397            arm_ob = ob.parent
398
399        if arm_ob and arm_ob.type == 'ARMATURE':
400            active_command = ob.cm3d2_menu.get_active_command()
401            if type(active_command) != menu_file.CM3D2MENU_PG_AttachPointCommand:
402                return False
403        
404        selection = None
405        try:
406            selection = context.selected_objects
407        except:
408            return False
409
410        if not selection or len(selection) < 1:
411            return False
412
413        for selected in selection:
414            if selected != arm_ob and selected != ob:
415                return True
416
417        return False
418
419    def invoke(self, context, event):
420        self.scale = common.preferences().scale
421        return context.window_manager.invoke_props_dialog(self)
422
423    def draw(self, context):
424        self.layout.prop(self, 'scale')
425
426    def execute(self, context):
427        ob = context.object
428        if ob.type == 'ARMATURE':
429            arm_ob = ob
430        else:
431            arm_ob = ob.find_armature()
432        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
433            arm_ob = ob.parent
434        selection = context.selected_objects
435        
436        attach_point = ob.cm3d2_menu.get_active_command()
437
438
439        for selected in selection:
440            if selected == arm_ob or selected == ob:
441                continue
442            mat = compat.mul(arm_ob.matrix_world.inverted(), selected.matrix_world)
443            mat = compat.convert_bl_to_cm_space(mat)
444            mat = compat.convert_bl_to_cm_bone_rotation(mat)
445
446            attach_point.location = mat.translation * (1/self.scale)
447            attach_point.rotation = mat.to_euler()
448    
449        return {'FINISHED'}
bl_idname = 'cm3d2menu.align_attach_point_to_selected'
bl_label = 'Align Attach Point to Selected'
bl_description = "Align the active CM3D2Menu's active attach point to the first other selected object"
bl_options = {'REGISTER', 'UNDO'}
scale: <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}> = <_PropertyDeferred, <built-in function FloatProperty>, {'name': 'Scale', 'default': 5, 'min': 0.1, 'max': 100, 'soft_min': 0.1, 'soft_max': 100, 'step': 100, 'precision': 1, 'description': 'The amount by which the mesh is scaled when imported. Recommended that you use the same when at the time of export.', 'attr': 'scale'}>
@classmethod
def poll(cls, context):
388    @classmethod
389    def poll(cls, context):
390        ob = context.object
391        arm_ob = None
392        if ob.type == 'ARMATURE':
393            arm_ob = ob
394        else:
395            arm_ob = ob.find_armature()
396        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
397            arm_ob = ob.parent
398
399        if arm_ob and arm_ob.type == 'ARMATURE':
400            active_command = ob.cm3d2_menu.get_active_command()
401            if type(active_command) != menu_file.CM3D2MENU_PG_AttachPointCommand:
402                return False
403        
404        selection = None
405        try:
406            selection = context.selected_objects
407        except:
408            return False
409
410        if not selection or len(selection) < 1:
411            return False
412
413        for selected in selection:
414            if selected != arm_ob and selected != ob:
415                return True
416
417        return False
def invoke(self, context, event):
419    def invoke(self, context, event):
420        self.scale = common.preferences().scale
421        return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
423    def draw(self, context):
424        self.layout.prop(self, 'scale')
def execute(self, context):
426    def execute(self, context):
427        ob = context.object
428        if ob.type == 'ARMATURE':
429            arm_ob = ob
430        else:
431            arm_ob = ob.find_armature()
432        if (not arm_ob) and (ob.parent and ob.parent.type == 'ARMATURE'):
433            arm_ob = ob.parent
434        selection = context.selected_objects
435        
436        attach_point = ob.cm3d2_menu.get_active_command()
437
438
439        for selected in selection:
440            if selected == arm_ob or selected == ob:
441                continue
442            mat = compat.mul(arm_ob.matrix_world.inverted(), selected.matrix_world)
443            mat = compat.convert_bl_to_cm_space(mat)
444            mat = compat.convert_bl_to_cm_bone_rotation(mat)
445
446            attach_point.location = mat.translation * (1/self.scale)
447            attach_point.rotation = mat.to_euler()
448    
449        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("CM3D2MENU_OT_align_attach_point_to_selected")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CM3D2MENU_OT_param_add(bpy_types.Operator):
455@compat.BlRegister()
456class CM3D2MENU_OT_param_add(bpy.types.Operator):
457    bl_idname      = 'cm3d2menu.param_add'
458    bl_label       = "Add Parameter"
459    bl_description = "Adds a new CM3D2MenuParam to the active CM3D2MenuCommand"
460    bl_options     = {'REGISTER', 'UNDO'}
461
462    @classmethod
463    def poll(cls, context):
464        ob = context.object
465        if ob and ob.cm3d2_menu:
466            misc_command = ob.cm3d2_menu.get_active_command()
467            if type(misc_command) == menu_file.CM3D2MENU_PG_MiscCommand:
468                return True
469        return False
470   
471    def execute(self, context):
472        ob = context.object
473        cm3d2_menu = ob.cm3d2_menu
474        misc_command = ob.cm3d2_menu.get_active_command()
475        misc_command.new_param()
476        misc_command.active_index = len(misc_command.params) - 1
477
478        return {'FINISHED'}
bl_idname = 'cm3d2menu.param_add'
bl_label = 'Add Parameter'
bl_description = 'Adds a new CM3D2MenuParam to the active CM3D2MenuCommand'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
462    @classmethod
463    def poll(cls, context):
464        ob = context.object
465        if ob and ob.cm3d2_menu:
466            misc_command = ob.cm3d2_menu.get_active_command()
467            if type(misc_command) == menu_file.CM3D2MENU_PG_MiscCommand:
468                return True
469        return False
def execute(self, context):
471    def execute(self, context):
472        ob = context.object
473        cm3d2_menu = ob.cm3d2_menu
474        misc_command = ob.cm3d2_menu.get_active_command()
475        misc_command.new_param()
476        misc_command.active_index = len(misc_command.params) - 1
477
478        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("CM3D2MENU_OT_param_add")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CM3D2MENU_OT_param_remove(bpy_types.Operator):
481@compat.BlRegister()
482class CM3D2MENU_OT_param_remove(bpy.types.Operator):
483    bl_idname      = 'cm3d2menu.param_remove'
484    bl_label       = "Remove Parameter"
485    bl_description = "Removes the active CM3D2MenuParam from the active CM3D2MenuCommand"
486    bl_options     = {'REGISTER', 'UNDO'}
487
488    @classmethod
489    def poll(cls, context):
490        ob = context.object
491        if not ob or not ob.cm3d2_menu:
492            return False
493
494        misc_command = ob.cm3d2_menu.get_active_command()
495        if type(misc_command) != menu_file.CM3D2MENU_PG_MiscCommand:
496            return False
497        
498        if len(misc_command.params) - misc_command.active_index <= 0:
499            return False
500            
501        return True
502
503    def execute(self, context):
504        ob = context.object
505        cm3d2_menu = ob.cm3d2_menu
506        misc_command = ob.cm3d2_menu.get_active_command()
507        misc_command.remove_param(misc_command.active_index)
508        if misc_command.active_index >= len(misc_command.params):
509            misc_command.active_index = len(misc_command.params) - 1
510
511        return {'FINISHED'}
bl_idname = 'cm3d2menu.param_remove'
bl_label = 'Remove Parameter'
bl_description = 'Removes the active CM3D2MenuParam from the active CM3D2MenuCommand'
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
488    @classmethod
489    def poll(cls, context):
490        ob = context.object
491        if not ob or not ob.cm3d2_menu:
492            return False
493
494        misc_command = ob.cm3d2_menu.get_active_command()
495        if type(misc_command) != menu_file.CM3D2MENU_PG_MiscCommand:
496            return False
497        
498        if len(misc_command.params) - misc_command.active_index <= 0:
499            return False
500            
501        return True
def execute(self, context):
503    def execute(self, context):
504        ob = context.object
505        cm3d2_menu = ob.cm3d2_menu
506        misc_command = ob.cm3d2_menu.get_active_command()
507        misc_command.remove_param(misc_command.active_index)
508        if misc_command.active_index >= len(misc_command.params):
509            misc_command.active_index = len(misc_command.params) - 1
510
511        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("CM3D2MENU_OT_param_remove")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
items
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data
@compat.BlRegister()
class CM3D2MENU_OT_param_move(bpy_types.Operator):
514@compat.BlRegister()
515class CM3D2MENU_OT_param_move(bpy.types.Operator):
516    bl_idname      = 'cm3d2menu.param_move'
517    bl_label       = "Move Parameter"
518    bl_description = "Moves the active CM3D2MenuParameter up/down in the list"
519    bl_options     = {'REGISTER', 'UNDO'}
520
521    items = [
522        ('UP'  , "Up"  , "Move the active CM3D2MenuCommand up in the list"  ),
523        ('DOWN', "Down", "Move the active CM3D2MenuCommand down in the list"),
524    ]
525    direction = bpy.props.EnumProperty(items=items, name="Direction")
526
527    @classmethod
528    def poll(cls, context):
529        ob = context.object
530        if not ob or not ob.cm3d2_menu:
531            return False
532
533        misc_command = ob.cm3d2_menu.get_active_command()
534        if type(misc_command) != menu_file.CM3D2MENU_PG_MiscCommand:
535            return False
536        
537        if len(misc_command.params) - misc_command.active_index <= 0:
538            return False
539
540        return True
541
542    def execute(self, context):
543        ob = context.object
544        cm3d2_menu = ob.cm3d2_menu
545        misc_command = ob.cm3d2_menu.get_active_command()
546
547        new_index = misc_command.active_index - 1 if self.direction == 'UP' else misc_command.active_index + 1
548        if new_index >= len(misc_command.params):
549            new_index = len(misc_command.params) - 1
550        elif new_index < 0:
551            new_index = 0
552
553        misc_command.move_param(misc_command.active_index, new_index)
554        misc_command.active_index = new_index
555
556        return {'FINISHED'}
bl_idname = 'cm3d2menu.param_move'
bl_label = 'Move Parameter'
bl_description = 'Moves the active CM3D2MenuParameter up/down in the list'
bl_options = {'REGISTER', 'UNDO'}
items = [('UP', 'Up', 'Move the active CM3D2MenuCommand up in the list'), ('DOWN', 'Down', 'Move the active CM3D2MenuCommand down in the list')]
direction: <_PropertyDeferred, <built-in function EnumProperty>, {'items': [('UP', 'Up', 'Move the active CM3D2MenuCommand up in the list'), ('DOWN', 'Down', 'Move the active CM3D2MenuCommand down in the list')], 'name': 'Direction', 'attr': 'direction'}> = <_PropertyDeferred, <built-in function EnumProperty>, {'items': [('UP', 'Up', 'Move the active CM3D2MenuCommand up in the list'), ('DOWN', 'Down', 'Move the active CM3D2MenuCommand down in the list')], 'name': 'Direction', 'attr': 'direction'}>
@classmethod
def poll(cls, context):
527    @classmethod
528    def poll(cls, context):
529        ob = context.object
530        if not ob or not ob.cm3d2_menu:
531            return False
532
533        misc_command = ob.cm3d2_menu.get_active_command()
534        if type(misc_command) != menu_file.CM3D2MENU_PG_MiscCommand:
535            return False
536        
537        if len(misc_command.params) - misc_command.active_index <= 0:
538            return False
539
540        return True
def execute(self, context):
542    def execute(self, context):
543        ob = context.object
544        cm3d2_menu = ob.cm3d2_menu
545        misc_command = ob.cm3d2_menu.get_active_command()
546
547        new_index = misc_command.active_index - 1 if self.direction == 'UP' else misc_command.active_index + 1
548        if new_index >= len(misc_command.params):
549            new_index = len(misc_command.params) - 1
550        elif new_index < 0:
551            new_index = 0
552
553        misc_command.move_param(misc_command.active_index, new_index)
554        misc_command.active_index = new_index
555
556        return {'FINISHED'}
bl_rna = <bpy_struct, Struct("CM3D2MENU_OT_param_move")>
Inherited Members
bpy_types.Operator
as_keywords
poll_message_set
builtins.bpy_struct
keys
values
get
pop
as_pointer
keyframe_insert
keyframe_delete
driver_add
driver_remove
is_property_set
property_unset
is_property_hidden
is_property_readonly
is_property_overridable_library
property_overridable_library_set
path_resolve
path_from_id
type_recast
bl_rna_get_subclass_py
bl_rna_get_subclass
id_properties_ensure
id_properties_clear
id_properties_ui
id_data