0
$\begingroup$

First of all, excuse me as I'm not really a programmer, so probably this is a super easy question...

I'm trying to scale the location of fcurves to 0.01 of both my current Armature and all my Actions.

I tried using AI to create a script and it works... BUT it also shortens my animations (probably because it scales in the X axis too?) I tried to fix it but I just break my animations.

I'm trying (I think) to scale only the Y axis, using 0 as a pivot point.

This is the script:

import bpy

# Set the scale factor
scale_factor = 0.01

# Find the armature by its name
armature = bpy.data.objects.get("Armature")

if armature:
    # Select the armature
    bpy.ops.object.select_all(action='DESELECT')
    armature.select_set(True)
    bpy.context.view_layer.objects.active = armature

    # Scale down the location fcurves of the selected armature
    for action in bpy.data.actions:
        for fcurve in action.fcurves:
            if fcurve.data_path.endswith("location"):
                for keyframe_point in fcurve.keyframe_points:
                    keyframe_point.co[1] *= scale_factor

    # Update the frame range to reflect the scaled animation
    for action in bpy.data.actions:
        for fcurve in action.fcurves:
            for keyframe_point in fcurve.keyframe_points:
                keyframe_point.co[0] *= scale_factor

    # Update the timeline and redraw the viewport
    bpy.context.scene.frame_start = int(bpy.context.scene.frame_start * scale_factor)
    bpy.context.scene.frame_end = int(bpy.context.scene.frame_end * scale_factor)
    bpy.context.scene.frame_current = int(bpy.context.scene.frame_current * scale_factor)
    bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
else:
    print("Armature not found in the scene.")

I'd really, really appreciate some help in how to modify this script. I've been trying to fix this for days.

$\endgroup$
1
  • $\begingroup$ This script done by AI is rather impressive, nonetheless. I've also tried AI-created blender scripts and it does need test/debug. But I bet they're learning (I informed my BOT of the bugs and it offered an improved version!) and will become proficient. $\endgroup$
    – james_t
    Oct 28, 2023 at 17:16

2 Answers 2

0
$\begingroup$

I want to suggest another direction via the UI instead of python, as there are useful, powerful techniques. I use this technique frequently to scale along only the X or Y axis. In the Graph Editor panel (Animations workspace), I box-select the points I want to scale -- in this example I selected the Z and Y locations at frame=50 (highlighted in orange).

enter image description here

Then I hit 's' to scale (or use menu Key>>Transform>>Scale) those points:

enter image description here

When the scale status appears, I hit 'y' so that the Graph points will only scale along the y-axis:

enter image description here

The menu area replaced by status "Scale", showing that I selected "along Y" only. The cursor is replaced by "scaling gizmo" (double arrow with dashed line to midpoint of points). Here it is rather low-contrast, so I highlighted in yellow.

Then you would move your mouse left/right or up/down and you'll see the points scale, and the menu indication will change from 1.00 up or down as it scales the points.

Additionally if you scale along 'x', it will scale your selected fcurve points relative to the current frame (here at 70). I tend to often use this x-axis scaling, for example where I find a character animation is too fast or slow. Or simply move ('g' for move, instead of 's' for scale), the animation where a bone needs to animate earlier or later.

$\endgroup$
1
  • 1
    $\begingroup$ THANK YOU IT WORKED Your script seemed to work too but it wasn't 100% accurate in my case because my animations had mostly free handles (and I didn't want to bake them because I might need to edit them later) and they weren't scaled properly. The manual way of doing it worked though!! THANK YOU I learned a lot today thanks to you James. I appreciate it!! :D $\endgroup$
    – Ashley L
    Oct 27, 2023 at 18:15
0
$\begingroup$

Remove the section "# Update the frame range to reflect the scaled animation" and also the section "# Update the timeline and redraw the viewport". co[1] is the Y axis (can also be written as "co.y"). co[0] is "co.x" which is the timeline (frame number). Note how I changed co[1] to co.y. Also the last part of your script is scaling the timeline -- you also don't want this so I removed.

import bpy

# Set the scale factor
scale_factor = 0.01

# Find the armature by its name
armature = bpy.data.objects.get("Armature")

if armature:
    # Select the armature
    bpy.ops.object.select_all(action='DESELECT')
    armature.select_set(True)
    bpy.context.view_layer.objects.active = armature

    # Scale down the location fcurves of the selected armature
    for action in bpy.data.actions:
        for fcurve in action.fcurves:
            if fcurve.data_path.endswith("location"):
                for keyframe_point in fcurve.keyframe_points:
                    keyframe_point.co.y *= scale_factor
  
else:
    print("Armature not found in the scene.")
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .