Merge branch 'blender-v2.92-release'

This commit is contained in:
Julien Duroure 2021-02-10 20:18:06 +01:00
commit e5a2d98c82
10 changed files with 4910 additions and 2055 deletions

View File

@ -1402,7 +1402,7 @@ class BlenderKitModelSearchProps(PropertyGroup, BlenderKitCommonSearchProps):
),
description="Appended objects are editable in your scene. Linked assets are saved in original files, "
"aren't editable but also don't increase your file size",
default="LINK_COLLECTION"
default="APPEND_OBJECTS"
)
append_link: EnumProperty(
name="How to Attach",
@ -1498,7 +1498,19 @@ class BlenderKitSceneSearchProps(PropertyGroup, BlenderKitCommonSearchProps):
default="",
update=search.search_update
)
append_link: EnumProperty(
name="Append or link",
items=(
('LINK', 'Link', ''),
('APPEND', 'Append', ''),
),
description="choose if the scene will be linked or appended",
default="APPEND"
)
switch_after_append: BoolProperty(
name = 'Switch to scene after download',
default = False
)
def fix_subdir(self, context):
'''Fixes project subdicrectory settings if people input invalid path.'''

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@ import shutil, sys, os
import uuid
import copy
import logging
bk_logger = logging.getLogger('blenderkit')
import bpy
@ -303,8 +304,7 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
#####
# how to do particle drop:
# link the group we are interested in( there are more groups in File!!!! , have to get the correct one!)
#
scene = bpy.context.scene
s = bpy.context.scene
user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
@ -312,16 +312,22 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
user_preferences.asset_counter += 1
if asset_data['assetType'] == 'scene':
scene = append_link.append_scene(file_names[0], link=False, fake_user=False)
props = scene.blenderkit
asset_main = scene
sprops = s.blenderkit_scene
scene = append_link.append_scene(file_names[0], link=sprops.append_link == 'LINK', fake_user=False)
print('scene appended')
if scene is not None:
props = scene.blenderkit
asset_main = scene
print(sprops.switch_after_append)
if sprops.switch_after_append:
bpy.context.window_manager.windows[0].scene = scene
if asset_data['assetType'] == 'hdr':
hdr = append_link.load_HDR(file_name = file_names[0], name = asset_data['name'])
hdr = append_link.load_HDR(file_name=file_names[0], name=asset_data['name'])
props = hdr.blenderkit
asset_main = hdr
s = bpy.context.scene
if asset_data['assetType'] == 'model':
downloaders = kwargs.get('downloaders')
@ -899,7 +905,7 @@ def check_existing(asset_data, resolution='blend', can_return_others=False):
file_names = paths.get_download_filepaths(asset_data, resolution, can_return_others=can_return_others)
bk_logger.debug('check if file already exists'+ str( file_names))
bk_logger.debug('check if file already exists' + str(file_names))
if len(file_names) == 2:
# TODO this should check also for failed or running downloads.
# If download is running, assign just the running thread. if download isn't running but the file is wrong size,
@ -1147,7 +1153,7 @@ def start_download(asset_data, **kwargs):
# check if there are files already. This check happens 2x once here(for free assets),
# once in thread(for non-free)
fexists = check_existing(asset_data, resolution=kwargs['resolution'])
bk_logger.debug('does file exist?'+ str( fexists))
bk_logger.debug('does file exist?' + str(fexists))
bk_logger.debug('asset is in scene' + str(ain))
if ain and not kwargs.get('replace_resolution'):
# this goes to appending asset - where it should duplicate the original asset already in scene.

View File

