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:
authorPeter Kim <pk15950@gmail.com>2022-06-17 11:28:06 +0300
committerPeter Kim <pk15950@gmail.com>2022-06-17 11:28:06 +0300
commitec84e3294593e2e26475f18c81e847bf00dc201e (patch)
treea9c52b070d2ec514e4d5fe434a91709a4b79dfbd
parent633e707c40ad94d75a5f0c23ad5f5df0514fc92d (diff)
parentaa353e127c2be0a31e10f8b3621fc418bcf6d6ef (diff)
Merge branch 'master' into xr-dev
-rw-r--r--add_camera_rigs/operators.py5
-rw-r--r--animation_animall.py119
-rw-r--r--development_edit_operator.py20
-rw-r--r--io_scene_fbx/__init__.py2
-rw-r--r--io_scene_fbx/fbx_utils.py11
-rw-r--r--io_scene_fbx/import_fbx.py12
-rwxr-xr-xio_scene_gltf2/__init__.py2
-rw-r--r--io_scene_gltf2/blender/exp/gltf2_blender_gather_drivers.py7
-rw-r--r--node_wrangler.py28
-rw-r--r--object_color_rules.py2
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):