Merge branch 'master' into xr-dev
This commit is contained in:
commit
ec84e32945
|
@ -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':
|
||||
|
|
|
@ -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__":
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue