BlenderKit:fixes
- improve material and model thumbnailers -Now it's possible to re-render assets directly from right-click menu. -fix appending of assets with wrong name -several fixes for experimental asset bar - small fixes in bg_blender for background operations - material thumbnailer background fixed - draw upload thumbnail in upload UI
This commit is contained in:
parent
4cb833e84a
commit
e7acb93c89
|
@ -227,26 +227,10 @@ mesh_poly_types = (
|
|||
('OTHER', 'other', ''),
|
||||
)
|
||||
|
||||
thumbnail_angles = (
|
||||
('DEFAULT', 'default', ''),
|
||||
('FRONT', 'front', ''),
|
||||
('SIDE', 'side', ''),
|
||||
('TOP', 'top', ''),
|
||||
)
|
||||
|
||||
thumbnail_snap = (
|
||||
('GROUND', 'ground', ''),
|
||||
('WALL', 'wall', ''),
|
||||
('CEILING', 'ceiling', ''),
|
||||
('FLOAT', 'floating', ''),
|
||||
)
|
||||
|
||||
thumbnail_resolutions = (
|
||||
('256', '256', ''),
|
||||
('512', '512', ''),
|
||||
('1024', '1024 - minimum for public', ''),
|
||||
('2048', '2048', ''),
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
def udate_down_up(self, context):
|
||||
|
@ -588,8 +572,30 @@ def update_free(self, context):
|
|||
" based on our fair share system. " \
|
||||
"Part of subscription is sent to artists based on usage by paying users.\n")
|
||||
|
||||
# common_upload_props = [
|
||||
# {
|
||||
# 'identifier':'id',
|
||||
# 'name':"Asset Version Id",
|
||||
# 'type':'StringProperty',
|
||||
# 'description':'Unique name of the asset version(hidden)',
|
||||
# 'default':''
|
||||
# }
|
||||
# {
|
||||
# 'identifier':'id',
|
||||
# 'name':"Asset Version Id",
|
||||
# 'type':'StringProperty',
|
||||
# 'description':'Unique name of the asset version(hidden)',
|
||||
# 'default':''
|
||||
# }
|
||||
# ]
|
||||
|
||||
|
||||
|
||||
|
||||
class BlenderKitCommonUploadProps(object):
|
||||
# for p in common_upload_props:
|
||||
# exec(f"{p['identifier']}: {p['type']}(name='{p['name']}',description='{p['description']}',default='{p['default']}')")
|
||||
|
||||
id: StringProperty(
|
||||
name="Asset Version Id",
|
||||
description="Unique name of the asset version(hidden)",
|
||||
|
@ -888,7 +894,7 @@ class BlenderKitMaterialUploadProps(PropertyGroup, BlenderKitCommonUploadProps):
|
|||
|
||||
thumbnail_resolution: EnumProperty(
|
||||
name="Resolution",
|
||||
items=thumbnail_resolutions,
|
||||
items=autothumb.thumbnail_resolutions,
|
||||
description="Thumbnail resolution",
|
||||
default="1024",
|
||||
)
|
||||
|
@ -1064,21 +1070,21 @@ class BlenderKitModelUploadProps(PropertyGroup, BlenderKitCommonUploadProps):
|
|||
|
||||
thumbnail_angle: EnumProperty(
|
||||
name='Thumbnail Angle',
|
||||
items=thumbnail_angles,
|
||||
items=autothumb.thumbnail_angles,
|
||||
default='DEFAULT',
|
||||
description='thumbnailer angle',
|
||||
)
|
||||
|
||||
thumbnail_snap_to: EnumProperty(
|
||||
name='Model Snaps To:',
|
||||
items=thumbnail_snap,
|
||||
items=autothumb.thumbnail_snap,
|
||||
default='GROUND',
|
||||
description='typical placing of the interior. Leave on ground for most objects that respect gravity :)',
|
||||
)
|
||||
|
||||
thumbnail_resolution: EnumProperty(
|
||||
name="Resolution",
|
||||
items=thumbnail_resolutions,
|
||||
items=autothumb.thumbnail_resolutions,
|
||||
description="Thumbnail resolution",
|
||||
default="1024",
|
||||
)
|
||||
|
|
|
@ -55,23 +55,28 @@ def append_material(file_name, matname=None, link=False, fake_user=True):
|
|||
break;
|
||||
|
||||
#not found yet? probably some name inconsistency then.
|
||||
# if not found and len(data_from.materials)>0:
|
||||
# data_to.materials = data_from.materials[0]
|
||||
# matname = data_from.materials[0]
|
||||
# print('had to assign')
|
||||
if not found and len(data_from.materials)>0:
|
||||
data_to.materials = [data_from.materials[0]]
|
||||
matname = data_from.materials[0]
|
||||
print(f"the material wasn't found under the exact name, appended another one: {matname}")
|
||||
# print('in the appended file the name is ', matname)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print('failed to open the asset file')
|
||||
# we have to find the new material :(
|
||||
# we have to find the new material , due to possible name changes
|
||||
mat = None
|
||||
for m in bpy.data.materials:
|
||||
print(m.name)
|
||||
if m not in mats_before:
|
||||
mat = m
|
||||
break
|
||||
break;
|
||||
#still not found?
|
||||
if mat is None:
|
||||
mat = bpy.data.materials.get(matname)
|
||||
|
||||
if fake_user:
|
||||
mat.use_fake_user = True
|
||||
|
||||
return mat
|
||||
|
||||
|
||||
|
|
|
@ -52,6 +52,11 @@ BL_UI_Widget.get_area_height = get_area_height
|
|||
|
||||
|
||||
def asset_bar_modal(self, context, event):
|
||||
ui_props = bpy.context.scene.blenderkitUI
|
||||
if ui_props.turn_off:
|
||||
ui_props.turn_off = False
|
||||
self.finish()
|
||||
|
||||
if self._finished:
|
||||
return {'FINISHED'}
|
||||
|
||||
|
@ -76,7 +81,9 @@ def asset_bar_modal(self, context, event):
|
|||
self.scroll_update()
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
|
||||
if self.check_ui_resized(context):
|
||||
self.update_ui_size(context)
|
||||
self.update_layout(context)
|
||||
return {"PASS_THROUGH"}
|
||||
|
||||
def asset_bar_invoke(self, context, event):
|
||||
|
@ -235,6 +242,27 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
|
|||
for w in self.tooltip_widgets:
|
||||
w.visible = True
|
||||
|
||||
def check_ui_resized(self,context):
|
||||
region = context.region
|
||||
area = context.area
|
||||
ui_props = bpy.context.scene.blenderkitUI
|
||||
ui_scale = bpy.context.preferences.view.ui_scale
|
||||
|
||||
reg_multiplier = 1
|
||||
if not bpy.context.preferences.system.use_region_overlap:
|
||||
reg_multiplier = 0
|
||||
|
||||
for r in area.regions:
|
||||
if r.type == 'TOOLS':
|
||||
self.bar_x = r.width * reg_multiplier + self.margin + ui_props.bar_x_offset * ui_scale
|
||||
elif r.type == 'UI':
|
||||
self.bar_end = r.width * reg_multiplier + 100 * ui_scale
|
||||
|
||||
bar_width = region.width - self.bar_x - self.bar_end
|
||||
if bar_width != self.bar_width:
|
||||
return True
|
||||
return False
|
||||
|
||||
def update_ui_size(self, context):
|
||||
|
||||
if bpy.app.background or not context.area:
|
||||
|
@ -264,16 +292,18 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
|
|||
elif r.type == 'UI':
|
||||
self.bar_end = r.width * reg_multiplier + 100 * ui_scale
|
||||
|
||||
self.bar_width = region.width - ui_props.bar_x - ui_props.bar_end
|
||||
self.bar_width = region.width - self.bar_x - self.bar_end
|
||||
|
||||
self.wcount = math.floor(
|
||||
(self.bar_width) / (self.button_size))
|
||||
|
||||
search_results = bpy.context.window_manager.get('search results')
|
||||
if search_results is not None and self.wcount > 0:
|
||||
self.hcount = min(user_preferences.max_assetbar_rows, math.ceil(len(search_results) / self.wcount))
|
||||
else:
|
||||
self.hcount = 1
|
||||
# we need to init all possible thumb previews in advance/
|
||||
self.hcount = user_preferences.max_assetbar_rows
|
||||
# if search_results is not None and self.wcount > 0:
|
||||
# self.hcount = min(user_preferences.max_assetbar_rows, math.ceil(len(search_results) / self.wcount))
|
||||
# else:
|
||||
# self.hcount = 1
|
||||
|
||||
self.bar_height = (self.button_size) * self.hcount + 2 * self.assetbar_margin
|
||||
# self.bar_y = region.height - ui_props.bar_y_offset * ui_scale
|
||||
|
@ -285,6 +315,9 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
|
|||
self.reports_y = self.bar_y - self.bar_height - 100
|
||||
self.reports_x = self.bar_x
|
||||
|
||||
def update_layout(self, context):
|
||||
pass;
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
|
@ -490,7 +523,14 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
|
|||
if img:
|
||||
self.tooltip_image.set_image(img.filepath)
|
||||
self.asset_name.text = asset_data['name']
|
||||
self.tooltip_panel.update(widget.x_screen + widget.width, widget.y_screen + widget.height)
|
||||
|
||||
properties_width = 0
|
||||
for r in bpy.context.area.regions:
|
||||
if r.type == 'UI':
|
||||
properties_width = r.width
|
||||
tooltip_x = min(widget.x_screen + widget.width, bpy.context.region.width - self.tooltip_panel.width -properties_width)
|
||||
|
||||
self.tooltip_panel.update(tooltip_x, widget.y_screen + widget.height)
|
||||
self.tooltip_panel.layout_widgets()
|
||||
|
||||
def exit_button(self, widget):
|
||||
|
@ -518,8 +558,9 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
|
|||
blenderkit.search.search(get_next=True)
|
||||
|
||||
def update_images(self):
|
||||
sr = bpy.context.window_manager['search results']
|
||||
|
||||
sr = bpy.context.window_manager.get('search results')
|
||||
if not sr:
|
||||
return
|
||||
for asset_button in self.asset_buttons:
|
||||
asset_button.asset_index = asset_button.button_index + self.scroll_offset
|
||||
if asset_button.asset_index < len(sr):
|
||||
|
@ -580,6 +621,15 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
|
|||
self.scroll_offset -= self.wcount * self.hcount
|
||||
self.scroll_update()
|
||||
|
||||
def update_sizes(self):
|
||||
properties_width = 0
|
||||
for r in bpy.context.area.regions:
|
||||
if r.type == 'UI':
|
||||
properties_width = r.width
|
||||
tooltip_x = min(widget.x_screen + widget.width,
|
||||
bpy.context.region.width - self.tooltip_panel.width - properties_width)
|
||||
print(widget.x_screen + widget.width, bpy.context.region.width - self.tooltip_panel.width)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(BlenderKitAssetBarOperator)
|
||||
|
|
|
@ -16,23 +16,69 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
|
||||
from blenderkit import paths, utils, bg_blender, ui_panels
|
||||
from blenderkit import paths, utils, bg_blender, ui_panels, icons, tasks_queue, download
|
||||
|
||||
import tempfile, os, subprocess, json, sys
|
||||
|
||||
import bpy
|
||||
from bpy.props import (
|
||||
FloatProperty,
|
||||
IntProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
StringProperty,
|
||||
)
|
||||
|
||||
BLENDERKIT_EXPORT_DATA_FILE = "data.json"
|
||||
|
||||
thumbnail_resolutions = (
|
||||
('256', '256', ''),
|
||||
('512', '512', ''),
|
||||
('1024', '1024 - minimum for public', ''),
|
||||
('2048', '2048', ''),
|
||||
)
|
||||
|
||||
thumbnail_angles = (
|
||||
('DEFAULT', 'default', ''),
|
||||
('FRONT', 'front', ''),
|
||||
('SIDE', 'side', ''),
|
||||
('TOP', 'top', ''),
|
||||
)
|
||||
|
||||
thumbnail_snap = (
|
||||
('GROUND', 'ground', ''),
|
||||
('WALL', 'wall', ''),
|
||||
('CEILING', 'ceiling', ''),
|
||||
('FLOAT', 'floating', ''),
|
||||
)
|
||||
|
||||
|
||||
def get_texture_ui(tpath, iname):
|
||||
tex = bpy.data.textures.get(iname)
|
||||
|
||||
if tpath.startswith('//'):
|
||||
tpath = bpy.path.abspath(tpath)
|
||||
|
||||
if not tex or not tex.image or not tex.image.filepath == tpath:
|
||||
tasks_queue.add_task((utils.get_hidden_image, (tpath, iname)), only_last=True)
|
||||
tasks_queue.add_task((utils.get_hidden_texture, (iname,)), only_last=True)
|
||||
return None
|
||||
return tex
|
||||
|
||||
|
||||
def check_thumbnail(props, imgpath):
|
||||
img = utils.get_hidden_image(imgpath, 'upload_preview', force_reload=True)
|
||||
print(' check thumbnail ', img)
|
||||
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
|
||||
|
||||
tex = utils.get_hidden_texture(img.name)
|
||||
# pcoll = icons.icon_collections["previews"]
|
||||
# pcoll.load(img.name, img.filepath, 'IMAGE')
|
||||
|
||||
return img
|
||||
else:
|
||||
props.has_thumbnail = False
|
||||
output = ''
|
||||
|
@ -55,7 +101,7 @@ def update_upload_model_preview(self, context):
|
|||
if ob is not None:
|
||||
props = ob.blenderkit
|
||||
imgpath = props.thumbnail
|
||||
check_thumbnail(props, imgpath)
|
||||
img = check_thumbnail(props, imgpath)
|
||||
|
||||
|
||||
def update_upload_scene_preview(self, context):
|
||||
|
@ -83,55 +129,19 @@ def update_upload_brush_preview(self, context):
|
|||
check_thumbnail(props, imgpath)
|
||||
|
||||
|
||||
def start_thumbnailer(self, context):
|
||||
def start_thumbnailer(self=None, json_args=None, props=None, wait=False, add_bg_process=True):
|
||||
# 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)
|
||||
ext = '.blend'
|
||||
|
||||
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)
|
||||
datafile = os.path.join(json_args['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', encoding = 'utf-8') 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, ensure_ascii=False, indent=4)
|
||||
with open(datafile, 'w', encoding='utf-8') as s:
|
||||
json.dump(json_args, s, ensure_ascii=False, indent=4)
|
||||
|
||||
proc = subprocess.Popen([
|
||||
binary_path,
|
||||
|
@ -139,72 +149,49 @@ def start_thumbnailer(self, context):
|
|||
"-noaudio",
|
||||
tfpath,
|
||||
"--python", os.path.join(script_path, "autothumb_model_bg.py"),
|
||||
"--", datafile, filepath, thumb_path, tempdir
|
||||
"--", datafile,
|
||||
], 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
|
||||
eval_path_computing = "bpy.data.objects['%s'].blenderkit.is_generating_thumbnail" % json_args['asset_name']
|
||||
eval_path_state = "bpy.data.objects['%s'].blenderkit.thumbnail_generating_state" % json_args['asset_name']
|
||||
eval_path = "bpy.data.objects['%s']" % json_args['asset_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):
|
||||
# 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'
|
||||
def start_material_thumbnailer(self=None, json_args=None, props=None, wait=False, add_bg_process=True):
|
||||
'''
|
||||
|
||||
Parameters
|
||||
----------
|
||||
self
|
||||
json_args - all arguments:
|
||||
props - blenderkit upload props with thumbnail settings, to communicate back, if not present, not used.
|
||||
wait - wait for the rendering to finish
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
'''
|
||||
if props:
|
||||
props.is_generating_thumbnail = True
|
||||
props.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)
|
||||
datafile = os.path.join(json_args['tempdir'], BLENDERKIT_EXPORT_DATA_FILE)
|
||||
|
||||
with open(datafile, 'w', encoding = 'utf-8') 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, ensure_ascii=False, indent=4)
|
||||
try:
|
||||
with open(datafile, 'w', encoding='utf-8') as s:
|
||||
json.dump(json_args, s, ensure_ascii=False, indent=4)
|
||||
|
||||
proc = subprocess.Popen([
|
||||
binary_path,
|
||||
|
@ -212,20 +199,28 @@ def start_material_thumbnailer(self, context, wait=False):
|
|||
"-noaudio",
|
||||
tfpath,
|
||||
"--python", os.path.join(script_path, "autothumb_material_bg.py"),
|
||||
"--", datafile, filepath, thumb_path, tempdir
|
||||
"--", datafile,
|
||||
], 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
|
||||
eval_path_computing = "bpy.data.materials['%s'].blenderkit.is_generating_thumbnail" % json_args['asset_name']
|
||||
eval_path_state = "bpy.data.materials['%s'].blenderkit.thumbnail_generating_state" % json_args['asset_name']
|
||||
eval_path = "bpy.data.materials['%s']" % json_args['asset_name']
|
||||
|
||||
bg_blender.add_bg_process(eval_path_computing=eval_path_computing, eval_path_state=eval_path_state,
|
||||
bg_blender.add_bg_process(name=json_args['asset_name'], eval_path_computing=eval_path_computing,
|
||||
eval_path_state=eval_path_state,
|
||||
eval_path=eval_path, process_type='THUMBNAILER', process=proc)
|
||||
if props:
|
||||
props.thumbnail_generating_state = 'Saving .blend file'
|
||||
|
||||
mat.blenderkit.thumbnail = rel_thumb_path + '.png'
|
||||
mat.blenderkit.thumbnail_generating_state = 'Saving .blend file'
|
||||
if wait:
|
||||
while proc.poll() is None:
|
||||
stdout_data, stderr_data = proc.communicate()
|
||||
print(stdout_data)
|
||||
except Exception as e:
|
||||
self.report({'WARNING'}, "Error while packing file: %s" % str(e))
|
||||
if self:
|
||||
self.report({'WARNING'}, "Error while packing file: %s" % str(e))
|
||||
else:
|
||||
print(e)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
@ -256,24 +251,198 @@ class GenerateThumbnailOperator(bpy.types.Operator):
|
|||
layout.prop(preferences, "thumbnail_use_gpu")
|
||||
|
||||
def execute(self, context):
|
||||
asset = utils.get_active_model()
|
||||
asset.blenderkit.is_generating_thumbnail = True
|
||||
asset.blenderkit.thumbnail_generating_state = 'starting blender instance'
|
||||
|
||||
tempdir = tempfile.mkdtemp()
|
||||
ext = '.blend'
|
||||
filepath = os.path.join(tempdir, "thumbnailer_blenderkit" + ext)
|
||||
|
||||
path_can_be_relative = True
|
||||
file_dir = os.path.dirname(bpy.data.filepath)
|
||||
if file_dir == '':
|
||||
file_dir = tempdir
|
||||
path_can_be_relative = False
|
||||
|
||||
an_slug = paths.slugify(asset.name)
|
||||
thumb_path = os.path.join(file_dir, an_slug)
|
||||
if path_can_be_relative:
|
||||
rel_thumb_path = os.path.join('//', an_slug)
|
||||
else:
|
||||
rel_thumb_path = thumb_path
|
||||
|
||||
|
||||
i = 0
|
||||
while os.path.isfile(thumb_path + '.jpg'):
|
||||
thumb_path = os.path.join(file_dir, an_slug + '_' + str(i).zfill(4))
|
||||
rel_thumb_path = os.path.join('//', an_slug + '_' + str(i).zfill(4))
|
||||
i += 1
|
||||
bkit = asset.blenderkit
|
||||
|
||||
bkit.thumbnail = rel_thumb_path + '.jpg'
|
||||
bkit.thumbnail_generating_state = 'Saving .blend file'
|
||||
|
||||
# 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)
|
||||
# get all included objects
|
||||
obs = utils.get_hierarchy(asset)
|
||||
obnames = []
|
||||
for ob in obs:
|
||||
obnames.append(ob.name)
|
||||
|
||||
args_dict = {
|
||||
"type": "material",
|
||||
"asset_name": asset.name,
|
||||
"filepath": filepath,
|
||||
"thumbnail_path": thumb_path,
|
||||
"tempdir": tempdir,
|
||||
}
|
||||
thumbnail_args = {
|
||||
"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,
|
||||
}
|
||||
args_dict.update(thumbnail_args)
|
||||
|
||||
start_thumbnailer(self,
|
||||
json_args=args_dict,
|
||||
props=asset.blenderkit, wait=False)
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.window_manager
|
||||
# if bpy.data.filepath == '':
|
||||
# ui_panels.ui_message(
|
||||
# title="Can't render thumbnail",
|
||||
# message="please save your file first")
|
||||
#
|
||||
# return {'FINISHED'}
|
||||
|
||||
return wm.invoke_props_dialog(self)
|
||||
|
||||
|
||||
class ReGenerateThumbnailOperator(bpy.types.Operator):
|
||||
"""Generate Cycles thumbnail for model assets"""
|
||||
bl_idname = "object.blenderkit_regenerate_thumbnail"
|
||||
bl_label = "BlenderKit Thumbnail Re-generate"
|
||||
bl_options = {'REGISTER', 'INTERNAL'}
|
||||
|
||||
asset_index: IntProperty(name="Asset Index", description='asset index in search results', default=-1)
|
||||
|
||||
thumbnail_background_lightness: FloatProperty(name="Thumbnail Background Lightness",
|
||||
description="set to make your material stand out", default=1.0,
|
||||
min=0.01, max=10)
|
||||
|
||||
thumbnail_angle: EnumProperty(
|
||||
name='Thumbnail Angle',
|
||||
items=thumbnail_angles,
|
||||
default='DEFAULT',
|
||||
description='thumbnailer angle',
|
||||
)
|
||||
|
||||
thumbnail_snap_to: EnumProperty(
|
||||
name='Model Snaps To:',
|
||||
items=thumbnail_snap,
|
||||
default='GROUND',
|
||||
description='typical placing of the interior. Leave on ground for most objects that respect gravity :)',
|
||||
)
|
||||
|
||||
thumbnail_resolution: EnumProperty(
|
||||
name="Resolution",
|
||||
items=thumbnail_resolutions,
|
||||
description="Thumbnail resolution",
|
||||
default="1024",
|
||||
)
|
||||
|
||||
thumbnail_samples: IntProperty(name="Cycles Samples",
|
||||
description="cycles samples setting", default=100,
|
||||
min=5, max=5000)
|
||||
thumbnail_denoising: BoolProperty(name="Use Denoising",
|
||||
description="Use denoising", default=True)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return True # 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 = self
|
||||
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')
|
||||
preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
layout.prop(preferences, "thumbnail_use_gpu")
|
||||
|
||||
def execute(self, context):
|
||||
if not self.asset_index > -1:
|
||||
return {'CANCELLED'}
|
||||
|
||||
# either get the data from search results
|
||||
sr = bpy.context.window_manager['search results']
|
||||
asset_data = sr[self.asset_index].to_dict()
|
||||
|
||||
tempdir = tempfile.mkdtemp()
|
||||
|
||||
an_slug = paths.slugify(asset_data['name'])
|
||||
thumb_path = os.path.join(tempdir, an_slug)
|
||||
|
||||
|
||||
args_dict = {
|
||||
"type": "material",
|
||||
"asset_name": asset_data['name'],
|
||||
"asset_data": asset_data,
|
||||
# "filepath": filepath,
|
||||
"thumbnail_path": thumb_path,
|
||||
"tempdir": tempdir,
|
||||
"do_download": True,
|
||||
"upload_after_render": True,
|
||||
}
|
||||
thumbnail_args = {
|
||||
"type": "model",
|
||||
"thumbnail_angle": self.thumbnail_angle,
|
||||
"thumbnail_snap_to": self.thumbnail_snap_to,
|
||||
"thumbnail_background_lightness": self.thumbnail_background_lightness,
|
||||
"thumbnail_resolution": self.thumbnail_resolution,
|
||||
"thumbnail_samples": self.thumbnail_samples,
|
||||
"thumbnail_denoising": self.thumbnail_denoising,
|
||||
}
|
||||
args_dict.update(thumbnail_args)
|
||||
|
||||
start_thumbnailer(self,
|
||||
json_args=args_dict,
|
||||
wait=False)
|
||||
return {'FINISHED'}
|
||||
start_thumbnailer(self, context)
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.window_manager
|
||||
if bpy.data.filepath == '':
|
||||
ui_panels.ui_message(
|
||||
title = "Can't render thumbnail",
|
||||
message = "please save your file first")
|
||||
|
||||
return {'FINISHED'}
|
||||
# if bpy.data.filepath == '':
|
||||
# ui_panels.ui_message(
|
||||
# title="Can't render thumbnail",
|
||||
# message="please save your file first")
|
||||
#
|
||||
# return {'FINISHED'}
|
||||
|
||||
return wm.invoke_props_dialog(self)
|
||||
|
||||
|
||||
class GenerateMaterialThumbnailOperator(bpy.types.Operator):
|
||||
"""Generate default thumbnail with Cycles renderer."""
|
||||
bl_idname = "object.blenderkit_material_thumbnail"
|
||||
bl_idname = "object.blenderkit_generate_material_thumbnail"
|
||||
bl_label = "BlenderKit Material Thumbnail Generator"
|
||||
bl_options = {'REGISTER', 'INTERNAL'}
|
||||
|
||||
|
@ -300,7 +469,48 @@ class GenerateMaterialThumbnailOperator(bpy.types.Operator):
|
|||
layout.prop(preferences, "thumbnail_use_gpu")
|
||||
|
||||
def execute(self, context):
|
||||
start_material_thumbnailer(self, context)
|
||||
asset = bpy.context.active_object.active_material
|
||||
tempdir = tempfile.mkdtemp()
|
||||
filepath = os.path.join(tempdir, "material_thumbnailer_cycles.blend")
|
||||
# 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)
|
||||
|
||||
thumb_dir = os.path.dirname(bpy.data.filepath)
|
||||
thumb_path = os.path.join(thumb_dir, asset.name)
|
||||
rel_thumb_path = os.path.join('//', asset.name)
|
||||
# auto increase number of the generated thumbnail.
|
||||
i = 0
|
||||
while os.path.isfile(thumb_path + '.png'):
|
||||
thumb_path = os.path.join(thumb_dir, asset.name + '_' + str(i).zfill(4))
|
||||
rel_thumb_path = os.path.join('//', asset.name + '_' + str(i).zfill(4))
|
||||
i += 1
|
||||
|
||||
asset.blenderkit.thumbnail = rel_thumb_path + '.png'
|
||||
bkit = asset.blenderkit
|
||||
|
||||
args_dict = {
|
||||
"type": "material",
|
||||
"asset_name": asset.name,
|
||||
"filepath": filepath,
|
||||
"thumbnail_path": thumb_path,
|
||||
"tempdir": tempdir,
|
||||
}
|
||||
|
||||
thumbnail_args = {
|
||||
"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,
|
||||
}
|
||||
args_dict.update(thumbnail_args)
|
||||
start_material_thumbnailer(self,
|
||||
json_args=args_dict,
|
||||
props=asset.blenderkit, wait=False)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
@ -309,11 +519,144 @@ class GenerateMaterialThumbnailOperator(bpy.types.Operator):
|
|||
return wm.invoke_props_dialog(self)
|
||||
|
||||
|
||||
class ReGenerateMaterialThumbnailOperator(bpy.types.Operator):
|
||||
"""
|
||||
Generate default thumbnail with Cycles renderer.
|
||||
Works also for assets from search results, without being downloaded before.
|
||||
"""
|
||||
bl_idname = "object.blenderkit_regenerate_material_thumbnail"
|
||||
bl_label = "BlenderKit Material Thumbnail Re-Generator"
|
||||
bl_options = {'REGISTER', 'INTERNAL'}
|
||||
|
||||
asset_index: IntProperty(name="Asset Index", description='asset index in search results', default=-1)
|
||||
|
||||
thumbnail_scale: FloatProperty(name="Thumbnail Object Size",
|
||||
description="Size of material preview object in meters."
|
||||
"Change for materials that look better at sizes different than 1m",
|
||||
default=1, min=0.00001, max=10)
|
||||
thumbnail_background: BoolProperty(name="Thumbnail Background (for Glass only)",
|
||||
description="For refractive materials, you might need a background.\n"
|
||||
"Don't use for other types of materials.\n"
|
||||
"Transparent background is preferred",
|
||||
default=False)
|
||||
thumbnail_background_lightness: FloatProperty(name="Thumbnail Background Lightness",
|
||||
description="Set to make your material stand out with enough contrast",
|
||||
default=.9,
|
||||
min=0.00001, max=1)
|
||||
thumbnail_samples: IntProperty(name="Cycles Samples",
|
||||
description="Cycles samples", default=100,
|
||||
min=5, max=5000)
|
||||
thumbnail_denoising: BoolProperty(name="Use Denoising",
|
||||
description="Use denoising", default=True)
|
||||
adaptive_subdivision: BoolProperty(name="Adaptive Subdivide",
|
||||
description="Use adaptive displacement subdivision", default=False)
|
||||
|
||||
thumbnail_resolution: EnumProperty(
|
||||
name="Resolution",
|
||||
items=thumbnail_resolutions,
|
||||
description="Thumbnail resolution",
|
||||
default="1024",
|
||||
)
|
||||
|
||||
thumbnail_generator_type: EnumProperty(
|
||||
name="Thumbnail Style",
|
||||
items=(
|
||||
('BALL', 'Ball', ""),
|
||||
('BALL_COMPLEX', 'Ball complex', 'Complex ball to highlight edgewear or material thickness'),
|
||||
('FLUID', 'Fluid', 'Fluid'),
|
||||
('CLOTH', 'Cloth', 'Cloth'),
|
||||
('HAIR', 'Hair', 'Hair ')
|
||||
),
|
||||
description="Style of asset",
|
||||
default="BALL",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return True # bpy.context.view_layer.objects.active is not None
|
||||
|
||||
def check(self, context):
|
||||
return True
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = self
|
||||
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):
|
||||
|
||||
if not self.asset_index > -1:
|
||||
return {'CANCELLED'}
|
||||
|
||||
# either get the data from search results
|
||||
sr = bpy.context.window_manager['search results']
|
||||
asset_data = sr[self.asset_index].to_dict()
|
||||
|
||||
tempdir = tempfile.mkdtemp()
|
||||
|
||||
thumb_path = os.path.join(tempdir, asset_data['name'])
|
||||
|
||||
args_dict = {
|
||||
"type": "material",
|
||||
"asset_name": asset_data['name'],
|
||||
"asset_data": asset_data,
|
||||
"thumbnail_path": thumb_path,
|
||||
"tempdir": tempdir,
|
||||
"do_download": True,
|
||||
"upload_after_render": True,
|
||||
}
|
||||
thumbnail_args = {
|
||||
"thumbnail_type": self.thumbnail_generator_type,
|
||||
"thumbnail_scale": self.thumbnail_scale,
|
||||
"thumbnail_background": self.thumbnail_background,
|
||||
"thumbnail_background_lightness": self.thumbnail_background_lightness,
|
||||
"thumbnail_resolution": self.thumbnail_resolution,
|
||||
"thumbnail_samples": self.thumbnail_samples,
|
||||
"thumbnail_denoising": self.thumbnail_denoising,
|
||||
"adaptive_subdivision": self.adaptive_subdivision,
|
||||
"texture_size_meters": utils.get_param(asset_data, 'textureSizeMeters', 1.0),
|
||||
}
|
||||
args_dict.update(thumbnail_args)
|
||||
start_material_thumbnailer(self,
|
||||
json_args=args_dict,
|
||||
wait=False)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
# scene = bpy.context.scene
|
||||
# ui_props = scene.blenderkitUI
|
||||
# if ui_props.active_index > -1:
|
||||
# sr = bpy.context.window_manager['search results']
|
||||
# self.asset_data = dict(sr[ui_props.active_index])
|
||||
# else:
|
||||
#
|
||||
# active_asset = utils.get_active_asset_by_type(asset_type = self.asset_type)
|
||||
# self.asset_data = active_asset.get('asset_data')
|
||||
|
||||
wm = context.window_manager
|
||||
return wm.invoke_props_dialog(self)
|
||||
|
||||
|
||||
def register_thumbnailer():
|
||||
bpy.utils.register_class(GenerateThumbnailOperator)
|
||||
bpy.utils.register_class(ReGenerateThumbnailOperator)
|
||||
bpy.utils.register_class(GenerateMaterialThumbnailOperator)
|
||||
bpy.utils.register_class(ReGenerateMaterialThumbnailOperator)
|
||||
|
||||
|
||||
def unregister_thumbnailer():
|
||||
bpy.utils.unregister_class(GenerateThumbnailOperator)
|
||||
bpy.utils.unregister_class(ReGenerateThumbnailOperator)
|
||||
bpy.utils.unregister_class(GenerateMaterialThumbnailOperator)
|
||||
bpy.utils.unregister_class(ReGenerateMaterialThumbnailOperator)
|
||||
|
|
|
@ -18,16 +18,14 @@
|
|||
|
||||
|
||||
|
||||
from blenderkit import utils, append_link, bg_blender
|
||||
from blenderkit import utils, append_link, bg_blender, upload_bg, download
|
||||
|
||||
import sys, json, math
|
||||
import bpy
|
||||
from pathlib import Path
|
||||
|
||||
BLENDERKIT_EXPORT_TEMP_DIR = sys.argv[-1]
|
||||
BLENDERKIT_THUMBNAIL_PATH = sys.argv[-2]
|
||||
BLENDERKIT_EXPORT_FILE_INPUT = sys.argv[-3]
|
||||
BLENDERKIT_EXPORT_DATA = sys.argv[-4]
|
||||
|
||||
BLENDERKIT_EXPORT_DATA = sys.argv[-1]
|
||||
|
||||
|
||||
def render_thumbnails():
|
||||
|
@ -44,13 +42,26 @@ def unhide_collection(cname):
|
|||
if __name__ == "__main__":
|
||||
try:
|
||||
bg_blender.progress('preparing thumbnail scene')
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
|
||||
with open(BLENDERKIT_EXPORT_DATA, 'r',encoding='utf-8') as s:
|
||||
data = json.load(s)
|
||||
# append_material(file_name, matname = None, link = False, fake_user = True)
|
||||
mat = append_link.append_material(file_name=BLENDERKIT_EXPORT_FILE_INPUT, matname=data["material"], link=True,
|
||||
if data.get('do_download'):
|
||||
asset_data = data['asset_data']
|
||||
has_url = download.get_download_url(asset_data, download.get_scene_id(), user_preferences.api_key, tcom=None,
|
||||
resolution='blend')
|
||||
if not has_url:
|
||||
bg_blender.progress("couldn't download asset for thumnbail re-rendering")
|
||||
exit()
|
||||
# download first, or rather make sure if it's already downloaded
|
||||
bg_blender.progress('downloading asset')
|
||||
fpath = download.download_asset_file(asset_data)
|
||||
data['filepath'] = fpath
|
||||
|
||||
mat = append_link.append_material(file_name=data['filepath'], matname=data["asset_name"], link=True,
|
||||
fake_user=False)
|
||||
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
|
||||
s = bpy.context.scene
|
||||
|
||||
|
@ -61,7 +72,6 @@ if __name__ == "__main__":
|
|||
'CLOTH': 'Cloth',
|
||||
'HAIR': 'Hair'
|
||||
}
|
||||
|
||||
unhide_collection(colmapdict[data["thumbnail_type"]])
|
||||
if data['thumbnail_background']:
|
||||
unhide_collection('Background')
|
||||
|
@ -70,6 +80,9 @@ if __name__ == "__main__":
|
|||
tscale = data["thumbnail_scale"]
|
||||
bpy.context.view_layer.objects['scaler'].scale = (tscale, tscale, tscale)
|
||||
bpy.context.view_layer.update()
|
||||
print('we have this materialB')
|
||||
print(mat)
|
||||
|
||||
for ob in bpy.context.visible_objects:
|
||||
if ob.name[:15] == 'MaterialPreview':
|
||||
ob.material_slots[0].material = mat
|
||||
|
@ -86,6 +99,7 @@ if __name__ == "__main__":
|
|||
if data["thumbnail_type"] in ['BALL', 'BALL_COMPLEX', 'CLOTH']:
|
||||
utils.automap(ob.name, tex_size = ts / tscale, just_scale = True, bg_exception=True)
|
||||
bpy.context.view_layer.update()
|
||||
print('got to C')
|
||||
|
||||
s.cycles.volume_step_size = tscale * .1
|
||||
|
||||
|
@ -113,9 +127,24 @@ if __name__ == "__main__":
|
|||
bpy.context.scene.render.resolution_x = int(data['thumbnail_resolution'])
|
||||
bpy.context.scene.render.resolution_y = int(data['thumbnail_resolution'])
|
||||
|
||||
bpy.context.scene.render.filepath = BLENDERKIT_THUMBNAIL_PATH
|
||||
bpy.context.scene.render.filepath = data['thumbnail_path']
|
||||
bg_blender.progress('rendering thumbnail')
|
||||
render_thumbnails()
|
||||
if data.get('upload_after_render') and data.get('asset_data'):
|
||||
bg_blender.progress('uploading thumbnail')
|
||||
preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
|
||||
file = {
|
||||
"type": "thumbnail",
|
||||
"index": 0,
|
||||
"file_path": data['thumbnail_path'] + '.png'
|
||||
}
|
||||
upload_data = {
|
||||
"name": data['asset_data']['name'],
|
||||
"token": preferences.api_key,
|
||||
"id": data['asset_data']['id']
|
||||
}
|
||||
upload_bg.upload_file(upload_data, file)
|
||||
bg_blender.progress('background autothumbnailer finished successfully')
|
||||
|
||||
|
||||
|
|
|
@ -18,17 +18,14 @@
|
|||
|
||||
|
||||
|
||||
from blenderkit import utils, append_link, bg_blender
|
||||
from blenderkit import utils, append_link, bg_blender, download, upload_bg
|
||||
|
||||
import sys, json, math
|
||||
from pathlib import Path
|
||||
import bpy
|
||||
import mathutils
|
||||
|
||||
BLENDERKIT_EXPORT_TEMP_DIR = sys.argv[-1]
|
||||
BLENDERKIT_THUMBNAIL_PATH = sys.argv[-2]
|
||||
BLENDERKIT_EXPORT_FILE_INPUT = sys.argv[-3]
|
||||
BLENDERKIT_EXPORT_DATA = sys.argv[-4]
|
||||
BLENDERKIT_EXPORT_DATA = sys.argv[-1]
|
||||
|
||||
|
||||
def get_obnames():
|
||||
|
@ -42,6 +39,8 @@ def center_obs_for_thumbnail(obs):
|
|||
s = bpy.context.scene
|
||||
# obs = bpy.context.selected_objects
|
||||
parent = obs[0]
|
||||
if parent.type == 'EMPTY' and parent.instance_collection is not None:
|
||||
obs = parent.instance_collection.objects[:]
|
||||
|
||||
while parent.parent != None:
|
||||
parent = parent.parent
|
||||
|
@ -79,18 +78,42 @@ def render_thumbnails():
|
|||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
print( 'got to A')
|
||||
with open(BLENDERKIT_EXPORT_DATA, 'r',encoding='utf-8') as s:
|
||||
data = json.load(s)
|
||||
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
|
||||
bg_blender.progress('preparing thumbnail scene')
|
||||
obnames = get_obnames()
|
||||
main_object, allobs = append_link.append_objects(file_name=BLENDERKIT_EXPORT_FILE_INPUT,
|
||||
|
||||
if data.get('do_download'):
|
||||
bg_blender.progress('Downloading asset')
|
||||
|
||||
asset_data = data['asset_data']
|
||||
has_url = download.get_download_url(asset_data, download.get_scene_id(), user_preferences.api_key, tcom=None,
|
||||
resolution='blend')
|
||||
if not has_url == True:
|
||||
bg_blender.progress("couldn't download asset for thumnbail re-rendering")
|
||||
# download first, or rather make sure if it's already downloaded
|
||||
bg_blender.progress('downloading asset')
|
||||
fpath = download.download_asset_file(asset_data)
|
||||
data['filepath'] = fpath
|
||||
main_object, allobs = append_link.link_collection(fpath,
|
||||
location=(0,0,0),
|
||||
rotation=(0,0,0),
|
||||
link=True,
|
||||
name=asset_data['name'],
|
||||
parent=None)
|
||||
allobs = [main_object]
|
||||
else:
|
||||
bg_blender.progress('preparing thumbnail scene')
|
||||
|
||||
obnames = get_obnames()
|
||||
main_object, allobs = append_link.append_objects(file_name=data['filepath'],
|
||||
obnames=obnames,
|
||||
link=True)
|
||||
link=True)
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
|
||||
camdict = {
|
||||
'GROUND': 'camera ground',
|
||||
'WALL': 'camera wall',
|
||||
|
@ -100,7 +123,7 @@ if __name__ == "__main__":
|
|||
|
||||
bpy.context.scene.camera = bpy.data.objects[camdict[data['thumbnail_snap_to']]]
|
||||
center_obs_for_thumbnail(allobs)
|
||||
bpy.context.scene.render.filepath = BLENDERKIT_THUMBNAIL_PATH
|
||||
bpy.context.scene.render.filepath = data['thumbnail_path']
|
||||
if user_preferences.thumbnail_use_gpu:
|
||||
bpy.context.scene.cycles.device = 'GPU'
|
||||
|
||||
|
@ -112,6 +135,7 @@ if __name__ == "__main__":
|
|||
}
|
||||
s = bpy.context.scene
|
||||
s.frame_set(fdict[data['thumbnail_angle']])
|
||||
print( 'got to C')
|
||||
|
||||
snapdict = {
|
||||
'GROUND': 'Ground',
|
||||
|
@ -131,6 +155,7 @@ if __name__ == "__main__":
|
|||
s.cycles.samples = data['thumbnail_samples']
|
||||
bpy.context.view_layer.cycles.use_denoising = data['thumbnail_denoising']
|
||||
bpy.context.view_layer.update()
|
||||
print( 'got to D')
|
||||
|
||||
# import blender's HDR here
|
||||
# hdr_path = Path('datafiles/studiolights/world/interior.exr')
|
||||
|
@ -152,10 +177,32 @@ if __name__ == "__main__":
|
|||
|
||||
bg_blender.progress('rendering thumbnail')
|
||||
render_thumbnails()
|
||||
fpath = BLENDERKIT_THUMBNAIL_PATH + '0001.jpg'
|
||||
fpath = data['thumbnail_path'] + '.jpg'
|
||||
if data.get('upload_after_render') and data.get('asset_data'):
|
||||
bg_blender.progress('uploading thumbnail')
|
||||
preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
print('uploading A')
|
||||
file = {
|
||||
"type": "thumbnail",
|
||||
"index": 0,
|
||||
"file_path": fpath
|
||||
}
|
||||
upload_data = {
|
||||
"name": data['asset_data']['name'],
|
||||
"token": preferences.api_key,
|
||||
"id": data['asset_data']['id']
|
||||
}
|
||||
print('uploading B')
|
||||
|
||||
upload_bg.upload_file(upload_data, file)
|
||||
print('uploading C')
|
||||
|
||||
bg_blender.progress('background autothumbnailer finished successfully')
|
||||
|
||||
|
||||
print( 'got to E')
|
||||
|
||||
|
||||
except:
|
||||
import traceback
|
||||
|
||||
|
|
|
@ -56,6 +56,9 @@ def threadread(tcom):
|
|||
fills the data, dies.'''
|
||||
found = False
|
||||
while not found:
|
||||
if tcom.proc.poll() is not None:
|
||||
#process terminated
|
||||
return
|
||||
inline = tcom.proc.stdout.readline()
|
||||
# print('readthread', time.time())
|
||||
inline = str(inline)
|
||||
|
@ -111,7 +114,15 @@ def bg_update():
|
|||
global bg_processes
|
||||
if len(bg_processes) == 0:
|
||||
return 2
|
||||
#cleanup dead processes first
|
||||
remove_processes = []
|
||||
for p in bg_processes:
|
||||
if p[1].proc.poll() is not None:
|
||||
remove_processes.append(p)
|
||||
for p in remove_processes:
|
||||
bg_processes.remove(p)
|
||||
|
||||
#Parse process output
|
||||
for p in bg_processes:
|
||||
# proc=p[1].proc
|
||||
readthread = p[0]
|
||||
|
@ -119,26 +130,29 @@ def bg_update():
|
|||
if not readthread.is_alive():
|
||||
readthread.join()
|
||||
# readthread.
|
||||
estring = None
|
||||
if tcom.error:
|
||||
estring = tcom.eval_path_computing + ' = False'
|
||||
exec(estring)
|
||||
|
||||
tcom.lasttext = tcom.outtext
|
||||
if tcom.outtext != '':
|
||||
tcom.outtext = ''
|
||||
text =tcom.lasttext.replace("'","")
|
||||
estring = tcom.eval_path_state + ' = text'
|
||||
|
||||
exec(estring)
|
||||
# print(tcom.lasttext)
|
||||
if 'finished successfully' in tcom.lasttext:
|
||||
bg_processes.remove(p)
|
||||
estring = tcom.eval_path_computing + ' = False'
|
||||
exec(estring)
|
||||
else:
|
||||
readthread = threading.Thread(target=threadread, args=([tcom]), daemon=True)
|
||||
readthread.start()
|
||||
p[0] = readthread
|
||||
if estring:
|
||||
try:
|
||||
exec(estring)
|
||||
except Exception as e:
|
||||
print('Exception while reading from background process')
|
||||
print(e)
|
||||
|
||||
# if len(bg_processes) == 0:
|
||||
# bpy.app.timers.unregister(bg_update)
|
||||
if len(bg_processes) > 0:
|
||||
|
|
Binary file not shown.
|
@ -17,7 +17,7 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
|
||||
from blenderkit import paths, utils, tasks_queue, rerequests
|
||||
from blenderkit import paths, utils, tasks_queue, rerequests, ui, colors
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
@ -233,7 +233,9 @@ def fetch_categories(API_key, force=False):
|
|||
json.dump(categories, s, ensure_ascii=False, indent=4)
|
||||
tasks_queue.add_task((load_categories, ()))
|
||||
except Exception as e:
|
||||
bk_logger.debug('category fetching failed')
|
||||
t = 'BlenderKit failed to download fresh categories from the server'
|
||||
tasks_queue.add_task((ui.add_report,(t, 15, colors.RED)))
|
||||
bk_logger.debug(t)
|
||||
bk_logger.exception(e)
|
||||
if not os.path.exists(categories_filepath):
|
||||
source_path = paths.get_addon_file(subpath='data' + os.sep + 'categories.json')
|
||||
|
|
|
@ -492,6 +492,8 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
|||
udpate_asset_data_in_dicts(asset_data)
|
||||
|
||||
asset_main['asset_data'] = asset_data # TODO remove this??? should write to blenderkit Props?
|
||||
asset_main.blenderkit.asset_base_id = asset_data['assetBaseId']
|
||||
asset_main.blenderkit.id = asset_data['id']
|
||||
bpy.ops.wm.undo_push_context(message='add %s to scene' % asset_data['name'])
|
||||
# moving reporting to on save.
|
||||
# report_use_success(asset_data['id'])
|
||||
|
@ -683,7 +685,7 @@ def delete_unfinished_file(file_name):
|
|||
return
|
||||
|
||||
|
||||
def download_file(asset_data, resolution='blend'):
|
||||
def download_asset_file(asset_data, resolution='blend', api_key = ''):
|
||||
# this is a simple non-threaded way to download files for background resolution genenration tool
|
||||
file_name = paths.get_download_filepaths(asset_data, resolution)[0] # prefer global dir if possible.
|
||||
|
||||
|
@ -691,14 +693,11 @@ def download_file(asset_data, resolution='blend'):
|
|||
# this sends the thread for processing, where another check should occur, since the file might be corrupted.
|
||||
bk_logger.debug('not downloading, already in db')
|
||||
return file_name
|
||||
preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
api_key = preferences.api_key
|
||||
|
||||
download_canceled = False
|
||||
|
||||
with open(file_name, "wb") as f:
|
||||
print("Downloading %s" % file_name)
|
||||
headers = utils.get_headers(api_key)
|
||||
res_file_info, resolution = paths.get_res_file(asset_data, resolution)
|
||||
response = requests.get(res_file_info['url'], stream=True)
|
||||
total_length = response.headers.get('Content-Length')
|
||||
|
@ -1110,18 +1109,18 @@ def get_download_url(asset_data, scene_id, api_key, tcom=None, resolution='blend
|
|||
tasks_queue.add_task((ui.add_report, (str(r), 10, colors.RED)))
|
||||
|
||||
if r.status_code == 403:
|
||||
r = 'You need Full plan to get this item.'
|
||||
report = 'You need Full plan to get this item.'
|
||||
# r1 = 'All materials and brushes are available for free. Only users registered to Standard plan can use all models.'
|
||||
# tasks_queue.add_task((ui.add_report, (r1, 5, colors.RED)))
|
||||
if tcom is not None:
|
||||
tcom.report = r
|
||||
tcom.report = report
|
||||
tcom.error = True
|
||||
|
||||
if r.status_code == 404:
|
||||
r = 'Url not found - 404.'
|
||||
report = 'Url not found - 404.'
|
||||
# r1 = 'All materials and brushes are available for free. Only users registered to Standard plan can use all models.'
|
||||
if tcom is not None:
|
||||
tcom.report = r
|
||||
tcom.report = report
|
||||
tcom.error = True
|
||||
|
||||
elif r.status_code >= 500:
|
||||
|
|
|
@ -51,6 +51,7 @@ def register_icons():
|
|||
# iprev.image_pixels_float = img.pixels[:]
|
||||
|
||||
icon_collections["main"] = pcoll
|
||||
icon_collections["previews"] = bpy.utils.previews.new()
|
||||
|
||||
|
||||
def unregister_icons():
|
||||
|
|
|
@ -410,7 +410,7 @@ def regenerate_thumbnail_material(data):
|
|||
# preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
# layout.prop(preferences, "thumbnail_use_gpu")
|
||||
# TODO: here it should call start_material_thumbnailer , but with the wait property on, so it can upload afterwards.
|
||||
bpy.ops.object.blenderkit_material_thumbnail()
|
||||
bpy.ops.object.blenderkit_generate_material_thumbnail()
|
||||
time.sleep(130)
|
||||
# save
|
||||
# this does the actual job
|
||||
|
@ -525,7 +525,7 @@ def download_asset(asset_data, resolution='blend', unpack=False, api_key=''):
|
|||
has_url = download.get_download_url(asset_data, download.get_scene_id(), api_key, tcom=None,
|
||||
resolution='blend')
|
||||
if has_url:
|
||||
fpath = download.download_file(asset_data)
|
||||
fpath = download.download_asset_file(asset_data, api_key = api_key)
|
||||
if fpath and unpack and asset_data['assetType'] != 'hdr':
|
||||
send_to_bg(asset_data, fpath, command='unpack', wait=True)
|
||||
return fpath
|
||||
|
|
|
@ -48,7 +48,7 @@ import copy
|
|||
import json
|
||||
import math
|
||||
import unicodedata
|
||||
|
||||
import queue
|
||||
import logging
|
||||
|
||||
bk_logger = logging.getLogger('blenderkit')
|
||||
|
@ -75,7 +75,7 @@ def check_errors(rdata):
|
|||
search_threads = []
|
||||
thumb_sml_download_threads = {}
|
||||
thumb_full_download_threads = {}
|
||||
reports = ''
|
||||
reports_queue = queue.Queue()
|
||||
|
||||
rtips = ['Click or drag model or material in scene to link/append ',
|
||||
"Please rate responsively and plentifully. This helps us distribute rewards to the authors.",
|
||||
|
@ -412,9 +412,10 @@ def timer_update():
|
|||
|
||||
wm[search_name] = []
|
||||
|
||||
global reports
|
||||
if reports != '':
|
||||
props.report = str(reports)
|
||||
global reports_queue
|
||||
|
||||
while not reports_queue.empty():
|
||||
props.report = str(reports_queue.get())
|
||||
return .2
|
||||
|
||||
rdata = thread[0].result
|
||||
|
@ -628,7 +629,7 @@ def generate_tooltip(mdata):
|
|||
t += 'Size: %s x %s x %sm\n' % (fmt_length(mparams['dimensionX']),
|
||||
fmt_length(mparams['dimensionY']),
|
||||
fmt_length(mparams['dimensionZ']))
|
||||
if has(mparams, 'faceCount'):
|
||||
if has(mparams, 'faceCount') and mdata['assetType'] == 'model':
|
||||
t += 'Face count: %s\n' % (mparams['faceCount'])
|
||||
# t += 'face count: %s, render: %s\n' % (mparams['faceCount'], mparams['faceCountRender'])
|
||||
|
||||
|
@ -709,7 +710,7 @@ def generate_tooltip(mdata):
|
|||
|
||||
show_rating_threshold = 5
|
||||
|
||||
if rcount < show_rating_threshold:
|
||||
if rcount < show_rating_threshold and mdata['assetType'] != 'hdr':
|
||||
t += f"Only assets with enough ratings \nshow the rating value. Please rate.\n"
|
||||
if rc['quality'] >= show_rating_threshold:
|
||||
# t += f"{int(mdata['ratingsAverage']['quality']) * '*'}\n"
|
||||
|
@ -765,26 +766,6 @@ def generate_author_textblock(adata):
|
|||
return t
|
||||
|
||||
|
||||
def get_items_models(self, context):
|
||||
global search_items_models
|
||||
return search_items_models
|
||||
|
||||
|
||||
def get_items_brushes(self, context):
|
||||
global search_items_brushes
|
||||
return search_items_brushes
|
||||
|
||||
|
||||
def get_items_materials(self, context):
|
||||
global search_items_materials
|
||||
return search_items_materials
|
||||
|
||||
|
||||
def get_items_textures(self, context):
|
||||
global search_items_textures
|
||||
return search_items_textures
|
||||
|
||||
|
||||
class ThumbDownloader(threading.Thread):
|
||||
query = None
|
||||
|
||||
|
@ -801,7 +782,12 @@ class ThumbDownloader(threading.Thread):
|
|||
return self._stop_event.is_set()
|
||||
|
||||
def run(self):
|
||||
r = rerequests.get(self.url, stream=False)
|
||||
print('thumb downloader', self.url)
|
||||
try:
|
||||
r = requests.get(self.url, stream=False)
|
||||
except Exception as e:
|
||||
bk_logger.error('Thumbnail download failed')
|
||||
bk_logger.error(str(e))
|
||||
if r.status_code == 200:
|
||||
with open(self.path, 'wb') as f:
|
||||
f.write(r.content)
|
||||
|
@ -962,6 +948,11 @@ def query_to_url(query = {}, params = {}):
|
|||
urlquery = url + requeststring
|
||||
return urlquery
|
||||
|
||||
def parse_html_formated_error(text):
|
||||
report = text[text.find('<title>') + 7: text.find('</title>')]
|
||||
|
||||
return report
|
||||
|
||||
class Searcher(threading.Thread):
|
||||
query = None
|
||||
|
||||
|
@ -982,10 +973,12 @@ class Searcher(threading.Thread):
|
|||
return self._stop_event.is_set()
|
||||
|
||||
def run(self):
|
||||
global reports_queue
|
||||
|
||||
maxthreads = 50
|
||||
query = self.query
|
||||
params = self.params
|
||||
global reports
|
||||
|
||||
|
||||
t = time.time()
|
||||
mt('search thread started')
|
||||
|
@ -999,21 +992,21 @@ class Searcher(threading.Thread):
|
|||
try:
|
||||
utils.p(self.urlquery)
|
||||
r = rerequests.get(self.urlquery, headers=self.headers) # , params = rparameters)
|
||||
# print(r.url)
|
||||
reports = ''
|
||||
# utils.p(r.text)
|
||||
except requests.exceptions.RequestException as e:
|
||||
bk_logger.error(e)
|
||||
reports = e
|
||||
# props.report = e
|
||||
reports_queue.put(str(e))
|
||||
return
|
||||
|
||||
mt('search response is back ')
|
||||
try:
|
||||
rdata = r.json()
|
||||
except Exception as e:
|
||||
reports = r.text
|
||||
bk_logger.error(e)
|
||||
error_description = parse_html_formated_error(r.text)
|
||||
reports_queue.put(error_description)
|
||||
tasks_queue.add_task((ui.add_report, (error_description, 10, colors.RED)))
|
||||
|
||||
bk_logger.error(e)
|
||||
return
|
||||
mt('data parsed ')
|
||||
if not rdata.get('results'):
|
||||
utils.pprint(rdata)
|
||||
|
|
|
@ -655,7 +655,10 @@ def draw_callback_2d_progress(self, context):
|
|||
|
||||
for process in bg_blender.bg_processes:
|
||||
tcom = process[1]
|
||||
draw_progress(x, y - index * 30, '%s' % tcom.lasttext,
|
||||
n=''
|
||||
if tcom.name is not None:
|
||||
n = tcom.name +': '
|
||||
draw_progress(x, y - index * 30, '%s' % n+tcom.lasttext,
|
||||
tcom.progress)
|
||||
index += 1
|
||||
global reports
|
||||
|
@ -1873,6 +1876,11 @@ class AssetBarOperator(bpy.types.Operator):
|
|||
|
||||
context.window_manager.modal_handler_add(self)
|
||||
ui_props.assetbar_on = True
|
||||
|
||||
#in an exceptional case these were accessed before drag start.
|
||||
self.drag_start_x = 0
|
||||
self.drag_start_y = 0
|
||||
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def execute(self, context):
|
||||
|
@ -2151,6 +2159,9 @@ class RunAssetBarWithContext(bpy.types.Operator):
|
|||
bl_description = "Run assetbar with fixed context"
|
||||
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
|
||||
|
||||
keep_running: BoolProperty(name="Keep Running", description='', default=True, options={'SKIP_SAVE'})
|
||||
do_search: BoolProperty(name="Run Search", description='', default=False, options={'SKIP_SAVE'})
|
||||
|
||||
# def modal(self, context, event):
|
||||
# return {'RUNNING_MODAL'}
|
||||
|
||||
|
@ -2159,11 +2170,11 @@ class RunAssetBarWithContext(bpy.types.Operator):
|
|||
if C_dict.get('window'): # no 3d view, no asset bar.
|
||||
preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
if preferences.experimental_features:
|
||||
bpy.ops.view3d.blenderkit_asset_bar_widget(C_dict, 'INVOKE_REGION_WIN', keep_running=True,
|
||||
do_search=False)
|
||||
bpy.ops.view3d.blenderkit_asset_bar_widget(C_dict, 'INVOKE_REGION_WIN', keep_running=self.keep_running,
|
||||
do_search=self.do_search)
|
||||
|
||||
else:
|
||||
bpy.ops.view3d.blenderkit_asset_bar(C_dict, 'INVOKE_REGION_WIN', keep_running=True, do_search=False)
|
||||
bpy.ops.view3d.blenderkit_asset_bar(C_dict, 'INVOKE_REGION_WIN', keep_running=self.keep_running, do_search=self.do_search)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
@ -2208,7 +2219,7 @@ def register_ui():
|
|||
return
|
||||
km = wm.keyconfigs.addon.keymaps.new(name="Window", space_type='EMPTY')
|
||||
# asset bar shortcut
|
||||
kmi = km.keymap_items.new(AssetBarOperator.bl_idname, 'SEMI_COLON', 'PRESS', ctrl=False, shift=False)
|
||||
kmi = km.keymap_items.new("object.run_assetbar_fix_context", 'SEMI_COLON', 'PRESS', ctrl=False, shift=False)
|
||||
kmi.properties.keep_running = False
|
||||
kmi.properties.do_search = False
|
||||
addon_keymapitems.append(kmi)
|
||||
|
|
|
@ -77,6 +77,8 @@ def draw_rect_3d(coords, color):
|
|||
|
||||
def draw_image(x, y, width, height, image, transparency, crop=(0, 0, 1, 1)):
|
||||
# draw_rect(x,y, width, height, (.5,0,0,.5))
|
||||
if not image:
|
||||
return;
|
||||
|
||||
coords = [
|
||||
(x, y), (x + width, y),
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
|
||||
from blenderkit import paths, ratings, utils, download, categories, icons, search, resolutions, ui
|
||||
from blenderkit import paths, ratings, utils, download, categories, icons, search, resolutions, ui, tasks_queue, \
|
||||
autothumb
|
||||
|
||||
from bpy.types import (
|
||||
Panel
|
||||
|
@ -35,8 +36,11 @@ from bpy.props import (
|
|||
import bpy
|
||||
import os
|
||||
import random
|
||||
import logging
|
||||
import blenderkit
|
||||
|
||||
bk_logger = logging.getLogger('blenderkit')
|
||||
|
||||
|
||||
# this was moved to separate interface:
|
||||
|
||||
|
@ -153,6 +157,7 @@ def draw_upload_common(layout, props, asset_type, context):
|
|||
layout.prop(props, 'description')
|
||||
layout.prop(props, 'tags')
|
||||
|
||||
|
||||
def poll_local_panels():
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
return user_preferences.panel_behaviour == 'BOTH' or user_preferences.panel_behaviour == 'LOCAL'
|
||||
|
@ -189,7 +194,6 @@ def draw_panel_hdr_upload(self, context):
|
|||
draw_upload_common(layout, props, 'HDR', context)
|
||||
|
||||
|
||||
|
||||
def draw_panel_hdr_search(self, context):
|
||||
s = context.scene
|
||||
props = s.blenderkit_HDR
|
||||
|
@ -203,6 +207,15 @@ def draw_panel_hdr_search(self, context):
|
|||
utils.label_multiline(layout, text=props.report)
|
||||
|
||||
|
||||
|
||||
def draw_thumbnail_upload_panel(layout, props):
|
||||
update = False
|
||||
tex = autothumb.get_texture_ui(props.thumbnail, '.upload_preview')
|
||||
if not tex or not tex.image:
|
||||
return
|
||||
box = layout.box()
|
||||
box.template_icon(icon_value=tex.image.preview.icon_id, scale=6.0)
|
||||
|
||||
def draw_panel_model_upload(self, context):
|
||||
ob = bpy.context.active_object
|
||||
while ob.parent is not None:
|
||||
|
@ -216,6 +229,9 @@ def draw_panel_model_upload(self, context):
|
|||
col = layout.column()
|
||||
if props.is_generating_thumbnail:
|
||||
col.enabled = False
|
||||
|
||||
draw_thumbnail_upload_panel(col, props)
|
||||
|
||||
prop_needed(col, props, 'thumbnail', props.thumbnail)
|
||||
if bpy.context.scene.render.engine in ('CYCLES', 'BLENDER_EEVEE'):
|
||||
col.operator("object.blenderkit_generate_thumbnail", text='Generate thumbnail', icon='IMAGE')
|
||||
|
@ -275,6 +291,8 @@ def draw_panel_scene_upload(self, context):
|
|||
col = layout.column()
|
||||
# if props.is_generating_thumbnail:
|
||||
# col.enabled = False
|
||||
draw_thumbnail_upload_panel(col, props)
|
||||
|
||||
prop_needed(col, props, 'thumbnail', props.has_thumbnail, False)
|
||||
# if bpy.context.scene.render.engine == 'CYCLES':
|
||||
# col.operator("object.blenderkit_generate_thumbnail", text='Generate thumbnail', icon='IMAGE_COL')
|
||||
|
@ -289,8 +307,6 @@ def draw_panel_scene_upload(self, context):
|
|||
# elif props.thumbnail_generating_state != '':
|
||||
# utils.label_multiline(layout, text = props.thumbnail_generating_state)
|
||||
|
||||
|
||||
|
||||
layout.prop(props, 'style')
|
||||
layout.prop(props, 'production_level')
|
||||
layout.prop(props, 'use_design_year')
|
||||
|
@ -621,15 +637,16 @@ def draw_panel_material_upload(self, context):
|
|||
draw_upload_common(layout, props, 'MATERIAL', context)
|
||||
|
||||
# THUMBNAIL
|
||||
row = layout.row()
|
||||
row = layout.column()
|
||||
if props.is_generating_thumbnail:
|
||||
row.enabled = False
|
||||
|
||||
draw_thumbnail_upload_panel(row, props)
|
||||
|
||||
prop_needed(row, props, 'thumbnail', props.has_thumbnail, False)
|
||||
|
||||
|
||||
|
||||
if bpy.context.scene.render.engine in ('CYCLES', 'BLENDER_EEVEE'):
|
||||
layout.operator("object.blenderkit_material_thumbnail", text='Render thumbnail with Cycles', icon='EXPORT')
|
||||
layout.operator("object.blenderkit_generate_material_thumbnail", text='Render thumbnail with Cycles', icon='EXPORT')
|
||||
if props.is_generating_thumbnail:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=props.thumbnail_generating_state, icon='RENDER_STILL')
|
||||
|
@ -653,8 +670,6 @@ def draw_panel_material_upload(self, context):
|
|||
layout.prop(props, 'animated')
|
||||
layout.prop(props, 'texture_size_meters')
|
||||
|
||||
|
||||
|
||||
# tname = "." + bpy.context.active_object.active_material.name + "_thumbnail"
|
||||
# if props.has_thumbnail and bpy.data.textures.get(tname) is not None:
|
||||
# row = layout.row()
|
||||
|
@ -971,15 +986,15 @@ class VIEW3D_PT_blenderkit_unified(Panel):
|
|||
if ui_props.asset_type_fold:
|
||||
expand_icon = 'TRIA_RIGHT'
|
||||
row = layout.row()
|
||||
split = row.split(factor = 0.15)
|
||||
split.prop(ui_props, 'asset_type_fold', icon = expand_icon, icon_only = True, emboss = False)
|
||||
split = row.split(factor=0.15)
|
||||
split.prop(ui_props, 'asset_type_fold', icon=expand_icon, icon_only=True, emboss=False)
|
||||
|
||||
if ui_props.asset_type_fold:
|
||||
pass
|
||||
#expanded interface with names in column
|
||||
# expanded interface with names in column
|
||||
split = split.row()
|
||||
split.scale_x = 8
|
||||
split.scale_y =1.6
|
||||
split.scale_y = 1.6
|
||||
# split = row
|
||||
# split = layout.row()
|
||||
else:
|
||||
|
@ -1160,10 +1175,9 @@ def draw_asset_context_menu(layout, context, asset_data, from_panel=False):
|
|||
# build search string from description and tags:
|
||||
op.keywords = asset_data['name']
|
||||
if asset_data.get('description'):
|
||||
op.keywords += ' ' + asset_data.get('description')+' '
|
||||
op.keywords += ' ' + asset_data.get('description') + ' '
|
||||
op.keywords += ' '.join(asset_data.get('tags'))
|
||||
|
||||
|
||||
if asset_data.get('canDownload') != 0:
|
||||
if len(bpy.context.selected_objects) > 0 and ui_props.asset_type == 'MODEL':
|
||||
aob = bpy.context.active_object
|
||||
|
@ -1228,7 +1242,7 @@ def draw_asset_context_menu(layout, context, asset_data, from_panel=False):
|
|||
0) # str(utils.get_param(asset_data, 'textureResolutionMax'))
|
||||
|
||||
elif asset_data['assetBaseId'] in s['assets used'].keys() and asset_data['assetType'] != 'hdr':
|
||||
#HDRs are excluded from replacement, since they are always replaced.
|
||||
# HDRs are excluded from replacement, since they are always replaced.
|
||||
# called from asset bar:
|
||||
print('context menu')
|
||||
op = col.operator('scene.blenderkit_download', text='Replace asset resolution')
|
||||
|
@ -1287,6 +1301,16 @@ def draw_asset_context_menu(layout, context, asset_data, from_panel=False):
|
|||
op.asset_id = asset_data['id']
|
||||
op.asset_type = asset_data['assetType']
|
||||
|
||||
if asset_data['assetType'] == 'model':
|
||||
op = layout.operator('object.blenderkit_regenerate_thumbnail', text='Regenerate thumbnail')
|
||||
op.asset_index = ui_props.active_index
|
||||
|
||||
if asset_data['assetType'] == 'material':
|
||||
op = layout.operator('object.blenderkit_regenerate_material_thumbnail', text='Regenerate thumbnail')
|
||||
op.asset_index = ui_props.active_index
|
||||
# op.asset_id = asset_data['id']
|
||||
# op.asset_type = asset_data['assetType']
|
||||
|
||||
if author_id == str(profile['user']['id']):
|
||||
row = layout.row()
|
||||
row.operator_context = 'INVOKE_DEFAULT'
|
||||
|
|
|
@ -659,6 +659,11 @@ class FastMetadata(bpy.types.Operator):
|
|||
update=update_free_full
|
||||
)
|
||||
|
||||
|
||||
####################
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
scene = bpy.context.scene
|
||||
|
@ -739,6 +744,7 @@ class FastMetadata(bpy.types.Operator):
|
|||
self.subcategory = cat_path[2]
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
self.message = f"Fast edit metadata of {asset_data['name']}"
|
||||
self.name = asset_data['displayName']
|
||||
self.description = asset_data['description']
|
||||
|
|
|
@ -93,8 +93,9 @@ def upload_file(upload_data, f):
|
|||
uploaded = True
|
||||
upload_done_url = paths.get_api_url() + 'uploads_s3/' + upload['id'] + '/upload-file/'
|
||||
upload_response = rerequests.post(upload_done_url, headers=headers, verify=True)
|
||||
print(upload_response)
|
||||
tasks_queue.add_task((ui.add_report, (f"Finished file upload{os.path.basename(f['file_path'])}",)))
|
||||
# print(upload_response)
|
||||
# print(upload_response.text)
|
||||
tasks_queue.add_task((ui.add_report, (f"Finished file upload: {os.path.basename(f['file_path'])}",)))
|
||||
return True
|
||||
else:
|
||||
print(upload_response.text)
|
||||
|
|
|
@ -326,14 +326,14 @@ def uploadable_asset_poll():
|
|||
return True
|
||||
|
||||
|
||||
def get_hidden_texture(img, force_reload=False):
|
||||
# i = get_hidden_image(tpath, bdata_name, force_reload=force_reload)
|
||||
# bdata_name = f".{bdata_name}"
|
||||
t = bpy.data.textures.get(img.name)
|
||||
def get_hidden_texture(name, force_reload=False):
|
||||
t = bpy.data.textures.get(name)
|
||||
if t is None:
|
||||
t = bpy.data.textures.new(img.name, 'IMAGE')
|
||||
if t.image != img:
|
||||
t.image = img
|
||||
t = bpy.data.textures.new(name, 'IMAGE')
|
||||
if not t.image or t.image.name != name:
|
||||
img = bpy.data.images.get(name)
|
||||
if img:
|
||||
t.image = img
|
||||
return t
|
||||
|
||||
|
||||
|
@ -691,15 +691,15 @@ def name_update(props):
|
|||
asset.name = fname
|
||||
|
||||
|
||||
def get_param(asset_data, parameter_name):
|
||||
def get_param(asset_data, parameter_name, default = None):
|
||||
if not asset_data.get('parameters'):
|
||||
# this can appear in older version files.
|
||||
return None
|
||||
return default
|
||||
|
||||
for p in asset_data['parameters']:
|
||||
if p.get('parameterType') == parameter_name:
|
||||
return p['value']
|
||||
return None
|
||||
return default
|
||||
|
||||
|
||||
def params_to_dict(params):
|
||||
|
|
Loading…
Reference in New Issue