@ -54,6 +54,17 @@ def img_save_as(img, filepath='//', file_format='JPEG', quality=90, color_mode='
set_orig_render_settings(ors)
def set_colorspace(img, colorspace):
'''sets image colorspace, but does so in a try statement, because some people might actually replace the default
colorspace settings, and it literally can't be guessed what these people use, even if it will mostly be the filmic addon.
'''
try:
if colorspace == 'Non-Color':
img.colorspace_settings.is_data = True
else:
img.colorspace_settings.name = colorspace
except:
print(f'Colorspace {colorspace} not found.')
def generate_hdr_thumbnail():
scene = bpy.context.scene
@ -79,7 +90,7 @@ def generate_hdr_thumbnail():
hdr_image.pixels.foreach_get(tempBuffer)
inew.filepath = thumb_path
inew.colorspace_settings.name = 'Linear'
set_colorspace(inew, 'Linear')
inew.pixels.foreach_set(tempBuffer)
bpy.context.view_layer.update()

View File

@ -337,7 +337,7 @@ class FastRateMenu(Operator):
rating_work_hours: FloatProperty(name="Work Hours",
description="How many hours did this work take?",
default=0.00,
min=0.0, max=150, update=update_ratings_work_hours
min=0.0, max=300, update=update_ratings_work_hours
)
rating_work_hours_ui: EnumProperty(name="Work Hours",

View File

@ -17,7 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
from blenderkit import paths, utils, categories, ui, colors, bkit_oauth, version_checker, tasks_queue, rerequests, \
resolutions
resolutions, image_utils
import blenderkit
from bpy.app.handlers import persistent
@ -474,9 +474,9 @@ def load_previews():
img.reload()
if r['assetType'] == 'hdr':
# to display hdr thumbnails correctly, we use non-color, otherwise looks shifted
img.colorspace_settings.name = 'Non-Color'
image_utils.set_colorspace(img, 'Non-Color')
else:
img.colorspace_settings.name = 'sRGB'
image_utils.set_colorspace(img, 'sRGB')
i += 1
# print('previews loaded')

View File

@ -1672,6 +1672,12 @@ class AssetBarOperator(bpy.types.Operator):
target_slot = temp_mesh.polygons[face_index].material_index
object_eval.to_mesh_clear()
else:
if object.is_library_indirect:
ui_panels.ui_message(title='This object is linked from outer file',
message="Please select the model,"
"go to the 'Selected Model' panel "
"in BlenderKit and hit 'Bring to Scene' first.")
self.report({'WARNING'}, "Invalid or library object as input:")
target_object = ''
target_slot = ''
@ -1914,6 +1920,12 @@ def draw_callback_3d_dragging(self, context):
if self.has_hit:
draw_bbox(self.snapped_location, self.snapped_rotation, self.snapped_bbox_min, self.snapped_bbox_max)
def find_and_activate_instancers(object):
for ob in bpy.context.visible_objects:
if ob.instance_type == 'COLLECTION' and ob.instance_collection and object.name in ob.instance_collection.objects:
utils.activate(ob)
return ob
class AssetDragOperator(bpy.types.Operator):
"""Draw a line with the mouse"""
@ -1942,6 +1954,11 @@ class AssetDragOperator(bpy.types.Operator):
if ui_props.asset_type == 'MATERIAL':
# first, test if object can have material applied.
object = bpy.data.objects[self.object_name]
# this enables to run Bring to scene automatically when dropping on a linked objects.
# it's however quite a slow operation, that's why not enabled (and finished) now.
# if object is not None and object.is_library_indirect:
# find_and_activate_instancers(object)
# bpy.ops.object.blenderkit_bring_to_scene()
if object is not None and not object.is_library_indirect and object.type == 'MESH':
target_object = object.name
# create final mesh to extract correct material slot
@ -1953,6 +1970,12 @@ class AssetDragOperator(bpy.types.Operator):
# elif object.is_library_indirect:#case for bring to scene objects, will be solved through prefs and direct
# action
else:
if object.is_library_indirect:
ui_panels.ui_message(title = 'This object is linked from outer file',
message = "Please select the model,"
"go to the 'Selected Model' panel "
"in BlenderKit and hit 'Bring to Scene' first.")
self.report({'WARNING'}, "Invalid or library object as input:")
target_object = ''
target_slot = ''
@ -2007,6 +2030,11 @@ class AssetDragOperator(bpy.types.Operator):
target_object=target_object)
else:
if ui_props.asset_type =='SCENE':
ui_panels.ui_message(title = 'Scene will be appended after download',
message = 'After the scene is appended, you have to switch to it manually.'
'If you want to switch to scenes automatically after appending,'
' you can set it in import settings.')
bpy.ops.scene.blenderkit_download( # asset_type=ui_props.asset_type,
asset_index=self.asset_search_index)

View File

@ -112,7 +112,7 @@ def draw_upload_common(layout, props, asset_type, context):
op = layout.operator("object.blenderkit_upload", text=optext, icon='EXPORT')
op.asset_type = asset_type
op.reupload = False
#make sure everything gets uploaded.
# make sure everything gets uploaded.
op.main_file = True
op.metadata = True
op.thumbnail = True
@ -163,6 +163,7 @@ def prop_needed(layout, props, name, value, is_not_filled=''):
icon = None
row.prop(props, name)
def draw_panel_hdr_upload(self, context):
layout = self.layout
ui_props = bpy.context.scene.blenderkitUI
@ -172,7 +173,6 @@ def draw_panel_hdr_upload(self, context):
hdr = utils.get_active_HDR()
if hdr is not None:
props = hdr.blenderkit
@ -184,6 +184,7 @@ def draw_panel_hdr_upload(self, context):
layout.prop(props, 'description')
layout.prop(props, 'tags')
def draw_panel_hdr_search(self, context):
s = context.scene
props = s.blenderkit_HDR
@ -196,6 +197,7 @@ def draw_panel_hdr_search(self, context):
utils.label_multiline(layout, text=props.report)
def draw_panel_model_upload(self, context):
ob = bpy.context.active_object
while ob.parent is not None:
@ -316,7 +318,7 @@ def draw_assetbar_show_hide(layout, props):
preferences = bpy.context.preferences.addons['blenderkit'].preferences
if preferences.experimental_features:
op = layout.operator('view3d.blenderkit_asset_bar_widget', text = '', icon = icon)
op = layout.operator('view3d.blenderkit_asset_bar_widget', text='', icon=icon)
op.keep_running = False
op.do_search = False
op.tooltip = ttip
@ -510,7 +512,7 @@ class VIEW3D_PT_blenderkit_ratings(Panel):
utils.label_multiline(layout, text='Please help BlenderKit community by rating these assets:')
for a in assets:
if a.bkit_ratings.rating_work_hours==0:
if a.bkit_ratings.rating_work_hours == 0:
draw_rating_asset(self, context, asset=a)
@ -546,7 +548,7 @@ class VIEW3D_PT_blenderkit_profile(Panel):
if me is not None:
me = me['user']
# user name
if len(me['firstName'])>0 or len(me['lastName'])>0:
if len(me['firstName']) > 0 or len(me['lastName']) > 0:
layout.label(text=f"Me: {me['firstName']} {me['lastName']}")
else:
layout.label(text=f"Me: {me['email']}")
@ -781,7 +783,6 @@ class VIEW3D_PT_blenderkit_advanced_model_search(Panel):
layout.prop(props, "free_only")
layout.prop(props, "search_style")
# DESIGN YEAR
layout.prop(props, "search_design_year", text='Designed in Year')
if props.search_design_year:
@ -897,7 +898,7 @@ class VIEW3D_PT_blenderkit_import_settings(Panel):
def poll(cls, context):
s = context.scene
ui_props = s.blenderkitUI
return ui_props.down_up == 'SEARCH' and ui_props.asset_type in ['MATERIAL', 'MODEL', 'HDR']
return ui_props.down_up == 'SEARCH' and ui_props.asset_type in ['MATERIAL', 'MODEL', 'SCENE', 'HDR']
def draw(self, context):
layout = self.layout
@ -926,10 +927,17 @@ class VIEW3D_PT_blenderkit_import_settings(Panel):
row = layout.row()
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)
if ui_props.asset_type == 'HDR':
props = s.blenderkit_HDR
layout.prop(props, 'resolution')
if ui_props.asset_type in ['MATERIAL', 'MODEL', 'HDR']:
layout.prop(props, 'resolution')
# layout.prop(props, 'unpack_files')
@ -1199,7 +1207,6 @@ def draw_asset_context_menu(layout, context, asset_data, from_panel=False):
# if ui_props.asset_type in ('MODEL', 'MATERIAL'):
# layout.menu(OBJECT_MT_blenderkit_resolution_menu.bl_idname)
if ui_props.asset_type in ('MODEL', 'MATERIAL', 'HDR') and \
utils.get_param(asset_data, 'textureResolutionMax') is not None and \
utils.get_param(asset_data, 'textureResolutionMax') > 512:
@ -1247,7 +1254,8 @@ def draw_asset_context_menu(layout, context, asset_data, from_panel=False):
op.invoke_resolution = True
o = utils.get_active_model()
if o and o.get('asset_data'):
if o['asset_data']['assetBaseId'] == bpy.context.window_manager['search results'][ui_props.active_index]:
if o['asset_data']['assetBaseId'] == bpy.context.window_manager['search results'][
ui_props.active_index]:
op.model_location = o.location
op.model_rotation = o.rotation_euler
else:
@ -1302,14 +1310,10 @@ def draw_asset_context_menu(layout, context, asset_data, from_panel=False):
if utils.profile_is_validator():
layout.label(text='Admin Tools:')
op = layout.operator('object.blenderkit_print_asset_debug', text='Print asset debug')
op.asset_id = asset_data['id']
# def draw_asset_resolution_replace(self, context, resolution):
# layout = self.layout
# ui_props = bpy.context.scene.blenderkitUI
@ -1392,12 +1396,13 @@ class OBJECT_MT_blenderkit_asset_menu(bpy.types.Menu):
# box2.label(text='************')
# box2.label(text='dadydadadada')
class AssetPopupCard(bpy.types.Operator):
"""Generate Cycles thumbnail for model assets"""
bl_idname = "wm.blenderkit_asset_popup"
bl_label = "BlenderKit asset popup"
# bl_options = {'REGISTER', 'INTERNAL'}
bl_options = {'REGISTER',}
bl_options = {'REGISTER', }
@classmethod
def poll(cls, context):
@ -1418,11 +1423,10 @@ class AssetPopupCard(bpy.types.Operator):
split = split.split(factor=0.5)
col1 = split.column()
box = col1.box()
utils.label_multiline(box,asset_data['tooltip'], width = 300)
utils.label_multiline(box, asset_data['tooltip'], width=300)
col2 = split.column()
pcoll = icons.icon_collections["main"]
my_icon = pcoll['test']
col2.template_icon(icon_value=my_icon.icon_id, scale=20.0)
@ -1430,7 +1434,7 @@ class AssetPopupCard(bpy.types.Operator):
box2 = col2.box()
# draw_ratings(box2, context, asset_data)
box2.label(text = 'Ratings')
box2.label(text='Ratings')
# print(tp, dir(tp))
# if not hasattr(self, 'first_draw'):# try to redraw because of template preview which needs update
# for region in context.area.regions:
@ -1451,8 +1455,9 @@ class AssetPopupCard(bpy.types.Operator):
# self.tex = utils.get_hidden_texture(self.img)
# self.tex.update_tag()
bl_label = asset_data['name']
return wm.invoke_props_dialog(self, width = 700)
bl_label = asset_data['name']
return wm.invoke_props_dialog(self, width=700)
class OBJECT_MT_blenderkit_login_menu(bpy.types.Menu):
bl_label = "BlenderKit login/signup:"
@ -1523,14 +1528,14 @@ class UrlPopupDialog(bpy.types.Operator):
def draw(self, context):
layout = self.layout
utils.label_multiline(layout, text=self.message, width = 300)
utils.label_multiline(layout, text=self.message, width=300)
layout.active_default = True
op = layout.operator("wm.url_open", text=self.link_text, icon='QUESTION')
if not utils.user_logged_in():
utils.label_multiline(layout,
text='Already subscribed? You need to login to access your Full Plan.',
width = 300)
width=300)
layout.operator_context = 'EXEC_DEFAULT'
layout.operator("wm.blenderkit_login", text="Login",
@ -1544,7 +1549,7 @@ class UrlPopupDialog(bpy.types.Operator):
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self,width = 300)
return wm.invoke_props_dialog(self, width=300)
class LoginPopupDialog(bpy.types.Operator):
@ -1695,16 +1700,19 @@ def header_search_draw(self, context):
# 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", expand = True, icon_only = True, text='', icon='URL')
layout.prop(ui_props, "asset_type", expand=True, icon_only=True, text='', icon='URL')
layout.prop(props, "search_keywords", text="", icon='VIEWZOOM')
draw_assetbar_show_hide(layout, props)
def ui_message(title, message):
def draw_message(self, context):
layout = self.layout
utils.label_multiline(layout, text=message)
utils.label_multiline(layout, text=message, width=400)
bpy.context.window_manager.popup_menu(draw_message, title=title, icon='INFO')
# We can store multiple preview collections here,
# however in this example we only store "main"
preview_collections = {}

