def plusx_cylinder_unwrap(part):
    """
    Rotate the part from +X to face -Z, cylinder project it, then rotate it back

    WARNING: The cylinder projection operation is VERY particular about the 'context' being right
    """

    if len(part.data.vertices) == 0:
        return

    bpy.context.view_layer.objects.active = part
    butil.select(part)

    orig = part.rotation_euler.copy()

    # translate to pointing upwards
    part.rotation_euler = (0, np.pi / 2, 0)
    bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)

    bpy.ops.object.mode_set(mode="EDIT")
    bpy.ops.mesh.select_all(action="SELECT")
    bpy.ops.uv.cylinder_project(direction="ALIGN_TO_OBJECT", correct_aspect=True)
    bpy.ops.object.mode_set(mode="OBJECT")

    # undo the rotation we just applied into th emesh
    part.rotation_euler = (0, -np.pi / 2, 0)
    bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)

    # back to normal
    part.rotation_euler = orig

    Rotate the part from +X to face -Z, cylinder project it, then rotate it back

    WARNING: The cylinder projection operation is VERY particular about the 'context' being right
    
infinigen/assets/utils/geometry/metaballs.py