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:
authorVilém Duha <vilda.novak@gmail.com>2020-12-31 16:07:58 +0300
committerVilém Duha <vilda.novak@gmail.com>2020-12-31 16:07:58 +0300
commit90918ce7adaa7b60d67370fb9929f0b4770bcf7a (patch)
tree26dce071f1ec4e8dd4ecbc4fe085bff7abcbbba5
parentac2ae65989f10a03f7a1009ddccddef07e8a9bac (diff)
BlenderKit Fast metadata edit operator
Shortcut Ctrl+F or menu item in asset context menu. Also several fixes to logging
-rw-r--r--blenderkit/__init__.py34
-rw-r--r--blenderkit/ratings.py10
-rw-r--r--blenderkit/ui.py2
-rw-r--r--blenderkit/ui_panels.py6
-rw-r--r--blenderkit/upload.py185
-rw-r--r--blenderkit/utils.py24
6 files changed, 155 insertions, 106 deletions
diff --git a/blenderkit/__init__.py b/blenderkit/__init__.py
index 6c690553..f3746ce7 100644
--- a/blenderkit/__init__.py
+++ b/blenderkit/__init__.py
@@ -113,10 +113,7 @@ def check_timers_timer():
return 5.0
-licenses = (
- ('royalty_free', 'Royalty Free', 'royalty free commercial license'),
- ('cc_zero', 'Creative Commons Zero', 'Creative Commons Zero'),
-)
+
conditions = (
('UNSPECIFIED', 'Unspecified', "Don't use this in search"),
('NEW', 'New', 'Shiny new item'),
@@ -266,7 +263,7 @@ def asset_type_callback(self, context):
('HDR', 'Hdrs', 'Browse hdrs', 'WORLD', 4),
('BRUSH', 'Brush', 'Upload a brush to BlenderKit', 'BRUSH_DATA', 5)
)
-
+
return items
@@ -527,29 +524,6 @@ def name_update(self, context):
utils.name_update()
-def update_tags(self, context):
- props = utils.get_upload_props()
-
- commasep = props.tags.split(',')
- ntags = []
- for tag in commasep:
- if len(tag) > 19:
- short_tags = tag.split(' ')
- for short_tag in short_tags:
- if len(short_tag) > 19:
- short_tag = short_tag[:18]
- ntags.append(short_tag)
- else:
- ntags.append(tag)
- if len(ntags) == 1:
- ntags = ntags[0].split(' ')
- ns = ''
- for t in ntags:
- if t != '':
- ns += t + ','
- ns = ns[:-1]
- if props.tags != ns:
- props.tags = ns
def update_free(self, context):
@@ -597,7 +571,7 @@ class BlenderKitCommonUploadProps(object):
name="Tags",
description="List of tags, separated by commas (optional)",
default="",
- update=update_tags
+ update=utils.update_tags
)
name_changed: BoolProperty(name="Name Changed",
@@ -616,7 +590,7 @@ class BlenderKitCommonUploadProps(object):
default="METALLIC",
)
license: EnumProperty(
- items=licenses,
+ items=upload.licenses,
default='royalty_free',
description='License. Please read our help for choosing the right licenses',
)
diff --git a/blenderkit/ratings.py b/blenderkit/ratings.py
index 3705f820..898867dd 100644
--- a/blenderkit/ratings.py
+++ b/blenderkit/ratings.py
@@ -29,6 +29,7 @@ else:
import bpy
import requests, threading
import logging
+
bk_logger = logging.getLogger('blenderkit')
from bpy.props import (
@@ -59,7 +60,7 @@ def pretty_print_POST(req):
def upload_rating_thread(url, ratings, headers):
''' Upload rating thread function / disconnected from blender data.'''
- bk_logger.debug('upload rating', url, ratings)
+ bk_logger.debug('upload rating ' + url + str(ratings))
for rating_name, score in ratings:
if (score != -1 and score != 0):
rating_url = url + rating_name + '/'
@@ -388,7 +389,7 @@ class FastRateMenu(Operator):
def poll(cls, context):
# scene = bpy.context.scene
# ui_props = scene.blenderkitUI
- return True#ui_props.active_index > -1
+ return True # ui_props.active_index > -1
def draw(self, context):
layout = self.layout
@@ -445,11 +446,12 @@ class FastRateMenu(Operator):
wm = context.window_manager
if utils.profile_is_validator() and self.asset_type == 'model':
- #spawn a wider one for validators for the enum buttons
- return wm.invoke_props_dialog(self, width = 500)
+ # spawn a wider one for validators for the enum buttons
+ return wm.invoke_props_dialog(self, width=500)
else:
return wm.invoke_props_dialog(self)
+
def rating_menu_draw(self, context):
layout = self.layout
diff --git a/blenderkit/ui.py b/blenderkit/ui.py
index 60e99c4f..411c3b18 100644
--- a/blenderkit/ui.py
+++ b/blenderkit/ui.py
@@ -1882,7 +1882,7 @@ def register_ui():
km = wm.keyconfigs.addon.keymaps['Window']
kmi = km.keymap_items.new(ratings.FastRateMenu.bl_idname, 'F', 'PRESS', ctrl=False, shift=False)
addon_keymapitems.append(kmi)
- kmi = km.keymap_items.new(upload.FastCategory.bl_idname, 'F', 'PRESS', ctrl=True, shift=False)
+ kmi = km.keymap_items.new(upload.FastMetadata.bl_idname, 'F', 'PRESS', ctrl=True, shift=False)
addon_keymapitems.append(kmi)
diff --git a/blenderkit/ui_panels.py b/blenderkit/ui_panels.py
index f3e0491e..985a846b 100644
--- a/blenderkit/ui_panels.py
+++ b/blenderkit/ui_panels.py
@@ -1282,6 +1282,12 @@ def draw_asset_context_menu(self, context, asset_data, from_panel=False):
if author_id == str(profile['user']['id']):
layout.label(text='Management tools:')
+
+ row = layout.row()
+ row.operator_context = 'INVOKE_DEFAULT'
+ op = layout.operator('wm.blenderkit_fast_metadata', text='Fast Edit Metadata')
+ op.asset_id = asset_data['id']
+
row = layout.row()
row.operator_context = 'INVOKE_DEFAULT'
op = row.operator('object.blenderkit_change_status', text='Delete')
diff --git a/blenderkit/upload.py b/blenderkit/upload.py
index 9d9303a9..9ca9f68d 100644
--- a/blenderkit/upload.py
+++ b/blenderkit/upload.py
@@ -62,6 +62,10 @@ from bpy.types import (
UIList
)
+licenses = (
+ ('royalty_free', 'Royalty Free', 'royalty free commercial license'),
+ ('cc_zero', 'Creative Commons Zero', 'Creative Commons Zero'),
+)
def comma2array(text):
commasep = text.split(',')
@@ -161,7 +165,7 @@ def camel_to_sub(content):
return replaced
-def get_upload_data(caller = None, context = None, asset_type = None):
+def get_upload_data(caller=None, context=None, asset_type=None):
'''
works though metadata from addom props and prepares it for upload to dicts.
Parameters
@@ -431,7 +435,7 @@ def get_upload_data(caller = None, context = None, asset_type = None):
ui_props = bpy.context.scene.blenderkitUI
# imagename = ui_props.hdr_upload_image
- image = ui_props.hdr_upload_image#bpy.data.images.get(imagename)
+ image = ui_props.hdr_upload_image # bpy.data.images.get(imagename)
if not image:
return None, None
@@ -452,7 +456,7 @@ def get_upload_data(caller = None, context = None, asset_type = None):
# mat analytics happen here, since they don't take up any time...
upload_params = {
- "textureResolutionMax" : props.texture_resolution_max
+ "textureResolutionMax": props.texture_resolution_max
}
@@ -491,7 +495,7 @@ def get_upload_data(caller = None, context = None, asset_type = None):
upload_data["description"] = props.description
upload_data["tags"] = comma2array(props.tags)
- #category is always only one value by a slug, that's why we go down to the lowest level and overwrite.
+ # category is always only one value by a slug, that's why we go down to the lowest level and overwrite.
if props.category == '':
upload_data["category"] = asset_type.lower()
else:
@@ -517,6 +521,7 @@ def get_upload_data(caller = None, context = None, asset_type = None):
return export_data, upload_data
+
def patch_individual_metadata(asset_id, metadata_dict, api_key):
upload_data = metadata_dict
url = paths.get_api_url() + 'assets/' + str(asset_id) + '/'
@@ -528,23 +533,12 @@ def patch_individual_metadata(asset_id, metadata_dict, api_key):
return {'CANCELLED'}
return {'FINISHED'}
-def category_change_thread(asset_id, category, api_key):
- upload_data = {
- "category": category
- }
- url = paths.get_api_url() + 'assets/' + str(asset_id) + '/'
- headers = utils.get_headers(api_key)
- try:
- r = rerequests.patch(url, json=upload_data, headers=headers, verify=True) # files = files,
- except requests.exceptions.RequestException as e:
- print(e)
- return {'CANCELLED'}
- return {'FINISHED'}
-# class OBJECT_MT_blenderkit_fast_category_menu(bpy.types.Menu):
+
+# class OBJECT_MT_blenderkit_fast_metadata_menu(bpy.types.Menu):
# bl_label = "Fast category change"
-# bl_idname = "OBJECT_MT_blenderkit_fast_category_menu"
+# bl_idname = "OBJECT_MT_blenderkit_fast_metadata_menu"
#
# def draw(self, context):
# layout = self.layout
@@ -558,16 +552,35 @@ def category_change_thread(asset_id, category, api_key):
# for c in categories:
# if c['name'].lower() == asset_data['assetType']:
# for ch in c['children']:
-# op = layout.operator('wm.blenderkit_fast_category', text = ch['name'])
-# op = layout.operator('wm.blenderkit_fast_category', text = ch['name'])
+# op = layout.operator('wm.blenderkit_fast_metadata', text = ch['name'])
+# op = layout.operator('wm.blenderkit_fast_metadata', text = ch['name'])
-class FastCategory(bpy.types.Operator):
+class FastMetadata(bpy.types.Operator):
"""Fast change of the category of object directly in asset bar."""
- bl_idname = "wm.blenderkit_fast_category"
- bl_label = "Update categories"
+ bl_idname = "wm.blenderkit_fast_metadata"
+ bl_label = "Update metadata"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
+ asset_id: StringProperty(
+ name="Asset Base Id",
+ description="Unique name of the asset (hidden)",
+ default=""
+ )
+ name: StringProperty(
+ name="Name",
+ description="Main name of the asset",
+ default="",
+ )
+ description: StringProperty(
+ name="Description",
+ description="Description of the asset",
+ default="")
+ tags: StringProperty(
+ name="Tags",
+ description="List of tags, separated by commas (optional)",
+ default="",
+ )
category: EnumProperty(
name="Category",
description="main category to put into",
@@ -583,11 +596,21 @@ class FastCategory(bpy.types.Operator):
description="main category to put into",
items=categories.get_subcategory1_enums
)
-
- asset_id: StringProperty(
- name="Asset Base Id",
- description="Unique name of the asset (hidden)",
- default="")
+ license: EnumProperty(
+ items=licenses,
+ default='royalty_free',
+ description='License. Please read our help for choosing the right licenses',
+ )
+ is_private: EnumProperty(
+ name="Thumbnail Style",
+ items=(
+ ('PRIVATE', 'Private', "You asset will be hidden to public. The private assets are limited by a quota."),
+ ('PUBLIC', 'Public', '"Your asset will go into the validation process automatically')
+ ),
+ description="If not marked private, your asset will go into the validation process automatically\n"
+ "Private assets are limited by quota.",
+ default="PUBLIC",
+ )
@classmethod
def poll(cls, context):
@@ -600,34 +623,47 @@ class FastCategory(bpy.types.Operator):
# col = layout.column()
layout.label(text=self.message)
row = layout.row()
- # col = row.column()
- # layout.template_icon_view(bkit_ratings, property, show_labels=False, scale=6.0, scale_popup=5.0)
- # col.prop(self, 'category')
layout.prop(self, 'category')
if self.category != 'NONE' and self.subcategory != 'NONE':
layout.prop(self, 'subcategory')
if self.subcategory != 'NONE' and self.subcategory1 != 'NONE':
layout.prop(self, 'subcategory1')
+ layout.prop(self, 'name')
+ layout.prop(self, 'description')
+ layout.prop(self, 'tags')
+ layout.prop(self, 'is_private', expand=True)
+ if self.is_private == 'PUBLIC':
+ layout.prop(self, 'license')
+
- # layout.prop(self, 'category') # , expand = True)
- # props = bpy.context.scene.blenderkitUI
- # if props.asset_type == 'MODEL': # by now block this for other asset types.
- # # col = row.column()
- # layout.prop(self, 'subcategory')
- # layout.prop(self, 'subcategory1')
- # # layout.prop(self, 'subcategory', expand = True)
def execute(self, context):
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
props = bpy.context.scene.blenderkitUI
- if props.asset_type == 'MODEL':
+ if self.subcategory1 != 'NONE':
+ category = self.subcategory1
+ elif self.subcategory != 'NONE':
category = self.subcategory
else:
category = self.category
- thread = threading.Thread(target=category_change_thread,
- args=(self.asset_id, category, user_preferences.api_key))
+ utils.update_tags(self, context)
+
+ mdict = {
+ 'category': category,
+ 'displayName': self.name,
+ 'description': self.description,
+ 'tags': comma2array(self.tags),
+ 'isPrivate': self.is_private == 'PRIVATE',
+ 'license': self.license,
+ }
+
+ thread = threading.Thread(target=patch_individual_metadata,
+ args=(self.asset_id, mdict, user_preferences.api_key))
thread.start()
+ tasks_queue.add_task((ui.add_report, (f'Uploading metadata for {self.name}. '
+ f'Refreash search results to see that changes applied correctly.', 8,)))
+
return {'FINISHED'}
def invoke(self, context, event):
@@ -636,20 +672,34 @@ class FastCategory(bpy.types.Operator):
if ui_props.active_index > -1:
sr = bpy.context.scene['search results']
asset_data = dict(sr[ui_props.active_index])
- self.asset_id = asset_data['id']
- self.asset_type = asset_data['assetType']
- cat_path = categories.get_category_path(bpy.context.window_manager['bkit_categories'],
- asset_data['category'])
- try:
- if len(cat_path) > 1:
- self.category = cat_path[1]
- if len(cat_path) > 2:
- self.subcategory = cat_path[2]
- except Exception as e:
- print(e)
- self.message = f"Recategorize asset {asset_data['name']}"
+ else:
+ for result in bpy.context.scene['search results']:
+ if result['id'] == self.asset_id:
+ asset_data = dict(result)
+
+ self.asset_id = asset_data['id']
+ self.asset_type = asset_data['assetType']
+ cat_path = categories.get_category_path(bpy.context.window_manager['bkit_categories'],
+ asset_data['category'])
+ try:
+ if len(cat_path) > 1:
+ self.category = cat_path[1]
+ if len(cat_path) > 2:
+ self.subcategory = cat_path[2]
+ except Exception as e:
+ print(e)
+ self.message = f"Recategorize asset {asset_data['name']}"
+ self.name = asset_data['displayName']
+ self.description = asset_data['description']
+ self.tags = ','.join(asset_data['tags'])
+ if asset_data['isPrivate']:
+ self.is_private = 'PRIVATE'
+ else:
+ self.is_private = 'PUBLIC'
+ self.license = asset_data['license']
+
wm = context.window_manager
- return wm.invoke_props_dialog(self)
+ return wm.invoke_props_dialog(self, width = 600)
def verification_status_change_thread(asset_id, state, api_key):
@@ -773,7 +823,6 @@ class Uploader(threading.Thread):
script_path = os.path.dirname(os.path.realpath(__file__))
-
# first upload metadata to server, so it can be saved inside the current file
url = paths.get_api_url() + 'assets/'
@@ -836,17 +885,16 @@ class Uploader(threading.Thread):
if self.export_data['assetBaseId'] == '':
self.export_data['assetBaseId'] = rj['assetBaseId']
self.export_data['id'] = rj['id']
- #here we need to send asset ID's back into UI to be written in asset data.
- estring = f"{self.export_data['eval_path']}.blenderkit.asset_base_id = '{rj['assetBaseId']}'"
+ # here we need to send asset ID's back into UI to be written in asset data.
+ estring = f"{self.export_data['eval_path']}.blenderkit.asset_base_id = '{rj['assetBaseId']}'"
tasks_queue.add_task((exec, (estring,)))
- estring = f"{self.export_data['eval_path']}.blenderkit.id = '{rj['id']}'"
+ estring = f"{self.export_data['eval_path']}.blenderkit.id = '{rj['id']}'"
tasks_queue.add_task((exec, (estring,)))
- #after that, the user's file needs to be saved to save the
+ # after that, the user's file needs to be saved to save the
self.upload_data['assetBaseId'] = self.export_data['assetBaseId']
self.upload_data['id'] = self.export_data['id']
-
# props.uploading = True
if 'MAINFILE' in self.upload_set:
@@ -868,7 +916,7 @@ class Uploader(threading.Thread):
with open(datafile, 'w') as s:
json.dump(data, s)
- #non waiting method - not useful here..
+ # non waiting method - not useful here..
# proc = subprocess.Popen([
# binary_path,
# "--background",
@@ -893,7 +941,6 @@ class Uploader(threading.Thread):
self.end_upload('Upload stopped by user')
return
-
files = []
if 'THUMBNAIL' in self.upload_set:
files.append({
@@ -902,7 +949,6 @@ class Uploader(threading.Thread):
"file_path": self.export_data["thumbnail_path"]
})
if 'MAINFILE' in self.upload_set:
-
files.append({
"type": "blend",
"index": 0,
@@ -959,7 +1005,6 @@ def check_missing_data(asset_type, props):
check_missing_data_brush(props)
-
def start_upload(self, context, asset_type, reupload, upload_set):
'''start upload process, by processing data, then start a thread that cares about the rest of the upload.'''
@@ -980,7 +1025,6 @@ def start_upload(self, context, asset_type, reupload, upload_set):
# do this for fixing long tags in some upload cases
props.tags = props.tags[:]
-
# check for missing metadata
check_missing_data(asset_type, props)
# if previous check did find any problems then
@@ -992,7 +1036,7 @@ def start_upload(self, context, asset_type, reupload, upload_set):
props.asset_base_id = ''
props.id = ''
- export_data, upload_data = get_upload_data(caller = self, context = context, asset_type = asset_type)
+ export_data, upload_data = get_upload_data(caller=self, context=context, asset_type=asset_type)
# print(export_data)
# print(upload_data)
# check if thumbnail exists, generate for HDR:
@@ -1010,7 +1054,6 @@ def start_upload(self, context, asset_type, reupload, upload_set):
props.upload_state = "Starting upload. Please don't close Blender until upload finishes"
props.uploading = True
-
# save a copy of the file for processing. Only for blend files
basename, ext = os.path.splitext(bpy.data.filepath)
if not ext:
@@ -1249,15 +1292,15 @@ class AssetVerificationStatusChange(Operator):
def register_upload():
bpy.utils.register_class(UploadOperator)
- # bpy.utils.register_class(FastCategoryMenu)
- bpy.utils.register_class(FastCategory)
+ # bpy.utils.register_class(FastMetadataMenu)
+ bpy.utils.register_class(FastMetadata)
bpy.utils.register_class(AssetDebugPrint)
bpy.utils.register_class(AssetVerificationStatusChange)
def unregister_upload():
bpy.utils.unregister_class(UploadOperator)
- # bpy.utils.unregister_class(FastCategoryMenu)
- bpy.utils.unregister_class(FastCategory)
+ # bpy.utils.unregister_class(FastMetadataMenu)
+ bpy.utils.unregister_class(FastMetadata)
bpy.utils.unregister_class(AssetDebugPrint)
bpy.utils.unregister_class(AssetVerificationStatusChange)
diff --git a/blenderkit/utils.py b/blenderkit/utils.py
index 09d6c77b..7befc97e 100644
--- a/blenderkit/utils.py
+++ b/blenderkit/utils.py
@@ -677,6 +677,7 @@ def get_param(asset_data, parameter_name):
return None
+
def params_to_dict(params):
params_dict = {}
for p in params:
@@ -707,6 +708,29 @@ def dict_to_params(inputs, parameters=None):
})
return parameters
+def update_tags(self, context):
+ props = self
+
+ commasep = props.tags.split(',')
+ ntags = []
+ for tag in commasep:
+ if len(tag) > 19:
+ short_tags = tag.split(' ')
+ for short_tag in short_tags:
+ if len(short_tag) > 19:
+ short_tag = short_tag[:18]
+ ntags.append(short_tag)
+ else:
+ ntags.append(tag)
+ if len(ntags) == 1:
+ ntags = ntags[0].split(' ')
+ ns = ''
+ for t in ntags:
+ if t != '':
+ ns += t + ','
+ ns = ns[:-1]
+ if props.tags != ns:
+ props.tags = ns
def user_logged_in():
a = bpy.context.window_manager.get('bkit profile')