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:
Diffstat (limited to 'blenderkit/search.py')
-rw-r--r--blenderkit/search.py211
1 files changed, 134 insertions, 77 deletions
diff --git a/blenderkit/search.py b/blenderkit/search.py
index 87bf45da..56c22dbb 100644
--- a/blenderkit/search.py
+++ b/blenderkit/search.py
@@ -24,12 +24,13 @@ if "bpy" in locals():
utils = reload(utils)
categories = reload(categories)
ui = reload(ui)
+ colors = reload(colors)
bkit_oauth = reload(bkit_oauth)
version_checker = reload(version_checker)
tasks_queue = reload(tasks_queue)
rerequests = reload(rerequests)
else:
- from blenderkit import paths, utils, categories, ui, bkit_oauth, version_checker, tasks_queue, rerequests
+ from blenderkit import paths, utils, categories, ui, colors, bkit_oauth, version_checker, tasks_queue, rerequests
import blenderkit
from bpy.app.handlers import persistent
@@ -80,6 +81,16 @@ thumb_sml_download_threads = {}
thumb_full_download_threads = {}
reports = ''
+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.",
+ "Storage for public assets is unlimited.",
+ "Locked models are available if you subscribe to Full plan.",
+ "Login to upload your own models, materials or brushes.",
+ "Use 'A' key over asset bar to search assets by same author.",
+ "Use 'W' key over asset bar to open Authors webpage.", ]
+
def refresh_token_timer():
''' this timer gets run every time the token needs refresh. It refreshes tokens and also categories.'''
@@ -117,16 +128,37 @@ def fetch_server_data():
first_time = True
+last_clipboard = ''
+
@bpy.app.handlers.persistent
def timer_update(): # TODO might get moved to handle all blenderkit stuff.
- #this makes a first search after opening blender. showing latest assets.
+ # this makes a first search after opening blender. showing latest assets.
global first_time
preferences = bpy.context.preferences.addons['blenderkit'].preferences
if first_time:
first_time = False
if preferences.show_on_start:
search()
+ if preferences.tips_on_start:
+ ui.get_largest_3dview()
+ ui.update_ui_size(ui.active_area, ui.active_region)
+ ui.add_report(text='BlenderKit Tip: ' + random.choice(rtips), timeout=12, color=colors.GREEN)
+
+ # clipboard monitoring to search assets from web
+ global last_clipboard
+ if bpy.context.window_manager.clipboard != last_clipboard:
+ last_clipboard = bpy.context.window_manager.clipboard
+ instr = 'asset_base_id:'
+ if last_clipboard[:len(instr)] == instr:
+ atstr = 'asset_type:'
+ ati = last_clipboard.find(atstr)
+ if ati > -1:
+ at = last_clipboard[ati:]
+
+ search_props = utils.get_search_props()
+ search_props.search_keywords = last_clipboard
+ search()
global search_threads
# don't do anything while dragging - this could switch asset type during drag, and make results list length different,
@@ -134,7 +166,7 @@ def timer_update(): # TODO might get moved to handle all blenderkit stuff.
if len(search_threads) == 0 or bpy.context.scene.blenderkitUI.dragging:
return 1
for thread in search_threads: # TODO this doesn't check all processes when one gets removed,
- # but most of the time only one is running anyway
+ # but most of the time only one is running anyway
if not thread[0].is_alive():
search_threads.remove(thread) #
icons_dir = thread[1]
@@ -220,7 +252,7 @@ def timer_update(): # TODO might get moved to handle all blenderkit stuff.
asset_data['downloaded'] = 0
# parse extra params needed for blender here
- params = params_to_dict(r['parameters'])
+ params = utils.params_to_dict(r['parameters'])
if asset_type == 'model':
if params.get('boundBoxMinX') != None:
@@ -333,11 +365,11 @@ def split_subs(text, threshold=40):
lines = []
while len(text) > threshold:
- #first handle if there's an \n line ending
+ # first handle if there's an \n line ending
i_rn = text.find('\n')
if 1 < i_rn < threshold:
i = i_rn
- text = text.replace('\n','',1)
+ text = text.replace('\n', '', 1)
else:
i = text.rfind(' ', 0, threshold)
i1 = text.rfind(',', 0, threshold)
@@ -403,17 +435,10 @@ def has(mdata, prop):
return False
-def params_to_dict(params):
- params_dict = {}
- for p in params:
- params_dict[p['parameterType']] = p['value']
- return params_dict
-
-
def generate_tooltip(mdata):
col_w = 40
if type(mdata['parameters']) == list:
- mparams = params_to_dict(mdata['parameters'])
+ mparams = utils.params_to_dict(mdata['parameters'])
else:
mparams = mdata['parameters']
t = ''
@@ -479,7 +504,7 @@ def generate_tooltip(mdata):
# t += 'uv: %s\n' % mdata['uv']
# t += '\n'
- # t = writeblockm(t, mdata, key='license', width = col_w)
+ t = writeblockm(t, mdata, key='license', width = col_w)
# generator is for both upload preview and search, this is only after search
# if mdata.get('versionNumber'):
@@ -500,14 +525,7 @@ def generate_tooltip(mdata):
def get_random_tip(mdata):
t = ''
- rtips = ['Click or drag model or material in scene to link/append ',
- "Click on brushes to link them into scene.",
- "All materials are free.",
- "All brushes are free.",
- "Locked models are available if you subscribe to Full plan.",
- "Login to upload your own models, materials or brushes.",
- "Use 'A' key to search assets by same author.",
- "Use 'W' key to open Authors webpage.", ]
+
tip = 'Tip: ' + random.choice(rtips)
t = writeblock(t, tip)
return t
@@ -623,6 +641,7 @@ def fetch_author(a_id, api_key):
utils.p(e)
utils.p('finish fetch')
+
# profile_counter =0
def get_author(r):
@@ -632,7 +651,7 @@ def get_author(r):
if authors == {}:
bpy.context.window_manager['bkit authors'] = authors
a = authors.get(a_id)
- if a is None:# or a is '' or (a.get('gravatarHash') is not None and a.get('gravatarImg') is None):
+ if a is None: # or a is '' or (a.get('gravatarHash') is not None and a.get('gravatarImg') is None):
authors[a_id] = ''
thread = threading.Thread(target=fetch_author, args=(a_id, preferences.api_key), daemon=True)
thread.start()
@@ -683,7 +702,6 @@ def fetch_profile(api_key):
utils.p(e)
-
def get_profile():
preferences = bpy.context.preferences.addons['blenderkit'].preferences
a = bpy.context.window_manager.get('bkit profile')
@@ -691,11 +709,6 @@ def get_profile():
thread.start()
return a
-def profile_is_validator():
- a = bpy.context.window_manager.get('bkit profile')
- if a is not None and a['user'].get('exmenu'):
- return True
- return False
class Searcher(threading.Thread):
query = None
@@ -712,6 +725,45 @@ class Searcher(threading.Thread):
def stopped(self):
return self._stop_event.is_set()
+ def query_to_url(self):
+ query = self.query
+ params = self.params
+ # build a new request
+ url = paths.get_api_url() + 'search/'
+
+ # build request manually
+ # TODO use real queries
+ requeststring = '?query='
+ #
+ if query.get('query') not in ('', None):
+ requeststring += query['query'].lower()
+ for i, q in enumerate(query):
+ if q != 'query':
+ requeststring += '+'
+ requeststring += q + ':' + str(query[q]).lower()
+
+ # result ordering: _score - relevance, score - BlenderKit score
+
+ if query.get('query') is None and query.get('category_subtree') == None:
+ # assumes no keywords and no category, thus an empty search that is triggered on start.
+ # orders by last core file upload
+ requeststring += '+order:-last_upload'
+ elif query.get('author_id') is not None and utils.profile_is_validator():
+
+ requeststring += '+order:-created'
+ else:
+ if query.get('category_subtree') is not None:
+ requeststring += '+order:-score,_score'
+ else:
+ requeststring += '+order:_score'
+
+ requeststring += '&addon_version=%s' % params['addon_version']
+ if params.get('scene_uuid') is not None:
+ requeststring += '&scene_uuid=%s' % params['scene_uuid']
+ # print('params', params)
+ urlquery = url + requeststring
+ return urlquery
+
def run(self):
maxthreads = 50
query = self.query
@@ -733,44 +785,23 @@ class Searcher(threading.Thread):
try:
origdata = json.load(infile)
urlquery = origdata['next']
+ # rparameters = {}
if urlquery == None:
return;
except:
# in case no search results found on drive we don't do next page loading.
params['get_next'] = False
if not params['get_next']:
- # build a new request
url = paths.get_api_url() + 'search/'
- # build request manually
- # TODO use real queries
- requeststring = '?query=' + query['keywords'].lower() + '+'
- #
- for i, q in enumerate(query):
- requeststring += q + ':' + str(query[q]).lower()
- if i < len(query) - 1:
- requeststring += '+'
-
- # result ordering: _score - relevance, score - BlenderKit score
- #first condition assumes no keywords and no category, thus an empty search that is triggered on start.
- if query['keywords'] == '' and query.get('category_subtree') == None:
- requeststring += '+order:-created'
- elif query.get('author_id') is not None and profile_is_validator():
- requeststring += '+order:-created'
- else:
- if query.get('category_subtree') is not None:
- requeststring += '+order:-score,_score'
- else:
- requeststring += '+order:_score'
-
- requeststring += '&addon_version=%s' % params['addon_version']
- if params.get('scene_uuid') is not None:
- requeststring += '&scene_uuid=%s' % params['scene_uuid']
+ urlquery = url
- urlquery = url + requeststring
+ # rparameters = query
+ urlquery = self.query_to_url()
try:
utils.p(urlquery)
- r = rerequests.get(urlquery, headers=headers)
+ r = rerequests.get(urlquery, headers=headers) # , params = rparameters)
+ # print(r.url)
reports = ''
# utils.p(r.text)
except requests.exceptions.RequestException as e:
@@ -798,13 +829,13 @@ class Searcher(threading.Thread):
if p['parameterType'] == 'mode':
mode = p['value']
if query['asset_type'] != 'brush' or (
- query.get('brushType') != None and query['brushType']) == mode:
+ query.get('mode') != None and query['mode']) == mode:
nresults.append(d)
rdata['results'] = nresults
# print('number of results: ', len(rdata.get('results', [])))
if self.stopped():
- utils.p('stopping search : ' + query['keywords'])
+ utils.p('stopping search : ' + str(query))
return
mt('search finished')
@@ -863,7 +894,7 @@ class Searcher(threading.Thread):
# TODO do the killing/ stopping here! remember threads might have finished inbetween!
if self.stopped():
- utils.p('stopping search : ' + query['keywords'])
+ utils.p('stopping search : ' + str(query))
return
# this loop handles downloading of small thumbnails
@@ -887,7 +918,7 @@ class Searcher(threading.Thread):
# utils.p('fetched thumbnail ', i)
i += 1
if self.stopped():
- utils.p('stopping search : ' + query['keywords'])
+ utils.p('stopping search : ' + str(query))
return
idx = 0
while len(thumb_sml_download_threads) > 0:
@@ -899,7 +930,7 @@ class Searcher(threading.Thread):
i += 1
if self.stopped():
- utils.p('stopping search : ' + query['keywords'])
+ utils.p('stopping search : ' + str(query))
return
# start downloading full thumbs in the end
@@ -914,13 +945,35 @@ class Searcher(threading.Thread):
def build_query_common(query, props):
- query_common = {
- "keywords": props.search_keywords
- }
- query.update(query_common)
+ '''add shared parameters to query'''
+ query_common = {}
+ if props.search_keywords != '':
+ query_common["query"] = props.search_keywords
+
+ if props.search_verification_status != 'ALL':
+ query_common['verification_status'] = props.search_verification_status.lower()
+
+ if props.search_advanced:
+ if props.search_texture_resolution:
+ query["textureResolutionMax_gte"] = props.search_texture_resolution_min
+ query["textureResolutionMax_lte"] = props.search_texture_resolution_max
+
+ elif props.search_procedural == 'TEXTURE_BASED':
+ # todo this procedural hack should be replaced with the parameter
+ query["textureResolutionMax_gte"] = 0
+ # query["procedural"] = False
+ if props.search_procedural == "PROCEDURAL":
+ #todo this procedural hack should be replaced with the parameter
+ query["files_size_lte"] = 1024 * 1024
+ # query["procedural"] = True
+ elif props.search_file_size:
+ query_common["files_size_gte"] = props.search_file_size_min * 1024 * 1024
+ query_common["files_size_lte"] = props.search_file_size_max * 1024 * 1024
+
+
+ query.update(query_common)
-# def query_add_range(query, name, rmin, rmax):
def build_query_model():
'''use all search input to request results from server'''
@@ -944,14 +997,11 @@ def build_query_model():
if props.search_condition != 'UNSPECIFIED':
query["condition"] = props.search_condition
if props.search_design_year:
- query["designYearMin"] = props.search_design_year_min
- query["designYearMax"] = props.search_design_year_max
+ query["designYear_gte"] = props.search_design_year_min
+ query["designYear_lte"] = props.search_design_year_max
if props.search_polycount:
- query["polyCountMin"] = props.search_polycount_min
- query["polyCountMax"] = props.search_polycount_max
- if props.search_texture_resolution:
- query["textureResolutionMin"] = props.search_texture_resolution_min
- query["textureResolutionMax"] = props.search_texture_resolution_max
+ query["faceCount_gte"] = props.search_polycount_min
+ query["faceCount_lte"] = props.search_polycount_max
build_query_common(query, props)
@@ -988,6 +1038,7 @@ def build_query_material():
query["style"] = props.search_style
else:
query["style"] = props.search_style_other
+
build_query_common(query, props)
return query
@@ -1024,7 +1075,7 @@ def build_query_brush():
query = {
"asset_type": 'brush',
- "brushType": brush_type
+ "mode": brush_type
}
build_query_common(query, props)
@@ -1063,7 +1114,7 @@ def search(category='', get_next=False, author_id=''):
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
search_start_time = time.time()
- mt('start')
+ #mt('start')
scene = bpy.context.scene
uiprops = scene.blenderkitUI
@@ -1106,6 +1157,12 @@ def search(category='', get_next=False, author_id=''):
if author_id != '':
query['author_id'] = author_id
+ elif props.own_only:
+ # if user searches for [another] author, 'only my assets' is invalid. that's why in elif.
+ profile = bpy.context.window_manager.get('bkit profile')
+ if profile is not None:
+ query['author_id'] = str(profile['user']['id'])
+
# utils.p('searching')
props.is_searching = True
@@ -1127,7 +1184,7 @@ def search(category='', get_next=False, author_id=''):
def search_update(self, context):
utils.p('search updater')
- #if self.search_keywords != '':
+ # if self.search_keywords != '':
ui_props = bpy.context.scene.blenderkitUI
if ui_props.down_up != 'SEARCH':
ui_props.down_up = 'SEARCH'