BlenderKit:
-icons module -clipboard monitoring -fix link to website when people want to see asset online -advanced search parameters
This commit is contained in:
parent
7c3d8127da
commit
7410d631ce
|
@ -39,6 +39,7 @@ if "bpy" in locals():
|
|||
ratings = reload(ratings)
|
||||
autothumb = reload(autothumb)
|
||||
ui = reload(ui)
|
||||
icons = reload(icons)
|
||||
bg_blender = reload(bg_blender)
|
||||
paths = reload(paths)
|
||||
utils = reload(utils)
|
||||
|
@ -48,7 +49,8 @@ if "bpy" in locals():
|
|||
bkit_oauth = reload(bkit_oauth)
|
||||
tasks_queue = reload(tasks_queue)
|
||||
else:
|
||||
from blenderkit import asset_inspector, search, download, upload, ratings, autothumb, ui, bg_blender, paths, utils, \
|
||||
from blenderkit import asset_inspector, search, download, upload, ratings, autothumb, ui, icons, bg_blender, paths, \
|
||||
utils, \
|
||||
overrides, ui_panels, categories, bkit_oauth, tasks_queue
|
||||
|
||||
import os
|
||||
|
@ -91,6 +93,7 @@ def scene_load(context):
|
|||
preferences = bpy.context.preferences.addons['blenderkit'].preferences
|
||||
preferences.login_attempt = False
|
||||
|
||||
|
||||
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):
|
||||
|
@ -103,6 +106,7 @@ def check_timers_timer():
|
|||
bpy.app.timers.register(bg_blender.bg_update)
|
||||
return 5.0
|
||||
|
||||
|
||||
licenses = (
|
||||
('royalty_free', 'Royalty Free', 'royalty free commercial license'),
|
||||
('cc_zero', 'Creative Commons Zero', 'Creative Commons Zero'),
|
||||
|
@ -191,6 +195,7 @@ thumbnail_resolutions = (
|
|||
('2048', '2048', ''),
|
||||
)
|
||||
|
||||
|
||||
def get_upload_asset_type(self):
|
||||
typemapper = {
|
||||
BlenderKitModelUploadProps: 'model',
|
||||
|
@ -244,9 +249,10 @@ def switch_search_results(self, context):
|
|||
s['search results orig'] = s.get('bkit brush search orig')
|
||||
search.load_previews()
|
||||
|
||||
|
||||
def asset_type_callback(self, context):
|
||||
#s = bpy.context.scene
|
||||
#ui_props = s.blenderkitUI
|
||||
# s = bpy.context.scene
|
||||
# ui_props = s.blenderkitUI
|
||||
if self.down_up == 'SEARCH':
|
||||
items = (
|
||||
('MODEL', 'Find Models', 'Find models in the BlenderKit online database', 'OBJECT_DATAMODE', 0),
|
||||
|
@ -265,6 +271,7 @@ def asset_type_callback(self, context):
|
|||
)
|
||||
return items
|
||||
|
||||
|
||||
class BlenderKitUIProps(PropertyGroup):
|
||||
down_up: EnumProperty(
|
||||
name="Download vs Upload",
|
||||
|
@ -387,13 +394,35 @@ class BlenderKitCommonSearchProps(object):
|
|||
search_done: BoolProperty(name="Search Completed", description="at least one search did run (internal)",
|
||||
default=False)
|
||||
own_only: BoolProperty(name="My Assets", description="Search only for your assets",
|
||||
default=False)
|
||||
default=False)
|
||||
search_error: BoolProperty(name="Search Error", description="last search had an error", default=False)
|
||||
report: StringProperty(
|
||||
name="Report",
|
||||
description="errors and messages",
|
||||
default="")
|
||||
|
||||
# TEXTURE RESOLUTION
|
||||
search_texture_resolution: BoolProperty(name="Texture Resolution",
|
||||
description="Span of the texture resolutions",
|
||||
default=False,
|
||||
update=search.search_update,
|
||||
)
|
||||
search_texture_resolution_min: IntProperty(name="Min Texture Resolution",
|
||||
description="Minimum texture resolution",
|
||||
default=256,
|
||||
min=0,
|
||||
max=32768,
|
||||
update=search.search_update,
|
||||
)
|
||||
|
||||
search_texture_resolution_max: IntProperty(name="Max Texture Resolution",
|
||||
description="Maximum texture resolution",
|
||||
default=4096,
|
||||
min=0,
|
||||
max=32768,
|
||||
update=search.search_update,
|
||||
)
|
||||
|
||||
|
||||
def name_update(self, context):
|
||||
''' checks for name change, because it decides if whole asset has to be re-uploaded. Name is stored in the blend file
|
||||
|
@ -401,7 +430,6 @@ def name_update(self, context):
|
|||
utils.name_update()
|
||||
|
||||
|
||||
|
||||
def update_tags(self, context):
|
||||
props = utils.get_upload_props()
|
||||
|
||||
|
@ -426,6 +454,7 @@ def update_tags(self, context):
|
|||
if props.tags != ns:
|
||||
props.tags = ns
|
||||
|
||||
|
||||
def update_free(self, context):
|
||||
if self.is_free == False:
|
||||
self.is_free = True
|
||||
|
@ -440,6 +469,7 @@ def update_free(self, context):
|
|||
|
||||
bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO')
|
||||
|
||||
|
||||
class BlenderKitCommonUploadProps(object):
|
||||
id: StringProperty(
|
||||
name="Asset Version Id",
|
||||
|
@ -506,9 +536,9 @@ class BlenderKitCommonUploadProps(object):
|
|||
)
|
||||
|
||||
is_procedural: BoolProperty(name="Procedural",
|
||||
description="Asset is procedural - has no texture.",
|
||||
default=True
|
||||
)
|
||||
description="Asset is procedural - has no texture.",
|
||||
default=True
|
||||
)
|
||||
node_count: IntProperty(name="Node count", description="Total nodes in the asset", default=0)
|
||||
texture_count: IntProperty(name="Texture count", description="Total texture count in asset", default=0)
|
||||
total_megapixels: IntProperty(name="Megapixels", description="Total megapixels of texture", default=0)
|
||||
|
@ -593,22 +623,26 @@ class BlenderKitMaterialSearchProps(PropertyGroup, BlenderKitCommonSearchProps):
|
|||
items=search_material_styles,
|
||||
description="Style of material",
|
||||
default="ANY",
|
||||
update=search.search_update,
|
||||
)
|
||||
search_style_other: StringProperty(
|
||||
name="Style Other",
|
||||
description="Style not in the list",
|
||||
default="",
|
||||
update=search.search_update,
|
||||
)
|
||||
search_engine: EnumProperty(
|
||||
name='Engine',
|
||||
items=engines,
|
||||
default='NONE',
|
||||
description='Output engine',
|
||||
update=search.search_update,
|
||||
)
|
||||
search_engine_other: StringProperty(
|
||||
name="Engine",
|
||||
description="engine not specified by addon",
|
||||
default="",
|
||||
update=search.search_update,
|
||||
)
|
||||
automap: BoolProperty(name="Auto-Map",
|
||||
description="reset object texture space and also add automatically a cube mapped UV "
|
||||
|
@ -1147,10 +1181,10 @@ class BlenderKitModelSearchProps(PropertyGroup, BlenderKitCommonSearchProps):
|
|||
)
|
||||
|
||||
free_only: BoolProperty(name="Free only", description="Show only free models",
|
||||
default=False)
|
||||
default=False,update=search.search_update)
|
||||
|
||||
search_advanced: BoolProperty(name="Advanced Search Options", description="use advanced search properties",
|
||||
default=False)
|
||||
default=False,update=search.search_update)
|
||||
|
||||
# CONDITION
|
||||
search_condition: EnumProperty(
|
||||
|
@ -1169,9 +1203,9 @@ class BlenderKitModelSearchProps(PropertyGroup, BlenderKitCommonSearchProps):
|
|||
|
||||
search_procedural: EnumProperty(
|
||||
items=(
|
||||
('BOTH', 'Both',''),
|
||||
('PROCEDURAL', 'Procedural',''),
|
||||
('TEXTURE_BASED', 'Texture based',''),
|
||||
('BOTH', 'Both', ''),
|
||||
('PROCEDURAL', 'Procedural', ''),
|
||||
('TEXTURE_BASED', 'Texture based', ''),
|
||||
|
||||
),
|
||||
default='BOTH',
|
||||
|
@ -1182,51 +1216,47 @@ class BlenderKitModelSearchProps(PropertyGroup, BlenderKitCommonSearchProps):
|
|||
# DESIGN YEAR
|
||||
search_design_year: BoolProperty(name="Sesigned in Year",
|
||||
description="when the object was approximately designed",
|
||||
default=False)
|
||||
default=False,
|
||||
update=search.search_update,
|
||||
)
|
||||
|
||||
search_design_year_min: IntProperty(name="Min Age",
|
||||
description="when the object was approximately designed",
|
||||
default=1950, min=-100000000, max=1000000000)
|
||||
default=1950, min=-100000000, max=1000000000,
|
||||
update=search.search_update,
|
||||
)
|
||||
|
||||
search_design_year_max: IntProperty(name="Max Age",
|
||||
description="when the object was approximately designed",
|
||||
default=2017,
|
||||
min=0,
|
||||
max=10000000)
|
||||
max=10000000,
|
||||
update=search.search_update,
|
||||
)
|
||||
|
||||
# TEXTURE RESOLUTION
|
||||
search_texture_resolution: BoolProperty(name="Texture Resolution",
|
||||
description="Span of the texture resolutions",
|
||||
default=False)
|
||||
|
||||
search_texture_resolution_min: IntProperty(name="Min Texture Resolution",
|
||||
description="when the object was approximately designed",
|
||||
default=256,
|
||||
min=0,
|
||||
max=32768)
|
||||
|
||||
search_texture_resolution_max: IntProperty(name="Max Texture Resolution",
|
||||
description="when the object was approximately designed",
|
||||
default=4096,
|
||||
min=0,
|
||||
max=32768)
|
||||
|
||||
# POLYCOUNT
|
||||
search_polycount: BoolProperty(name="Use Polycount",
|
||||
description="use polycount of object search tag",
|
||||
default=False)
|
||||
default=False,
|
||||
update=search.search_update,)
|
||||
|
||||
search_polycount_min: IntProperty(name="Min Polycount",
|
||||
description="polycount of the asset minimum",
|
||||
default=0,
|
||||
min=0,
|
||||
max=100000000)
|
||||
max=100000000,
|
||||
update=search.search_update,)
|
||||
|
||||
search_polycount_max: IntProperty(name="Max Polycount",
|
||||
description="polycount of the asset maximum",
|
||||
default=100000000,
|
||||
min=0,
|
||||
max=100000000)
|
||||
max=100000000,
|
||||
update=search.search_update,
|
||||
)
|
||||
|
||||
append_method: EnumProperty(
|
||||
name="Import Method",
|
||||
|
@ -1313,6 +1343,7 @@ class BlenderKitSceneSearchProps(PropertyGroup, BlenderKitCommonSearchProps):
|
|||
)
|
||||
|
||||
|
||||
|
||||
class BlenderKitAddonPreferences(AddonPreferences):
|
||||
# this must match the addon name, use '__package__'
|
||||
# when defining this in a submodule of a python package.
|
||||
|
@ -1338,9 +1369,9 @@ class BlenderKitAddonPreferences(AddonPreferences):
|
|||
)
|
||||
|
||||
api_key_timeout: IntProperty(
|
||||
name = 'api key timeout',
|
||||
description = 'time where the api key will need to be refreshed',
|
||||
default = 0,
|
||||
name='api key timeout',
|
||||
description='time where the api key will need to be refreshed',
|
||||
default=0,
|
||||
)
|
||||
|
||||
api_key_life: IntProperty(
|
||||
|
@ -1370,7 +1401,7 @@ class BlenderKitAddonPreferences(AddonPreferences):
|
|||
tips_on_start: BoolProperty(
|
||||
name="Show tips when starting blender",
|
||||
description="Show tips when starting blender",
|
||||
default=True
|
||||
default=False
|
||||
)
|
||||
|
||||
search_in_header: BoolProperty(
|
||||
|
@ -1439,10 +1470,8 @@ class BlenderKitAddonPreferences(AddonPreferences):
|
|||
min=0,
|
||||
max=20)
|
||||
|
||||
|
||||
thumb_size: IntProperty(name="Assetbar thumbnail Size", default=96, min=-1, max=256)
|
||||
|
||||
|
||||
asset_counter: IntProperty(name="Usage Counter",
|
||||
description="Counts usages so it asks for registration only after reaching a limit",
|
||||
default=0,
|
||||
|
@ -1473,7 +1502,7 @@ class BlenderKitAddonPreferences(AddonPreferences):
|
|||
layout.operator("wm.blenderkit_logout", text="Logout",
|
||||
icon='URL')
|
||||
|
||||
#if not self.enable_oauth:
|
||||
# if not self.enable_oauth:
|
||||
layout.prop(self, "api_key", text='Your API Key')
|
||||
# layout.label(text='After you paste API Key, categories are downloaded, so blender will freeze for a few seconds.')
|
||||
layout.prop(self, "global_dir")
|
||||
|
@ -1489,7 +1518,6 @@ class BlenderKitAddonPreferences(AddonPreferences):
|
|||
layout.prop(self, "search_in_header")
|
||||
|
||||
|
||||
|
||||
# registration
|
||||
classes = (
|
||||
|
||||
|
@ -1560,6 +1588,7 @@ def register():
|
|||
ratings.register_ratings()
|
||||
autothumb.register_thumbnailer()
|
||||
ui.register_ui()
|
||||
icons.register_icons()
|
||||
ui_panels.register_ui_panels()
|
||||
bg_blender.register()
|
||||
utils.load_prefs()
|
||||
|
@ -1573,10 +1602,10 @@ def register():
|
|||
|
||||
|
||||
def unregister():
|
||||
|
||||
bpy.app.timers.unregister(check_timers_timer)
|
||||
|
||||
ui.unregister_ui()
|
||||
icons.unregister_icons()
|
||||
search.unregister_search()
|
||||
asset_inspector.unregister_asset_inspector()
|
||||
download.unregister_download()
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
|
||||
import os
|
||||
import bpy
|
||||
|
||||
# We can store multiple preview collections here,
|
||||
# however in this example we only store "main"
|
||||
icon_collections = {}
|
||||
|
||||
icons_read = {
|
||||
'fp.png': 'free',
|
||||
'flp.png': 'full',
|
||||
}
|
||||
|
||||
|
||||
def register_icons():
|
||||
# Note that preview collections returned by bpy.utils.previews
|
||||
# are regular py objects - you can use them to store custom data.
|
||||
import bpy.utils.previews
|
||||
pcoll = bpy.utils.previews.new()
|
||||
|
||||
# path to the folder where the icon is
|
||||
# the path is calculated relative to this py file inside the addon folder
|
||||
icons_dir = os.path.join(os.path.dirname(__file__), "thumbnails")
|
||||
|
||||
# load a preview thumbnail of a file and store in the previews collection
|
||||
for ir in icons_read.keys():
|
||||
pcoll.load(icons_read[ir], os.path.join(icons_dir, ir), 'IMAGE')
|
||||
|
||||
icon_collections["main"] = pcoll
|
||||
|
||||
|
||||
def unregister_icons():
|
||||
for pcoll in icon_collections.values():
|
||||
bpy.utils.previews.remove(pcoll)
|
||||
icon_collections.clear()
|
|
@ -33,7 +33,6 @@ BLENDERKIT_BRUSH_UPLOAD_INSTRUCTIONS_URL = "https://www.blenderkit.com/docs/uplo
|
|||
BLENDERKIT_LOGIN_URL = "https://www.blenderkit.com/accounts/login"
|
||||
BLENDERKIT_OAUTH_LANDING_URL = "/oauth-landing/"
|
||||
BLENDERKIT_SIGNUP_URL = "https://www.blenderkit.com/accounts/register"
|
||||
BLENDERKIT_ADDON_FILE_URL = "https://www.blenderkit.com/get-blenderkit/"
|
||||
BLENDERKIT_SETTINGS_FILENAME = os.path.join(_presets, "bkit.json")
|
||||
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ asset_types = (
|
|||
class UploadRatingOperator(bpy.types.Operator):
|
||||
"""Upload rating to the web db"""
|
||||
bl_idname = "object.blenderkit_rating_upload"
|
||||
bl_label = "Upload the Rating"
|
||||
bl_label = "Send Rating"
|
||||
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
|
||||
|
||||
# type of upload - model, material, textures, e.t.c.
|
||||
|
|
|
@ -86,10 +86,11 @@ 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 to search assets by same author.",
|
||||
"Use 'W' key to open Authors webpage.", ]
|
||||
"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.'''
|
||||
|
@ -127,7 +128,7 @@ 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.
|
||||
|
@ -142,6 +143,22 @@ def timer_update(): # TODO might get moved to handle all blenderkit stuff.
|
|||
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,
|
||||
# causing a lot of throuble literally.
|
||||
|
@ -700,6 +717,9 @@ def profile_is_validator():
|
|||
return True
|
||||
return False
|
||||
|
||||
|
||||
|
||||
|
||||
class Searcher(threading.Thread):
|
||||
query = None
|
||||
|
||||
|
@ -715,6 +735,43 @@ 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
|
||||
# first condition assumes no keywords and no category, thus an empty search that is triggered on start.
|
||||
if query.get('query') is None 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']
|
||||
print('params', params)
|
||||
urlquery = url + requeststring
|
||||
return urlquery
|
||||
|
||||
def run(self):
|
||||
maxthreads = 50
|
||||
query = self.query
|
||||
|
@ -736,45 +793,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):
|
||||
if q != 'keywords':
|
||||
requeststring += q + ':' + str(query[q]).lower()
|
||||
if i < len(query) - 1:
|
||||
requeststring += '+'
|
||||
urlquery = url
|
||||
|
||||
# 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 + 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:
|
||||
|
@ -808,7 +843,7 @@ class Searcher(threading.Thread):
|
|||
|
||||
# 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')
|
||||
|
@ -867,7 +902,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
|
||||
|
@ -891,7 +926,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:
|
||||
|
@ -903,7 +938,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
|
||||
|
@ -918,10 +953,11 @@ class Searcher(threading.Thread):
|
|||
|
||||
|
||||
def build_query_common(query, props):
|
||||
query_common = {
|
||||
"keywords": props.search_keywords
|
||||
}
|
||||
query.update(query_common)
|
||||
if props.search_keywords != '':
|
||||
query_common = {
|
||||
"query": props.search_keywords
|
||||
}
|
||||
query.update(query_common)
|
||||
|
||||
|
||||
# def query_add_range(query, name, rmin, rmax):
|
||||
|
@ -948,19 +984,19 @@ 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
|
||||
query["faceCount_gte"] = props.search_polycount_min
|
||||
query["faceCount_lte"] = props.search_polycount_max
|
||||
if props.search_texture_resolution:
|
||||
query["textureResolutionMin"] = props.search_texture_resolution_min
|
||||
query["textureResolutionMax"] = props.search_texture_resolution_max
|
||||
query["textureResolutionMax_gte"] = props.search_texture_resolution_min
|
||||
query["textureResolutionMax_lte"] = props.search_texture_resolution_max
|
||||
|
||||
if props.search_procedural == "PROCEDURAL":
|
||||
query["procedural"] = True
|
||||
elif props.search_procedural == 'TEXTURE_BASED':
|
||||
query["procedural"] = False
|
||||
if props.search_procedural == "PROCEDURAL":
|
||||
query["procedural"] = True
|
||||
elif props.search_procedural == 'TEXTURE_BASED':
|
||||
query["procedural"] = False
|
||||
|
||||
build_query_common(query, props)
|
||||
|
||||
|
@ -997,6 +1033,11 @@ def build_query_material():
|
|||
query["style"] = props.search_style
|
||||
else:
|
||||
query["style"] = props.search_style_other
|
||||
|
||||
if props.search_texture_resolution:
|
||||
query["textureResolutionMax_gte"] = props.search_texture_resolution_min
|
||||
query["textureResolutionMax_lte"] = props.search_texture_resolution_max
|
||||
|
||||
build_query_common(query, props)
|
||||
|
||||
return query
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 540 B |
Binary file not shown.
After Width: | Height: | Size: 561 B |
|
@ -1428,7 +1428,6 @@ class AssetBarOperator(bpy.types.Operator):
|
|||
ui_props.draw_tooltip = True
|
||||
|
||||
ui_props.tooltip = asset_data['tooltip']
|
||||
|
||||
# bpy.ops.wm.call_menu(name='OBJECT_MT_blenderkit_asset_menu')
|
||||
|
||||
else:
|
||||
|
@ -1490,7 +1489,7 @@ class AssetBarOperator(bpy.types.Operator):
|
|||
if not asset_data['can_download']:
|
||||
message = 'Asset locked. Find out how to unlock Everything and ...'
|
||||
link_text = 'support all BlenderKit artists.'
|
||||
url = paths.get_bkit_url() + '/get-blenderkit/' + asset_data['id']
|
||||
url = paths.get_bkit_url() + '/get-blenderkit/' + asset_data['id'] + '/?from_addon'
|
||||
bpy.ops.wm.blenderkit_url_dialog('INVOKE_REGION_WIN', url=url, message=message,
|
||||
link_text=link_text)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
|
|
@ -24,8 +24,9 @@ if "bpy" in locals():
|
|||
utils = importlib.reload(utils)
|
||||
download = importlib.reload(download)
|
||||
categories = importlib.reload(categories)
|
||||
icons = importlib.reload(icons)
|
||||
else:
|
||||
from blenderkit import paths, ratings, utils, download, categories
|
||||
from blenderkit import paths, ratings, utils, download, categories, icons
|
||||
|
||||
from bpy.types import (
|
||||
Panel
|
||||
|
@ -75,10 +76,10 @@ def draw_ratings(layout, context):
|
|||
layout.prop(bkit_ratings, 'rating_work_hours')
|
||||
w = context.region.width
|
||||
|
||||
layout.label(text='problems')
|
||||
layout.prop(bkit_ratings, 'rating_problems', text='')
|
||||
layout.label(text='compliments')
|
||||
layout.prop(bkit_ratings, 'rating_compliments', text='')
|
||||
# layout.label(text='problems')
|
||||
# layout.prop(bkit_ratings, 'rating_problems', text='')
|
||||
# layout.label(text='compliments')
|
||||
# layout.prop(bkit_ratings, 'rating_compliments', text='')
|
||||
|
||||
row = layout.row()
|
||||
op = row.operator("object.blenderkit_rating_upload", text="Send rating", icon='URL')
|
||||
|
@ -151,7 +152,7 @@ def prop_needed(layout, props, name, value, is_not_filled=''):
|
|||
# row.label(text='', icon = 'ERROR')
|
||||
icon = 'ERROR'
|
||||
row.alert = True
|
||||
row.prop(props, name)#, icon=icon)
|
||||
row.prop(props, name) # , icon=icon)
|
||||
row.alert = False
|
||||
else:
|
||||
# row.label(text='', icon = 'FILE_TICK')
|
||||
|
@ -264,6 +265,7 @@ def draw_panel_scene_upload(self, context):
|
|||
row.prop(props, 'work_hours')
|
||||
layout.prop(props, 'adult')
|
||||
|
||||
|
||||
def draw_assetbar_show_hide(layout, props):
|
||||
s = bpy.context.scene
|
||||
ui_props = s.blenderkitUI
|
||||
|
@ -301,7 +303,7 @@ def draw_panel_model_search(self, context):
|
|||
layout.prop(props, "search_style")
|
||||
layout.prop(props, "own_only")
|
||||
layout.prop(props, "free_only")
|
||||
#layout.prop(props, "search_procedural", expand = True)
|
||||
# layout.prop(props, "search_procedural", expand = True)
|
||||
# if props.search_style == 'OTHER':
|
||||
# layout.prop(props, "search_style_other")
|
||||
# layout.prop(props, "search_engine")
|
||||
|
@ -309,7 +311,7 @@ def draw_panel_model_search(self, context):
|
|||
# layout.prop(props, 'append_link', expand=True, icon_only=False)
|
||||
# layout.prop(props, 'import_as', expand=True, icon_only=False)
|
||||
|
||||
# layout.prop(props, "search_advanced")
|
||||
layout.prop(props, "search_advanced")
|
||||
if props.search_advanced:
|
||||
layout.separator()
|
||||
|
||||
|
@ -320,34 +322,31 @@ def draw_panel_model_search(self, context):
|
|||
# layout.prop(props, "search_engine_keyword")
|
||||
|
||||
# AGE
|
||||
layout.prop(props, "search_condition") # , text ='condition of object new/old e.t.c.')
|
||||
layout.prop(props, "search_condition", text = 'Condition') # , text ='condition of object new/old e.t.c.')
|
||||
|
||||
# DESIGN YEAR
|
||||
layout.prop(props, "search_design_year", text='designed in ( min - max )')
|
||||
row = layout.row(align=True)
|
||||
if not props.search_design_year_min:
|
||||
row.active = False
|
||||
row.prop(props, "search_design_year_min", text='min')
|
||||
row.prop(props, "search_design_year_max", text='max')
|
||||
if props.search_design_year:
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "search_design_year_min", text='min')
|
||||
row.prop(props, "search_design_year_max", text='max')
|
||||
|
||||
# POLYCOUNT
|
||||
layout.prop(props, "search_polycount", text='polycount in ( min - max )')
|
||||
row = layout.row(align=True)
|
||||
if not props.search_polycount:
|
||||
row.active = False
|
||||
row.prop(props, "search_polycount_min", text='min')
|
||||
row.prop(props, "search_polycount_max", text='max')
|
||||
layout.prop(props, "search_polycount", text='Poly count in ( min - max )')
|
||||
if props.search_polycount:
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "search_polycount_min", text='min')
|
||||
row.prop(props, "search_polycount_max", text='max')
|
||||
|
||||
# TEXTURE RESOLUTION
|
||||
layout.prop(props, "search_texture_resolution", text='texture resolution ( min - max )')
|
||||
row = layout.row(align=True)
|
||||
if not props.search_texture_resolution:
|
||||
row.active = False
|
||||
row.prop(props, "search_texture_resolution_min", text='min')
|
||||
row.prop(props, "search_texture_resolution_max", text='max')
|
||||
if props.search_texture_resolution:
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "search_texture_resolution_min", text='min')
|
||||
row.prop(props, "search_texture_resolution_max", text='max')
|
||||
|
||||
# ADULT
|
||||
layout.prop(props, "search_adult") # , text ='condition of object new/old e.t.c.')
|
||||
#layout.prop(props, "search_adult") # , text ='condition of object new/old e.t.c.')
|
||||
|
||||
draw_panel_categories(self, context)
|
||||
|
||||
|
@ -403,6 +402,8 @@ class VIEW3D_PT_blenderkit_model_properties(Panel):
|
|||
if o.instance_type == 'COLLECTION' and o.instance_collection is not None:
|
||||
layout.operator('object.blenderkit_bring_to_scene', text='Bring to scene')
|
||||
|
||||
draw_panel_model_rating(self, context)
|
||||
|
||||
# if 'rig' in ad['tags']:
|
||||
# # layout.label(text = 'can make proxy')
|
||||
# layout.operator('object.blenderkit_make_proxy', text = 'Make Armature proxy')
|
||||
|
@ -442,19 +443,31 @@ class VIEW3D_PT_blenderkit_profile(Panel):
|
|||
draw_login_progress(layout)
|
||||
return
|
||||
|
||||
|
||||
if user_preferences.api_key != '':
|
||||
me = bpy.context.window_manager.get('bkit profile')
|
||||
if me is not None:
|
||||
me = me['user']
|
||||
layout.label(text='User: %s %s' % (me['firstName'], me['lastName']))
|
||||
layout.label(text='Email: %s' % (me['email']))
|
||||
if me.get('sumAssetFilesSize') is not None: # TODO remove this when production server has these too.
|
||||
layout.label(text='Public assets: %i MiB' % (me['sumAssetFilesSize']))
|
||||
if me.get('sumPrivateAssetFilesSize') is not None:
|
||||
layout.label(text='Private assets: %i MiB' % (me['sumPrivateAssetFilesSize']))
|
||||
#user name
|
||||
layout.label(text='Me: %s %s' % (me['firstName'], me['lastName']))
|
||||
# layout.label(text='Email: %s' % (me['email']))
|
||||
|
||||
# plan information
|
||||
|
||||
# pcoll = icons.icon_collections["main"]
|
||||
# my_icon = pcoll['free']
|
||||
# row = layout.row()
|
||||
# row.label(text='My plan:')
|
||||
# row.label(text='Free plan', icon_value=my_icon.icon_id)
|
||||
# layout.operator("wm.url_open", text="Change plan",
|
||||
# icon='URL').url = paths.get_bkit_url() + paths.BLENDERKIT_PLANS
|
||||
|
||||
#storage statistics
|
||||
# if me.get('sumAssetFilesSize') is not None: # TODO remove this when production server has these too.
|
||||
# layout.label(text='My public assets: %i MiB' % (me['sumAssetFilesSize']))
|
||||
# if me.get('sumPrivateAssetFilesSize') is not None:
|
||||
# layout.label(text='My private assets: %i MiB' % (me['sumPrivateAssetFilesSize']))
|
||||
if me.get('remainingPrivateQuota') is not None:
|
||||
layout.label(text='Remaining private storage: %i MiB' % (me['remainingPrivateQuota']))
|
||||
layout.label(text='My free storage: %i MiB' % (me['remainingPrivateQuota']))
|
||||
|
||||
layout.operator("wm.url_open", text="See my uploads",
|
||||
icon='URL').url = paths.get_bkit_url() + paths.BLENDERKIT_USER_ASSETS
|
||||
|
@ -482,6 +495,7 @@ class VIEW3D_PT_blenderkit_login(Panel):
|
|||
if user_preferences.enable_oauth:
|
||||
draw_login_buttons(layout)
|
||||
|
||||
|
||||
def draw_panel_model_rating(self, context):
|
||||
o = bpy.context.active_object
|
||||
op = draw_ratings(self.layout, context) # , props)
|
||||
|
@ -558,10 +572,18 @@ def draw_panel_material_search(self, context):
|
|||
# if props.search_engine == 'OTHER':
|
||||
# layout.prop(props, 'search_engine_other')
|
||||
|
||||
layout.prop(props, 'automap')
|
||||
# TEXTURE RESOLUTION
|
||||
layout.prop(props, "search_texture_resolution", text='texture resolution ( min - max )')
|
||||
if props.search_texture_resolution:
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "search_texture_resolution_min", text='min')
|
||||
row.prop(props, "search_texture_resolution_max", text='max')
|
||||
|
||||
draw_panel_categories(self, context)
|
||||
|
||||
layout.prop(props, 'automap')
|
||||
|
||||
|
||||
|
||||
def draw_panel_material_ratings(self, context):
|
||||
op = draw_ratings(self.layout, context) # , props)
|
||||
|
@ -644,19 +666,19 @@ class VIEW3D_PT_blenderkit_unified(Panel):
|
|||
# layout.prop_tabs_enum(ui_props, "asset_type", icon_only = True)
|
||||
|
||||
row = layout.row()
|
||||
#row.scale_x = 1.6
|
||||
#row.scale_y = 1.6
|
||||
# row.scale_x = 1.6
|
||||
# row.scale_y = 1.6
|
||||
#
|
||||
row.prop(ui_props, 'down_up', expand=True, icon_only=False)
|
||||
# row.label(text='')
|
||||
#row = row.split().row()
|
||||
#layout.alert = True
|
||||
#layout.alignment = 'CENTER'
|
||||
#row = layout.row(align = True)
|
||||
#split = row.split(factor=.5)
|
||||
#row.prop(ui_props, 'asset_type', expand=True, icon_only=True)
|
||||
#row = layout.column(align = False)
|
||||
layout.prop(ui_props, 'asset_type', expand=False, text = '')
|
||||
# row = row.split().row()
|
||||
# layout.alert = True
|
||||
# layout.alignment = 'CENTER'
|
||||
# row = layout.row(align = True)
|
||||
# split = row.split(factor=.5)
|
||||
# row.prop(ui_props, 'asset_type', expand=True, icon_only=True)
|
||||
# row = layout.column(align = False)
|
||||
layout.prop(ui_props, 'asset_type', expand=False, text='')
|
||||
|
||||
w = context.region.width
|
||||
if user_preferences.login_attempt:
|
||||
|
@ -766,7 +788,6 @@ class VIEW3D_PT_blenderkit_unified(Panel):
|
|||
layout.label(text='not yet implemented')
|
||||
|
||||
|
||||
|
||||
class OBJECT_MT_blenderkit_asset_menu(bpy.types.Menu):
|
||||
bl_label = "Asset options:"
|
||||
bl_idname = "OBJECT_MT_blenderkit_asset_menu"
|
||||
|
@ -907,7 +928,7 @@ class UrlPopupDialog(bpy.types.Operator):
|
|||
op.url = self.url
|
||||
|
||||
def execute(self, context):
|
||||
#start_thumbnailer(self, context)
|
||||
# start_thumbnailer(self, context)
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
|
@ -1014,8 +1035,9 @@ def header_search_draw(self, context):
|
|||
if ui_props.asset_type == 'BRUSH':
|
||||
props = s.blenderkit_brush
|
||||
|
||||
if context.space_data.show_region_tool_header == True:
|
||||
layout.separator_spacer()
|
||||
# the center snap menu is in edit and object mode if tool settings are off.
|
||||
if context.space_data.show_region_tool_header == True or context.mode[:4] not in ('EDIT', 'OBJE'):
|
||||
layout.separator_spacer()
|
||||
layout.prop(ui_props, "asset_type", text='', icon='URL')
|
||||
layout.prop(props, "search_keywords", text="", icon='VIEWZOOM')
|
||||
draw_assetbar_show_hide(layout, props)
|
||||
|
@ -1046,4 +1068,4 @@ def register_ui_panels():
|
|||
def unregister_ui_panels():
|
||||
for c in classess:
|
||||
bpy.utils.unregister_class(c)
|
||||
bpy.types.VIEW3D_MT_editor_menus.remove(header_search_draw)
|
||||
bpy.types.VIEW3D_MT_editor_menus.remove(header_search_draw)
|
||||
|
|
Loading…
Reference in New Issue