Having issues with installing Gscatter 0.12.0 (Python 3.11) on Blender 5.1 (Python 3.13)

Hello, I need Gscatter to use graswald assets in Blender 5.1.

If there is a workaround of using graswald without Gscatter then that would be great?

But currently Gscatter only works in Blender 5.0, when I try to install Gscatter in Blender 5.1 then I get this error message:
“extension bl_ext.user_default.gscatter is incompatible (This Python version (3.13) isn’t compatible with (3.11))”

Can it be fixed within Blender 5.1, if not then does anyone know where to contact graswald support considering Gscatter for Blender 5.1?

Thanks.

i used ai claude.ai and give him the addon zip and the error and he give me new one for 5.1

Wow if thats true this is pretty crazy & also totally eliminated the hive market place after obtaining anything from their, just stick it into one of these & boom, free updates, not only that no more money for you developers, oh well apart from the blender devs atm i mean if they get anything, they are the only ones for now benefiting from the “donations”, so i doubt they care about this huge issue for the rest of their user base.

10/10 sounds great.

I use this code generated via Claude.ai to fix the 0.12.0 for Blender 5.1.1
Put “gscatter-0_12_0.zip” and “fix_gscatter_blender51.py” in the same folder.
Open a terminal in that folder and run:
python fix_gscatter_blender51.py

#!/usr/bin/env python3
"""
fix_gscatter_blender51.py
=========================
Fixes the Gscatter 0.12.0 addon zip so it works with Blender 5.1 (Python 3.13).

Problem:  The bundled Pillow wheels are compiled for Python 3.11 (cp311).
          Blender 5.1 ships Python 3.13, which cannot load cp311 binaries.

Fix:      1. Downloads Pillow cp313 wheels for all supported platforms.
          2. Updates blender_manifest.toml to reference the new wheels.
          3. Repacks everything as gscatter-0_12_0-blender51.zip.

Usage:
    python fix_gscatter_blender51.py [path/to/gscatter-0_12_0.zip]

    If no path is given, the script looks for gscatter-0_12_0.zip in the
    current directory.

Requirements: Python 3.8+, pip, internet access.
"""

import os
import sys
import shutil
import zipfile
import tempfile
import subprocess
import re

# ---------------------------------------------------------------------------
# Config
# ---------------------------------------------------------------------------

PILLOW_VERSION = "11.2.1"
PYTHON_TAG     = "cp313"

# Platform tags: (pip --platform value, unique suffix to find the wheel file)
PLATFORMS = [
    ("win_amd64",               "win_amd64"),
    ("win_arm64",               "win_arm64"),
    ("macosx_11_0_x86_64",     "macosx_10_13_x86_64"),
    ("macosx_11_0_arm64",      "macosx_11_0_arm64"),
    ("manylinux_2_28_x86_64",  "manylinux_2_28_x86_64"),
]

OUTPUT_ZIP = "gscatter-0_12_0-blender51.zip"

# ---------------------------------------------------------------------------

def run(cmd, **kw):
    print("  $", " ".join(cmd))
    result = subprocess.run(cmd, capture_output=True, text=True, **kw)
    if result.returncode != 0:
        print("STDOUT:", result.stdout[-2000:])
        print("STDERR:", result.stderr[-2000:])
        raise RuntimeError(f"Command failed (exit {result.returncode})")
    return result.stdout.strip()


def find_downloaded_wheel(directory, platform_suffix, used):
    """Find the wheel file for a given platform suffix, skipping already-used files."""
    for f in sorted(os.listdir(directory)):
        full = os.path.join(directory, f)
        if full in used:
            continue
        if f.lower().startswith("pillow-") and platform_suffix.lower() in f.lower():
            return full
    return None


def download_pillow_wheels(dest_dir):
    """Download Pillow cp313 wheels for all target platforms."""
    downloaded = []
    used = set()
    for pip_platform, suffix in PLATFORMS:
        print(f"\n  → Downloading Pillow {PILLOW_VERSION} for {pip_platform} ...")
        run([
            sys.executable, "-m", "pip", "download",
            f"Pillow=={PILLOW_VERSION}",
            "--only-binary=:all:",
            "--python-version=3.13",
            f"--platform={pip_platform}",
            "--no-deps",
            "-d", dest_dir,
        ])
        whl = find_downloaded_wheel(dest_dir, suffix, used)
        if whl is None:
            files = os.listdir(dest_dir)
            raise FileNotFoundError(
                f"Could not find wheel for '{suffix}' in download dir.\n"
                f"Files present: {files}"
            )
        used.add(whl)
        downloaded.append((suffix, whl))
        print(f"     ✓ {os.path.basename(whl)}")
    return downloaded


