2019年1月19日土曜日

How to change the scale my Blender assets

How to scale the model 100 times
1. Off the auto key.
2. Snap the cursor to center(Shift+s)
3. Set Pivot to 3d cursor.
4. Select the armature in object mode.
5. Scale the armature(s+100).
6. Select the IKTargets.
7. Open graph editer.
8. Set 2d cursor to 0
9. Set Pivot to 2d cursor.
10. Show location key only(input "loc" in the search window).
11. Select all key frames.
12. Scale the keys y direction(s+y+100)
13. Select the armature in object mode.
14. Apply Scale.(Here the animation will be broken.)
15. Select all bones in pose mode.
16. Show location key only(Enter "loc" at the magnifying glass mark in the graph editor.).
17. Select all key frames.
18. Scale the keys y direction(s+y+100)

Or use the following script(ArmatureAndIKScaleChange.py):

import bpy

# Set the desired scaling factor
scale_factor = 100  # Change this to any scale multiplier you want

# Get the selected Armature
armature = bpy.context.active_object
if not armature or armature.type != 'ARMATURE':
    raise ValueError("Please select an Armature object.")

# === 1. Scale the Armature and apply the scale (without affecting location/rotation) ===
armature.scale = [s * scale_factor for s in armature.scale]
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)

# === 2. Switch to Pose Mode and select all bones ===
bpy.ops.object.mode_set(mode='POSE')
for bone in armature.pose.bones:
    bone.bone.select = True

# === 3. Rescale all location keyframes of all pose bones ===
def rescale_pose_bone_keyframes(armature, scale):
    action = armature.animation_data.action
    if not action:
        return
    for pb in armature.pose.bones:
        keyframe_data = {0: [], 1: [], 2: []}
        for axis in range(3):
            path = f'pose.bones["{pb.name}"].location'
            fcurve = next((fc for fc in action.fcurves if fc.data_path == path and fc.array_index == axis), None)
            if fcurve:
                for key in fcurve.keyframe_points:
                    keyframe_data[axis].append((int(key.co.x), key.co.y * scale))
                action.fcurves.remove(fcurve)
        for axis in range(3):
            for frame, value in keyframe_data[axis]:
                pb.location[axis] = value
                pb.keyframe_insert(data_path="location", index=axis, frame=frame)

# === 4. Get all IK target objects used in IK constraints ===
def get_ik_targets(arm):
    targets = set()
    for pb in arm.pose.bones:
        for c in pb.constraints:
            if c.type == 'IK' and c.target:
                targets.add(c.target)
    return list(targets)

# === 5. Rescale location keyframes of the IK target objects ===
def rescale_and_rekey_location(obj, scale):
    if not obj.animation_data or not obj.animation_data.action:
        return
    action = obj.animation_data.action
    keyframe_data = {0: [], 1: [], 2: []}
    for axis in range(3):
        path = f'location'
        fcurve = next((fc for fc in action.fcurves if fc.data_path == path and fc.array_index == axis), None)
        if fcurve:
            for key in fcurve.keyframe_points:
                keyframe_data[axis].append((int(key.co.x), key.co.y * scale))
            action.fcurves.remove(fcurve)
    for axis in range(3):
        for frame, value in keyframe_data[axis]:
            obj.location[axis] = value
            obj.keyframe_insert(data_path="location", index=axis, frame=frame)

# === 6. Execute keyframe rescaling ===
rescale_pose_bone_keyframes(armature, scale_factor)
for target in get_ik_targets(armature):
    rescale_and_rekey_location(target, scale_factor)

# === 7. Return to Object Mode ===
bpy.ops.object.mode_set(mode='OBJECT')


0 件のコメント:

コメントを投稿