Merge branch 'master' into xr-controller-support
This commit is contained in:
commit
2528deb849
|
@ -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():
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
@ -81,11 +81,35 @@ def get_category_path(categories, category):
|
|||
slug = ch['slug']
|
||||
while parents.get(slug):
|
||||
slug = parents.get(slug)
|
||||
|
||||
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'''
|
||||
category_path = []
|
||||
check_categories = categories[:]
|
||||
parents = {}
|
||||
utils.pprint(categories)
|
||||
while len(check_categories) > 0:
|
||||
ccheck = check_categories.pop()
|
||||
# print(ccheck['name'])
|
||||
if not ccheck.get('children'):
|
||||
continue
|
||||
|
||||
for ch in ccheck['children']:
|
||||
# print(ch['name'])
|
||||
parents[ch['slug']] = ccheck['slug']
|
||||
|
||||
if ch['slug'] == category:
|
||||
category_path = [ch['slug']]
|
||||
slug = ch['slug']
|
||||
while parents.get(slug):
|
||||
slug = parents.get(slug)
|
||||
category_path.insert(0, slug)
|
||||
return category_path
|
||||
check_categories.append(ch)
|
||||
|
||||
def get_category(categories, cat_path=()):
|
||||
for category in cat_path:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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/"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
||||
|
||||
|
@ -432,14 +444,14 @@ def timer_update():
|
|||
result_field.append(asset_data)
|
||||
|
||||
# Get ratings from BlenderKit server
|
||||
if utils.profile_is_validator():
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
api_key = user_preferences.api_key
|
||||
headers = utils.get_headers(api_key)
|
||||
for r in rdata['results']:
|
||||
if ratings_utils.get_rating_local(asset_data['id']) is None:
|
||||
thread = threading.Thread(target=ratings_utils.get_rating, args=([r['id'], headers]), daemon=True)
|
||||
thread.start()
|
||||
# if utils.profile_is_validator():
|
||||
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
api_key = user_preferences.api_key
|
||||
headers = utils.get_headers(api_key)
|
||||
for r in rdata['results']:
|
||||
if ratings_utils.get_rating_local(asset_data['id']) is None:
|
||||
rating_thread = threading.Thread(target=ratings_utils.get_rating, args=([r['id'], headers]), daemon=True)
|
||||
rating_thread.start()
|
||||
|
||||
wm[search_name] = result_field
|
||||
wm['search results'] = result_field
|
||||
|
@ -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()
|
||||
|
@ -1215,7 +1248,7 @@ def get_search_simple(parameters, filepath=None, page_size=100, max_results=1000
|
|||
requeststring += '&page_size=' + str(page_size)
|
||||
bk_logger.debug(requeststring)
|
||||
response = rerequests.get(requeststring, headers=headers) # , params = rparameters)
|
||||
# print(r.json())
|
||||
# print(response.json())
|
||||
search_results = response.json()
|
||||
|
||||
results = []
|
||||
|
@ -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)
|
||||
|
|
|
@ -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 |
|
@ -371,13 +371,17 @@ def draw_tooltip_with_author(asset_data, x, y):
|
|||
|
||||
img = get_large_thumbnail_image(asset_data)
|
||||
gimg = None
|
||||
atip = ''
|
||||
author_text = ''
|
||||
|
||||
if bpy.context.window_manager.get('bkit authors') is not None:
|
||||
a = bpy.context.window_manager['bkit authors'].get(asset_data['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'])
|
||||
|
||||
if len(a['firstName'])>0 or len(a['lastName'])>0:
|
||||
author_text = f"by {a['firstName']} {a['lastName']}"
|
||||
|
||||
aname = asset_data['displayName']
|
||||
aname = aname[0].upper() + aname[1:]
|
||||
if len(aname) > 36:
|
||||
|
@ -388,12 +392,9 @@ def draw_tooltip_with_author(asset_data, x, y):
|
|||
rcount = 0
|
||||
quality = '-'
|
||||
if rc:
|
||||
rcount = min(rc['quality'], rc['workingHours'])
|
||||
rcount = min(rc.get('quality',0), rc.get('workingHours',0))
|
||||
if rcount > show_rating_threshold:
|
||||
quality = round(asset_data['ratingsAverage'].get('quality'))
|
||||
author_text = ''
|
||||
if len(a['firstName'])>0 or len(a['lastName'])>0:
|
||||
author_text = f"by {a['firstName']} {a['lastName']}"
|
||||
|
||||
draw_tooltip(x, y, name=aname, author=author_text, quality=quality, img=img,
|
||||
gravatar=gimg)
|
||||
|
@ -482,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)
|
||||
|
@ -1191,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()
|
||||
|
||||
|
@ -1450,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'}
|
||||
|
@ -1625,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,
|
||||
|
|
|
@ -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):
|
||||
|
@ -1468,6 +1503,7 @@ class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties):
|
|||
box.scale_y = 0.4
|
||||
box.label(text='Properties')
|
||||
box.separator()
|
||||
|
||||
if self.asset_data.get('license') == 'cc_zero':
|
||||
t = 'CC Zero '
|
||||
icon = pcoll['cc0']
|
||||
|
@ -1778,9 +1814,19 @@ 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(bcats,
|
||||
self.asset_data['category'])[1:]
|
||||
for i,c in enumerate(cat_path):
|
||||
cat_path[i] = c.capitalize()
|
||||
cat_path = ' > '.join(cat_path)
|
||||
# box.label(text=cat_path)
|
||||
|
||||
aname = asset_data['displayName']
|
||||
aname = aname[0].upper() + aname[1:]
|
||||
top_drag_bar.label(text=aname)
|
||||
|
||||
top_drag_bar.label(text=f'{cat_path} > {aname}')
|
||||
|
||||
# left side
|
||||
row = layout.row(align=True)
|
||||
|
@ -1811,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)
|
||||
|
|
|
@ -731,7 +731,6 @@ class FastMetadata(bpy.types.Operator):
|
|||
active_asset = utils.get_active_asset_by_type(asset_type = self.asset_type)
|
||||
asset_data = active_asset.get('asset_data')
|
||||
|
||||
print('can edit asset?', can_edit_asset(asset_data=asset_data))
|
||||
if not can_edit_asset(asset_data=asset_data):
|
||||
return {'CANCELLED'}
|
||||
self.asset_id = asset_data['id']
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
import bpy
|
||||
import math
|
||||
from mathutils import Vector, Matrix, Color
|
||||
from rna_prop_ui import rna_idprop_ui_prop_get
|
||||
|
||||
from .errors import MetarigError
|
||||
from .naming import get_name, make_derived_name, is_control_bone
|
||||
|
|
|
@ -429,7 +429,7 @@ def copy_custom_properties(src, dest, *, prefix='', dest_prefix='', link_driver=
|
|||
if key.startswith(prefix) and key not in exclude:
|
||||
new_key = dest_prefix + key[len(prefix):]
|
||||
|
||||
info = rna_idprop_ui_prop_get(src, key, False)
|
||||
info = rna_idprop_ui_prop_get(src, key, create=False)
|
||||
|
||||
if src != dest or new_key != key:
|
||||
dest[new_key] = value
|
||||
|
|
Loading…
Reference in New Issue