115 lines
3.8 KiB
Python
115 lines
3.8 KiB
Python
import functools
|
|
import logging
|
|
|
|
from flask import Blueprint, request, current_app, g
|
|
from eve.methods.get import get
|
|
from eve.utils import config as eve_config
|
|
from werkzeug.datastructures import MultiDict
|
|
from werkzeug.exceptions import InternalServerError
|
|
|
|
from application import utils
|
|
from application.utils.authentication import current_user_id
|
|
from application.utils.authorization import require_login
|
|
|
|
FIRST_ADDON_VERSION_WITH_HDRI = (1, 4, 0)
|
|
TL_PROJECTION = utils.dumps({'name': 1, 'url': 1, 'permissions': 1,})
|
|
TL_SORT = utils.dumps([('name', 1)])
|
|
|
|
TEXTURE_LIBRARY_QUERY_ARGS = {
|
|
eve_config.QUERY_PROJECTION: TL_PROJECTION,
|
|
eve_config.QUERY_SORT: TL_SORT,
|
|
'max_results': 'null', # this needs to be there, or we get a KeyError.
|
|
}
|
|
|
|
blueprint = Blueprint('blender_cloud.texture_libs', __name__)
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
def keep_fetching_texture_libraries(proj_filter):
|
|
groups = g.current_user['groups']
|
|
user_id = g.current_user['user_id']
|
|
|
|
page = 1
|
|
max_page = float('inf')
|
|
|
|
while page <= max_page:
|
|
request.args.setlist(eve_config.QUERY_PAGE, [page])
|
|
|
|
result, _, _, status, _ = get(
|
|
'projects',
|
|
{'$or': [
|
|
{'user': user_id},
|
|
{'permissions.groups.group': {'$in': groups}},
|
|
{'permissions.world': 'GET'}
|
|
]})
|
|
|
|
if status != 200:
|
|
log.warning('Error fetching texture libraries: %s', result)
|
|
raise InternalServerError('Error fetching texture libraries')
|
|
|
|
for proj in result['_items']:
|
|
if proj_filter(proj):
|
|
yield proj
|
|
|
|
# Compute the last page number we should query.
|
|
meta = result['_meta']
|
|
max_page = meta['total'] // meta['max_results']
|
|
if meta['total'] % meta['max_results'] > 0:
|
|
max_page += 1
|
|
|
|
page += 1
|
|
|
|
|
|
@blueprint.route('/texture-libraries')
|
|
@require_login()
|
|
def texture_libraries():
|
|
from . import blender_cloud_addon_version
|
|
|
|
# Use Eve method so that we get filtering on permissions for free.
|
|
# This gives all the projects that contain the required node types.
|
|
request.args = MultiDict(request.args) # allow changes; it's an ImmutableMultiDict by default.
|
|
request.args.setlist(eve_config.QUERY_PROJECTION, [TL_PROJECTION])
|
|
request.args.setlist(eve_config.QUERY_SORT, [TL_SORT])
|
|
|
|
# Determine whether to return HDRi projects too, based on the version
|
|
# of the Blender Cloud Addon. If the addon version is None, we're dealing
|
|
# with a version of the BCA that's so old it doesn't send its version along.
|
|
addon_version = blender_cloud_addon_version()
|
|
return_hdri = addon_version >= FIRST_ADDON_VERSION_WITH_HDRI
|
|
log.debug('User %s has Blender Cloud Addon version %s; return_hdri=%s',
|
|
current_user_id(), addon_version, return_hdri)
|
|
|
|
accept_as_library = functools.partial(has_texture_node, return_hdri=return_hdri)
|
|
|
|
# Construct eve-like response.
|
|
projects = list(keep_fetching_texture_libraries(accept_as_library))
|
|
result = {'_items': projects,
|
|
'_meta': {
|
|
'max_results': len(projects),
|
|
'page': 1,
|
|
'total': len(projects),
|
|
}}
|
|
|
|
return utils.jsonify(result)
|
|
|
|
|
|
def has_texture_node(proj, return_hdri=True):
|
|
"""Returns True iff the project has a top-level (group)texture node."""
|
|
|
|
nodes_collection = current_app.data.driver.db['nodes']
|
|
|
|
# See which types of nodes we support.
|
|
node_types = ['group_texture']
|
|
if return_hdri:
|
|
node_types.append('hdri')
|
|
|
|
count = nodes_collection.count(
|
|
{'node_type': {'$in': node_types},
|
|
'project': proj['_id'],
|
|
'parent': None})
|
|
return count > 0
|
|
|
|
|
|
def setup_app(app, url_prefix):
|
|
app.register_blueprint(blueprint, url_prefix=url_prefix)
|