Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVilem Duha <vilem.duha@gmail.com>2021-07-01 13:09:55 +0300
committerJeroen Bakker <jeroen@blender.org>2021-07-26 09:08:10 +0300
commit526557bba142a359b9aad773cecf5d702577eb2e (patch)
treece7a6db6561821e0dd834ec1fa5d1dc613f9c179
parent0d880d1273a3640a089b5fa6c75d4cc67efb4c62 (diff)
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
-rw-r--r--blenderkit/__init__.py29
-rw-r--r--blenderkit/bg_blender.py7
-rw-r--r--blenderkit/categories.py1
-rw-r--r--blenderkit/download.py43
-rw-r--r--blenderkit/paths.py2
-rw-r--r--blenderkit/rerequests.py14
-rw-r--r--blenderkit/search.py64
-rw-r--r--blenderkit/tasks_queue.py4
-rw-r--r--blenderkit/thumbnails/intro.jpgbin0 -> 66605 bytes
-rw-r--r--blenderkit/ui.py16
-rw-r--r--blenderkit/ui_panels.py68
-rw-r--r--blenderkit/utils.py16
12 files changed, 204 insertions, 60 deletions
diff --git a/blenderkit/__init__.py b/blenderkit/__init__.py
index e8043626..c58e5d99 100644
--- a/blenderkit/__init__.py
+++ b/blenderkit/__init__.py
@@ -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():
diff --git a/blenderkit/bg_blender.py b/blenderkit/bg_blender.py
index 01c62538..c4294b30 100644
--- a/blenderkit/bg_blender.py
+++ b/blenderkit/bg_blender.py
@@ -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.
diff --git a/blenderkit/categories.py b/blenderkit/categories.py
index 46d10f86..3a0d2624 100644
--- a/blenderkit/categories.py
+++ b/blenderkit/categories.py
@@ -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'''
diff --git a/blenderkit/download.py b/blenderkit/download.py
index 7cffff44..f0c101a1 100644
--- a/blenderkit/download.py
+++ b/blenderkit/download.py
@@ -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)
diff --git a/blenderkit/paths.py b/blenderkit/paths.py
index 0ca55271..57511108 100644
--- a/blenderkit/paths.py
+++ b/blenderkit/paths.py
@@ -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/"
diff --git a/blenderkit/rerequests.py b/blenderkit/rerequests.py
index 6a2659c2..f9c51559 100644
--- a/blenderkit/rerequests.py
+++ b/blenderkit/rerequests.py
@@ -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
diff --git a/blenderkit/search.py b/blenderkit/search.py
index d6e89a7b..23440b7c 100644
--- a/blenderkit/search.py
+++ b/blenderkit/search.py
@@ -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,13 +422,21 @@ 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
result_field = []
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()
+
+
+
for r in rdata['results']:
asset_data = parse_result(r)
if asset_data != None:
@@ -443,7 +458,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
@@ -453,7 +467,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)
@@ -462,6 +476,7 @@ def timer_update():
# print('finished search thread')
mt('preview loading finished')
+ # utils.p('end search timer')
return .3
@@ -638,6 +653,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)
@@ -651,6 +667,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):
@@ -796,7 +814,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:
@@ -839,6 +858,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'])
@@ -852,6 +873,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 ')
@@ -871,10 +894,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')
@@ -892,7 +919,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']
@@ -941,10 +968,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
@@ -969,6 +998,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:
@@ -980,6 +1011,8 @@ class Searcher(threading.Thread):
i += 1
if self.stopped():
+ # utils.p('end search thread')
+
utils.p('stopping search : ' + str(query))
return
@@ -991,6 +1024,7 @@ class Searcher(threading.Thread):
# daemon=True)
thread.start()
thumb_full_download_threads[imgpath] = thread
+ # utils.p('end search thread')
mt('thumbnails finished')
@@ -998,7 +1032,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()
@@ -1500,7 +1536,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()
@@ -1511,5 +1547,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)
diff --git a/blenderkit/tasks_queue.py b/blenderkit/tasks_queue.py
index f52cfd63..0d991878 100644
--- a/blenderkit/tasks_queue.py
+++ b/blenderkit/tasks_queue.py
@@ -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
diff --git a/blenderkit/thumbnails/intro.jpg b/blenderkit/thumbnails/intro.jpg
new file mode 100644
index 00000000..52ce56e3
--- /dev/null
+++ b/blenderkit/thumbnails/intro.jpg
Binary files differ
diff --git a/blenderkit/ui.py b/blenderkit/ui.py
index 25d6fca5..7b51eb65 100644
--- a/blenderkit/ui.py
+++ b/blenderkit/ui.py
@@ -486,12 +486,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)
@@ -1189,8 +1191,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()
@@ -1448,7 +1450,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'}
@@ -1623,6 +1625,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,
diff --git a/blenderkit/ui_panels.py b/blenderkit/ui_panels.py
index 3c5f4dcf..fe91658c 100644
--- a/blenderkit/ui_panels.py
+++ b/blenderkit/ui_panels.py
@@ -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)
diff --git a/blenderkit/utils.py b/blenderkit/utils.py
index bae1244d..3d1f3eae 100644
--- a/blenderkit/utils.py
+++ b/blenderkit/utils.py
@@ -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: