BlenderKit: many post-release fixes

Fix for rerequests recursion crash
rename timers
fix manual link
attemt to fix mysterious crashes on some machines by limiting some calls to assetbar operator, and not copying image into it's preview so often
fix search when & was present
add a popup when appending a scene
improve starup dialog with an image
This commit is contained in:
Vilem Duha 2021-07-01 12:09:55 +02:00
parent 620bb458da
commit c84f831539
12 changed files with 201 additions and 60 deletions

View File

@ -155,10 +155,10 @@ def scene_load(context):
@bpy.app.handlers.persistent
def check_timers_timer():
''' checks if all timers are registered regularly. Prevents possible bugs from stopping the addon.'''
if not bpy.app.timers.is_registered(search.timer_update):
bpy.app.timers.register(search.timer_update)
if not bpy.app.timers.is_registered(download.timer_update):
bpy.app.timers.register(download.timer_update)
if not bpy.app.timers.is_registered(search.search_timer):
bpy.app.timers.register(search.search_timer)
if not bpy.app.timers.is_registered(download.download_timer):
bpy.app.timers.register(download.download_timer)
if not (bpy.app.timers.is_registered(tasks_queue.queue_worker)):
bpy.app.timers.register(tasks_queue.queue_worker)
if not bpy.app.timers.is_registered(bg_blender.bg_update):
@ -1542,7 +1542,7 @@ class BlenderKitSceneSearchProps(PropertyGroup, BlenderKitCommonSearchProps):
)
switch_after_append: BoolProperty(
name='Switch to scene after download',
default=False
default=True
)
@ -1714,6 +1714,13 @@ class BlenderKitAddonPreferences(AddonPreferences):
update=utils.save_prefs
)
# single_timer: BoolProperty(
# name="Use timers",
# description="Use timers for BlenderKit. Usefull for debugging since timers seem to be unstable",
# default=True,
# update=utils.save_prefs
# )
experimental_features: BoolProperty(
name="Enable experimental features",
description="Enable all experimental features of BlenderKit. Use at your own risk.",
@ -1773,6 +1780,15 @@ class BlenderKitAddonPreferences(AddonPreferences):
layout.prop(self, "categories_fix")
# # @bpy.app.handlers.persistent
# def blenderkit_timer():
#
#
# if not user_preferences.use_timers:
# search.search_timer()
# download.download_timer()
# tasks_queue.queue_worker()
# bg_blender.bg_update()
# registration
classes = (
@ -1800,6 +1816,7 @@ classes = (
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
@ -1874,6 +1891,8 @@ def register():
if a.type == 'PREFERENCES':
tasks_queue.add_task((bpy.ops.wm.blenderkit_welcome, ('INVOKE_DEFAULT',)), fake_context=True,
fake_context_area='PREFERENCES')
#save preferences after manually enabling the addon
tasks_queue.add_task((bpy.ops.wm.save_userpref, ()), fake_context=False,)
def unregister():

View File

@ -108,11 +108,14 @@ def bg_update():
'''monitoring of background process'''
text = ''
#utils.p('timer search')
# utils.p('start bg_blender timer bg_update')
s = bpy.context.scene
global bg_processes
if len(bg_processes) == 0:
# utils.p('end bg_blender timer bg_update')
return 2
#cleanup dead processes first
remove_processes = []
@ -156,7 +159,11 @@ def bg_update():
# if len(bg_processes) == 0:
# bpy.app.timers.unregister(bg_update)
if len(bg_processes) > 0:
# utils.p('end bg_blender timer bg_update')
return .3
# utils.p('end bg_blender timer bg_update')
return 1.

View File

@ -84,6 +84,7 @@ def get_category_path(categories, category):
category_path.insert(0, slug)
return category_path
check_categories.append(ch)
return category_path
def get_category_name_path(categories, category):
'''finds the category in all possible subcategories and returns the path to it'''

View File

@ -17,7 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
from blenderkit import paths, append_link, utils, ui, colors, tasks_queue, rerequests, resolutions
from blenderkit import paths, append_link, utils, ui, colors, tasks_queue, rerequests, resolutions, ui_panels
import threading
import time
@ -62,7 +62,7 @@ def check_missing():
for l in missing:
asset_data = l['asset_data']
downloaded = check_existing(asset_data, resolution=asset_data['resolution'])
downloaded = check_existing(asset_data, resolution=asset_data.get('resolution'))
if downloaded:
try:
l.reload()
@ -315,11 +315,11 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
sprops = s.blenderkit_scene
scene = append_link.append_scene(file_names[0], link=sprops.append_link == 'LINK', fake_user=False)
print('scene appended')
# print('scene appended')
if scene is not None:
props = scene.blenderkit
asset_main = scene
print(sprops.switch_after_append)
# print(sprops.switch_after_append)
if sprops.switch_after_append:
bpy.context.window_manager.windows[0].scene = scene
@ -563,7 +563,7 @@ def replace_resolution_appended(file_paths, asset_data, resolution):
# @bpy.app.handlers.persistent
def timer_update():
def download_timer():
# TODO might get moved to handle all blenderkit stuff, not to slow down.
'''
check for running and finished downloads.
@ -571,10 +571,14 @@ def timer_update():
Finished downloads are processed and linked/appended to scene.
'''
global download_threads
# utils.p('start download timer')
# bk_logger.debug('timer download')
if len(download_threads) == 0:
return 2.0
# utils.p('end download timer')
return 2
s = bpy.context.scene
for threaddata in download_threads:
t = threaddata[0]
@ -589,13 +593,14 @@ def timer_update():
if sr is not None:
for r in sr:
if asset_data['id'] == r['id']:
r['downloaded'] = tcom.progress
r['downloaded'] = 0.5#tcom.progress
if not t.is_alive():
if tcom.error:
sprops = utils.get_search_props()
sprops.report = tcom.report
download_threads.remove(threaddata)
# utils.p('end download timer')
return
file_paths = paths.get_download_filepaths(asset_data, tcom.passargs['resolution'])
@ -661,6 +666,8 @@ def timer_update():
sres['downloaded'] = 100
bk_logger.debug('finished download thread')
# utils.p('end download timer')
return .5
@ -753,6 +760,7 @@ class Downloader(threading.Thread):
# def main_download_thread(asset_data, tcom, scene_id, api_key):
def run(self):
'''try to download file from blenderkit'''
# utils.p('start downloader thread')
asset_data = self.asset_data
tcom = self.tcom
scene_id = self.scene_id
@ -832,6 +840,8 @@ class Downloader(threading.Thread):
tcom.report = f'Unpacking files'
self.asset_data['resolution'] = self.resolution
resolutions.send_to_bg(self.asset_data, file_name, command='unpack')
# utils.p('end downloader thread')
class ThreadCom: # object passed to threads to read background process stdout info
@ -1226,7 +1236,7 @@ def show_enum_values(obj, prop_name):
class BlenderkitDownloadOperator(bpy.types.Operator):
"""Download and link asset to scene. Only link if asset already available locally"""
bl_idname = "scene.blenderkit_download"
bl_label = "BlenderKit Asset Download"
bl_label = "Download"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
# asset_type: EnumProperty(
@ -1258,6 +1268,8 @@ class BlenderkitDownloadOperator(bpy.types.Operator):
invoke_resolution: BoolProperty(name='Replace resolution popup',
description='pop up to ask which resolution to download', default=False)
invoke_scene_settings: BoolProperty(name='Scene import settings popup',
description='pop up scene import settings', default=False)
resolution: EnumProperty(
items=available_resolutions_callback,
@ -1376,7 +1388,10 @@ class BlenderkitDownloadOperator(bpy.types.Operator):
def draw(self, context):
layout = self.layout
layout.prop(self, 'resolution', expand=True, icon_only=False)
if self.invoke_resolution:
layout.prop(self, 'resolution', expand=True, icon_only=False)
if self.invoke_scene_settings:
ui_panels.draw_scene_import_settings(self, context)
def invoke(self, context, event):
# if self.close_window:
@ -1399,6 +1414,8 @@ class BlenderkitDownloadOperator(bpy.types.Operator):
self.resolution = 'ORIGINAL'
return wm.invoke_props_dialog(self)
if self.invoke_scene_settings:
return wm.invoke_props_dialog(self)
# if self.close_window:
# time.sleep(0.1)
# context.area.tag_redraw()
@ -1416,7 +1433,7 @@ def register_download():
bpy.app.handlers.save_pre.append(scene_save)
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
if user_preferences.use_timers:
bpy.app.timers.register(timer_update)
bpy.app.timers.register(download_timer)
def unregister_download():
@ -1424,5 +1441,5 @@ def unregister_download():
bpy.utils.unregister_class(BlenderkitKillDownloadOperator)
bpy.app.handlers.load_post.remove(scene_load)
bpy.app.handlers.save_pre.remove(scene_save)
if bpy.app.timers.is_registered(timer_update):
bpy.app.timers.unregister(timer_update)
if bpy.app.timers.is_registered(download_timer):
bpy.app.timers.unregister(download_timer)

View File

@ -27,7 +27,7 @@ BLENDERKIT_API = "/api/v1/"
BLENDERKIT_REPORT_URL = "usage_report/"
BLENDERKIT_USER_ASSETS = "/my-assets"
BLENDERKIT_PLANS = "/plans/pricing/"
BLENDERKIT_MANUAL = "https://youtu.be/1hVgcQhIAo8"
BLENDERKIT_MANUAL = "https://youtu.be/pSay3yaBWV0"
BLENDERKIT_MODEL_UPLOAD_INSTRUCTIONS_URL = "https://www.blenderkit.com/docs/upload/"
BLENDERKIT_MATERIAL_UPLOAD_INSTRUCTIONS_URL = "https://www.blenderkit.com/docs/uploading-material/"
BLENDERKIT_BRUSH_UPLOAD_INSTRUCTIONS_URL = "https://www.blenderkit.com/docs/uploading-brush/"

View File

@ -22,10 +22,11 @@ from blenderkit import ui, utils, paths, tasks_queue, bkit_oauth
import requests
import bpy
import logging
bk_logger = logging.getLogger('rerequests')
def rerequest(method, url, **kwargs):
def rerequest(method, url, recursion=0, **kwargs):
# first get any additional args from kwargs
immediate = False
if kwargs.get('immediate'):
@ -34,10 +35,11 @@ def rerequest(method, url, **kwargs):
# first normal attempt
try:
response = requests.request(method, url, **kwargs)
except:
return rerequest(method, url, **kwargs)
except Exception as e:
print(e)
return None
bk_logger.debug(url+ str( kwargs))
bk_logger.debug(url + str(kwargs))
bk_logger.debug(response.status_code)
if response.status_code == 401:
@ -53,7 +55,7 @@ def rerequest(method, url, **kwargs):
if user_preferences.api_key != '':
if user_preferences.enable_oauth and user_preferences.api_key_refresh != '':
tasks_queue.add_task((ui.add_report, (
'refreshing token. If this fails, please login in BlenderKit Login panel.', 10)))
'refreshing token. If this fails, please login in BlenderKit Login panel.', 10)))
refresh_url = paths.get_bkit_url()
auth_token, refresh_token, oauth_response = bkit_oauth.refresh_token(
user_preferences.api_key_refresh, refresh_url)
@ -80,7 +82,7 @@ def rerequest(method, url, **kwargs):
tasks_queue.add_task((ui.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)
tasks_queue.add_task((bpy.ops.wm.blenderkit_login, ('INVOKE_DEFAULT',)), fake_context=True)
return response

View File

@ -48,6 +48,7 @@ import copy
import json
import math
import unicodedata
import urllib
import queue
import logging
@ -80,7 +81,7 @@ reports_queue = queue.Queue()
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 and brushes are free.",
"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.",
@ -246,7 +247,7 @@ def parse_result(r):
durl, tname, small_tname = '', '', ''
if r['assetType'] == 'hdr':
tname = paths.extract_filename_from_url(r['thumbnailMiddleUrlNonsquared'])
tname = paths.extract_filename_from_url(r['thumbnailLargeUrlNonsquared'])
else:
tname = paths.extract_filename_from_url(r['thumbnailMiddleUrl'])
small_tname = paths.extract_filename_from_url(r['thumbnailSmallUrl'])
@ -349,10 +350,10 @@ def parse_result(r):
# @bpy.app.handlers.persistent
def timer_update():
def search_timer():
# this makes a first search after opening blender. showing latest assets.
# utils.p('timer search')
# utils.p('start search timer')
global first_time
preferences = bpy.context.preferences.addons['blenderkit'].preferences
if first_time and not bpy.app.background: # first time
@ -367,6 +368,8 @@ def timer_update():
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)
# utils.p('end search timer')
return 3.0
# if preferences.first_run:
@ -377,10 +380,14 @@ def timer_update():
global search_threads
if len(search_threads) == 0:
# utils.p('end search timer')
return 1.0
# don't do anything while dragging - this could switch asset during drag, and make results list length different,
# causing a lot of throuble.
if bpy.context.scene.blenderkitUI.dragging:
# utils.p('end search timer')
return 0.5
for thread in search_threads:
# TODO this doesn't check all processes when one gets removed,
@ -415,6 +422,8 @@ def timer_update():
while not reports_queue.empty():
props.report = str(reports_queue.get())
# utils.p('end search timer')
return .2
rdata = thread[0].result
@ -422,7 +431,10 @@ def timer_update():
ok, error = check_errors(rdata)
if ok:
bpy.ops.object.run_assetbar_fix_context()
ui_props = bpy.context.scene.blenderkitUI
if not ui_props.assetbar_on:
bpy.ops.object.run_assetbar_fix_context()
@ -447,7 +459,6 @@ def timer_update():
wm['search results orig'] = wm[search_name + ' orig']
load_previews()
ui_props = bpy.context.scene.blenderkitUI
if len(result_field) < ui_props.scrolloffset or not (thread[0].params.get('get_next')):
# jump back
ui_props.scrolloffset = 0
@ -457,7 +468,7 @@ def timer_update():
if len(wm['search results']) == 0:
tasks_queue.add_task((ui.add_report, ('No matching results found.',)))
# undo push
bpy.ops.wm.undo_push_context(message='Get BlenderKit search')
# bpy.ops.wm.undo_push_context(message='Get BlenderKit search')
else:
bk_logger.error(error)
@ -466,6 +477,7 @@ def timer_update():
# print('finished search thread')
mt('preview loading finished')
# utils.p('end search timer')
return .3
@ -642,6 +654,7 @@ class ThumbDownloader(threading.Thread):
def run(self):
# print('thumb downloader', self.url)
# utils.p('start thumbdownloader thread')
r = None
try:
r = requests.get(self.url, stream=False)
@ -655,6 +668,8 @@ class ThumbDownloader(threading.Thread):
# with open(path, 'wb') as f:
# for chunk in r.iter_content(1048576*4):
# f.write(chunk)
# utils.p('end thumbdownloader thread')
def write_gravatar(a_id, gravatar_path):
@ -800,7 +815,8 @@ def query_to_url(query={}, params={}):
order.append('-score,_score')
else:
order.append('_score')
requeststring += '+order:' + ','.join(order)
if requeststring.find('+order:')==-1:
requeststring += '+order:' + ','.join(order)
requeststring += '&addon_version=%s' % params['addon_version']
if params.get('scene_uuid') is not None:
@ -843,6 +859,8 @@ class Searcher(threading.Thread):
params = self.params
t = time.time()
# utils.p('start search thread')
mt('search thread started')
# tempdir = paths.get_temp_dir('%s_search' % query['asset_type'])
# json_filepath = os.path.join(tempdir, '%s_searchresult.json' % query['asset_type'])
@ -856,6 +874,8 @@ class Searcher(threading.Thread):
except requests.exceptions.RequestException as e:
bk_logger.error(e)
reports_queue.put(str(e))
# utils.p('end search thread')
return
mt('search response is back ')
@ -875,10 +895,14 @@ class Searcher(threading.Thread):
# 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.
self.result = rdata
# utils.p('end search thread')
return
# print('number of results: ', len(rdata.get('results', [])))
if self.stopped():
utils.p('stopping search : ' + str(query))
# utils.p('end search thread')
return
mt('search finished')
@ -896,7 +920,7 @@ class Searcher(threading.Thread):
thumb_small_filepaths.append(imgpath)
if d["assetType"] == 'hdr':
larege_thumb_url = d['thumbnailMiddleUrlNonsquared']
larege_thumb_url = d['thumbnailLargeUrlNonsquared']
else:
larege_thumb_url = d['thumbnailMiddleUrl']
@ -945,10 +969,12 @@ class Searcher(threading.Thread):
for k in thumb_full_download_threads.keys():
if k not in thumb_full_filepaths:
killthreads_full.append(k) # do actual killing here?
# TODO do the killing/ stopping here! remember threads might have finished inbetween!
# TODO do the killing/ stopping here. remember threads might have finished inbetween.
if self.stopped():
utils.p('stopping search : ' + str(query))
# utils.p('end search thread')
return
# this loop handles downloading of small thumbnails
@ -973,6 +999,8 @@ class Searcher(threading.Thread):
i += 1
if self.stopped():
utils.p('stopping search : ' + str(query))
# utils.p('end search thread')
return
idx = 0
while len(thumb_sml_download_threads) > 0:
@ -984,6 +1012,8 @@ class Searcher(threading.Thread):
i += 1
if self.stopped():
# utils.p('end search thread')
utils.p('stopping search : ' + str(query))
return
@ -995,6 +1025,7 @@ class Searcher(threading.Thread):
# daemon=True)
thread.start()
thumb_full_download_threads[imgpath] = thread
# utils.p('end search thread')
mt('thumbnails finished')
@ -1002,7 +1033,9 @@ def build_query_common(query, props):
'''add shared parameters to query'''
query_common = {}
if props.search_keywords != '':
query_common["query"] = props.search_keywords
# keywords = urllib.parse.urlencode(props.search_keywords)
keywords = props.search_keywords.replace('&','%26')
query_common["query"] = keywords
if props.search_verification_status != 'ALL' and utils.profile_is_validator():
query_common['verification_status'] = props.search_verification_status.lower()
@ -1504,7 +1537,7 @@ def register_search():
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
if user_preferences.use_timers:
bpy.app.timers.register(timer_update)
bpy.app.timers.register(search_timer)
categories.load_categories()
@ -1515,5 +1548,5 @@ 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)
if bpy.app.timers.is_registered(search_timer):
bpy.app.timers.unregister(search_timer)

