Newer
Older
# ##### 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 #####
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import tempfile, os, subprocess, json, sys
import bpy
BLENDERKIT_EXPORT_DATA_FILE = "data.json"
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.view_layer.objects.active 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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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)
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=utils.get_process_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, wait=False):
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# 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)
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=utils.get_process_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"
return bpy.context.view_layer.objects.active 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')
preferences = bpy.context.preferences.addons['blenderkit'].preferences
layout.prop(preferences, "thumbnail_use_gpu")
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):
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"
return bpy.context.view_layer.objects.active 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')
preferences = bpy.context.preferences.addons['blenderkit'].preferences
layout.prop(preferences, "thumbnail_use_gpu")
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)