1 # SPDX-License-Identifier: GPL-2.0-or-later
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 get_brushes(blend_fp
):
28 cur_brushes
= [b
.name
for b
in bpy
.data
.brushes
]
29 with bpy
.data
.libraries
.load(str(blend_fp
), link
=False) as (data_from
, data_to
):
30 # load brushes starting with 'tex' prefix if there are not already there
31 data_to
.brushes
= [b
for b
in data_from
.brushes
if b
.startswith('tex_') and not b
in cur_brushes
]
33 if 'z_holdout' in data_from
.brushes
and not 'z_holdout' in cur_brushes
:
34 data_to
.brushes
.append('z_holdout')
36 ## force fake user for the brushes
37 for b
in data_to
.brushes
:
38 b
.use_fake_user
= True
40 return len(data_to
.brushes
)
42 class GP_OT_install_brush_pack(bpy
.types
.Operator
):
43 bl_idname
= "gp.import_brush_pack"
44 bl_label
= "Download and import texture brush pack"
45 bl_description
= "Download and import Grease Pencil brush pack from the web (~3.7 Mo)"
46 bl_options
= {"REGISTER", "INTERNAL"}
49 # def poll(cls, context):
52 def _append_brushes(self
, blend_fp
):
53 bct
= get_brushes(blend_fp
)
55 self
.report({'INFO'}, f
'{bct} brushes installed')
57 self
.report({'WARNING'}, 'Brushes already loaded')
59 def _install_from_zip(self
):
60 ## get blend file name
62 with zipfile
.ZipFile(self
.brushzip
, 'r') as zfd
:
63 for f
in zfd
.namelist():
64 if f
.endswith('.blend'):
68 self
.report({'ERROR'}, f
'blend file not found in zip {self.brushzip}')
71 unzip(self
.brushzip
, self
.temp
)
73 self
._append
_brushes
(Path(self
.temp
) / blendname
)
75 def execute(self
, context
):
80 temp
= tempfile
.gettempdir()
82 self
.report({'ERROR'}, 'no os temporary directory found to download brush pack (using python tempfile.gettempdir())')
85 self
.temp
= Path(temp
)
87 dl_url
= 'https://download.blender.org/demo/bundles/bundles-3.0/grease-pencil-brush-pack.zip'
89 ## need to create an SSl context or linux fail and raise unverified ssl
90 ssl
._create
_default
_https
_context
= ssl
._create
_unverified
_context
95 with urllib
.request
.urlopen(dl_url
) as response
:
96 file_size
= int(response
.getheader('Content-Length'))
98 ## try loading from tempdir
99 packs
= [f
for f
in os
.listdir(self
.temp
) if 'gp_brush_pack' in f
.lower() and f
.endswith('.blend')]
102 self
._append
_brushes
(Path(self
.temp
) / packs
[-1])
103 self
.report({'WARNING'}, 'Brushes loaded from temp directory (No download)')
106 self
.report({'ERROR'}, f
'Check your internet connection, impossible to connect to url: {dl_url}')
109 if file_size
is None:
110 self
.report({'ERROR'}, f
'No response read from: {dl_url}')
113 self
.brushzip
= self
.temp
/ Path(dl_url
).name
115 ### Load existing files instead of redownloading if exists and up to date (same hash)
116 if self
.brushzip
.exists():
118 ### compare using file size with size from url header
119 disk_size
= self
.brushzip
.stat().st_size
120 if disk_size
== file_size
:
121 ## is up to date, install
122 print(f
'{self.brushzip} is up do date, appending brushes')
123 self
._install
_from
_zip
()
126 ## Download, unzip, use blend
127 print(f
'Downloading brushpack in {self.brushzip}')
129 fallback_url
='https://cloud.blender.org/p/gallery/5f235cc297f8815e74ffb90b'
130 err
= simple_dl_url(dl_url
, str(self
.brushzip
), fallback_url
)
133 self
.report({'ERROR'}, 'Could not download brush pack. Check your internet connection. (see console for detail)')
137 self
._install
_from
_zip
()
142 bpy
.utils
.register_class(GP_OT_install_brush_pack
)
145 bpy
.utils
.unregister_class(GP_OT_install_brush_pack
)