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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_operators/rigidbody.py190
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py2
2 files changed, 192 insertions, 0 deletions
diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py
new file mode 100644
index 00000000000..55a2cef4535
--- /dev/null
+++ b/release/scripts/startup/bl_operators/rigidbody.py
@@ -0,0 +1,190 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8-80 compliant>
+
+import bpy
+from bpy.types import Operator
+from bpy.props import IntProperty
+from bpy.props import EnumProperty
+
+
+class CopyRigidbodySettings(Operator):
+ '''Copy Rigid Body settings from active object to selected'''
+ bl_idname = "rigidbody.object_settings_copy"
+ bl_label = "Copy Rigidbody Settings"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ obj = bpy.context.object
+ return (obj and obj.rigid_body)
+
+ def execute(self, context):
+ obj = context.object
+ scn = context.scene
+
+ # deselect all but mesh objects
+ for o in context.selected_objects:
+ if o.type != 'MESH':
+ o.select = False
+
+ sel = context.selected_objects
+ if sel:
+ # add selected objects to active one groups and recalculate
+ bpy.ops.group.objects_add_active()
+ scn.frame_set(scn.frame_current)
+
+ # copy settings
+ for o in sel:
+ if o.rigid_body is None:
+ continue
+
+ o.rigid_body.type = obj.rigid_body.type
+ o.rigid_body.kinematic = obj.rigid_body.kinematic
+ o.rigid_body.mass = obj.rigid_body.mass
+ o.rigid_body.collision_shape = obj.rigid_body.collision_shape
+ o.rigid_body.use_margin = obj.rigid_body.use_margin
+ o.rigid_body.collision_margin = obj.rigid_body.collision_margin
+ o.rigid_body.friction = obj.rigid_body.friction
+ o.rigid_body.restitution = obj.rigid_body.restitution
+ o.rigid_body.use_deactivation = obj.rigid_body.use_deactivation
+ o.rigid_body.start_deactivated = obj.rigid_body.start_deactivated
+ o.rigid_body.deactivate_linear_velocity = obj.rigid_body.deactivate_linear_velocity
+ o.rigid_body.deactivate_angular_velocity = obj.rigid_body.deactivate_angular_velocity
+ o.rigid_body.linear_damping = obj.rigid_body.linear_damping
+ o.rigid_body.angular_damping = obj.rigid_body.angular_damping
+ o.rigid_body.collision_groups = obj.rigid_body.collision_groups
+
+ return {'FINISHED'}
+
+
+class BakeToKeyframes(Operator):
+ '''Bake rigid body transformations of selected objects to keyframes'''
+ bl_idname = "rigidbody.bake_to_keyframes"
+ bl_label = "Bake To Keyframes"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ frame_start = IntProperty(
+ name="Start Frame",
+ description="Start frame for baking",
+ min=0, max=300000,
+ default=1,
+ )
+ frame_end = IntProperty(
+ name="End Frame",
+ description="End frame for baking",
+ min=1, max=300000,
+ default=250,
+ )
+ step = IntProperty(
+ name="Frame Step",
+ description="Frame Step",
+ min=1, max=120,
+ default=1,
+ )
+
+ @classmethod
+ def poll(cls, context):
+ obj = bpy.context.object
+ return (obj and obj.rigid_body)
+
+ def execute(self, context):
+ bake = []
+ objs = []
+ scene = bpy.context.scene
+ frame_orig = scene.frame_current
+ frames = list(range(self.frame_start, self.frame_end + 1, self.step))
+
+ # filter objects selection
+ for ob in bpy.context.selected_objects:
+ if not ob.rigid_body or ob.rigid_body.type != 'ACTIVE':
+ ob.select = False
+
+ objs = bpy.context.selected_objects
+
+ if objs:
+ # store transformation data
+ for f in list(range(self.frame_start, self.frame_end + 1)):
+ scene.frame_set(f)
+ if f in frames:
+ mat = {}
+ for i, ob in enumerate(objs):
+ mat[i] = ob.matrix_world.copy()
+ bake.append(mat)
+
+ # apply transformations as keyframes
+ for i, f in enumerate(frames):
+ scene.frame_set(f)
+ ob_prev = objs[0]
+ for j, ob in enumerate(objs):
+ mat = bake[i][j]
+
+ ob.location = mat.to_translation()
+
+ rot_mode = ob.rotation_mode
+ if rot_mode == 'QUATERNION':
+ ob.rotation_quaternion = mat.to_quaternion()
+ elif rot_mode == 'AXIS_ANGLE':
+ # this is a little roundabout but there's no better way right now
+ aa = mat.to_quaternion().to_axis_angle()
+ ob.rotation_axis_angle = (aa[1], ) + aa[0][:]
+ else: # euler
+ # make sure euler rotation is compatible to previous frame
+ ob.rotation_euler = mat.to_euler(rot_mode, ob_prev.rotation_euler)
+
+ ob_prev = ob
+
+ bpy.ops.anim.keyframe_insert(type='BUILTIN_KSI_LocRot', confirm_success=False)
+
+ # remove baked objects from simulation
+ bpy.ops.rigidbody.objects_remove()
+
+ # clean up keyframes
+ for ob in objs:
+ action = ob.animation_data.action
+ for fcu in action.fcurves:
+ keyframe_points = fcu.keyframe_points
+ i = 1
+ # remove unneeded keyframes
+ while i < len(keyframe_points) - 1:
+ val_prev = keyframe_points[i - 1].co[1]
+ val_next = keyframe_points[i + 1].co[1]
+ val = keyframe_points[i].co[1]
+
+ if abs(val - val_prev) + abs(val - val_next) < 0.0001:
+ keyframe_points.remove(keyframe_points[i])
+ else:
+ i += 1
+ # use linear interpolation for better visual results
+ for keyframe in keyframe_points:
+ keyframe.interpolation = 'LINEAR'
+
+ # return to the frame we started on
+ scene.frame_set(frame_orig)
+
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ scene = context.scene
+ self.frame_start = scene.frame_start
+ self.frame_end = scene.frame_end
+
+ wm = context.window_manager
+ return wm.invoke_props_dialog(self)
+
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 2df156abd55..ba9b32310b2 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -131,6 +131,8 @@ class VIEW3D_PT_tools_rigidbody(View3DPanel, Panel):
col.label(text="Object Tools:")
col.operator("rigidbody.shape_change", text="Change Shape")
col.operator("rigidbody.mass_calculate", text="Calculate Mass")
+ col.operator("rigidbody.object_settings_copy", text="Copy from Active")
+ col.operator("rigidbody.bake_to_keyframes", text="Bake To Keyframes")
# ********** default tools for editmode_mesh ****************