View File

@ -58,6 +58,8 @@ def add_task(task, wait = 0, only_last = False, fake_context = False, fake_conte
def queue_worker():
# utils.p('start queue worker timer')
#bk_logger.debug('timer queue worker')
time_step = 2.0
q = get_queue()
@ -110,6 +112,8 @@ def queue_worker():
# print('queue while 2')
for task in back_to_queue:
q.put(task)
# utils.p('end queue worker timer')
return 2.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -483,12 +483,14 @@ 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'])
# print('drawing downloader')
if loc is not None:
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, text=tcom.report)
else:
draw_downloader(loc[0], loc[1], percent=tcom.progress, img=img, text=tcom.report)
# utils.p('end drawing downlaoders downloader')
else:
draw_progress(x, y - index * 30, text='downloading %s' % asset_data['name'],
percent=tcom.progress)
@ -1192,8 +1194,8 @@ class AssetBarOperator(bpy.types.Operator):
# 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()
search.search_timer()
download.download_timer()
tasks_queue.queue_worker()
bg_blender.bg_update()
@ -1451,7 +1453,7 @@ class AssetBarOperator(bpy.types.Operator):
if not asset_data.get('canDownload'):
message = "Let's support asset creators and Open source."
link_text = 'Unlock the asset.'
url = paths.get_bkit_url() + '/get-blenderkit/' + asset_data['id'] + '/?from_addon'
url = paths.get_bkit_url() + '/get-blenderkit/' + asset_data['id'] + '/?from_addon=True'
bpy.ops.wm.blenderkit_url_dialog('INVOKE_REGION_WIN', url=url, message=message,
link_text=link_text)
return {'RUNNING_MODAL'}
@ -1626,6 +1628,14 @@ class AssetBarOperator(bpy.types.Operator):
invoke_resolution=True,
max_resolution=asset_data.get('max_resolution', 0)
)
elif ui_props.asset_type == 'SCENE':
bpy.ops.scene.blenderkit_download('INVOKE_DEFAULT',
asset_index=asset_search_index,
# replace_resolution=True,
invoke_resolution=False,
invoke_scene_settings=True,
max_resolution=asset_data.get('max_resolution', 0)
)
else:
bpy.ops.scene.blenderkit_download( # asset_type=ui_props.asset_type,
asset_index=asset_search_index,

View File

@ -36,6 +36,7 @@ from bpy.props import (
import bpy
import os
import random
import logging
bk_logger = logging.getLogger('blenderkit')
@ -887,6 +888,15 @@ class VIEW3D_PT_blenderkit_categories(Panel):
def draw(self, context):
draw_panel_categories(self, context)
def draw_scene_import_settings(self, context):
s = context.scene
props = s.blenderkit_scene
layout = self.layout
layout.prop(props, 'switch_after_append')
# layout.label(text='Import method:')
row = layout.row()
row.prop(props, 'append_link', expand=True, icon_only=False)
class VIEW3D_PT_blenderkit_import_settings(Panel):
bl_category = "BlenderKit"
@ -931,11 +941,8 @@ class VIEW3D_PT_blenderkit_import_settings(Panel):
row.prop(props, 'append_method', expand=True, icon_only=False)
if ui_props.asset_type == 'SCENE':
props = s.blenderkit_scene
layout.prop(props, 'switch_after_append')
layout.label(text='Import method:')
row = layout.row()
row.prop(props, 'append_link', expand=True, icon_only=False)
draw_scene_import_settings(self,context)
if ui_props.asset_type == 'HDR':
props = s.blenderkit_HDR
@ -1113,13 +1120,19 @@ class BlenderKitWelcomeOperator(bpy.types.Operator):
if self.step == 0:
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
message = "BlenderKit connects from Blender to an online, " \
"community built shared library of models, " \
"materials, and brushes. " \
"Use addon preferences to set up where files will be saved in the Global directory setting."
# message = "BlenderKit connects from Blender to an online, " \
# "community built shared library of models, " \
# "materials, and brushes. " \
# "Use addon preferences to set up where files will be saved in the Global directory setting."
#
# utils.label_multiline(layout, text=message, width=300)
layout.template_icon(icon_value=self.img.preview.icon_id, scale=18)
# utils.label_multiline(layout, text="\n Let's start by searching for some cool materials?", width=300)
op = layout.operator("wm.url_open", text='Watch Video Tutorial', icon='QUESTION')
op.url = paths.BLENDERKIT_MANUAL
utils.label_multiline(layout, text=message, width=300)
utils.label_multiline(layout, text="\n Let's start by searching for some cool materials?", width=300)
else:
message = "Operator Tutorial called with invalid step"
@ -1131,14 +1144,36 @@ class BlenderKitWelcomeOperator(bpy.types.Operator):
# bpy.context.window_manager.windows[0].screen.areas[5].spaces[0].show_region_ui = False
print('running search no')
ui_props = bpy.context.scene.blenderkitUI
ui_props.asset_type = 'MATERIAL'
bpy.context.scene.blenderkit_mat.search_keywords = 'ice'
random_searches = [
('MATERIAL','ice'),
('MODEL','car'),
('MODEL','vase'),
('MODEL','grass'),
('MODEL','plant'),
('MODEL','man'),
('MATERIAL','metal'),
('MATERIAL','wood'),
('MATERIAL','floor'),
('MATERIAL','bricks'),
]
random_search = random.choice(random_searches)
ui_props.asset_type = random_search[0]
bpy.context.scene.blenderkit_mat.search_keywords = ''#random_search[1]
bpy.context.scene.blenderkit_mat.search_keywords = '+is_free:true+score_gte:1000+order:-created'#random_search[1]
# search.search()
return {'FINISHED'}
def invoke(self, context, event):
wm = bpy.context.window_manager
return wm.invoke_props_dialog(self)
img = utils.get_thumbnail('intro.jpg')
utils.img_to_preview(img, copy_original = True)
self.img = img
w, a, r = utils.get_largest_area(area_type='VIEW_3D')
if a is not None:
a.spaces.active.show_region_ui = True
return wm.invoke_props_dialog(self, width = 500)
def draw_asset_context_menu(layout, context, asset_data, from_panel=False):
@ -1779,8 +1814,9 @@ class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties):
# top draggabe bar with name of the asset
top_row = layout.row()
top_drag_bar = top_row.box()
bcats = bpy.context.window_manager['bkit_categories']
cat_path = categories.get_category_path(bpy.context.window_manager['bkit_categories'],
cat_path = categories.get_category_path(bcats,
self.asset_data['category'])[1:]
for i,c in enumerate(cat_path):
cat_path[i] = c.capitalize()
@ -1821,6 +1857,8 @@ class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties):
sr = bpy.context.window_manager['search results']
asset_data = sr[ui_props.active_index]
self.img = ui.get_large_thumbnail_image(asset_data)
utils.img_to_preview(self.img, copy_original = True)
self.asset_type = asset_data['assetType']
self.asset_id = asset_data['id']
# self.tex = utils.get_hidden_texture(self.img)

View File

@ -337,9 +337,14 @@ def get_hidden_texture(name, force_reload=False):
return t
def img_to_preview(img):
img.preview.image_size = (img.size[0], img.size[1])
img.preview.image_pixels_float = img.pixels[:]
def img_to_preview(img, copy_original = False):
if bpy.app.version[0]>=3:
img.preview_ensure()
if not copy_original:
return;
if img.preview.image_size != img.size:
img.preview.image_size = (img.size[0], img.size[1])
img.preview.image_pixels_float = img.pixels[:]
# img.preview.icon_size = (img.size[0], img.size[1])
# img.preview.icon_pixels_float = img.pixels[:]
@ -852,11 +857,14 @@ def get_fake_context(context, area_type='VIEW_3D'):
# print(w,a,r)
return C_dict
# def is_url(text):
def label_multiline(layout, text='', icon='NONE', width=-1):
''' draw a ui label, but try to split it in multiple lines.'''
if text.strip() == '':
return
text = text.replace('\r\n','\n')
lines = text.split('\n')
if width > 0:
threshold = int(width / 5.5)
@ -865,6 +873,8 @@ def label_multiline(layout, text='', icon='NONE', width=-1):
maxlines = 8
li = 0
for l in lines:
# if is_url(l):
while len(l) > threshold:
i = l.rfind(' ', 0, threshold)
if i < 1: