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, {'&quot;': '"'})
 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_RSS(bpy_types.Menu):
 29@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, {'&quot;': '"'})
 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')
bl_idname = 'INFO_MT_help_CM3D2_Converter_RSS'
bl_label = 'CM3D2 Converterの更新履歴'
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, {'&quot;': '"'})
 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')
bl_rna = <bpy_struct, Struct("INFO_MT_help_CM3D2_Converter_RSS")>
Inherited Members
bpy_types.Menu
path_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_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 CNV_OT_update_cm3d2_converter(bpy_types.Operator):
131@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'}
bl_idname = 'script.update_cm3d2_converter'
bl_label = 'CM3D2 Converterを更新「luv」バージョン'
bl_description = 'GitHubから最新版のCM3D2 Converterアドオンをダウンロードし上書き更新します'
bl_options = {'REGISTER'}
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'}>
items = [('current', 'Current (bl_28)', ''), ('bl_28', 'bl_28', ''), ('testing', 'testing', '')]
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 invoke(self, context, event):
148    def invoke(self, context, event):
149        return context.window_manager.invoke_props_dialog(self)
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'}
bl_rna = <bpy_struct, Struct("SCRIPT_OT_update_cm3d2_converter")>
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 CNV_OT_show_cm3d2_converter_preference(bpy_types.Operator):
217@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'}
bl_idname = 'wm.show_cm3d2_converter_preference'
bl_label = 'CM3D2 Converterの設定画面を開く'
bl_description = 'CM3D2 Converterアドオンの設定画面を表示します'
bl_options = {'REGISTER', 'UNDO'}
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'}
bl_rna = <bpy_struct, Struct("WM_OT_show_cm3d2_converter_preference")>
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