# Copyright 1999-2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 PYTHON_COMPAT=( python3_{12..13} ) inherit python-single-r1 # Upstream tags no releases; pin the commit. The repo bundles its own copy of # Microsoft's TRELLIS library under trellis/ (plus a wheels/ dir of prebuilt # CUDA extensions and an extensions/ source tree we do not use -- those ship as # their own ebuilds). MY_NODE is the on-disk custom_nodes directory name ComfyUI # scans for; keep upstream's spelling so bundled workflows resolve. COMMIT="51bdfc6fae11bb3966f0cbe22239c13ba612c57e" MY_NODE="ComfyUI-IF_Trellis" DESCRIPTION="ComfyUI custom node: TRELLIS image-to-3D (Gaussian/.ply generation)" HOMEPAGE="https://github.com/if-ai/ComfyUI-IF_Trellis" SRC_URI=" https://github.com/if-ai/${MY_NODE}/archive/${COMMIT}.tar.gz -> ${P}.gh.tar.gz " S="${WORKDIR}/${MY_NODE}-${COMMIT}" LICENSE="MIT" SLOT="0" KEYWORDS="~amd64" IUSE="mesh" REQUIRED_USE="${PYTHON_REQUIRED_USE}" # The node loads trellis/ at ComfyUI import time, which eagerly pulls torch, the # renderers (nvdiffrast/diff-gaussian-rasterization), cv2, plyfile, trimesh, # etc. The sparse/attention CUDA extensions (spconv, flash-attn, diffoctreerast, # vox2seq) import lazily but are required at generation time, so they are hard # deps too. spconv is the sparse-conv backend: the TRELLIS pretrained weights # are spconv-format, so torchsparse (different weight naming/layout) cannot load # them -- the loader auto-selects spconv when present. # # USE=mesh pulls the textured/solid mesh (.glb) post-processing stack # (xatlas UV unwrap, pyvista decimation, python-igraph hole-fill). Without it the # node still loads and the Gaussian (.ply) path works -- patches 0002/0003 make # those imports optional -- but save_glb=True then errors. kaolin/open3d remain # unpackaged and are stubbed/avoided. RDEPEND=" ${PYTHON_DEPS} media-gfx/comfyui[${PYTHON_SINGLE_USEDEP}] sci-ml/caffe2[${PYTHON_SINGLE_USEDEP}] sci-ml/torchvision[${PYTHON_SINGLE_USEDEP}] sci-ml/huggingface_hub[${PYTHON_SINGLE_USEDEP}] dev-python/spconv-cu126[${PYTHON_SINGLE_USEDEP}] dev-python/flash-attn[${PYTHON_SINGLE_USEDEP}] dev-python/nvdiffrast[${PYTHON_SINGLE_USEDEP}] dev-python/diff-gaussian-rasterization[${PYTHON_SINGLE_USEDEP}] dev-python/diffoctreerast[${PYTHON_SINGLE_USEDEP}] dev-python/vox2seq[${PYTHON_SINGLE_USEDEP}] $(python_gen_cond_dep ' dev-python/easydict[${PYTHON_USEDEP}] dev-python/utils3d[${PYTHON_USEDEP}] dev-python/plyfile[${PYTHON_USEDEP}] dev-python/einops[${PYTHON_USEDEP}] dev-python/numpy[${PYTHON_USEDEP}] dev-python/scipy[${PYTHON_USEDEP}] dev-python/tqdm[${PYTHON_USEDEP}] dev-python/imageio[${PYTHON_USEDEP}] dev-python/pillow[${PYTHON_USEDEP}] dev-python/trimesh[${PYTHON_USEDEP}] sci-ml/safetensors[${PYTHON_USEDEP}] media-libs/opencv[${PYTHON_USEDEP},python] ') mesh? ( dev-python/pyvista[${PYTHON_SINGLE_USEDEP}] $(python_gen_cond_dep ' dev-python/xatlas[${PYTHON_USEDEP}] dev-python/python-igraph[${PYTHON_USEDEP}] dev-python/pymeshfix[${PYTHON_USEDEP}] ') ) " PATCHES=( # Defer rembg to call time -- only auto-masking of non-alpha inputs needs # it, so the node loads (and RGBA inputs work) without dev-python/rembg. "${FILESDIR}/0001-rembg-lazy-import.patch" # Make the mesh-only post-processing deps optional so the Gaussian .ply # pipeline imports cleanly. .glb export lights up if they are installed. "${FILESDIR}/0002-postprocess-optional-mesh-deps.patch" # kaolin only backs optional FlexiCubes shape asserts; stub it out. "${FILESDIR}/0003-flexicube-optional-kaolin.patch" # Guard an unconditional texture_image.shape log so the gaussian-only path # (save_glb=False) does not crash before the .ply write. "${FILESDIR}/0004-gaussian-only-texture-guard.patch" ) src_prepare() { # IF_Trellis.py ships with CRLF line endings (the bundled trellis/ files are # LF); normalise it so the LF 0004 patch applies. sed -i 's/\r$//' IF_Trellis.py || die default } src_install() { python_setup local dest="/usr/share/comfyui/custom_nodes/${MY_NODE}" insinto "${dest}" # Ship the node sources + bundled trellis library + example workflows and # assets. Exclude the prebuilt wheels/ (wrong ABI -- we build the CUDA # extensions from source) and extensions/ (their own ebuilds), plus the pip # install scaffolding and VCS/CI leftovers. doins -r \ __init__.py \ IF_Trellis.py \ IF_TrellisCheckpointLoader.py \ trellis_model_manager.py \ trellis \ workflow \ assets \ LICENSE \ README.md python_optimize "${ED}${dest}" } pkg_postinst() { elog "TRELLIS image-to-3D node installed to:" elog " ${EROOT}/usr/share/comfyui/custom_nodes/${MY_NODE}" elog "" elog "Place the model under your ComfyUI base dir before first use:" elog " \${COMFYUI_BASE:-~/.local/share/comfyui}/models/checkpoints/TRELLIS-image-large/" elog "(pipeline.json + ckpts/, from huggingface microsoft/TRELLIS-image-large)." elog "" elog "The Gaussian (.ply) output path works out of the box. For mesh (.glb)" elog "export, rebuild with USE=mesh (pulls xatlas, pyvista, python-igraph and" elog "pymeshfix; note pyvista drags in sci-libs/vtk)." }