diff options
-rw-r--r-- | blenderkit/__init__.py | 6 | ||||
-rw-r--r-- | blenderkit/asset_bar_op.py | 107 | ||||
-rw-r--r-- | blenderkit/bkit_oauth.py | 10 | ||||
-rw-r--r-- | blenderkit/bl_ui_widgets/bl_ui_draw_op.py | 9 | ||||
-rw-r--r-- | blenderkit/bl_ui_widgets/bl_ui_widget.py | 2 | ||||
-rw-r--r-- | blenderkit/categories.py | 4 | ||||
-rw-r--r-- | blenderkit/comments_utils.py | 11 | ||||
-rw-r--r-- | blenderkit/download.py | 10 | ||||
-rw-r--r-- | blenderkit/paths.py | 4 | ||||
-rw-r--r-- | blenderkit/ratings_utils.py | 5 | ||||
-rw-r--r-- | blenderkit/reports.py | 20 | ||||
-rw-r--r-- | blenderkit/rerequests.py | 10 | ||||
-rw-r--r-- | blenderkit/search.py | 46 | ||||
-rw-r--r-- | blenderkit/ui.py | 64 | ||||
-rw-r--r-- | blenderkit/ui_panels.py | 80 | ||||
-rw-r--r-- | blenderkit/upload.py | 16 | ||||
-rw-r--r-- | blenderkit/upload_bg.py | 12 | ||||
-rw-r--r-- | blenderkit/utils.py | 20 |
18 files changed, 261 insertions, 175 deletions
diff --git a/blenderkit/__init__.py b/blenderkit/__init__.py index 3b35b912..22afd2a1 100644 --- a/blenderkit/__init__.py +++ b/blenderkit/__init__.py @@ -60,6 +60,7 @@ if "bpy" in locals(): upload = reload(upload) upload_bg = reload(upload_bg) utils = reload(utils) + reports = reload(reports) bl_ui_widget = reload(bl_ui_widget) bl_ui_label = reload(bl_ui_label) @@ -99,6 +100,7 @@ else: from blenderkit import upload from blenderkit import upload_bg from blenderkit import utils + from blenderkit import reports from blenderkit.bl_ui_widgets import bl_ui_widget from blenderkit.bl_ui_widgets import bl_ui_label @@ -270,7 +272,7 @@ def switch_search_results(self, context): wm['search results'] = wm.get('bkit brush search') wm['search results orig'] = wm.get('bkit brush search orig') if not (context.sculpt_object or context.image_paint_object): - ui.add_report( + reports.add_report( 'Switch to paint or sculpt mode to search in BlenderKit brushes.') # if wm['search results'] == None: # wm['search results'] = [] @@ -1658,7 +1660,7 @@ class BlenderKitAddonPreferences(AddonPreferences): tips_on_start: BoolProperty( name="Show tips when starting blender", description="Show tips when starting blender", - default=False + default=True ) search_in_header: BoolProperty( diff --git a/blenderkit/asset_bar_op.py b/blenderkit/asset_bar_op.py index 17638f4e..98b89f14 100644 --- a/blenderkit/asset_bar_op.py +++ b/blenderkit/asset_bar_op.py @@ -24,6 +24,7 @@ from bpy.props import ( StringProperty ) +active_area_pointer = 0 def get_area_height(self): if type(self.context) != dict: @@ -64,7 +65,7 @@ def modal_inside(self, context, event): self.finish() return {'FINISHED'} - self.update_timer +=1 + self.update_timer += 1 if self.update_timer > self.update_timer_limit: self.update_timer = 0 @@ -84,7 +85,6 @@ def modal_inside(self, context, event): else: asset_button.progress_bar.visible = False - if self.handle_widget_events(event): return {'RUNNING_MODAL'} @@ -124,11 +124,16 @@ def asset_bar_invoke(self, context, event): self.register_handlers(args, context) self.update_timer_limit = 30 - self.update_timer =0 + self.update_timer = 0 # print('adding timer') # self._timer = context.window_manager.event_timer_add(10.0, window=context.window) - + global active_area_pointer context.window_manager.modal_handler_add(self) + self.active_window_pointer = context.window.as_pointer() + self.active_area_pointer = context.area.as_pointer() + active_area_pointer = context.area.as_pointer() + self.active_region_pointer = context.region.as_pointer() + return {"RUNNING_MODAL"} @@ -188,7 +193,7 @@ def get_tooltip_data(asset_data): if rc: rcount = min(rc.get('quality', 0), rc.get('workingHours', 0)) if rcount > show_rating_threshold: - quality = round(asset_data['ratingsAverage'].get('quality')) + quality = str(round(asset_data['ratingsAverage'].get('quality'))) tooltip_data = { 'aname': aname, 'author_text': author_text, @@ -273,16 +278,32 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): self.authors_name = authors_name self.tooltip_widgets.append(authors_name) - gravatar_image = BL_UI_Image(self.tooltip_width - self.gravatar_size, self.tooltip_height - self.gravatar_size, 1, 1) + gravatar_image = BL_UI_Image(self.tooltip_width - self.gravatar_size, self.tooltip_height - self.gravatar_size, + 1, 1) img_path = paths.get_addon_thumbnail_path('thumbnail_notready.jpg') gravatar_image.set_image(img_path) gravatar_image.set_image_size((self.gravatar_size - 1 * self.margin, self.gravatar_size - 1 * self.margin)) gravatar_image.set_image_position((0, 0)) self.gravatar_image = gravatar_image self.tooltip_widgets.append(gravatar_image) - offset_y = 16 + self.margin - # label = self.new_text('Left click or drag to append/link. Right click for more options.', self.margin*2, labels_start + offset_y, - # text_size=14) + + quality_star = BL_UI_Image(self.margin, self.tooltip_height - self.margin - self.asset_name_text_size, + 1, 1) + img_path = paths.get_addon_thumbnail_path('star_grey.png') + quality_star.set_image(img_path) + quality_star.set_image_size((self.asset_name_text_size, self.asset_name_text_size)) + quality_star.set_image_position((0, 0)) + # self.quality_star = quality_star + self.tooltip_widgets.append(quality_star) + label = self.new_text('', 2*self.margin+self.asset_name_text_size, + self.tooltip_height - int(self.asset_name_text_size+ self.margin * .5), + text_size=self.asset_name_text_size) + self.tooltip_widgets.append(label) + self.quality_label = label + + # label = self.new_text('Right click for menu.', self.margin, + # self.tooltip_height - int(self.author_text_size) - self.margin, + # text_size=int(self.author_text_size*.7)) # self.tooltip_widgets.append(label) def hide_tooltip(self): @@ -383,7 +404,7 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): if not bpy.context.preferences.system.use_region_overlap: reg_multiplier = 0 for r in area.regions: - if r.type == 'UI' : + if r.type == 'UI': ui_width = r.width * reg_multiplier if r.type == 'TOOLS': tools_width = r.width * reg_multiplier @@ -409,13 +430,17 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): # self.bar_y = region.height - ui_props.bar_y_offset * ui_scale self.bar_y = ui_props.bar_y_offset * ui_scale if ui_props.down_up == 'UPLOAD': - self.reports_y = self.bar_y - 600 + self.reports_y = region.height - self.bar_y - 600 + ui_props.reports_y = region.height - self.bar_y - 600 self.reports_x = self.bar_x - else: - self.reports_y = self.bar_y - self.bar_height - 100 - self.reports_x = self.bar_x - + ui_props.reports_x = self.bar_x + else:#ui.bar_y - ui.bar_height - 100 + self.reports_y = region.height - self.bar_y - self.bar_height - 50 + ui_props.reports_y =region.height - self.bar_y - self.bar_height- 50 + self.reports_x = self.bar_x + ui_props.reports_x = self.bar_x + # print(self.bar_y, self.bar_height, region.height) def update_layout(self, context, event): # restarting asset_bar completely since the widgets are too hard to get working with updates. @@ -437,9 +462,10 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): self.tooltip_panel.width = self.tooltip_width self.tooltip_image.width = self.tooltip_width self.tooltip_image.set_image_size((self.tooltip_width, self.tooltip_height)) - self.gravatar_image.set_location(self.tooltip_width - self.gravatar_size, self.tooltip_height - self.gravatar_size) + self.gravatar_image.set_location(self.tooltip_width - self.gravatar_size, + self.tooltip_height - self.gravatar_size) self.authors_name.set_location(self.tooltip_width - self.gravatar_size - self.margin, - self.tooltip_height - self.author_text_size - self.margin) + self.tooltip_height - self.author_text_size - self.margin) # to hide arrows accordingly self.scroll_update() @@ -491,6 +517,12 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): new_button.progress_bar = progress_bar self.progress_bars.append(progress_bar) + if utils.profile_is_validator(): + red_alert = BL_UI_Widget(asset_x, asset_y, self.button_size, self.button_size) + red_alert.bg_color = (1.0, 0.0, 0.0, 0.0) + red_alert.visible = False + new_button.red_alert = red_alert + self.red_alerts.append(red_alert) # if result['downloaded'] > 0: # ui_bgl.draw_rect(x, y, int(ui_props.thumb_size * result['downloaded'] / 100.0), 2, green) @@ -506,6 +538,7 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): self.asset_buttons = [] self.validation_icons = [] self.progress_bars = [] + self.red_alerts = [] self.widgets_panel = [] self.panel = BL_UI_Drag_Panel(0, 0, self.bar_width, self.bar_height) @@ -608,6 +641,8 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): button.visible = False button.validation_icon.visible = False button.progress_bar.visible = False + if utils.profile_is_validator(): + button.red_alert.set_location(asset_x, asset_y) i += 1 for a in range(i, len(self.asset_buttons)): @@ -641,6 +676,7 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): widgets_panel.extend(self.asset_buttons) widgets_panel.extend(self.validation_icons) widgets_panel.extend(self.progress_bars) + widgets_panel.extend(self.red_alerts) widgets = [self.panel] @@ -702,6 +738,14 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): # to hide arrows accordingly self.scroll_update() + self.window = context.window + self.area = context.area + self.scene = bpy.context.scene + # global active_window_pointer, active_area_pointer, active_region_pointer + # ui.active_window_pointer = self.window.as_pointer() + # ui.active_area_pointer = self.area.as_pointer() + # ui.active_region_pointer = self.region.as_pointer() + return True def on_finish(self, context): @@ -754,7 +798,8 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): get_tooltip_data(asset_data) self.asset_name.text = asset_data['name'] self.authors_name.text = asset_data['tooltip_data']['author_text'] - + self.quality_label.text = asset_data['tooltip_data']['quality'] + # print(asset_data['tooltip_data']['quality']) gimg = asset_data['tooltip_data']['gimg'] if gimg is not None: gimg = bpy.data.images[gimg] @@ -817,11 +862,21 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): def update_validation_icon(self, asset_button, asset_data): if utils.profile_is_validator(): + ar = bpy.context.window_manager.get('asset ratings') + rating = ar.get(asset_data['id']) + if rating is not None: + rating = rating.to_dict() + 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 + elif rating in (None, {}): + v_icon = 'star_grey.png' + 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: @@ -854,8 +909,21 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): asset_button.set_image(img_filepath) self.update_validation_icon(asset_button, asset_data) + + if utils.profile_is_validator() and asset_data['verificationStatus'] == 'uploaded': + over_limit = utils.is_upload_old(asset_data) + if over_limit: + redness = min(over_limit * .05, 0.7) + asset_button.red_alert.bg_color = (1, 0, 0, redness) + asset_button.red_alert.visible = True + else: + asset_button.red_alert.visible = False + elif utils.profile_is_validator(): + asset_button.red_alert.visible = False else: asset_button.validation_icon.visible = False + if utils.profile_is_validator(): + asset_button.red_alert.visible = False def scroll_update(self): sr = bpy.context.window_manager.get('search results') @@ -869,7 +937,7 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): self.scroll_offset = min(self.scroll_offset, len(sr) - (self.wcount * self.hcount)) self.scroll_offset = max(self.scroll_offset, 0) self.update_images() - + # print(sro) if sro['count'] > len(sr) and len(sr) - self.scroll_offset < (self.wcount * self.hcount) + 15: self.search_more() @@ -898,6 +966,7 @@ class BlenderKitAssetBarOperator(BL_UI_OT_draw_operator): def handle_key_input(self, event): if event.type == 'A': self.search_by_author(self.active_index) + return True return False def scroll_up(self, widget): diff --git a/blenderkit/bkit_oauth.py b/blenderkit/bkit_oauth.py index fa00e616..b4e944a3 100644 --- a/blenderkit/bkit_oauth.py +++ b/blenderkit/bkit_oauth.py @@ -17,7 +17,7 @@ # ##### END GPL LICENSE BLOCK ##### -from blenderkit import tasks_queue, utils, paths, search, categories, oauth, ui, ui_panels, colors +from blenderkit import tasks_queue, utils, paths, search, categories, oauth, ui, ui_panels, colors, reports import bpy @@ -25,6 +25,8 @@ import threading import requests import time import logging + + bk_logger = logging.getLogger('blenderkit') from bpy.props import ( @@ -52,7 +54,7 @@ def login(signup, url, r_url, authenticator): try: auth_token, refresh_token, oauth_response = authenticator.get_new_token(register=signup, redirect_url=r_url) except Exception as e: - tasks_queue.add_task((ui.add_report, (e, 20, colors.RED))) + tasks_queue.add_task((reports.add_report, (e, 20, colors.RED))) bk_logger.debug('tokens retrieved') tasks_queue.add_task((write_tokens, (auth_token, refresh_token, oauth_response))) @@ -66,7 +68,7 @@ def refresh_token_thread(): thread = threading.Thread(target=refresh_token, args=([preferences.api_key_refresh, url]), daemon=True) thread.start() else: - ui.add_report('Already Refreshing token, will be ready soon. If this fails, please login again in Login panel.') + reports.add_report('Already Refreshing token, will be ready soon. If this fails, please login again in Login panel.') def refresh_token(api_key_refresh, url): @@ -89,7 +91,7 @@ def write_tokens(auth_token, refresh_token, oauth_response): props = utils.get_search_props() if props is not None: props.report = '' - ui.add_report('BlenderKit Re-Login success') + reports.add_report('BlenderKit Re-Login success') search.get_profile() categories.fetch_categories_thread(auth_token, force = False) diff --git a/blenderkit/bl_ui_widgets/bl_ui_draw_op.py b/blenderkit/bl_ui_widgets/bl_ui_draw_op.py index 43a79111..bc2e9cb5 100644 --- a/blenderkit/bl_ui_widgets/bl_ui_draw_op.py +++ b/blenderkit/bl_ui_widgets/bl_ui_draw_op.py @@ -35,6 +35,10 @@ class BL_UI_OT_draw_operator(Operator): self.register_handlers(args, context) context.window_manager.modal_handler_add(self) + + self.active_window_pointer = context.window.as_pointer() + self.active_area_pointer = context.area.as_pointer() + self.active_region_pointer = context.region.as_pointer() return {"RUNNING_MODAL"} def register_handlers(self, args, context): @@ -80,8 +84,9 @@ class BL_UI_OT_draw_operator(Operator): # Draw handler to paint onto the screen def draw_callback_px(self, op, context): try: - for widget in self.widgets: - widget.draw() + if context.area.as_pointer() == self.active_area_pointer: + for widget in self.widgets: + widget.draw() except: pass; # context.window_manager.event_timer_remove(self.draw_event) diff --git a/blenderkit/bl_ui_widgets/bl_ui_widget.py b/blenderkit/bl_ui_widgets/bl_ui_widget.py index 4b98f154..90fefddf 100644 --- a/blenderkit/bl_ui_widgets/bl_ui_widget.py +++ b/blenderkit/bl_ui_widgets/bl_ui_widget.py @@ -125,7 +125,7 @@ class BL_UI_Widget: return False - elif event.value == 'PRESS' and (event.ascii != '' or event.type in self.get_input_keys()): + elif event.value == 'PRESS' and self.__inrect and (event.ascii != '' or event.type in self.get_input_keys()): return self.text_input(event) diff --git a/blenderkit/categories.py b/blenderkit/categories.py index 9a19c120..c97c339c 100644 --- a/blenderkit/categories.py +++ b/blenderkit/categories.py @@ -17,7 +17,7 @@ # ##### END GPL LICENSE BLOCK ##### -from blenderkit import paths, utils, tasks_queue, rerequests, ui, colors +from blenderkit import paths, utils, tasks_queue, rerequests, ui, colors, reports import requests import json @@ -261,7 +261,7 @@ def fetch_categories(API_key, force=False): tasks_queue.add_task((load_categories, ())) except Exception as e: t = 'BlenderKit failed to download fresh categories from the server' - tasks_queue.add_task((ui.add_report,(t, 15, colors.RED))) + tasks_queue.add_task((reports.add_report(),(t, 15, colors.RED))) bk_logger.debug(t) bk_logger.exception(e) if not os.path.exists(categories_filepath): diff --git a/blenderkit/comments_utils.py b/blenderkit/comments_utils.py index adca81ed..4be80bd8 100644 --- a/blenderkit/comments_utils.py +++ b/blenderkit/comments_utils.py @@ -110,11 +110,6 @@ def get_comments_thread(asset_id, api_key): thread = threading.Thread(target=get_comments, args=([asset_id, api_key]), daemon=True) thread.start() - -def get_comments_thread(asset_id, api_key): - thread = threading.Thread(target=get_comments, args=([asset_id, api_key]), daemon=True) - thread.start() - def get_comments(asset_id, api_key): ''' Retrieve comments from BlenderKit server. Can be run from a thread @@ -166,9 +161,9 @@ def count_all_notifications(): def check_notifications_read(): '''checks if all notifications were already read, and removes them if so''' notifications = bpy.context.window_manager.get('bkit notifications') - if notifications is None: + if notifications is None or notifications.get('count') == 0: return True - for n in notifications: + for n in notifications['results']: if n['unread'] == 1: return False bpy.context.window_manager['bkit notifications'] = None @@ -198,7 +193,7 @@ def get_notifications(api_key, all_count = 1000): r = rerequests.get(url, params=params, verify=True, headers=headers) if r.status_code ==200: rj = r.json() - print(rj) + # print(rj) # no new notifications? if all_count >= rj['allCount']: tasks_queue.add_task((store_notifications_count_local, ([rj['allCount']]))) diff --git a/blenderkit/download.py b/blenderkit/download.py index f33e636f..70ab8755 100644 --- a/blenderkit/download.py +++ b/blenderkit/download.py @@ -779,7 +779,7 @@ class Downloader(threading.Thread): if not has_url: tasks_queue.add_task( - (ui.add_report, ('Failed to obtain download URL for %s.' % asset_data['name'], 5, colors.RED))) + (reports.add_report, ('Failed to obtain download URL for %s.' % asset_data['name'], 5, colors.RED))) return; if tcom.error: return @@ -814,7 +814,7 @@ class Downloader(threading.Thread): else: # bk_logger.debug(total_length) if int(total_length) < 1000: # means probably no file returned. - tasks_queue.add_task((ui.add_report, (response.content, 20, colors.RED))) + tasks_queue.add_task((reports.add_report, (response.content, 20, colors.RED))) tcom.report = response.content @@ -875,7 +875,7 @@ def download(asset_data, **kwargs): sprops = utils.get_search_props() report = f"Maximum retries exceeded for {asset_data['name']}" sprops.report = report - ui.add_report(report, 5, colors.RED) + reports.add_report(report, 5, colors.RED) bk_logger.debug(sprops.report) return @@ -1122,12 +1122,12 @@ def get_download_url(asset_data, scene_id, api_key, tcom=None, resolution='blend return True # let's print it into UI - tasks_queue.add_task((ui.add_report, (str(r), 10, colors.RED))) + tasks_queue.add_task((reports.add_report, (str(r), 10, colors.RED))) if r.status_code == 403: 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))) + # tasks_queue.add_task((reports.add_report, (r1, 5, colors.RED))) if tcom is not None: tcom.report = report tcom.error = True diff --git a/blenderkit/paths.py b/blenderkit/paths.py index 08a4e492..ea7d35d8 100644 --- a/blenderkit/paths.py +++ b/blenderkit/paths.py @@ -129,12 +129,12 @@ def get_temp_dir(subdir=None): cleanup_old_folders() except: - tasks_queue.add_task((ui.add_report, ('Cache directory not found. Resetting Cache folder path.',))) + tasks_queue.add_task((reports.add_report, ('Cache directory not found. Resetting Cache folder path.',))) p = default_global_dict() if p == user_preferences.global_dir: message = 'Global dir was already default, plese set a global directory in addon preferences to a dir where you have write permissions.' - tasks_queue.add_task((ui.add_report, (message,))) + tasks_queue.add_task((reports.add_report, (message,))) return None user_preferences.global_dir = p tempdir = get_temp_dir(subdir=subdir) diff --git a/blenderkit/ratings_utils.py b/blenderkit/ratings_utils.py index eafa60fa..d813f444 100644 --- a/blenderkit/ratings_utils.py +++ b/blenderkit/ratings_utils.py @@ -78,7 +78,7 @@ def store_rating_local(asset_id, type='quality', value=0): context = bpy.context ar = context.window_manager['asset ratings'] ar[asset_id] = ar.get(asset_id, {}) - ar[asset_id]['type'] = value + ar[asset_id][type] = value def get_rating(asset_id, headers): @@ -101,6 +101,7 @@ def get_rating(asset_id, headers): if r.status_code == 200: rj = r.json() ratings = {} + print(rj) # store ratings - send them to task queue for r in rj['results']: ratings[r['ratingType']] = r['score'] @@ -353,6 +354,8 @@ class RatingsProperties(): def prefill_ratings(self): # pre-fill ratings ratings = get_rating_local(self.asset_id) + print('prefill ratings') + print(ratings) if ratings and ratings.get('quality'): self.rating_quality = ratings['quality'] if ratings and ratings.get('working_hours'): diff --git a/blenderkit/reports.py b/blenderkit/reports.py index 816ac791..7a455863 100644 --- a/blenderkit/reports.py +++ b/blenderkit/reports.py @@ -17,7 +17,11 @@ # ##### END GPL LICENSE BLOCK ##### import time -from blenderkit import colors +import bpy +from blenderkit import colors, asset_bar_op, ui_bgl, utils + +reports = [] + def add_report(text='', timeout=5, color=colors.GREEN): global reports @@ -26,18 +30,24 @@ def add_report(text='', timeout=5, color=colors.GREEN): if old_report.text == text: old_report.timeout = old_report.age + timeout return - report = Report(text=text, timeout=timeout, color=color) + report = Report(text=text, timeout=timeout, color=color) reports.append(report) class Report(): - def __init__(self, text='', timeout=5, color=(.5, 1, .5, 1)): + def __init__(self, area_pointer=0, text='', timeout=5, color=(.5, 1, .5, 1)): self.text = text self.timeout = timeout self.start_time = time.time() self.color = color self.draw_color = color self.age = 0 + if asset_bar_op.active_area_pointer == 0: + w, a, r = utils.get_largest_area(area_type='VIEW_3D') + + self.active_area_pointer = a.as_pointer() + else: + self.active_area_pointer = asset_bar_op.active_area_pointer def fade(self): fade_time = 1 @@ -53,5 +63,5 @@ class Report(): pass; def draw(self, x, y): - if bpy.context.area.as_pointer() == active_area_pointer: - ui_bgl.draw_text(self.text, x, y + 8, 16, self.draw_color)
\ No newline at end of file + if (bpy.context.area is not None and bpy.context.area.as_pointer() == self.active_area_pointer): + ui_bgl.draw_text(self.text, x, y + 8, 16, self.draw_color) diff --git a/blenderkit/rerequests.py b/blenderkit/rerequests.py index 735feb35..a9f3bacd 100644 --- a/blenderkit/rerequests.py +++ b/blenderkit/rerequests.py @@ -44,7 +44,7 @@ def rerequest(method, url, recursion=0, **kwargs): response = requests.request(method, url, **kwargs) except Exception as e: print(e) - tasks_queue.add_task((ui.add_report, ( + tasks_queue.add_task((reports.add_report, ( 'Connection error.', 10))) return FakeResponse() @@ -57,13 +57,13 @@ def rerequest(method, url, recursion=0, **kwargs): except: rdata = {} - tasks_queue.add_task((ui.add_report, (method + ' request Failed.' + str(rdata.get('detail')),))) + tasks_queue.add_task((reports.add_report, (method + ' request Failed.' + str(rdata.get('detail')),))) if rdata.get('detail') == 'Invalid token.': user_preferences = bpy.context.preferences.addons['blenderkit'].preferences if user_preferences.api_key != '': if user_preferences.enable_oauth and user_preferences.api_key_refresh != '': - tasks_queue.add_task((ui.add_report, ( + tasks_queue.add_task((reports.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( @@ -84,11 +84,11 @@ def rerequest(method, url, recursion=0, **kwargs): bk_logger.debug('reresult', response.status_code) if response.status_code >= 400: bk_logger.debug('reresult', response.text) - tasks_queue.add_task((ui.add_report, ( + tasks_queue.add_task((reports.add_report, ( response.text, 10))) else: - tasks_queue.add_task((ui.add_report, ( + tasks_queue.add_task((reports.add_report, ( 'Refreshing token failed.Please login manually.', 10))) # tasks_queue.add_task((bkit_oauth.write_tokens, ('', '', ''))) tasks_queue.add_task((bpy.ops.wm.blenderkit_login, ('INVOKE_DEFAULT',)), fake_context=True) diff --git a/blenderkit/search.py b/blenderkit/search.py index 9c19b25b..f86a9a5e 100644 --- a/blenderkit/search.py +++ b/blenderkit/search.py @@ -17,7 +17,7 @@ # ##### END GPL LICENSE BLOCK ##### from blenderkit import paths, utils, categories, ui, colors, bkit_oauth, version_checker, tasks_queue, rerequests, \ - resolutions, image_utils, ratings_utils, comments_utils + resolutions, image_utils, ratings_utils, comments_utils, reports import blenderkit from bpy.app.handlers import persistent @@ -83,15 +83,22 @@ thumb_full_download_threads = queue.Queue() reports_queue = queue.Queue() all_thumbs_loaded = True -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.", - "Click on brushes to link them into scene.", - "All materials are free.", - "Storage for public assets is unlimited.", - "Locked models are available if you subscribe to Full plan.", - "Login to upload your own models, materials or brushes.", - "Use 'A' key over asset bar to search assets by same author.", - "Use 'W' key over asset bar to open Authors webpage.", ] +rtips_string = """You can disable tips in the add-on preferences. +Ratings help us distribute funds to creators. +Creators also gain credits for free assets from subscribers. +Click or drag model or material in scene to link/append +Right click in the asset bar for more options +Use Append in import settings if you want to edit downloaded objects. +Please rate responsively and plentifully. This helps us distribute rewards to the authors. +All materials are free. +Storage for public assets is unlimited. +Locked models are available if you subscribe to Full plan. +Login to upload your own models, materials or brushes. +Use 'A' key over the asset bar to search assets by the same author. +Use semicolon - ; to hide or show the AssetBar. +Support the authors by subscribing to Full plan. +""" +rtips = rtips_string.splitlines() def refresh_token_timer(): @@ -192,7 +199,7 @@ def scene_load(context): 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) + bpy.app.timers.register(refresh_notifications_timer, persistent=True, first_interval=5) update_assets_data() @@ -211,7 +218,8 @@ def fetch_server_data(): get_profile() if bpy.context.window_manager.get('bkit_categories') is None: categories.fetch_categories_thread(api_key, force=False) - + all_notifications_count = comments_utils.count_all_notifications() + comments_utils.get_notifications_thread(api_key, all_count = all_notifications_count) first_time = True last_clipboard = '' @@ -374,7 +382,7 @@ def search_timer(): if preferences.tips_on_start: utils.get_largest_area() ui.update_ui_size(ui.active_area_pointer, ui.active_region_pointer) - ui.add_report(text='BlenderKit Tip: ' + random.choice(rtips), timeout=12, color=colors.GREEN) + reports.add_report(text='BlenderKit Tip: ' + random.choice(rtips), timeout=12, color=colors.GREEN) # utils.p('end search timer') return 3.0 @@ -481,7 +489,7 @@ def search_timer(): props.search_error = False props.report = 'Found %i results. ' % (wm['search results orig']['count']) if len(wm['search results']) == 0: - tasks_queue.add_task((ui.add_report, ('No matching results found.',))) + tasks_queue.add_task((reports.add_report, ('No matching results found.',))) # undo push # bpy.ops.wm.undo_push_context(message='Get BlenderKit search') # show asset bar automatically, but only on first page - others are loaded also when asset bar is hidden. @@ -740,7 +748,7 @@ def fetch_gravatar(adata = None): ''' # utils.p('fetch gravatar') - print(adata) + # print(adata) # fetch new avatars if available already if adata.get('avatar128') is not None: avatar_path = paths.get_temp_dir(subdir='bkit_g/') + adata['id'] + '.jpg' @@ -968,13 +976,13 @@ class Searcher(threading.Thread): if hasattr(r, 'text'): 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))) + tasks_queue.add_task((reports.add_report, (error_description, 10, colors.RED))) bk_logger.error(e) return mt('data parsed ') if not rdata.get('results'): - utils.pprint(rdata) + # utils.pprint(rdata) # if the result was converted to json and didn't return results, # it means it's a server error that has a clear message. # That's why it gets processed in the update timer, where it can be passed in messages to user. @@ -1437,7 +1445,7 @@ def search(category='', get_next=False, author_id=''): if orig_results is not None and get_next: params['next'] = orig_results['next'] add_search_process(query, params) - tasks_queue.add_task((ui.add_report, ('BlenderKit searching....', 2))) + tasks_queue.add_task((reports.add_report, ('BlenderKit searching....', 2))) props.report = 'BlenderKit searching....' @@ -1583,7 +1591,7 @@ class SearchOperator(Operator): sprops.search_keywords = self.keywords search(category=self.category, get_next=self.get_next, author_id=self.author_id) - # bpy.ops.view3d.blenderkit_asset_bar() + # bpy.ops.view3d.blenderkit_asset_bar_widget() return {'FINISHED'} diff --git a/blenderkit/ui.py b/blenderkit/ui.py index 70abd898..41c4feee 100644 --- a/blenderkit/ui.py +++ b/blenderkit/ui.py @@ -18,7 +18,7 @@ from blenderkit import paths, ratings, utils, search, upload, ui_bgl, download, bg_blender, colors, tasks_queue, \ - ui_panels, icons, ratings_utils + ui_panels, icons, ratings_utils, reports import bpy @@ -51,8 +51,6 @@ active_area_pointer = None active_window_pointer = None active_region_pointer = None -reports = [] - mappingdict = { 'MODEL': 'model', 'SCENE': 'scene', @@ -101,43 +99,6 @@ def get_approximate_text_width(st): return size # Convert to picas -def add_report(text='', timeout=5, color=colors.GREEN): - global reports - # check for same reports and just make them longer by the timeout. - for old_report in reports: - if old_report.text == text: - old_report.timeout = old_report.age + timeout - return - report = Report(text=text, timeout=timeout, color=color) - reports.append(report) - - -class Report(): - def __init__(self, text='', timeout=5, color=(.5, 1, .5, 1)): - self.text = text - self.timeout = timeout - self.start_time = time.time() - self.color = color - self.draw_color = color - self.age = 0 - - def fade(self): - fade_time = 1 - self.age = time.time() - self.start_time - if self.age + fade_time > self.timeout: - alpha_multiplier = (self.timeout - self.age) / fade_time - self.draw_color = (self.color[0], self.color[1], self.color[2], self.color[3] * alpha_multiplier) - if self.age > self.timeout: - global reports - try: - reports.remove(self) - except Exception as e: - pass; - - def draw(self, x, y): - if bpy.context.area.as_pointer() == active_area_pointer: - ui_bgl.draw_text(self.text, x, y + 8, 16, self.draw_color) - def get_asset_under_mouse(mousex, mousey): s = bpy.context.scene @@ -528,8 +489,8 @@ def draw_callback_2d_progress(self, context): draw_progress(x, y - index * 30, '%s' % n + tcom.lasttext, tcom.progress) index += 1 - global reports - for report in reports: + for report in reports.reports: + # print('drawing reports', x, y, report.text) report.draw(x, y - index * 30) index += 1 report.fade() @@ -557,21 +518,6 @@ def draw_callback_2d_upload_preview(self, context): draw_tooltip(ui_props.bar_x, ui_props.bar_y, name=props.name, img=img) -def is_upload_old(asset_data): - ''' - estimates if the asset is far too long in the 'uploaded' state - This returns the number of days the validation is over the limit. - ''' - date_time_str = asset_data["created"][:10] - # date_time_str = 'Jun 28 2018 7:40AM' - date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d') - today = date_time_obj.today() - age = today - date_time_obj - old = datetime.timedelta(days=7) - if age > old: - return (age.days - old.days) - return 0 - def get_large_thumbnail_image(asset_data): '''Get thumbnail image from asset data''' @@ -705,7 +651,7 @@ def draw_asset_bar(self, context): # code to inform validators that the validation is waiting too long and should be done asap if result['verificationStatus'] == 'uploaded': if is_validator: - over_limit = is_upload_old(result) + over_limit = utils.is_upload_old(result) if over_limit: redness = min(over_limit * .05, 0.5) red = (1, 0, 0, redness) @@ -1903,7 +1849,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 1:# 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) diff --git a/blenderkit/ui_panels.py b/blenderkit/ui_panels.py index dbf5fcda..f8f08a21 100644 --- a/blenderkit/ui_panels.py +++ b/blenderkit/ui_panels.py @@ -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 1: # 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) @@ -609,7 +609,7 @@ class MarkNotificationRead(bpy.types.Operator): def execute(self, context): notifications = bpy.context.window_manager['bkit notifications'] - for n in notifications: + for n in notifications['results']: if n['id'] == self.notification_id: n['unread'] = 0 comments_utils.check_notifications_read() @@ -634,7 +634,7 @@ class MarkAllNotificationsRead(bpy.types.Operator): user_preferences = bpy.context.preferences.addons['blenderkit'].preferences api_key = user_preferences.api_key notifications = bpy.context.window_manager['bkit notifications'] - for n in notifications: + for n in notifications.get('results'): if n['unread'] == 1: n['unread'] = 0 comments_utils.mark_notification_read_thread(api_key, n['id']) @@ -705,42 +705,54 @@ def draw_notification(self, notification, width=600): box = layout.box() firstline = f"{notification['actor']['string']} {notification['verb']} {notification['target']['string']}" box1 = box.box() - row = box1.row() - utils.label_multiline(row, text=firstline, width=width) + # row = box1.row() - op = row.operator("wm.blenderkit_mark_notification_read", text="", icon='CANCEL') - op.notification_id = notification['id'] + split_last = 0.7 if notification['description']: - rows = utils.label_multiline(box, text=notification['description'], width=width) - split = rows[-1].split(factor=0.8) + split_last = 0 + + + rows = utils.label_multiline(box1, text=firstline, width=width, split_last = split_last) + + + if notification['description']: + rows = utils.label_multiline(box, text=notification['description'], width=width, split_last = 0.7) + - else: - row = layout.row() - split = row.split(factor=0.8) - split.label(text='') - split = split.split() if notification['target']: # row = layout.row() # split = row.split(factor=.8) # split.label(text='') # split = split.split() - op = split.operator('wm.blenderkit_open_notification_target', text='Open page', icon='GREASEPENCIL') + # split = rows[-1].split(factor=0.8) + # split = split.split() + # split.alignment = 'RIGHT' + # row = split.row(align = True) + row = rows[-1] + row = row.row(align=False) + + # row = row.split(factor = 0.7) + + op = row.operator('wm.blenderkit_open_notification_target', text='Open page', icon='HIDE_OFF') op.tooltip = 'Open the browser on the asset page to comment' op.url = paths.get_bkit_url() + notification['target']['url'] op.notification_id = notification['id'] + # split = + op = row.operator("wm.blenderkit_mark_notification_read", text="", icon='CANCEL') + op.notification_id = notification['id'] def draw_notifications(self, context, width=600): layout = self.layout notifications = bpy.context.window_manager.get('bkit notifications') - if notifications is not None: + if notifications is not None and notifications.get('count')>0: row = layout.row() # row.alert = True split = row.split(factor = 0.7) split.label(text='') split = split.split() split.operator('wm.blenderkit_mark_notifications_read_all', text = 'Mark All Read', icon = 'CANCEL') - for notification in notifications: + for notification in notifications['results']: if notification['unread'] == 1: draw_notification(self, notification, width=width) @@ -778,7 +790,7 @@ class VIEW3D_PT_blenderkit_notifications(Panel): @classmethod def poll(cls, context): notifications = bpy.context.window_manager.get('bkit notifications') - if notifications is not None and len(notifications) > 0: + if notifications is not None and len(notifications['results']) > 0: return True return False @@ -1554,8 +1566,7 @@ def draw_asset_context_menu(layout, context, asset_data, from_panel=False): 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': + elif 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'] @@ -2129,7 +2140,7 @@ class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties): # name_row = name_row.row() for i, c in enumerate(cat_path): cat_name = cat_path_names[i] - op = name_row.operator('view3d.blenderkit_asset_bar', text=cat_name + ' >', emboss=True) + op = name_row.operator('view3d.blenderkit_asset_bar_widget', text=cat_name + ' >', emboss=True) op.do_search = True op.keep_running = True op.tooltip = f"Browse {cat_name} category" @@ -2225,13 +2236,30 @@ class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties): tip_box = layout.box() tip_box.label(text=self.tip) # comments - if utils.profile_is_validator() and bpy.app.debug_value == 2: + if utils.profile_is_validator(): comments = bpy.context.window_manager.get('asset comments', {}) self.comments = comments.get(self.asset_data['assetBaseId'], []) if self.comments is not None: for comment in self.comments: self.draw_comment(context, layout, comment, width=self.width) + def prefill_ratings(self): + # pre-fill ratings + ratings = ratings_utils.get_rating_local(self.asset_id) + print('prefill ratings') + print(ratings) + if ratings and ratings.get('quality'): + self.rating_quality = ratings['quality'] + if ratings and ratings.get('working_hours'): + wh = int(ratings['working_hours']) + whs = str(wh) + if wh in self.possible_wh_values: + self.rating_work_hours_ui = whs + if wh < 6 and wh in self.possible_wh_values_1_5: + self.rating_work_hours_ui_1_5 = whs + if wh < 11 and wh in self.possible_wh_values_1_10: + self.rating_work_hours_ui_1_10 = whs + def execute(self, context): wm = context.window_manager ui_props = context.window_manager.blenderkitUI @@ -2262,7 +2290,7 @@ class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties): self.prefill_ratings() # get comments - if utils.profile_is_validator() and bpy.app.debug_value == 2: + if utils.profile_is_validator(): user_preferences = bpy.context.preferences.addons['blenderkit'].preferences api_key = user_preferences.api_key comments = comments_utils.get_comments_local(asset_data['assetBaseId']) @@ -2452,7 +2480,7 @@ def draw_panel_categories(self, context): cats = categories.get_category(wm['bkit_categories'], cat_path=acat) # draw freebies only in models parent category # if ui_props.asset_type == 'MODEL' and len(acat) == 1: - # op = col.operator('view3d.blenderkit_asset_bar', text='freebies') + # op = col.operator('view3d.blenderkit_asset_bar_widget', text='freebies') # op.free_only = True for c in cats['children']: @@ -2465,7 +2493,7 @@ def draw_panel_categories(self, context): ctext = '%s (%i)' % (c['name'], c['assetCount']) preferences = bpy.context.preferences.addons['blenderkit'].preferences - if 1: # 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) @@ -2570,7 +2598,7 @@ def header_search_draw(self, context): layout.popover(panel="VIEW3D_PT_blenderkit_advanced_HDR_search", text="", icon_value=icon_id) notifications = bpy.context.window_manager.get('bkit notifications') - if notifications is not None and len(notifications) > 0: + if notifications is not None and notifications['count'] > 0: layout.operator('wm.show_notifications', text="", icon_value=pcoll['bell'].icon_id) # layout.popover(panel="VIEW3D_PT_blenderkit_notifications", text="", icon_value=pcoll['bell'].icon_id) diff --git a/blenderkit/upload.py b/blenderkit/upload.py index 7c67d55f..dfca4d94 100644 --- a/blenderkit/upload.py +++ b/blenderkit/upload.py @@ -18,7 +18,7 @@ from blenderkit import asset_inspector, paths, utils, bg_blender, autothumb, version_checker, search, ui_panels, ui, \ - overrides, colors, rerequests, categories, upload_bg, tasks_queue, image_utils, asset_bar_op + overrides, colors, rerequests, categories, upload_bg, tasks_queue, image_utils, asset_bar_op, reports import tempfile, os, subprocess, json, re @@ -715,7 +715,7 @@ class FastMetadata(bpy.types.Operator): thread = threading.Thread(target=patch_individual_metadata, args=(self.asset_id, mdict, user_preferences.api_key)) thread.start() - tasks_queue.add_task((ui.add_report, (f'Uploading metadata for {self.name}. ' + tasks_queue.add_task((reports.add_report, (f'Uploading metadata for {self.name}. ' f'Refresh search results to see that changes applied correctly.', 8,))) return {'FINISHED'} @@ -871,7 +871,7 @@ class Uploader(threading.Thread): message = str(message).replace("'", "") # this adds a UI report but also writes above the upload panel fields. - tasks_queue.add_task((ui.add_report, (message,))) + tasks_queue.add_task((reports.add_report, (message,))) estring = f"{self.export_data['eval_path_state']} = '{message}'" tasks_queue.add_task((exec, (estring,))) @@ -895,14 +895,14 @@ class Uploader(threading.Thread): # self.upload_data['license'] = 'ovejajojo' json_metadata = self.upload_data # json.dumps(self.upload_data, ensure_ascii=False).encode('utf8') - # tasks_queue.add_task((ui.add_report, ('Posting metadata',))) + # tasks_queue.add_task((reports.add_report, ('Posting metadata',))) self.send_message('Posting metadata') if self.export_data['assetBaseId'] == '': try: r = rerequests.post(url, json=json_metadata, headers=headers, verify=True, immediate=True) # files = files, - # tasks_queue.add_task((ui.add_report, ('uploaded metadata',))) + # tasks_queue.add_task((reports.add_report, ('uploaded metadata',))) utils.p(r.text) self.send_message('uploaded metadata') @@ -920,7 +920,7 @@ class Uploader(threading.Thread): immediate=True) # files = files, self.send_message('uploaded metadata') - # tasks_queue.add_task((ui.add_report, ('uploaded metadata',))) + # tasks_queue.add_task((reports.add_report, ('uploaded metadata',))) # parse the request # print('uploaded metadata') print(r.text) @@ -938,10 +938,10 @@ class Uploader(threading.Thread): return {'FINISHED'} try: rj = r.json() - utils.pprint(rj) + # utils.pprint(rj) # if r.status_code not in (200, 201): # if r.status_code == 401: - # ###ui.add_report(r.detail, 5, colors.RED) + # ###reports.add_report(r.detail, 5, colors.RED) # return {'CANCELLED'} # if props.asset_base_id == '': # props.asset_base_id = rj['assetBaseId'] diff --git a/blenderkit/upload_bg.py b/blenderkit/upload_bg.py index 1f29d9ff..b0487417 100644 --- a/blenderkit/upload_bg.py +++ b/blenderkit/upload_bg.py @@ -50,7 +50,7 @@ class upload_in_chunks(object): break self.readsofar += len(data) percent = self.readsofar * 1e2 / self.totalsize - tasks_queue.add_task((ui.add_report, (f"Uploading {self.report_name} {percent}%",))) + tasks_queue.add_task((reports.add_report, (f"Uploading {self.report_name} {percent}%",))) # bg_blender.progress('uploading %s' % self.report_name, percent) # sys.stderr.write("\r{percent:3.0f}%".format(percent=percent)) @@ -65,7 +65,7 @@ def upload_file(upload_data, f): version_id = upload_data['id'] message = f"uploading {f['type']} {os.path.basename(f['file_path'])}" - tasks_queue.add_task((ui.add_report, (message,))) + tasks_queue.add_task((reports.add_report, (message,))) upload_info = { 'assetId': version_id, @@ -95,17 +95,17 @@ def upload_file(upload_data, f): upload_response = rerequests.post(upload_done_url, headers=headers, verify=True) # print(upload_response) # print(upload_response.text) - tasks_queue.add_task((ui.add_report, (f"Finished file upload: {os.path.basename(f['file_path'])}",))) + tasks_queue.add_task((reports.add_report, (f"Finished file upload: {os.path.basename(f['file_path'])}",))) return True else: print(upload_response.text) message = f"Upload failed, retry. File : {f['type']} {os.path.basename(f['file_path'])}" - tasks_queue.add_task((ui.add_report, (message,))) + tasks_queue.add_task((reports.add_report, (message,))) except Exception as e: print(e) message = f"Upload failed, retry. File : {f['type']} {os.path.basename(f['file_path'])}" - tasks_queue.add_task((ui.add_report, (message,))) + tasks_queue.add_task((reports.add_report, (message,))) time.sleep(1) # confirm single file upload to bkit server @@ -123,7 +123,7 @@ def upload_files(upload_data, files): uploaded = upload_file(upload_data, f) if not uploaded: uploaded_all = False - tasks_queue.add_task((ui.add_report, (f"Uploaded all files for asset {upload_data['name']}",))) + tasks_queue.add_task((reports.add_report, (f"Uploaded all files for asset {upload_data['name']}",))) return uploaded_all diff --git a/blenderkit/utils.py b/blenderkit/utils.py index 5bbe96af..79998c26 100644 --- a/blenderkit/utils.py +++ b/blenderkit/utils.py @@ -28,6 +28,7 @@ import shutil import logging import traceback import inspect +import datetime bk_logger = logging.getLogger('blenderkit') @@ -913,7 +914,7 @@ def get_fake_context(context, area_type='VIEW_3D'): # def is_url(text): -def label_multiline(layout, text='', icon='NONE', width=-1, max_lines=10): +def label_multiline(layout, text='', icon='NONE', width=-1, max_lines=10, split_last = 0): ''' draw a ui label, but try to split it in multiple lines. @@ -958,6 +959,8 @@ def label_multiline(layout, text='', icon='NONE', width=-1, max_lines=10): if li > max_lines: break; row = layout.row() + if split_last > 0: + row = row.split(factor=split_last) row.label(text=l, icon=icon) rows.append(row) icon = 'NONE' @@ -965,5 +968,20 @@ def label_multiline(layout, text='', icon='NONE', width=-1, max_lines=10): return rows +def is_upload_old(asset_data): + ''' + estimates if the asset is far too long in the 'uploaded' state + This returns the number of days the validation is over the limit. + ''' + date_time_str = asset_data["created"][:10] + # date_time_str = 'Jun 28 2018 7:40AM' + date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d') + today = date_time_obj.today() + age = today - date_time_obj + old = datetime.timedelta(days=5) + if age > old: + return (age.days - old.days) + return 0 + def trace(): traceback.print_stack() |