keyingsets_builtins.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. # ##### BEGIN GPL LICENSE BLOCK #####
  2. #
  3. # This program is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU General Public License
  5. # as published by the Free Software Foundation; either version 2
  6. # of the License, or (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software Foundation,
  15. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. #
  17. # ##### END GPL LICENSE BLOCK #####
  18. # <pep8 compliant>
  19. """
  20. Built-In Keying Sets
  21. None of these Keying Sets should be removed, as these are needed by various parts of Blender in order for them
  22. to work correctly.
  23. Beware also about changing the order that these are defined here, since this can result in old files referring to the
  24. wrong Keying Set as the active one, potentially resulting in lost (i.e. unkeyed) animation.
  25. Note that these classes cannot be subclassed further; only direct subclasses of KeyingSetInfo
  26. are supported.
  27. """
  28. import bpy
  29. import keyingsets_utils
  30. from bpy.types import KeyingSetInfo
  31. ###############################
  32. # Built-In KeyingSets
  33. # "Defines"
  34. # Keep these in sync with those in ED_keyframing.h!
  35. ANIM_KS_LOCATION_ID = "Location"
  36. ANIM_KS_ROTATION_ID = "Rotation"
  37. ANIM_KS_SCALING_ID = "Scaling"
  38. ANIM_KS_LOC_ROT_SCALE_ID = "LocRotScale"
  39. ANIM_KS_AVAILABLE_ID = "Available"
  40. ANIM_KS_WHOLE_CHARACTER_ID = "WholeCharacter"
  41. ANIM_KS_WHOLE_CHARACTER_SELECTED_ID = "WholeCharacterSelected"
  42. # Location
  43. class BUILTIN_KSI_Location(KeyingSetInfo):
  44. """Insert a keyframe on each of the location channels"""
  45. bl_idname = ANIM_KS_LOCATION_ID
  46. bl_label = "Location"
  47. # poll - use predefined callback for selected bones/objects
  48. poll = keyingsets_utils.RKS_POLL_selected_items
  49. # iterator - use callback for selected bones/objects
  50. iterator = keyingsets_utils.RKS_ITER_selected_item
  51. # generator - use callback for location
  52. generate = keyingsets_utils.RKS_GEN_location
  53. # Rotation
  54. class BUILTIN_KSI_Rotation(KeyingSetInfo):
  55. """Insert a keyframe on each of the rotation channels"""
  56. bl_idname = ANIM_KS_ROTATION_ID
  57. bl_label = "Rotation"
  58. # poll - use predefined callback for selected bones/objects
  59. poll = keyingsets_utils.RKS_POLL_selected_items
  60. # iterator - use callback for selected bones/objects
  61. iterator = keyingsets_utils.RKS_ITER_selected_item
  62. # generator - use callback for rotation
  63. generate = keyingsets_utils.RKS_GEN_rotation
  64. # Scale
  65. class BUILTIN_KSI_Scaling(KeyingSetInfo):
  66. """Insert a keyframe on each of the scale channels"""
  67. bl_idname = ANIM_KS_SCALING_ID
  68. bl_label = "Scaling"
  69. # poll - use predefined callback for selected bones/objects
  70. poll = keyingsets_utils.RKS_POLL_selected_items
  71. # iterator - use callback for selected bones/objects
  72. iterator = keyingsets_utils.RKS_ITER_selected_item
  73. # generator - use callback for scaling
  74. generate = keyingsets_utils.RKS_GEN_scaling
  75. # ------------
  76. # LocRot
  77. class BUILTIN_KSI_LocRot(KeyingSetInfo):
  78. """Insert a keyframe on each of the location and rotation channels"""
  79. bl_label = "LocRot"
  80. # poll - use predefined callback for selected bones/objects
  81. poll = keyingsets_utils.RKS_POLL_selected_items
  82. # iterator - use callback for selected bones/objects
  83. iterator = keyingsets_utils.RKS_ITER_selected_item
  84. # generator
  85. def generate(self, context, ks, data):
  86. # location
  87. keyingsets_utils.RKS_GEN_location(self, context, ks, data)
  88. # rotation
  89. keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
  90. # LocScale
  91. class BUILTIN_KSI_LocScale(KeyingSetInfo):
  92. """Insert a keyframe on each of the location and scale channels"""
  93. bl_label = "LocScale"
  94. # poll - use predefined callback for selected bones/objects
  95. poll = keyingsets_utils.RKS_POLL_selected_items
  96. # iterator - use callback for selected bones/objects
  97. iterator = keyingsets_utils.RKS_ITER_selected_item
  98. # generator
  99. def generate(self, context, ks, data):
  100. # location
  101. keyingsets_utils.RKS_GEN_location(self, context, ks, data)
  102. # scale
  103. keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
  104. # LocRotScale
  105. class BUILTIN_KSI_LocRotScale(KeyingSetInfo):
  106. """Insert a keyframe on each of the location, rotation, and scale channels"""
  107. bl_idname = ANIM_KS_LOC_ROT_SCALE_ID
  108. bl_label = "LocRotScale"
  109. # poll - use predefined callback for selected bones/objects
  110. poll = keyingsets_utils.RKS_POLL_selected_items
  111. # iterator - use callback for selected bones/objects
  112. iterator = keyingsets_utils.RKS_ITER_selected_item
  113. # generator
  114. def generate(self, context, ks, data):
  115. # location
  116. keyingsets_utils.RKS_GEN_location(self, context, ks, data)
  117. # rotation
  118. keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
  119. # scale
  120. keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
  121. # RotScale
  122. class BUILTIN_KSI_RotScale(KeyingSetInfo):
  123. """Insert a keyframe on each of the rotation and scale channels"""
  124. bl_label = "RotScale"
  125. # poll - use predefined callback for selected bones/objects
  126. poll = keyingsets_utils.RKS_POLL_selected_items
  127. # iterator - use callback for selected bones/objects
  128. iterator = keyingsets_utils.RKS_ITER_selected_item
  129. # generator
  130. def generate(self, context, ks, data):
  131. # rotation
  132. keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
  133. # scaling
  134. keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
  135. # ------------
  136. # Bendy Bones
  137. class BUILTIN_KSI_BendyBones(KeyingSetInfo):
  138. """Insert a keyframe for each of the BBone shape properties"""
  139. bl_label = "BBone Shape"
  140. # poll - use callback for selected bones
  141. poll = keyingsets_utils.RKS_POLL_selected_bones
  142. # iterator - use callback for selected bones
  143. iterator = keyingsets_utils.RKS_ITER_selected_bones
  144. # generator - use generator for bendy bone properties
  145. generate = keyingsets_utils.RKS_GEN_bendy_bones
  146. # ------------
  147. # VisualLocation
  148. class BUILTIN_KSI_VisualLoc(KeyingSetInfo):
  149. """Insert a keyframe on each of the location channels, taking into account effects of constraints """
  150. """and relationships"""
  151. bl_label = "Visual Location"
  152. bl_options = {'INSERTKEY_VISUAL'}
  153. # poll - use predefined callback for selected bones/objects
  154. poll = keyingsets_utils.RKS_POLL_selected_items
  155. # iterator - use callback for selected bones/objects
  156. iterator = keyingsets_utils.RKS_ITER_selected_item
  157. # generator - use callback for location
  158. generate = keyingsets_utils.RKS_GEN_location
  159. # VisualRotation
  160. class BUILTIN_KSI_VisualRot(KeyingSetInfo):
  161. """Insert a keyframe on each of the rotation channels, taking into account effects of constraints """
  162. """and relationships"""
  163. bl_label = "Visual Rotation"
  164. bl_options = {'INSERTKEY_VISUAL'}
  165. # poll - use predefined callback for selected bones/objects
  166. poll = keyingsets_utils.RKS_POLL_selected_items
  167. # iterator - use callback for selected bones/objects
  168. iterator = keyingsets_utils.RKS_ITER_selected_item
  169. # generator - use callback for rotation
  170. generate = keyingsets_utils.RKS_GEN_rotation
  171. # VisualScaling
  172. class BUILTIN_KSI_VisualScaling(KeyingSetInfo):
  173. """Insert a keyframe on each of the scale channels, taking into account effects of constraints """
  174. """and relationships"""
  175. bl_label = "Visual Scaling"
  176. bl_options = {'INSERTKEY_VISUAL'}
  177. # poll - use predefined callback for selected bones/objects
  178. poll = keyingsets_utils.RKS_POLL_selected_items
  179. # iterator - use callback for selected bones/objects
  180. iterator = keyingsets_utils.RKS_ITER_selected_item
  181. # generator - use callback for location
  182. generate = keyingsets_utils.RKS_GEN_scaling
  183. # VisualLocRot
  184. class BUILTIN_KSI_VisualLocRot(KeyingSetInfo):
  185. """Insert a keyframe on each of the location and rotation channels, taking into account effects of constraints """
  186. """and relationships"""
  187. bl_label = "Visual LocRot"
  188. bl_options = {'INSERTKEY_VISUAL'}
  189. # poll - use predefined callback for selected bones/objects
  190. poll = keyingsets_utils.RKS_POLL_selected_items
  191. # iterator - use callback for selected bones/objects
  192. iterator = keyingsets_utils.RKS_ITER_selected_item
  193. # generator
  194. def generate(self, context, ks, data):
  195. # location
  196. keyingsets_utils.RKS_GEN_location(self, context, ks, data)
  197. # rotation
  198. keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
  199. # VisualLocScale
  200. class BUILTIN_KSI_VisualLocScale(KeyingSetInfo):
  201. """Insert a keyframe on each of the location and scaling channels, taking into account effects of constraints """
  202. """and relationships"""
  203. bl_label = "Visual LocScale"
  204. bl_options = {'INSERTKEY_VISUAL'}
  205. # poll - use predefined callback for selected bones/objects
  206. poll = keyingsets_utils.RKS_POLL_selected_items
  207. # iterator - use callback for selected bones/objects
  208. iterator = keyingsets_utils.RKS_ITER_selected_item
  209. # generator
  210. def generate(self, context, ks, data):
  211. # location
  212. keyingsets_utils.RKS_GEN_location(self, context, ks, data)
  213. # scaling
  214. keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
  215. # VisualLocRotScale
  216. class BUILTIN_KSI_VisualLocRotScale(KeyingSetInfo):
  217. """Insert a keyframe on each of the location, rotation and scaling channels, taking into account effects """
  218. """of constraints and relationships"""
  219. bl_label = "Visual LocRotScale"
  220. bl_options = {'INSERTKEY_VISUAL'}
  221. # poll - use predefined callback for selected bones/objects
  222. poll = keyingsets_utils.RKS_POLL_selected_items
  223. # iterator - use callback for selected bones/objects
  224. iterator = keyingsets_utils.RKS_ITER_selected_item
  225. # generator
  226. def generate(self, context, ks, data):
  227. # location
  228. keyingsets_utils.RKS_GEN_location(self, context, ks, data)
  229. # rotation
  230. keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
  231. # scaling
  232. keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
  233. # VisualRotScale
  234. class BUILTIN_KSI_VisualRotScale(KeyingSetInfo):
  235. """Insert a keyframe on each of the rotation and scaling channels, taking into account effects of constraints """
  236. """and relationships"""
  237. bl_label = "Visual RotScale"
  238. bl_options = {'INSERTKEY_VISUAL'}
  239. # poll - use predefined callback for selected bones/objects
  240. poll = keyingsets_utils.RKS_POLL_selected_items
  241. # iterator - use callback for selected bones/objects
  242. iterator = keyingsets_utils.RKS_ITER_selected_item
  243. # generator
  244. def generate(self, context, ks, data):
  245. # rotation
  246. keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
  247. # scaling
  248. keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
  249. # ------------
  250. # Available
  251. class BUILTIN_KSI_Available(KeyingSetInfo):
  252. """Insert a keyframe on each of the already existing F-Curves"""
  253. bl_idname = ANIM_KS_AVAILABLE_ID
  254. bl_label = "Available"
  255. # poll - selected objects or selected object with animation data
  256. def poll(ksi, context):
  257. ob = context.active_object
  258. if ob:
  259. # TODO: this fails if one animation-less object is active, but many others are selected
  260. return ob.animation_data and ob.animation_data.action
  261. else:
  262. return bool(context.selected_objects)
  263. # iterator - use callback for selected bones/objects
  264. iterator = keyingsets_utils.RKS_ITER_selected_item
  265. # generator - use callback for doing this
  266. generate = keyingsets_utils.RKS_GEN_available
  267. ###############################
  268. # All properties that are likely to get animated in a character rig
  269. class BUILTIN_KSI_WholeCharacter(KeyingSetInfo):
  270. """Insert a keyframe for all properties that are likely to get animated in a character rig """
  271. """(useful when blocking out a shot)"""
  272. bl_idname = ANIM_KS_WHOLE_CHARACTER_ID
  273. bl_label = "Whole Character"
  274. # these prefixes should be avoided, as they are not really bones
  275. # that animators should be touching (or need to touch)
  276. badBonePrefixes = (
  277. 'DEF',
  278. 'GEO',
  279. 'MCH',
  280. 'ORG',
  281. 'COR',
  282. 'VIS',
  283. # ... more can be added here as you need in your own rigs ...
  284. )
  285. # poll - pose-mode on active object only
  286. def poll(ksi, context):
  287. return ((context.active_object) and (context.active_object.pose) and
  288. (context.active_object.mode == 'POSE'))
  289. # iterator - all bones regardless of selection
  290. def iterator(ksi, context, ks):
  291. for bone in context.active_object.pose.bones:
  292. if not bone.name.startswith(BUILTIN_KSI_WholeCharacter.badBonePrefixes):
  293. ksi.generate(context, ks, bone)
  294. # generator - all unlocked bone transforms + custom properties
  295. def generate(ksi, context, ks, bone):
  296. # loc, rot, scale - only include unlocked ones
  297. if not bone.bone.use_connect:
  298. ksi.doLoc(ks, bone)
  299. if bone.rotation_mode in {'QUATERNION', 'AXIS_ANGLE'}:
  300. ksi.doRot4d(ks, bone)
  301. else:
  302. ksi.doRot3d(ks, bone)
  303. ksi.doScale(ks, bone)
  304. # bbone properties?
  305. ksi.doBBone(context, ks, bone)
  306. # custom props?
  307. ksi.doCustomProps(ks, bone)
  308. # ----------------
  309. # helper to add some bone's property to the Keying Set
  310. def addProp(ksi, ks, bone, prop, index=-1, use_groups=True):
  311. # add the property name to the base path
  312. id_path = bone.path_from_id()
  313. id_block = bone.id_data
  314. if prop.startswith('['):
  315. # custom properties
  316. path = id_path + prop
  317. else:
  318. # standard transforms/properties
  319. path = keyingsets_utils.path_add_property(id_path, prop)
  320. # add Keying Set entry for this...
  321. if use_groups:
  322. ks.paths.add(id_block, path, index=index, group_method='NAMED', group_name=bone.name)
  323. else:
  324. ks.paths.add(id_block, path, index=index)
  325. # ----------------
  326. # location properties
  327. def doLoc(ksi, ks, bone):
  328. if bone.lock_location == (False, False, False):
  329. ksi.addProp(ks, bone, "location")
  330. else:
  331. for i in range(3):
  332. if not bone.lock_location[i]:
  333. ksi.addProp(ks, bone, "location", i)
  334. # rotation properties
  335. def doRot4d(ksi, ks, bone):
  336. # rotation mode affects the property used
  337. if bone.rotation_mode == 'QUATERNION':
  338. prop = "rotation_quaternion"
  339. elif bone.rotation_mode == 'AXIS_ANGLE':
  340. prop = "rotation_axis_angle"
  341. # add rotation properties if they will
  342. if bone.lock_rotations_4d:
  343. # can check individually
  344. if (bone.lock_rotation == (False, False, False)) and (bone.lock_rotation_w is False):
  345. ksi.addProp(ks, bone, prop)
  346. else:
  347. if bone.lock_rotation_w is False:
  348. ksi.addProp(ks, bone, prop, 0) # w = 0
  349. for i in range(3):
  350. if not bone.lock_rotation[i]:
  351. ksi.addProp(ks, bone, prop, i + 1) # i + 1, since here x/y/z = 1,2,3, and w=0
  352. elif True not in bone.lock_rotation:
  353. # if axis-angle rotations get locked as eulers, then it's too messy to allow anything
  354. # other than all open unless we keyframe the whole lot
  355. ksi.addProp(ks, bone, prop)
  356. def doRot3d(ksi, ks, bone):
  357. if bone.lock_rotation == (False, False, False):
  358. ksi.addProp(ks, bone, "rotation_euler")
  359. else:
  360. for i in range(3):
  361. if not bone.lock_rotation[i]:
  362. ksi.addProp(ks, bone, "rotation_euler", i)
  363. # scale properties
  364. def doScale(ksi, ks, bone):
  365. if bone.lock_scale == (0, 0, 0):
  366. ksi.addProp(ks, bone, "scale")
  367. else:
  368. for i in range(3):
  369. if not bone.lock_scale[i]:
  370. ksi.addProp(ks, bone, "scale", i)
  371. # ----------------
  372. # bendy bone properties
  373. def doBBone(ksi, context, ks, pchan):
  374. bone = pchan.bone
  375. # This check is crude, but is the best we can do for now
  376. # It simply adds all of these if the bbone has segments
  377. # (and the bone is a control bone). This may lead to some
  378. # false positives...
  379. if bone.bbone_segments > 1:
  380. keyingsets_utils.RKS_GEN_bendy_bones(ksi, context, ks, pchan)
  381. # ----------------
  382. # custom properties
  383. def doCustomProps(ksi, ks, bone):
  384. prop_type_compat = {bpy.types.BoolProperty,
  385. bpy.types.IntProperty,
  386. bpy.types.FloatProperty}
  387. # go over all custom properties for bone
  388. for prop in bone.keys():
  389. # ignore special "_RNA_UI" used for UI editing
  390. if prop == "_RNA_UI":
  391. continue
  392. # for now, just add all of 'em
  393. prop_rna = type(bone).bl_rna.properties.get(prop, None)
  394. if prop_rna is None:
  395. prop_path = '["%s"]' % prop
  396. if bone.path_resolve(prop_path, False).rna_type in prop_type_compat:
  397. ksi.addProp(ks, bone, prop_path)
  398. elif prop_rna.is_animatable:
  399. ksi.addProp(ks, bone, prop)
  400. # All properties that are likely to get animated in a character rig, only selected bones.
  401. class BUILTIN_KSI_WholeCharacterSelected(KeyingSetInfo):
  402. """Insert a keyframe for all properties that are likely to get animated in a character rig """
  403. """(only selected bones)"""
  404. bl_idname = ANIM_KS_WHOLE_CHARACTER_SELECTED_ID
  405. bl_label = "Whole Character (Selected bones only)"
  406. # iterator - all bones regardless of selection
  407. def iterator(ksi, context, ks):
  408. # Use either the selected bones, or all of them if none are selected.
  409. bones = context.selected_pose_bones_from_active_object or context.active_object.pose.bones
  410. for bone in bones:
  411. if bone.name.startswith(BUILTIN_KSI_WholeCharacter.badBonePrefixes):
  412. continue
  413. ksi.generate(context, ks, bone)
  414. # Poor man's subclassing. Blender breaks when we actually subclass BUILTIN_KSI_WholeCharacter.
  415. poll = BUILTIN_KSI_WholeCharacter.poll
  416. generate = BUILTIN_KSI_WholeCharacter.generate
  417. addProp = BUILTIN_KSI_WholeCharacter.addProp
  418. doLoc = BUILTIN_KSI_WholeCharacter.doLoc
  419. doRot4d = BUILTIN_KSI_WholeCharacter.doRot4d
  420. doRot3d = BUILTIN_KSI_WholeCharacter.doRot3d
  421. doScale = BUILTIN_KSI_WholeCharacter.doScale
  422. doBBone = BUILTIN_KSI_WholeCharacter.doBBone
  423. doCustomProps = BUILTIN_KSI_WholeCharacter.doCustomProps
  424. ###############################
  425. # Delta Location
  426. class BUILTIN_KSI_DeltaLocation(KeyingSetInfo):
  427. """Insert keyframes for additional location offset"""
  428. bl_label = "Delta Location"
  429. # poll - selected objects only (and only if active object in object mode)
  430. poll = keyingsets_utils.RKS_POLL_selected_objects
  431. # iterator - selected objects only
  432. iterator = keyingsets_utils.RKS_ITER_selected_objects
  433. # generator - delta location channels only
  434. def generate(ksi, context, ks, data):
  435. # get id-block and path info
  436. id_block, base_path, grouping = keyingsets_utils.get_transform_generators_base_info(data)
  437. # add the property name to the base path
  438. path = keyingsets_utils.path_add_property(base_path, "delta_location")
  439. # add Keying Set entry for this...
  440. if grouping:
  441. ks.paths.add(id_block, path, group_method='NAMED', group_name=grouping)
  442. else:
  443. ks.paths.add(id_block, path)
  444. # Delta Rotation
  445. class BUILTIN_KSI_DeltaRotation(KeyingSetInfo):
  446. """Insert keyframes for additional rotation offset"""
  447. bl_label = "Delta Rotation"
  448. # poll - selected objects only (and only if active object in object mode)
  449. poll = keyingsets_utils.RKS_POLL_selected_objects
  450. # iterator - selected objects only
  451. iterator = keyingsets_utils.RKS_ITER_selected_objects
  452. # generator - delta location channels only
  453. def generate(ksi, context, ks, data):
  454. # get id-block and path info
  455. id_block, base_path, grouping = keyingsets_utils.get_transform_generators_base_info(data)
  456. # add the property name to the base path
  457. # rotation mode affects the property used
  458. if data.rotation_mode == 'QUATERNION':
  459. path = keyingsets_utils.path_add_property(base_path, "delta_rotation_quaternion")
  460. elif data.rotation_mode == 'AXIS_ANGLE':
  461. # XXX: for now, this is not available yet
  462. #path = path_add_property(base_path, "delta_rotation_axis_angle")
  463. return
  464. else:
  465. path = keyingsets_utils.path_add_property(base_path, "delta_rotation_euler")
  466. # add Keying Set entry for this...
  467. if grouping:
  468. ks.paths.add(id_block, path, group_method='NAMED', group_name=grouping)
  469. else:
  470. ks.paths.add(id_block, path)
  471. # Delta Scale
  472. class BUILTIN_KSI_DeltaScale(KeyingSetInfo):
  473. """Insert keyframes for additional scaling factor"""
  474. bl_label = "Delta Scale"
  475. # poll - selected objects only (and only if active object in object mode)
  476. poll = keyingsets_utils.RKS_POLL_selected_objects
  477. # iterator - selected objects only
  478. iterator = keyingsets_utils.RKS_ITER_selected_objects
  479. # generator - delta location channels only
  480. def generate(ksi, context, ks, data):
  481. # get id-block and path info
  482. id_block, base_path, grouping = keyingsets_utils.get_transform_generators_base_info(data)
  483. # add the property name to the base path
  484. path = keyingsets_utils.path_add_property(base_path, "delta_scale")
  485. # add Keying Set entry for this...
  486. if grouping:
  487. ks.paths.add(id_block, path, group_method='NAMED', group_name=grouping)
  488. else:
  489. ks.paths.add(id_block, path)
  490. ###############################
  491. # Note that this controls order of options in 'insert keyframe' menu.
  492. # Better try to keep some logical order here beyond mere alphabetical one, also because of menu entries shortcut.
  493. # See also T51867.
  494. classes = (
  495. BUILTIN_KSI_Available,
  496. BUILTIN_KSI_Location,
  497. BUILTIN_KSI_Rotation,
  498. BUILTIN_KSI_Scaling,
  499. BUILTIN_KSI_LocRot,
  500. BUILTIN_KSI_LocRotScale,
  501. BUILTIN_KSI_LocScale,
  502. BUILTIN_KSI_RotScale,
  503. BUILTIN_KSI_DeltaLocation,
  504. BUILTIN_KSI_DeltaRotation,
  505. BUILTIN_KSI_DeltaScale,
  506. BUILTIN_KSI_VisualLoc,
  507. BUILTIN_KSI_VisualRot,
  508. BUILTIN_KSI_VisualScaling,
  509. BUILTIN_KSI_VisualLocRot,
  510. BUILTIN_KSI_VisualLocRotScale,
  511. BUILTIN_KSI_VisualLocScale,
  512. BUILTIN_KSI_VisualRotScale,
  513. BUILTIN_KSI_BendyBones,
  514. BUILTIN_KSI_WholeCharacter,
  515. BUILTIN_KSI_WholeCharacterSelected,
  516. )
  517. def register():
  518. from bpy.utils import register_class
  519. for cls in classes:
  520. register_class(cls)
  521. def unregister():
  522. from bpy.utils import unregister_class
  523. for cls in classes:
  524. unregister_class(cls)
  525. if __name__ == "__main__":
  526. register()