{ description = "Westgate Urban Foundation MVP — Blender 4.0.2 tileset generator kit"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; # Reuse the machine's pinned Blender 4.0.2 + NWN toolchain via the repo overlay. theorem.url = "git+file:///nix/nixos"; }; outputs = { self, nixpkgs, theorem, }: let system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; overlays = [ theorem.overlays.default ]; }; blender = pkgs.blender-402-bin; # /bin/blender-4.0.2 (NWN needs 4.0.x, not 5.x) py = pkgs.python3.withPackages (ps: [ ps.mcp ]); gen = ./generator; # whole dir so tiles.py sits beside each script for import build = pkgs.writeShellApplication { name = "wgt-build"; runtimeInputs = [ blender ]; text = '' out="''${1:-westgate_urban_foundation_mvp.blend}" exec blender-4.0.2 --background --python ${gen}/build.py -- "$out" ''; }; mkset = pkgs.writeShellApplication { name = "wgt-set"; runtimeInputs = [ py ]; text = ''exec python ${gen}/make_set.py "$@"''; }; mkwok = pkgs.writeShellApplication { name = "wgt-wok"; runtimeInputs = [ py ]; text = ''exec python ${gen}/make_wok.py "$@"''; }; # Pure-Python .mdl + .wok + solid-colour .tga (the shipping model path; # no Blender, and unlike Neverblender it keeps per-texture trimesh nodes). mkmdlpy = pkgs.writeShellApplication { name = "wgt-mdl"; runtimeInputs = [ py ]; text = ''exec python ${gen}/make_mdl.py "$@"''; }; # Tileset palette (GFF ITP) so the toolset registers the set. mkitp = pkgs.writeShellApplication { name = "wgt-itp"; runtimeInputs = [ py pkgs.neverwinter-nim ]; text = ''exec python ${gen}/make_itp.py "$@"''; }; # Real .mdl + .wok export via the Neverblender addon (must be enabled in # this Blender's user config — confirmed working headless). mkmdl = pkgs.writeShellApplication { name = "wgt-export"; runtimeInputs = [ blender ]; text = '' blend="''${1:?usage: wgt-export [CODE...]}" outdir="''${2:-mdl}" shift 2 || true exec blender-4.0.2 --background "$blend" --python ${gen}/export_mdl.py \ --python-exit-code 1 -- "$outdir" "$@" ''; }; # One shot: models (.mdl/.wok/.tga) + .set + .itp, staged into the toolset's # development/ folder (no .hak, no Blender). Work dir defaults to ./build. mkdev = pkgs.writeShellApplication { name = "wgt-dev-install"; runtimeInputs = [ py pkgs.neverwinter-nim ]; text = '' work="''${1:-$PWD/build}" dev="$HOME/Documents/Neverwinter Nights/development" mkdir -p "$work/mdl" "$dev" python ${gen}/make_mdl.py "$work/mdl" # .mdl + .wok + .tga python ${gen}/make_set.py "$work/twu01.set" python ${gen}/make_itp.py "$work/twu01palstd.itp" # replace only our own files in development/, leave everything else alone rm -f "$dev"/twu01_*.mdl "$dev"/twu01_*.wok "$dev"/twu01_*.tga \ "$dev"/twu01.set "$dev"/twu01palstd.itp cp "$work"/mdl/twu01_*.mdl "$work"/mdl/twu01_*.wok "$work"/mdl/twu01_*.tga \ "$work"/twu01.set "$work"/twu01palstd.itp "$dev"/ n=$(find "$work/mdl" -name 'twu01_*.mdl' | wc -l) echo "installed $n tiles + twu01.set + twu01palstd.itp -> $dev" ''; }; in { packages.${system}.default = build; apps.${system} = { default = { type = "app"; program = "${build}/bin/wgt-build"; }; build = { type = "app"; program = "${build}/bin/wgt-build"; }; set = { type = "app"; program = "${mkset}/bin/wgt-set"; }; wok = { type = "app"; program = "${mkwok}/bin/wgt-wok"; }; mdl = { type = "app"; program = "${mkmdlpy}/bin/wgt-mdl"; }; itp = { type = "app"; program = "${mkitp}/bin/wgt-itp"; }; export = { type = "app"; program = "${mkmdl}/bin/wgt-export"; }; dev-install = { type = "app"; program = "${mkdev}/bin/wgt-dev-install"; }; }; devShells.${system}.default = pkgs.mkShell { packages = [ blender py pkgs.neverwinter-nim pkgs.cleanmodels ]; shellHook = '' export BLENDER_BIN=${blender}/bin/blender-4.0.2 echo "wgt01 dev shell — build: blender-4.0.2 --background --python generator/build.py -- out.blend" >&2 ''; }; }; }