BlenderKit: add use_timers to debug timers and check stability issues
rename several asset data dict properties to be serverdata-compatible - this needed an update function on scene load for older scenes. draw asset context menu also in selected model panel remove brush mode filtering from search code(is filtered in Elastic for some time already)
This commit is contained in:
parent
f1f69a63e0
commit
8bf7c77ca0
|
@ -1555,6 +1555,13 @@ class BlenderKitAddonPreferences(AddonPreferences):
|
|||
default=True,
|
||||
update=utils.save_prefs
|
||||
)
|
||||
|
||||
use_timers: BoolProperty(
|
||||
name="Use timers",
|
||||
description="Use timers for bkit",
|
||||
default=True,
|
||||
update=utils.save_prefs
|
||||
)
|
||||
# allow_proximity : BoolProperty(
|
||||
# name="allow proximity data reports",
|
||||
# description="This sends anonymized proximity data \n \
|
||||
|
@ -1673,13 +1680,16 @@ def register():
|
|||
bkit_oauth.register()
|
||||
tasks_queue.register()
|
||||
|
||||
bpy.app.timers.register(check_timers_timer, persistent=True)
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
if user_preferences.use_timers:
|
||||
bpy.app.timers.register(check_timers_timer, persistent=True)
|
||||
|
||||
bpy.app.handlers.load_post.append(scene_load)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.app.timers.unregister(check_timers_timer)
|
||||
if bpy.app.timers.is_registered(check_timers_timer):
|
||||
bpy.app.timers.unregister(check_timers_timer)
|
||||
ui_panels.unregister_ui_panels()
|
||||
ui.unregister_ui()
|
||||
|
||||
|
|
|
@ -232,7 +232,9 @@ def add_bg_process(location=None, name=None, eval_path_computing='', eval_path_s
|
|||
|
||||
def register():
|
||||
bpy.utils.register_class(KillBgProcess)
|
||||
bpy.app.timers.register(bg_update)
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
if user_preferences.use_timers:
|
||||
bpy.app.timers.register(bg_update)
|
||||
|
||||
|
||||
def unregister():
|
||||
|
|
|
@ -190,7 +190,7 @@ def report_usages():
|
|||
|
||||
for ob in asset_obs:
|
||||
asset_data = ob['asset_data']
|
||||
abid = asset_data['asset_base_id']
|
||||
abid = asset_data['assetBaseId']
|
||||
|
||||
if assets.get(abid) is None:
|
||||
asset_usages[abid] = {'count': 1}
|
||||
|
@ -201,7 +201,7 @@ def report_usages():
|
|||
# brushes
|
||||
for b in bpy.data.brushes:
|
||||
if b.get('asset_data') != None:
|
||||
abid = b['asset_data']['asset_base_id']
|
||||
abid = b['asset_data']['assetBaseId']
|
||||
asset_usages[abid] = {'count': 1}
|
||||
assets[abid] = b['asset_data']
|
||||
# materials
|
||||
|
@ -211,7 +211,7 @@ def report_usages():
|
|||
|
||||
if m is not None and m.get('asset_data') is not None:
|
||||
|
||||
abid = m['asset_data']['asset_base_id']
|
||||
abid = m['asset_data']['assetBaseId']
|
||||
if assets.get(abid) is None:
|
||||
asset_usages[abid] = {'count': 1}
|
||||
assets[abid] = m['asset_data']
|
||||
|
@ -288,12 +288,12 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
|||
if user_preferences.api_key == '':
|
||||
user_preferences.asset_counter += 1
|
||||
|
||||
if asset_data['asset_type'] == 'scene':
|
||||
if asset_data['assetType'] == 'scene':
|
||||
scene = append_link.append_scene(file_names[0], link=False, fake_user=False)
|
||||
props = scene.blenderkit
|
||||
parent = scene
|
||||
|
||||
if asset_data['asset_type'] == 'model':
|
||||
if asset_data['assetType'] == 'model':
|
||||
s = bpy.context.scene
|
||||
downloaders = kwargs.get('downloaders')
|
||||
s = bpy.context.scene
|
||||
|
@ -383,7 +383,7 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
|||
lib = group.library
|
||||
lib['asset_data'] = asset_data
|
||||
|
||||
elif asset_data['asset_type'] == 'brush':
|
||||
elif asset_data['assetType'] == 'brush':
|
||||
|
||||
# TODO if already in scene, should avoid reappending.
|
||||
inscene = False
|
||||
|
@ -414,7 +414,7 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
|||
props = brush.blenderkit
|
||||
parent = brush
|
||||
|
||||
elif asset_data['asset_type'] == 'material':
|
||||
elif asset_data['assetType'] == 'material':
|
||||
inscene = False
|
||||
for m in bpy.data.materials:
|
||||
if m.blenderkit.id == asset_data['id']:
|
||||
|
@ -433,11 +433,11 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
|||
parent = material
|
||||
|
||||
scene['assets used'] = scene.get('assets used', {})
|
||||
scene['assets used'][asset_data['asset_base_id']] = asset_data.copy()
|
||||
scene['assets used'][asset_data['assetBaseId']] = asset_data.copy()
|
||||
|
||||
scene['assets rated'] = scene.get('assets rated', {})
|
||||
|
||||
id = asset_data['asset_base_id']
|
||||
id = asset_data['assetBaseId']
|
||||
scene['assets rated'][id] = scene['assets rated'].get(id, False)
|
||||
|
||||
parent['asset_data'] = asset_data # TODO remove this??? should write to blenderkit Props?
|
||||
|
@ -477,7 +477,7 @@ def timer_update(): # TODO might get moved to handle all blenderkit stuff, not
|
|||
file_names = paths.get_download_filenames(asset_data)
|
||||
wm = bpy.context.window_manager
|
||||
|
||||
at = asset_data['asset_type']
|
||||
at = asset_data['assetType']
|
||||
if ((bpy.context.mode == 'OBJECT' and (at == 'model' \
|
||||
or at == 'material'))) \
|
||||
or ((at == 'brush') \
|
||||
|
@ -505,15 +505,15 @@ def timer_update(): # TODO might get moved to handle all blenderkit stuff, not
|
|||
else:
|
||||
done = try_finished_append(asset_data, **tcom.passargs)
|
||||
if not done:
|
||||
at = asset_data['asset_type']
|
||||
at = asset_data['assetType']
|
||||
tcom.passargs['retry_counter'] = tcom.passargs.get('retry_counter', 0) + 1
|
||||
if at in ('model', 'material'):
|
||||
download(asset_data, **tcom.passargs)
|
||||
elif asset_data['asset_type'] == 'material':
|
||||
elif asset_data['assetType'] == 'material':
|
||||
download(asset_data, **tcom.passargs)
|
||||
elif asset_data['asset_type'] == 'scene':
|
||||
elif asset_data['assetType'] == 'scene':
|
||||
download(asset_data, **tcom.passargs)
|
||||
elif asset_data['asset_type'] == 'brush' or asset_data['asset_type'] == 'texture':
|
||||
elif asset_data['assetType'] == 'brush' or asset_data['assetType'] == 'texture':
|
||||
download(asset_data, **tcom.passargs)
|
||||
if bpy.context.scene['search results'] is not None and done:
|
||||
for sres in bpy.context.scene['search results']:
|
||||
|
@ -675,7 +675,7 @@ def check_downloading(asset_data, **kwargs):
|
|||
for p in download_threads:
|
||||
p_asset_data = p[1]
|
||||
if p_asset_data['id'] == asset_data['id']:
|
||||
at = asset_data['asset_type']
|
||||
at = asset_data['assetType']
|
||||
if at in ('model', 'material'):
|
||||
downloader = {'location': kwargs['model_location'],
|
||||
'rotation': kwargs['model_rotation']}
|
||||
|
@ -737,7 +737,7 @@ def asset_in_scene(asset_data):
|
|||
scene = bpy.context.scene
|
||||
au = scene.get('assets used', {})
|
||||
|
||||
id = asset_data['asset_base_id']
|
||||
id = asset_data['assetBaseId']
|
||||
if id in au.keys():
|
||||
ad = au[id]
|
||||
if ad.get('file_name') != None:
|
||||
|
@ -831,15 +831,15 @@ def start_download(asset_data, **kwargs):
|
|||
# props = utils.get_search_props()
|
||||
# props.report = str('asset ')
|
||||
if not done:
|
||||
at = asset_data['asset_type']
|
||||
at = asset_data['assetType']
|
||||
if at in ('model', 'material'):
|
||||
downloader = {'location': kwargs['model_location'],
|
||||
'rotation': kwargs['model_rotation']}
|
||||
download(asset_data, downloaders=[downloader], **kwargs)
|
||||
|
||||
elif asset_data['asset_type'] == 'scene':
|
||||
elif asset_data['assetType'] == 'scene':
|
||||
download(asset_data, **kwargs)
|
||||
elif asset_data['asset_type'] == 'brush' or asset_data['asset_type'] == 'texture':
|
||||
elif asset_data['assetType'] == 'brush' or asset_data['assetType'] == 'texture':
|
||||
download(asset_data)
|
||||
|
||||
|
||||
|
@ -911,10 +911,10 @@ class BlenderkitDownloadOperator(bpy.types.Operator):
|
|||
au = s.get('assets used')
|
||||
if au == None:
|
||||
s['assets used'] = {}
|
||||
if asset_data['asset_base_id'] in s.get('assets used'):
|
||||
asset_data = s['assets used'][asset_data['asset_base_id']].to_dict()
|
||||
if asset_data['assetBaseId'] in s.get('assets used'):
|
||||
asset_data = s['assets used'][asset_data['assetBaseId']].to_dict()
|
||||
|
||||
atype = asset_data['asset_type']
|
||||
atype = asset_data['assetType']
|
||||
if bpy.context.mode != 'OBJECT' and (
|
||||
atype == 'model' or atype == 'material') and bpy.context.view_layer.objects.active is not None:
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
@ -953,7 +953,9 @@ def register_download():
|
|||
bpy.utils.register_class(BlenderkitKillDownloadOperator)
|
||||
bpy.app.handlers.load_post.append(scene_load)
|
||||
bpy.app.handlers.save_pre.append(scene_save)
|
||||
bpy.app.timers.register(timer_update)
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
if user_preferences.use_timers:
|
||||
bpy.app.timers.register(timer_update)
|
||||
|
||||
|
||||
def unregister_download():
|
||||
|
|
|
@ -170,7 +170,7 @@ def extract_filename_from_url(url):
|
|||
|
||||
|
||||
def get_download_filenames(asset_data):
|
||||
dirs = get_download_dirs(asset_data['asset_type'])
|
||||
dirs = get_download_dirs(asset_data['assetType'])
|
||||
file_names = []
|
||||
# fn = asset_data['file_name'].replace('blend_', '')
|
||||
if asset_data.get('url') is not None:
|
||||
|
|
|
@ -139,7 +139,7 @@ def upload_rating(asset):
|
|||
headers = utils.get_headers(api_key)
|
||||
|
||||
bkit_ratings = asset.bkit_ratings
|
||||
# print('rating asset', asset_data['name'], asset_data['asset_base_id'])
|
||||
# print('rating asset', asset_data['name'], asset_data['assetBaseId'])
|
||||
url = paths.get_api_url() + 'assets/' + asset['asset_data']['id'] + '/rating/'
|
||||
|
||||
ratings = [
|
||||
|
@ -168,7 +168,7 @@ def upload_rating(asset):
|
|||
s = bpy.context.scene
|
||||
s['assets rated'] = s.get('assets rated', {})
|
||||
if bkit_ratings.rating_quality > 0.1 and bkit_ratings.rating_work_hours > 0.1:
|
||||
s['assets rated'][asset['asset_data']['asset_base_id']] = True
|
||||
s['assets rated'][asset['asset_data']['assetBaseId']] = True
|
||||
|
||||
|
||||
class StarRatingOperator(bpy.types.Operator):
|
||||
|
|
|
@ -101,14 +101,33 @@ def refresh_token_timer():
|
|||
|
||||
return max(3600, user_preferences.api_key_life - 3600)
|
||||
|
||||
def update_assets_data():# updates assets data on scene load.
|
||||
'''updates some properties that were changed on scenes with older assets.
|
||||
The properties were mainly changed from snake_case to CamelCase to fit the data that is coming from the server.
|
||||
'''
|
||||
for ob in bpy.context.scene.objects:
|
||||
if ob.get('asset_data') != None:
|
||||
ad = ob['asset_data']
|
||||
if not ad.get('assetBaseId'):
|
||||
ad['assetBaseId'] = ad['asset_base_id'],#this should stay ONLY for compatibility with older scenes
|
||||
ad['assetType'] = ad['asset_type'],#this should stay ONLY for compatibility with older scenes
|
||||
ad['canDownload'] = ad['can_download'],#this should stay ONLY for compatibility with older scenes
|
||||
ad['verificationStatus'] = ad['verification_status'],#this should stay ONLY for compatibility with older scenes
|
||||
ad['author'] = {}
|
||||
ad['author']['id'] = ad['author_id'],#this should stay ONLY for compatibility with older scenes
|
||||
|
||||
@persistent
|
||||
def scene_load(context):
|
||||
'''
|
||||
Loads categories , checks timers registration, and updates scene asset data.
|
||||
Should (probably)also update asset data from server (after user consent)
|
||||
'''
|
||||
wm = bpy.context.window_manager
|
||||
fetch_server_data()
|
||||
categories.load_categories()
|
||||
if not bpy.app.timers.is_registered(refresh_token_timer):
|
||||
bpy.app.timers.register(refresh_token_timer, persistent=True, first_interval=36000)
|
||||
update_assets_data()
|
||||
|
||||
|
||||
def fetch_server_data():
|
||||
|
@ -132,6 +151,12 @@ last_clipboard = ''
|
|||
|
||||
|
||||
def check_clipboard():
|
||||
'''
|
||||
Checks clipboard for an exact string containing asset ID.
|
||||
The string is generated on www.blenderkit.com as for example here:
|
||||
https://www.blenderkit.com/get-blenderkit/54ff5c85-2c73-49e9-ba80-aec18616a408/
|
||||
'''
|
||||
|
||||
# clipboard monitoring to search assets from web
|
||||
if platform.system() != 'Linux':
|
||||
global last_clipboard
|
||||
|
@ -148,6 +173,97 @@ def check_clipboard():
|
|||
search_props.search_keywords = last_clipboard
|
||||
# don't run search after this - assigning to keywords runs the search_update function.
|
||||
|
||||
def parse_result(r):
|
||||
'''
|
||||
needed to generate some extra data in the result(by now)
|
||||
Parameters
|
||||
----------
|
||||
r - search result, also called asset_data
|
||||
'''
|
||||
scene = bpy.context.scene
|
||||
|
||||
# TODO remove this fix when filesSize is fixed.
|
||||
# this is a temporary fix for too big numbers from the server.
|
||||
try:
|
||||
r['filesSize'] = int(r['filesSize'] / 1024)
|
||||
except:
|
||||
utils.p('asset with no files-size')
|
||||
asset_type = r['assetType']
|
||||
if len(r['files']) > 0:
|
||||
|
||||
allthumbs = []
|
||||
durl, tname = None, None
|
||||
for f in r['files']:
|
||||
if f['fileType'] == 'thumbnail':
|
||||
tname = paths.extract_filename_from_url(f['fileThumbnailLarge'])
|
||||
small_tname = paths.extract_filename_from_url(f['fileThumbnail'])
|
||||
allthumbs.append(tname) # TODO just first thumb is used now.
|
||||
|
||||
tdict = {}
|
||||
for i, t in enumerate(allthumbs):
|
||||
tdict['thumbnail_%i'] = t
|
||||
if f['fileType'] == 'blend':
|
||||
durl = f['downloadUrl'].split('?')[0]
|
||||
# fname = paths.extract_filename_from_url(f['filePath'])
|
||||
if durl and tname:
|
||||
|
||||
tooltip = generate_tooltip(r)
|
||||
# for some reason, the id was still int on some occurances. investigate this.
|
||||
r['author']['id'] = str(r['author']['id'])
|
||||
|
||||
#some helper props, but generally shouldn't be renaming/duplifiying original properties,
|
||||
# so blender's data is same as on server.
|
||||
asset_data = {'thumbnail': tname,
|
||||
'thumbnail_small': small_tname,
|
||||
# 'thumbnails':allthumbs,
|
||||
'download_url': durl,
|
||||
# 'id': r['id'],
|
||||
# 'asset_base_id': r['assetBaseId'],#this should stay ONLY for compatibility with older scenes
|
||||
# 'name': r['name'],
|
||||
# 'asset_type': r['assetType'], #this should stay ONLY for compatibility with older scenes
|
||||
'tooltip': tooltip,
|
||||
# 'tags': r['tags'],
|
||||
# 'can_download': r.get('canDownload', True),#this should stay ONLY for compatibility with older scenes
|
||||
# 'verification_status': r['verificationStatus'],#this should stay ONLY for compatibility with older scenes
|
||||
# 'author_id': r['author']['id'],#this should stay ONLY for compatibility with older scenes
|
||||
# 'author': r['author']['firstName'] + ' ' + r['author']['lastName']
|
||||
# 'description': r['description'],
|
||||
}
|
||||
asset_data['downloaded'] = 0
|
||||
|
||||
# parse extra params needed for blender here
|
||||
params = utils.params_to_dict(r['parameters'])
|
||||
|
||||
if asset_type == 'model':
|
||||
if params.get('boundBoxMinX') != None:
|
||||
bbox = {
|
||||
'bbox_min': (
|
||||
float(params['boundBoxMinX']),
|
||||
float(params['boundBoxMinY']),
|
||||
float(params['boundBoxMinZ'])),
|
||||
'bbox_max': (
|
||||
float(params['boundBoxMaxX']),
|
||||
float(params['boundBoxMaxY']),
|
||||
float(params['boundBoxMaxZ']))
|
||||
}
|
||||
|
||||
else:
|
||||
bbox = {
|
||||
'bbox_min': (-.5, -.5, 0),
|
||||
'bbox_max': (.5, .5, 1)
|
||||
}
|
||||
asset_data.update(bbox)
|
||||
if asset_type == 'material':
|
||||
asset_data['texture_size_meters'] = params.get('textureSizeMeters', 1.0)
|
||||
|
||||
asset_data.update(tdict)
|
||||
if r['assetBaseId'] in scene.get('assets used', {}).keys():
|
||||
asset_data['downloaded'] = 100
|
||||
|
||||
#attempt to switch to use original data gradually, since the parsing as itself should become obsolete.
|
||||
asset_data.update(r)
|
||||
return asset_data
|
||||
|
||||
|
||||
# @bpy.app.handlers.persistent
|
||||
def timer_update():
|
||||
|
@ -221,84 +337,8 @@ def timer_update():
|
|||
if ok:
|
||||
bpy.ops.object.run_assetbar_fix_context()
|
||||
for r in rdata['results']:
|
||||
# TODO remove this fix when filesSize is fixed.
|
||||
# this is a temporary fix for too big numbers from the server.
|
||||
try:
|
||||
r['filesSize'] = int(r['filesSize'] / 1024)
|
||||
except:
|
||||
utils.p('asset with no files-size')
|
||||
if r['assetType'] == asset_type:
|
||||
if len(r['files']) > 0:
|
||||
furl = None
|
||||
tname = None
|
||||
allthumbs = []
|
||||
durl, tname = None, None
|
||||
for f in r['files']:
|
||||
if f['fileType'] == 'thumbnail':
|
||||
tname = paths.extract_filename_from_url(f['fileThumbnailLarge'])
|
||||
small_tname = paths.extract_filename_from_url(f['fileThumbnail'])
|
||||
allthumbs.append(tname) # TODO just first thumb is used now.
|
||||
|
||||
tdict = {}
|
||||
for i, t in enumerate(allthumbs):
|
||||
tdict['thumbnail_%i'] = t
|
||||
if f['fileType'] == 'blend':
|
||||
durl = f['downloadUrl'].split('?')[0]
|
||||
# fname = paths.extract_filename_from_url(f['filePath'])
|
||||
if durl and tname:
|
||||
|
||||
tooltip = generate_tooltip(r)
|
||||
# for some reason, the id was still int on some occurances. investigate this.
|
||||
r['author']['id'] = str(r['author']['id'])
|
||||
|
||||
asset_data = {'thumbnail': tname,
|
||||
'thumbnail_small': small_tname,
|
||||
# 'thumbnails':allthumbs,
|
||||
'download_url': durl,
|
||||
'id': r['id'],
|
||||
'asset_base_id': r['assetBaseId'],
|
||||
'name': r['name'],
|
||||
'asset_type': r['assetType'],
|
||||
'tooltip': tooltip,
|
||||
'tags': r['tags'],
|
||||
'can_download': r.get('canDownload', True),
|
||||
'verification_status': r['verificationStatus'],
|
||||
'author_id': r['author']['id'],
|
||||
# 'author': r['author']['firstName'] + ' ' + r['author']['lastName']
|
||||
# 'description': r['description'],
|
||||
}
|
||||
asset_data['downloaded'] = 0
|
||||
|
||||
# parse extra params needed for blender here
|
||||
params = utils.params_to_dict(r['parameters'])
|
||||
|
||||
if asset_type == 'model':
|
||||
if params.get('boundBoxMinX') != None:
|
||||
bbox = {
|
||||
'bbox_min': (
|
||||
float(params['boundBoxMinX']),
|
||||
float(params['boundBoxMinY']),
|
||||
float(params['boundBoxMinZ'])),
|
||||
'bbox_max': (
|
||||
float(params['boundBoxMaxX']),
|
||||
float(params['boundBoxMaxY']),
|
||||
float(params['boundBoxMaxZ']))
|
||||
}
|
||||
|
||||
else:
|
||||
bbox = {
|
||||
'bbox_min': (-.5, -.5, 0),
|
||||
'bbox_max': (.5, .5, 1)
|
||||
}
|
||||
asset_data.update(bbox)
|
||||
if asset_type == 'material':
|
||||
asset_data['texture_size_meters'] = params.get('textureSizeMeters', 1.0)
|
||||
|
||||
asset_data.update(tdict)
|
||||
if r['assetBaseId'] in scene.get('assets used', {}).keys():
|
||||
asset_data['downloaded'] = 100
|
||||
|
||||
result_field.append(asset_data)
|
||||
asset_data = parse_result(r)
|
||||
result_field.append(asset_data)
|
||||
|
||||
# results = rdata['results']
|
||||
s[search_name] = result_field
|
||||
|
@ -846,18 +886,18 @@ class Searcher(threading.Thread):
|
|||
|
||||
# filter results here:
|
||||
# todo remove this in future
|
||||
nresults = []
|
||||
for d in rdata.get('results', []):
|
||||
# TODO this code is for filtering brush types, should vanish after we implement filter in Elastic
|
||||
mode = None
|
||||
if query['asset_type'] == 'brush':
|
||||
for p in d['parameters']:
|
||||
if p['parameterType'] == 'mode':
|
||||
mode = p['value']
|
||||
if query['asset_type'] != 'brush' or (
|
||||
query.get('mode') != None and query['mode']) == mode:
|
||||
nresults.append(d)
|
||||
rdata['results'] = nresults
|
||||
# nresults = []
|
||||
# for d in rdata.get('results', []):
|
||||
# # TODO this code is for filtering brush types, should vanish after we implement filter in Elastic
|
||||
# mode = None
|
||||
# if query['asset_type'] == 'brush':
|
||||
# for p in d['parameters']:
|
||||
# if p['parameterType'] == 'mode':
|
||||
# mode = p['value']
|
||||
# if query['asset_type'] != 'brush' or (
|
||||
# query.get('mode') != None and query['mode']) == mode:
|
||||
# nresults.append(d)
|
||||
# rdata['results'] = nresults
|
||||
|
||||
# print('number of results: ', len(rdata.get('results', [])))
|
||||
if self.stopped():
|
||||
|
@ -1307,7 +1347,9 @@ def register_search():
|
|||
for c in classes:
|
||||
bpy.utils.register_class(c)
|
||||
|
||||
bpy.app.timers.register(timer_update)
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
if user_preferences.use_timers:
|
||||
bpy.app.timers.register(timer_update)
|
||||
|
||||
categories.load_categories()
|
||||
|
||||
|
@ -1317,5 +1359,6 @@ def unregister_search():
|
|||
|
||||
for c in classes:
|
||||
bpy.utils.unregister_class(c)
|
||||
|
||||
if bpy.app.timers.is_registered(timer_update):
|
||||
bpy.app.timers.unregister(timer_update)
|
||||
|
|
|
@ -30,8 +30,10 @@ import queue
|
|||
|
||||
@persistent
|
||||
def scene_load(context):
|
||||
if not (bpy.app.timers.is_registered(queue_worker)):
|
||||
bpy.app.timers.register(queue_worker)
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
if user_preferences.use_timers:
|
||||
if not (bpy.app.timers.is_registered(queue_worker)):
|
||||
bpy.app.timers.register(queue_worker)
|
||||
|
||||
|
||||
def get_queue():
|
||||
|
|
|
@ -257,7 +257,7 @@ def draw_ratings_bgl():
|
|||
# b = utils.get_active_brush()
|
||||
# thumbnail_image = b.icon_filepath
|
||||
|
||||
directory = paths.get_temp_dir('%s_search' % asset_data['asset_type'])
|
||||
directory = paths.get_temp_dir('%s_search' % asset_data['assetType'])
|
||||
tpath = os.path.join(directory, asset_data['thumbnail_small'])
|
||||
|
||||
img = utils.get_hidden_image(tpath, 'rating_preview')
|
||||
|
@ -274,7 +274,7 @@ def draw_ratings_bgl():
|
|||
ui.rating_ui_width + ui.margin,
|
||||
ui.rating_ui_height + 2 * ui.margin + font_size,
|
||||
bgcol)
|
||||
if asset_data['asset_type'] == 'model':
|
||||
if asset_data['assetType'] == 'model':
|
||||
ui_img_name = 'rating_ui.png'
|
||||
else:
|
||||
ui_img_name = 'rating_ui_empty.png'
|
||||
|
@ -303,7 +303,7 @@ def draw_ratings_bgl():
|
|||
img = utils.get_thumbnail('bar_slider.png')
|
||||
# for a in range(0,11):
|
||||
if work_hours > 0.2:
|
||||
if asset_data['asset_type'] == 'model':
|
||||
if asset_data['assetType'] == 'model':
|
||||
complexity = math.log2(work_hours) + 2 # real complexity
|
||||
complexity = (1. / 9.) * (complexity - 1) * ui.workhours_bar_x_max
|
||||
else:
|
||||
|
@ -321,7 +321,7 @@ def draw_ratings_bgl():
|
|||
# (0.5,1,2,4,8,16,32,64,128,256)
|
||||
# ratings have to be different for models and brushes+materials.
|
||||
|
||||
scalevalues, xs = get_rating_scalevalues(asset_data['asset_type'])
|
||||
scalevalues, xs = get_rating_scalevalues(asset_data['assetType'])
|
||||
for v, x in zip(scalevalues, xs):
|
||||
ui_bgl.draw_rect(ui.rating_x + ui.workhours_bar_x + int(
|
||||
x * ui.workhours_bar_x_max) - 1 + ui.workhours_bar_slider_size / 2,
|
||||
|
@ -650,7 +650,7 @@ def draw_callback_3d_progress(self, context):
|
|||
tcom = threaddata[2]
|
||||
if tcom.passargs.get('downloaders'):
|
||||
for d in tcom.passargs['downloaders']:
|
||||
if asset_data['asset_type'] == 'model':
|
||||
if asset_data['assetType'] == 'model':
|
||||
draw_bbox(d['location'], d['rotation'], asset_data['bbox_min'], asset_data['bbox_max'],
|
||||
progress=tcom.progress)
|
||||
|
||||
|
@ -669,7 +669,7 @@ def draw_callback_2d_progress(self, context):
|
|||
asset_data = threaddata[1]
|
||||
tcom = threaddata[2]
|
||||
|
||||
directory = paths.get_temp_dir('%s_search' % asset_data['asset_type'])
|
||||
directory = paths.get_temp_dir('%s_search' % asset_data['assetType'])
|
||||
tpath = os.path.join(directory, asset_data['thumbnail_small'])
|
||||
img = utils.get_hidden_image(tpath, asset_data['id'])
|
||||
|
||||
|
@ -679,7 +679,7 @@ def draw_callback_2d_progress(self, context):
|
|||
loc = view3d_utils.location_3d_to_region_2d(bpy.context.region, bpy.context.space_data.region_3d,
|
||||
d['location'])
|
||||
if loc is not None:
|
||||
if asset_data['asset_type'] == 'model':
|
||||
if asset_data['assetType'] == 'model':
|
||||
# models now draw with star trek mode, no need to draw percent for the image.
|
||||
draw_downloader(loc[0], loc[1], percent=tcom.progress, img=img)
|
||||
else:
|
||||
|
@ -823,11 +823,11 @@ def draw_callback_2d_search(self, context):
|
|||
# object type icons - just a test..., adds clutter/ not so userfull:
|
||||
# icons = ('type_finished.png', 'type_template.png', 'type_particle_system.png')
|
||||
|
||||
if (result.get('can_download', True)) == 0:
|
||||
if (result.get('canDownload', True)) == 0:
|
||||
img = utils.get_thumbnail('locked.png')
|
||||
ui_bgl.draw_image(x + 2, y + 2, 24, 24, img, 1)
|
||||
|
||||
v_icon = verification_icons[result.get('verification_status', 'validated')]
|
||||
v_icon = verification_icons[result.get('verificationStatus', 'validated')]
|
||||
if v_icon is not None:
|
||||
img = utils.get_thumbnail(v_icon)
|
||||
ui_bgl.draw_image(x + ui_props.thumb_size - 26, y + 2, 24, 24, img, 1)
|
||||
|
@ -881,7 +881,7 @@ def draw_callback_2d_search(self, context):
|
|||
gimg = None
|
||||
atip = ''
|
||||
if bpy.context.window_manager.get('bkit authors') is not None:
|
||||
a = bpy.context.window_manager['bkit authors'].get(r['author_id'])
|
||||
a = bpy.context.window_manager['bkit authors'].get(r['author']['id'])
|
||||
if a is not None and a != '':
|
||||
if a.get('gravatarImg') is not None:
|
||||
gimg = utils.get_hidden_image(a['gravatarImg'], a['gravatarHash'])
|
||||
|
@ -999,7 +999,7 @@ def is_rating_possible():
|
|||
b = utils.get_active_brush()
|
||||
ad = b.get('asset_data')
|
||||
if ad is not None:
|
||||
rated = bpy.context.scene['assets rated'].get(ad['asset_base_id'])
|
||||
rated = bpy.context.scene['assets rated'].get(ad['assetBaseId'])
|
||||
return True, rated, b, ad
|
||||
if ao is not None:
|
||||
ad = None
|
||||
|
@ -1008,7 +1008,7 @@ def is_rating_possible():
|
|||
while ad is None or (ad is None and ao_check.parent is not None):
|
||||
ad = ao_check.get('asset_data')
|
||||
if ad is not None:
|
||||
rated = bpy.context.scene['assets rated'].get(ad['asset_base_id'])
|
||||
rated = bpy.context.scene['assets rated'].get(ad['assetBaseId'])
|
||||
# originally hidden for already rated assets
|
||||
return True, rated, ao_check, ad
|
||||
elif ao_check.parent is not None:
|
||||
|
@ -1021,7 +1021,7 @@ def is_rating_possible():
|
|||
if m is not None:
|
||||
ad = m.get('asset_data')
|
||||
if ad is not None:
|
||||
rated = bpy.context.scene['assets rated'].get(ad['asset_base_id'])
|
||||
rated = bpy.context.scene['assets rated'].get(ad['assetBaseId'])
|
||||
return True, rated, m, ad
|
||||
|
||||
# if t>2 and t<2.5:
|
||||
|
@ -1092,7 +1092,7 @@ def interact_rating(r, mx, my, event):
|
|||
if ui.dragging_rating_work_hours:
|
||||
xv = rmx - ui.workhours_bar_x - ui.workhours_bar_slider_size / 2
|
||||
ratio = xv / ui.workhours_bar_x_max
|
||||
if asset_data['asset_type'] == 'model':
|
||||
if asset_data['assetType'] == 'model':
|
||||
wh_log2 = ratio * 9 - 1
|
||||
wh = 2 ** wh_log2
|
||||
else:
|
||||
|
@ -1255,6 +1255,14 @@ class AssetBarOperator(bpy.types.Operator):
|
|||
|
||||
areas = []
|
||||
|
||||
|
||||
#timers testing - seems timers might be causing crashes. testing it this way now.
|
||||
if not user_preferences.use_timers:
|
||||
search.timer_update()
|
||||
download.timer_update()
|
||||
tasks_queue.queue_worker()
|
||||
bg_blender.bg_update()
|
||||
|
||||
if bpy.context.scene != self.scene:
|
||||
self.exit_modal()
|
||||
return {'CANCELLED'}
|
||||
|
@ -1505,7 +1513,7 @@ class AssetBarOperator(bpy.types.Operator):
|
|||
# check if asset is locked and let the user know in that case
|
||||
asset_search_index = ui_props.active_index
|
||||
asset_data = sr[asset_search_index]
|
||||
if not asset_data['can_download']:
|
||||
if not asset_data.get('canDownload'):
|
||||
message = "Let's support asset creators and Blender development."
|
||||
link_text = 'Unlock the asset.'
|
||||
url = paths.get_bkit_url() + '/get-blenderkit/' + asset_data['id'] + '/?from_addon'
|
||||
|
@ -1667,7 +1675,7 @@ class AssetBarOperator(bpy.types.Operator):
|
|||
if event.type == 'W' and ui_props.active_index > -1:
|
||||
sr = bpy.context.scene['search results']
|
||||
asset_data = sr[ui_props.active_index]
|
||||
a = bpy.context.window_manager['bkit authors'].get(asset_data['author_id'])
|
||||
a = bpy.context.window_manager['bkit authors'].get(asset_data['author']['id'])
|
||||
if a is not None:
|
||||
utils.p('author:', a)
|
||||
if a.get('aboutMeUrl') is not None:
|
||||
|
@ -1676,7 +1684,7 @@ class AssetBarOperator(bpy.types.Operator):
|
|||
if event.type == 'A' and ui_props.active_index > -1:
|
||||
sr = bpy.context.scene['search results']
|
||||
asset_data = sr[ui_props.active_index]
|
||||
a = asset_data['author_id']
|
||||
a = asset_data['author']['id']
|
||||
if a is not None:
|
||||
sprops = utils.get_search_props()
|
||||
sprops.search_keywords = ''
|
||||
|
|
|
@ -94,15 +94,19 @@ def draw_ratings(layout, context):
|
|||
# op = row.operator("object.blenderkit_rating_upload", text="Send rating", icon='URL')
|
||||
# return op
|
||||
|
||||
|
||||
def draw_not_logged_in(source):
|
||||
title = "User not logged in"
|
||||
|
||||
def draw_message(source, context):
|
||||
layout = source.layout
|
||||
label_multiline(layout, text='Please login or sign up '
|
||||
'to upload files.')
|
||||
'to upload files.')
|
||||
draw_login_buttons(layout)
|
||||
|
||||
bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO')
|
||||
|
||||
|
||||
def draw_upload_common(layout, props, asset_type, context):
|
||||
op = layout.operator("wm.url_open", text="Read upload instructions",
|
||||
icon='QUESTION')
|
||||
|
@ -434,6 +438,7 @@ class VIEW3D_PT_blenderkit_model_properties(Panel):
|
|||
|
||||
draw_panel_model_rating(self, context)
|
||||
|
||||
draw_asset_context_menu(self, context, ad)
|
||||
# if 'rig' in ad['tags']:
|
||||
# # layout.label(text = 'can make proxy')
|
||||
# layout.operator('object.blenderkit_make_proxy', text = 'Make Armature proxy')
|
||||
|
@ -494,9 +499,9 @@ class VIEW3D_PT_blenderkit_profile(Panel):
|
|||
row = layout.row()
|
||||
row.label(text='My plan:')
|
||||
row.label(text='%s plan' % pn, icon_value=my_icon.icon_id)
|
||||
if pn =='Free':
|
||||
if pn == 'Free':
|
||||
layout.operator("wm.url_open", text="Change plan",
|
||||
icon='URL').url = paths.get_bkit_url() + paths.BLENDERKIT_PLANS
|
||||
icon='URL').url = paths.get_bkit_url() + paths.BLENDERKIT_PLANS
|
||||
|
||||
# storage statistics
|
||||
# if me.get('sumAssetFilesSize') is not None: # TODO remove this when production server has these too.
|
||||
|
@ -903,81 +908,87 @@ class VIEW3D_PT_blenderkit_unified(Panel):
|
|||
layout.label(text='not yet implemented')
|
||||
|
||||
|
||||
def draw_asset_context_menu(self, context, asset_data):
|
||||
layout = self.layout
|
||||
ui_props = context.scene.blenderkitUI
|
||||
|
||||
author_id = str(asset_data['author']['id'])
|
||||
wm = bpy.context.window_manager
|
||||
if wm.get('bkit authors') is not None:
|
||||
a = bpy.context.window_manager['bkit authors'].get(author_id)
|
||||
if a is not None:
|
||||
# utils.p('author:', a)
|
||||
if a.get('aboutMeUrl') is not None:
|
||||
op = layout.operator('wm.url_open', text="Open Author's Website")
|
||||
op.url = a['aboutMeUrl']
|
||||
|
||||
op = layout.operator('view3d.blenderkit_search', text="Show Assets By Author")
|
||||
op.keywords = ''
|
||||
op.author_id = author_id
|
||||
|
||||
op = layout.operator('view3d.blenderkit_search', text='Search Similar')
|
||||
op.keywords = asset_data['name'] + ' ' + asset_data['description'] + ' ' + ' '.join(asset_data['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
|
||||
if aob is None:
|
||||
aob = bpy.context.selected_objects[0]
|
||||
op = layout.operator('scene.blenderkit_download', text='Replace Active Models')
|
||||
op.asset_type = ui_props.asset_type
|
||||
op.asset_index = ui_props.active_index
|
||||
op.model_location = aob.location
|
||||
op.model_rotation = aob.rotation_euler
|
||||
op.target_object = aob.name
|
||||
op.material_target_slot = aob.active_material_index
|
||||
op.replace = True
|
||||
|
||||
wm = bpy.context.window_manager
|
||||
profile = wm.get('bkit profile')
|
||||
if profile is not None:
|
||||
# validation
|
||||
if utils.profile_is_validator():
|
||||
layout.label(text='Validation tools:')
|
||||
if asset_data['verificationStatus'] != 'uploaded':
|
||||
op = layout.operator('object.blenderkit_change_status', text='set Uploaded')
|
||||
op.asset_id = asset_data['id']
|
||||
op.state = 'uploaded'
|
||||
if asset_data['verificationStatus'] != 'validated':
|
||||
op = layout.operator('object.blenderkit_change_status', text='Validate')
|
||||
op.asset_id = asset_data['id']
|
||||
op.state = 'validated'
|
||||
if asset_data['verificationStatus'] != 'on_hold':
|
||||
op = layout.operator('object.blenderkit_change_status', text='Put on Hold')
|
||||
op.asset_id = asset_data['id']
|
||||
op.state = 'on_hold'
|
||||
if asset_data['verificationStatus'] != 'rejected':
|
||||
op = layout.operator('object.blenderkit_change_status', text='Reject')
|
||||
op.asset_id = asset_data['id']
|
||||
op.state = 'rejected'
|
||||
|
||||
if author_id == str(profile['user']['id']):
|
||||
layout.label(text='Management tools:')
|
||||
row = layout.row()
|
||||
row.operator_context = 'INVOKE_DEFAULT'
|
||||
op = row.operator('object.blenderkit_change_status', text='Delete')
|
||||
op.asset_id = asset_data['id']
|
||||
op.state = 'deleted'
|
||||
# else:
|
||||
# #not an author - can rate
|
||||
# draw_ratings(layout, context)
|
||||
|
||||
|
||||
class OBJECT_MT_blenderkit_asset_menu(bpy.types.Menu):
|
||||
bl_label = "Asset options:"
|
||||
bl_idname = "OBJECT_MT_blenderkit_asset_menu"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
ui_props = context.scene.blenderkitUI
|
||||
|
||||
sr = bpy.context.scene['search results']
|
||||
# sr = bpy.context.scene['search results']
|
||||
sr = bpy.context.scene['search results orig']['results']
|
||||
asset_data = sr[ui_props.active_index]
|
||||
author_id = str(asset_data['author']['id'])
|
||||
|
||||
wm = bpy.context.window_manager
|
||||
if wm.get('bkit authors') is not None:
|
||||
a = bpy.context.window_manager['bkit authors'].get(author_id)
|
||||
if a is not None:
|
||||
# utils.p('author:', a)
|
||||
if a.get('aboutMeUrl') is not None:
|
||||
op = layout.operator('wm.url_open', text="Open Author's Website")
|
||||
op.url = a['aboutMeUrl']
|
||||
|
||||
op = layout.operator('view3d.blenderkit_search', text="Show Assets By Author")
|
||||
op.keywords = ''
|
||||
op.author_id = author_id
|
||||
|
||||
op = layout.operator('view3d.blenderkit_search', text='Search Similar')
|
||||
op.keywords = asset_data['name'] + ' ' + asset_data['description'] + ' ' + ' '.join(asset_data['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
|
||||
if aob is None:
|
||||
aob = bpy.context.selected_objects[0]
|
||||
op = layout.operator('scene.blenderkit_download', text='Replace Active Models')
|
||||
op.asset_type = ui_props.asset_type
|
||||
op.asset_index = ui_props.active_index
|
||||
op.model_location = aob.location
|
||||
op.model_rotation = aob.rotation_euler
|
||||
op.target_object = aob.name
|
||||
op.material_target_slot = aob.active_material_index
|
||||
op.replace = True
|
||||
|
||||
wm = bpy.context.window_manager
|
||||
profile = wm.get('bkit profile')
|
||||
if profile is not None:
|
||||
# validation
|
||||
if utils.profile_is_validator():
|
||||
layout.label(text='Validation tools:')
|
||||
if asset_data['verificationStatus'] != 'uploaded':
|
||||
op = layout.operator('object.blenderkit_change_status', text='set Uploaded')
|
||||
op.asset_id = asset_data['id']
|
||||
op.state = 'uploaded'
|
||||
if asset_data['verificationStatus'] != 'validated':
|
||||
op = layout.operator('object.blenderkit_change_status', text='Validate')
|
||||
op.asset_id = asset_data['id']
|
||||
op.state = 'validated'
|
||||
if asset_data['verificationStatus'] != 'on_hold':
|
||||
op = layout.operator('object.blenderkit_change_status', text='Put on Hold')
|
||||
op.asset_id = asset_data['id']
|
||||
op.state = 'on_hold'
|
||||
if asset_data['verificationStatus'] != 'rejected':
|
||||
op = layout.operator('object.blenderkit_change_status', text='Reject')
|
||||
op.asset_id = asset_data['id']
|
||||
op.state = 'rejected'
|
||||
|
||||
if author_id == str(profile['user']['id']):
|
||||
layout.label(text='Management tools:')
|
||||
row = layout.row()
|
||||
row.operator_context = 'INVOKE_DEFAULT'
|
||||
op = row.operator('object.blenderkit_change_status', text='Delete')
|
||||
op.asset_id = asset_data['id']
|
||||
op.state = 'deleted'
|
||||
# else:
|
||||
# #not an author - can rate
|
||||
# draw_ratings(layout, context)
|
||||
draw_asset_context_menu(self, context, asset_data)
|
||||
|
||||
|
||||
class SetCategoryOperator(bpy.types.Operator):
|
||||
|
|
|
@ -822,11 +822,12 @@ class AssetVerificationStatusChange(Operator):
|
|||
|
||||
for r in sr:
|
||||
if r['id'] == self.asset_id:
|
||||
r['verification_status'] = self.state
|
||||
r['verificationStatus'] = self.state
|
||||
for r in sro:
|
||||
if r['id'] == self.asset_id:
|
||||
r['verificationStatus'] = self.state
|
||||
|
||||
|
||||
thread = threading.Thread(target=verification_status_change_thread,
|
||||
args=(self.asset_id, self.state, preferences.api_key))
|
||||
thread.start()
|
||||
|
|
Loading…
Reference in New Issue