7 from pathlib
import Path
9 def unzip(zip_path
, extract_dir_path
):
10 '''Get a zip path and a directory path to extract to'''
11 with zipfile
.ZipFile(zip_path
, 'r') as zip_ref
:
12 zip_ref
.extractall(extract_dir_path
)
14 def simple_dl_url(url
, dest
, fallback_url
=None):
15 ## need to import urlib.request or linux module does not found 'request' using urllib directly
16 ## need to create an SSl context or linux fail returning unverified ssl
17 # ssl._create_default_https_context = ssl._create_unverified_context
20 urllib
.request
.urlretrieve(url
, dest
)
21 except Exception as e
:
22 print('Error trying to download\n', e
)
24 print('\nDownload page for manual install:', fallback_url
)
27 def download_url(url
, dest
):
28 '''download passed url to dest file (include filename)'''
31 ssl
._create
_default
_https
_context
= ssl
._create
_unverified
_context
32 start_time
= time
.time()
35 with urllib
.request
.urlopen(url
) as response
, open(dest
, 'wb') as out_file
:
36 shutil
.copyfileobj(response
, out_file
)
37 except Exception as e
:
38 print('Error trying to download\n', e
)
41 print(f
"Download time {time.time() - start_time:.2f}s",)
44 def get_brushes(blend_fp
):
45 cur_brushes
= [b
.name
for b
in bpy
.data
.brushes
]
46 with bpy
.data
.libraries
.load(str(blend_fp
), link
=False) as (data_from
, data_to
):
47 # load brushes starting with 'tex' prefix if there are not already there
48 data_to
.brushes
= [b
for b
in data_from
.brushes
if b
.startswith('tex_') and not b
in cur_brushes
]
50 if 'z_holdout' in data_from
.brushes
and not 'z_holdout' in cur_brushes
:
51 data_to
.brushes
.append('z_holdout')
53 ## force fake user for the brushes
54 for b
in data_to
.brushes
:
55 b
.use_fake_user
= True
57 return len(data_to
.brushes
)
59 class GP_OT_install_brush_pack(bpy
.types
.Operator
):
60 bl_idname
= "gp.import_brush_pack"
61 bl_label
= "Download and import texture brush pack"
62 bl_description
= "Download and import Grease Pencil brush pack from the web (~3.7 Mo)"
63 bl_options
= {"REGISTER", "INTERNAL"}
66 # def poll(cls, context):
69 def _append_brushes(self
, blend_fp
):
70 bct
= get_brushes(blend_fp
)
72 self
.report({'INFO'}, f
'{bct} brushes installed')
74 self
.report({'WARNING'}, 'Brushes already loaded')
76 def _install_from_zip(self
):
77 ## get blend file name
79 with zipfile
.ZipFile(self
.brushzip
, 'r') as zfd
:
80 for f
in zfd
.namelist():
81 if f
.endswith('.blend'):
85 self
.report({'ERROR'}, f
'blend file not found in zip {self.brushzip}')
88 unzip(self
.brushzip
, self
.temp
)
90 self
._append
_brushes
(Path(self
.temp
) / blendname
)
92 def execute(self
, context
):
100 temp
= tempfile
.gettempdir()
102 self
.report({'ERROR'}, 'no os temporary directory found to download brush pack (using python tempfile.gettempdir())')
105 self
.temp
= Path(temp
)
107 ## download link from gitlab
108 # brush pack project https://gitlab.com/pepe-school-land/gp-brush-pack
109 repo_url
= r
'https://gitlab.com/api/v4/projects/21994857'
110 tree_url
= f
'{repo_url}/repository/tree'
112 ## need to create an SSl context or linux fail and raise unverified ssl
113 ssl
._create
_default
_https
_context
= ssl
._create
_unverified
_context
116 with urllib
.request
.urlopen(tree_url
) as response
:
117 html
= response
.read()
119 ## try loading from tempdir
120 packs
= [f
for f
in os
.listdir(self
.temp
) if 'GP_brush_pack' in f
and f
.endswith('.blend')]
123 self
._append
_brushes
(Path(self
.temp
) / packs
[-1])
124 self
.report({'WARNING'}, 'Brushes loaded from temp directory (No download)')
125 # print('Could not reach web url : Brushes were loaded from temp directory file (No download)')
128 self
.report({'ERROR'}, f
'Check your internet connexion, Impossible to connect to url: {tree_url}')
132 self
.report({'ERROR'}, f
'No response read from: {tree_url}')
135 tree_dic
= json
.loads(html
)
136 zips
= [fi
for fi
in tree_dic
if fi
['type'] == 'blob' and fi
['name'].endswith('.zip')]
139 print(f
'no zip file found in {tree_url}')
142 ## sort by name to get last
143 zips
.sort(key
=lambda x
: x
['name'])
145 zipname
= last_zip
['name']
146 id_num
= last_zip
['id']
150 # filepath_encode = urllib.parse.quote(zipname, safe='')# need safe to convert possible '/'
151 # dl_url = f'{repo_url}/repository/files/{filepath_encode}/raw?ref=master'
154 dl_url
= f
"{repo_url}/repository/blobs/{id_num}/raw"
156 self
.brushzip
= self
.temp
/ zipname
159 ### Load existing files instead of redownloading if exists and up to date (same hash)
160 if self
.brushzip
.exists():
161 ### Test the hash against online git hash (check for update)
162 BLOCK_SIZE
= 524288# 512 Kb buf size
163 file_hash
= hashlib
.sha1()
164 file_hash
.update(("blob %u\0" % os
.path
.getsize(self
.brushzip
)).encode('utf-8'))
165 with
open(self
.brushzip
, 'rb') as f
:
166 fb
= f
.read(BLOCK_SIZE
)
169 fb
= f
.read(BLOCK_SIZE
)
171 if file_hash
.hexdigest() == id_num
: # same git SHA1
172 ## is up to date, install
173 print(f
'{self.brushzip} is up do date, appending brushes')
174 self
._install
_from
_zip
()
177 ## Download, unzip, use blend
178 print(f
'Downloading brushpack in {self.brushzip}')
179 ## https://cloud.blender.org/p/gallery/5f235cc297f8815e74ffb90b
181 fallback_url
='https://gitlab.com/pepe-school-land/gp-brush-pack/-/blob/master/Official_GP_brush_pack_v01.zip'
182 err
= simple_dl_url(dl_url
, str(self
.brushzip
), fallback_url
)
183 # err = download_url(dl_url, str(self.brushzip), fallback_url)
186 self
.report({'ERROR'}, 'Could not download brush pack. Check your internet connection. (see console for detail)')
190 self
._install
_from
_zip
()
195 bpy
.utils
.register_class(GP_OT_install_brush_pack
)
198 bpy
.utils
.unregister_class(GP_OT_install_brush_pack
)