Skinify: fix shape generation
[blender-addons.git] / greasepencil_tools / import_brush_pack.py
blob695ca4117a9e810df3fa5407495760c0490ed54a
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 import bpy
4 import ssl
5 import urllib.request
6 import urllib.parse
7 import zipfile
8 from pathlib import Path
10 def unzip(zip_path, extract_dir_path):
11 '''Get a zip path and a directory path to extract to'''
12 with zipfile.ZipFile(zip_path, 'r') as zip_ref:
13 zip_ref.extractall(extract_dir_path)
15 def simple_dl_url(url, dest, fallback_url=None):
16 ## need to import urlib.request or linux module does not found 'request' using urllib directly
17 ## need to create an SSl context or linux fail returning unverified ssl
18 # ssl._create_default_https_context = ssl._create_unverified_context
20 try:
21 urllib.request.urlretrieve(url, dest)
22 except Exception as e:
23 print('Error trying to download\n', e)
24 if fallback_url:
25 print('\nDownload page for manual install:', fallback_url)
26 return e
28 def get_brushes(blend_fp):
29 cur_brushes = [b.name for b in bpy.data.brushes]
30 with bpy.data.libraries.load(str(blend_fp), link=False) as (data_from, data_to):
31 # load brushes starting with 'tex' prefix if there are not already there
32 data_to.brushes = [b for b in data_from.brushes if b.startswith('tex_') and not b in cur_brushes]
33 # Add holdout
34 if 'z_holdout' in data_from.brushes and not 'z_holdout' in cur_brushes:
35 data_to.brushes.append('z_holdout')
37 ## force fake user for the brushes
38 for b in data_to.brushes:
39 b.use_fake_user = True
41 return len(data_to.brushes)
43 class GP_OT_install_brush_pack(bpy.types.Operator):
44 bl_idname = "gp.import_brush_pack"
45 bl_label = "Download and import texture brush pack"
46 bl_description = "Download and import Grease Pencil brush pack from the web (~3.7 Mo)"
47 bl_options = {"REGISTER", "INTERNAL"}
49 # @classmethod
50 # def poll(cls, context):
51 # return True
53 def _append_brushes(self, blend_fp):
54 bct = get_brushes(blend_fp)
55 if bct:
56 self.report({'INFO'}, f'{bct} brushes installed')
57 else:
58 self.report({'WARNING'}, 'Brushes already loaded')
60 def _install_from_zip(self):
61 ## get blend file name
62 blendname = None
63 with zipfile.ZipFile(self.brushzip, 'r') as zfd:
64 for f in zfd.namelist():
65 if f.endswith('.blend'):
66 blendname = f
67 break
68 if not blendname:
69 self.report({'ERROR'}, f'blend file not found in zip {self.brushzip}')
70 return
72 unzip(self.brushzip, self.temp)
74 self._append_brushes(Path(self.temp) / blendname)
76 def execute(self, context):
77 import tempfile
78 import os
80 temp = tempfile.gettempdir()
81 if not temp:
82 self.report({'ERROR'}, 'no os temporary directory found to download brush pack (using python tempfile.gettempdir())')
83 return {"CANCELLED"}
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
92 file_size = None
94 try:
95 with urllib.request.urlopen(dl_url) as response:
96 file_size = int(response.getheader('Content-Length'))
97 except:
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')]
100 if packs:
101 packs.sort()
102 self._append_brushes(Path(self.temp) / packs[-1])
103 self.report({'WARNING'}, 'Brushes loaded from temp directory (No download)')
104 return {"FINISHED"}
106 self.report({'ERROR'}, f'Check your internet connection, impossible to connect to url: {dl_url}')
107 return {"CANCELLED"}
109 if file_size is None:
110 self.report({'ERROR'}, f'No response read from: {dl_url}')
111 return {"CANCELLED"}
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()
124 return {"FINISHED"}
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)
132 if err:
133 self.report({'ERROR'}, 'Could not download brush pack. Check your internet connection. (see console for detail)')
134 return {"CANCELLED"}
135 else:
136 print('Done')
137 self._install_from_zip()
138 return {"FINISHED"}
141 def register():
142 bpy.utils.register_class(GP_OT_install_brush_pack)
144 def unregister():
145 bpy.utils.unregister_class(GP_OT_install_brush_pack)