CM3D2 Converter.misc_INFO_MT_help
1# 画面上部 (「情報」エリア → ヘッダー) → ヘルプ 2import os 3import re 4import sys 5import urllib.request 6import zipfile 7import subprocess 8import datetime 9import xml.sax.saxutils 10import addon_utils 11import bpy 12import traceback 13from . import common 14from . import compat 15from .translations.pgettext_functions import * 16 17 18# メニュー等に項目追加 19def menu_func(self, context): 20 icon_id = common.kiss_icon() 21 self.layout.separator() 22 self.layout.operator('script.update_cm3d2_converter', icon_value=icon_id) 23 self.layout.operator('wm.call_menu', icon_value=icon_id, text="CM3D2 Converterの更新履歴").name = 'INFO_MT_help_CM3D2_Converter_RSS' 24 self.layout.operator('wm.show_cm3d2_converter_preference', icon_value=icon_id) 25 26 27# 更新履歴メニュー 28@compat.BlRegister() 29class INFO_MT_help_CM3D2_Converter_RSS(bpy.types.Menu): 30 bl_idname = 'INFO_MT_help_CM3D2_Converter_RSS' 31 bl_label = "CM3D2 Converterの更新履歴" 32 33 def draw(self, context): 34 try: 35 response = urllib.request.urlopen(common.URL_ATOM.format(branch=common.BRANCH)) 36 html = response.read().decode('utf-8') 37 titles = re.findall(r'\<title\>[ \s]*([^ \s][^\<]*[^ \s])[ \s]*\<\/title\>', html)[1:] # matches: <title> something </title> 38 updates = re.findall(r'\<updated\>([^\<\>]*)\<\/updated\>', html)[1:] 39 links = re.findall(r'<link [^\<\>]*href="([^"]+)"/>', html)[2:] 40 #version_datetime = datetime.datetime.strptime(str(common.bl_info["version"][0]) + "," + str(common.bl_info["version"][1]) + "," + str(common.bl_info["version"][2]) + "," + str(common.bl_info["version"][3]) + "," + str(common.bl_info["version"][4]) + "," + str(common.bl_info["version"][5]), '%Y,%m,{},%H,%M,{}') 41 numbers_in_version = 0 42 sub_version = None 43 year = 2000 44 month = 1 45 day = 1 46 hour = 0 47 minute = 0 48 second = 0 49 ms = 0 50 for version_sub_value in common.bl_info["version"]: 51 number = None 52 if type(version_sub_value) is int: 53 number = version_sub_value 54 elif type(version_sub_value) is float: 55 number = version_sub_value 56 elif type(version_sub_value) is str: 57 match = re.match(r'(\d+)\.?(.*)', version_sub_value) 58 if match: 59 number = int(match.group(1)) 60 sub_str = match.group(2) 61 if sub_str: 62 sub_version = sum( ord(char) << 8*(len(sub_str)-byte-1) for byte, char in enumerate(sub_str) ) 63 if number: 64 if numbers_in_version == 0: 65 year = number 66 elif numbers_in_version == 1: 67 month = number 68 elif numbers_in_version == 2: 69 day = number 70 elif numbers_in_version == 3: 71 hour = number 72 elif numbers_in_version == 4: 73 minute = number 74 elif numbers_in_version == 5: 75 second = number 76 numbers_in_version += 1 77 78 version_datetime = datetime.datetime(year, month, day, hour, minute, second, ms) 79 80 81 output_data = [] 82 update_diffs = [] 83 for title, update, link in zip(titles, updates, links): 84 title = xml.sax.saxutils.unescape(title, {'"': '"'}) 85 86 rss_datetime = datetime.datetime.strptime(update, '%Y-%m-%dT%H:%M:%SZ') + datetime.timedelta(hours=9) 87 diff_seconds = datetime.datetime.now() - rss_datetime 88 icon = 'SORTTIME' 89 if 60 * 60 * 24 * 7 < diff_seconds.total_seconds(): 90 icon = 'NLA' 91 elif 60 * 60 * 24 * 3 < diff_seconds.total_seconds(): 92 icon = 'COLLAPSEMENU' 93 elif 60 * 60 * 24 < diff_seconds.total_seconds(): 94 icon = 'TIME' 95 elif 60 * 60 < diff_seconds.total_seconds(): 96 icon = 'RECOVER_LAST' 97 else: 98 icon = 'PREVIEW_RANGE' 99 100 if 60 * 60 * 24 <= diff_seconds.total_seconds(): 101 date_str = f_iface_("{}日前", int(diff_seconds.total_seconds() / 60 / 60 / 24)) 102 elif 60 * 60 <= diff_seconds.total_seconds(): 103 date_str = f_iface_("{}時間前", int(diff_seconds.total_seconds() / 60 / 60)) 104 elif 60 <= diff_seconds.total_seconds(): 105 date_str = f_iface_("{}分前", int(diff_seconds.total_seconds() / 60)) 106 else: 107 date_str = f_iface_("{}秒前", diff_seconds.total_seconds()) 108 109 text = "(" + date_str + ") " + title 110 111 update_diff = abs((version_datetime - rss_datetime).total_seconds()) 112 113 output_data.append((text, icon, link, update_diff)) 114 update_diffs.append(update_diff) 115 116 min_update_diff = sorted(update_diffs)[0] 117 for text, icon, link, update_diff in output_data: 118 119 if update_diff == min_update_diff: 120 if update_diff < 30: 121 text = "Now! " + text 122 icon = 'QUESTION' 123 124 self.layout.operator('wm.url_open', text=text, icon=icon).url = link 125 except: 126 traceback.print_exc() 127 self.layout.label(text="更新の取得に失敗しました", icon='ERROR') 128 129 130@compat.BlRegister() 131class CNV_OT_update_cm3d2_converter(bpy.types.Operator): 132 bl_idname = 'script.update_cm3d2_converter' 133 bl_label = "CM3D2 Converterを更新「luv」バージョン" 134 bl_description = "GitHubから最新版のCM3D2 Converterアドオンをダウンロードし上書き更新します" 135 bl_options = {'REGISTER'} 136 137 is_restart = bpy.props.BoolProperty(name="更新後にBlenderを再起動", default=compat.IS_LEGACY) 138 is_toggle_console = bpy.props.BoolProperty(name="再起動後にコンソールを閉じる", default=True) 139 140 items = [ 141 ('current', f_iface_("Current ({branch})", branch=common.BRANCH), ""), 142 ('bl_28' , "bl_28", ""), 143 ('testing', "testing", ""), 144 ] 145 branch = bpy.props.EnumProperty(items=items, name="Branch", default='current') 146 147 def invoke(self, context, event): 148 return context.window_manager.invoke_props_dialog(self) 149 150 def draw(self, context): 151 layout = self.layout 152 layout.menu('INFO_MT_help_CM3D2_Converter_RSS', icon='INFO') 153 layout.separator() 154 layout.prop(self, 'branch') 155 col = layout.column() 156 col.prop(self, 'is_restart', icon='BLENDER') 157 row = col.row() 158 row.prop(self, 'is_toggle_console', icon='CONSOLE') 159 row.enabled = self.is_restart 160 161 def execute(self, context): 162 branch = self.branch 163 if branch == 'current': 164 branch = common.BRANCH 165 zip_path = os.path.join(bpy.app.tempdir, f"Blender-CM3D2-Converter-{branch}.zip") 166 addon_path = os.path.dirname(__file__) 167 168 response = urllib.request.urlopen(common.URL_MODULE.format(branch=branch)) 169 zip_file = open(zip_path, 'wb') 170 zip_file.write(response.read()) 171 zip_file.close() 172 173 zip_file = zipfile.ZipFile(zip_path, 'r') 174 sub_dir = "" 175 for path in zip_file.namelist(): 176 if not sub_dir and os.path.split(os.path.split(path)[0])[1] == "CM3D2 Converter": 177 sub_dir = path 178 continue 179 if not sub_dir or sub_dir not in path: 180 continue 181 relative_path = os.path.relpath(path, start=sub_dir) 182 real_path = os.path.join(addon_path, relative_path) 183 # If it is a file 184 if os.path.basename(path): # is a file 185 file = open(real_path, 'wb') # open() will automatically create it if it does not exist 186 file.write(zip_file.read(path)) 187 file.close() 188 # If it is a missing directory 189 elif not os.path.exists(real_path): 190 os.mkdir(real_path) 191 192 zip_file.close() 193 return {'CANCELLED'} 194 195 if self.is_restart: 196 filepath = bpy.data.filepath 197 command_line = [sys.argv[0]] 198 if filepath: 199 command_line.append(filepath) 200 if self.is_toggle_console: 201 py = os.path.join(os.path.dirname(__file__), "console_toggle.py") 202 command_line.append('-P') 203 command_line.append(py) 204 205 subprocess.Popen(command_line) 206 bpy.ops.wm.quit_blender() 207 else: 208 if compat.IS_LEGACY: 209 self.report(type={'INFO'}, message="Blender-CM3D2-Converterを更新しました、再起動して下さい") 210 else: 211 bpy.ops.scripts.reload() 212 self.report(type={'INFO'}, message="Blender-CM3D2-Converter updated") 213 return {'FINISHED'} 214 215 216@compat.BlRegister() 217class CNV_OT_show_cm3d2_converter_preference(bpy.types.Operator): 218 bl_idname = 'wm.show_cm3d2_converter_preference' 219 bl_label = "CM3D2 Converterの設定画面を開く" 220 bl_description = "CM3D2 Converterアドオンの設定画面を表示します" 221 bl_options = {'REGISTER', 'UNDO'} 222 223 def execute(self, context): 224 my_info = None 225 for module in addon_utils.modules(): 226 info = addon_utils.module_bl_info(module) 227 if info['name'] == common.ADDON_NAME: 228 my_info = info 229 break 230 area = common.get_request_area(context, compat.pref_type()) 231 if area and my_info: 232 compat.get_prefs(context).active_section = 'ADDONS' 233 context.window_manager.addon_search = my_info['name'] 234 context.window_manager.addon_filter = 'All' 235 if 'COMMUNITY' not in context.window_manager.addon_support: 236 context.window_manager.addon_support = {'OFFICIAL', 'COMMUNITY'} 237 if not my_info['show_expanded']: 238 if compat.IS_LEGACY: 239 bpy.ops.wm.addon_expand(module=__package__) 240 else: 241 bpy.ops.preferences.addon_expand(module=__package__) 242 else: 243 self.report(type={'ERROR'}, message="表示できるエリアが見つかりませんでした") 244 return {'CANCELLED'} 245 return {'FINISHED'}
@compat.BlRegister()
class
INFO_MT_help_CM3D2_Converter_RSS29@compat.BlRegister() 30class INFO_MT_help_CM3D2_Converter_RSS(bpy.types.Menu): 31 bl_idname = 'INFO_MT_help_CM3D2_Converter_RSS' 32 bl_label = "CM3D2 Converterの更新履歴" 33 34 def draw(self, context): 35 try: 36 response = urllib.request.urlopen(common.URL_ATOM.format(branch=common.BRANCH)) 37 html = response.read().decode('utf-8') 38 titles = re.findall(r'\<title\>[ \s]*([^ \s][^\<]*[^ \s])[ \s]*\<\/title\>', html)[1:] # matches: <title> something </title> 39 updates = re.findall(r'\<updated\>([^\<\>]*)\<\/updated\>', html)[1:] 40 links = re.findall(r'<link [^\<\>]*href="([^"]+)"/>', html)[2:] 41 #version_datetime = datetime.datetime.strptime(str(common.bl_info["version"][0]) + "," + str(common.bl_info["version"][1]) + "," + str(common.bl_info["version"][2]) + "," + str(common.bl_info["version"][3]) + "," + str(common.bl_info["version"][4]) + "," + str(common.bl_info["version"][5]), '%Y,%m,{},%H,%M,{}') 42 numbers_in_version = 0 43 sub_version = None 44 year = 2000 45 month = 1 46 day = 1 47 hour = 0 48 minute = 0 49 second = 0 50 ms = 0 51 for version_sub_value in common.bl_info["version"]: 52 number = None 53 if type(version_sub_value) is int: 54 number = version_sub_value 55 elif type(version_sub_value) is float: 56 number = version_sub_value 57 elif type(version_sub_value) is str: 58 match = re.match(r'(\d+)\.?(.*)', version_sub_value) 59 if match: 60 number = int(match.group(1)) 61 sub_str = match.group(2) 62 if sub_str: 63 sub_version = sum( ord(char) << 8*(len(sub_str)-byte-1) for byte, char in enumerate(sub_str) ) 64 if number: 65 if numbers_in_version == 0: 66 year = number 67 elif numbers_in_version == 1: 68 month = number 69 elif numbers_in_version == 2: 70 day = number 71 elif numbers_in_version == 3: 72 hour = number 73 elif numbers_in_version == 4: 74 minute = number 75 elif numbers_in_version == 5: 76 second = number 77 numbers_in_version += 1 78 79 version_datetime = datetime.datetime(year, month, day, hour, minute, second, ms) 80 81 82 output_data = [] 83 update_diffs = [] 84 for title, update, link in zip(titles, updates, links): 85 title = xml.sax.saxutils.unescape(title, {'"': '"'}) 86 87 rss_datetime = datetime.datetime.strptime(update, '%Y-%m-%dT%H:%M:%SZ') + datetime.timedelta(hours=9) 88 diff_seconds = datetime.datetime.now() - rss_datetime 89 icon = 'SORTTIME' 90 if 60 * 60 * 24 * 7 < diff_seconds.total_seconds(): 91 icon = 'NLA' 92 elif 60 * 60 * 24 * 3 < diff_seconds.total_seconds(): 93 icon = 'COLLAPSEMENU' 94 elif 60 * 60 * 24 < diff_seconds.total_seconds(): 95 icon = 'TIME' 96 elif 60 * 60 < diff_seconds.total_seconds(): 97 icon = 'RECOVER_LAST' 98 else: 99 icon = 'PREVIEW_RANGE' 100 101 if 60 * 60 * 24 <= diff_seconds.total_seconds(): 102 date_str = f_iface_("{}日前", int(diff_seconds.total_seconds() / 60 / 60 / 24)) 103 elif 60 * 60 <= diff_seconds.total_seconds(): 104 date_str = f_iface_("{}時間前", int(diff_seconds.total_seconds() / 60 / 60)) 105 elif 60 <= diff_seconds.total_seconds(): 106 date_str = f_iface_("{}分前", int(diff_seconds.total_seconds() / 60)) 107 else: 108 date_str = f_iface_("{}秒前", diff_seconds.total_seconds()) 109 110 text = "(" + date_str + ") " + title 111 112 update_diff = abs((version_datetime - rss_datetime).total_seconds()) 113 114 output_data.append((text, icon, link, update_diff)) 115 update_diffs.append(update_diff) 116 117 min_update_diff = sorted(update_diffs)[0] 118 for text, icon, link, update_diff in output_data: 119 120 if update_diff == min_update_diff: 121 if update_diff < 30: 122 text = "Now! " + text 123 icon = 'QUESTION' 124 125 self.layout.operator('wm.url_open', text=text, icon=icon).url = link 126 except: 127 traceback.print_exc() 128 self.layout.label(text="更新の取得に失敗しました", icon='ERROR')
def
draw(self, context):
34 def draw(self, context): 35 try: 36 response = urllib.request.urlopen(common.URL_ATOM.format(branch=common.BRANCH)) 37 html = response.read().decode('utf-8') 38 titles = re.findall(r'\<title\>[ \s]*([^ \s][^\<]*[^ \s])[ \s]*\<\/title\>', html)[1:] # matches: <title> something </title> 39 updates = re.findall(r'\<updated\>([^\<\>]*)\<\/updated\>', html)[1:] 40 links = re.findall(r'<link [^\<\>]*href="([^"]+)"/>', html)[2:] 41 #version_datetime = datetime.datetime.strptime(str(common.bl_info["version"][0]) + "," + str(common.bl_info["version"][1]) + "," + str(common.bl_info["version"][2]) + "," + str(common.bl_info["version"][3]) + "," + str(common.bl_info["version"][4]) + "," + str(common.bl_info["version"][5]), '%Y,%m,{},%H,%M,{}') 42 numbers_in_version = 0 43 sub_version = None 44 year = 2000 45 month = 1 46 day = 1 47 hour = 0 48 minute = 0 49 second = 0 50 ms = 0 51 for version_sub_value in common.bl_info["version"]: 52 number = None 53 if type(version_sub_value) is int: 54 number = version_sub_value 55 elif type(version_sub_value) is float: 56 number = version_sub_value 57 elif type(version_sub_value) is str: 58 match = re.match(r'(\d+)\.?(.*)', version_sub_value) 59 if match: 60 number = int(match.group(1)) 61 sub_str = match.group(2) 62 if sub_str: 63 sub_version = sum( ord(char) << 8*(len(sub_str)-byte-1) for byte, char in enumerate(sub_str) ) 64 if number: 65 if numbers_in_version == 0: 66 year = number 67 elif numbers_in_version == 1: 68 month = number 69 elif numbers_in_version == 2: 70 day = number 71 elif numbers_in_version == 3: 72 hour = number 73 elif numbers_in_version == 4: 74 minute = number 75 elif numbers_in_version == 5: 76 second = number 77 numbers_in_version += 1 78 79 version_datetime = datetime.datetime(year, month, day, hour, minute, second, ms) 80 81 82 output_data = [] 83 update_diffs = [] 84 for title, update, link in zip(titles, updates, links): 85 title = xml.sax.saxutils.unescape(title, {'"': '"'}) 86 87 rss_datetime = datetime.datetime.strptime(update, '%Y-%m-%dT%H:%M:%SZ') + datetime.timedelta(hours=9) 88 diff_seconds = datetime.datetime.now() - rss_datetime 89 icon = 'SORTTIME' 90 if 60 * 60 * 24 * 7 < diff_seconds.total_seconds(): 91 icon = 'NLA' 92 elif 60 * 60 * 24 * 3 < diff_seconds.total_seconds(): 93 icon = 'COLLAPSEMENU' 94 elif 60 * 60 * 24 < diff_seconds.total_seconds(): 95 icon = 'TIME' 96 elif 60 * 60 < diff_seconds.total_seconds(): 97 icon = 'RECOVER_LAST' 98 else: 99 icon = 'PREVIEW_RANGE' 100 101 if 60 * 60 * 24 <= diff_seconds.total_seconds(): 102 date_str = f_iface_("{}日前", int(diff_seconds.total_seconds() / 60 / 60 / 24)) 103 elif 60 * 60 <= diff_seconds.total_seconds(): 104 date_str = f_iface_("{}時間前", int(diff_seconds.total_seconds() / 60 / 60)) 105 elif 60 <= diff_seconds.total_seconds(): 106 date_str = f_iface_("{}分前", int(diff_seconds.total_seconds() / 60)) 107 else: 108 date_str = f_iface_("{}秒前", diff_seconds.total_seconds()) 109 110 text = "(" + date_str + ") " + title 111 112 update_diff = abs((version_datetime - rss_datetime).total_seconds()) 113 114 output_data.append((text, icon, link, update_diff)) 115 update_diffs.append(update_diff) 116 117 min_update_diff = sorted(update_diffs)[0] 118 for text, icon, link, update_diff in output_data: 119 120 if update_diff == min_update_diff: 121 if update_diff < 30: 122 text = "Now! " + text 123 icon = 'QUESTION' 124 125 self.layout.operator('wm.url_open', text=text, icon=icon).url = link 126 except: 127 traceback.print_exc() 128 self.layout.label(text="更新の取得に失敗しました", icon='ERROR')
Inherited Members
- bpy_types.Menu
- draw_preset
- draw_collapsible
- 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_readonly
- is_property_overridable_library
- property_overridable_library_set
- path_resolve
- path_from_id
- type_recast
- bl_rna_get_subclass_py
- bl_rna_get_subclass
- id_properties_ensure
- id_properties_clear
- id_properties_ui
- id_data
@compat.BlRegister()
class
CNV_OT_update_cm3d2_converter131@compat.BlRegister() 132class CNV_OT_update_cm3d2_converter(bpy.types.Operator): 133 bl_idname = 'script.update_cm3d2_converter' 134 bl_label = "CM3D2 Converterを更新「luv」バージョン" 135 bl_description = "GitHubから最新版のCM3D2 Converterアドオンをダウンロードし上書き更新します" 136 bl_options = {'REGISTER'} 137 138 is_restart = bpy.props.BoolProperty(name="更新後にBlenderを再起動", default=compat.IS_LEGACY) 139 is_toggle_console = bpy.props.BoolProperty(name="再起動後にコンソールを閉じる", default=True) 140 141 items = [ 142 ('current', f_iface_("Current ({branch})", branch=common.BRANCH), ""), 143 ('bl_28' , "bl_28", ""), 144 ('testing', "testing", ""), 145 ] 146 branch = bpy.props.EnumProperty(items=items, name="Branch", default='current') 147 148 def invoke(self, context, event): 149 return context.window_manager.invoke_props_dialog(self) 150 151 def draw(self, context): 152 layout = self.layout 153 layout.menu('INFO_MT_help_CM3D2_Converter_RSS', icon='INFO') 154 layout.separator() 155 layout.prop(self, 'branch') 156 col = layout.column() 157 col.prop(self, 'is_restart', icon='BLENDER') 158 row = col.row() 159 row.prop(self, 'is_toggle_console', icon='CONSOLE') 160 row.enabled = self.is_restart 161 162 def execute(self, context): 163 branch = self.branch 164 if branch == 'current': 165 branch = common.BRANCH 166 zip_path = os.path.join(bpy.app.tempdir, f"Blender-CM3D2-Converter-{branch}.zip") 167 addon_path = os.path.dirname(__file__) 168 169 response = urllib.request.urlopen(common.URL_MODULE.format(branch=branch)) 170 zip_file = open(zip_path, 'wb') 171 zip_file.write(response.read()) 172 zip_file.close() 173 174 zip_file = zipfile.ZipFile(zip_path, 'r') 175 sub_dir = "" 176 for path in zip_file.namelist(): 177 if not sub_dir and os.path.split(os.path.split(path)[0])[1] == "CM3D2 Converter": 178 sub_dir = path 179 continue 180 if not sub_dir or sub_dir not in path: 181 continue 182 relative_path = os.path.relpath(path, start=sub_dir) 183 real_path = os.path.join(addon_path, relative_path) 184 # If it is a file 185 if os.path.basename(path): # is a file 186 file = open(real_path, 'wb') # open() will automatically create it if it does not exist 187 file.write(zip_file.read(path)) 188 file.close() 189 # If it is a missing directory 190 elif not os.path.exists(real_path): 191 os.mkdir(real_path) 192 193 zip_file.close() 194 return {'CANCELLED'} 195 196 if self.is_restart: 197 filepath = bpy.data.filepath 198 command_line = [sys.argv[0]] 199 if filepath: 200 command_line.append(filepath) 201 if self.is_toggle_console: 202 py = os.path.join(os.path.dirname(__file__), "console_toggle.py") 203 command_line.append('-P') 204 command_line.append(py) 205 206 subprocess.Popen(command_line) 207 bpy.ops.wm.quit_blender() 208 else: 209 if compat.IS_LEGACY: 210 self.report(type={'INFO'}, message="Blender-CM3D2-Converterを更新しました、再起動して下さい") 211 else: 212 bpy.ops.scripts.reload() 213 self.report(type={'INFO'}, message="Blender-CM3D2-Converter updated") 214 return {'FINISHED'}
is_restart: <_PropertyDeferred, <built-in function BoolProperty>, {'name': '更新後にBlenderを再起動', 'default': False, 'attr': 'is_restart'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': '更新後にBlenderを再起動', 'default': False, 'attr': 'is_restart'}>
is_toggle_console: <_PropertyDeferred, <built-in function BoolProperty>, {'name': '再起動後にコンソールを閉じる', 'default': True, 'attr': 'is_toggle_console'}> =
<_PropertyDeferred, <built-in function BoolProperty>, {'name': '再起動後にコンソールを閉じる', 'default': True, 'attr': 'is_toggle_console'}>
branch: <_PropertyDeferred, <built-in function EnumProperty>, {'items': [('current', 'Current (bl_28)', ''), ('bl_28', 'bl_28', ''), ('testing', 'testing', '')], 'name': 'Branch', 'default': 'current', 'attr': 'branch'}> =
<_PropertyDeferred, <built-in function EnumProperty>, {'items': [('current', 'Current (bl_28)', ''), ('bl_28', 'bl_28', ''), ('testing', 'testing', '')], 'name': 'Branch', 'default': 'current', 'attr': 'branch'}>
def
draw(self, context):
151 def draw(self, context): 152 layout = self.layout 153 layout.menu('INFO_MT_help_CM3D2_Converter_RSS', icon='INFO') 154 layout.separator() 155 layout.prop(self, 'branch') 156 col = layout.column() 157 col.prop(self, 'is_restart', icon='BLENDER') 158 row = col.row() 159 row.prop(self, 'is_toggle_console', icon='CONSOLE') 160 row.enabled = self.is_restart
def
execute(self, context):
162 def execute(self, context): 163 branch = self.branch 164 if branch == 'current': 165 branch = common.BRANCH 166 zip_path = os.path.join(bpy.app.tempdir, f"Blender-CM3D2-Converter-{branch}.zip") 167 addon_path = os.path.dirname(__file__) 168 169 response = urllib.request.urlopen(common.URL_MODULE.format(branch=branch)) 170 zip_file = open(zip_path, 'wb') 171 zip_file.write(response.read()) 172 zip_file.close() 173 174 zip_file = zipfile.ZipFile(zip_path, 'r') 175 sub_dir = "" 176 for path in zip_file.namelist(): 177 if not sub_dir and os.path.split(os.path.split(path)[0])[1] == "CM3D2 Converter": 178 sub_dir = path 179 continue 180 if not sub_dir or sub_dir not in path: 181 continue 182 relative_path = os.path.relpath(path, start=sub_dir) 183 real_path = os.path.join(addon_path, relative_path) 184 # If it is a file 185 if os.path.basename(path): # is a file 186 file = open(real_path, 'wb') # open() will automatically create it if it does not exist 187 file.write(zip_file.read(path)) 188 file.close() 189 # If it is a missing directory 190 elif not os.path.exists(real_path): 191 os.mkdir(real_path) 192 193 zip_file.close() 194 return {'CANCELLED'} 195 196 if self.is_restart: 197 filepath = bpy.data.filepath 198 command_line = [sys.argv[0]] 199 if filepath: 200 command_line.append(filepath) 201 if self.is_toggle_console: 202 py = os.path.join(os.path.dirname(__file__), "console_toggle.py") 203 command_line.append('-P') 204 command_line.append(py) 205 206 subprocess.Popen(command_line) 207 bpy.ops.wm.quit_blender() 208 else: 209 if compat.IS_LEGACY: 210 self.report(type={'INFO'}, message="Blender-CM3D2-Converterを更新しました、再起動して下さい") 211 else: 212 bpy.ops.scripts.reload() 213 self.report(type={'INFO'}, message="Blender-CM3D2-Converter updated") 214 return {'FINISHED'}
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_readonly
- is_property_overridable_library
- property_overridable_library_set
- path_resolve
- path_from_id
- type_recast
- bl_rna_get_subclass_py
- bl_rna_get_subclass
- id_properties_ensure
- id_properties_clear
- id_properties_ui
- id_data
@compat.BlRegister()
class
CNV_OT_show_cm3d2_converter_preference217@compat.BlRegister() 218class CNV_OT_show_cm3d2_converter_preference(bpy.types.Operator): 219 bl_idname = 'wm.show_cm3d2_converter_preference' 220 bl_label = "CM3D2 Converterの設定画面を開く" 221 bl_description = "CM3D2 Converterアドオンの設定画面を表示します" 222 bl_options = {'REGISTER', 'UNDO'} 223 224 def execute(self, context): 225 my_info = None 226 for module in addon_utils.modules(): 227 info = addon_utils.module_bl_info(module) 228 if info['name'] == common.ADDON_NAME: 229 my_info = info 230 break 231 area = common.get_request_area(context, compat.pref_type()) 232 if area and my_info: 233 compat.get_prefs(context).active_section = 'ADDONS' 234 context.window_manager.addon_search = my_info['name'] 235 context.window_manager.addon_filter = 'All' 236 if 'COMMUNITY' not in context.window_manager.addon_support: 237 context.window_manager.addon_support = {'OFFICIAL', 'COMMUNITY'} 238 if not my_info['show_expanded']: 239 if compat.IS_LEGACY: 240 bpy.ops.wm.addon_expand(module=__package__) 241 else: 242 bpy.ops.preferences.addon_expand(module=__package__) 243 else: 244 self.report(type={'ERROR'}, message="表示できるエリアが見つかりませんでした") 245 return {'CANCELLED'} 246 return {'FINISHED'}
def
execute(self, context):
224 def execute(self, context): 225 my_info = None 226 for module in addon_utils.modules(): 227 info = addon_utils.module_bl_info(module) 228 if info['name'] == common.ADDON_NAME: 229 my_info = info 230 break 231 area = common.get_request_area(context, compat.pref_type()) 232 if area and my_info: 233 compat.get_prefs(context).active_section = 'ADDONS' 234 context.window_manager.addon_search = my_info['name'] 235 context.window_manager.addon_filter = 'All' 236 if 'COMMUNITY' not in context.window_manager.addon_support: 237 context.window_manager.addon_support = {'OFFICIAL', 'COMMUNITY'} 238 if not my_info['show_expanded']: 239 if compat.IS_LEGACY: 240 bpy.ops.wm.addon_expand(module=__package__) 241 else: 242 bpy.ops.preferences.addon_expand(module=__package__) 243 else: 244 self.report(type={'ERROR'}, message="表示できるエリアが見つかりませんでした") 245 return {'CANCELLED'} 246 return {'FINISHED'}
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_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