mirror of
https://github.com/blender/blender-addons.git
synced 2025-07-25 16:05:20 +00:00
146 lines
5.2 KiB
Python
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)
|