Skip to content

Commit f265d7d

Browse files
feat: consolidate fork fixes (#1)
* Bake operators fix By using bpy_extras.anim_utils module directly there is more control over baking actions, but the pose transform bone needs to be reset in order to correctly bake steering. The bone resetting is neccessary even for Blender 3.3. * chore: add pycharm shared settings and dictionary * feat!: blender 4 support by jiapeiLu * chore: pep8, formatting, typos, fork readme --------- Co-authored-by: Zdenek Dolezal <zdeno@polygoniq.com>
1 parent f25da07 commit f265d7d

File tree

11 files changed

+468
-241
lines changed

11 files changed

+468
-241
lines changed

.idea/.gitignore

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/inspectionProfiles/profiles_settings.xml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/rigacar.iml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
# Rigacar
2+
3+
## Fork
4+
5+
_This fork supports **Blender 4.0+** and consolidates fixes from the community while the maintainer is absent._
6+
7+
Upstream readme description below.
8+
9+
## Upstream
10+
111
Rigacar is a free addon for Blender. It is designed to fulfill the following goals:
212

313
* generate a complete rig as quickly as possible (actually few seconds) for standard car models
@@ -6,6 +16,6 @@ Rigacar is a free addon for Blender. It is designed to fulfill the following goa
616

717
Please read [full documentation](http://digicreatures.net/articles/rigacar.html) on my website.
818

9-
You can also watch the series of videotutorials:
19+
You can also watch the series of video tutorials:
1020

11-
[![Rigacar Part 1](http://img.youtube.com/vi/D3XQxA_-TzY/0.jpg)](https://www.youtube.com/watch?v=D3XQxA_-TzY&list=PLH_mmrv8SfPFiEj93RJt3sBvHCnipI9qK "Rigacar videotutorials")
21+
[![Rigacar Part 1](http://img.youtube.com/vi/D3XQxA_-TzY/0.jpg)](https://www.youtube.com/watch?v=D3XQxA_-TzY&list=PLH_mmrv8SfPFiEj93RJt3sBvHCnipI9qK "Rigacar video tutorials")

__init__.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,18 @@
2121
bl_info = {
2222
"name": "Rigacar (Generates Car Rig)",
2323
"author": "David Gayerie",
24-
"version": (7, 1),
25-
"blender": (2, 83, 0),
24+
"version": (8, 0),
25+
"blender": (4, 0, 0),
2626
"location": "View3D > Add > Armature",
2727
"description": "Adds a deformation rig for vehicules, generates animation rig and bake wheels animation.",
2828
"wiki_url": "http://digicreatures.net/articles/rigacar.html",
2929
"tracker_url": "https://github.com/digicreatures/rigacar/issues",
30-
"category": "Rigging"}
31-
30+
"category": "Rigging"
31+
}
3232

3333
if "bpy" in locals():
3434
import importlib
35+
3536
if "bake_operators" in locals():
3637
importlib.reload(bake_operators)
3738
if "car_rig" in locals():
@@ -188,15 +189,16 @@ def draw(self, context):
188189

189190

190191
def menu_entries(menu, context):
191-
menu.layout.operator(car_rig.OBJECT_OT_armatureCarDeformationRig.bl_idname, text="Car (deformation rig)", icon='AUTO')
192+
menu.layout.operator(car_rig.OBJECT_OT_armatureCarDeformationRig.bl_idname, text="Car (deformation rig)",
193+
icon='AUTO')
192194

193195

194196
classes = (
195-
RIGACAR_PT_rigProperties,
196-
RIGACAR_PT_groundSensorsProperties,
197-
RIGACAR_PT_animationRigView,
198-
RIGACAR_PT_wheelsAnimationView,
199-
RIGACAR_PT_groundSensorsView,
197+
RIGACAR_PT_rigProperties,
198+
RIGACAR_PT_groundSensorsProperties,
199+
RIGACAR_PT_animationRigView,
200+
RIGACAR_PT_wheelsAnimationView,
201+
RIGACAR_PT_groundSensorsView,
200202
)
201203

202204

bake_operators.py

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# <pep8 compliant>
2020

2121
import bpy
22+
import bpy_extras.anim_utils
2223
import mathutils
2324
import math
2425
import itertools
@@ -33,7 +34,9 @@ def wrapper(self, context, *args, **kwargs):
3334
return func(self, context, *args, **kwargs)
3435
finally:
3536
context.window.cursor_modal_restore()
37+
3638
return wrapper
39+
3740
return cursor_decorator
3841

3942

@@ -135,7 +138,7 @@ def evaluate(self, f):
135138

136139
def fix_old_steering_rotation(rig_object):
137140
"""
138-
Fix armature generated with rigacar version < 6.0
141+
Fix armature generated with Rigacar version < 6.0
139142
"""
140143
if rig_object.pose and rig_object.pose.bones:
141144
if 'MCH-Steering.rotation' in rig_object.pose.bones:
@@ -194,7 +197,8 @@ def _create_scale_evaluator(self, action, source_bone):
194197

195198
def _bake_action(self, context, *source_bones):
196199
action = context.object.animation_data.action
197-
nla_tweak_mode = context.object.animation_data.use_tweak_mode if hasattr(context.object.animation_data, 'use_tweak_mode') else False
200+
nla_tweak_mode = context.object.animation_data.use_tweak_mode if hasattr(context.object.animation_data,
201+
'use_tweak_mode') else False
198202

199203
# saving context
200204
selected_bones = [b for b in context.object.data.bones if b.select]
@@ -208,14 +212,15 @@ def _bake_action(self, context, *source_bones):
208212
source_bones_matrix_basis.append(context.object.pose.bones[source_bone.name].matrix_basis.copy())
209213
source_bone.select = True
210214

211-
# Blender 2.81 : Another hack for another bug in the bake operator
212-
# removing from the selection objects which are not the current one
213-
for obj in context.selected_objects:
214-
if obj is not context.object:
215-
obj.select_set(state=False)
216-
217-
bpy.ops.nla.bake(frame_start=self.frame_start, frame_end=self.frame_end, only_selected=True, bake_types={'POSE'}, visual_keying=True)
218-
baked_action = context.object.animation_data.action
215+
baked_action = bpy_extras.anim_utils.bake_action(
216+
context.object,
217+
action=None,
218+
frames=range(self.frame_start, self.frame_end + 1),
219+
only_selected=True,
220+
do_pose=True,
221+
do_object=False,
222+
do_visual_keying=True,
223+
)
219224

220225
# restoring context
221226
for source_bone, matrix_basis in zip(source_bones, source_bones_matrix_basis):
@@ -262,6 +267,10 @@ def _bake_wheels_rotation(self, context):
262267
bones = set(wheel_bones + brake_bones)
263268
baked_action = self._bake_action(context, *bones)
264269

270+
if baked_action is None:
271+
self.report({'WARNING'}, "Existing action failed to bake. Won't bake wheel rotation")
272+
return
273+
265274
try:
266275
for wheel_bone, brake_bone in zip(wheel_bones, brake_bones):
267276
self._bake_wheel_rotation(context, baked_action, wheel_bone, brake_bone)
@@ -302,6 +311,10 @@ def _evaluate_distance_per_frame(self, action, bone, brake_bone):
302311
def _bake_wheel_rotation(self, context, baked_action, bone, brake_bone):
303312
fc_rot = create_property_animation(context, bone.name.replace('MCH-', ''))
304313

314+
# Reset the transform of the wheel bone, otherwise baking yields wrong results
315+
pb: bpy.types.PoseBone = context.object.pose.bones[bone.name]
316+
pb.matrix_basis.identity()
317+
305318
for f, distance in self._evaluate_distance_per_frame(baked_action, bone, brake_bone):
306319
kf = fc_rot.keyframe_points.insert(f, distance)
307320
kf.interpolation = 'LINEAR'
@@ -362,10 +375,12 @@ def _evaluate_rotation_per_frame(self, action, bone_offset, bone):
362375
length_ratio = bone_offset * self.rotation_factor / projected_steering_direction
363376
steering_direction_vector *= length_ratio
364377

365-
steering_position = mathutils.geometry.distance_point_to_plane(steering_direction_vector, world_space_bone_direction_vector, world_space_bone_normal_vector)
378+
steering_position = mathutils.geometry.distance_point_to_plane(steering_direction_vector,
379+
world_space_bone_direction_vector,
380+
world_space_bone_normal_vector)
366381

367382
if previous_steering_position is not None \
368-
and abs(steering_position - previous_steering_position) < steering_threshold:
383+
and abs(steering_position - previous_steering_position) < steering_threshold:
369384
continue
370385

371386
yield f, steering_position
@@ -377,15 +392,24 @@ def _bake_steering_rotation(self, context, bone_offset, bone):
377392
clear_property_animation(context, 'Steering.rotation')
378393
fix_old_steering_rotation(context.object)
379394
fc_rot = create_property_animation(context, 'Steering.rotation')
380-
action = self._bake_action(context, bone)
395+
396+
baked_action = self._bake_action(context, bone)
397+
if baked_action is None:
398+
self.report({'WARNING'}, "Existing action failed to bake. Won't bake steering rotation")
399+
return
381400

382401
try:
383-
for f, steering_pos in self._evaluate_rotation_per_frame(action, bone_offset, bone):
402+
# Reset the transform of the steering bone, because baking action manipulates the transform
403+
# and evaluate_rotation_frame expects it at it's default position
404+
pb: bpy.types.PoseBone = context.object.pose.bones[bone.name]
405+
pb.matrix_basis.identity()
406+
407+
for f, steering_pos in self._evaluate_rotation_per_frame(baked_action, bone_offset, bone):
384408
kf = fc_rot.keyframe_points.insert(f, steering_pos)
385409
kf.type = 'JITTER'
386410
kf.interpolation = 'LINEAR'
387411
finally:
388-
bpy.data.actions.remove(action)
412+
bpy.data.actions.remove(baked_action)
389413

390414

391415
class ANIM_OT_carClearSteeringWheelsRotation(bpy.types.Operator):
@@ -394,8 +418,10 @@ class ANIM_OT_carClearSteeringWheelsRotation(bpy.types.Operator):
394418
bl_description = "Clear generated rotation for steering and wheels"
395419
bl_options = {'REGISTER', 'UNDO'}
396420

397-
clear_steering: bpy.props.BoolProperty(name="Steering", description="Clear generated animation for steering", default=True)
398-
clear_wheels: bpy.props.BoolProperty(name="Wheels", description="Clear generated animation for wheels", default=True)
421+
clear_steering: bpy.props.BoolProperty(name="Steering", description="Clear generated animation for steering",
422+
default=True)
423+
clear_wheels: bpy.props.BoolProperty(name="Wheels", description="Clear generated animation for wheels",
424+
default=True)
399425

400426
def draw(self, context):
401427
self.layout.use_property_decorate = False

0 commit comments

Comments
 (0)