BlenderKit:

-improve multiline tooltips
-change addon category to 3d view, fits a bit more than add mesh
-support searching only own assets
-support searching for procedural only assets(hiddn by now)
-switch off defautl GPU on for thumbnails- this was a bug that went unnoticed for a long time.
-add gpu render option directly to thumbnail render dialogs
-non-treaded downloading for resolutions
-move in utils and rename correctly params_to_dict and dict_to_params
-display icon for rejected assets(needs a new icon)
-split login panel
-rename some panels for more consistency
-improve some tooltips
This commit is contained in:
Vilém Duha 2020-01-18 15:29:38 +01:00
parent 171648da57
commit 8e3757177c
Notes: blender-bot 2023-02-14 18:55:34 +01:00
Referenced by issue #76905, Unable to download blenderkit (in steam version) not in add-on section.
10 changed files with 154 additions and 59 deletions

View File

@ -26,7 +26,7 @@ bl_info = {
"warning": "",
"wiki_url": "https://youtu.be/1hVgcQhIAo8"
"Scripts/Add_Mesh/BlenderKit",
"category": "Add Mesh",
"category": "3D View",
}
if "bpy" in locals():
@ -249,11 +249,11 @@ def asset_type_callback(self, context):
#ui_props = s.blenderkitUI
if self.down_up == 'SEARCH':
items = (
('MODEL', 'Search Models', 'Browse models', 'OBJECT_DATAMODE', 0),
('MODEL', 'Find Models', 'Find models in the BlenderKit online database', 'OBJECT_DATAMODE', 0),
# ('SCENE', 'SCENE', 'Browse scenes', 'SCENE_DATA', 1),
('MATERIAL', 'Search Materials', 'Browse materials', 'MATERIAL', 2),
('MATERIAL', 'Find Materials', 'Find models in the BlenderKit online database', 'MATERIAL', 2),
# ('TEXTURE', 'Texture', 'Browse textures', 'TEXTURE', 3),
('BRUSH', 'Search Brushes', 'Browse brushes', 'BRUSH_DATA', 3)
('BRUSH', 'Find Brushes', 'Find models in the BlenderKit online database', 'BRUSH_DATA', 3)
)
else:
items = (
@ -386,6 +386,8 @@ class BlenderKitCommonSearchProps(object):
default=False)
search_done: BoolProperty(name="Search Completed", description="at least one search did run (internal)",
default=False)
own_only: BoolProperty(name="My Assets", description="Search only for your assets",
default=False)
search_error: BoolProperty(name="Search Error", description="last search had an error", default=False)
report: StringProperty(
name="Report",
@ -508,8 +510,8 @@ class BlenderKitCommonUploadProps(object):
default=True
)
node_count: IntProperty(name="Node count", description="Total nodes in the asset", default=0)
texture_count: IntProperty(name="Node count", description="Total nodes in the asset", default=0)
total_megapixels: IntProperty(name="Node count", description="Total nodes in the asset", default=0)
texture_count: IntProperty(name="Texture count", description="Total texture count in asset", default=0)
total_megapixels: IntProperty(name="Megapixels", description="Total megapixels of texture", default=0)
# is_private: BoolProperty(name="Asset is Private",
# description="If not marked private, your asset will go into the validation process automatically\n"
@ -1165,6 +1167,18 @@ class BlenderKitModelSearchProps(PropertyGroup, BlenderKitCommonSearchProps):
update=search.search_update
)
search_procedural: EnumProperty(
items=(
('BOTH', 'Both',''),
('PROCEDURAL', 'Procedural',''),
('TEXTURE_BASED', 'Texture based',''),
),
default='BOTH',
description='Search only procedural/texture based assets',
update=search.search_update
)
# DESIGN YEAR
search_design_year: BoolProperty(name="Sesigned in Year",
description="when the object was approximately designed",
@ -1389,7 +1403,7 @@ class BlenderKitAddonPreferences(AddonPreferences):
thumbnail_use_gpu: BoolProperty(
name="Use GPU for Thumbnails Rendering",
description="By default this is off so you can continue your work without any lag",
default=True
default=False
)
panel_behaviour: EnumProperty(

View File

@ -262,6 +262,8 @@ class GenerateThumbnailOperator(bpy.types.Operator):
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):
start_thumbnailer(self, context)
@ -307,6 +309,8 @@ class GenerateMaterialThumbnailOperator(bpy.types.Operator):
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)

