Welcome to mirror list, hosted at ThFree Co, Russian Federation.

keyingsets_utils.py « keyingsets « scripts « release - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 77b0f3ebacdbe360be478ac6933bdb8ab11a9e63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# This file defines a set of methods that are useful for various 
# Relative Keying Set (RKS) related operations, such as: callbacks
# for polling, iterator callbacks, and also generate callbacks. 
# All of these can be used in conjunction with the others. 

import bpy

###########################
# General Utilities

# Append the specified property name on the the existing path
def path_add_property(path, prop):
    if len(path):
        return path + "." + prop;
    else:
        return prop;

###########################
# Poll Callbacks

# selected objects
def RKS_POLL_selected_objects(ksi, context):
    return context.active_object or len(context.selected_objects);
    
# selected bones
def RKS_POLL_selected_bones(ksi, context):
    # we must be in Pose Mode, and there must be some bones selected 
    if (context.active_object) and (context.active_object.mode == 'POSE'):
        if context.active_pose_bone or len(context.selected_pose_bones):
            return True;
    
    # nothing selected 
    return False;


# selected bones or objects
def RKS_POLL_selected_items(ksi, context):
    return RKS_POLL_selected_bones(ksi, context) or RKS_POLL_selected_objects(ksi, context);

###########################
# Iterator Callbacks

# all selected objects or pose bones, depending on which we've got
def RKS_ITER_selected_item(ksi, context, ks):
    if (context.active_object) and (context.active_object.mode == 'POSE'):
        for bone in context.selected_pose_bones:
            ksi.generate(context, ks, bone)
    else:
        for ob in context.selected_objects:
            ksi.generate(context, ks, ob)

###########################
# Generate Callbacks

# 'Available' F-Curves
def RKS_GEN_available(ksi, context, ks, data):
    # try to get the animation data associated with the closest 
    # ID-block to the data (neither of which may exist/be easy to find)
    id_block = data.id_data
    adt = getattr(id_block, "animation_data", None)

    # there must also be an active action...
    if adt is None or adt.action is None:
        return;
        
    # for each F-Curve, include an path to key it
    # NOTE: we don't need to set the group settings here
    for fcu in adt.action.fcurves:
        ks.paths.add(id_block, fcu.data_path, index=fcu.array_index)
    
# ------

# get ID block and based ID path for transform generators
def get_transform_generators_base_info(data):
    # ID-block for the data 
    id_block = data.id_data
    
    # get base path and grouping method/name
    if isinstance(data, bpy.types.ID):
        # no path in this case
        path = ""
        
        # data on ID-blocks directly should get grouped by the KeyingSet
        grouping = None
    else:
        # get the path to the ID-block
        path = data.path_from_id()

        # try to use the name of the data element to group the F-Curve
        # else fallback on the KeyingSet name
        grouping = getattr(data, "name", None)
        
    # return the ID-block and the path
    return id_block, path, grouping

# Location 
def RKS_GEN_location(ksi, context, ks, data):
    # get id-block and path info
    id_block, base_path, grouping= get_transform_generators_base_info(data)
    
    # add the property name to the base path
    path = path_add_property(base_path, "location")
    
    # add Keying Set entry for this...
    if grouping:
        ks.paths.add(id_block, path, grouping_method='NAMED', group_name=grouping)
    else:
        ks.paths.add(id_block, path)

# Rotation 
def RKS_GEN_rotation(ksi, context, ks, data):
    # get id-block and path info
    id_block, base_path, grouping= get_transform_generators_base_info(data)
    
    # add the property name to the base path
    #   rotation mode affects the property used
    if data.rotation_mode == 'QUATERNION':
        path = path_add_property(base_path, "rotation_quaternion")
    elif data.rotation_mode == 'AXISANGLE':
        path = path_add_property(base_path, "rotation_axis_angle")
    else:
        path = path_add_property(base_path, "rotation_euler")
    
    # add Keying Set entry for this...
    if grouping:
        ks.paths.add(id_block, path, grouping_method='NAMED', group_name=grouping)
    else:
        ks.paths.add(id_block, path)

# Scaling 
def RKS_GEN_scaling(ksi, context, ks, data):
    # get id-block and path info
    id_block, base_path, grouping= get_transform_generators_base_info(data)
    
    # add the property name to the base path
    path = path_add_property(base_path, "scale")
    
    # add Keying Set entry for this...
    if grouping:
        ks.paths.add(id_block, path, grouping_method='NAMED', group_name=grouping)
    else:
        ks.paths.add(id_block, path)

###########################
# Un-needed stuff which is here to just shut up the warnings...

classes = []

def register():
    register = bpy.types.register
    for cls in classes:
        register(cls)


def unregister():
    unregister = bpy.types.unregister
    for cls in classes:
        unregister(cls)

if __name__ == "__main__":
    register()

###########################