[Bf-extensions-cvs] [06766ff5] blender-v2.81-release: glTF exporter: fix exporting shapekeys animation when some sk are not animated
Julien Duroure
noreply at git.blender.org
Sat Oct 12 13:22:40 CEST 2019
Commit: 06766ff5d5932a7acb05a45d6cd045e5374e6b38
Author: Julien Duroure
Date: Sat Oct 12 13:21:42 2019 +0200
Branches: blender-v2.81-release
https://developer.blender.org/rBA06766ff5d5932a7acb05a45d6cd045e5374e6b38
glTF exporter: fix exporting shapekeys animation when some sk are not animated
===================================================================
M io_scene_gltf2/__init__.py
M io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py
M io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py
M io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py
M io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_samplers.py
===================================================================
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index 0548f2ec..36fda5ce 100755
--- a/io_scene_gltf2/__init__.py
+++ b/io_scene_gltf2/__init__.py
@@ -15,7 +15,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
- "version": (1, 0, 3),
+ "version": (1, 0, 4),
'blender': (2, 81, 6),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',
@@ -834,3 +834,4 @@ def unregister():
# remove from the export / import menu
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
+
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py
index 2c458742..04028d20 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py
@@ -78,7 +78,8 @@ def __gather_path(channels: typing.Tuple[bpy.types.FCurve],
bake_channel: typing.Union[str, None]
) -> str:
if bake_channel is None:
- target = channels[0].data_path.split('.')[-1]
+ # Note: channels has some None items only for SK if some SK are not animated
+ target = [c for c in channels if c is not None][0].data_path.split('.')[-1]
else:
target = bake_channel
path = {
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py
index da963eab..edee0971 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py
@@ -37,16 +37,17 @@ def gather_animation_channels(blender_action: bpy.types.Action,
bake_range_start = None
bake_range_end = None
groups = __get_channel_groups(blender_action, blender_object, export_settings)
+ # Note: channels has some None items only for SK if some SK are not animated
for chans in groups:
- ranges = [channel.range() for channel in chans]
+ ranges = [channel.range() for channel in chans if channel is not None]
if bake_range_start is None:
- bake_range_start = min([channel.range()[0] for channel in chans])
+ bake_range_start = min([channel.range()[0] for channel in chans if channel is not None])
else:
- bake_range_start = min(bake_range_start, min([channel.range()[0] for channel in chans]))
+ bake_range_start = min(bake_range_start, min([channel.range()[0] for channel in chans if channel is not None]))
if bake_range_end is None:
- bake_range_end = max([channel.range()[1] for channel in chans])
+ bake_range_end = max([channel.range()[1] for channel in chans if channel is not None])
else:
- bake_range_end = max(bake_range_end, max([channel.range()[1] for channel in chans]))
+ bake_range_end = max(bake_range_end, max([channel.range()[1] for channel in chans if channel is not None]))
if blender_object.type == "ARMATURE" and export_settings['gltf_force_sampling'] is True:
@@ -55,7 +56,7 @@ def gather_animation_channels(blender_action: bpy.types.Action,
# Check that there are some anim in this action
if bake_range_start is None:
return []
-
+
# Then bake all bones
for bone in blender_object.data.bones:
for p in ["location", "rotation_quaternion", "scale"]:
@@ -96,7 +97,21 @@ def __get_channel_group_sorted(channels: typing.Tuple[bpy.types.FCurve], blender
shapekeys_idx[sk.name] = cpt_sk
cpt_sk += 1
- return tuple(sorted(channels, key=lambda x: shapekeys_idx[blender_object.data.shape_keys.path_resolve(get_target_object_path(x.data_path)).name]))
+ # Note: channels will have some None items only for SK if some SK are not animated
+ idx_channel_mapping = []
+ all_sorted_channels = []
+ for sk_c in channels:
+ sk_name = blender_object.data.shape_keys.path_resolve(get_target_object_path(sk_c.data_path)).name
+ idx = shapekeys_idx[sk_name]
+ idx_channel_mapping.append((shapekeys_idx[sk_name], sk_c))
+ existing_idx = dict(idx_channel_mapping)
+ for i in range(0, cpt_sk):
+ if i not in existing_idx.keys():
+ all_sorted_channels.append(None)
+ else:
+ all_sorted_channels.append(existing_idx[i])
+
+ return tuple(all_sorted_channels)
# if not shapekeys, stay in same order, because order doesn't matter
return channels
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py
index 8a4f011a..8b6f0db6 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_sampler_keyframes.py
@@ -29,9 +29,15 @@ class Keyframe:
self.seconds = frame / bpy.context.scene.render.fps
self.frame = frame
self.fps = bpy.context.scene.render.fps
+ self.__length_morph = 0
+ # Note: channels has some None items only for SK if some SK are not animated
if bake_channel is None:
- self.target = channels[0].data_path.split('.')[-1]
- self.__indices = [c.array_index for c in channels]
+ self.target = [c for c in channels if c is not None][0].data_path.split('.')[-1]
+ if self.target != "value":
+ self.__indices = [c.array_index for c in channels]
+ else:
+ self.__indices = [i for i, c in enumerate(channels) if c is not None]
+ self.__length_morph = len(channels)
else:
self.target = bake_channel
self.__indices = []
@@ -53,7 +59,7 @@ class Keyframe:
"rotation_euler": 3,
"rotation_quaternion": 4,
"scale": 3,
- "value": 1
+ "value": self.__length_morph
}.get(self.target)
if length is None:
@@ -62,17 +68,18 @@ class Keyframe:
return length
def __set_indexed(self, value):
- # 'value' targets don't use keyframe.array_index
- if self.target == "value":
- return value
# Sometimes blender animations only reference a subset of components of a data target. Keyframe should always
# contain a complete Vector/ Quaternion --> use the array_index value of the keyframe to set components in such
# structures
+ # For SK, must contains all SK values
result = [0.0] * self.get_target_len()
for i, v in zip(self.__indices, value):
result[i] = v
- result = gltf2_blender_math.list_to_mathutils(result, self.target)
- return result
+ if self.target == "value":
+ return result
+ else:
+ result = gltf2_blender_math.list_to_mathutils(result, self.target)
+ return result
def get_indices(self):
return self.__indices
@@ -164,10 +171,11 @@ def gather_keyframes(blender_object_if_armature: typing.Optional[bpy.types.Objec
"""Convert the blender action groups' fcurves to keyframes for use in glTF."""
if bake_bone is None:
# Find the start and end of the whole action group
- ranges = [channel.range() for channel in channels]
+ # Note: channels has some None items only for SK if some SK are not animated
+ ranges = [channel.range() for channel in channels if channel is not None]
- start_frame = min([channel.range()[0] for channel in channels])
- end_frame = max([channel.range()[1] for channel in channels])
+ start_frame = min([channel.range()[0] for channel in channels if channel is not None])
+ end_frame = max([channel.range()[1] for channel in channels if channel is not None])
else:
start_frame = bake_range_start
end_frame = bake_range_end
@@ -218,25 +226,27 @@ def gather_keyframes(blender_object_if_armature: typing.Optional[bpy.types.Objec
"scale": scale
}[target_property]
else:
- key.value = [c.evaluate(frame) for c in channels]
+ # Note: channels has some None items only for SK if some SK are not animated
+ key.value = [c.evaluate(frame) for c in channels if c is not None]
complete_key(key, non_keyed_values)
keyframes.append(key)
frame += step
else:
# Just use the keyframes as they are specified in blender
- frames = [keyframe.co[0] for keyframe in channels[0].keyframe_points]
+ # Note: channels has some None items only for SK if some SK are not animated
+ frames = [keyframe.co[0] for keyframe in [c for c in channels if c is not None][0].keyframe_points]
# some weird files have duplicate frame at same time, removed them
frames = sorted(set(frames))
for i, frame in enumerate(frames):
key = Keyframe(channels, frame, bake_channel)
# key.value = [c.keyframe_points[i].co[0] for c in action_group.channels]
- key.value = [c.evaluate(frame) for c in channels]
+ key.value = [c.evaluate(frame) for c in channels if c is not None]
# Complete key with non keyed values, if needed
- if len(channels) != key.get_target_len():
+ if len([c for c in channels if c is not None]) != key.get_target_len():
complete_key(key, non_keyed_values)
# compute tangents for cubic spline interpolation
- if channels[0].keyframe_points[0].interpolation == "BEZIER":
+ if [c for c in channels i
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list