View File

@ -17,7 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
from blenderkit import paths, rerequests
from blenderkit import paths, rerequests, image_utils
import bpy
from mathutils import Vector
@ -313,7 +313,6 @@ def get_hidden_texture(img, force_reload=False):
t.image = img
return t
def get_hidden_image(tpath, bdata_name, force_reload=False, colorspace = 'sRGB'):
if bdata_name[0] == '.':
hidden_name = bdata_name
@ -340,12 +339,13 @@ def get_hidden_image(tpath, bdata_name, force_reload=False, colorspace = 'sRGB')
img.filepath = tpath
img.reload()
img.colorspace_settings.name = colorspace
image_utils.set_colorspace(img,colorspace)
elif force_reload:
if img.packed_file is not None:
img.unpack(method='USE_ORIGINAL')
img.reload()
img.colorspace_settings.name = colorspace
image_utils.set_colorspace(img,colorspace)
return img
@ -355,7 +355,7 @@ def get_thumbnail(name):
img = bpy.data.images.get(name)
if img == None:
img = bpy.data.images.load(p)
img.colorspace_settings.name = 'sRGB'
image_utils.set_colorspace(img,'sRGB')
img.name = name
img.name = name

View File

@ -15,7 +15,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
"version": (1, 6, 3),
"version": (1, 6, 4),
'blender': (2, 91, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',
@ -70,21 +70,42 @@ from bpy_extras.io_utils import ImportHelper, ExportHelper
extension_panel_unregister_functors = []
def ensure_filepath_matches_export_format(filepath, export_format):
import os
filename = os.path.basename(filepath)
if not filename:
return filepath
stem, ext = os.path.splitext(filename)
if stem.startswith('.') and not ext:
stem, ext = '', stem
desired_ext = '.glb' if export_format == 'GLB' else '.gltf'
ext_lower = ext.lower()
if ext_lower not in ['.glb', '.gltf']:
return filepath + desired_ext
elif ext_lower != desired_ext:
filepath = filepath[:-len(ext)] # strip off ext
return filepath + desired_ext
else:
return filepath
def on_export_format_changed(self, context):
# Update the file extension when the format (.glb/.gltf) changes
# Update the filename in the file browser when the format (.glb/.gltf)
# changes
sfile = context.space_data
if sfile is None:
return # Avoid error when export from background
operator = sfile.active_operator
if operator.bl_idname != "EXPORT_SCENE_OT_gltf":
if not isinstance(sfile, bpy.types.SpaceFileBrowser):
return
if operator.check(context):
# Weird hack to force the filepicker to notice filename changed
from os.path import basename
filepath = operator.filepath
bpy.ops.file.filenum(increment=-1)
if basename(operator.filepath) != basename(filepath):
bpy.ops.file.filenum(increment=1)
if not sfile.active_operator:
return
if sfile.active_operator.bl_idname != "EXPORT_SCENE_OT_gltf":
return
sfile.params.filename = ensure_filepath_matches_export_format(
sfile.params.filename,
self.export_format,
)
class ExportGLTF2_Base:
@ -384,28 +405,12 @@ class ExportGLTF2_Base:
def check(self, _context):
# Ensure file extension matches format
import os
filename = os.path.basename(self.filepath)
if filename:
filepath = self.filepath
desired_ext = '.glb' if self.export_format == 'GLB' else '.gltf'
stem, ext = os.path.splitext(filename)
if stem.startswith('.') and not ext:
stem, ext = '', stem
ext_lower = ext.lower()
if ext_lower not in ['.glb', '.gltf']:
filepath = filepath + desired_ext
elif ext_lower != desired_ext:
filepath = filepath[:-len(ext)] # strip off ext
filepath += desired_ext
if filepath != self.filepath:
self.filepath = filepath
return True
return False
old_filepath = self.filepath
self.filepath = ensure_filepath_matches_export_format(
self.filepath,
self.export_format,
)
return self.filepath != old_filepath
def invoke(self, context, event):
settings = context.scene.get(self.scene_key)