Skip to content

DCC Integration

Each DCC is its own self-contained workspace package under packages/<dcc>/src/kpipe_<dcc>/, following a three-layer pattern within that one package.

Layers

1. Launcher (packages/<dcc>/src/kpipe_<dcc>/launcher.py)

  • Reads the DCC executable path from config
  • Sets environment variables: PYTHONPATH, OCIO, KPIPE_ENV, etc.
  • Spawns the DCC process

Run from the command line:

uv run kpipe launch blender
uv run kpipe launch nuke
uv run kpipe launch premiere
uv run kpipe launch tvpaint
uv run kpipe launch substance
uv run kpipe launch mrv2

All arguments after the DCC name are passed on to the DCC. kpipe launch does the DCC-independent setup (logging via kpipe.init(), version banner, KPIPE_ROOT) and then calls the launcher's launch(args: list[str]) -> int; the return value is the exit code. Use kpipe -d launch <dcc> for debug logging.

2. Extension (sibling files in kpipe_<dcc>/)

Startup scripts loaded by the DCC when it launches, packaged alongside the launcher in the same directory. Responsibilities:

  • Import and initialise the K-Pipe session
  • Register DCC-specific actions into the action registry
  • Add K-Pipe menus or panels to the DCC UI

Blender uses the Blender 4+ extension system (kpipe_blender/system/, containing both the kpipe_blender extension and the integrated kpipe_asset_pipeline extension as sibling installable extensions — required so Blender's local extension repository scan sees both). Nuke uses a menu.py/init.py startup script pair, found by pointing NUKE_PATH/NUKE_MENU_PATH at the package directory itself (Path(__file__).resolve().parent from launcher.py, since launcher and extension files are always siblings in this layout).

3. Session (kpipe.session, in packages/core/src/kpipe/session.py)

  • Manages the active entity and task state
  • Extensions register DCC-specific callbacks for open, save, and close events
  • Handles versioned workfile naming on save

Adding a new DCC

  1. Create packages/<dcc>/ with a src/kpipe_<dcc>/ tree containing launcher.py plus the DCC's startup/extension scripts
  2. Implement launch(args: list[str]) -> int in launcher.py (optionally decorated with @kpipe.cli.launch.launcher("<Display Name>")) and register it in the kpipe.cli.launch entry-point group in packages/<dcc>/pyproject.toml ([project.entry-points."kpipe.cli.launch"], e.g. <dcc> = "kpipe_<dcc>.launcher:launch"), which makes it available as kpipe launch <dcc>
  3. Add packages/<dcc> to the root pyproject.toml's [tool.uv.workspace] members
  4. Add DCC path config key to your project bundle's kpipe.toml

Opening a published mesh in Substance Painter

kpipe launch substance takes three arguments that belong together, used by LaunchDcc at the end of the blender_asset_fbx pipeline:

kpipe launch substance --kpipe-entity asset:Character:Doris --kpipe-task shading --kpipe-mesh Q:/.../doplay-Character_Doris-asset_fbx-v003.fbx
  • No workfile for the task yet: a project is created from the mesh without a dialog, with the settings of [dcc.substance.project], and saved as the first workfile as soon as Painter can save.
  • A workfile exists: the latest version of the main layer opens. If the mesh differs from the one stored in the project, including a re-publish to the same path, the artist can replace it. Replacing saves a new workfile version.

The task is set in the pipeline config, in LaunchDcc's args. Other arguments are passed on to Painter.

[dcc.substance.project] Default Values
normal_map_format "OpenGL" OpenGL, DirectX
tangent_space_mode "PerFragment" PerFragment, PerVertex
project_workflow "UVTile" UVTile, TextureSetPerUVTile, Default
default_texture_resolution 2048 Texture Set resolution
import_cameras false Import cameras from the mesh
template unset Painter template file (template string)

Every launch starts a new Painter instance and workfiles aren't locked, so a workfile can end up open in two instances.