From 20cbcd98e0455a0afdf8c69d7864f0721c49bca0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 23 Sep 2021 17:49:59 +0200 Subject: Auto Tile Size: remove the add-on after the cycles-x merge The new render scheduling in Cycles makes this obsolete. There can still be reasons for tweaking tile size, mainly related to memory usage, but the add-on is not designed for that. Fixes T91645 --- render_auto_tile_size.py | 500 ----------------------------------------------- 1 file changed, 500 deletions(-) delete mode 100644 render_auto_tile_size.py diff --git a/render_auto_tile_size.py b/render_auto_tile_size.py deleted file mode 100644 index 078513c6..00000000 --- a/render_auto_tile_size.py +++ /dev/null @@ -1,500 +0,0 @@ -# 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 ##### - -bl_info = { - "name": "Auto Tile Size", - "description": "Estimate and set the tile size that will render the fastest", - "author": "Greg Zaal", - "version": (3, 1, 3), - "blender": (2, 80, 0), - "location": "Render Settings > Performance", - "warning": "", - "doc_url": "{BLENDER_MANUAL_URL}/addons/render/auto_tile_size.html", - "category": "Render", -} - - -import bpy -from bpy.types import ( - Operator, - PropertyGroup, - ) -from bpy.props import ( - BoolProperty, - EnumProperty, - FloatVectorProperty, - IntProperty, - IntVectorProperty, - StringProperty, - PointerProperty, - ) -from bpy.app.handlers import persistent -from math import ( - ceil, floor, - sqrt, - ) - - -SUPPORTED_RENDER_ENGINES = {'CYCLES', 'BLENDER_RENDER'} -TILE_SIZES = ( - ('16', "16", "16 x 16"), - ('32', "32", "32 x 32"), - ('64', "64", "64 x 64"), - ('128', "128", "128 x 128"), - ('256', "256", "256 x 256"), - ('512', "512", "512 x 512"), - ('1024', "1024", "1024 x 1024"), -) - - -def _update_tile_size(self, context): - do_set_tile_size(context) - - -class AutoTileSizeSettings(PropertyGroup): - gpu_choice: EnumProperty( - name="Target GPU Tile Size", - items=TILE_SIZES, - default='256', - description="Square dimensions of tiles for GPU rendering", - update=_update_tile_size - ) - cpu_choice: EnumProperty( - name="Target CPU Tile Size", - items=TILE_SIZES, - default='32', - description="Square dimensions of tiles for CPU rendering", - update=_update_tile_size - ) - bi_choice: EnumProperty( - name="Target CPU Tile Size", - items=TILE_SIZES, - default='64', - description="Square dimensions of tiles", - update=_update_tile_size - ) - gpu_custom: IntProperty( - name="Target Size", - default=256, - min=8, # same as blender's own limits - max=65536, - description="Custom target tile size for GPU rendering", - update=_update_tile_size - ) - cpu_custom: IntProperty( - name="Target Size", - default=32, - min=8, # same as blender's own limits - max=65536, - description="Custom target tile size for CPU rendering", - update=_update_tile_size - ) - bi_custom: IntProperty( - name="Target Size", - default=64, - min=8, # same as blender's own limits - max=65536, - description="Custom target tile size", - update=_update_tile_size - ) - target_type: EnumProperty( - name="Target tile size", - items=( - ('po2', "Po2", "A choice between powers of 2 (16, 32, 64...)"), - ('custom', "Custom", "Choose any number as the tile size target")), - default='po2', - description="Method of choosing the target tile size", - update=_update_tile_size - ) - use_optimal: BoolProperty( - name="Optimal Tiles", - default=True, - description="Try to find a similar tile size for best performance, " - "instead of using exact selected one", - update=_update_tile_size - ) - is_enabled: BoolProperty( - name="Auto Tile Size", - default=True, - description="Calculate the best tile size based on factors of the " - "render size and the chosen target", - update=_update_tile_size - ) - use_advanced_ui: BoolProperty( - name="Advanced Settings", - default=False, - description="Show extra options for more control over the calculated tile size" - ) - thread_error_correct: BoolProperty( - name="Fix", - default=True, - description="Reduce the tile size so that all your available threads are used", - update=_update_tile_size - ) - - # Internally used props (not for GUI) - first_run: BoolProperty( - default=True, - options={'HIDDEN'} - ) - threads_error: BoolProperty( - options={'HIDDEN'} - ) - num_tiles: IntVectorProperty( - default=(0, 0), - size=2, - options={'HIDDEN'} - ) - prev_choice: StringProperty( - default='', - options={'HIDDEN'} - ) - prev_engine: StringProperty( - default='', - options={'HIDDEN'} - ) - prev_device: StringProperty( - default='', - options={'HIDDEN'} - ) - prev_res: IntVectorProperty( - default=(0, 0), - size=2, - options={'HIDDEN'} - ) - prev_border: BoolProperty( - default=False, - options={'HIDDEN'} - ) - prev_border_res: FloatVectorProperty( - default=(0, 0, 0, 0), - size=4, - options={'HIDDEN'} - ) - prev_actual_tile_size: IntVectorProperty( - default=(0, 0), - size=2, - options={'HIDDEN'} - ) - prev_threads: IntProperty( - default=0, - options={'HIDDEN'} - ) - - -def ats_poll(context): - scene = context.scene - if scene.render.engine not in SUPPORTED_RENDER_ENGINES or not scene.ats_settings.is_enabled: - return False - return True - - -def engine_is_gpu(engine, device, userpref): - if engine == 'CYCLES' and device == 'GPU': - return userpref.addons['cycles'].preferences.has_active_device() - return False - - -def get_tilesize_prop(engine, device, userpref): - target_type = "_choice" if bpy.context.scene.ats_settings.target_type == 'po2' else "_custom" - if engine_is_gpu(engine, device, userpref): - return ("gpu" + target_type) - elif engine == 'CYCLES': - return ("cpu" + target_type) - return ("bi" + target_type) - - -@persistent -def on_scene_update(scene): - context = bpy.context - - if not ats_poll(context): - return - - userpref = context.preferences - - settings = scene.ats_settings - render = scene.render - engine = render.engine - - # scene.cycles might not always exist (Cycles is an addon)... - device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device - border = render.use_border - threads = get_threads(context, device) - - choice = getattr(settings, get_tilesize_prop(engine, device, userpref)) - - res = get_actual_res(render) - actual_ts = (render.tile_x, render.tile_y) - border_res = (render.border_min_x, render.border_min_y, render.border_max_x, render.border_max_y) - - # detect relevant changes in scene - do_change = (engine != settings.prev_engine or - device != settings.prev_device or - border != settings.prev_border or - threads != settings.prev_threads or - str(choice) != settings.prev_choice or - res != settings.prev_res[:] or - border_res != settings.prev_border_res[:] or - actual_ts != settings.prev_actual_tile_size[:]) - if do_change: - do_set_tile_size(context) - - -def get_actual_res(render): - rend_percent = render.resolution_percentage * 0.01 - # floor is implicitly done by int conversion... - return (int(render.resolution_x * rend_percent), int(render.resolution_y * rend_percent)) - - -def get_threads(context, device): - render = context.scene.render - engine = render.engine - userpref = context.preferences - - if engine_is_gpu(engine, device, userpref): - threads = userpref.addons['cycles'].preferences.get_num_gpu_devices() - else: - threads = render.threads - - return threads - - -def max_tile_size(threads, xres, yres): - ''' Give the largest tile size that will still use all threads ''' - - render_area = xres * yres - tile_area = render_area / threads - tile_length = sqrt(tile_area) - - # lists: num x tiles, num y tiles, squareness, total tiles - perfect_attempts = [] # attempts with correct number of tiles - attempts = [] # all attempts, even if incorrect number of tiles - - axes = [xres, yres] - funcs = [floor, ceil] - - for axis in axes: - sec_axis = yres if axis == xres else xres - for func in funcs: - primary = func(axis / tile_length) - if primary > 0: - secondary = threads / primary - ts_p = axis / primary - ts_s = sec_axis / secondary - squareness = max(ts_p, ts_s) - min(ts_p, ts_s) - attempt = [primary if axis == xres else secondary, primary if - axis != xres else secondary, squareness, primary * secondary] - if attempt not in attempts: - attempts.append(attempt) - # will only be an integer if there are the right number of tiles - if secondary.is_integer(): - perfect_attempts.append(attempt) - - if perfect_attempts: # prefer to use attempt that has exactly the right number of tiles - attempts = perfect_attempts - - attempt = sorted(attempts, key=lambda k: k[2])[0] # pick set with most square tiles - numtiles_x = round(attempt[0]) - numtiles_y = round(attempt[1]) - tile_x = ceil(xres / numtiles_x) - tile_y = ceil(yres / numtiles_y) - - return (tile_x, tile_y) - - -def do_set_tile_size(context): - if not ats_poll(context): - return False - - scene = context.scene - userpref = context.preferences - - settings = scene.ats_settings - render = scene.render - engine = render.engine - device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device - border = render.use_border - - realxres, realyres = xres, yres = res = get_actual_res(scene.render) - - if border: - xres = round(xres * (render.border_max_x - render.border_min_x)) - yres = round(yres * (render.border_max_y - render.border_min_y)) - - choice = getattr(settings, get_tilesize_prop(engine, device, userpref)) - target = int(choice) - - numtiles_x = ceil(xres / target) - numtiles_y = ceil(yres / target) - settings.num_tiles = (numtiles_x, numtiles_y) - if settings.use_optimal: - tile_x = ceil(xres / numtiles_x) - tile_y = ceil(yres / numtiles_y) - else: - tile_x = target - tile_y = target - - # Print tile size (for debug purposes) - # print("Tile size: %dx%d (%dx%d tiles)" % (tile_x, tile_y, ceil(xres / tile_x), ceil(yres / tile_y))) - - # Detect if there are fewer tiles than available threads - threads = get_threads(context, device) - if ((numtiles_x * numtiles_y) < threads): - settings.threads_error = True - if settings.thread_error_correct: - tile_x, tile_y = max_tile_size(threads, xres, yres) - settings.num_tiles = (ceil(xres / tile_x), ceil(yres / tile_y)) - else: - settings.threads_error = False - - # Make sure tile sizes are within the internal limit - tile_x = max(8, tile_x) - tile_y = max(8, tile_y) - tile_x = min(65536, tile_x) - tile_y = min(65536, tile_y) - - render.tile_x = tile_x - render.tile_y = tile_y - - settings.prev_engine = engine - settings.prev_device = device - settings.prev_border = border - settings.prev_threads = threads - settings.prev_choice = str(choice) - settings.prev_res = res - settings.prev_border_res = (render.border_min_x, render.border_min_y, - render.border_max_x, render.border_max_y) - settings.prev_actual_tile_size = (tile_x, tile_y) - settings.first_run = False - - return True - - -class SetTileSize(Operator): - bl_idname = "render.autotilesize_set" - bl_label = "Set" - bl_description = "The first render may not obey the tile-size set here" - - @classmethod - def poll(clss, context): - return ats_poll(context) - - def execute(self, context): - if do_set_tile_size(context): - return {'FINISHED'} - return {'CANCELLED'} - - -# ##### INTERFACE ##### - -def ui_layout(engine, layout, context): - scene = context.scene - userpref = context.preferences - - settings = scene.ats_settings - render = scene.render - engine = render.engine - device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device - - col = layout.column(align=True) - sub = col.column(align=True) - row = sub.row(align=True) - row.prop(settings, "is_enabled", toggle=True) - row.prop(settings, "use_advanced_ui", toggle=True, text="", icon='PREFERENCES') - - sub = col.column(align=False) - sub.enabled = settings.is_enabled - - if settings.use_advanced_ui: - row = sub.row(align=True) - row.label(text="Target tile size:") - row.separator() - row.prop(settings, "target_type", expand=True) - - row = sub.row(align=True) - row.prop(settings, get_tilesize_prop(engine, device, userpref), expand=True) - sub.prop(settings, "use_optimal", text="Calculate Optimal Size") - - sub.label(text="Number of tiles: %s x %s (Total: %s)" % - (settings.num_tiles[0], settings.num_tiles[1], - settings.num_tiles[0] * settings.num_tiles[1]) - ) - - if settings.first_run: - sub = layout.column(align=True) - sub.operator("render.autotilesize_set", text="First-render fix", icon='ERROR') - elif settings.prev_device != device: - sub = layout.column(align=True) - sub.operator("render.autotilesize_set", text="Device changed - fix", icon='ERROR') - - # if not very square tile - if (render.tile_x / render.tile_y > 2) or (render.tile_x / render.tile_y < 0.5): - sub.label(text="Warning: Tile size is not very square", icon='ERROR') - sub.label(text=" Try a slightly different resolution") - - if settings.threads_error: - row = sub.row(align=True) - row.alignment = 'CENTER' - row.label(text="Warning: Fewer tiles than threads", icon='ERROR') - row.prop(settings, 'thread_error_correct') - - -def menu_func_cycles(self, context): - ui_layout('CYCLES', self.layout, context) - - -# ##### REGISTRATION ##### - -classes = ( - AutoTileSizeSettings, - SetTileSize -) - -def register(): - for cls in classes: - bpy.utils.register_class(cls) - - bpy.types.Scene.ats_settings = PointerProperty( - type=AutoTileSizeSettings - ) - - # Note, the Cycles addon must be registered first, otherwise - # this panel doesn't exist - better be safe here! - cycles_panel = getattr(bpy.types, "CYCLES_RENDER_PT_performance", None) - if cycles_panel is not None: - cycles_panel.append(menu_func_cycles) - - bpy.app.handlers.depsgraph_update_post.append(on_scene_update) - - -def unregister(): - bpy.app.handlers.depsgraph_update_post.remove(on_scene_update) - - cycles_panel = getattr(bpy.types, "CYCLES_RENDER_PT_performance", None) - if cycles_panel is not None: - cycles_panel.remove(menu_func_cycles) - - del bpy.types.Scene.ats_settings - - for cls in reversed(classes): - bpy.utils.unregister_class(cls) - - -if __name__ == "__main__": - register() -- cgit v1.2.3 From e1748aecd5ba33e803989b20a94f22e099c8b79b Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 24 Sep 2021 12:42:32 +0200 Subject: BlenderKit: Temp hack following `proxy_make` operator removal. The addon needs to be properly updated to use overrides, but for now allow it to keep working without accessing non-existant API. Ping Vilem Duha (@pildanovak) too. --- blenderkit/overrides.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/blenderkit/overrides.py b/blenderkit/overrides.py index c2934781..28c5e7f7 100644 --- a/blenderkit/overrides.py +++ b/blenderkit/overrides.py @@ -106,6 +106,9 @@ def addColorCorrectors(material): def modelProxy(): + utils.p('No proxies in Blender anymore') + return False + s = bpy.context.scene ao = bpy.context.active_object if utils.is_linked_asset(ao): @@ -128,7 +131,7 @@ def modelProxy(): new_ao.empty_display_type = 'SPHERE' new_ao.empty_display_size *= 0.1 - bpy.ops.object.proxy_make(object=rigs[0].name) + # bpy.ops.object.proxy_make(object=rigs[0].name) proxy = bpy.context.active_object bpy.context.view_layer.objects.active = ao ao.select_set(True) -- cgit v1.2.3 From 8975ba0a553a6cbe6b9e086a474331bddfb55841 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Fri, 24 Sep 2021 16:43:33 +0200 Subject: glTF export: fix animation export for objects parented to bones --- io_scene_gltf2/__init__.py | 2 +- io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index 9a89cfbe..44d0ec92 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -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, 7, 28), + "version": (1, 7, 29), 'blender': (2, 91, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py index 28a19c9e..13c347dc 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py @@ -225,7 +225,7 @@ def __gather_children(blender_object, blender_scene, export_settings): parent_joint = find_parent_joint(root_joints, child.parent_bone) if not parent_joint: continue - child_node = gather_node(child, None, None, None, export_settings) + child_node = gather_node(child, None, blender_scene, None, export_settings) if child_node is None: continue blender_bone = blender_object.pose.bones[parent_joint.name] -- cgit v1.2.3 From ba969e8b536781450d8b43959c95ca07e886b2b6 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Fri, 24 Sep 2021 16:47:51 +0200 Subject: glTF exporter: cleanup object animation curves when animation is constant --- io_scene_gltf2/__init__.py | 2 +- .../exp/gltf2_blender_gather_animation_sampler_keyframes.py | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index 44d0ec92..41f09df9 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -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, 7, 29), + "version": (1, 7, 30), 'blender': (2, 91, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py index df069f79..d70f4de2 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py @@ -317,7 +317,7 @@ def gather_keyframes(blender_object_if_armature: typing.Optional[bpy.types.Objec # We can ignore this keyframes # if there are some fcurve, we can keep only 2 keyframes, first and last if blender_object_if_armature is not None: - cst = all([j < 0.0001 for j in np.ptp([[k.value[i] for i in range(len(keyframes[0].value))] for k in keyframes], axis=0)]) + cst = fcurve_is_constant(keyframes) if node_channel_is_animated is True: # fcurve on this bone for this property # Keep animation, but keep only 2 keyframes if data are not changing @@ -325,10 +325,18 @@ def gather_keyframes(blender_object_if_armature: typing.Optional[bpy.types.Objec else: # bone is not animated (no fcurve) # Not keeping if not changing property return None if cst is True else keyframes + else: + # For objects, if all values are the same, we keep only first and last + cst = fcurve_is_constant(keyframes) + return [keyframes[0], keyframes[-1]] if cst is True and len(keyframes) >= 2 else keyframes + return keyframes +def fcurve_is_constant(keyframes): + return all([j < 0.0001 for j in np.ptp([[k.value[i] for i in range(len(keyframes[0].value))] for k in keyframes], axis=0)]) + def complete_key(key: Keyframe, non_keyed_values: typing.Tuple[typing.Optional[float]]): """ Complete keyframe with non keyed values -- cgit v1.2.3 From b1226da66a49a524ee17053c8f43d356597b18f4 Mon Sep 17 00:00:00 2001 From: stephen-l Date: Sat, 25 Sep 2021 12:03:10 +0200 Subject: Blender 3.0 compatibility --- archipack/__init__.py | 4 ++-- archipack/archipack_autoboolean.py | 6 ------ archipack/archipack_material.py | 2 +- archipack/archipack_preset.py | 4 ++-- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/archipack/__init__.py b/archipack/__init__.py index 0474cbd1..44c56b7c 100644 --- a/archipack/__init__.py +++ b/archipack/__init__.py @@ -31,8 +31,8 @@ bl_info = { 'author': 's-leger', 'license': 'GPL', 'deps': '', - 'version': (1, 2, 84), - 'blender': (2, 90, 0), + 'version': (1, 2, 85), + 'blender': (3, 0, 0), 'location': 'View3D > Sidebar > Create > Archipack', 'warning': '', 'doc_url': 'https://github.com/s-leger/archipack/wiki', diff --git a/archipack/archipack_autoboolean.py b/archipack/archipack_autoboolean.py index f5b6eaf4..3a424728 100644 --- a/archipack/archipack_autoboolean.py +++ b/archipack/archipack_autoboolean.py @@ -108,12 +108,6 @@ class ArchipackBoolManager(ArchipackCollectionManager): hole.hide_render = True hole.hide_select = True hole.select_set(state=True) - hole.cycles_visibility.camera = False - hole.cycles_visibility.diffuse = False - hole.cycles_visibility.glossy = False - hole.cycles_visibility.shadow = False - hole.cycles_visibility.scatter = False - hole.cycles_visibility.transmission = False def get_child_hole(self, o): for hole in o.children: diff --git a/archipack/archipack_material.py b/archipack/archipack_material.py index e363f304..5ac29d99 100644 --- a/archipack/archipack_material.py +++ b/archipack/archipack_material.py @@ -83,7 +83,7 @@ class MatLib(): """ try: # print("MatLib.load_mat(%s) linked:%s" % (name, link)) - with bpy.data.libraries.load(self.path, link, False) as (data_from, data_to): + with bpy.data.libraries.load(self.path, link=link, relative=False) as (data_from, data_to): data_to.materials = [name] except: pass diff --git a/archipack/archipack_preset.py b/archipack/archipack_preset.py index fe4b9307..65ca7245 100644 --- a/archipack/archipack_preset.py +++ b/archipack/archipack_preset.py @@ -34,8 +34,8 @@ from .archipack_gl import ( ThumbHandle, Screen, GlRect, GlPolyline, GlPolygon, GlText, GlHandle ) -preset_paths = bpy.utils.script_paths(subdir="presets") -addons_paths = bpy.utils.script_paths(subdir="addons") +preset_paths = [os.path.join(path, "presets") for path in bpy.utils.script_paths()] +addons_paths = [os.path.join(path, "addons") for path in bpy.utils.script_paths()] class CruxHandle(GlHandle): -- cgit v1.2.3 From 4a278c282fe6d85f0ceea3f3b94592e595b0b189 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Mon, 20 Sep 2021 21:49:56 +0200 Subject: Hide Pose Library panels unless in Pose Mode Otherwise, there will be a useless tab in the sidebar, and panels in the Asset Browser and Dopesheet that do nothing. So far the Asset Browser hides these panels unless the Animation category is selected, but this won't work once asset catalogs replace the categories. Differential Revision: https://developer.blender.org/D12576 --- pose_library/gui.py | 53 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/pose_library/gui.py b/pose_library/gui.py index a2f04a22..2082dff7 100644 --- a/pose_library/gui.py +++ b/pose_library/gui.py @@ -33,21 +33,25 @@ from bpy.types import ( from bpy_extras import asset_utils -class VIEW3D_PT_pose_library(Panel): +class PoseLibraryPanel: + @classmethod + def pose_library_panel_poll(cls, context: Context) -> bool: + return bool( + context.object + and context.object.mode == 'POSE' + ) + + @classmethod + def poll(cls, context: Context) -> bool: + return cls.pose_library_panel_poll(context); + + +class VIEW3D_PT_pose_library(PoseLibraryPanel, Panel): bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_category = "Animation" bl_label = "Pose Library" - @classmethod - def poll(cls, context: Context) -> bool: - exp_prefs = context.preferences.experimental - try: - return exp_prefs.use_asset_browser - except AttributeError: - # The 'use_asset_browser' experimental option was removed from Blender. - return True - def draw(self, context: Context) -> None: layout = self.layout @@ -124,11 +128,18 @@ def pose_library_list_item_context_menu(self: UIList, context: Context) -> None: layout.operator("asset.open_containing_blend_file") -class ASSETBROWSER_PT_pose_library_usage(asset_utils.AssetBrowserSpecificCategoryPanel, Panel): +class ASSETBROWSER_PT_pose_library_usage(PoseLibraryPanel, asset_utils.AssetBrowserSpecificCategoryPanel, Panel): bl_region_type = "TOOLS" bl_label = "Pose Library" asset_categories = {'ANIMATIONS'} + @classmethod + def poll(cls, context: Context) -> bool: + return ( + cls.pose_library_panel_poll(context) + and cls.asset_category_poll(context) + ) + def draw(self, context: Context) -> None: layout = self.layout wm = context.window_manager @@ -149,11 +160,18 @@ class ASSETBROWSER_PT_pose_library_usage(asset_utils.AssetBrowserSpecificCategor props.select = False -class ASSETBROWSER_PT_pose_library_editing(asset_utils.AssetBrowserSpecificCategoryPanel, Panel): +class ASSETBROWSER_PT_pose_library_editing(PoseLibraryPanel, asset_utils.AssetBrowserSpecificCategoryPanel, Panel): bl_region_type = "TOOL_PROPS" bl_label = "Pose Library" asset_categories = {'ANIMATIONS'} + @classmethod + def poll(cls, context: Context) -> bool: + return ( + cls.pose_library_panel_poll(context) + and cls.asset_category_poll(context) + ) + def draw(self, context: Context) -> None: layout = self.layout @@ -169,21 +187,12 @@ class ASSETBROWSER_PT_pose_library_editing(asset_utils.AssetBrowserSpecificCateg col.operator("poselib.paste_asset", icon="PASTEDOWN") -class DOPESHEET_PT_asset_panel(Panel): +class DOPESHEET_PT_asset_panel(PoseLibraryPanel, Panel): bl_space_type = "DOPESHEET_EDITOR" bl_region_type = "UI" bl_label = "Create Pose Asset" bl_category = "Pose Library" - @classmethod - def poll(cls, context: Context) -> bool: - exp_prefs = context.preferences.experimental - try: - return exp_prefs.use_asset_browser - except AttributeError: - # The 'use_asset_browser' experimental option was removed from Blender. - return True - def draw(self, context: Context) -> None: layout = self.layout col = layout.column(align=True) -- cgit v1.2.3 From ea457d4ab516e0cfa0ea28c5b601c02a87805cf1 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 29 Sep 2021 17:16:14 +0200 Subject: Update Pose Library add-on to work without asset categories Pose Library panels are now always displayed in pose mode, and don't hide or unhide anymore depending on the visible asset types. --- pose_library/gui.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pose_library/gui.py b/pose_library/gui.py index 2082dff7..da7b77c7 100644 --- a/pose_library/gui.py +++ b/pose_library/gui.py @@ -128,7 +128,7 @@ def pose_library_list_item_context_menu(self: UIList, context: Context) -> None: layout.operator("asset.open_containing_blend_file") -class ASSETBROWSER_PT_pose_library_usage(PoseLibraryPanel, asset_utils.AssetBrowserSpecificCategoryPanel, Panel): +class ASSETBROWSER_PT_pose_library_usage(PoseLibraryPanel, asset_utils.AssetBrowserPanel, Panel): bl_region_type = "TOOLS" bl_label = "Pose Library" asset_categories = {'ANIMATIONS'} @@ -137,7 +137,7 @@ class ASSETBROWSER_PT_pose_library_usage(PoseLibraryPanel, asset_utils.AssetBrow def poll(cls, context: Context) -> bool: return ( cls.pose_library_panel_poll(context) - and cls.asset_category_poll(context) + and cls.asset_browser_panel_poll(context) ) def draw(self, context: Context) -> None: @@ -160,7 +160,7 @@ class ASSETBROWSER_PT_pose_library_usage(PoseLibraryPanel, asset_utils.AssetBrow props.select = False -class ASSETBROWSER_PT_pose_library_editing(PoseLibraryPanel, asset_utils.AssetBrowserSpecificCategoryPanel, Panel): +class ASSETBROWSER_PT_pose_library_editing(PoseLibraryPanel, asset_utils.AssetBrowserPanel, Panel): bl_region_type = "TOOL_PROPS" bl_label = "Pose Library" asset_categories = {'ANIMATIONS'} @@ -169,7 +169,7 @@ class ASSETBROWSER_PT_pose_library_editing(PoseLibraryPanel, asset_utils.AssetBr def poll(cls, context: Context) -> bool: return ( cls.pose_library_panel_poll(context) - and cls.asset_category_poll(context) + and cls.asset_browser_panel_poll(context) ) def draw(self, context: Context) -> None: -- cgit v1.2.3 From 9a285d80167fc8c9e8b0c7ab2f2fd3c7487fa01d Mon Sep 17 00:00:00 2001 From: Samuli Raivio Date: Wed, 29 Sep 2021 17:58:50 +0200 Subject: FBX export / subdivision: Write proper boundary rule Currently when exporting a subdivision surface (//Geometry / Export Subdivision Surface// enabled) the exporter uses a hard-coded BoundaryRule rule of 2 (CreaseAll, meaning hard corners). The subdivision surface modifier has an option for boundary smoothing mode so this patch propagates that information to the FBX exporter. Example .fbx file with this feature exported from modified Blender 2.93: https://github.com/bqqbarbhg/ufbx/blob/overhaul/data/blender_293x_subsurf_boundary_7400_binary.fbx Reviewed By: mont29 Differential Revision: https://developer.blender.org/D12204 --- io_scene_fbx/__init__.py | 2 +- io_scene_fbx/export_fbx_bin.py | 5 ++++- io_scene_fbx/import_fbx.py | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py index 495e62d2..a9c58915 100644 --- a/io_scene_fbx/__init__.py +++ b/io_scene_fbx/__init__.py @@ -21,7 +21,7 @@ bl_info = { "name": "FBX format", "author": "Campbell Barton, Bastien Montagne, Jens Restemeier", - "version": (4, 24, 0), + "version": (4, 25, 0), "blender": (2, 90, 0), "location": "File > Import-Export", "description": "FBX IO meshes, UV's, vertex colors, materials, textures, cameras, lamps and actions", diff --git a/io_scene_fbx/export_fbx_bin.py b/io_scene_fbx/export_fbx_bin.py index 3950ed5b..09dfaa9f 100644 --- a/io_scene_fbx/export_fbx_bin.py +++ b/io_scene_fbx/export_fbx_bin.py @@ -879,7 +879,10 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes): if last_subsurf: elem_data_single_int32(geom, b"Smoothness", 2) # Display control mesh and smoothed - elem_data_single_int32(geom, b"BoundaryRule", 2) # Round edges like Blender + if last_subsurf.boundary_smooth == "PRESERVE_CORNERS": + elem_data_single_int32(geom, b"BoundaryRule", 2) # CreaseAll + else: + elem_data_single_int32(geom, b"BoundaryRule", 1) # CreaseEdge elem_data_single_int32(geom, b"PreviewDivisionLevels", last_subsurf.levels) elem_data_single_int32(geom, b"RenderDivisionLevels", last_subsurf.render_levels) diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py index ba11757a..a07e919e 100644 --- a/io_scene_fbx/import_fbx.py +++ b/io_scene_fbx/import_fbx.py @@ -2928,6 +2928,11 @@ def load(operator, context, filepath="", mod = parent.bl_obj.modifiers.new('subsurf', 'SUBSURF') mod.levels = preview_levels mod.render_levels = render_levels + boundary_rule = elem_prop_first(elem_find_first(fbx_sdata, b'BoundaryRule'), default=1) + if boundary_rule == 2: + mod.boundary_smooth = "PRESERVE_CORNERS" + else: + mod.boundary_smooth = "ALL" _(); del _ -- cgit v1.2.3 From 13140e3947af5c1becd752e7fb2c627b3ed95d96 Mon Sep 17 00:00:00 2001 From: Vilem Duha Date: Sat, 2 Oct 2021 17:32:37 +0200 Subject: BlenderKit: basic asset_browser compatibility fix default search report blender version instead of addon version during search --- blenderkit/resolutions.py | 25 ++++++++++++++++++++++ blenderkit/search.py | 9 ++++++++ blenderkit/ui_panels.py | 48 ++++++++++++++++++++++++++----------------- blenderkit/version_checker.py | 11 +++++++--- 4 files changed, 71 insertions(+), 22 deletions(-) diff --git a/blenderkit/resolutions.py b/blenderkit/resolutions.py index 1a4af5fc..e2412786 100644 --- a/blenderkit/resolutions.py +++ b/blenderkit/resolutions.py @@ -168,6 +168,31 @@ def unpack_asset(data): # image.unpack(method='REMOVE') image.unpack(method='WRITE_ORIGINAL') + #mark asset browser asset + data_block = None + if asset_data['assetType'] == 'model': + for ob in bpy.context.scene.objects: + if ob.parent == None: + ob.asset_mark() + data_block = ob + elif asset_data['assetType'] == 'material': + for m in bpy.data.materials: + m.asset_mark() + data_block = m + elif asset_data['assetType'] == 'scene': + bpy.context.scene.asset_mark() + elif asset_data['assetType'] =='brush': + for b in bpy.data.brushes: + if b.get('asset_data') is not None: + b.asset_mark() + data_block = b + if data_block is not None: + tags = data_block.asset_data.tags + for t in tags: + tags.remove(t) + tags.new('description: ' + asset_data['description']) + tags.new('tags: ' + ','.join(asset_data['tags'])) + bpy.ops.wm.save_mainfile(compress=False) # now try to delete the .blend1 file try: diff --git a/blenderkit/search.py b/blenderkit/search.py index c386f588..e846e8bc 100644 --- a/blenderkit/search.py +++ b/blenderkit/search.py @@ -1313,6 +1313,15 @@ def get_search_simple(parameters, filepath=None, page_size=100, max_results=1000 bk_logger.info(f'retrieved {len(results)} assets from elastic search') return results +def get_single_asset(asset_base_id): + preferences = bpy.context.preferences.addons['blenderkit'].preferences + params = { + 'asset_base_id': asset_base_id + } + results = get_search_simple(params, api_key=preferences.api_key) + if len(results)>0: + return results[0] + return None def search(category='', get_next=False, author_id=''): ''' initialize searching''' diff --git a/blenderkit/ui_panels.py b/blenderkit/ui_panels.py index 25fa5927..f65833ed 100644 --- a/blenderkit/ui_panels.py +++ b/blenderkit/ui_panels.py @@ -1175,23 +1175,32 @@ class BlenderKitWelcomeOperator(bpy.types.Operator): # bpy.context.window_manager.windows[0].screen.areas[5].spaces[0].show_region_ui = False print('running search no') ui_props = bpy.context.scene.blenderkitUI - random_searches = [ - ('MATERIAL', 'ice'), - ('MODEL', 'car'), - ('MODEL', 'vase'), - ('MODEL', 'grass'), - ('MODEL', 'plant'), - ('MODEL', 'man'), - ('MATERIAL', 'metal'), - ('MATERIAL', 'wood'), - ('MATERIAL', 'floor'), - ('MATERIAL', 'bricks'), - ] - random_search = random.choice(random_searches) - ui_props.asset_type = random_search[0] - - bpy.context.window_manager.blenderkit_mat.search_keywords = '' # random_search[1] - bpy.context.window_manager.blenderkit_mat.search_keywords = '+is_free:true+score_gte:1000+order:-created' # random_search[1] + # random_searches = [ + # ('MATERIAL', 'ice'), + # ('MODEL', 'car'), + # ('MODEL', 'vase'), + # ('MODEL', 'grass'), + # ('MODEL', 'plant'), + # ('MODEL', 'man'), + # ('MATERIAL', 'metal'), + # ('MATERIAL', 'wood'), + # ('MATERIAL', 'floor'), + # ('MATERIAL', 'bricks'), + # ] + # random_search = random.choice(random_searches) + # ui_props.asset_type = random_search[0] + ui_props.asset_type = 'MODEL' + + score_limit = 450 + if ui_props.asset_type == 'MATERIAL': + props = bpy.context.window_manager.blenderkit_mat + + elif ui_props.asset_type == 'MODEL': + props = bpy.context.window_manager.blenderkit_models + score_limit = 1000 + + props.search_keywords = ''#random_search[1] + props.search_keywords += f'+is_free:true+score_gte:{score_limit}+order:-created' # random_search[1] # search.search() return {'FINISHED'} @@ -1655,8 +1664,9 @@ class AssetPopupCard(bpy.types.Operator, ratings_utils.RatingsProperties): # self.draw_asset_parameter(box, key='purePbr', pretext='Pure PBR') # self.draw_asset_parameter(box, key='productionLevel', pretext='Readiness') # self.draw_asset_parameter(box, key='condition', pretext='Condition') - self.draw_asset_parameter(box, key='material_style', pretext='Style') - self.draw_asset_parameter(box, key='model_style', pretext='Style') + if utils.profile_is_validator(): + self.draw_asset_parameter(box, key='materialStyle', pretext='Style') + self.draw_asset_parameter(box, key='modelStyle', pretext='Style') if utils.get_param(self.asset_data, 'dimensionX'): t = '%s×%s×%s m' % (utils.fmt_length(mparams['dimensionX']), diff --git a/blenderkit/version_checker.py b/blenderkit/version_checker.py index 993ff238..37aeadc4 100644 --- a/blenderkit/version_checker.py +++ b/blenderkit/version_checker.py @@ -16,18 +16,23 @@ # # ##### END GPL LICENSE BLOCK ##### - +import bpy from blenderkit import paths import requests, os, json, threading def get_addon_version(): - import blenderkit - ver = blenderkit.bl_info['version'] + # should return addon version, but since Blender 3.0 this is synced with Blender version + ver = bpy.app.version return '%i.%i.%i' % (ver[0], ver[1], ver[2]) + # import blenderkit + # ver = blenderkit.bl_info['version'] + # return '%i.%i.%i' % (ver[0], ver[1], ver[2]) + + def check_version(url, api_key, module): headers = { "accept": "application/json", -- cgit v1.2.3