BlenderKit lots of fixes for asset bar

lock icons are back
thumbnail update partially fixed.
This commit is contained in:
Vilem Duha 2021-10-22 08:24:39 +02:00
parent 79a0f96101
commit 259ab9a873
6 changed files with 108 additions and 52 deletions

View File

@ -24,14 +24,6 @@ from bpy.props import (
)
def draw_callback_tooltip(self, context):
if self.draw_tooltip:
wm = bpy.context.window_manager
sr = wm.get('search results')
r = sr[self.active_index]
ui.draw_tooltip_with_author(r, 0, 500)
def get_area_height(self):
if type(self.context) != dict:
if self.context is None:
@ -90,14 +82,14 @@ def modal_inside(self,context,event):
if event.type in {"ESC"}:
self.finish()
x = event.mouse_region_x
y = event.mouse_region_y
if event.type == 'WHEELUPMOUSE' and self.panel.is_in_rect(x, y):
self.mouse_x = event.mouse_region_x
self.mouse_y = event.mouse_region_y
if event.type == 'WHEELUPMOUSE' and self.panel.is_in_rect(self.mouse_x, self.mouse_y):
self.scroll_offset -= 5
self.scroll_update()
return {'RUNNING_MODAL'}
elif event.type == 'WHEELDOWNMOUSE' and self.panel.is_in_rect(x, y):
elif event.type == 'WHEELDOWNMOUSE' and self.panel.is_in_rect(self.mouse_x, self.mouse_y):
self.scroll_offset += 5
self.scroll_update()
return {'RUNNING_MODAL'}
@ -409,7 +401,9 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
self.position_and_hide_buttons()
self.button_close.set_location(self.bar_width - self.other_button_size, 0)
self.button_close.set_location(self.bar_width - self.other_button_size, -self.other_button_size)
if hasattr(self,'button_notifications'):
self.button_notifications.set_location(self.bar_width - self.other_button_size*2, -self.other_button_size)
self.button_scroll_up.set_location(self.bar_width, 0)
self.panel.width = self.bar_width
self.panel.height = self.bar_height
@ -543,7 +537,7 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
#notifications
if not comments_utils.check_notifications_read():
self.button_notifications = BL_UI_Button(self.bar_width - self.other_button_size, self.bar_height, self.other_button_size,
self.button_notifications = BL_UI_Button(self.bar_width - self.other_button_size*2, -self.other_button_size, self.other_button_size,
self.other_button_size)
self.button_notifications.bg_color = button_bg_color
self.button_notifications.hover_bg_color = button_hover_color
@ -568,6 +562,8 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
asset_y = self.assetbar_margin + y * (self.button_size)
button_idx = x + y * self.wcount
asset_idx = button_idx + self.scroll_offset
if len(self.asset_buttons)<=button_idx:
break
button = self.asset_buttons[button_idx]
button.set_location(asset_x, asset_y)
button.validation_icon.set_location(
@ -738,11 +734,11 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
for r in bpy.context.area.regions:
if r.type == 'UI':
properties_width = r.width
tooltip_x = min(int(widget.x_screen + widget.width),
tooltip_x = min(int(widget.x_screen),
int(bpy.context.region.width - self.tooltip_panel.width - properties_width))
tooltip_y = int(widget.y_screen + widget.height)
# self.init_tooltip()
self.tooltip_panel.update(tooltip_x, tooltip_y)
self.tooltip_panel.set_location(tooltip_x, tooltip_y)
self.tooltip_panel.layout_widgets()
# print(tooltip_x, tooltip_y)
# bpy.ops.wm.blenderkit_asset_popup('INVOKE_DEFAULT')
@ -756,6 +752,13 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
ui_props.draw_tooltip = False
self.draw_tooltip = False
self.hide_tooltip()
#popup asset card on mouse down
# if utils.experimental_enabled():
# h = widget.get_area_height()
# print(h,h-self.mouse_y,self.panel.y_screen, self.panel.y,widget.y_screen, widget.y)
# if utils.experimental_enabled() and self.mouse_y<widget.y_screen:
# self.active_index = widget.button_index + self.scroll_offset
# bpy.ops.wm.blenderkit_asset_popup('INVOKE_DEFAULT')
def drag_drop_asset(self, widget):
bpy.ops.view3d.asset_drag_drop('INVOKE_DEFAULT', asset_search_index=widget.search_index + self.scroll_offset)
@ -781,13 +784,20 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
blenderkit.search.search(get_next=True)
def update_validation_icon(self, asset_button, asset_data):
v_icon = ui.verification_icons[asset_data.get('verificationStatus', 'validated')]
if v_icon is not None:
img_fp = paths.get_addon_thumbnail_path(v_icon)
asset_button.validation_icon.set_image(img_fp)
asset_button.validation_icon.visible = True
if utils.profile_is_validator():
v_icon = ui.verification_icons[asset_data.get('verificationStatus', 'validated')]
if v_icon is not None:
img_fp = paths.get_addon_thumbnail_path(v_icon)
asset_button.validation_icon.set_image(img_fp)
asset_button.validation_icon.visible = True
else:
asset_button.validation_icon.visible = False
else:
asset_button.validation_icon.visible = False
if asset_data.get('canDownload', True) == 0:
img_fp = paths.get_addon_thumbnail_path('locked.png')
asset_button.validation_icon.set_image(img_fp)
else:
asset_button.validation_icon.visible = False
def update_images(self):
sr = bpy.context.window_manager.get('search results')
@ -804,7 +814,7 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator):
# show indices for debug purposes
# asset_button.text = str(asset_button.asset_index)
img = bpy.data.images.get(iname)
if not img:
if img is None or len(img.pixels) == 0:
img_filepath = paths.get_addon_thumbnail_path('thumbnail_notready.jpg')
else:
img_filepath = img.filepath

View File

@ -135,41 +135,59 @@ def get_comments(asset_id, api_key):
def store_notifications_local(notifications):
bpy.context.window_manager['bkit notifications'] = notifications
def count_unread_notifications():
notifications = bpy.context.window_manager.get('bkit notifications')
if notifications is None:
return 0
unread = 0
for n in notifications:
if n['unread'] == 1:
unread +=1
print('counted', unread)
return unread
def check_notifications_read():
'''checks if all notifications were already read, and removes them if so'''
all_read = True
notifications = bpy.context.window_manager.get('bkit notifications')
if notifications is None:
return True
for n in notifications:
if n['unread'] == 1:
all_read = False
return False
bpy.context.window_manager['bkit notifications'] = None
return True
def get_notifications(api_key):
def get_notifications(api_key, unread_count = 1000):
'''
Retrieve ratings from BlenderKit server. Can be run from a thread
Retrieve notifications from BlenderKit server. Can be run from a thread.
Parameters
----------
asset_id
headers
api_key
unread_count
Returns
-------
ratings - dict of type:value ratings
'''
headers = utils.get_headers(api_key)
url = paths.get_api_url() + 'notifications/unread/'
params = {}
url = paths.get_api_url() + 'notifications/api/unread_count/'
r = rerequests.get(url, params=params, verify=True, headers=headers)
if r.status_code ==200:
rj = r.json()
# no new notifications?
if unread_count >= rj['unreadCount']:
return
print('notifications', unread_count, rj['unreadCount'])
url = paths.get_api_url() + 'notifications/unread/'
r = rerequests.get(url, params=params, verify=True, headers=headers)
if r is None:
return
if r.status_code == 200:
rj = r.json()
print(rj)
# store notifications - send them to task queue
tasks_queue.add_task((store_notifications_local, ([rj])))

View File

@ -104,6 +104,15 @@ def refresh_token_timer():
return max(3600, user_preferences.api_key_life - 3600)
def refresh_notifications_timer():
''' this timer gets notifications.'''
preferences = bpy.context.preferences.addons['blenderkit'].preferences
fetch_server_data()
unread_notifications_count = comments_utils.count_unread_notifications()
comments_utils.get_notifications(preferences.api_key, unread_count = unread_notifications_count)
return 300
def update_ad(ad):
if not ad.get('assetBaseId'):
try:
@ -181,6 +190,10 @@ def scene_load(context):
categories.load_categories()
if not bpy.app.timers.is_registered(refresh_token_timer) and not bpy.app.background:
bpy.app.timers.register(refresh_token_timer, persistent=True, first_interval=36000)
if utils.experimental_enabled() and not bpy.app.timers.is_registered(
refresh_notifications_timer) and not bpy.app.background:
bpy.app.timers.register(refresh_notifications_timer, persistent=True, first_interval=2)
update_assets_data()
@ -199,6 +212,7 @@ def fetch_server_data():
if bpy.context.window_manager.get('bkit_categories') is None:
categories.fetch_categories_thread(api_key, force=False)
first_time = True
last_clipboard = ''
@ -377,11 +391,15 @@ def search_timer():
ui_props = bpy.context.window_manager.blenderkitUI
search_name = f'bkit {ui_props.asset_type.lower()} search'
wm = bpy.context.window_manager
print('finishing reading thumbs')
if wm.get(search_name) is not None:
all_loaded = True
for ri, r in enumerate(wm[search_name]):
if not r.get('thumb_small_loaded'):
all_loaded = all_loaded and load_preview(r, ri)
preview_loaded = load_preview(r, ri)
print(ri, preview_loaded, all_thumbs_loaded)
all_loaded = all_loaded and preview_loaded
all_thumbs_loaded = all_loaded
global search_threads
@ -434,6 +452,7 @@ def search_timer():
if ok:
ui_props = bpy.context.window_manager.blenderkitUI
orig_len = len(result_field)
print('reading from thread')
for ri, r in enumerate(rdata['results']):
asset_data = parse_result(r)
@ -487,13 +506,9 @@ def search_timer():
def load_preview(asset, index):
scene = bpy.context.scene
# FIRST START SEARCH
props = bpy.context.window_manager.blenderkitUI
directory = paths.get_temp_dir('%s_search' % props.asset_type.lower())
s = bpy.context.scene
results = bpy.context.window_manager.get('search results')
loaded = True
tpath = os.path.join(directory, asset['thumbnail_small'])
if not asset['thumbnail_small'] or asset['thumbnail_small'] == '' or not os.path.exists(tpath):
@ -505,7 +520,7 @@ def load_preview(asset, index):
# if os.path.exists(tpath): # sometimes we are unlucky...
img = bpy.data.images.get(iname)
if img is None:
if img is None or len(img.pixels) == 0:
if not os.path.exists(tpath):
return False
# wrap into try statement since sometimes
@ -837,8 +852,6 @@ def get_profile():
a = bpy.context.window_manager.get('bkit profile')
thread = threading.Thread(target=fetch_profile, args=(preferences.api_key,), daemon=True)
thread.start()
if utils.experimental_enabled():
comments_utils.get_notifications(preferences.api_key)
return a
@ -1315,16 +1328,18 @@ def get_search_simple(parameters, filepath=None, page_size=100, max_results=1000
bk_logger.info(f'retrieved {len(results)} assets from elastic search')
return results
def get_single_asset(asset_base_id):
preferences = bpy.context.preferences.addons['blenderkit'].preferences
params = {
'asset_base_id': asset_base_id
}
results = get_search_simple(params, api_key=preferences.api_key)
if len(results)>0:
if len(results) > 0:
return results[0]
return None
def search(category='', get_next=False, author_id=''):
''' initialize searching'''
global search_start_time

View File

@ -1903,7 +1903,7 @@ class RunAssetBarWithContext(bpy.types.Operator):
C_dict = utils.get_fake_context(context)
if C_dict.get('window'): # no 3d view, no asset bar.
preferences = bpy.context.preferences.addons['blenderkit'].preferences
if preferences.experimental_features:
if 1:# preferences.experimental_features:
bpy.ops.view3d.blenderkit_asset_bar_widget(C_dict, 'INVOKE_REGION_WIN', keep_running=self.keep_running,
do_search=self.do_search)

View File

@ -334,7 +334,7 @@ def draw_assetbar_show_hide(layout, props):
ttip = 'Click to Show Asset Bar'
preferences = bpy.context.preferences.addons['blenderkit'].preferences
if preferences.experimental_features:
if 1:#preferences.experimental_features:
op = layout.operator('view3d.blenderkit_asset_bar_widget', text='', icon=icon)
else:
op = layout.operator('view3d.blenderkit_asset_bar', text='', icon=icon)
@ -1438,6 +1438,13 @@ 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 author_id == str(profile['user']['id']):
row.operator_context = 'EXEC_DEFAULT'
op = layout.operator('wm.blenderkit_url', text='Edit Metadata (browser)')
op.url = paths.get_bkit_url() + paths.BLENDERKIT_USER_ASSETS + f"/{asset_data['assetBaseId']}/?edit#"
row.operator_context = 'INVOKE_DEFAULT'
if asset_data['assetType'] == 'model':
op = layout.operator('object.blenderkit_regenerate_thumbnail', text='Regenerate thumbnail')
op.asset_index = ui_props.active_index
@ -1957,7 +1964,11 @@ class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties):
row.scale_y = 3
ui_props = bpy.context.window_manager.blenderkitUI
row.prop(ui_props, 'drag_init_button', icon='MOUSE_LMB_DRAG', text='Click / Drag from here', emboss=True)
if self.asset_data.get('canDownload', True):
row.prop(ui_props, 'drag_init_button', icon='MOUSE_LMB_DRAG', text='Click / Drag from here', emboss=True)
else:
op = layout.operator('wm.blenderkit_url', text='Unlock this asset', icon = 'UNLOCKED')
op.url = paths.get_bkit_url() + '/get-blenderkit/' + self.asset_data['id'] + '/?from_addon=True'
def draw_menu_desc_author(self, context, layout, width=330):
box = layout.column()
@ -2026,13 +2037,14 @@ class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties):
def draw_comment(self, context, layout, comment, width=330):
box = layout.box()
box.emboss = 'NORMAL'
row = box.row()
split = row.split(factor = 0.8)
is_moderator = comment['userModerator']
if is_moderator:
role_text = f" - moderator"
else:
role_text = ""
box.label(text=f"{comment['submitDate']} - {comment['userName']}{role_text}")
utils.label_multiline(box, text=comment['comment'], width=width)
split.label(text=f"{comment['submitDate']} - {comment['userName']}{role_text}")
removal = False
likes = 0
dislikes = 0
@ -2043,13 +2055,15 @@ class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties):
dislikes += 1
if l['flag'] == 'removal':
removal = True
row = box.row()
row.label(text=str(likes), icon='TRIA_UP')
row.label(text=str(dislikes), icon='TRIA_DOWN')
# row = box.row()
split1 = split.split()
split1.label(text=str(likes), icon='TRIA_UP')
split1.label(text=str(dislikes), icon='TRIA_DOWN')
if removal:
row.label(text='', icon='ERROR')
utils.label_multiline(box, text=comment['comment'], width=width)
# box.label(text=str(comment['flags']))
def draw(self, context):
@ -2316,7 +2330,7 @@ def draw_panel_categories(self, context):
ctext = '%s (%i)' % (c['name'], c['assetCount'])
preferences = bpy.context.preferences.addons['blenderkit'].preferences
if preferences.experimental_features:
if 1:#preferences.experimental_features:
op = row.operator('view3d.blenderkit_asset_bar_widget', text=ctext)
else:
op = row.operator('view3d.blenderkit_asset_bar', text=ctext)

View File

@ -62,7 +62,6 @@ def activate(ob):
ob.select_set(True)
bpy.context.view_layer.objects.active = ob
def selection_get():
aob = bpy.context.view_layer.objects.active
selobs = bpy.context.view_layer.objects.selected[:]