diff options
-rw-r--r-- | blenderkit/bkit_oauth.py | 6 | ||||
-rw-r--r-- | blenderkit/colors.py | 1 | ||||
-rw-r--r-- | blenderkit/search.py | 161 | ||||
-rw-r--r-- | blenderkit/thumbnails/rating_ui_empty.png | bin | 0 -> 29345 bytes | |||
-rw-r--r-- | blenderkit/ui.py | 146 |
5 files changed, 218 insertions, 96 deletions
diff --git a/blenderkit/bkit_oauth.py b/blenderkit/bkit_oauth.py index 6685ff2c..5350ae74 100644 --- a/blenderkit/bkit_oauth.py +++ b/blenderkit/bkit_oauth.py @@ -19,6 +19,7 @@ if "bpy" in locals(): from importlib import reload + ui = reload(ui) tasks_queue = reload(tasks_queue) utils = reload(utils) paths = reload(paths) @@ -26,7 +27,7 @@ if "bpy" in locals(): categories = reload(categories) oauth = reload(oauth) else: - from blenderkit import tasks_queue, utils, paths, search, categories, oauth + from blenderkit import tasks_queue, utils, paths, search, categories, oauth, ui import bpy @@ -75,7 +76,8 @@ def write_tokens(auth_token, refresh_token): preferences.api_key = auth_token preferences.login_attempt = False props = utils.get_search_props() - props.report = 'Login success!' + props.report = '' + ui.add_report('BlenderKit Login success') search.get_profile() categories.fetch_categories_thread(auth_token) diff --git a/blenderkit/colors.py b/blenderkit/colors.py index 42545941..d01bdb0a 100644 --- a/blenderkit/colors.py +++ b/blenderkit/colors.py @@ -18,5 +18,6 @@ # this module defines color palette for BlenderKit UI +TEXT = (.9, .9, .9, .6) GREEN = (.9, 1, .9, .6) RED = (1, .5, .5, .8)
\ No newline at end of file diff --git a/blenderkit/search.py b/blenderkit/search.py index c1adf9b0..1123f879 100644 --- a/blenderkit/search.py +++ b/blenderkit/search.py @@ -160,7 +160,7 @@ def timer_update(): # TODO might get moved to handle all blenderkit stuff. for r in rdata['results']: if r['assetType'] == asset_type: - # print(r) + # utils.pprint(r) if len(r['files']) > 0: furl = None tname = None @@ -304,10 +304,11 @@ def load_previews(): # line splitting for longer texts... -def split_subs(text): +def split_subs(text, threshold=40): if text == '': return [] - threshold = 40 + # temporarily disable this, to be able to do this in drawing code + text = text.rstrip() lines = [] @@ -333,14 +334,14 @@ def list_to_str(input): return output -def writeblock(t, input): # for longer texts - dlines = split_subs(input) +def writeblock(t, input, width=40): # for longer texts + dlines = split_subs(input, threshold=width) for i, l in enumerate(dlines): t += '%s\n' % l return t -def writeblockm(tooltip, mdata, key='', pretext=None): # for longer texts +def writeblockm(tooltip, mdata, key='', pretext=None, width=40): # for longer texts if mdata.get(key) == None: return tooltip else: @@ -357,7 +358,7 @@ def writeblockm(tooltip, mdata, key='', pretext=None): # for longer texts if pretext != '': pretext = pretext + ': ' text = pretext + intext - dlines = split_subs(text) + dlines = split_subs(text, threshold=width) for i, l in enumerate(dlines): tooltip += '%s\n' % l @@ -384,14 +385,16 @@ def params_to_dict(params): def generate_tooltip(mdata): + col_w = 40 if type(mdata['parameters']) == list: mparams = params_to_dict(mdata['parameters']) else: mparams = mdata['parameters'] t = '' - t = writeblock(t, mdata['name']) + t = writeblock(t, mdata['name'], width=col_w) + t += '\n' - t = writeblockm(t, mdata, key='description', pretext='') + t = writeblockm(t, mdata, key='description', pretext='', width=col_w) if mdata['description'] != '': t += '\n' @@ -407,20 +410,20 @@ def generate_tooltip(mdata): for b in bools_data: if mdata.get(b) and mdata[b]: mdata['tags'].append(b) - t = writeblockm(t, mparams, key='designer', pretext='designer') - t = writeblockm(t, mparams, key='manufacturer', pretext='manufacturer') - t = writeblockm(t, mparams, key='designCollection', pretext='design collection') - - # t = writeblockm(t, mparams, key='engines', pretext='engine') - # t = writeblockm(t, mparams, key='model_style', pretext='style') - # t = writeblockm(t, mparams, key='material_style', pretext='style') - # t = writeblockm(t, mdata, key='tags') - # t = writeblockm(t, mparams, key='condition', pretext='condition') - # t = writeblockm(t, mparams, key='productionLevel', pretext='production level') + t = writeblockm(t, mparams, key='designer', pretext='designer', width=col_w) + t = writeblockm(t, mparams, key='manufacturer', pretext='manufacturer', width=col_w) + t = writeblockm(t, mparams, key='designCollection', pretext='design collection', width=col_w) + + # t = writeblockm(t, mparams, key='engines', pretext='engine', width = col_w) + # t = writeblockm(t, mparams, key='model_style', pretext='style', width = col_w) + # t = writeblockm(t, mparams, key='material_style', pretext='style', width = col_w) + # t = writeblockm(t, mdata, key='tags', width = col_w) + # t = writeblockm(t, mparams, key='condition', pretext='condition', width = col_w) + # t = writeblockm(t, mparams, key='productionLevel', pretext='production level', width = col_w) if has(mdata, 'purePbr'): - t = writeblockm(t, mparams, key='pbrType', pretext='pbr') + t = writeblockm(t, mparams, key='pbrType', pretext='pbr', width=col_w) - t = writeblockm(t, mparams, key='designYear', pretext='design year') + t = writeblockm(t, mparams, key='designYear', pretext='design year', width=col_w) if has(mparams, 'dimensionX'): t += 'size: %s, %s, %s\n' % (fmt_length(mparams['dimensionX']), @@ -429,65 +432,87 @@ def generate_tooltip(mdata): if has(mparams, 'faceCount'): t += 'face count: %s, render: %s\n' % (mparams['faceCount'], mparams['faceCountRender']) - # t = writeblockm(t, mparams, key='meshPolyType', pretext='mesh type') - # t = writeblockm(t, mparams, key='objectCount', pretext='nubmber of objects') + # t = writeblockm(t, mparams, key='meshPolyType', pretext='mesh type', width = col_w) + # t = writeblockm(t, mparams, key='objectCount', pretext='nubmber of objects', width = col_w) - # t = writeblockm(t, mparams, key='materials') - # t = writeblockm(t, mparams, key='modifiers') - # t = writeblockm(t, mparams, key='shaders') + # t = writeblockm(t, mparams, key='materials', width = col_w) + # t = writeblockm(t, mparams, key='modifiers', width = col_w) + # t = writeblockm(t, mparams, key='shaders', width = col_w) if has(mparams, 'textureSizeMeters'): t += 'texture size: %s\n' % fmt_length(mparams['textureSizeMeters']) if has(mparams, 'textureResolutionMax') and mparams['textureResolutionMax'] > 0: if mparams['textureResolutionMin'] == mparams['textureResolutionMax']: - t = writeblockm(t, mparams, key='textureResolutionMin', pretext='texture resolution') + t = writeblockm(t, mparams, key='textureResolutionMin', pretext='texture resolution', width=col_w) else: t += 'tex resolution: %i - %i\n' % (mparams['textureResolutionMin'], mparams['textureResolutionMax']) if has(mparams, 'thumbnailScale'): - t = writeblockm(t, mparams, key='thumbnailScale', pretext='preview scale') + t = writeblockm(t, mparams, key='thumbnailScale', pretext='preview scale', width=col_w) # t += 'uv: %s\n' % mdata['uv'] - t += '\n' - # t = writeblockm(t, mdata, key='license') + # t += '\n' + # t = writeblockm(t, mdata, key='license', width = col_w) # generator is for both upload preview and search, this is only after search - if mdata.get('versionNumber'): - # t = writeblockm(t, mdata, key='versionNumber', pretext='version') - a_id = mdata['author'].get('id') - if a_id != None: - adata = bpy.context.window_manager['bkit authors'].get(str(a_id)) - if adata != None: - t += generate_author_textblock(adata) - - t += '\n' - t += get_random_tip(mdata) + # if mdata.get('versionNumber'): + # # t = writeblockm(t, mdata, key='versionNumber', pretext='version', width = col_w) + # a_id = mdata['author'].get('id') + # if a_id != None: + # adata = bpy.context.window_manager['bkit authors'].get(str(a_id)) + # if adata != None: + # t += generate_author_textblock(adata) + + # t += '\n' + if len(t.split('\n')) < 6: + t += '\n' + t += get_random_tip(mdata) + t += '\n' return t def get_random_tip(mdata): - at = mdata['assetType'] t = '' - if at == 'brush' or at == 'texture': - t += 'click to link %s' % mdata['assetType'] - if at == 'model' or at == 'material': - tips = ['Click or drag in scene to link/append %s' % mdata['assetType'], - "'A' key to search assets by same author", - "'W' key to open Authors webpage", - ] - tip = 'Tip: ' + random.choice(tips) - t = writeblock(t, tip) + rtips = ['Click or drag model or material in scene to link/append ', + "Click on brushes to link them into scene.", + "All materials are free.", + "All brushes are free.", + "Locked models are available if you subscribe to standard plan.", + "Login to upload your own models, materials or brushes.", + "Use 'A' key to search assets by same author.", + "Use 'W' key to open Authors webpage.", ] + tip = 'Tip: ' + random.choice(rtips) + t = writeblock(t, tip) + return t + # at = mdata['assetType'] + # if at == 'brush' or at == 'texture': + # t += 'click to link %s' % mdata['assetType'] + # if at == 'model' or at == 'material': + # tips = ['Click or drag in scene to link/append %s' % mdata['assetType'], + # "'A' key to search assets by same author", + # "'W' key to open Authors webpage", + # ] + # tip = 'Tip: ' + random.choice(tips) + # t = writeblock(t, tip) return t def generate_author_textblock(adata): - t = '' + t = '\n\n\n' + if adata not in (None, ''): - t += 'author: %s %s\n' % (adata['firstName'], adata['lastName']) - t = writeblockm(t, adata, key='aboutMe', pretext='about me') - t += '\n' - t = writeblockm(t, adata, key='aboutMeUrl', pretext='') + col_w = 40 + if len(adata['firstName'] + adata['lastName']) > 0: + t = 'Author:\n' + t += '%s %s\n' % (adata['firstName'], adata['lastName']) + t += '\n' + if adata.get('aboutMeUrl') is not None: + t = writeblockm(t, adata, key='aboutMeUrl', pretext='', width=col_w) + t += '\n' + if adata.get('aboutMe') is not None: + t = writeblockm(t, adata, key='aboutMe', pretext='', width=col_w) + t += '\n' return t @@ -551,11 +576,20 @@ def fetch_author(a_id, api_key): a_url = paths.get_api_url() + 'accounts/' + a_id + '/' headers = utils.get_headers(api_key) r = requests.get(a_url, headers=headers) - adata = r.json() - if not hasattr(adata, 'id'): - utils.p(adata) - # utils.p(adata) - tasks_queue.add_task((write_author, (a_id, adata))) + if r.status_code == 200: + adata = r.json() + if not hasattr(adata, 'id'): + utils.p(adata) + # utils.p(adata) + tasks_queue.add_task((write_author, (a_id, adata))) + if adata.get('gravatarHash') is not None: + gravatar_path = paths.get_temp_dir(subdir=None) + adata['gravatarHash'] + '.jpg' + url = "https://www.gravatar.com/avatar/" + adata['gravatarHash'] + '?d=404' + r = requests.get(url, stream=False) + if r.status_code == 200: + with open(gravatar_path, 'wb') as f: + f.write(r.content) + adata['gravatarImg'] = gravatar_path except Exception as e: utils.p(e) utils.p('finish fetch') @@ -568,8 +602,9 @@ def get_author(r): if authors == {}: bpy.context.window_manager['bkit authors'] = authors a = authors.get(a_id) - if a is None or a is '': - authors[a_id] = '' + if a is None or a is '' or \ + (a.get('gravatarHash') is not None and a.get('gravatarImg') is None): + authors[a_id] = None thread = threading.Thread(target=fetch_author, args=(a_id, preferences.api_key), daemon=True) thread.start() return a @@ -1032,7 +1067,7 @@ def search(category='', get_next=False, author_id=''): # query['keywords'] += '+is_free:true' add_search_process(query, params) - tasks_queue.add_task((ui.add_report, ('BlenderKit searching....',2))) + tasks_queue.add_task((ui.add_report, ('BlenderKit searching....', 2))) props.report = 'BlenderKit searching....' diff --git a/blenderkit/thumbnails/rating_ui_empty.png b/blenderkit/thumbnails/rating_ui_empty.png Binary files differnew file mode 100644 index 00000000..f734d98c --- /dev/null +++ b/blenderkit/thumbnails/rating_ui_empty.png diff --git a/blenderkit/ui.py b/blenderkit/ui.py index 727f0927..923cc9a7 100644 --- a/blenderkit/ui.py +++ b/blenderkit/ui.py @@ -99,18 +99,13 @@ def get_approximate_text_width(st): def add_report(text='', timeout=5, color=colors.GREEN): global reports - updated = False - - #check for same reports and just make them longer by the timeout. + # 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 - updated = True - if not updated: - report = Report(text=text, timeout=timeout, color=color) - reports.append(report) - print('added report') - print(report) + return + report = Report(text=text, timeout=timeout, color=color) + reports.append(report) class Report(): @@ -224,7 +219,6 @@ def get_rating_scalevalues(asset_type): xs.append(x) return scalevalues, xs - def draw_ratings_bgl(): # return; ui = bpy.context.scene.blenderkitUI @@ -271,7 +265,15 @@ def draw_ratings_bgl(): ui.rating_ui_width + ui.margin, ui.rating_ui_height + 2 * ui.margin + font_size, bgcol) - img = utils.get_thumbnail('rating_ui.png') + if asset_data['asset_type'] == 'model': + ui_img_name = 'rating_ui.png' + else: + ui_img_name = 'rating_ui_empty.png' + text = 'Try to estimate how many hours it would take to a proffesional artist to create this asset:' + tx = ui.rating_x + ui.workhours_bar_x + # draw_text_block(x=tx, y=ui.rating_y, width=80, font_size=20, line_height=15, text=text, color=colors.TEXT) + + img = utils.get_thumbnail(ui_img_name) ui_bgl.draw_image(ui.rating_x, ui.rating_y - ui.rating_ui_height - 2 * ui.margin, ui.rating_ui_width, @@ -333,26 +335,43 @@ def draw_ratings_bgl(): font_size) -def draw_tooltip(x, y, text='', author='', img=None): +def draw_text_block(x=0, y=0, width=40, font_size=10, line_height=15, text='', color=colors.TEXT): + lines = text.split('\n') + nlines = [] + for l in lines: + nlines.extend(search.split_subs(l, )) + + column_lines = 0 + for l in nlines: + ytext = y - column_lines * line_height + column_lines += 1 + ui_bgl.draw_text(l, x, ytext, font_size, color) + + +def draw_tooltip(x, y, text='', author='', img=None, gravatar=None): region = bpy.context.region scale = bpy.context.preferences.view.ui_scale t = time.time() - ttipmargin = 10 + ttipmargin = 5 + textmargin = 10 font_height = int(12 * scale) line_height = int(15 * scale) nameline_height = int(23 * scale) lines = text.split('\n') + alines = author.split('\n') ncolumns = 2 - nlines = math.ceil((len(lines) - 1) / ncolumns) + # nlines = math.ceil((len(lines) - 1) / ncolumns) + nlines = max(len(lines) - 1, len(alines)) # math.ceil((len(lines) - 1) / ncolumns) + texth = line_height * nlines + nameline_height isizex = int(512 * scale * img.size[0] / max(img.size[0], img.size[1])) isizey = int(512 * scale * img.size[1] / max(img.size[0], img.size[1])) - estimated_height = 3 * ttipmargin + isizey + estimated_height = 2 * ttipmargin + textmargin + isizey if estimated_height > y: scaledown = y / (estimated_height) @@ -363,7 +382,7 @@ def draw_tooltip(x, y, text='', author='', img=None): nameline_height = int(23 * scale) lines = text.split('\n') - ncolumns = 2 + nlines = math.ceil((len(lines) - 1) / ncolumns) texth = line_height * nlines + nameline_height @@ -392,30 +411,39 @@ def draw_tooltip(x, y, text='', author='', img=None): textcol_strong = (textcol[0] * 1.3, textcol[1] * 1.3, textcol[2] * 1.3, 1) white = (1, 1, 1, .1) + # background ui_bgl.draw_rect(x - ttipmargin, y - 2 * ttipmargin - isizey, isizex + ttipmargin * 2, 2 * ttipmargin + isizey, bgcol) + # main preview image ui_bgl.draw_image(x, y - isizey - ttipmargin, isizex, isizey, img, 1) + # text overlay background ui_bgl.draw_rect(x - ttipmargin, y - 2 * ttipmargin - isizey, isizex + ttipmargin * 2, 2 * ttipmargin + texth, bgcol1) + # draw gravatar + gsize = 40 + if gravatar is not None: + # ui_bgl.draw_image(x + isizex - gsize - textmargin, y - isizey + texth - gsize - nameline_height - textmargin, + # gsize, gsize, gravatar, 1) + ui_bgl.draw_image(x + isizex / 2 + textmargin, y - isizey + texth - gsize - nameline_height - textmargin, + gsize, gsize, gravatar, 1) + i = 0 - column_break = -1 # start minus one for the name - xtext = x + ttipmargin + column_lines = -1 # start minus one for the name + xtext = x + textmargin fsize = name_height tcol = textcol + for l in lines: - if column_break >= nlines: - xtext += int(isizex / ncolumns) - column_break = 0 - ytext = y - column_break * line_height - nameline_height - ttipmargin * 2 - isizey + texth + ytext = y - column_lines * line_height - nameline_height - ttipmargin - textmargin - isizey + texth if i == 0: - ytext = y - name_height + 5 - isizey + texth - ttipmargin + ytext = y - name_height + 5 - isizey + texth - textmargin elif i == len(lines) - 1: ytext = y - (nlines - 1) * line_height - nameline_height - ttipmargin * 2 - isizey + texth tcol = textcol @@ -425,8 +453,52 @@ def draw_tooltip(x, y, text='', author='', img=None): tcol = textcol_strong fsize = font_height i += 1 - column_break += 1 + column_lines += 1 ui_bgl.draw_text(l, xtext, ytext, fsize, tcol) + xtext += int(isizex / ncolumns) + + column_lines = 1 + for l in alines: + if gravatar is not None: + if column_lines == 1: + xtext += gsize + textmargin + if column_lines == 4: + xtext -= gsize + textmargin + + ytext = y - column_lines * line_height - nameline_height - ttipmargin - textmargin - isizey + texth + if i == 0: + ytext = y - name_height + 5 - isizey + texth - textmargin + elif i == len(lines) - 1: + ytext = y - (nlines - 1) * line_height - nameline_height - ttipmargin * 2 - isizey + texth + tcol = textcol + tsize = font_height + else: + if l[:4] == 'Tip:': + tcol = textcol_strong + fsize = font_height + i += 1 + column_lines += 1 + ui_bgl.draw_text(l, xtext, ytext, fsize, tcol) + + # for l in lines: + # if column_lines >= nlines: + # xtext += int(isizex / ncolumns) + # column_lines = 0 + # ytext = y - column_lines * line_height - nameline_height - ttipmargin - textmargin - isizey + texth + # if i == 0: + # ytext = y - name_height + 5 - isizey + texth - textmargin + # elif i == len(lines) - 1: + # ytext = y - (nlines - 1) * line_height - nameline_height - ttipmargin * 2 - isizey + texth + # tcol = textcol + # tsize = font_height + # else: + # if l[:4] == 'Tip:': + # tcol = textcol_strong + # fsize = font_height + # i += 1 + # column_lines += 1 + # ui_bgl.draw_text(l, xtext, ytext, fsize, tcol) + t = time.time() @@ -494,15 +566,15 @@ def draw_tooltip_old(x, y, text='', author='', img=None): bgcol) i = 0 - column_break = -1 # start minus one for the name + column_lines = -1 # start minus one for the name xtext = x fsize = name_height tcol = textcol for l in lines: - if column_break >= nlines: + if column_lines >= nlines: xtext += int(isizex / ncolumns) - column_break = 0 - ytext = y - column_break * line_height - nameline_height - ttipmargin + column_lines = 0 + ytext = y - column_lines * line_height - nameline_height - ttipmargin if i == 0: ytext = y - name_height + 5 elif i == len(lines) - 1: @@ -514,7 +586,7 @@ def draw_tooltip_old(x, y, text='', author='', img=None): tcol = textcol1 fsize = font_height i += 1 - column_break += 1 + column_lines += 1 ui_bgl.draw_text(l, xtext, ytext, fsize, tcol) t = time.time() ui_bgl.draw_image(x, y - texth - isizey - ttipmargin, isizex, isizey, img, 1) @@ -761,7 +833,8 @@ def draw_callback_2d_search(self, context): img = bpy.data.images.get(iname) if img == None or img.filepath != tpath: - if os.path.exists(tpath): # sometimes we are unlucky... + # TODO replace it with a function + if os.path.exists(tpath): if img is None: img = bpy.data.images.load(tpath) @@ -778,7 +851,18 @@ def draw_callback_2d_search(self, context): iname = utils.previmg_name(ui_props.active_index) img = bpy.data.images.get(iname) img.colorspace_settings.name = 'Linear' - draw_tooltip(ui_props.mouse_x, ui_props.mouse_y, text=ui_props.tooltip, img=img) + + 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']) + if a is not None and a != '': + if a.get('gravatarImg') is not None: + gimg = utils.get_hidden_image(a['gravatarImg'], a['gravatarHash']) + atip = a['tooltip'] + + draw_tooltip(ui_props.mouse_x, ui_props.mouse_y, text=ui_props.tooltip, author=atip, img=img, + gravatar=gimg) if ui_props.dragging and ( ui_props.draw_drag_image or ui_props.draw_snapped_bounds) and ui_props.active_index > -1: |