Export_3ds: Improved distance cue node search
[blender-addons.git] / io_scene_gltf2 / blender / imp / gltf2_blender_animation_weight.py
blobeb7ac34d7eaea7675da46b946e0419aaff3d57f3
1 # SPDX-FileCopyrightText: 2018-2021 The glTF-Blender-IO authors
3 # SPDX-License-Identifier: Apache-2.0
5 import bpy
7 from ...io.imp.gltf2_io_user_extensions import import_user_extensions
8 from ...io.imp.gltf2_io_binary import BinaryData
9 from .gltf2_blender_animation_utils import make_fcurve
12 class BlenderWeightAnim():
13 """Blender ShapeKey Animation."""
14 def __new__(cls, *args, **kwargs):
15 raise RuntimeError("%s should not be instantiated" % cls)
17 @staticmethod
18 def anim(gltf, anim_idx, vnode_id):
19 """Manage animation."""
20 vnode = gltf.vnodes[vnode_id]
22 node_idx = vnode.mesh_node_idx
24 import_user_extensions('gather_import_animation_weight_before_hook', gltf, vnode, gltf.data.animations[anim_idx])
26 if node_idx is None:
27 return
29 node = gltf.data.nodes[node_idx]
30 obj = vnode.blender_object
31 fps = (bpy.context.scene.render.fps * bpy.context.scene.render.fps_base)
33 animation = gltf.data.animations[anim_idx]
35 if anim_idx not in node.animations.keys():
36 return
38 for channel_idx in node.animations[anim_idx]:
39 channel = animation.channels[channel_idx]
40 if channel.target.path == "weights":
41 break
42 if channel.target.path == "pointer":
43 pointer_tab = channel.target.extensions["KHR_animation_pointer"]["pointer"].split("/")
44 if len(pointer_tab) >= 4 and pointer_tab[1] in ["nodes", "meshes"] and pointer_tab[3] == "weights":
45 break
46 else:
47 return
49 name = animation.track_name + "_" + obj.name
50 action = bpy.data.actions.new(name)
51 action.id_root = "KEY"
52 gltf.needs_stash.append((obj.data.shape_keys, action))
54 keys = BinaryData.get_data_from_accessor(gltf, animation.samplers[channel.sampler].input)
55 values = BinaryData.get_data_from_accessor(gltf, animation.samplers[channel.sampler].output)
57 # retrieve number of targets
58 pymesh = gltf.data.meshes[gltf.data.nodes[node_idx].mesh]
59 nb_targets = len(pymesh.shapekey_names)
61 if animation.samplers[channel.sampler].interpolation == "CUBICSPLINE":
62 offset = nb_targets
63 stride = 3 * nb_targets
64 else:
65 offset = 0
66 stride = nb_targets
68 coords = [0] * (2 * len(keys))
69 coords[::2] = (key[0] * fps for key in keys)
71 for sk in range(nb_targets):
72 if pymesh.shapekey_names[sk] is not None: # Do not animate shapekeys not created
73 coords[1::2] = (values[offset + stride * i + sk][0] for i in range(len(keys)))
74 kb_name = pymesh.shapekey_names[sk]
75 data_path = 'key_blocks["%s"].value' % bpy.utils.escape_identifier(kb_name)
77 make_fcurve(
78 action,
79 coords,
80 data_path=data_path,
81 group_name="ShapeKeys",
82 interpolation=animation.samplers[channel.sampler].interpolation,
85 # Expand weight range if needed
86 kb = obj.data.shape_keys.key_blocks[kb_name]
87 min_weight = min(coords[1:2])
88 max_weight = max(coords[1:2])
89 if min_weight < kb.slider_min: kb.slider_min = min_weight
90 if max_weight > kb.slider_max: kb.slider_max = max_weight
92 import_user_extensions('gather_import_animation_weight_after_hook', gltf, vnode, animation)