Files
blender-addons/greasepencil_tools/import_brush_pack.py
Brecht Van Lommel df34f4f1db Cleanup: fix source comment typos
Contributed by luzpaz.

Differential Revision: https://developer.blender.org/D14312
2022-03-15 18:31:13 +01:00

146 lines
5.2 KiB
Python

# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
import ssl
import urllib.request
import urllib.parse
import zipfile
from pathlib import Path
def unzip(zip_path, extract_dir_path):
'''Get a zip path and a directory path to extract to'''
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
zip_ref.extractall(extract_dir_path)
def simple_dl_url(url, dest, fallback_url=None):
## need to import urlib.request or linux module does not found 'request' using urllib directly
## need to create an SSl context or linux fail returning unverified ssl
# ssl._create_default_https_context = ssl._create_unverified_context
try:
urllib.request.urlretrieve(url, dest)
except Exception as e:
print('Error trying to download\n', e)
if fallback_url:
print('\nDownload page for manual install:', fallback_url)
return e
def get_brushes(blend_fp):
cur_brushes = [b.name for b in bpy.data.brushes]
with bpy.data.libraries.load(str(blend_fp), link=False) as (data_from, data_to):
# load brushes starting with 'tex' prefix if there are not already there
data_to.brushes = [b for b in data_from.brushes if b.startswith('tex_') and not b in cur_brushes]
# Add holdout
if 'z_holdout' in data_from.brushes and not 'z_holdout' in cur_brushes:
data_to.brushes.append('z_holdout')
## force fake user for the brushes
for b in data_to.brushes:
b.use_fake_user = True
return len(data_to.brushes)
class GP_OT_install_brush_pack(bpy.types.Operator):
bl_idname = "gp.import_brush_pack"
bl_label = "Download and import texture brush pack"
bl_description = "Download and import Grease Pencil brush pack from the web (~3.7 Mo)"
bl_options = {"REGISTER", "INTERNAL"}
# @classmethod
# def poll(cls, context):
# return True
def _append_brushes(self, blend_fp):
bct = get_brushes(blend_fp)
if bct:
self.report({'INFO'}, f'{bct} brushes installed')
else:
self.report({'WARNING'}, 'Brushes already loaded')
def _install_from_zip(self):
## get blend file name
blendname = None
with zipfile.ZipFile(self.brushzip, 'r') as zfd:
for f in zfd.namelist():
if f.endswith('.blend'):
blendname = f
break
if not blendname:
self.report({'ERROR'}, f'blend file not found in zip {self.brushzip}')
return
unzip(self.brushzip, self.temp)
self._append_brushes(Path(self.temp) / blendname)
def execute(self, context):
import tempfile
import os
temp = tempfile.gettempdir()
if not temp:
self.report({'ERROR'}, 'no os temporary directory found to download brush pack (using python tempfile.gettempdir())')
return {"CANCELLED"}
self.temp = Path(temp)
dl_url = 'https://download.blender.org/demo/bundles/bundles-3.0/grease-pencil-brush-pack.zip'
## need to create an SSl context or linux fail and raise unverified ssl
ssl._create_default_https_context = ssl._create_unverified_context
file_size = None
try:
with urllib.request.urlopen(dl_url) as response:
file_size = int(response.getheader('Content-Length'))
except:
## try loading from tempdir
packs = [f for f in os.listdir(self.temp) if 'gp_brush_pack' in f.lower() and f.endswith('.blend')]
if packs:
packs.sort()
self._append_brushes(Path(self.temp) / packs[-1])
self.report({'WARNING'}, 'Brushes loaded from temp directory (No download)')
return {"FINISHED"}
self.report({'ERROR'}, f'Check your internet connection, impossible to connect to url: {dl_url}')
return {"CANCELLED"}
if file_size is None:
self.report({'ERROR'}, f'No response read from: {dl_url}')
return {"CANCELLED"}
self.brushzip = self.temp / Path(dl_url).name
### Load existing files instead of redownloading if exists and up to date (same hash)
if self.brushzip.exists():
### compare using file size with size from url header
disk_size = self.brushzip.stat().st_size
if disk_size == file_size:
## is up to date, install
print(f'{self.brushzip} is up do date, appending brushes')
self._install_from_zip()
return {"FINISHED"}
## Download, unzip, use blend
print(f'Downloading brushpack in {self.brushzip}')
fallback_url='https://cloud.blender.org/p/gallery/5f235cc297f8815e74ffb90b'
err = simple_dl_url(dl_url, str(self.brushzip), fallback_url)
if err:
self.report({'ERROR'}, 'Could not download brush pack. Check your internet connection. (see console for detail)')
return {"CANCELLED"}
else:
print('Done')
self._install_from_zip()
return {"FINISHED"}
def register():
bpy.utils.register_class(GP_OT_install_brush_pack)
def unregister():
bpy.utils.unregister_class(GP_OT_install_brush_pack)