class IMPORT_OT_egg(bpy.types.Operator, ImportHelper): """Import .egg Operator""" bl_idname = "import_scene.egg" bl_label = "Import .egg" bl_description = "Import a Panda3D .egg file" bl_options = {'REGISTER', 'UNDO'} filename_ext = ".egg" filter_glob = props.StringProperty(default="*.egg;*.egg.pz;*.egg.gz", options={'HIDDEN'}) directory = props.StringProperty(name="Directory", options={'HIDDEN'}) files = props.CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN'}) load_external = props.BoolProperty(name="Load external references", description="Loads other .egg files referenced by this file as separate scenes, and instantiates them using DupliGroups.") auto_bind = props.BoolProperty(name="Auto bind", default=True, description="Automatically tries to bind actions to armatures.") def execute(self, context): context = importer.EggContext() context.info = lambda msg: self.report({'INFO'}, context.prefix_message(msg)) context.warn = lambda msg: self.report({'WARNING'}, context.prefix_message(msg)) context.error = lambda msg: self.report({'ERROR'}, context.prefix_message(msg)) context.search_dir = self.directory roots = [] for file in self.files: path = os.path.join(self.directory, file.name) root = context.read_file(path) roots.append(root) for root in roots: root.build_tree(context) context.assign_vertex_groups() if self.load_external: context.load_external_references() if self.auto_bind: context.auto_bind() context.final_report() return {'FINISHED'} def invoke(self, context, event): wm = context.window_manager wm.fileselect_add(self) return {'RUNNING_MODAL'} def draw(self, context): layout = self.layout row = layout.row() row.prop(self, "load_external") row = layout.row() row.prop(self, "auto_bind")
class RPCGroup(types.PropertyGroup): """PropertyGroup for RPC calls""" name = props.StringProperty("name", default="RPC", description="Name of RPC call") reliable = props.BoolProperty(default=False, description="Guarantee delivery of RPC call") simulated = props.BoolProperty( default=False, description="Allow execution for simulated proxies") target = props.EnumProperty(items=NETWORK_ENUMS, description="Netmode of RPC target") arguments = props.CollectionProperty(type=RPCArgumentGroup) arguments_index = props.IntProperty()
class AttributeGroup(types.PropertyGroup): """PropertyGroup for Actor attributes""" name = props.StringProperty(description="Name of game property") type = props.StringProperty(description="Data type of game property") replicate = props.BoolProperty(default=False, description="Replicate this game property") replicate_for_owner = props.BoolProperty( default=False, description="Replicate this game property to the owner" "client") replicate_after_initial = props.BoolProperty( default=True, description="Replicate this game property after initial " "replication")
class IMPORT_OT_lol(bpy.types.Operator, ImportHelper): bl_label = "Import LoL" bl_idname = "import.lol" SKN_FILE = props.StringProperty(name='Mesh', description='Model .skn file') SKL_FILE = props.StringProperty(name='Skeleton', description='Model .skl file') DDS_FILE = props.StringProperty(name='Texture', description='Model .dds file') MODEL_DIR = props.StringProperty() CLEAR_SCENE = props.BoolProperty( name='ClearScene', description='Clear current scene before importing?', default=True) APPLY_WEIGHTS = props.BoolProperty( name='LoadWeights', description='Load default bone weights from .skn file', default=True) def draw(self, context): layout = self.layout fileProps = context.space_data.params self.MODEL_DIR = fileProps.directory selectedFileExt = path.splitext(fileProps.filename)[-1].lower() if selectedFileExt == '.skn': self.SKN_FILE = fileProps.filename elif selectedFileExt == '.skl': self.SKL_FILE = fileProps.filename elif selectedFileExt == '.dds': self.DDS_FILE = fileProps.filename box = layout.box() box.prop(self.properties, 'SKN_FILE') box.prop(self.properties, 'SKL_FILE') box.prop(self.properties, 'DDS_FILE') box.prop(self.properties, 'CLEAR_SCENE', text='Clear scene before importing') box.prop(self.properties, 'APPLY_WEIGHTS', text='Load mesh weights') def execute(self, context): import_char(MODEL_DIR=self.MODEL_DIR, SKN_FILE=self.SKN_FILE, SKL_FILE=self.SKL_FILE, DDS_FILE=self.DDS_FILE, CLEAR_SCENE=self.CLEAR_SCENE, APPLY_WEIGHTS=self.APPLY_WEIGHTS) return {'FINISHED'}
class TemplateAttributeDefault(types.PropertyGroup): @property def hash(self): return str(hash(getattr(self, self.value_name))) @property def value_name(self): return "value_{}".format(self.type.lower()) @property def value(self): return getattr(self, self.value_name) @value.setter def value(self, value): setattr(self, self.value_name, value) name = props.StringProperty( description="Name of template attribute default value") type = props.EnumProperty( description="Data type of template attribute default value", items=TYPE_ENUMS) value_int = props.IntProperty() value_float = props.FloatProperty() value_string = props.StringProperty() value_bool = props.BoolProperty()
class ParallelRenderPreferences(types.AddonPreferences): bl_idname = __name__ ffmpeg_executable = props.StringProperty( name="Path to ffmpeg executable", default="", update=lambda self, context: self.update(context), subtype='FILE_PATH', ) ffmpeg_status = props.StringProperty(default="") ffmpeg_valid = props.BoolProperty(default=False) def update(self, context): error = _is_valid_ffmpeg_executable(self.ffmpeg_executable) if error is None: self.ffmpeg_valid = True info = subprocess.check_output( (self.ffmpeg_executable, '-version')).decode('utf-8') self.ffmpeg_status = 'Version: {}'.format(info) else: self.ffmpeg_valid = False self.ffmpeg_status = error context.scene.parallel_render_panel.update(context) def draw(self, context): layout = self.layout layout.prop(self, "ffmpeg_executable") icon = 'INFO' if self.ffmpeg_valid else 'ERROR' layout.label(self.ffmpeg_status, icon=icon)
class PieMenuSubItem(_PieMenuItem, bpy.types.PropertyGroup): active = props.BoolProperty( name="Active", description="Activate or deactivate item", default=False, ) operator_arguments = props.CollectionProperty(type=OperatorArgument)
class RPCArgumentGroup(types.PropertyGroup): """PropertyGroup for RPC arguments""" name = props.StringProperty(description="Name of game property") type = props.StringProperty(description="Data type of RPC argument") replicate = props.BoolProperty( default=False, description="Replicate this game property with RPC call")
class ParameterGroup(types.PropertyGroup): name = props.StringProperty(name="Name") data_type = props.EnumProperty(items=enum_data_types) value_str = props.StringProperty() value_int = props.IntProperty() value_bool = props.BoolProperty() value_float = props.FloatProperty() @property def value(self): return getattr(self, "value_{}".format(self.data_type)) @value.setter def value(self, value): setattr(self, "value_{}".format(self.data_type), value)
class EXPORT_OT_lol(bpy.types.Operator, ExportHelper): '''Export a mesh as a League of Legends .skn file''' bl_idname = "export.lol" bl_label = "Export .skn" VERSION = props.IntProperty(name='Version No.', description='.SKN version number', default=4) OUTPUT_FILE = props.StringProperty( name='Export File', description='File to which model will be exported') BASE_ON_IMPORT = props.BoolProperty( name='Base On Imported SKN', description='Base writing on an imported SKN of choice', default=True) INPUT_FILE = props.StringProperty( name='Import File', description='File to import certain metadata from') MODEL_DIR = props.StringProperty() filename_ext = '.skn' def draw(self, context): layout = self.layout fileProps = context.space_data.params self.MODEL_DIR = fileProps.directory selectedFileExt = path.splitext(fileProps.filename)[-1].lower() self.OUTPUT_FILE = fileProps.filename box = layout.box() box.prop(self.properties, 'VERSION') box.prop(self.properties, 'OUTPUT_FILE') box.prop(self.properties, 'BASE_ON_IMPORT') box.prop(self.properties, 'INPUT_FILE') def execute(self, context): export_char(MODEL_DIR=self.MODEL_DIR, OUTPUT_FILE=self.OUTPUT_FILE, INPUT_FILE=self.INPUT_FILE, BASE_ON_IMPORT=self.BASE_ON_IMPORT, VERSION=self.VERSION) return {'FINISHED'}
class MediaInfoPreferences(types.AddonPreferences): bl_idname = __name__ mediainfo_executable = props.StringProperty( name="MediaInfo_Command_Line_Executable", description="Path to MediaInfo executable", default="MediaInfo.exe", update=lambda self, context: self.update(context), subtype='FILE_PATH') #bpy.ops.file.make_paths_absolute() # Paths will be wrong without this mediainfo_status = props.StringProperty(default="") mediainfo_valid = props.BoolProperty(default=False) def update(self, context): # check media info path print("update") global media_info_path mi_exe_path = bpy.path.abspath( self.mediainfo_executable) #convert to absolute path error = "" error = _is_valid_mediainfo_executable(mi_exe_path) if error is None: # path is ok error is None and info = subprocess.check_output(mi_exe_path + ' --Version').decode('utf-8') self.mediainfo_valid = True self.mediainfo_status = 'Version: {}'.format(info) media_info_path = mi_exe_path else: # path is not ok media_info_path = "" self.mediainfo_executable.setvalue = '' self.mediainfo_valid = False self.mediainfo_status = error context.scene.media_info_panel.update(context) def draw(self, context): # add info to properties layout = self.layout layout.prop(self, "mediainfo_executable") if self.mediainfo_valid: icon = 'INFO' else: icon = 'ERROR' layout.label(self.mediainfo_status, icon=icon)
class EXPORT_OT_lolanm(bpy.types.Operator, ImportHelper): bl_label = "Export LoL Animation" bl_idname = "export.lolanm" OUTPUT_FILE = props.StringProperty( name='Export File', description='File to which animation will be exported') INPUT_FILE = props.StringProperty( name='Import File', description='File to import certain metadata from') OVERWRITE_FILE_VERSION = props.BoolProperty( name='Overwrite File Version', description='Write a version different from the imported file', default=False) VERSION = props.IntProperty(name='File Version', description='Overwrite file version', default=3) filename_ext = '.anm' def draw(self, context): layout = self.layout fileProps = context.space_data.params self.MODEL_DIR = fileProps.directory selectedFileExt = path.splitext(fileProps.filename)[-1].lower() self.OUTPUT_FILE = fileProps.filename box = layout.box() box.prop(self.properties, 'OUTPUT_FILE') box.prop(self.properties, 'INPUT_FILE') box.prop(self.properties, 'OVERWRITE_FILE_VERSION') if self.OVERWRITE_FILE_VERSION: box.prop(self.properties, 'VERSION') def execute(self, context): export_animation(MODEL_DIR=self.MODEL_DIR, OUTPUT_FILE=self.OUTPUT_FILE, INPUT_FILE=self.INPUT_FILE, OVERWRITE_FILE_VERSION=self.OVERWRITE_FILE_VERSION, VERSION=self.VERSION) return {'FINISHED'}
class ParallelRenderPropertyGroup(types.PropertyGroup): def update(self, context): addon_props = context.user_preferences.addons[__name__].preferences if not addon_props.ffmpeg_valid and self.concatenate: LOGGER.info( "ParallelRenderPropertyGroup forcing concatenate to false") self.concatenate = False self.clean_up_parts = False if not self.concatenate: self.clean_up_parts = False last_run_result = props.EnumProperty( items=[ # (identifier, name, description, icon, number) ('done', '', ''), ('pending', '', ''), ('failed', '', ''), ], name="Render Batch Size") batch_type = props.EnumProperty( items=[ # (identifier, name, description, icon, number) ('parts', 'No. parts', 'Render in given number of batches (automatically splits it)'), ('fixed', 'Fixed', 'Render in fixed size batches'), ], name="Render Batch Size") max_parallel = props.IntProperty( name="Number of background worker Blender instances", min=1, default=cpu_count() - 1, max=10000) overwrite = props.BoolProperty( name="Overwrite existing files", default=True, ) mixdown = props.BoolProperty( name="Mixdown sound", default=True, ) concatenate = props.BoolProperty( name="Concatenate output files into one", update=lambda self, context: self.update(context), ) clean_up_parts = props.BoolProperty( name="Clean up partial files (after successful concatenation)", ) fixed = props.IntProperty(name="Number of frames per batch", min=1, default=300, max=10000) parts = props.IntProperty(name="Number of batches", min=1, default=cpu_count() * 2, max=10000)
def register(): app.handlers.scene_update_post.append(post_update) app.handlers.load_post.append(post_load) app.handlers.save_pre.append(save_pre) types.Scene.use_hive = props.BoolProperty(default=False)
class ParallelRenderPropertyGroup(types.PropertyGroup): def update(self, context): addon_props = context.preferences.addons[__name__].preferences if not addon_props.ffmpeg_valid and self.concatenate: LOGGER.info( "ParallelRenderPropertyGroup forcing concatenate to false") self.concatenate = False self.clean_up_parts = False if not self.concatenate: self.clean_up_parts = False last_run_result: props.EnumProperty( items=[ # (identifier, name, description, icon, number) ('done', '', ''), ('pending', '', ''), ('failed', '', ''), ], name="Render Batch Size") batch_type: props.EnumProperty( items=[ # (identifier, name, description, icon, number) ('parts', 'Parts', 'Render in given number of batches (automatically splits it)'), ('fixed', 'Fixed', 'Render in fixed size batches'), ], name="Render Batch Size") max_parallel: props.IntProperty(name="Blender Instances", min=1, default=cpu_count() - 1, max=10000) overwrite: props.BoolProperty( name="Overwrite Existing Files", default=True, ) mixdown: props.BoolProperty( name="Mixdown Sound", default=True, ) concatenate: props.BoolProperty( name="Concatenate Output Files", update=lambda self, context: self.update(context), ) clean_up_parts: props.BoolProperty(name="Clean Up Partial Files", ) fixed: props.IntProperty(name="Number of Frames per Batch", min=1, default=300, max=10000) parts: props.IntProperty(name="Number of Parts", min=1, default=(cpu_count() - 1) * 2, max=10000)
class PieMenuPreferences(addongroup.AddonGroup, bpy.types.PropertyGroup if "." in __name__ else bpy.types.AddonPreferences): bl_idname = __package__ submodules = None menus = props.CollectionProperty(type=PieMenu) font_id = props.IntProperty(name="Font ID", default=0, min=0, get=font_id_get) # 読み込み専用 font_id_mono = props.IntProperty(name="Font ID Mono", default=1, min=0) # 読み込み専用 # 中心からアイコンの円の境界まで menu_radius = props.IntProperty(name="Menu Radius", default=30, min=10) menu_radius_center = props.IntProperty(name="Menu Radius Center", default=10, min=0) # submenuに切り替えた際に中心を変えない lock_menu_location = props.BoolProperty(name="Lock Menu Location", default=False) # Itemの上下の隙間がこれより狭いならmenu_radiusを広げる item_min_space = props.IntProperty(name="MenuItem Min Space", default=4, min=0) colors = props.PointerProperty(type=PieMenu_PG_Colors) """:type: PieMenu_PG_Colors""" draw_type = props.EnumProperty(name="Draw Type", description="Default draw type", items=[('SIMPLE', "Simple", ""), ('BOX', "Box", ""), ('CIRCLE', "Circle", ""), ('SIMPLE_BOX', "Simple - Box", ""), ('SIMPLE_CIRCLE', "Simple - Circle", "")], default='BOX') def reset_menus(self): self.menus.clear() pass def draw(self, context): layout = self.layout draw_install = False try: import pie_menu except: draw_install = True else: try: mod = importlib.import_module(".".join( __name__.split(".")[:-1])) except: draw_install = True else: if pie_menu.VERSION != mod.bl_info["version"]: draw_install = True if draw_install: dst = ops.WM_OT_pie_menu_module_install.install_path() row = layout.row() row.operator(ops.WM_OT_pie_menu_module_install.bl_idname, text="Install Module") row = layout.row() row.label("Install Path: " + dst) if ops.module_installed: row = layout.row() row.label("Restart Blender !", icon='ERROR') layout.separator() super().draw(context) return colors = self.colors column = layout.column() sp = column.split() col = sp.column() col.prop(self, "draw_type") col.prop(self, "menu_radius") col.prop(self, "menu_radius_center") col = sp.column() col.prop(self, "lock_menu_location") # col.prop(self, "item_min_space") # わざわざ設定する人もいないだろう col.prop(colors, "use_theme", "Use Current Theme") split = layout.split() column = split.column() sub = column.box().column() sub.prop(colors, "line") sub.prop(colors, "separator") sub.prop(colors, "pointer") sub.prop(colors, "pointer_outline") sub.prop(colors, "pie_sel") sub.prop(colors, "item_highlight") column = split.column() sub = column.box().column() sub.active = not colors.use_theme sub.label("Menu Back:") sub.prop(colors, "menu_inner", text="Inner") sub.prop(colors, "menu_show_shaded") sub2 = sub.column(align=True) sub2.active = colors.menu_show_shaded sub2.prop(colors, "menu_shadetop") sub2.prop(colors, "menu_shadedown") sub.prop(colors, "text") column = split.column() sub = column.box().column() sub.active = not colors.use_theme sub.label("Title:") sub.prop(colors, "title_outline", text="Outline") sub.prop(colors, "title_inner", text="Inner") sub.prop(colors, "title_inner_sel", text="Inner Sel") sub.prop(colors, "title_text", text="Text") sub.prop(colors, "title_text_sel", text="Text Sel") sub.prop(colors, "title_show_shaded") sub2 = sub.column(align=True) sub2.active = colors.title_show_shaded sub2.prop(colors, "title_shadetop") sub2.prop(colors, "title_shadedown") column = split.column() sub = column.box().column() sub.active = not colors.use_theme sub.label("Item:") sub.prop(colors, "item_outline", text="Outline") sub.prop(colors, "item_inner", text="Inner") sub.prop(colors, "item_inner_sel", text="Inner Sel") sub.prop(colors, "item_text", text="Text") sub.prop(colors, "item_text_sel", text="Text Sel") sub.prop(colors, "item_show_shaded") sub2 = sub.column(align=True) sub2.active = colors.item_show_shaded sub2.prop(colors, "item_shadetop") sub2.prop(colors, "item_shadedown") column = split.column() sub = column.box().column() sub.active = not colors.use_theme sub.label("Tooltip:") sub.prop(colors, "tooltip_outline", text="Outline") sub.prop(colors, "tooltip_inner", text="Inner") sub.prop(colors, "tooltip_text", text="Text") sub.prop(colors, "tooltip_show_shaded") sub2 = sub.column(align=True) sub2.active = colors.tooltip_show_shaded sub2.prop(colors, "tooltip_shadetop") sub2.prop(colors, "tooltip_shadedown") draw_separator(layout) # Menus row = layout.row() row.label("Menus:") draw_menus(self, context, layout) draw_separator(layout) super().draw(context)
class PieMenu_PG_Colors(bpy.types.PropertyGroup): use_theme = props.BoolProperty(name="Use Theme Color", description="if True, read user preference", default=False) @classmethod def _generate_props(cls): def gen(attr, klass, name, get_string, **kwargs): def get(self): if self.use_theme: user_pref = bpy.context.user_preferences theme = user_pref.themes["Default"] ui = theme.user_interface value = eval(get_string, globals(), locals()) else: value = getattr(self, "prop_" + attr) try: ls = list(value) return (ls + [1.0])[:4] except: return value def set(self, value): setattr(self, "prop_" + attr, value) setattr(cls, "prop_" + attr, klass(name=name, **kwargs)) setattr(cls, attr, klass(name=name, set=set, get=get, **kwargs)) gen("menu_inner", FVPColor, "Menu Inner", "ui.wcol_menu_back.inner", default=(0.0, 0.0, 0.0, 1.0)) gen("menu_show_shaded", props.BoolProperty, "Shaded", "ui.wcol_menu_back.show_shaded", default=False) gen("menu_shadetop", props.IntProperty, "Shade Top", "ui.wcol_menu_back.shadetop", default=30, min=-100, max=100) gen("menu_shadedown", props.IntProperty, "Shade Top", "ui.wcol_menu_back.shadedown", default=-30, min=-100, max=100) gen("title_outline", FVPColor, "Title Outline", "ui.wcol_menu_back.outline", default=(0.0, 0.0, 0.0, 1.0)) theme = bpy.context.user_preferences.themes["Default"] try: col = list(theme.view_3d.space.gradients.high_gradient) except: col = [0.4, 0.4, 0.4] gen("title_inner", FVPColor, "Title Inner", "ui.wcol_menu_back.inner", default=col + [1.0]) gen("title_inner_sel", FVPColor, "Title Inner Sel", "ui.wcol_menu_back.inner_sel", default=col + [1.0]) del theme, col gen("title_text", FVPColor, "Title Text", "ui.wcol_menu_back.text", default=(1.0, 1.0, 1.0, 1.0)) gen("title_text_sel", FVPColor, "Title Text Sel", "ui.wcol_menu_back.text_sel", default=(1.0, 1.0, 1.0, 1.0)) gen("title_show_shaded", props.BoolProperty, "Shaded", "ui.wcol_menu_back.show_shaded", default=False) gen("title_shadetop", props.IntProperty, "Shade Top", "ui.wcol_menu_back.shadetop", default=30, min=-100, max=100) gen("title_shadedown", props.IntProperty, "Shade Down", "ui.wcol_menu_back.shadedown", default=-30, min=-100, max=100) gen("item_outline", FVPColor, "Item Outline", "ui.wcol_menu_back.outline", default=(0.0, 0.0, 0.0, 1.0)) gen("item_inner", FVPColor, "Item Inner", "ui.wcol_menu_item.inner", default=(0.0, 0.0, 0.0, 0.0)) gen("item_inner_sel", FVPColor, "Item Inner Sel", "ui.wcol_menu_item.inner_sel", default=(0.9, 0.9, 0.9, 1.0)) gen("item_text", FVPColor, "Item Text", "ui.wcol_menu_item.text", default=(1.0, 1.0, 1.0, 1.0)) gen("item_text_sel", FVPColor, "Item Text Sel", "ui.wcol_menu_item.text_sel", default=(0.0, 0.0, 0.0, 1.0)) gen("item_show_shaded", props.BoolProperty, "Shaded", "ui.wcol_menu_item.show_shaded", default=False) gen("item_shadetop", props.IntProperty, "Shade Top", "ui.wcol_menu_item.shadetop", default=30, min=-100, max=100) gen("item_shadedown", props.IntProperty, "Shade Down", "ui.wcol_menu_item.shadedown", default=-30, min=-100, max=100) gen("tooltip_outline", FVPColor, "Tooltip Outline", "ui.wcol_tooltip.outline", default=(1.0, 1.0, 1.0, 1.0)) gen("tooltip_inner", FVPColor, "Tooltip Inner", "ui.wcol_tooltip.inner", default=(0.4, 0.4, 0.4, 1.0)) gen("tooltip_text", FVPColor, "Tooltip Text", "ui.wcol_tooltip.text", default=(1.0, 1.0, 1.0, 1.0)) gen("tooltip_show_shaded", props.BoolProperty, "Shaded", "ui.wcol_tooltip.show_shaded", default=False) gen("tooltip_shadetop", props.IntProperty, "Shade Top", "ui.wcol_tooltip.shadetop", default=30, min=-100, max=100) gen("tooltip_shadedown", props.IntProperty, "Shade Down", "ui.wcol_tooltip.shadedown", default=-30, min=-100, max=100) gen("text", FVPColor, "Text", "theme.view_3d.space.text_hi", default=(1.0, 1.0, 1.0, 1.0)) line = FVPColor(name="Line", default=(1.0, 1.0, 1.0, 1.0)) separator = FVPColor(name="Separator", default=(1.0, 1.0, 1.0, 0.5)) pointer = FVPColor(name="Pointer", default=(1.0, 1.0, 1.0, 1.0)) pointer_outline = FVPColor(name="Pointer Outline", default=(0.0, 0.0, 0.0, 1.0)) pie_sel = FVPColor(name="Pie Sel", default=(1.0, 1.0, 1.0, 0.4)) menu_marker = FVPColor(name="Menu Marker", default=(1.0, 1.0, 1.0, 1.0)) menu_marker_outline = FVPColor(name="Menu Marker Outline", default=(0.0, 0.0, 0.0, 1.0)) item_highlight = FVPColor( name="Item Highlight", default=(1.0, 1.0, 1.0, 1.0), description="Item outline color", )
class Mafia4ds_GlobalMaterialProperties(types.PropertyGroup): UseDiffuseTex : props.BoolProperty (name = "Use Diffuse Tex", default = True) Coloring : props.BoolProperty (name = "Coloring", default = False) AmbientColor : props.FloatVectorProperty(name = "Ambient Color", default = (1.0, 1.0, 1.0), subtype = "COLOR", size = 3) DiffuseColor : props.FloatVectorProperty(name = "Diffuse Color", default = (1.0, 1.0, 1.0), subtype = "COLOR", size = 3) MipMapping : props.BoolProperty (name = "Mip Mapping", default = True) TwoSided : props.BoolProperty (name = "Two Sided", default = False) AddEffect : props.BoolProperty (name = "Add Effect", default = False) ColorKey : props.BoolProperty (name = "Color Key", default = False) AdditiveBlend : props.BoolProperty (name = "Additive Blend", default = False) UseAlphaTexture : props.BoolProperty (name = "Use Alpha Texture", default = False) AlphaTexture : props.StringProperty (name = "Alpha Texture", default = "", subtype = "FILE_PATH") UseEnvTexture : props.BoolProperty (name = "Use Env Texture", default = False) EnvDefaultMode : props.BoolProperty (name = "Env Default Mode", default = True) EnvMultiplyMode : props.BoolProperty (name = "Env Multiply Mode", default = False) EnvAdditiveMode : props.BoolProperty (name = "Env Additive Mode", default = False) EnvYAxisRefl : props.BoolProperty (name = "Env Y Axis Refl", default = True) EnvYAxisProj : props.BoolProperty (name = "Env Y Axis Proj", default = False) EnvZAxisProj : props.BoolProperty (name = "Env Z Axis Proj", default = False) EnvTexture : props.StringProperty (name = "Env Texture", default = "", subtype = "FILE_PATH") AnimatedDiffuse : props.BoolProperty (name = "Animated Diffuse", default = False) AnimatedAlpha : props.BoolProperty (name = "Animated Alpha", default = False) AnimatedFrames : props.IntProperty (name = "Animated Frames", default = 0) AnimFrameLength : props.IntProperty (name = "Anim Frame Length", default = 100)
class _PieMenuItem(ExecuteString): active = props.BoolProperty( name="Active", description="Activate or deactivate item", default=True, ) show_expanded = props.BoolProperty() type = props.EnumProperty( name="Type", items=[('OPERATOR', "Operator", ""), ('MENU', "Menu", ""), ('ADVANCED', "Advanced", ""), ('SPACER', "Spacer", "")], default='ADVANCED', ) poll_string = props.StringProperty( name="Poll", get=prop_poll_get, set=prop_poll_set, ) execute_string = props.StringProperty(name="Execute", ) # operator_arguments更新用 ensure_argument = props.StringProperty(get=prop_ensure_argument_get, ) operator = props.StringProperty(name="Operator", description="e.g. 'transform.translate'", get=prop_operator_get, set=prop_operator_set, update=prop_operator_update) # operator_arguments = props.CollectionProperty( # type=OperatorArgument) operator_arguments = [] # ↑継承で上書きする場合に問題が発生する label = props.StringProperty( name="Label", description="Item label", get=prop_label_get, set=prop_label_set, ) description = props.StringProperty( name="Description", get=prop_description_get, set=prop_description_set, ) icon = props.StringProperty(name="Icon", description="Item icon") menu = props.StringProperty(name="Menu", ) undo_push = props.BoolProperty(name="Undo Push", ) shortcut = props.StringProperty("Shortcut", ) translate = props.BoolProperty( name="Translate", default=True, ) # 描画時に使う enabled = props.BoolProperty() @property def icon_box_rect(self): return self.get("icon_box_rect", []) @icon_box_rect.setter def icon_box_rect(self, value): self["icon_box_rect"] = value @property def text_box_rect(self): return self.get("text_box_rect", []) @text_box_rect.setter def text_box_rect(self, value): self["text_box_rect"] = value def get_execute_string(self): if self.type == 'OPERATOR': if not verify_operator_string(self.operator): return "" arg_string_list = [] for arg in self.operator_arguments: if arg.name in arg: value = getattr(arg, arg.name) if isinstance(value, str): value = "'" + value + "'" else: value = str(value) arg_name = "".join(arg.name.split("."))[1:] arg_string_list.append(arg_name + "=" + value) text = self.operator + "(" + ", ".join(arg_string_list) + ")" return text elif self.type == 'ADVANCED': return self.execute_string else: return "" def draw_ui(self, context, layout, menu, index, sub_item_type=""): if self.show_expanded: main_layout = layout.box().column() else: main_layout = layout.column() main_layout.context_pointer_set("pie_menu_item", self) row = main_layout.row() pcol = custom_icons.preview_collections["main"] if not sub_item_type: icon = 'TRIA_DOWN' if self.show_expanded else 'TRIA_RIGHT' sub = row.row() sub.alignment = 'LEFT' sub.prop(self, "show_expanded", text="", icon=icon, emboss=False) sub.prop(self, "active", text="") # draw direction icon items = {} i = 0 for item in menu.menu_items: if item.active: items[item] = i i += 1 if i == 16: break if self not in items: icon = pcol["empty"] sub.label(text="", icon_value=icon.icon_id) else: num = len(items) if num <= 4: num = 4 names = list(range(0, 16, 4)) elif num <= 8: num = 8 names = list(range(0, 16, 2)) else: num = 16 names = list(range(0, 16, 1)) item_indices = menu.calc_item_indices(menu.item_order, num) name = str(names[item_indices.index(items[self])]) icon = pcol[name] sub.label(text="", icon_value=icon.icon_id) sp = row.split(0.2) if not self.active: sp.active = False sub1 = sp.row() sp_sub = sp.split(0.5) sub2 = sp_sub.row() sub3 = sp_sub.row(align=True) sub3_1 = sub3.row(align=True) sub3_1.alignment = 'LEFT' sub3_2 = sub3.row(align=True) sub3_3 = sub3.row(align=True) sub1.prop(self, "type", text="") if self.type != 'SPACER': draw_property(sub2, self, "label", "", unset=True, context_attr="pie_menu_item", active=True) if self.icon in all_icon_identifiers: icon_value = all_icon_identifiers[self.icon] elif self.icon in pcol: icon_value = pcol[self.icon].icon_id elif self.icon.endswith((".png", ".jpg")): try: preview = pcol.load(self.icon, self.icon, 'IMAGE') icon_value = preview.icon_id except: # no exception ? icon_value = pcol["empty"].icon_id sub3_2.alert = True else: if self.icon: sub3_2.alert = True icon_value = pcol["empty"].icon_id sub3_1.label(text="", icon_value=icon_value) sub3_2.prop(self, "icon", text="") sub3_3.operator(ops.WM_OT_pie_menu_item_icon_search.bl_idname, text="", icon='VIEWZOOM') op = sub3_3.operator( ops.WM_OT_pie_menu_item_icon_file_search.bl_idname, text="", icon='FILE_IMAGE') op.display_type = 'THUMBNAIL' # if self.icon and os.path.exists(self.icon): if self.icon: op.filepath = self.icon sub = row.row(align=True) sub.alignment = 'RIGHT' sub1 = sub.row(align=True) op = sub1.operator(ops.WM_OT_pie_menu_item_copy.bl_idname, text="", icon='COPYDOWN') sub2 = sub.row(align=True) op = sub2.operator(ops.WM_OT_pie_menu_item_paste.bl_idname, text="", icon='PASTEDOWN') if not sub_item_type: # sub = row.row(align=True) # sub.alignment = 'RIGHT' sub1 = sub.row(align=True) op = sub1.operator(ops.WM_OT_pie_menu_item_move.bl_idname, text="", icon='TRIA_UP') op.direction = -1 sub2 = sub.row(align=True) op = sub2.operator(ops.WM_OT_pie_menu_item_move.bl_idname, text="", icon='TRIA_DOWN') op.direction = 1 # sub = row.row(align=True) # sub.alignment = 'RIGHT' sub.operator(ops.WM_OT_pie_menu_item_remove.bl_idname, text="", icon='X') if not self.show_expanded: return column = main_layout.column() if self.type == 'SPACER': return elif self.type == 'MENU': column.prop(self, "menu") elif self.type == 'OPERATOR': _ = self.ensure_argument row = column.row() is_valid = verify_operator_string(self.operator) if self.operator != "": if not is_valid: row.alert = True sub = row.row(align=True) sub1 = sub.row(align=True) if self.operator and not oputils.get_operator_rna(self.operator): sub1.alert = True sub1.prop(self, "operator") # 重いのでコメントアウト # sub.operator(ops.WM_OT_pie_menu_item_operator_search.bl_idname, # text="", icon='VIEWZOOM') if is_valid and self.operator_arguments: box = column.box() flow = box.column_flow(2) for arg in self.operator_arguments: arg.draw_ui(context, flow) else: draw_property(column, self, "execute_string", "Execute", paste=True, context_attr="pie_menu_item") draw_property(column, self, "poll_string", "Poll", unset=True, paste=True, context_attr="pie_menu_item", active=True) draw_property(column, self, "description", unset=True, paste=True, context_attr="pie_menu_item", active=True) column.prop(self, "menu") column.prop(self, "undo_push") column.prop(self, "shortcut") # draw_property(column, self, "translate", unset=True, # context_attr="pie_menu_item") column.prop(self, "translate") for key in ["shift", "ctrl"]: if hasattr(self, key): sub_item = getattr(self, key) row = main_layout.row() icon = 'TRIA_DOWN' if sub_item.show_expanded else 'TRIA_RIGHT' sub = row.row() sub.alignment = 'LEFT' sub.prop(sub_item, "show_expanded", text="", icon=icon, emboss=False) sub.prop(sub_item, "active", text="") sub = row.row() if not sub_item.active: sub.active = False sub.label(key.title() + ":", translate=False) if sub_item.show_expanded: column = main_layout.column() col = indented_layout(column) sub_item.draw_ui(context, col, menu, index, sub_item_type=key) def poll(self, context, event=None): if self.poll_string: return bool(self.exec_string("poll_string", context, event)) else: return True def execute(self, context, event=None): if self.type == 'OPERATOR': text = self.get_execute_string() return self.exec_string_data(text, context, event) elif self.type == 'ADVANCED': return self.exec_string("execute_string", context, event) else: return None
class RF_OT_Reflow(bpy.types.Operator): bl_idname = "keys.reflow" bl_label = "Change fps for animations" bl_description = "Recalculate animations for a different fps" bl_options = {"REGISTER", "UNDO"} # Settings # ------------------------------------------------------------------------- fps_source = prop.IntProperty(name="Source FPS", min=1, default=24, description="Original FPS to convert from") fps_dest = prop.IntProperty(name="Destination FPS", min=1, default=60, description="Final FPS to convert to") do_actions = prop.BoolProperty( name="Change actions", description="Move keyframes in actions", default=True, ) do_nla = prop.BoolProperty( name="Fix NLA Tracks", description=("Change Start and End frames" " For NLA Tracks"), default=True, ) do_markers = prop.BoolProperty( name="Change Markers", description="Move markers' frames", default=True, ) do_markers_name = prop.BoolProperty( name="Change Marker Names", description=("Try to change markers" " default names"), default=True, ) do_fix_endframe = prop.BoolProperty( name="Change end frame", description=("Change scene's end" " end frame"), default=True, ) # Loop Methods # ------------------------------------------------------------------------- def keyframe_resample(self, curve): """ Resample every keyframe in a curve """ for keyframe in curve.keyframe_points: frame_original = keyframe.co[0] if frame_original != 0: keyframe.co[0] = frame_original // self.diff def fix_nla_length(self, track): """ Fix start and end frames for NLA tracks """ for strip in track.strips: strip.action_frame_start //= self.diff strip.action_frame_end //= self.diff # Main Methods # ------------------------------------------------------------------------- @classmethod def poll(cls, context): return len(bpy.data.actions) > 0 def invoke(self, context, event): """ Show settings dialog """ # Set default FPS from current FPS self.fps_source = context.scene.render.fps return context.window_manager.invoke_props_dialog(self) def draw(self, context): """ Draw settings dialog """ self.layout.separator() row = self.layout.row() row.prop(self, "fps_source") row.label("", icon="FORWARD") row.prop(self, "fps_dest") self.layout.separator() row = self.layout.row() row.label("Settings", icon="SCRIPTWIN") row = self.layout.row() row.prop(self, "do_nla") row = self.layout.row() row.prop(self, "do_actions") row = self.layout.row() row.prop(self, "do_markers") row = self.layout.row() row.prop(self, "do_markers_name") row = self.layout.row() row.prop(self, "do_fix_endframe") self.layout.separator() def execute(self, context): """ Resample animation data """ # Init # --------------------------------------------------------------------- render = context.scene.render actions = bpy.data.actions markers = context.scene.timeline_markers objects = bpy.data.objects self.diff = self.fps_source / self.fps_dest if self.diff == 1: self.report({"WARNING"}, "Source and Destination FPS are the same.") return {"CANCELLED"} # Set new FPS in scene properties render.fps = self.fps_dest # Fix endframe # --------------------------------------------------------------------- if self.do_fix_endframe: scene.frame_end = scene.frame_end // self.diff # Fix actions # --------------------------------------------------------------------- if self.do_actions: for action in actions: for curve in action.fcurves: self.keyframe_resample(curve) # Fix NLA tracks # --------------------------------------------------------------------- if self.do_nla: for obj in objects: if obj.animation_data and obj.animation_data.use_nla: for track in obj.animation_data.nla_tracks: self.fix_nla_length(track) # Fix Markers # --------------------------------------------------------------------- if self.do_markers: for mark in markers: if mark.frame != 0: new_frame = mark.frame // self.diff mark.frame = new_frame if self.do_markers_name: regex = re.match('^F_[0-9]*$', mark.name) if regex: mark.name = 'F_{0}'.format(new_frame) return {'FINISHED'}
class _PieMenu(ExecuteString): # {idname: index, ...} _last_item_index = {} idname = props.StringProperty(name="ID Name", get=prop_idname_get, set=prop_idname_set) active = props.BoolProperty(name="Active", description="Activate or deactivate menu", default=True) show_expanded = props.BoolProperty() poll_string = props.StringProperty( name="Poll", description="e.g.\nreturn context.mode == 'EDIT_MESH'", ) init_string = props.StringProperty(name="Init", ) label = props.StringProperty( name="Label", description="Menu title", ) draw_type = props.EnumProperty(name="Draw Type", items=[('SIMPLE', "Simple", ""), ('BOX', "Box", ""), ('CIRCLE', "Circle", "")], default='BOX', get=prop_draw_type_get, set=prop_draw_type_set) icon_scale = props.FloatProperty( name="Icon Scale", default=1.0, min=1.0, max=10.0, ) icon_expand = props.FloatProperty( name="Icon Expand", default=0.0, min=-1.0, max=1.0, ) radius = props.IntProperty(name="Radius", description="Pie menu size in pixels", min=0, default=0, get=prop_radius_get, set=prop_radius_set) quick_action = props.EnumProperty( name="Quick Action", items=[('NONE', "None", ""), ('LAST', "Last", ""), ('FIXED', "Fixed", "")], default='NONE', ) quick_action_index = props.IntProperty( name="Quick Action Index", description="", min=0, max=16, default=0, ) highlight = props.EnumProperty( name="Highlight", items=[('NONE', "None", ""), ('LAST', "Last", ""), ('FIXED', "Fixed", "")], default='NONE', ) highlight_index = props.IntProperty( name="Highlight Index", description="", min=0, max=16, default=0, ) translate = props.BoolProperty( name="Translate", default=True, ) items_num = props.EnumProperty( name="Number of Items", items=[('4', "4", ""), ('8', "8", ""), ('16', "16", "")], default='8', ) # menu_items = props.CollectionProperty( # name="Items", type=PieMenuItem) menu_items = [] # ↑継承で上書きする場合に問題が発生する item_order = props.EnumProperty( name="Item Order", items=[ ('CW', "Clockwise", "[0, 1, 2, 3, 4, 5, 6, 7]"), ('CW6', "Clockwise 6", "[4, 5, 6, 7, 0, 1, 2, 3] Start from six o'clock"), ('OFFICIAL', "Official", "[3, 5, 1, 7, 2, 6, 0, 4]"), ('MODIFIED', "Modified", "[3, 7, 1, 5, 2, 4, 0, 6]"), ], default='OFFICIAL', ) next = props.StringProperty( name="Next Menu", description="Shortcut: wheel down", ) prev = props.StringProperty( name="Previous Menu", description="Shortcut: wheel up", ) # 上書き radius_ = props.IntProperty() quick_action_index_ = props.IntProperty() highlight_index_ = props.IntProperty() # 描画時に使用 active_index = props.IntProperty(default=-1) active_item_index = props.IntProperty(default=-1) # -1: None is_valid_click = props.BoolProperty(default=True) co = props.FloatVectorProperty(subtype='XYZ', size=2) current_items_type = props.StringProperty( ) # "", "shift", "ctrl", "alt", "oskey" @property def item_boundary_angles(self): return self["item_boundary_angles"] @item_boundary_angles.setter def item_boundary_angles(self, value): self["item_boundary_angles"] = value @property def current_items(self): mod = self.current_items_type items = [] for item in self.menu_items: if item.active: if mod == "shift" and item.shift.active: items.append(item.shift) elif mod == "ctrl" and item.ctrl.active: items.append(item.ctrl) else: items.append(item) ls = [] for i in self["current_items_indices"]: if i == -1: ls.append(None) else: item = items[i] if item.type == 'SPACER': ls.append(None) else: ls.append(item) return ls def poll(self, context, event=None): if self.poll_string: return bool(self.exec_string("poll_string", context, event)) else: return True def init(self, context): if self.init_string: self.exec_string("init_string", context, None) @staticmethod def calc_item_indices(item_order, num): def sort_cw(): for n in (4, 8, 16): if num <= n: return list(range(num)) + [-1] * (n - num) def sort_cw6(): indices = sort_cw() n = int(len(indices) / 2) indices = indices[n:] + indices[:n] return indices def sort_official_modified(modified=False): if modified: if num <= 4: order = [3, 1, 2, 0] elif num <= 8: order = [3, 7, 1, 5, 2, 4, 0, 6] else: # if num <= 16: order = [ 3, 15, 7, 11, 1, 9, 5, 13, 2, 12, 4, 8, 0, 10, 6, 14 ] else: if num <= 4: order = [3, 1, 2, 0] elif num <= 8: order = [3, 5, 1, 7, 2, 6, 0, 4] else: # if num <= 16: order = [ 3, 15, 5, 11, 1, 9, 7, 13, 2, 12, 6, 8, 0, 10, 4, 14 ] indices = list(range(num)) + [-1] * (len(order) - num) return [indices[i] for i in order] if num > 16: raise ValueError() if item_order == 'CW': indices = sort_cw() elif item_order == 'CW6': indices = sort_cw6() elif item_order == 'OFFICIAL': indices = sort_official_modified() else: # elif self.item_order == 'MODIFIED': indices = sort_official_modified(True) return indices def update_current_items(self, context, op): mod = op.last_modifier() self.current_items_type = mod items = [] for item in self.menu_items: if item.active: if mod == "shift" and item.shift.active: items.append(item.shift) elif mod == "ctrl" and item.ctrl.active: items.append(item.ctrl) else: items.append(item) items = items[:16] num = len(items) indices = self.calc_item_indices(self.item_order, num) self["current_items_indices"] = indices # quick_action_index, highlight_index if num <= 4: n = 4 elif num <= 8: n = 8 else: # if num <= 16: n = 16 indices_ = self.calc_item_indices(self.item_order, n) for attr in ["quick_action_index", "highlight_index"]: index = getattr(self, attr) if 0 <= index < num: setattr(self, attr + "_", indices_.index(index)) # poll() for i in indices: if i != -1: item = items[i] item.enabled = item.poll(context) # calc boundaries num = len(indices) pie_angle = math.pi * 2 / num item_boundary_angles = [[0.0, 0.0] for i in range(num)] current_items = self.current_items for i, item in enumerate(current_items): if not item: continue angle = math.pi * 0.5 - pie_angle * i if angle < -1e-5: angle += math.pi * 2 # CCW side for k in range(1, num + 1): if current_items[i - k]: ang = angle + pie_angle * k * 0.5 item_boundary_angles[i][0] = ang break # CW side for k in range(1, num + 1): if current_items[(i + k) % num]: ang = angle - pie_angle * k * 0.5 item_boundary_angles[i][1] = ang break self.item_boundary_angles = item_boundary_angles def correct_radius(self): """Item同士が重ならないようにMenu半径を大きくする。 値は redius_ に格納する """ addon_prefs = pie_menu.addon_preferences radius = self.get("radius", addon_prefs.menu_radius) current_items = self.current_items if len(current_items) == 0: return pie_angle = math.pi * 2 / len(current_items) widget_unit = vawm.widget_unit() if self.draw_type == 'SIMPLE': n = len(current_items) / 4 r = widget_unit * (n - 0.5) + addon_prefs.item_min_space * n self.radius_ = max(r, radius) else: icon_box_size = widget_unit * self.icon_scale if self.draw_type == 'CIRCLE': # >>> (r + icon_size / 2) * math.sin(pie_angle / 2) = \ # (icon_size + item_min_space) / 2 r = (icon_box_size + addon_prefs.item_min_space) / 2 / \ math.sin(pie_angle / 2) - icon_box_size / 2 self.radius_ = max(r, radius) else: # 'BOX' # >>> (r + icon_size / 2) * math.sin(pie_angle) = \ # icon_size + item_min_space r = (icon_box_size + addon_prefs.item_min_space) / \ math.sin(pie_angle) - icon_box_size / 2 self.radius_ = max(r, radius) def calc_active(self, mco): """:rtype: (int, int)""" addon_prefs = pie_menu.addon_preferences current_items = self.current_items if not current_items: return -1, -1 vec = mco - self.co if vec.length < addon_prefs.menu_radius_center: active_index = -1 else: idx = 0 for i, item in enumerate(current_items): if not item: continue idx = i a1, a2 = self.item_boundary_angles[i] a1 += 1e-4 a2 -= 1e-4 v1 = (math.cos(a1), math.sin(a1)) v2 = (math.cos(a2), math.sin(a2)) if cross2d(v2, vec) >= 0 and cross2d(vec, v1) >= 0: active_index = i break else: active_index = idx active_item_index = -1 if active_index == -1: if self.quick_action == 'LAST': last_item_index = self.get_last_item_index() if 0 <= last_item_index < len(current_items): item = current_items[last_item_index] if item: active_item_index = last_item_index elif self.quick_action == 'FIXED': if 0 <= self.quick_action_index_ < len(current_items): item = current_items[self.quick_action_index_] if item: active_item_index = self.quick_action_index_ else: item = current_items[active_index] if item: active_item_index = active_index return active_index, active_item_index def update_active(self, mco, mco_press): """active_indexとactive_itemを更新。 """ self.active_index, self.active_item_index = self.calc_active(mco) if mco_press is not None: i, _ = self.calc_active(mco_press) self.is_valid_click = i == self.active_index else: self.is_valid_click = True def get_last_item_index(self): return self._last_item_index.get(self.idname, -1) def set_last_item_index(self, index): self._last_item_index[self.idname] = index def clear_last_item_idnex(self): if self.idname in self._last_item_index: del self._last_item_index[self.idname] def draw_ui(self, context, layout): if self.show_expanded: main_layout = layout.box().column() else: main_layout = layout.column() main_layout.context_pointer_set("pie_menu", self) row = main_layout.row() icon = 'TRIA_DOWN' if self.show_expanded else 'TRIA_RIGHT' sub = row.row() sub.alignment = 'LEFT' sub.prop(self, "show_expanded", text="", icon=icon, emboss=False) sub.prop(self, "active", text="") sub = row.row() if not self.active: sub.active = False sub.prop(self, "label", text="") sub2 = sub.row() """:type: bpy.types.UILayout""" if not self.idname: sub2.alert = True sub2.prop(self, "name", text="ID Name") sub = row.row(align=True) sub.alignment = 'RIGHT' sub1 = sub.row(align=True) op = sub1.operator(ops.WM_OT_pie_menu_menu_copy.bl_idname, text="", icon='COPYDOWN') sub2 = sub.row(align=True) op = sub2.operator(ops.WM_OT_pie_menu_menu_paste.bl_idname, text="", icon='PASTEDOWN') sub1 = sub.row(align=True) op = sub1.operator(ops.WM_OT_pie_menu_menu_move.bl_idname, text="", icon='TRIA_UP') op.direction = -1 sub2 = sub.row(align=True) op = sub2.operator(ops.WM_OT_pie_menu_menu_move.bl_idname, text="", icon='TRIA_DOWN') op.direction = 1 sub.operator(ops.WM_OT_pie_menu_menu_remove.bl_idname, text="", icon='X') if not self.show_expanded: return column = main_layout.column() row = column.row() split = row.split() sp_column1 = split.column() sp_column2 = split.column() draw_property(sp_column1, self, "draw_type", unset=True, context_attr="pie_menu") draw_property(sp_column1, self, "icon_scale") draw_property(sp_column1, self, "icon_expand") draw_property(sp_column1, self, "radius", unset=True, context_attr="pie_menu") draw_property(sp_column1, self, "translate") draw_property(sp_column1, self, "item_order") sp_column2.label("Quick Action:") draw_property(sp_column2, self, "quick_action", text="", context_attr="pie_menu") sub = sp_column2.row() if self.quick_action != 'FIXED': sub.active = False draw_property(sub, self, "quick_action_index", context_attr="pie_menu") sp_column2.label("Highlight:") draw_property(sp_column2, self, "highlight", text="", context_attr="pie_menu") sub = sp_column2.row() if self.highlight != 'FIXED': sub.active = False draw_property(sub, self, "highlight_index", context_attr="pie_menu") draw_separator(column) draw_property(column, self, "poll_string", "Poll Function", paste=True, context_attr="pie_menu") draw_property(column, self, "init_string", "Init Function", paste=True, context_attr="pie_menu") draw_separator(column) column = main_layout.column() for i, item in enumerate(self.menu_items): col = column.column() item.draw_ui(context, col, self, i) row = column.row() row.alignment = 'LEFT' op = row.operator(ops.WM_OT_pie_menu_item_add.bl_idname, text="Add Item", icon='ZOOMIN')
class PropCustomMotion(Property): """ PropCustomMotion: keep track of custom motion properties """ is_Enable = props.BoolProperty()