def fix_manifest(manifest_path, new_wheel_names):
    """Rewrite blender_manifest.toml with updated wheel list."""
    with open(manifest_path, "r", encoding="utf-8") as f:
        content = f.read()

    non_pillow_wheels = [
        "./wheels/attrs-24.2.0-py3-none-any.whl",
        "./wheels/jsonschema-4.6.0-py3-none-any.whl",
        "./wheels/pyrsistent-0.20.0-py3-none-any.whl",
        "./wheels/t3dn_bip-1.0.9-py3-none-any.whl",
    ]
    all_wheels = non_pillow_wheels + [f"./wheels/{n}" for n in new_wheel_names]
    wheels_toml = "wheels = [\n" + "".join(f'  "{w}",\n' for w in all_wheels) + "]"

    content = re.sub(r'wheels\s*=\s*\[.*?\]', wheels_toml, content, flags=re.DOTALL)
    # Remove blender_version_max if it would block Blender 5.x
    content = re.sub(r'\nblender_version_max\s*=\s*"[^"]*"', '', content)

    with open(manifest_path, "w", encoding="utf-8") as f:
        f.write(content)

    print("\n  ✓ blender_manifest.toml updated.")


def main():
    input_zip = sys.argv[1] if len(sys.argv) > 1 else "gscatter-0_12_0.zip"

    if not os.path.exists(input_zip):
        print(f"ERROR: Cannot find '{input_zip}'.")
        print("Usage: python fix_gscatter_blender51.py [path/to/gscatter-0_12_0.zip]")
        sys.exit(1)

    print(f"Input zip : {input_zip}")
    print(f"Output zip: {OUTPUT_ZIP}\n")

    with tempfile.TemporaryDirectory() as tmpdir:
        # 1. Extract
        extract_dir = os.path.join(tmpdir, "addon")
        print("[1/5] Extracting original zip ...")
        with zipfile.ZipFile(input_zip, "r") as z:
            z.extractall(extract_dir)

        addon_dir  = os.path.join(extract_dir, "gscatter")
        wheels_dir = os.path.join(addon_dir, "wheels")

        # 2. Remove old cp311 Pillow wheels
        print("\n[2/5] Removing cp311 Pillow wheels ...")
        removed = 0
        for f in os.listdir(wheels_dir):
            if f.lower().startswith("pillow-") and "cp311" in f:
                os.remove(os.path.join(wheels_dir, f))
                print(f"  Removed: {f}")
                removed += 1
        print(f"  {removed} wheel(s) removed.")

        # 3. Download cp313 Pillow wheels
        print("\n[3/5] Downloading Pillow cp313 wheels from PyPI ...")
        wheel_dl_dir = os.path.join(tmpdir, "dl")
        os.makedirs(wheel_dl_dir)
        downloaded = download_pillow_wheels(wheel_dl_dir)

        # 4. Copy new wheels in
        print("\n[4/5] Installing new wheels ...")
        new_wheel_names = []
        for suffix, whl_path in downloaded:
            name = os.path.basename(whl_path)
            shutil.copy2(whl_path, os.path.join(wheels_dir, name))
            new_wheel_names.append(name)
            print(f"  Added: {name}")

        # 5. Patch manifest
        fix_manifest(os.path.join(addon_dir, "blender_manifest.toml"), new_wheel_names)

        # 6. Repack
        output_path = os.path.abspath(OUTPUT_ZIP)
        print(f"\n[5/5] Repacking → {output_path} ...")
        with zipfile.ZipFile(output_path, "w", compression=zipfile.ZIP_DEFLATED) as zout:
            for root, dirs, files in os.walk(extract_dir):
                for file in files:
                    full_path = os.path.join(root, file)
                    arcname = os.path.relpath(full_path, extract_dir)
                    zout.write(full_path, arcname)

        size_mb = os.path.getsize(output_path) / 1024 / 1024
        print(f"\n✅ Done! {OUTPUT_ZIP}  ({size_mb:.1f} MB)")
        print("\nInstall in Blender 5.1:")
        print("  Edit → Preferences → Add-ons → Install from Disk")
        print(f"  → select {OUTPUT_ZIP}")


if __name__ == "__main__":
    main()```

gscatter-0_12_0-py313-patch.zip (3.2 MB)
drag and drop :}

Ohh thanks, so I’m supposed to install this patched gscatter 0.12.0 just like I usually do it, through zip file?

Also will this fix the issues that come with Blenders geometry nodes updates where some gscatters effect layers won’t work, such as Randomize Translation and Translate which make the assets disappear from the object?

Blender 5.2 is gonna bring new changes which might make the gscatter 0.12.0 even more obsolete (less and less of it’s features can be used).