View File

@ -523,6 +523,34 @@ def timer_update(): # TODO might get moved to handle all blenderkit stuff, not
return .5
def download_file(asset_data):
#this is a simple non-threaded way to download files for background resolution genenration tool
file_name = paths.get_download_filenames(asset_data)[0] # prefer global dir if possible.
if check_existing(asset_data):
# this sends the thread for processing, where another check should occur, since the file might be corrupted.
utils.p('not downloading, already in db')
return file_name
preferences = bpy.context.preferences.addons['blenderkit'].preferences
api_key = preferences.api_key
with open(file_name, "wb") as f:
print("Downloading %s" % file_name)
headers = utils.get_headers(api_key)
response = requests.get(asset_data['url'], stream=True)
total_length = response.headers.get('Content-Length')
if total_length is None: # no content length header
f.write(response.content)
else:
dl = 0
for data in response.iter_content(chunk_size=4096):
dl += len(data)
print(dl)
f.write(data)
return file_name
class Downloader(threading.Thread):
def __init__(self, asset_data, tcom, scene_id, api_key):
super(Downloader, self).__init__()

View File

@ -55,9 +55,11 @@ def rerequest(method, url, **kwargs):
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
if user_preferences.api_key != '':
if user_preferences.enable_oauth:
tasks_queue.add_task((ui.add_report, ('refreshing token.',)))
tasks_queue.add_task((ui.add_report, (
'refreshing token. If this fails, please login in BlenderKit Login panel.', 10)))
refresh_url = paths.get_bkit_url()
auth_token, refresh_token, oauth_response = bkit_oauth.refresh_token(user_preferences.api_key_refresh, refresh_url)
auth_token, refresh_token, oauth_response = bkit_oauth.refresh_token(
user_preferences.api_key_refresh, refresh_url)
# utils.p(auth_token, refresh_token)
if auth_token is not None:

View File

@ -220,7 +220,7 @@ def timer_update(): # TODO might get moved to handle all blenderkit stuff.
asset_data['downloaded'] = 0
# parse extra params needed for blender here
params = params_to_dict(r['parameters'])
params = utils.params_to_dict(r['parameters'])
if asset_type == 'model':
if params.get('boundBoxMinX') != None:
@ -403,17 +403,13 @@ def has(mdata, prop):
return False
def params_to_dict(params):
params_dict = {}
for p in params:
params_dict[p['parameterType']] = p['value']
return params_dict
def generate_tooltip(mdata):
col_w = 40
if type(mdata['parameters']) == list:
mparams = params_to_dict(mdata['parameters'])
mparams = utils.params_to_dict(mdata['parameters'])
else:
mparams = mdata['parameters']
t = ''
@ -953,6 +949,11 @@ def build_query_model():
query["textureResolutionMin"] = props.search_texture_resolution_min
query["textureResolutionMax"] = props.search_texture_resolution_max
if props.search_procedural == "PROCEDURAL":
query["procedural"] = True
elif props.search_procedural == 'TEXTURE_BASED':
query["procedural"] = False
build_query_common(query, props)
return query
@ -1106,6 +1107,12 @@ def search(category='', get_next=False, author_id=''):
if author_id != '':
query['author_id'] = author_id
elif props.own_only:
# if user searches for [another] author, 'only my assets' is invalid. that's why in elif.
profile = bpy.context.window_manager.get('bkit profile')
if profile is not None:
query['author_id'] = str(profile['user']['id'])
# utils.p('searching')
props.is_searching = True

View File

@ -67,7 +67,7 @@ verification_icons = {
'uploading': 'vs_uploading.png',
'on_hold': 'vs_on_hold.png',
'validated': None,
'rejected': None
'rejected': 'vs_on_hold.png'
}
@ -698,6 +698,7 @@ def draw_callback_2d_upload_preview(self, context):
props = utils.get_upload_props()
if props != None and ui_props.draw_tooltip:
if ui_props.asset_type != 'BRUSH':
ui_props.thumbnail_image = props.thumbnail
else:
@ -1417,6 +1418,9 @@ class AssetBarOperator(bpy.types.Operator):
ui_props.draw_tooltip = True
ui_props.tooltip = asset_data['tooltip']
#bpy.ops.wm.call_menu(name='OBJECT_MT_blenderkit_asset_menu')
else:
ui_props.draw_tooltip = False

