FBX IO: Export normals matching the mesh's normals_domain #104976
@ -5,8 +5,8 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "AnimAll",
|
"name": "AnimAll",
|
||||||
"author": "Daniel Salazar (ZanQdo), Damien Picard (pioverfour)",
|
"author": "Daniel Salazar (ZanQdo), Damien Picard (pioverfour)",
|
||||||
"version": (0, 9, 6),
|
"version": (0, 10, 0),
|
||||||
"blender": (3, 3, 0),
|
"blender": (4, 0, 0),
|
||||||
"location": "3D View > Toolbox > Animation tab > AnimAll",
|
"location": "3D View > Toolbox > Animation tab > AnimAll",
|
||||||
"description": "Allows animation of mesh, lattice, curve and surface data",
|
"description": "Allows animation of mesh, lattice, curve and surface data",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
@ -22,6 +22,7 @@ from bpy.app.translations import (pgettext_iface as iface_,
|
|||||||
pgettext_data as data_)
|
pgettext_data as data_)
|
||||||
from . import translations
|
from . import translations
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
# Property Definitions
|
# Property Definitions
|
||||||
class AnimallProperties(bpy.types.PropertyGroup):
|
class AnimallProperties(bpy.types.PropertyGroup):
|
||||||
@ -49,10 +50,12 @@ class AnimallProperties(bpy.types.PropertyGroup):
|
|||||||
name="Vertex Bevel",
|
name="Vertex Bevel",
|
||||||
description="Insert keyframes on vertex bevel weight",
|
description="Insert keyframes on vertex bevel weight",
|
||||||
default=False)
|
default=False)
|
||||||
# key_vertex_crease: BoolProperty(
|
|
||||||
# name="Vertex Crease",
|
key_vertex_crease: BoolProperty(
|
||||||
# description="Insert keyframes on vertex crease weight",
|
name="Vertex Crease",
|
||||||
# default=False)
|
description="Insert keyframes on vertex crease weight",
|
||||||
|
default=False)
|
||||||
|
|
||||||
key_vertex_group: BoolProperty(
|
key_vertex_group: BoolProperty(
|
||||||
name="Vertex Group",
|
name="Vertex Group",
|
||||||
description="Insert keyframes on active vertex group values",
|
description="Insert keyframes on active vertex group values",
|
||||||
@ -67,8 +70,8 @@ class AnimallProperties(bpy.types.PropertyGroup):
|
|||||||
description="Insert keyframes on edge creases",
|
description="Insert keyframes on edge creases",
|
||||||
default=False)
|
default=False)
|
||||||
|
|
||||||
key_attribute: BoolProperty(
|
key_active_attribute: BoolProperty(
|
||||||
name="Attribute",
|
name="Active Attribute",
|
||||||
description="Insert keyframes on active attribute values",
|
description="Insert keyframes on active attribute values",
|
||||||
default=False)
|
default=False)
|
||||||
key_uvs: BoolProperty(
|
key_uvs: BoolProperty(
|
||||||
@ -115,6 +118,55 @@ def delete_key(data, key):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_attribute(data, name, type=None, domain=None):
|
||||||
|
if name in data.attributes:
|
||||||
|
return data.attributes[name]
|
||||||
|
if type is not None and domain is not None:
|
||||||
|
return data.attributes.new(name, type, domain)
|
||||||
|
|
||||||
|
|
||||||
|
def get_attribute_paths(data, attribute, key_selected):
|
||||||
|
# Cannot animate string attributes?
|
||||||
|
if attribute.data_type == 'STRING':
|
||||||
|
yield ("", "")
|
||||||
|
|
||||||
|
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 = data_("Vertex %s")
|
||||||
|
elif attribute.domain == 'EDGE':
|
||||||
|
group = data_("Edge %s")
|
||||||
|
elif attribute.domain == 'FACE':
|
||||||
|
group = data_("Face %s")
|
||||||
|
elif attribute.domain == 'CORNER':
|
||||||
|
group = data_("Loop %s")
|
||||||
|
|
||||||
|
for e_i, _attribute_data in enumerate(attribute.data):
|
||||||
|
if (not 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)):
|
||||||
|
yield (f'attributes["{attribute.name}"].data[{e_i}].{attribute_key}', group % e_i)
|
||||||
|
|
||||||
|
|
||||||
|
def insert_attribute_key(data, attribute, key_selected):
|
||||||
|
for path, group in get_attribute_paths(data, attribute, key_selected):
|
||||||
|
if path:
|
||||||
|
insert_key(data, path, group=group)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_attribute_key(data, attribute, key_selected):
|
||||||
|
for path, group in get_attribute_paths(data, attribute, key_selected):
|
||||||
|
if path:
|
||||||
|
delete_key(data, path)
|
||||||
|
|
||||||
|
|
||||||
def is_selected_vert_loop(data, loop_i):
|
def is_selected_vert_loop(data, loop_i):
|
||||||
"""Get selection status of vertex corresponding to a loop"""
|
"""Get selection status of vertex corresponding to a loop"""
|
||||||
vertex_index = data.loops[loop_i].vertex_index
|
vertex_index = data.loops[loop_i].vertex_index
|
||||||
@ -126,7 +178,7 @@ def is_selected_vert_loop(data, loop_i):
|
|||||||
class VIEW3D_PT_animall(Panel):
|
class VIEW3D_PT_animall(Panel):
|
||||||
bl_space_type = 'VIEW_3D'
|
bl_space_type = 'VIEW_3D'
|
||||||
bl_region_type = 'UI'
|
bl_region_type = 'UI'
|
||||||
bl_category = "Animate"
|
bl_category = "Animation"
|
||||||
bl_label = ''
|
bl_label = ''
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -137,7 +189,7 @@ class VIEW3D_PT_animall(Panel):
|
|||||||
|
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.label (text = 'AnimAll', icon = 'ARMATURE_DATA')
|
row.label(text='AnimAll', icon='ARMATURE_DATA')
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
obj = context.active_object
|
obj = context.active_object
|
||||||
@ -161,6 +213,7 @@ class VIEW3D_PT_animall(Panel):
|
|||||||
col = layout.column(heading="Points", align=True)
|
col = layout.column(heading="Points", align=True)
|
||||||
col.prop(animall_properties, "key_point_location")
|
col.prop(animall_properties, "key_point_location")
|
||||||
col.prop(animall_properties, "key_vertex_bevel", text="Bevel")
|
col.prop(animall_properties, "key_vertex_bevel", text="Bevel")
|
||||||
|
col.prop(animall_properties, "key_vertex_crease", text="Crease")
|
||||||
col.prop(animall_properties, "key_vertex_group")
|
col.prop(animall_properties, "key_vertex_group")
|
||||||
|
|
||||||
col = layout.column(heading="Edges", align=True)
|
col = layout.column(heading="Edges", align=True)
|
||||||
@ -171,7 +224,7 @@ class VIEW3D_PT_animall(Panel):
|
|||||||
col.prop(animall_properties, "key_material_index")
|
col.prop(animall_properties, "key_material_index")
|
||||||
|
|
||||||
col = layout.column(heading="Others", align=True)
|
col = layout.column(heading="Others", align=True)
|
||||||
col.prop(animall_properties, "key_attribute")
|
col.prop(animall_properties, "key_active_attribute")
|
||||||
col.prop(animall_properties, "key_uvs")
|
col.prop(animall_properties, "key_uvs")
|
||||||
col.prop(animall_properties, "key_shape_key")
|
col.prop(animall_properties, "key_shape_key")
|
||||||
|
|
||||||
@ -179,10 +232,10 @@ class VIEW3D_PT_animall(Panel):
|
|||||||
if (obj.data.animation_data is not None
|
if (obj.data.animation_data is not None
|
||||||
and obj.data.animation_data.action is not None):
|
and obj.data.animation_data.action is not None):
|
||||||
for fcurve in context.active_object.data.animation_data.action.fcurves:
|
for fcurve in context.active_object.data.animation_data.action.fcurves:
|
||||||
if fcurve.data_path.startswith("vertex_colors"):
|
if bpy.ops.anim.update_attribute_animation_animall.poll():
|
||||||
col = layout.column(align=True)
|
col = layout.column(align=True)
|
||||||
col.label(text="Object includes old-style vertex colors. Consider updating them.", icon="ERROR")
|
col.label(text="Object includes old-style attributes. Consider updating them.", icon="ERROR")
|
||||||
col.operator("anim.update_vertex_color_animation_animall", icon="FILE_REFRESH")
|
col.operator("anim.update_attribute_animation_animall", icon="FILE_REFRESH")
|
||||||
break
|
break
|
||||||
|
|
||||||
elif obj.type in {'CURVE', 'SURFACE'}:
|
elif obj.type in {'CURVE', 'SURFACE'}:
|
||||||
@ -315,13 +368,12 @@ class ANIM_OT_insert_keyframe_animall(Operator):
|
|||||||
insert_key(vert, 'co', group=data_("Vertex %s") % v_i)
|
insert_key(vert, 'co', group=data_("Vertex %s") % v_i)
|
||||||
|
|
||||||
if animall_properties.key_vertex_bevel:
|
if animall_properties.key_vertex_bevel:
|
||||||
for v_i, vert in enumerate(data.vertices):
|
attribute = get_attribute(data, "bevel_weight_vert", 'FLOAT', 'POINT')
|
||||||
if not animall_properties.key_selected or vert.select:
|
insert_attribute_key(data, attribute, animall_properties.key_selected)
|
||||||
insert_key(vert, 'bevel_weight', group=data_("Vertex %s") % v_i)
|
|
||||||
# if animall_properties.key_vertex_crease:
|
if animall_properties.key_vertex_crease:
|
||||||
# for v_i, vert in enumerate(data.vertices):
|
attribute = get_attribute(data, "crease_vert", 'FLOAT', 'POINT')
|
||||||
# if not animall_properties.key_selected or vert.select:
|
insert_attribute_key(data, attribute, animall_properties.key_selected)
|
||||||
# insert_key(vert, 'crease', group=data_("Vertex %s") % v_i)
|
|
||||||
|
|
||||||
if animall_properties.key_vertex_group:
|
if animall_properties.key_vertex_group:
|
||||||
for v_i, vert in enumerate(data.vertices):
|
for v_i, vert in enumerate(data.vertices):
|
||||||
@ -330,55 +382,31 @@ class ANIM_OT_insert_keyframe_animall(Operator):
|
|||||||
insert_key(group, 'weight', group=data_("Vertex %s") % v_i)
|
insert_key(group, 'weight', group=data_("Vertex %s") % v_i)
|
||||||
|
|
||||||
if animall_properties.key_edge_bevel:
|
if animall_properties.key_edge_bevel:
|
||||||
for e_i, edge in enumerate(data.edges):
|
attribute = get_attribute(data, "bevel_weight_edge", 'FLOAT', 'EDGE')
|
||||||
if not animall_properties.key_selected or edge.select:
|
insert_attribute_key(data, attribute, animall_properties.key_selected)
|
||||||
insert_key(edge, 'bevel_weight', group=data_("Edge %s") % e_i)
|
|
||||||
|
|
||||||
if animall_properties.key_edge_crease:
|
if animall_properties.key_edge_crease:
|
||||||
for e_i, edge in enumerate(data.edges):
|
attribute = get_attribute(data, "crease_edge", 'FLOAT', 'EDGE')
|
||||||
if not animall_properties.key_selected or edge.select:
|
insert_attribute_key(data, attribute, animall_properties.key_selected)
|
||||||
insert_key(edge, 'crease', group=data_("Edge %s") % e_i)
|
|
||||||
|
|
||||||
if animall_properties.key_material_index:
|
if animall_properties.key_material_index:
|
||||||
for p_i, polygon in enumerate(data.polygons):
|
for p_i, polygon in enumerate(data.polygons):
|
||||||
if not animall_properties.key_selected or polygon.select:
|
if not animall_properties.key_selected or polygon.select:
|
||||||
insert_key(polygon, 'material_index', group=data_("Face %s") % p_i)
|
insert_key(polygon, 'material_index', group=data_("Face %s") % p_i)
|
||||||
|
|
||||||
if animall_properties.key_attribute:
|
if animall_properties.key_active_attribute:
|
||||||
if data.attributes.active is not None:
|
if data.attributes.active is not None:
|
||||||
attribute = data.attributes.active
|
for path, group in get_attribute_paths(
|
||||||
if attribute.data_type != 'STRING':
|
data, data.attributes.active,
|
||||||
# Cannot animate string attributes?
|
animall_properties.key_selected):
|
||||||
if attribute.data_type in {'FLOAT', 'INT', 'BOOLEAN', 'INT8'}:
|
if path:
|
||||||
attribute_key = "value"
|
insert_key(data, path, group=group)
|
||||||
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 = data_("Vertex %s")
|
|
||||||
elif attribute.domain == 'EDGE':
|
|
||||||
group = data_("Edge %s")
|
|
||||||
elif attribute.domain == 'FACE':
|
|
||||||
group = data_("Face %s")
|
|
||||||
elif attribute.domain == 'CORNER':
|
|
||||||
group = data_("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)
|
|
||||||
|
|
||||||
if animall_properties.key_uvs:
|
if animall_properties.key_uvs:
|
||||||
if data.uv_layers.active is not None:
|
if data.uv_layers.active is not None:
|
||||||
for uv_i, uv in enumerate(data.uv_layers.active.data):
|
for uv_i, uv in enumerate(data.uv_layers.active.data):
|
||||||
if not animall_properties.key_selected or uv.select:
|
if not animall_properties.key_selected or uv.select:
|
||||||
insert_key(uv, 'uv', group=data_("UV layer %s") % uv_i)
|
insert_key(uv, 'uv', group=data_("UV Layer %s") % uv_i)
|
||||||
|
|
||||||
if animall_properties.key_shape_key:
|
if animall_properties.key_shape_key:
|
||||||
if obj.active_shape_key_index > 0:
|
if obj.active_shape_key_index > 0:
|
||||||
@ -402,9 +430,15 @@ class ANIM_OT_insert_keyframe_animall(Operator):
|
|||||||
if obj.active_shape_key_index > 0:
|
if obj.active_shape_key_index > 0:
|
||||||
CV = obj.active_shape_key.data[global_spline_index]
|
CV = obj.active_shape_key.data[global_spline_index]
|
||||||
insert_key(CV, 'co', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
insert_key(CV, 'co', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
||||||
insert_key(CV, 'handle_left', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
insert_key(
|
||||||
insert_key(CV, 'handle_right', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
CV, 'handle_left', group=data_("%s Spline %s CV %s") %
|
||||||
insert_key(CV, 'radius', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
(sk_name, s_i, v_i))
|
||||||
|
insert_key(
|
||||||
|
CV, 'handle_right', group=data_("%s Spline %s CV %s") %
|
||||||
|
(sk_name, s_i, v_i))
|
||||||
|
insert_key(
|
||||||
|
CV, 'radius', group=data_("%s Spline %s CV %s") %
|
||||||
|
(sk_name, s_i, v_i))
|
||||||
insert_key(CV, 'tilt', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
insert_key(CV, 'tilt', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
||||||
global_spline_index += 1
|
global_spline_index += 1
|
||||||
|
|
||||||
@ -414,7 +448,8 @@ class ANIM_OT_insert_keyframe_animall(Operator):
|
|||||||
if obj.active_shape_key_index > 0:
|
if obj.active_shape_key_index > 0:
|
||||||
CV = obj.active_shape_key.data[global_spline_index]
|
CV = obj.active_shape_key.data[global_spline_index]
|
||||||
insert_key(CV, 'co', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
insert_key(CV, 'co', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
||||||
insert_key(CV, 'radius', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
insert_key(
|
||||||
|
CV, 'radius', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
||||||
insert_key(CV, 'tilt', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
insert_key(CV, 'tilt', group=data_("%s Spline %s CV %s") % (sk_name, s_i, v_i))
|
||||||
global_spline_index += 1
|
global_spline_index += 1
|
||||||
|
|
||||||
@ -443,15 +478,22 @@ class ANIM_OT_delete_keyframe_animall(Operator):
|
|||||||
for obj in objects:
|
for obj in objects:
|
||||||
data = obj.data
|
data = obj.data
|
||||||
if obj.type == 'MESH':
|
if obj.type == 'MESH':
|
||||||
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
if animall_properties.key_point_location:
|
if animall_properties.key_point_location:
|
||||||
for vert in data.vertices:
|
for vert in data.vertices:
|
||||||
if not animall_properties.key_selected or vert.select:
|
if not animall_properties.key_selected or vert.select:
|
||||||
delete_key(vert, 'co')
|
delete_key(vert, 'co')
|
||||||
|
|
||||||
if animall_properties.key_vertex_bevel:
|
if animall_properties.key_vertex_bevel:
|
||||||
for vert in data.vertices:
|
attribute = get_attribute(data, "bevel_weight_vert", 'FLOAT', 'POINT')
|
||||||
if not animall_properties.key_selected or vert.select:
|
if attribute is not None:
|
||||||
delete_key(vert, 'bevel_weight')
|
delete_attribute_key(data, attribute, animall_properties.key_selected)
|
||||||
|
|
||||||
|
if animall_properties.key_vertex_crease:
|
||||||
|
attribute = get_attribute(data, "crease_vert", 'FLOAT', 'POINT')
|
||||||
|
if attribute is not None:
|
||||||
|
delete_attribute_key(data, attribute, animall_properties.key_selected)
|
||||||
|
|
||||||
if animall_properties.key_vertex_group:
|
if animall_properties.key_vertex_group:
|
||||||
for vert in data.vertices:
|
for vert in data.vertices:
|
||||||
@ -459,20 +501,20 @@ class ANIM_OT_delete_keyframe_animall(Operator):
|
|||||||
for group in vert.groups:
|
for group in vert.groups:
|
||||||
delete_key(group, 'weight')
|
delete_key(group, 'weight')
|
||||||
|
|
||||||
# if animall_properties.key_vertex_crease:
|
|
||||||
# for vert in data.vertices:
|
|
||||||
# if not animall_properties.key_selected or vert.select:
|
|
||||||
# delete_key(vert, 'crease')
|
|
||||||
|
|
||||||
if animall_properties.key_edge_bevel:
|
if animall_properties.key_edge_bevel:
|
||||||
for edge in data.edges:
|
attribute = get_attribute(data, "bevel_weight_edge", 'FLOAT', 'EDGE')
|
||||||
if not animall_properties.key_selected or edge.select:
|
if attribute is not None:
|
||||||
delete_key(edge, 'bevel_weight')
|
delete_attribute_key(data, attribute, animall_properties.key_selected)
|
||||||
|
|
||||||
if animall_properties.key_edge_crease:
|
if animall_properties.key_edge_crease:
|
||||||
for edge in data.edges:
|
attribute = get_attribute(data, "crease_edge", 'FLOAT', 'EDGE')
|
||||||
if not animall_properties.key_selected or vert.select:
|
if attribute is not None:
|
||||||
delete_key(edge, 'crease')
|
delete_attribute_key(data, attribute, animall_properties.key_selected)
|
||||||
|
|
||||||
|
if animall_properties.key_material_index:
|
||||||
|
for p_i, polygon in enumerate(data.polygons):
|
||||||
|
if not animall_properties.key_selected or polygon.select:
|
||||||
|
delete_key(polygon, 'material_index')
|
||||||
|
|
||||||
if animall_properties.key_shape_key:
|
if animall_properties.key_shape_key:
|
||||||
if obj.active_shape_key:
|
if obj.active_shape_key:
|
||||||
@ -486,25 +528,15 @@ class ANIM_OT_delete_keyframe_animall(Operator):
|
|||||||
if not animall_properties.key_selected or uv.select:
|
if not animall_properties.key_selected or uv.select:
|
||||||
delete_key(uv, 'uv')
|
delete_key(uv, 'uv')
|
||||||
|
|
||||||
if animall_properties.key_attribute:
|
if animall_properties.key_active_attribute:
|
||||||
if data.attributes.active is not None:
|
if data.attributes.active is not None:
|
||||||
attribute = data.attributes.active
|
for path, _group in get_attribute_paths(
|
||||||
if attribute.data_type != 'STRING':
|
data, data.attributes.active,
|
||||||
# Cannot animate string attributes?
|
animall_properties.key_selected):
|
||||||
if attribute.data_type in {'FLOAT', 'INT', 'BOOLEAN', 'INT8'}:
|
if path:
|
||||||
attribute_key = "value"
|
delete_key(data, path)
|
||||||
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):
|
bpy.ops.object.mode_set(mode=mode)
|
||||||
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':
|
elif obj.type == 'LATTICE':
|
||||||
if animall_properties.key_shape_key:
|
if animall_properties.key_shape_key:
|
||||||
@ -588,12 +620,20 @@ class ANIM_OT_clear_animation_animall(Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class ANIM_OT_update_vertex_color_animation_animall(Operator):
|
class ANIM_OT_update_attribute_animation_animall(Operator):
|
||||||
bl_label = "Update Vertex Color Animation"
|
bl_label = "Update Attribute Animation"
|
||||||
bl_idname = "anim.update_vertex_color_animation_animall"
|
bl_idname = "anim.update_attribute_animation_animall"
|
||||||
bl_description = "Update old vertex color channel formats from pre-3.3 versions"
|
bl_description = "Update attributes from the old format"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
path_re = re.compile(r"^vertex_colors|(vertices|edges)\[([0-9]+)\]\.(bevel_weight|crease)")
|
||||||
|
attribute_map = {
|
||||||
|
("vertices", "bevel_weight"): ("bevel_weight_vert", "FLOAT", "POINT"),
|
||||||
|
("edges", "bevel_weight"): ("bevel_weight_edge", "FLOAT", "POINT"),
|
||||||
|
("vertices", "crease"): ("crease_vert", "FLOAT", "EDGE"),
|
||||||
|
("edges", "crease"): ("crease_edge", "FLOAT", "EDGE"),
|
||||||
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(self, context):
|
def poll(self, context):
|
||||||
if (context.active_object is None
|
if (context.active_object is None
|
||||||
@ -602,21 +642,30 @@ class ANIM_OT_update_vertex_color_animation_animall(Operator):
|
|||||||
or context.active_object.data.animation_data.action is None):
|
or context.active_object.data.animation_data.action is None):
|
||||||
return False
|
return False
|
||||||
for fcurve in context.active_object.data.animation_data.action.fcurves:
|
for fcurve in context.active_object.data.animation_data.action.fcurves:
|
||||||
if fcurve.data_path.startswith("vertex_colors"):
|
if self.path_re.match(fcurve.data_path):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
for fcurve in context.active_object.data.animation_data.action.fcurves:
|
for fcurve in context.active_object.data.animation_data.action.fcurves:
|
||||||
if fcurve.data_path.startswith("vertex_colors"):
|
if fcurve.data_path.startswith("vertex_colors"):
|
||||||
|
# Update pre-3.3 vertex colors
|
||||||
fcurve.data_path = fcurve.data_path.replace("vertex_colors", "attributes")
|
fcurve.data_path = fcurve.data_path.replace("vertex_colors", "attributes")
|
||||||
|
else:
|
||||||
|
# Update pre-4.0 attributes
|
||||||
|
match = self.path_re.match(fcurve.data_path)
|
||||||
|
if match is None:
|
||||||
|
continue
|
||||||
|
domain, index, src_attribute = match.groups()
|
||||||
|
attribute, type, domain = self.attribute_map[(domain, src_attribute)]
|
||||||
|
get_attribute(context.active_object.data, attribute, type, domain)
|
||||||
|
fcurve.data_path = f'attributes["{attribute}"].data[{index}].value'
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
# Add-ons Preferences Update Panel
|
# Add-ons Preferences Update Panel
|
||||||
|
|
||||||
# Define Panel classes for updating
|
# Define Panel classes for updating
|
||||||
panels = [
|
panels = [VIEW3D_PT_animall]
|
||||||
VIEW3D_PT_animall
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def update_panel(self, context):
|
def update_panel(self, context):
|
||||||
@ -643,7 +692,7 @@ class AnimallAddonPreferences(AddonPreferences):
|
|||||||
category: StringProperty(
|
category: StringProperty(
|
||||||
name="Tab Category",
|
name="Tab Category",
|
||||||
description="Choose a name for the category of the panel",
|
description="Choose a name for the category of the panel",
|
||||||
default="Animate",
|
default="Animation",
|
||||||
update=update_panel
|
update=update_panel
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -658,7 +707,7 @@ class AnimallAddonPreferences(AddonPreferences):
|
|||||||
register_classes, unregister_classes = bpy.utils.register_classes_factory(
|
register_classes, unregister_classes = bpy.utils.register_classes_factory(
|
||||||
(AnimallProperties, VIEW3D_PT_animall, ANIM_OT_insert_keyframe_animall,
|
(AnimallProperties, VIEW3D_PT_animall, ANIM_OT_insert_keyframe_animall,
|
||||||
ANIM_OT_delete_keyframe_animall, ANIM_OT_clear_animation_animall,
|
ANIM_OT_delete_keyframe_animall, ANIM_OT_clear_animation_animall,
|
||||||
ANIM_OT_update_vertex_color_animation_animall, AnimallAddonPreferences))
|
ANIM_OT_update_attribute_animation_animall, AnimallAddonPreferences))
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
register_classes()
|
register_classes()
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
translations_tuple = (
|
translations_tuple = (
|
||||||
(("*", ""),
|
(("*", ""),
|
||||||
((), ()),
|
((), ()),
|
||||||
("fr_FR", "Project-Id-Version: AnimAll 0.9.6 (0)\n",
|
("fr_FR", "Project-Id-Version: AnimAll 0.10.0 (0)\n",
|
||||||
(False,
|
(False,
|
||||||
("Blender's translation file (po format).",
|
("Blender's translation file (po format).",
|
||||||
"Copyright (C) 2022 The Blender Foundation.",
|
"Copyright (C) 2022-2023 The Blender Foundation.",
|
||||||
"This file is distributed under the same license as the Blender package.",
|
"This file is distributed under the same license as the Blender package.",
|
||||||
"Damien Picard <dam.pic@free.fr>, 2022."))),
|
"Damien Picard <dam.pic@free.fr>, 2022."))),
|
||||||
),
|
),
|
||||||
@ -59,7 +59,7 @@ translations_tuple = (
|
|||||||
(("Operator", "Delete Key"),
|
(("Operator", "Delete Key"),
|
||||||
(("bpy.types.ANIM_OT_delete_keyframe_animall",),
|
(("bpy.types.ANIM_OT_delete_keyframe_animall",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Supprimer image clé",
|
("fr_FR", "Supprimer l’image clé",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Delete a Keyframe"),
|
(("*", "Delete a Keyframe"),
|
||||||
@ -68,16 +68,16 @@ translations_tuple = (
|
|||||||
("fr_FR", "Supprimer une image clé",
|
("fr_FR", "Supprimer une image clé",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("Operator", "Update Vertex Color Animation"),
|
(("Operator", "Update Attribute Animation"),
|
||||||
(("bpy.types.ANIM_OT_update_vertex_color_animation_animall",),
|
(("bpy.types.ANIM_OT_update_attribute_animation_animall",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Mettre à jour l’animation des couleurs de sommets",
|
("fr_FR", "Mettre à jour l’animation des attributs",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Update old vertex color channel formats from pre-3.3 versions"),
|
(("*", "Update attributes from the old format"),
|
||||||
(("bpy.types.ANIM_OT_update_vertex_color_animation_animall",),
|
(("bpy.types.ANIM_OT_update_attribute_animation_animall",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Mettre à jour les formats des canaux depuis les versions antérieures à la 3.3",
|
("fr_FR", "Mettre à jour les attributs depuis l’ancien format",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Animate"),
|
(("*", "Animate"),
|
||||||
@ -87,7 +87,7 @@ translations_tuple = (
|
|||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Insert keyframes on active attribute values"),
|
(("*", "Insert keyframes on active attribute values"),
|
||||||
(("bpy.types.AnimallProperties.key_attribute",),
|
(("bpy.types.AnimallProperties.key_active_attribute",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Insérer des clés sur l’attribut actif",
|
("fr_FR", "Insérer des clés sur l’attribut actif",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
@ -98,6 +98,12 @@ translations_tuple = (
|
|||||||
("fr_FR", "Insérer des clés sur les poids de biseau d’arête",
|
("fr_FR", "Insérer des clés sur les poids de biseau d’arête",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
|
(("*", "Edge Crease"),
|
||||||
|
(("bpy.types.AnimallProperties.key_edge_crease",),
|
||||||
|
()),
|
||||||
|
("fr_FR", "Plis d’arêtes",
|
||||||
|
(False, ())),
|
||||||
|
),
|
||||||
(("*", "Insert keyframes on edge creases"),
|
(("*", "Insert keyframes on edge creases"),
|
||||||
(("bpy.types.AnimallProperties.key_edge_crease",),
|
(("bpy.types.AnimallProperties.key_edge_crease",),
|
||||||
()),
|
()),
|
||||||
@ -158,6 +164,12 @@ translations_tuple = (
|
|||||||
("fr_FR", "Insérer des clés sur les poids de biseau des sommets",
|
("fr_FR", "Insérer des clés sur les poids de biseau des sommets",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
|
(("*", "Insert keyframes on vertex crease weight"),
|
||||||
|
(("bpy.types.AnimallProperties.key_vertex_crease",),
|
||||||
|
()),
|
||||||
|
("fr_FR", "Insérer des clés sur les plis de sommets",
|
||||||
|
(False, ())),
|
||||||
|
),
|
||||||
(("*", "Insert keyframes on active vertex group values"),
|
(("*", "Insert keyframes on active vertex group values"),
|
||||||
(("bpy.types.AnimallProperties.key_vertex_group",),
|
(("bpy.types.AnimallProperties.key_vertex_group",),
|
||||||
()),
|
()),
|
||||||
@ -165,190 +177,187 @@ translations_tuple = (
|
|||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "AnimAll"),
|
(("*", "AnimAll"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:138",
|
(("Add-on AnimAll info: name",),
|
||||||
"Add-on AnimAll info: name"),
|
|
||||||
()),
|
()),
|
||||||
("fr_FR", "AnimAll",
|
("fr_FR", "AnimAll",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Key:"),
|
(("*", "Key:"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:146",),
|
(("scripts/addons/animation_animall/__init__.py:200",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Insérer :",
|
("fr_FR", "Insérer :",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Tab Category:"),
|
(("*", "Tab Category:"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:653",),
|
(("scripts/addons/animation_animall/__init__.py:704",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Catégorie d’onglet :",
|
("fr_FR", "Catégorie d’onglet :",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Points"),
|
(("*", "Points"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:152",
|
(("scripts/addons/animation_animall/__init__.py:206",
|
||||||
"scripts/addons/animation_animall/__init__.py:159",
|
"scripts/addons/animation_animall/__init__.py:213",
|
||||||
"scripts/addons/animation_animall/__init__.py:188"),
|
"scripts/addons/animation_animall/__init__.py:243"),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Points",
|
("fr_FR", "Points",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Others"),
|
(("*", "Others"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:155",
|
(("scripts/addons/animation_animall/__init__.py:209",
|
||||||
"scripts/addons/animation_animall/__init__.py:171",
|
"scripts/addons/animation_animall/__init__.py:226",
|
||||||
"scripts/addons/animation_animall/__init__.py:196"),
|
"scripts/addons/animation_animall/__init__.py:251"),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Autres",
|
("fr_FR", "Autres",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Bevel"),
|
(("*", "Bevel"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:161",
|
(("scripts/addons/animation_animall/__init__.py:215",
|
||||||
"scripts/addons/animation_animall/__init__.py:165"),
|
"scripts/addons/animation_animall/__init__.py:220"),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Biseau",
|
("fr_FR", "Biseau",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Edges"),
|
(("*", "Edges"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:164",),
|
(("scripts/addons/animation_animall/__init__.py:219",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Arêtes",
|
("fr_FR", "Arêtes",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Crease"),
|
(("*", "Crease"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:166",),
|
(("scripts/addons/animation_animall/__init__.py:216",
|
||||||
|
"scripts/addons/animation_animall/__init__.py:221",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Plis",
|
("fr_FR", "Plis",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Faces"),
|
(("*", "Faces"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:168",),
|
(("scripts/addons/animation_animall/__init__.py:223",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Faces",
|
("fr_FR", "Faces",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "\"Location\" and \"Shape Key\" are redundant?"),
|
(("*", "\"Location\" and \"Shape Key\" are redundant?"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:218",),
|
(("scripts/addons/animation_animall/__init__.py:273",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "\"Position\" et \"Clé de forme\" sont redondants ?",
|
("fr_FR", "\"Position\" et \"Clé de forme\" sont redondants ?",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Splines"),
|
(("*", "Splines"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:193",),
|
(("scripts/addons/animation_animall/__init__.py:248",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Splines",
|
("fr_FR", "Splines",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Maybe set \"%s\" to 1.0?"),
|
(("*", "Maybe set \"%s\" to 1.0?"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:209",
|
(("scripts/addons/animation_animall/__init__.py:264"),
|
||||||
"scripts/addons/animation_animall/__init__.py:209"),
|
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Essayez de mettre « %s » à 1.0 ?",
|
("fr_FR", "Essayez de mettre « %s » à 1.0 ?",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Cannot key on Basis Shape"),
|
(("*", "Cannot key on Basis Shape"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:212",),
|
(("scripts/addons/animation_animall/__init__.py:267",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Impossible d’ajouter une clé sur la forme de base",
|
("fr_FR", "Impossible d’ajouter une clé sur la forme de base",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "No active Shape Key"),
|
(("*", "No active Shape Key"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:215",),
|
(("scripts/addons/animation_animall/__init__.py:270",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Pas de clé de forme active",
|
("fr_FR", "Pas de clé de forme active",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Clear Animation could not be performed"),
|
(("*", "Clear Animation could not be performed"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:581",),
|
(("scripts/addons/animation_animall/__init__.py:615",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "La suppression de l’animation n’a pas pu aboutir",
|
("fr_FR", "La suppression de l’animation n’a pas pu aboutir",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Object includes old-style vertex colors. Consider updating them."),
|
(("*", "Object includes old-style attributes. Consider updating them."),
|
||||||
(("scripts/addons/animation_animall/__init__.py:182",),
|
(("scripts/addons/animation_animall/__init__.py:237",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "L’objet contient des couleurs de sommets à l’ancien format. Veuillez les mettre à jour",
|
("fr_FR", "L’objet contient des attributs à l’ancien format. Veuillez les mettre à jour.",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Vertex %s"),
|
(("*", "Vertex %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:358",
|
(("scripts/addons/animation_animall/__init__.py:141",
|
||||||
"scripts/addons/animation_animall/__init__.py:313",
|
"scripts/addons/animation_animall/__init__.py:368",
|
||||||
"scripts/addons/animation_animall/__init__.py:318",
|
"scripts/addons/animation_animall/__init__.py:382",
|
||||||
"scripts/addons/animation_animall/__init__.py:328"),
|
"scripts/addons/animation_animall/__init__.py:416"),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Sommet %s",
|
("fr_FR", "Sommet %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Edge %s"),
|
(("*", "Edge %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:360",
|
(("scripts/addons/animation_animall/__init__.py:143"),
|
||||||
"scripts/addons/animation_animall/__init__.py:333",
|
|
||||||
"scripts/addons/animation_animall/__init__.py:338"),
|
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Arête %s",
|
("fr_FR", "Arête %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Point %s"),
|
(("*", "Point %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:265",),
|
(("scripts/addons/animation_animall/__init__.py:320",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Point %s",
|
("fr_FR", "Point %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Spline %s"),
|
(("*", "Spline %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:273",),
|
(("scripts/addons/animation_animall/__init__.py:328",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Spline %s",
|
("fr_FR", "Spline %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Face %s"),
|
(("*", "Face %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:343",
|
(("scripts/addons/animation_animall/__init__.py:145",
|
||||||
"scripts/addons/animation_animall/__init__.py:362"),
|
"scripts/addons/animation_animall/__init__.py:395"),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Face %s",
|
("fr_FR", "Face %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "%s Point %s"),
|
(("*", "%s Point %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:260",),
|
(("scripts/addons/animation_animall/__init__.py:315",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "%s Point %s",
|
("fr_FR", "%s Point %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Loop %s"),
|
(("*", "Loop %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:364",),
|
(("scripts/addons/animation_animall/__init__.py:147",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Boucle %s",
|
("fr_FR", "Boucle %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "UV layer %s"),
|
(("*", "UV Layer %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:379",),
|
(("scripts/addons/animation_animall/__init__.py:409",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Calque UV %s",
|
("fr_FR", "Calque UV %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "%s Vertex %s"),
|
(("*", "%s Vertex %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:386",),
|
(("scripts/addons/animation_animall/__init__.py:416",),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "%s Sommet %s",
|
("fr_FR", "%s Sommet %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "Spline %s CV %s"),
|
(("*", "Spline %s CV %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:283",
|
(("scripts/addons/animation_animall/__init__.py:338",
|
||||||
"scripts/addons/animation_animall/__init__.py:284",
|
"scripts/addons/animation_animall/__init__.py:339",
|
||||||
"scripts/addons/animation_animall/__init__.py:285",
|
"scripts/addons/animation_animall/__init__.py:340",
|
||||||
"scripts/addons/animation_animall/__init__.py:288",
|
"scripts/addons/animation_animall/__init__.py:343",
|
||||||
"scripts/addons/animation_animall/__init__.py:291",
|
"scripts/addons/animation_animall/__init__.py:346",
|
||||||
"scripts/addons/animation_animall/__init__.py:297",
|
"scripts/addons/animation_animall/__init__.py:352",
|
||||||
"scripts/addons/animation_animall/__init__.py:300",
|
"scripts/addons/animation_animall/__init__.py:355",
|
||||||
"scripts/addons/animation_animall/__init__.py:303"),
|
"scripts/addons/animation_animall/__init__.py:358"),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "Spline %s Point %s",
|
("fr_FR", "Spline %s Point %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
),
|
),
|
||||||
(("*", "%s Spline %s CV %s"),
|
(("*", "%s Spline %s CV %s"),
|
||||||
(("scripts/addons/animation_animall/__init__.py:402",
|
(("scripts/addons/animation_animall/__init__.py:432",
|
||||||
"scripts/addons/animation_animall/__init__.py:403",
|
"scripts/addons/animation_animall/__init__.py:434",
|
||||||
"scripts/addons/animation_animall/__init__.py:404",
|
"scripts/addons/animation_animall/__init__.py:437",
|
||||||
"scripts/addons/animation_animall/__init__.py:405",
|
"scripts/addons/animation_animall/__init__.py:440",
|
||||||
"scripts/addons/animation_animall/__init__.py:406",
|
"scripts/addons/animation_animall/__init__.py:442",
|
||||||
"scripts/addons/animation_animall/__init__.py:414",
|
"scripts/addons/animation_animall/__init__.py:450",
|
||||||
"scripts/addons/animation_animall/__init__.py:415",
|
"scripts/addons/animation_animall/__init__.py:452",
|
||||||
"scripts/addons/animation_animall/__init__.py:416"),
|
"scripts/addons/animation_animall/__init__.py:453"),
|
||||||
()),
|
()),
|
||||||
("fr_FR", "%s Spline %s Point %s",
|
("fr_FR", "%s Spline %s Point %s",
|
||||||
(False, ())),
|
(False, ())),
|
||||||
|
@ -628,8 +628,11 @@ def make_material_texture_chunk(chunk_id, texslots, pct):
|
|||||||
mat_sub_mapflags.add_variable("mapflags", _3ds_ushort(mapflags))
|
mat_sub_mapflags.add_variable("mapflags", _3ds_ushort(mapflags))
|
||||||
mat_sub.add_subchunk(mat_sub_mapflags)
|
mat_sub.add_subchunk(mat_sub_mapflags)
|
||||||
|
|
||||||
mat_sub_texblur = _3ds_chunk(MAT_MAP_TEXBLUR) # Based on observation this is usually 1.0
|
texblur = 0.0
|
||||||
mat_sub_texblur.add_variable("maptexblur", _3ds_float(1.0))
|
mat_sub_texblur = _3ds_chunk(MAT_MAP_TEXBLUR)
|
||||||
|
if texslot.socket_dst.identifier in {'Base Color', 'Specular Tint'}:
|
||||||
|
texblur = texslot.node_dst.inputs['Sheen Weight'].default_value
|
||||||
|
mat_sub_texblur.add_variable("maptexblur", _3ds_float(round(texblur, 6)))
|
||||||
mat_sub.add_subchunk(mat_sub_texblur)
|
mat_sub.add_subchunk(mat_sub_texblur)
|
||||||
|
|
||||||
mat_sub_uscale = _3ds_chunk(MAT_MAP_USCALE)
|
mat_sub_uscale = _3ds_chunk(MAT_MAP_USCALE)
|
||||||
@ -1306,9 +1309,9 @@ def make_object_node(ob, translation, rotation, scale, name_id):
|
|||||||
obj_node_header_chunk.add_variable("flags1", _3ds_ushort(0x0040))
|
obj_node_header_chunk.add_variable("flags1", _3ds_ushort(0x0040))
|
||||||
# Flag 0x01 display path 0x02 use autosmooth 0x04 object frozen 0x10 motion blur 0x20 material morph 0x40 mesh morph
|
# Flag 0x01 display path 0x02 use autosmooth 0x04 object frozen 0x10 motion blur 0x20 material morph 0x40 mesh morph
|
||||||
if ob.type == 'MESH' and 'Smooth by Angle' in ob.modifiers:
|
if ob.type == 'MESH' and 'Smooth by Angle' in ob.modifiers:
|
||||||
ob_node_header_chunk.add_variable("flags2", _3ds_ushort(0x02))
|
obj_node_header_chunk.add_variable("flags2", _3ds_ushort(0x02))
|
||||||
else:
|
else:
|
||||||
ob_node_header_chunk.add_variable("flags2", _3ds_ushort(0))
|
obj_node_header_chunk.add_variable("flags2", _3ds_ushort(0))
|
||||||
obj_node_header_chunk.add_variable("parent", _3ds_ushort(ROOT_OBJECT))
|
obj_node_header_chunk.add_variable("parent", _3ds_ushort(ROOT_OBJECT))
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
@ -90,6 +90,7 @@ MAT_SHIN_MAP = 0xA33C # This is a header for a new roughness map
|
|||||||
MAT_SELFI_MAP = 0xA33D # This is a header for a new emission map
|
MAT_SELFI_MAP = 0xA33D # This is a header for a new emission map
|
||||||
MAT_MAP_FILEPATH = 0xA300 # This holds the file name of the texture
|
MAT_MAP_FILEPATH = 0xA300 # This holds the file name of the texture
|
||||||
MAT_MAP_TILING = 0xA351 # 2nd bit (from LSB) is mirror UV flag
|
MAT_MAP_TILING = 0xA351 # 2nd bit (from LSB) is mirror UV flag
|
||||||
|
MAT_MAP_TEXBLUR = 0xA353 # Texture blurring factor (float 0-1)
|
||||||
MAT_MAP_USCALE = 0xA354 # U axis scaling
|
MAT_MAP_USCALE = 0xA354 # U axis scaling
|
||||||
MAT_MAP_VSCALE = 0xA356 # V axis scaling
|
MAT_MAP_VSCALE = 0xA356 # V axis scaling
|
||||||
MAT_MAP_UOFFSET = 0xA358 # U axis offset
|
MAT_MAP_UOFFSET = 0xA358 # U axis offset
|
||||||
@ -559,6 +560,8 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
|
|
||||||
elif temp_chunk.ID == MAT_BUMP_PERCENT:
|
elif temp_chunk.ID == MAT_BUMP_PERCENT:
|
||||||
contextWrapper.normalmap_strength = (float(read_short(temp_chunk) / 100))
|
contextWrapper.normalmap_strength = (float(read_short(temp_chunk) / 100))
|
||||||
|
elif mapto in {'COLOR', 'SPECULARITY'} and temp_chunk.ID == MAT_MAP_TEXBLUR:
|
||||||
|
contextWrapper.node_principled_bsdf.inputs['Sheen Weight'].default_value = float(read_float(temp_chunk))
|
||||||
|
|
||||||
elif temp_chunk.ID == MAT_MAP_TILING:
|
elif temp_chunk.ID == MAT_MAP_TILING:
|
||||||
"""Control bit flags, where 0x1 activates decaling, 0x2 activates mirror,
|
"""Control bit flags, where 0x1 activates decaling, 0x2 activates mirror,
|
||||||
@ -645,7 +648,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
hyp = math.sqrt(pow(plane.x,2) + pow(plane.y,2))
|
hyp = math.sqrt(pow(plane.x,2) + pow(plane.y,2))
|
||||||
dia = math.sqrt(pow(hyp,2) + pow(plane.z,2))
|
dia = math.sqrt(pow(hyp,2) + pow(plane.z,2))
|
||||||
yaw = math.atan2(math.copysign(hyp, sign_xy), axis_xy)
|
yaw = math.atan2(math.copysign(hyp, sign_xy), axis_xy)
|
||||||
bow = math.acos(hyp / dia)
|
bow = math.acos(hyp / dia) if dia != 0 else 0
|
||||||
turn = angle - yaw if check_sign else angle + yaw
|
turn = angle - yaw if check_sign else angle + yaw
|
||||||
tilt = angle - bow if loca.z > target.z else angle + bow
|
tilt = angle - bow if loca.z > target.z else angle + bow
|
||||||
pan = yaw if check_axes else turn
|
pan = yaw if check_axes else turn
|
||||||
@ -1002,7 +1005,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
elif new_chunk.ID == MAT_XPFALL:
|
elif new_chunk.ID == MAT_XPFALL:
|
||||||
read_chunk(file, temp_chunk)
|
read_chunk(file, temp_chunk)
|
||||||
if temp_chunk.ID == PCT_SHORT:
|
if temp_chunk.ID == PCT_SHORT:
|
||||||
contextTransmission = float(read_short(temp_chunk) / 100)
|
contextTransmission = float(abs(read_short(temp_chunk) / 100))
|
||||||
else:
|
else:
|
||||||
skip_to_end(file, temp_chunk)
|
skip_to_end(file, temp_chunk)
|
||||||
new_chunk.bytes_read += temp_chunk.bytes_read
|
new_chunk.bytes_read += temp_chunk.bytes_read
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "FBX format",
|
"name": "FBX format",
|
||||||
"author": "Campbell Barton, Bastien Montagne, Jens Restemeier, @Mysteryem",
|
"author": "Campbell Barton, Bastien Montagne, Jens Restemeier, @Mysteryem",
|
||||||
"version": (5, 8, 11),
|
"version": (5, 9, 1),
|
||||||
"blender": (4, 1, 0),
|
"blender": (4, 1, 0),
|
||||||
"location": "File > Import-Export",
|
"location": "File > Import-Export",
|
||||||
"description": "FBX IO meshes, UVs, vertex colors, materials, textures, cameras, lamps and actions",
|
"description": "FBX IO meshes, UVs, vertex colors, materials, textures, cameras, lamps and actions",
|
||||||
|
@ -629,7 +629,7 @@ def _transformation_curves_gen(item, values_arrays, channel_keys):
|
|||||||
# Create matrices/euler from the initial transformation values of this item.
|
# Create matrices/euler from the initial transformation values of this item.
|
||||||
# These variables will be updated in-place as we iterate through each frame.
|
# These variables will be updated in-place as we iterate through each frame.
|
||||||
lcl_translation_mat = Matrix.Translation(transform_data.loc)
|
lcl_translation_mat = Matrix.Translation(transform_data.loc)
|
||||||
lcl_rotation_eul = Euler(transform_data.rot, transform_data.rot_ord)
|
lcl_rotation_eul = Euler(convert_deg_to_rad_iter(transform_data.rot), transform_data.rot_ord)
|
||||||
lcl_scaling_mat = Matrix()
|
lcl_scaling_mat = Matrix()
|
||||||
lcl_scaling_mat[0][0], lcl_scaling_mat[1][1], lcl_scaling_mat[2][2] = transform_data.sca
|
lcl_scaling_mat[0][0], lcl_scaling_mat[1][1], lcl_scaling_mat[2][2] = transform_data.sca
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
'name': 'glTF 2.0 format',
|
'name': 'glTF 2.0 format',
|
||||||
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
|
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
|
||||||
"version": (4, 1, 17),
|
"version": (4, 1, 20),
|
||||||
'blender': (4, 1, 0),
|
'blender': (4, 1, 0),
|
||||||
'location': 'File > Import-Export',
|
'location': 'File > Import-Export',
|
||||||
'description': 'Import-Export as glTF 2.0',
|
'description': 'Import-Export as glTF 2.0',
|
||||||
|
@ -53,13 +53,16 @@ def __gather_scene(blender_scene, export_settings):
|
|||||||
vtree = gltf2_blender_gather_tree.VExportTree(export_settings)
|
vtree = gltf2_blender_gather_tree.VExportTree(export_settings)
|
||||||
vtree.construct(blender_scene)
|
vtree.construct(blender_scene)
|
||||||
vtree.search_missing_armature() # In case armature are no parented correctly
|
vtree.search_missing_armature() # In case armature are no parented correctly
|
||||||
vtree.bake_armature_bone_list() # Used in case we remove the armature
|
if export_settings['gltf_armature_object_remove'] is True:
|
||||||
vtree.check_if_we_can_remove_armature() # Check if we can remove the armatures objects
|
vtree.check_if_we_can_remove_armature() # Check if we can remove the armatures objects
|
||||||
|
|
||||||
export_user_extensions('vtree_before_filter_hook', export_settings, vtree)
|
export_user_extensions('vtree_before_filter_hook', export_settings, vtree)
|
||||||
|
|
||||||
# Now, we can filter tree if needed
|
# Now, we can filter tree if needed
|
||||||
vtree.filter()
|
vtree.filter()
|
||||||
|
|
||||||
|
vtree.bake_armature_bone_list() # Used in case we remove the armature. Doing it after filter, as filter can remove some bones
|
||||||
|
|
||||||
if export_settings['gltf_flatten_bones_hierarchy'] is True:
|
if export_settings['gltf_flatten_bones_hierarchy'] is True:
|
||||||
vtree.break_bone_hierarchy()
|
vtree.break_bone_hierarchy()
|
||||||
if export_settings['gltf_flatten_obj_hierarchy'] is True:
|
if export_settings['gltf_flatten_obj_hierarchy'] is True:
|
||||||
|
@ -25,3 +25,4 @@ def get_object_from_datapath(blender_object, data_path: str):
|
|||||||
# path_attr = data_path
|
# path_attr = data_path
|
||||||
|
|
||||||
return prop
|
return prop
|
||||||
|
|
||||||
|
@ -167,14 +167,14 @@ def __gather_extensions(blender_material, emissive_factor, export_settings):
|
|||||||
clearcoat_extension, uvmap_info = export_clearcoat(blender_material, export_settings)
|
clearcoat_extension, uvmap_info = export_clearcoat(blender_material, export_settings)
|
||||||
if clearcoat_extension:
|
if clearcoat_extension:
|
||||||
extensions["KHR_materials_clearcoat"] = clearcoat_extension
|
extensions["KHR_materials_clearcoat"] = clearcoat_extension
|
||||||
uvmap_infos.update(uvmap_infos)
|
uvmap_infos.update(uvmap_info)
|
||||||
|
|
||||||
# KHR_materials_transmission
|
# KHR_materials_transmission
|
||||||
|
|
||||||
transmission_extension, uvmap_info = export_transmission(blender_material, export_settings)
|
transmission_extension, uvmap_info = export_transmission(blender_material, export_settings)
|
||||||
if transmission_extension:
|
if transmission_extension:
|
||||||
extensions["KHR_materials_transmission"] = transmission_extension
|
extensions["KHR_materials_transmission"] = transmission_extension
|
||||||
uvmap_infos.update(uvmap_infos)
|
uvmap_infos.update(uvmap_info)
|
||||||
|
|
||||||
# KHR_materials_emissive_strength
|
# KHR_materials_emissive_strength
|
||||||
if any([i>1.0 for i in emissive_factor or []]):
|
if any([i>1.0 for i in emissive_factor or []]):
|
||||||
|
@ -347,6 +347,7 @@ def get_texture_transform_from_mapping_node(mapping_node):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
mapping_transform = {}
|
mapping_transform = {}
|
||||||
|
if mapping_node.node.vector_type != "VECTOR":
|
||||||
mapping_transform["offset"] = [mapping_node.node.inputs['Location'].default_value[0], mapping_node.node.inputs['Location'].default_value[1]]
|
mapping_transform["offset"] = [mapping_node.node.inputs['Location'].default_value[0], mapping_node.node.inputs['Location'].default_value[1]]
|
||||||
mapping_transform["rotation"] = mapping_node.node.inputs['Rotation'].default_value[2]
|
mapping_transform["rotation"] = mapping_node.node.inputs['Rotation'].default_value[2]
|
||||||
mapping_transform["scale"] = [mapping_node.node.inputs['Scale'].default_value[0], mapping_node.node.inputs['Scale'].default_value[1]]
|
mapping_transform["scale"] = [mapping_node.node.inputs['Scale'].default_value[0], mapping_node.node.inputs['Scale'].default_value[1]]
|
||||||
|
@ -20,10 +20,6 @@ def drawlayout(context, layout, mode='non-panel'):
|
|||||||
col.menu(NWMergeNodesMenu.bl_idname)
|
col.menu(NWMergeNodesMenu.bl_idname)
|
||||||
col.separator()
|
col.separator()
|
||||||
|
|
||||||
col = layout.column(align=True)
|
|
||||||
col.menu(NWSwitchNodeTypeMenu.bl_idname, text="Switch Node Type")
|
|
||||||
col.separator()
|
|
||||||
|
|
||||||
if tree_type == 'ShaderNodeTree':
|
if tree_type == 'ShaderNodeTree':
|
||||||
col = layout.column(align=True)
|
col = layout.column(align=True)
|
||||||
col.operator(operators.NWAddTextureSetup.bl_idname, text="Add Texture Setup", icon='NODE_SEL')
|
col.operator(operators.NWAddTextureSetup.bl_idname, text="Add Texture Setup", icon='NODE_SEL')
|
||||||
@ -385,32 +381,8 @@ class NWSwitchNodeTypeMenu(Menu, NWBase):
|
|||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
categories = [c for c in node_categories_iter(context)
|
layout.label(text="This operator is removed due to the changes of node menus.", icon='ERROR')
|
||||||
if c.name not in ['Group', 'Script']]
|
layout.label(text="A native implementation of the function is expected in the future.")
|
||||||
for cat in categories:
|
|
||||||
idname = f"NODE_MT_nw_switch_{cat.identifier}_submenu"
|
|
||||||
if hasattr(bpy.types, idname):
|
|
||||||
layout.menu(idname)
|
|
||||||
else:
|
|
||||||
layout.label(text="Unable to load altered node lists.")
|
|
||||||
layout.label(text="Please re-enable Node Wrangler.")
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def draw_switch_category_submenu(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
if self.category.name == 'Layout':
|
|
||||||
for node in self.category.items(context):
|
|
||||||
if node.nodetype != 'NodeFrame':
|
|
||||||
props = layout.operator(operators.NWSwitchNodeType.bl_idname, text=node.label)
|
|
||||||
props.to_type = node.nodetype
|
|
||||||
else:
|
|
||||||
for node in self.category.items(context):
|
|
||||||
if isinstance(node, NodeItemCustom):
|
|
||||||
node.draw(self, layout, context)
|
|
||||||
continue
|
|
||||||
props = layout.operator(operators.NWSwitchNodeType.bl_idname, text=node.label)
|
|
||||||
props.to_type = node.nodetype
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# APPENDAGES TO EXISTING UI
|
# APPENDAGES TO EXISTING UI
|
||||||
|
@ -914,195 +914,6 @@ class NWReloadImages(Operator):
|
|||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
|
||||||
class NWSwitchNodeType(Operator, NWBase):
|
|
||||||
"""Switch type of selected nodes """
|
|
||||||
bl_idname = "node.nw_swtch_node_type"
|
|
||||||
bl_label = "Switch Node Type"
|
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
|
||||||
|
|
||||||
to_type: StringProperty(
|
|
||||||
name="Switch to type",
|
|
||||||
default='',
|
|
||||||
)
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
to_type = self.to_type
|
|
||||||
if len(to_type) == 0:
|
|
||||||
return {'CANCELLED'}
|
|
||||||
|
|
||||||
nodes, links = get_nodes_links(context)
|
|
||||||
# Those types of nodes will not swap.
|
|
||||||
src_excludes = ('NodeFrame')
|
|
||||||
# Those attributes of nodes will be copied if possible
|
|
||||||
attrs_to_pass = ('color', 'hide', 'label', 'mute', 'parent',
|
|
||||||
'show_options', 'show_preview', 'show_texture',
|
|
||||||
'use_alpha', 'use_clamp', 'use_custom_color', 'location'
|
|
||||||
)
|
|
||||||
selected = [n for n in nodes if n.select]
|
|
||||||
reselect = []
|
|
||||||
for node in [n for n in selected if
|
|
||||||
n.rna_type.identifier not in src_excludes and
|
|
||||||
n.rna_type.identifier != to_type]:
|
|
||||||
new_node = nodes.new(to_type)
|
|
||||||
for attr in attrs_to_pass:
|
|
||||||
if hasattr(node, attr) and hasattr(new_node, attr):
|
|
||||||
setattr(new_node, attr, getattr(node, attr))
|
|
||||||
# set image datablock of dst to image of src
|
|
||||||
if hasattr(node, 'image') and hasattr(new_node, 'image'):
|
|
||||||
if node.image:
|
|
||||||
new_node.image = node.image
|
|
||||||
# Special cases
|
|
||||||
if new_node.type == 'SWITCH':
|
|
||||||
new_node.hide = True
|
|
||||||
# Dictionaries: src_sockets and dst_sockets:
|
|
||||||
# 'INPUTS': input sockets ordered by type (entry 'MAIN' main type of inputs).
|
|
||||||
# 'OUTPUTS': output sockets ordered by type (entry 'MAIN' main type of outputs).
|
|
||||||
# in 'INPUTS' and 'OUTPUTS':
|
|
||||||
# 'SHADER', 'RGBA', 'VECTOR', 'VALUE' - sockets of those types.
|
|
||||||
# socket entry:
|
|
||||||
# (index_in_type, socket_index, socket_name, socket_default_value, socket_links)
|
|
||||||
src_sockets = {
|
|
||||||
'INPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE': [], 'MAIN': None},
|
|
||||||
'OUTPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE': [], 'MAIN': None},
|
|
||||||
}
|
|
||||||
dst_sockets = {
|
|
||||||
'INPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE': [], 'MAIN': None},
|
|
||||||
'OUTPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE': [], 'MAIN': None},
|
|
||||||
}
|
|
||||||
types_order_one = 'SHADER', 'RGBA', 'VECTOR', 'VALUE'
|
|
||||||
types_order_two = 'SHADER', 'VECTOR', 'RGBA', 'VALUE'
|
|
||||||
# check src node to set src_sockets values and dst node to set dst_sockets dict values
|
|
||||||
for sockets, nd in ((src_sockets, node), (dst_sockets, new_node)):
|
|
||||||
# Check node's inputs and outputs and fill proper entries in "sockets" dict
|
|
||||||
for in_out, in_out_name in ((nd.inputs, 'INPUTS'), (nd.outputs, 'OUTPUTS')):
|
|
||||||
# enumerate in inputs, then in outputs
|
|
||||||
# find name, default value and links of socket
|
|
||||||
for i, socket in enumerate(in_out):
|
|
||||||
the_name = socket.name
|
|
||||||
dval = None
|
|
||||||
# Not every socket, especially in outputs has "default_value"
|
|
||||||
if hasattr(socket, 'default_value'):
|
|
||||||
dval = socket.default_value
|
|
||||||
socket_links = []
|
|
||||||
for lnk in socket.links:
|
|
||||||
socket_links.append(lnk)
|
|
||||||
# check type of socket to fill proper keys.
|
|
||||||
for the_type in types_order_one:
|
|
||||||
if socket.type == the_type:
|
|
||||||
# create values for sockets['INPUTS'][the_type] and sockets['OUTPUTS'][the_type]
|
|
||||||
# entry structure: (index_in_type, socket_index, socket_name,
|
|
||||||
# socket_default_value, socket_links)
|
|
||||||
sockets[in_out_name][the_type].append(
|
|
||||||
(len(sockets[in_out_name][the_type]), i, the_name, dval, socket_links))
|
|
||||||
# Check which of the types in inputs/outputs is considered to be "main".
|
|
||||||
# Set values of sockets['INPUTS']['MAIN'] and sockets['OUTPUTS']['MAIN']
|
|
||||||
for type_check in types_order_one:
|
|
||||||
if sockets[in_out_name][type_check]:
|
|
||||||
sockets[in_out_name]['MAIN'] = type_check
|
|
||||||
break
|
|
||||||
|
|
||||||
matches = {
|
|
||||||
'INPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE_NAME': [], 'VALUE': [], 'MAIN': []},
|
|
||||||
'OUTPUTS': {'SHADER': [], 'RGBA': [], 'VECTOR': [], 'VALUE_NAME': [], 'VALUE': [], 'MAIN': []},
|
|
||||||
}
|
|
||||||
|
|
||||||
for inout, soctype in (
|
|
||||||
('INPUTS', 'MAIN',),
|
|
||||||
('INPUTS', 'SHADER',),
|
|
||||||
('INPUTS', 'RGBA',),
|
|
||||||
('INPUTS', 'VECTOR',),
|
|
||||||
('INPUTS', 'VALUE',),
|
|
||||||
('OUTPUTS', 'MAIN',),
|
|
||||||
('OUTPUTS', 'SHADER',),
|
|
||||||
('OUTPUTS', 'RGBA',),
|
|
||||||
('OUTPUTS', 'VECTOR',),
|
|
||||||
('OUTPUTS', 'VALUE',),
|
|
||||||
):
|
|
||||||
if src_sockets[inout][soctype] and dst_sockets[inout][soctype]:
|
|
||||||
if soctype == 'MAIN':
|
|
||||||
sc = src_sockets[inout][src_sockets[inout]['MAIN']]
|
|
||||||
dt = dst_sockets[inout][dst_sockets[inout]['MAIN']]
|
|
||||||
else:
|
|
||||||
sc = src_sockets[inout][soctype]
|
|
||||||
dt = dst_sockets[inout][soctype]
|
|
||||||
# start with 'dt' to determine number of possibilities.
|
|
||||||
for i, soc in enumerate(dt):
|
|
||||||
# if src main has enough entries - match them with dst main sockets by indexes.
|
|
||||||
if len(sc) > i:
|
|
||||||
matches[inout][soctype].append(((sc[i][1], sc[i][3]), (soc[1], soc[3])))
|
|
||||||
# add 'VALUE_NAME' criterion to inputs.
|
|
||||||
if inout == 'INPUTS' and soctype == 'VALUE':
|
|
||||||
for s in sc:
|
|
||||||
if s[2] == soc[2]: # if names match
|
|
||||||
# append src (index, dval), dst (index, dval)
|
|
||||||
matches['INPUTS']['VALUE_NAME'].append(((s[1], s[3]), (soc[1], soc[3])))
|
|
||||||
|
|
||||||
# When src ['INPUTS']['MAIN'] is 'VECTOR' replace 'MAIN' with matches VECTOR if possible.
|
|
||||||
# This creates better links when relinking textures.
|
|
||||||
if src_sockets['INPUTS']['MAIN'] == 'VECTOR' and matches['INPUTS']['VECTOR']:
|
|
||||||
matches['INPUTS']['MAIN'] = matches['INPUTS']['VECTOR']
|
|
||||||
|
|
||||||
# Pass default values and RELINK:
|
|
||||||
for tp in ('MAIN', 'SHADER', 'RGBA', 'VECTOR', 'VALUE_NAME', 'VALUE'):
|
|
||||||
# INPUTS: Base on matches in proper order.
|
|
||||||
for (src_i, src_dval), (dst_i, dst_dval) in matches['INPUTS'][tp]:
|
|
||||||
# pass dvals
|
|
||||||
if src_dval and dst_dval and tp in {'RGBA', 'VALUE_NAME'}:
|
|
||||||
new_node.inputs[dst_i].default_value = src_dval
|
|
||||||
# Special case: switch to math
|
|
||||||
if node.type in {'MIX_RGB', 'ALPHAOVER', 'ZCOMBINE'} and\
|
|
||||||
new_node.type == 'MATH' and\
|
|
||||||
tp == 'MAIN':
|
|
||||||
new_dst_dval = max(src_dval[0], src_dval[1], src_dval[2])
|
|
||||||
new_node.inputs[dst_i].default_value = new_dst_dval
|
|
||||||
if node.type == 'MIX_RGB':
|
|
||||||
if node.blend_type in [o[0] for o in operations]:
|
|
||||||
new_node.operation = node.blend_type
|
|
||||||
# Special case: switch from math to some types
|
|
||||||
if node.type == 'MATH' and\
|
|
||||||
new_node.type in {'MIX_RGB', 'ALPHAOVER', 'ZCOMBINE'} and\
|
|
||||||
tp == 'MAIN':
|
|
||||||
for i in range(3):
|
|
||||||
new_node.inputs[dst_i].default_value[i] = src_dval
|
|
||||||
if new_node.type == 'MIX_RGB':
|
|
||||||
if node.operation in [t[0] for t in blend_types]:
|
|
||||||
new_node.blend_type = node.operation
|
|
||||||
# Set Fac of MIX_RGB to 1.0
|
|
||||||
new_node.inputs[0].default_value = 1.0
|
|
||||||
# make link only when dst matching input is not linked already.
|
|
||||||
if node.inputs[src_i].links and not new_node.inputs[dst_i].links:
|
|
||||||
in_src_link = node.inputs[src_i].links[0]
|
|
||||||
in_dst_socket = new_node.inputs[dst_i]
|
|
||||||
connect_sockets(in_src_link.from_socket, in_dst_socket)
|
|
||||||
links.remove(in_src_link)
|
|
||||||
# OUTPUTS: Base on matches in proper order.
|
|
||||||
for (src_i, src_dval), (dst_i, dst_dval) in matches['OUTPUTS'][tp]:
|
|
||||||
for out_src_link in node.outputs[src_i].links:
|
|
||||||
out_dst_socket = new_node.outputs[dst_i]
|
|
||||||
connect_sockets(out_dst_socket, out_src_link.to_socket)
|
|
||||||
# relink rest inputs if possible, no criteria
|
|
||||||
for src_inp in node.inputs:
|
|
||||||
for dst_inp in new_node.inputs:
|
|
||||||
if src_inp.links and not dst_inp.links:
|
|
||||||
src_link = src_inp.links[0]
|
|
||||||
connect_sockets(src_link.from_socket, dst_inp)
|
|
||||||
links.remove(src_link)
|
|
||||||
# relink rest outputs if possible, base on node kind if any left.
|
|
||||||
for src_o in node.outputs:
|
|
||||||
for out_src_link in src_o.links:
|
|
||||||
for dst_o in new_node.outputs:
|
|
||||||
if src_o.type == dst_o.type:
|
|
||||||
connect_sockets(dst_o, out_src_link.to_socket)
|
|
||||||
# relink rest outputs no criteria if any left. Link all from first output.
|
|
||||||
for src_o in node.outputs:
|
|
||||||
for out_src_link in src_o.links:
|
|
||||||
if new_node.outputs:
|
|
||||||
connect_sockets(new_node.outputs[0], out_src_link.to_socket)
|
|
||||||
nodes.remove(node)
|
|
||||||
force_update(context)
|
|
||||||
return {'FINISHED'}
|
|
||||||
|
|
||||||
|
|
||||||
class NWMergeNodes(Operator, NWBase):
|
class NWMergeNodes(Operator, NWBase):
|
||||||
bl_idname = "node.nw_merge_nodes"
|
bl_idname = "node.nw_merge_nodes"
|
||||||
bl_label = "Merge Nodes"
|
bl_label = "Merge Nodes"
|
||||||
@ -2976,7 +2787,6 @@ classes = (
|
|||||||
NWPreviewNode,
|
NWPreviewNode,
|
||||||
NWFrameSelected,
|
NWFrameSelected,
|
||||||
NWReloadImages,
|
NWReloadImages,
|
||||||
NWSwitchNodeType,
|
|
||||||
NWMergeNodes,
|
NWMergeNodes,
|
||||||
NWBatchChangeNodes,
|
NWBatchChangeNodes,
|
||||||
NWChangeMixFactor,
|
NWChangeMixFactor,
|
||||||
|
@ -162,7 +162,6 @@ class NWNodeWrangler(bpy.types.AddonPreferences):
|
|||||||
#
|
#
|
||||||
# REGISTER/UNREGISTER CLASSES AND KEYMAP ITEMS
|
# REGISTER/UNREGISTER CLASSES AND KEYMAP ITEMS
|
||||||
#
|
#
|
||||||
switch_category_menus = []
|
|
||||||
addon_keymaps = []
|
addon_keymaps = []
|
||||||
# kmi_defs entry: (identifier, key, action, CTRL, SHIFT, ALT, props, nice name)
|
# kmi_defs entry: (identifier, key, action, CTRL, SHIFT, ALT, props, nice name)
|
||||||
# props entry: (property name, property value)
|
# props entry: (property name, property value)
|
||||||
@ -392,28 +391,8 @@ def register():
|
|||||||
setattr(kmi.properties, prop, value)
|
setattr(kmi.properties, prop, value)
|
||||||
addon_keymaps.append((km, kmi))
|
addon_keymaps.append((km, kmi))
|
||||||
|
|
||||||
# switch submenus
|
|
||||||
switch_category_menus.clear()
|
|
||||||
for cat in node_categories_iter(None):
|
|
||||||
if cat.name not in ['Group', 'Script']:
|
|
||||||
idname = f"NODE_MT_nw_switch_{cat.identifier}_submenu"
|
|
||||||
switch_category_type = type(idname, (bpy.types.Menu,), {
|
|
||||||
"bl_space_type": 'NODE_EDITOR',
|
|
||||||
"bl_label": cat.name,
|
|
||||||
"category": cat,
|
|
||||||
"poll": cat.poll,
|
|
||||||
"draw": interface.draw_switch_category_submenu,
|
|
||||||
})
|
|
||||||
|
|
||||||
switch_category_menus.append(switch_category_type)
|
|
||||||
|
|
||||||
bpy.utils.register_class(switch_category_type)
|
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
for cat_types in switch_category_menus:
|
|
||||||
bpy.utils.unregister_class(cat_types)
|
|
||||||
switch_category_menus.clear()
|
|
||||||
|
|
||||||
# keymaps
|
# keymaps
|
||||||
for km, kmi in addon_keymaps:
|
for km, kmi in addon_keymaps:
|
||||||
|
@ -6,8 +6,8 @@ bl_info = {
|
|||||||
"name": "Collection Manager",
|
"name": "Collection Manager",
|
||||||
"description": "Manage collections and their objects",
|
"description": "Manage collections and their objects",
|
||||||
"author": "Ryan Inch",
|
"author": "Ryan Inch",
|
||||||
"version": (2, 24, 8),
|
"version": (2, 24, 9),
|
||||||
"blender": (3, 0, 0),
|
"blender": (4, 0, 0),
|
||||||
"location": "View3D - Object Mode (Shortcut - M)",
|
"location": "View3D - Object Mode (Shortcut - M)",
|
||||||
"warning": '', # used for warning icon and text in addons panel
|
"warning": '', # used for warning icon and text in addons panel
|
||||||
"doc_url": "{BLENDER_MANUAL_URL}/addons/interface/collection_manager.html",
|
"doc_url": "{BLENDER_MANUAL_URL}/addons/interface/collection_manager.html",
|
||||||
|
@ -50,7 +50,7 @@ def get_tool_text(self):
|
|||||||
return self["tool_text_color"]
|
return self["tool_text_color"]
|
||||||
else:
|
else:
|
||||||
color = bpy.context.preferences.themes[0].user_interface.wcol_tool.text
|
color = bpy.context.preferences.themes[0].user_interface.wcol_tool.text
|
||||||
self["tool_text_color"] = color.r, color.g, color.b
|
self["tool_text_color"] = color[0], color[1], color[2]
|
||||||
return self["tool_text_color"]
|
return self["tool_text_color"]
|
||||||
|
|
||||||
def set_tool_text(self, values):
|
def set_tool_text(self, values):
|
||||||
@ -62,7 +62,7 @@ def get_tool_text_sel(self):
|
|||||||
return self["tool_text_sel_color"]
|
return self["tool_text_sel_color"]
|
||||||
else:
|
else:
|
||||||
color = bpy.context.preferences.themes[0].user_interface.wcol_tool.text_sel
|
color = bpy.context.preferences.themes[0].user_interface.wcol_tool.text_sel
|
||||||
self["tool_text_sel_color"] = color.r, color.g, color.b
|
self["tool_text_sel_color"] = color[0], color[1], color[2]
|
||||||
return self["tool_text_sel_color"]
|
return self["tool_text_sel_color"]
|
||||||
|
|
||||||
def set_tool_text_sel(self, values):
|
def set_tool_text_sel(self, values):
|
||||||
@ -98,11 +98,11 @@ def get_tool_outline(self):
|
|||||||
return self["tool_outline_color"]
|
return self["tool_outline_color"]
|
||||||
else:
|
else:
|
||||||
color = bpy.context.preferences.themes[0].user_interface.wcol_tool.outline
|
color = bpy.context.preferences.themes[0].user_interface.wcol_tool.outline
|
||||||
self["tool_outline_color"] = color.r, color.g, color.b
|
self["tool_outline_color"] = color[0], color[1], color[2], color[3]
|
||||||
return self["tool_outline_color"]
|
return self["tool_outline_color"]
|
||||||
|
|
||||||
def set_tool_outline(self, values):
|
def set_tool_outline(self, values):
|
||||||
self["tool_outline_color"] = values[0], values[1], values[2]
|
self["tool_outline_color"] = values[0], values[1], values[2], values[3]
|
||||||
|
|
||||||
|
|
||||||
def get_menu_back_text(self):
|
def get_menu_back_text(self):
|
||||||
@ -110,7 +110,7 @@ def get_menu_back_text(self):
|
|||||||
return self["menu_back_text_color"]
|
return self["menu_back_text_color"]
|
||||||
else:
|
else:
|
||||||
color = bpy.context.preferences.themes[0].user_interface.wcol_menu_back.text
|
color = bpy.context.preferences.themes[0].user_interface.wcol_menu_back.text
|
||||||
self["menu_back_text_color"] = color.r, color.g, color.b
|
self["menu_back_text_color"] = color[0], color[1], color[2]
|
||||||
return self["menu_back_text_color"]
|
return self["menu_back_text_color"]
|
||||||
|
|
||||||
def set_menu_back_text(self, values):
|
def set_menu_back_text(self, values):
|
||||||
@ -134,11 +134,11 @@ def get_menu_back_outline(self):
|
|||||||
return self["menu_back_outline_color"]
|
return self["menu_back_outline_color"]
|
||||||
else:
|
else:
|
||||||
color = bpy.context.preferences.themes[0].user_interface.wcol_menu_back.outline
|
color = bpy.context.preferences.themes[0].user_interface.wcol_menu_back.outline
|
||||||
self["menu_back_outline_color"] = color.r, color.g, color.b
|
self["menu_back_outline_color"] = color[0], color[1], color[2], color[3]
|
||||||
return self["menu_back_outline_color"]
|
return self["menu_back_outline_color"]
|
||||||
|
|
||||||
def set_menu_back_outline(self, values):
|
def set_menu_back_outline(self, values):
|
||||||
self["menu_back_outline_color"] = values[0], values[1], values[2]
|
self["menu_back_outline_color"] = values[0], values[1], values[2], values[3]
|
||||||
|
|
||||||
|
|
||||||
def get_tooltip_text(self):
|
def get_tooltip_text(self):
|
||||||
@ -146,7 +146,7 @@ def get_tooltip_text(self):
|
|||||||
return self["tooltip_text_color"]
|
return self["tooltip_text_color"]
|
||||||
else:
|
else:
|
||||||
color = bpy.context.preferences.themes[0].user_interface.wcol_tooltip.text
|
color = bpy.context.preferences.themes[0].user_interface.wcol_tooltip.text
|
||||||
self["tooltip_text_color"] = color.r, color.g, color.b
|
self["tooltip_text_color"] = color[0], color[1], color[2]
|
||||||
return self["tooltip_text_color"]
|
return self["tooltip_text_color"]
|
||||||
|
|
||||||
def set_tooltip_text(self, values):
|
def set_tooltip_text(self, values):
|
||||||
@ -170,11 +170,11 @@ def get_tooltip_outline(self):
|
|||||||
return self["tooltip_outline_color"]
|
return self["tooltip_outline_color"]
|
||||||
else:
|
else:
|
||||||
color = bpy.context.preferences.themes[0].user_interface.wcol_tooltip.outline
|
color = bpy.context.preferences.themes[0].user_interface.wcol_tooltip.outline
|
||||||
self["tooltip_outline_color"] = color.r, color.g, color.b
|
self["tooltip_outline_color"] = color[0], color[1], color[2], color[3]
|
||||||
return self["tooltip_outline_color"]
|
return self["tooltip_outline_color"]
|
||||||
|
|
||||||
def set_tooltip_outline(self, values):
|
def set_tooltip_outline(self, values):
|
||||||
self["tooltip_outline_color"] = values[0], values[1], values[2]
|
self["tooltip_outline_color"] = values[0], values[1], values[2], values[3]
|
||||||
|
|
||||||
|
|
||||||
class CMPreferences(AddonPreferences):
|
class CMPreferences(AddonPreferences):
|
||||||
|
@ -771,7 +771,7 @@ def draw_callback_px(self, context):
|
|||||||
main_window = self.areas["Main Window"]
|
main_window = self.areas["Main Window"]
|
||||||
outline_color = addon_prefs.qcd_ogl_widget_menu_back_outline
|
outline_color = addon_prefs.qcd_ogl_widget_menu_back_outline
|
||||||
background_color = addon_prefs.qcd_ogl_widget_menu_back_inner
|
background_color = addon_prefs.qcd_ogl_widget_menu_back_inner
|
||||||
draw_rounded_rect(main_window, line_shader, outline_color[:] + (1,), outline=True)
|
draw_rounded_rect(main_window, line_shader, outline_color[:], outline=True)
|
||||||
draw_rounded_rect(main_window, shader, background_color)
|
draw_rounded_rect(main_window, shader, background_color)
|
||||||
|
|
||||||
# draw window title
|
# draw window title
|
||||||
@ -852,7 +852,7 @@ def draw_callback_px(self, context):
|
|||||||
|
|
||||||
# draw button
|
# draw button
|
||||||
outline_color = addon_prefs.qcd_ogl_widget_tool_outline
|
outline_color = addon_prefs.qcd_ogl_widget_tool_outline
|
||||||
draw_rounded_rect(button_area, line_shader, outline_color[:] + (1,), tl, tr, bl, br, outline=True)
|
draw_rounded_rect(button_area, line_shader, outline_color[:], tl, tr, bl, br, outline=True)
|
||||||
draw_rounded_rect(button_area, shader, button_color, tl, tr, bl, br)
|
draw_rounded_rect(button_area, shader, button_color, tl, tr, bl, br)
|
||||||
|
|
||||||
# ACTIVE OBJECT
|
# ACTIVE OBJECT
|
||||||
@ -979,7 +979,7 @@ def draw_tooltip(self, context, shader, line_shader, message):
|
|||||||
|
|
||||||
outline_color = addon_prefs.qcd_ogl_widget_tooltip_outline
|
outline_color = addon_prefs.qcd_ogl_widget_tooltip_outline
|
||||||
background_color = addon_prefs.qcd_ogl_widget_tooltip_inner
|
background_color = addon_prefs.qcd_ogl_widget_tooltip_inner
|
||||||
draw_rounded_rect(tooltip, line_shader, outline_color[:] + (1,), outline=True)
|
draw_rounded_rect(tooltip, line_shader, outline_color[:], outline=True)
|
||||||
draw_rounded_rect(tooltip, shader, background_color)
|
draw_rounded_rect(tooltip, shader, background_color)
|
||||||
|
|
||||||
line_pos = padding + line_height
|
line_pos = padding + line_height
|
||||||
|
Loading…
Reference in New Issue
Block a user