diff options
author | Peter Kim <pk15950@gmail.com> | 2022-06-17 11:28:06 +0300 |
---|---|---|
committer | Peter Kim <pk15950@gmail.com> | 2022-06-17 11:28:06 +0300 |
commit | ec84e3294593e2e26475f18c81e847bf00dc201e (patch) | |
tree | a9c52b070d2ec514e4d5fe434a91709a4b79dfbd | |
parent | 633e707c40ad94d75a5f0c23ad5f5df0514fc92d (diff) | |
parent | aa353e127c2be0a31e10f8b3621fc418bcf6d6ef (diff) |
Merge branch 'master' into xr-dev
-rw-r--r-- | add_camera_rigs/operators.py | 5 | ||||
-rw-r--r-- | animation_animall.py | 119 | ||||
-rw-r--r-- | development_edit_operator.py | 20 | ||||
-rw-r--r-- | io_scene_fbx/__init__.py | 2 | ||||
-rw-r--r-- | io_scene_fbx/fbx_utils.py | 11 | ||||
-rw-r--r-- | io_scene_fbx/import_fbx.py | 12 | ||||
-rwxr-xr-x | io_scene_gltf2/__init__.py | 2 | ||||
-rw-r--r-- | io_scene_gltf2/blender/exp/gltf2_blender_gather_drivers.py | 7 | ||||
-rw-r--r-- | node_wrangler.py | 28 | ||||
-rw-r--r-- | object_color_rules.py | 2 |
10 files changed, 157 insertions, 51 deletions
diff --git a/add_camera_rigs/operators.py b/add_camera_rigs/operators.py index 646566ae..18300e08 100644 --- a/add_camera_rigs/operators.py +++ b/add_camera_rigs/operators.py @@ -5,7 +5,10 @@ from bpy.types import Operator def get_rig_and_cam(obj): - if obj.type == 'ARMATURE': + if (obj.type == 'ARMATURE' + and "rig_id" in obj + and obj["rig_id"].lower() in {"dolly_rig", + "crane_rig", "2d_rig"}): cam = None for child in obj.children: if child.type == 'CAMERA': diff --git a/animation_animall.py b/animation_animall.py index 309141a9..a7d76f53 100644 --- a/animation_animall.py +++ b/animation_animall.py @@ -3,8 +3,8 @@ bl_info = { "name": "AnimAll", "author": "Daniel Salazar <zanqdo@gmail.com>", - "version": (0, 8, 3), - "blender": (2, 80, 0), + "version": (0, 9, 1), + "blender": (3, 3, 0), "location": "3D View > Toolbox > Animation tab > AnimAll", "description": "Allows animation of mesh, lattice, curve and surface data", "warning": "", @@ -62,16 +62,16 @@ class AnimallProperties(bpy.types.PropertyGroup): description="Insert keyframes on edge creases", default=False ) - key_vcols: BoolProperty( - name="V-Cols", - description="Insert keyframes on active Vertex Color values", - default=False - ) key_vgroups: BoolProperty( name="V-groups", description="Insert keyframes on active Vertex group values", default=False ) + key_attribute: BoolProperty( + name="Active Attribute", + description="Insert keyframes on active attribute values", + default=False + ) key_points: BoolProperty( name="Points", description="Insert keyframes on point locations", @@ -122,6 +122,12 @@ def delete_key(data, key): pass +def is_selected_vert_loop(data, loop_i): + """Get selection status of vertex corresponding to a loop""" + vertex_index = data.loops[loop_i].vertex_index + return data.vertices[vertex_index].select + + # GUI (Panel) class VIEW3D_PT_animall(Panel): @@ -161,9 +167,23 @@ class VIEW3D_PT_animall(Panel): row.prop(animall_properties, "key_crease") row.prop(animall_properties, "key_uvs") row = col.row() - row.prop(animall_properties, "key_vcols") + row.prop(animall_properties, "key_attribute") row.prop(animall_properties, "key_vgroups") + # Vertex group update operator + if (context.active_object is not None + and context.active_object.type == 'MESH' + and context.active_object.data.animation_data is not None + and context.active_object.data.animation_data.action is not None): + for fcurve in context.active_object.data.animation_data.action.fcurves: + if fcurve.data_path.startswith("vertex_colors"): + layout.separator() + row = layout.row() + row.label(text="Object includes old-style vertex colors. Consider updating them.", icon="ERROR") + row = layout.row() + row.operator("anim.update_vertex_color_animation_animall", icon="FILE_REFRESH") + break + elif obj.type == 'CURVE': row.prop(animall_properties, "key_points") row.prop(animall_properties, "key_shape") @@ -325,11 +345,35 @@ class ANIM_OT_insert_keyframe_animall(Operator): if not animall_properties.key_selected or uv.select: insert_key(uv, 'uv', group="UV layer %s" % uv_i) - if animall_properties.key_vcols: - for v_col_layer in data.vertex_colors: - if v_col_layer.active: # only insert in active VCol layer - for v_i, data in enumerate(v_col_layer.data): - insert_key(data, 'color', group="Loop %s" % v_i) + if animall_properties.key_attribute: + if data.attributes.active is not None: + attribute = data.attributes.active + if attribute.data_type != 'STRING': + # Cannot animate string attributes? + if attribute.data_type in {'FLOAT', 'INT', 'BOOLEAN', 'INT8'}: + attribute_key = "value" + elif attribute.data_type in {'FLOAT_COLOR', 'BYTE_COLOR'}: + attribute_key = "color" + elif attribute.data_type in {'FLOAT_VECTOR', 'FLOAT2'}: + attribute_key = "vector" + + if attribute.domain == 'POINT': + group = "Vertex %s" + elif attribute.domain == 'EDGE': + group = "Edge %s" + elif attribute.domain == 'FACE': + group = "Face %s" + elif attribute.domain == 'CORNER': + group = "Loop %s" + + for e_i, _attribute_data in enumerate(attribute.data): + if (not animall_properties.key_selected + or attribute.domain == 'POINT' and data.vertices[e_i].select + or attribute.domain == 'EDGE' and data.edges[e_i].select + or attribute.domain == 'FACE' and data.polygons[e_i].select + or attribute.domain == 'CORNER' and is_selected_vert_loop(data, e_i)): + insert_key(data, f'attributes["{attribute.name}"].data[{e_i}].{attribute_key}', + group=group % e_i) elif obj.type in {'CURVE', 'SURFACE'}: # Shape key keys have to be inserted in object mode for curves... @@ -426,11 +470,25 @@ class ANIM_OT_delete_keyframe_animall(Operator): if not animall_properties.key_selected or uv.select: delete_key(uv, 'uv') - if animall_properties.key_vcols: - for v_col_layer in data.vertex_colors: - if v_col_layer.active: # only delete in active VCol layer - for data in v_col_layer.data: - delete_key(data, 'color') + if animall_properties.key_attribute: + if data.attributes.active is not None: + attribute = data.attributes.active + if attribute.data_type != 'STRING': + # Cannot animate string attributes? + if attribute.data_type in {'FLOAT', 'INT', 'BOOLEAN', 'INT8'}: + attribute_key = "value" + elif attribute.data_type in {'FLOAT_COLOR', 'BYTE_COLOR'}: + attribute_key = "color" + elif attribute.data_type in {'FLOAT_VECTOR', 'FLOAT2'}: + attribute_key = "vector" + + for e_i, _attribute_data in enumerate(attribute.data): + if (not animall_properties.key_selected + or attribute.domain == 'POINT' and data.vertices[e_i].select + or attribute.domain == 'EDGE' and data.edges[e_i].select + or attribute.domain == 'FACE' and data.polygons[e_i].select + or attribute.domain == 'CORNER' and is_selected_vert_loop(data, e_i)): + delete_key(data, f'attributes["{attribute.name}"].data[{e_i}].{attribute_key}') elif obj.type == 'LATTICE': if animall_properties.key_shape: @@ -517,6 +575,29 @@ class ANIM_OT_clear_animation_animall(Operator): return {'FINISHED'} +class ANIM_OT_update_vertex_color_animation_animall(Operator): + bl_label = "Update Vertex Color Animation" + bl_idname = "anim.update_vertex_color_animation_animall" + bl_description = "Update old vertex color channel formats from pre-3.3 versions" + bl_options = {'REGISTER', 'UNDO'} + + @classmethod + def poll(self, context): + if (context.active_object is None + or context.active_object.type != 'MESH' + or context.active_object.data.animation_data is None + or context.active_object.data.animation_data.action is None): + return False + for fcurve in context.active_object.data.animation_data.action.fcurves: + if fcurve.data_path.startswith("vertex_colors"): + return True + + def execute(self, context): + for fcurve in context.active_object.data.animation_data.action.fcurves: + if fcurve.data_path.startswith("vertex_colors"): + fcurve.data_path = fcurve.data_path.replace("vertex_colors", "attributes") + return {'FINISHED'} + # Add-ons Preferences Update Panel # Define Panel classes for updating @@ -569,6 +650,7 @@ def register(): bpy.utils.register_class(ANIM_OT_insert_keyframe_animall) bpy.utils.register_class(ANIM_OT_delete_keyframe_animall) bpy.utils.register_class(ANIM_OT_clear_animation_animall) + bpy.utils.register_class(ANIM_OT_update_vertex_color_animation_animall) bpy.utils.register_class(AnimallAddonPreferences) update_panel(None, bpy.context) @@ -580,6 +662,7 @@ def unregister(): bpy.utils.unregister_class(ANIM_OT_insert_keyframe_animall) bpy.utils.unregister_class(ANIM_OT_delete_keyframe_animall) bpy.utils.unregister_class(ANIM_OT_clear_animation_animall) + bpy.utils.unregister_class(ANIM_OT_update_vertex_color_animation_animall) bpy.utils.unregister_class(AnimallAddonPreferences) if __name__ == "__main__": diff --git a/development_edit_operator.py b/development_edit_operator.py index e51df36e..bd406e49 100644 --- a/development_edit_operator.py +++ b/development_edit_operator.py @@ -4,8 +4,8 @@ bl_info = { "name": "Edit Operator Source", "author": "scorpion81", - "version": (1, 2, 2), - "blender": (2, 80, 0), + "version": (1, 2, 3), + "blender": (3, 2, 0), "location": "Text Editor > Sidebar > Edit Operator", "description": "Opens source file of chosen operator or call locations, if source not available", "warning": "", @@ -30,18 +30,6 @@ from bpy.props import ( IntProperty ) -def stdlib_excludes(): - #need a handy list of modules to avoid walking into - import distutils.sysconfig as sysconfig - excludes = [] - std_lib = sysconfig.get_python_lib(standard_lib=True) - for top, dirs, files in os.walk(std_lib): - for nm in files: - if nm != '__init__.py' and nm[-3:] == '.py': - excludes.append(os.path.join(top, nm)[len(std_lib)+1:-3].replace('\\','.')) - - return excludes - def make_loc(prefix, c): #too long and not helpful... omitting for now space = "" @@ -219,8 +207,10 @@ class TEXT_OT_EditOperator(Operator): def show_calls(self, context): import bl_ui import addon_utils + import sys - exclude = stdlib_excludes() + exclude = [] + exclude.extend(sys.stdlib_module_names) exclude.append("bpy") exclude.append("sys") diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py index 02d135b1..1b7e646d 100644 --- a/io_scene_fbx/__init__.py +++ b/io_scene_fbx/__init__.py @@ -3,7 +3,7 @@ bl_info = { "name": "FBX format", "author": "Campbell Barton, Bastien Montagne, Jens Restemeier", - "version": (4, 36, 0), + "version": (4, 36, 2), "blender": (3, 2, 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/fbx_utils.py b/io_scene_fbx/fbx_utils.py index 35fdede7..41c63ef8 100644 --- a/io_scene_fbx/fbx_utils.py +++ b/io_scene_fbx/fbx_utils.py @@ -112,21 +112,28 @@ RIGHT_HAND_AXES = { } +# NOTE: Not fully in enum value order, since when exporting the first entry matching the framerate value is used +# (e.g. better have NTSC fullframe than NTSC drop frame for 29.97 framerate). FBX_FRAMERATES = ( + #(-1.0, 0), # Default framerate. (-1.0, 14), # Custom framerate. (120.0, 1), (100.0, 2), (60.0, 3), (50.0, 4), (48.0, 5), - (30.0, 6), # BW NTSC. - (30.0 / 1.001, 9), # Color NTSC. + (30.0, 6), # BW NTSC, full frame. + (30.0, 7), # Drop frame. + (30.0 / 1.001, 9), # Color NTSC, full frame. + (30.0 / 1.001, 8), # Color NTSC, drop frame. (25.0, 10), (24.0, 11), + #(1.0, 12), # 1000 milli/s (use for date time?). (24.0 / 1.001, 13), (96.0, 15), (72.0, 16), (60.0 / 1.001, 17), + (120.0 / 1.001, 18), ) diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py index 5fabec24..90f0c016 100644 --- a/io_scene_fbx/import_fbx.py +++ b/io_scene_fbx/import_fbx.py @@ -778,16 +778,22 @@ def blen_read_geom_layerinfo(fbx_layer): def blen_read_geom_array_setattr(generator, blen_data, blen_attr, fbx_data, stride, item_size, descr, xform): """Generic fbx_layer to blen_data setter, generator is expected to yield tuples (ble_idx, fbx_idx).""" - max_idx = len(blen_data) - 1 + max_blen_idx = len(blen_data) - 1 + max_fbx_idx = len(fbx_data) - 1 print_error = True def check_skip(blen_idx, fbx_idx): nonlocal print_error if fbx_idx < 0: # Negative values mean 'skip'. return True - if blen_idx > max_idx: + if blen_idx > max_blen_idx: if print_error: - print("ERROR: too much data in this layer, compared to elements in mesh, skipping!") + print("ERROR: too much data in this Blender layer, compared to elements in mesh, skipping!") + print_error = False + return True + if fbx_idx + item_size - 1 > max_fbx_idx: + if print_error: + print("ERROR: not enough data in this FBX layer, skipping!") print_error = False return True return False diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index fd3d2d56..ce48f293 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -4,7 +4,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": (3, 3, 4), + "version": (3, 3, 5), 'blender': (3, 3, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_drivers.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_drivers.py index 4e77f60e..b0e538c8 100644 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_drivers.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_drivers.py @@ -12,7 +12,12 @@ def get_sk_drivers(blender_armature_uuid, export_settings): drivers = [] - for child_uuid in export_settings['vtree'].nodes[blender_armature_uuid].children: + # Take into account skinned mesh, and mesh parented to a bone of the armature + children_list = export_settings['vtree'].nodes[blender_armature_uuid].children + for bone in export_settings['vtree'].get_all_bones(blender_armature_uuid): + children_list.extend(export_settings['vtree'].nodes[bone].children) + + for child_uuid in children_list: if export_settings['vtree'].nodes[child_uuid].blender_type == "BONE": continue diff --git a/node_wrangler.py b/node_wrangler.py index f2280f2c..1a815dc6 100644 --- a/node_wrangler.py +++ b/node_wrangler.py @@ -1165,7 +1165,8 @@ class NWNodeWrangler(bpy.types.AddonPreferences): hotkey_list_filter: StringProperty( name=" Filter by Name", default="", - description="Show only hotkeys that have this text in their name" + description="Show only hotkeys that have this text in their name", + options={'TEXTEDIT_UPDATE'} ) show_principled_lists: BoolProperty( name="Show Principled naming tags", @@ -3747,7 +3748,7 @@ class NWLinkToOutputNode(Operator): @classmethod def poll(cls, context): valid = False - if nw_check(context) and context.space_data.tree_type != 'GeometryNodeTree': + if nw_check(context): if context.active_node is not None: for out in context.active_node.outputs: if is_visible_socket(out): @@ -3761,11 +3762,14 @@ class NWLinkToOutputNode(Operator): output_node = None output_index = None tree_type = context.space_data.tree_type - output_types_shaders = [x[1] for x in shaders_output_nodes_props] - output_types_compo = ['COMPOSITE'] - output_types_blender_mat = ['OUTPUT'] - output_types_textures = ['OUTPUT'] - output_types = output_types_shaders + output_types_compo + output_types_blender_mat + if tree_type == 'ShaderNodeTree': + output_types = [x[1] for x in shaders_output_nodes_props] + ['OUTPUT'] + elif tree_type == 'CompositorNodeTree': + output_types = ['COMPOSITE'] + elif tree_type == 'TextureNodeTree': + output_types = ['OUTPUT'] + elif tree_type == 'GeometryNodeTree': + output_types = ['GROUP_OUTPUT'] for node in nodes: if node.type in output_types: output_node = node @@ -3773,11 +3777,16 @@ class NWLinkToOutputNode(Operator): if not output_node: bpy.ops.node.select_all(action="DESELECT") if tree_type == 'ShaderNodeTree': - output_node = nodes.new('ShaderNodeOutputMaterial') + if context.space_data.shader_type == 'OBJECT': + output_node = nodes.new('ShaderNodeOutputMaterial') + elif context.space_data.shader_type == 'WORLD': + output_node = nodes.new('ShaderNodeOutputWorld') elif tree_type == 'CompositorNodeTree': output_node = nodes.new('CompositorNodeComposite') elif tree_type == 'TextureNodeTree': output_node = nodes.new('TextureNodeOutput') + elif tree_type == 'GeometryNodeTree': + output_node = nodes.new('NodeGroupOutput') output_node.location.x = active.location.x + active.dimensions.x + 80 output_node.location.y = active.location.y if (output_node and active.outputs): @@ -3796,6 +3805,9 @@ class NWLinkToOutputNode(Operator): out_input_index = 1 elif active.outputs[output_index].type != 'SHADER': # connect to displacement if not a shader out_input_index = 2 + elif tree_type == 'GeometryNodeTree': + if active.outputs[output_index].type != 'GEOMETRY': + return {'CANCELLED'} links.new(active.outputs[output_index], output_node.inputs[out_input_index]) force_update(context) # viewport render does not update diff --git a/object_color_rules.py b/object_color_rules.py index 52011366..f404c06e 100644 --- a/object_color_rules.py +++ b/object_color_rules.py @@ -172,7 +172,7 @@ def object_colors_select(rule, objects): test_cb = getattr(rule_test, rule_type) for obj in objects: - obj.select = test_cb(obj, rule, cache) + obj.select_set(test_cb(obj, rule, cache)) def object_colors_rule_validate(rule, report): |