View File

@ -53,7 +53,7 @@ def label_multiline(layout, text='', icon='NONE', width=-1):
l1 = l[:i]
layout.label(text=l1, icon=icon)
icon = 'NONE'
l = l[i:]
l = l[i:].lstrip()
li += 1
if li > maxlines:
break;
@ -299,7 +299,9 @@ def draw_panel_model_search(self, context):
layout.operator("wm.url_open", text="Get Full plan", icon='URL').url = paths.BLENDERKIT_PLANS
layout.prop(props, "search_style")
layout.prop(props, "own_only")
layout.prop(props, "free_only")
#layout.prop(props, "search_procedural", expand = True)
# if props.search_style == 'OTHER':
# layout.prop(props, "search_style_other")
# layout.prop(props, "search_engine")
@ -366,7 +368,7 @@ def draw_panel_scene_search(self, context):
row = layout.row()
row.prop(props, "search_keywords", text="", icon='VIEWZOOM')
draw_assetbar_show_hide(row, props)
layout.prop(props, "own_only")
label_multiline(layout, text=props.report)
# layout.prop(props, "search_style")
@ -424,7 +426,7 @@ class VIEW3D_PT_blenderkit_profile(Panel):
bl_idname = "VIEW3D_PT_blenderkit_profile"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Profile"
bl_label = "BlenderKit Profile"
@classmethod
def poll(cls, context):
@ -440,8 +442,6 @@ class VIEW3D_PT_blenderkit_profile(Panel):
draw_login_progress(layout)
return
if user_preferences.enable_oauth:
draw_login_buttons(layout)
if user_preferences.api_key != '':
me = bpy.context.window_manager.get('bkit profile')
@ -460,6 +460,28 @@ class VIEW3D_PT_blenderkit_profile(Panel):
icon='URL').url = paths.get_bkit_url() + paths.BLENDERKIT_USER_ASSETS
class VIEW3D_PT_blenderkit_login(Panel):
bl_category = "BlenderKit"
bl_idname = "VIEW3D_PT_blenderkit_login"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "BlenderKit Login"
@classmethod
def poll(cls, context):
return True
def draw(self, context):
layout = self.layout
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
if user_preferences.login_attempt:
draw_login_progress(layout)
return
if user_preferences.enable_oauth:
draw_login_buttons(layout)
def draw_panel_model_rating(self, context):
o = bpy.context.active_object
op = draw_ratings(self.layout, context) # , props)
@ -526,7 +548,7 @@ def draw_panel_material_search(self, context):
row = layout.row()
row.prop(props, "search_keywords", text="", icon='VIEWZOOM')
draw_assetbar_show_hide(row, props)
layout.prop(props, "own_only")
label_multiline(layout, text=props.report)
# layout.prop(props, 'search_style')
@ -568,7 +590,7 @@ def draw_panel_brush_search(self, context):
row = layout.row()
row.prop(props, "search_keywords", text="", icon='VIEWZOOM')
draw_assetbar_show_hide(row, props)
layout.prop(props, "own_only")
label_multiline(layout, text=props.report)
draw_panel_categories(self, context)
@ -605,7 +627,7 @@ class VIEW3D_PT_blenderkit_unified(Panel):
bl_idname = "VIEW3D_PT_blenderkit_unified"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "BlenderKit"
bl_label = "Find and Upload Assets"
@classmethod
def poll(cls, context):
@ -651,11 +673,11 @@ class VIEW3D_PT_blenderkit_unified(Panel):
layout.label(text='Paste your API Key:')
layout.prop(user_preferences, 'api_key', text='')
layout.separator()
if bpy.data.filepath == '':
layout.alert = True
label_multiline(layout, text="It's better to save your file first.", width=w)
layout.alert = False
layout.separator()
# if bpy.data.filepath == '':
# layout.alert = True
# label_multiline(layout, text="It's better to save your file first.", width=w)
# layout.alert = False
# layout.separator()
if ui_props.down_up == 'SEARCH':
@ -986,7 +1008,8 @@ def header_search_draw(self, context):
if ui_props.asset_type == 'BRUSH':
props = s.blenderkit_brush
layout.separator_spacer()
if context.space_data.show_region_tool_header == True:
layout.separator_spacer()
layout.prop(ui_props, "asset_type", text='', icon='URL')
layout.prop(props, "search_keywords", text="", icon='VIEWZOOM')
draw_assetbar_show_hide(layout, props)
@ -998,10 +1021,11 @@ preview_collections = {}
classess = (
SetCategoryOperator,
VIEW3D_PT_blenderkit_profile,
VIEW3D_PT_blenderkit_login,
VIEW3D_PT_blenderkit_unified,
VIEW3D_PT_blenderkit_model_properties,
VIEW3D_PT_blenderkit_downloads,
VIEW3D_PT_blenderkit_profile,
OBJECT_MT_blenderkit_asset_menu,
UrlPopupDialog
)

