-
Vilém Duha authored
it now doesn't allow these character in object/datablock names when uploading.
Vilém Duha authoredit now doesn't allow these character in object/datablock names when uploading.
autothumb.py 12.80 KiB
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
if "bpy" in locals():
from importlib import reload
paths = reload(paths)
utils = reload(utils)
bg_blender = reload(bg_blender)
else:
from blenderkit import paths, utils, bg_blender
import tempfile, os, subprocess, json, sys
import bpy
BLENDERKIT_EXPORT_DATA_FILE = "data.json"
ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000
HIGH_PRIORITY_CLASS = 0x00000080
IDLE_PRIORITY_CLASS = 0x00000040
NORMAL_PRIORITY_CLASS = 0x00000020
REALTIME_PRIORITY_CLASS = 0x00000100
def check_thumbnail(props, imgpath):
img = utils.get_hidden_image(imgpath, 'upload_preview', force_reload=True)
if img is not None: # and img.size[0] == img.size[1] and img.size[0] >= 512 and (
# img.file_format == 'JPEG' or img.file_format == 'PNG'):
props.has_thumbnail = True
props.thumbnail_generating_state = ''
return
else:
props.has_thumbnail = False
output = ''
if img is None or img.size[0] == 0 or img.filepath.find('thumbnail_notready.jpg') > -1:
output += 'No thumbnail or wrong file path\n'
else:
pass;
# this is causing problems on some platforms, don't know why..
# if img.size[0] != img.size[1]:
# output += 'image not a square\n'
# if img.size[0] < 512:
# output += 'image too small, should be at least 512x512\n'
# if img.file_format != 'JPEG' or img.file_format != 'PNG':
# output += 'image has to be a jpeg or png'
props.thumbnail_generating_state = output
def update_upload_model_preview(self, context):
ob = utils.get_active_model()
if ob is not None:
props = ob.blenderkit
imgpath = props.thumbnail
check_thumbnail(props, imgpath)
def update_upload_scene_preview(self, context):
s = bpy.context.scene
props = s.blenderkit
imgpath = props.thumbnail
check_thumbnail(props, imgpath)
def update_upload_material_preview(self, context):
if hasattr(bpy.context, 'active_object') \
and bpy.context.active_object is not None \
and bpy.context.active_object.active_material is not None:
mat = bpy.context.active_object.active_material
props = mat.blenderkit
imgpath = props.thumbnail
check_thumbnail(props, imgpath)
def update_upload_brush_preview(self, context):
brush = utils.get_active_brush()
if brush is not None:
props = brush.blenderkit
imgpath = bpy.path.abspath(brush.icon_filepath)
check_thumbnail(props, imgpath)
def start_thumbnailer(self, context):
# Prepare to save the file
mainmodel = utils.get_active_model()
mainmodel.blenderkit.is_generating_thumbnail = True
mainmodel.blenderkit.thumbnail_generating_state = 'starting blender instance'
binary_path = bpy.app.binary_path
script_path = os.path.dirname(os.path.realpath(__file__))
basename, ext = os.path.splitext(bpy.data.filepath)
if not basename:
basename = os.path.join(basename, "temp")
if not ext:
ext = ".blend"
asset_name = mainmodel.name
tempdir = tempfile.mkdtemp()
file_dir = os.path.dirname(bpy.data.filepath)
thumb_path = os.path.join(file_dir, asset_name)
rel_thumb_path = os.path.join('//', asset_name)
i = 0
while os.path.isfile(thumb_path + '.jpg'):
thumb_path = os.path.join(file_dir, asset_name + '_' + str(i).zfill(4))
rel_thumb_path = os.path.join('//', asset_name + '_' + str(i).zfill(4))
i += 1
filepath = os.path.join(tempdir, "thumbnailer_blenderkit" + ext)
tfpath = paths.get_thumbnailer_filepath()
datafile = os.path.join(tempdir, BLENDERKIT_EXPORT_DATA_FILE)
try:
# save a copy of actual scene but don't interfere with the users models
bpy.ops.wm.save_as_mainfile(filepath=filepath, compress=False, copy=True)
obs = utils.get_hierarchy(mainmodel)
obnames = []
for ob in obs:
obnames.append(ob.name)
with open(datafile, 'w') as s:
bkit = mainmodel.blenderkit
json.dump({
"type": "model",
"models": str(obnames),
"thumbnail_angle": bkit.thumbnail_angle,
"thumbnail_snap_to": bkit.thumbnail_snap_to,
"thumbnail_background_lightness": bkit.thumbnail_background_lightness,
"thumbnail_resolution": bkit.thumbnail_resolution,
"thumbnail_samples": bkit.thumbnail_samples,
"thumbnail_denoising": bkit.thumbnail_denoising,
}, s)
flags = BELOW_NORMAL_PRIORITY_CLASS
if sys.platform != 'win32': # TODO test this on windows and find out how to change process priority on linux
# without psutil - we don't want any more libs in the addon
flags = 0
proc = subprocess.Popen([
binary_path,
"--background",
"-noaudio",
tfpath,
"--python", os.path.join(script_path, "autothumb_model_bg.py"),
"--", datafile, filepath, thumb_path, tempdir
], bufsize=1, stdout=subprocess.PIPE, stdin=subprocess.PIPE, creationflags=flags)
eval_path_computing = "bpy.data.objects['%s'].blenderkit.is_generating_thumbnail" % mainmodel.name
eval_path_state = "bpy.data.objects['%s'].blenderkit.thumbnail_generating_state" % mainmodel.name
eval_path = "bpy.data.objects['%s']" % mainmodel.name
bg_blender.add_bg_process(eval_path_computing=eval_path_computing, eval_path_state=eval_path_state,
eval_path=eval_path, process_type='THUMBNAILER', process=proc)
mainmodel.blenderkit.thumbnail = rel_thumb_path + '.jpg'
mainmodel.blenderkit.thumbnail_generating_state = 'Saving .blend file'
except Exception as e:
self.report({'WARNING'}, "Error while exporting file: %s" % str(e))
return {'FINISHED'}
def start_material_thumbnailer(self, context):
# Prepare to save the file
mat = bpy.context.active_object.active_material
mat.blenderkit.is_generating_thumbnail = True
mat.blenderkit.thumbnail_generating_state = 'starting blender instance'
binary_path = bpy.app.binary_path
script_path = os.path.dirname(os.path.realpath(__file__))
basename, ext = os.path.splitext(bpy.data.filepath)
if not basename:
basename = os.path.join(basename, "temp")
if not ext:
ext = ".blend"
asset_name = mat.name
tempdir = tempfile.mkdtemp()
file_dir = os.path.dirname(bpy.data.filepath)
thumb_path = os.path.join(file_dir, asset_name)
rel_thumb_path = os.path.join('//', mat.name)
i = 0
while os.path.isfile(thumb_path + '.png'):
thumb_path = os.path.join(file_dir, mat.name + '_' + str(i).zfill(4))
rel_thumb_path = os.path.join('//', mat.name + '_' + str(i).zfill(4))
i += 1
filepath = os.path.join(tempdir, "material_thumbnailer_cycles" + ext)
tfpath = paths.get_material_thumbnailer_filepath()
datafile = os.path.join(tempdir, BLENDERKIT_EXPORT_DATA_FILE)
try:
# save a copy of actual scene but don't interfere with the users models
bpy.ops.wm.save_as_mainfile(filepath=filepath, compress=False, copy=True)
with open(datafile, 'w') as s:
bkit = mat.blenderkit
json.dump({
"type": "material",
"material": mat.name,
"thumbnail_type": bkit.thumbnail_generator_type,
"thumbnail_scale": bkit.thumbnail_scale,
"thumbnail_background": bkit.thumbnail_background,
"thumbnail_background_lightness": bkit.thumbnail_background_lightness,
"thumbnail_resolution": bkit.thumbnail_resolution,
"thumbnail_samples": bkit.thumbnail_samples,
"thumbnail_denoising": bkit.thumbnail_denoising,
"adaptive_subdivision": bkit.adaptive_subdivision,
"texture_size_meters": bkit.texture_size_meters,
}, s)
flags = BELOW_NORMAL_PRIORITY_CLASS
if sys.platform != 'win32': # TODO test this on windows
flags = 0
proc = subprocess.Popen([
binary_path,
"--background",
"-noaudio",
tfpath,
"--python", os.path.join(script_path, "autothumb_material_bg.py"),
"--", datafile, filepath, thumb_path, tempdir
], bufsize=1, stdout=subprocess.PIPE, stdin=subprocess.PIPE, creationflags=flags)
eval_path_computing = "bpy.data.materials['%s'].blenderkit.is_generating_thumbnail" % mat.name
eval_path_state = "bpy.data.materials['%s'].blenderkit.thumbnail_generating_state" % mat.name
eval_path = "bpy.data.materials['%s']" % mat.name
bg_blender.add_bg_process(eval_path_computing=eval_path_computing, eval_path_state=eval_path_state,
eval_path=eval_path, process_type='THUMBNAILER', process=proc)
mat.blenderkit.thumbnail = rel_thumb_path + '.png'
mat.blenderkit.thumbnail_generating_state = 'Saving .blend file'
except Exception as e:
self.report({'WARNING'}, "Error while packing file: %s" % str(e))
return {'FINISHED'}
class GenerateThumbnailOperator(bpy.types.Operator):
"""Generate Cycles thumbnail for model assets"""
bl_idname = "object.blenderkit_generate_thumbnail"
bl_label = "BlenderKit Thumbnail Generator"
bl_options = {'REGISTER', 'INTERNAL'}
@classmethod
def poll(cls, context):
return bpy.context.active_object is not None
def draw(self, context):
ob = bpy.context.active_object
while ob.parent is not None:
ob = ob.parent
props = ob.blenderkit
layout = self.layout
layout.label(text='thumbnailer settings')
layout.prop(props, 'thumbnail_background_lightness')
layout.prop(props, 'thumbnail_angle')
layout.prop(props, 'thumbnail_snap_to')
layout.prop(props, 'thumbnail_samples')
layout.prop(props, 'thumbnail_resolution')
layout.prop(props, 'thumbnail_denoising')
def execute(self, context):
start_thumbnailer(self, context)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
if bpy.data.filepath == '':
title = "Can't render thumbnail"
message = "please save your file first"
def draw_message(self, context):
self.layout.label(text = message)
bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO')
return {'FINISHED'}
return wm.invoke_props_dialog(self)
class GenerateMaterialThumbnailOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.blenderkit_material_thumbnail"
bl_label = "BlenderKit Material Thumbnail Generator"
bl_options = {'REGISTER', 'INTERNAL'}
@classmethod
def poll(cls, context):
return bpy.context.active_object is not None
def check(self, context):
return True
def draw(self, context):
layout = self.layout
props = bpy.context.active_object.active_material.blenderkit
layout.prop(props, 'thumbnail_generator_type')
layout.prop(props, 'thumbnail_scale')
layout.prop(props, 'thumbnail_background')
if props.thumbnail_background:
layout.prop(props, 'thumbnail_background_lightness')
layout.prop(props, 'thumbnail_resolution')
layout.prop(props, 'thumbnail_samples')
layout.prop(props, 'thumbnail_denoising')
layout.prop(props, 'adaptive_subdivision')
def execute(self, context):
start_material_thumbnailer(self, context)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
def register_thumbnailer():
bpy.utils.register_class(GenerateThumbnailOperator)
bpy.utils.register_class(GenerateMaterialThumbnailOperator)
def unregister_thumbnailer():
bpy.utils.unregister_class(GenerateThumbnailOperator)
bpy.utils.unregister_class(GenerateMaterialThumbnailOperator)