View File

@ -81,28 +81,6 @@ def add_version(data):
data["addonVersion"] = addon_version
def params_to_dict(inputs, parameters=None):
if parameters == None:
parameters = []
for k in inputs.keys():
if type(inputs[k]) == list:
strlist = ""
for idx, s in enumerate(inputs[k]):
strlist += s
if idx < len(inputs[k]) - 1:
strlist += ','
value = "%s" % strlist
elif type(inputs[k]) != bool:
value = inputs[k]
else:
value = str(inputs[k])
parameters.append(
{
"parameterType": k,
"value": value
})
return parameters
def write_to_report(props, text):
@ -570,7 +548,7 @@ def start_upload(self, context, asset_type, reupload, upload_set):
export_data, upload_data, eval_path_computing, eval_path_state, eval_path, props = get_upload_data(self, context,
asset_type)
# utils.pprint(upload_data)
upload_data['parameters'] = params_to_dict(
upload_data['parameters'] = utils.dict_to_params(
upload_data['parameters']) # weird array conversion only for upload, not for tooltips.
binary_path = bpy.app.binary_path
@ -783,7 +761,10 @@ class UploadOperator(Operator):
if props.is_private == 'PUBLIC':
ui_panels.label_multiline(layout, text='public assets are validated several hours'
' or days after upload. ', width=300)
' or days after upload. Remember always to '
'test download your asset to a clean file'
' to see if it uploaded correctly.'
, width=300)
def invoke(self, context, event):
props = utils.get_upload_props()

View File

@ -87,8 +87,8 @@ def upload_file(upload_data, f):
upload_create_url = paths.get_api_url() + 'uploads/'
upload = rerequests.post(upload_create_url, json=upload_info, headers=headers, verify=True)
upload = upload.json()
chunk_size = 1024 * 256
#
chunk_size = 1024 * 1024 * 2
utils.pprint(upload)
# file gets uploaded here:
uploaded = False
@ -103,8 +103,10 @@ def upload_file(upload_data, f):
if upload_response.status_code == 200:
uploaded = True
else:
print(upload_response.text)
bg_blender.progress(f'Upload failed, retry. {a}')
except Exception as e:
print(e)
bg_blender.progress('Upload %s failed, retrying' % f['type'])
time.sleep(1)

View File

@ -514,4 +514,33 @@ def name_update():
fname = fname.replace('\'', '')
fname = fname.replace('\"', '')
asset = get_active_asset()
asset.name = fname
asset.name = fname
def params_to_dict(params):
params_dict = {}
for p in params:
params_dict[p['parameterType']] = p['value']
return params_dict
def dict_to_params(inputs, parameters=None):
if parameters == None:
parameters = []
for k in inputs.keys():
if type(inputs[k]) == list:
strlist = ""
for idx, s in enumerate(inputs[k]):
strlist += s
if idx < len(inputs[k]) - 1:
strlist += ','
value = "%s" % strlist
elif type(inputs[k]) != bool:
value = inputs[k]
else:
value = str(inputs[k])
parameters.append(
{
"parameterType": k,
"value": value
})
return parameters