A ShotGrid engine for Adobe Substance 3D Painter that enables seamless integration with your VFX/animation pipeline.
- Project Management: Create and manage Substance Painter projects through the Shotgun Workfiles app
- Publishing: Publish both
.sppproject files and exported texture sets to Shotgun - Multi-App Support: Integrates with standard Shotgun apps (Workfiles2, Publisher, Breakdown, etc.)
- Adobe Substance 3D Painter (version 12 or higher recommended)
- Shotgun Toolkit
- Python 3.7+
- A configured Shotgun pipeline (based on
tk-config-default2)
Add the engine location to your pipeline configuration in env/includes/engine_locations.yml:
engines.tk-substancepainter.location:
type: git
path: https://github.com/dovanbel/tk-substancepainter.git
version: v1.0.1 # Update to the latest available tag from this repoThe following sections provide configuration examples for a pipeline based on tk-config-default2. Customize these to fit your studio's needs.
Add these template definitions to core/templates.yml:
##################### keys section
texture_extension:
type: str
filter_by: alphanumeric
alias: extension
##################### templates section
asset_root: Assets/{sg_asset_type}/{Asset}/{Step}
substancepainter_asset_root: '@asset_root/substancepainter'
substancepainter_asset_project_work_area:
definition: '@substancepainter_asset_root/projects/work'
substancepainter_asset_project_publish_area:
definition: '@substancepainter_asset_root/projects/publish'
substancepainter_asset_texture_work_area:
definition: '@substancepainter_asset_root/export/work'
substancepainter_asset_texture_publish_area:
definition: '@substancepainter_asset_root/export/publish'
# WIP project files
substancepainter_asset_work:
definition: '@substancepainter_asset_project_work_area/{Asset}_{task_name}_{name}_v{version}.spp'
# Published Substance Painter project files
substancepainter_asset_publish:
definition: '@substancepainter_asset_project_publish_area/{Asset}_{task_name}_{name}_v{version}.spp'
# Project snapshots
substancepainter_asset_snapshot:
definition: '@substancepainter_asset_project_work_area/snapshots/{Asset}_{task_name}_{name}_v{version}_{timestamp}.spp'
# Published texture files
substancepainter_asset_texture_publish:
definition: '@substancepainter_asset_texture_publish_area/{texture_set}_v{version}/{Asset}_{task_name}_{texture_set}_{texture_map}_{colorspace}_v{version}.{texture_extension}'
# Published UDIM texture files
substancepainter_asset_texture_udim_publish:
definition: '@substancepainter_asset_texture_publish_area/{texture_set}_v{version}/{Asset}_{task_name}_{texture_set}_{texture_map}_{colorspace}_v{version}.{UDIM}.{texture_extension}'
# Texture set publish folder
substancepainter_asset_texture_set_publish:
definition: '@substancepainter_asset_texture_publish_area/{texture_set}_v{version}'Define application paths in env/includes/software_paths.yml:
# Substance Painter
path.linux.substancepainter: '/opt/Adobe/Adobe_Substance_3D_Painter'
path.mac.substancepainter: '/Applications/Adobe Substance 3D Painter.app'
path.windows.substancepainter: 'C:\Program Files\Adobe\Adobe Substance 3D Painter\Adobe Substance 3D Painter.exe'Configure the launcher in env/includes/settings/tk-multi-launchapp.yml:
# Substance Painter
settings.tk-multi-launchapp.substancepainter:
engine: tk-substancepainter
linux_path: "@path.linux.substancepainter"
mac_path: "@path.mac.substancepainter"
windows_path: "@path.windows.substancepainter"
menu_name: "Substance Painter"
location: "@apps.tk-multi-launchapp.location"Add to env/project.yml:
includes:
- ./includes/settings/tk-substancepainter.yml
engines:
tk-substancepainter: "@settings.tk-substancepainter.project"Add to env/asset_step.yml:
includes:
- ./includes/settings/tk-substancepainter.yml
engines:
tk-substancepainter: "@settings.tk-substancepainter.asset_step"In env/includes/settings/tk-multi-breakdown2.yml:
settings.tk-multi-breakdown2.substancepainter:
hook_scene_operations: "{engine}/tk-multi-breakdown2/tk-substancepainter_scene_operations.py"
panel_mode: False
published_file_filters: []
location: "@apps.tk-multi-breakdown2.location"In env/includes/settings/tk-multi-loader2.yml:
settings.tk-multi-loader2.substancepainter:
actions_hook: "{engine}/tk-multi-loader2/tk-substancepainter_actions.py"
entities:
- caption: Current Project
type: Hierarchy
root: "{context.project}"
publish_filters: []
- caption: My Tasks
type: Query
entity_type: Task
filters:
- [project, is, '{context.project}']
- [task_assignees, is, '{context.user}']
hierarchy: [entity, content]
publish_filters: [["sg_status_list", "is_not", null]]
location: "@apps.tk-multi-loader2.location"In env/includes/settings/tk-multi-publish2.yml:
# Substance Painter - Asset Step
settings.tk-multi-publish2.substancepainter.asset_step:
collector: "{self}/collector.py:{engine}/tk-multi-publish2/basic/collector.py"
collector_settings:
Work Template: substancepainter_asset_work
publish_plugins:
- name: Publish Project to ShotGrid
hook: "{self}/publish_file.py:{engine}/tk-multi-publish2/basic/publish_session.py"
settings:
Publish Template: substancepainter_asset_publish
- name: Publish Textures to ShotGrid
hook: "{self}/publish_file.py:{engine}/tk-multi-publish2/basic/publish_texture_set.py"
settings:
Publish Template: substancepainter_asset_texture_publish
Publish UDIM Template: substancepainter_asset_texture_udim_publish
Publish Folder Template: substancepainter_asset_texture_set_publish
location: "@apps.tk-multi-publish2.location"In env/includes/settings/tk-multi-shotgunpanel.yml:
settings.tk-multi-shotgunpanel.substancepainter:
action_mappings:
PublishedFile:
- actions: [publish_clipboard]
filters: {}
Task:
- actions: [assign_task, task_to_ip]
filters: {}
Version:
- actions: [quicktime_clipboard, sequence_clipboard, add_to_playlist]
filters: {}
location: "@apps.tk-multi-shotgunpanel.location"In env/includes/settings/tk-multi-workfiles2.yml:
# Substance Painter - Project Context
settings.tk-multi-workfiles2.substancepainter.project:
hook_scene_operation: "{engine}/tk-multi-workfiles2/scene_operation_tk-substancepainter.py"
allow_task_creation: True
create_new_task_hook: "{self}/create_new_task.py"
custom_actions_hook: "{self}/custom_actions.py"
auto_expand_tree: True
entities:
- caption: Assets
entity_type: Task
filters:
- [entity, type_is, Asset]
- [step.Step.code, is, "texturing"]
hierarchy: [entity.Asset.sg_asset_type, entity, content]
location: "@apps.tk-multi-workfiles2.location"
# Substance Painter - Asset Step Context
settings.tk-multi-workfiles2.substancepainter.asset_step:
allow_task_creation: False
saveas_default_name: main
auto_expand_tree: True
custom_actions_hook: "{self}/custom_actions.py"
hook_copy_file: "{self}/copy_file.py"
hook_filter_publishes: default
hook_filter_work_files: default
hook_scene_operation: "{engine}/tk-multi-workfiles2/scene_operation_tk-substancepainter.py"
template_publish: substancepainter_asset_publish
template_publish_area: substancepainter_asset_project_publish_area
template_work: substancepainter_asset_work
template_work_area: substancepainter_asset_project_work_area
entities:
- caption: Assets
entity_type: Task
filters:
- [entity, type_is, Asset]
- [step.Step.code, is, "texturing"]
hierarchy: [entity.Asset.sg_asset_type, entity, content]
file_extensions: []
location: "@apps.tk-multi-workfiles2.location"Create env/includes/settings/tk-substancepainter.yml:
################################################################################
includes:
- ../app_locations.yml
- ../engine_locations.yml
- ./tk-multi-breakdown2.yml
- ./tk-multi-loader2.yml
- ./tk-multi-publish2.yml
- ./tk-multi-shotgunpanel.yml
- ./tk-multi-workfiles2.yml
################################################################################
# Project Context
settings.tk-substancepainter.project:
compatibility_dialog_min_version: 12
textures_export_work_area: substancepainter_asset_texture_work_area
modeling_root_area: asset_root
modeling_step_name: modeling
windows_path_mappings:
- unc_prefix: '\\yourserver\projects'
mapped_drive_prefix: 'X:\projects'
apps:
tk-multi-about:
location: "@apps.tk-multi-about.location"
tk-multi-shotgunpanel: "@settings.tk-multi-shotgunpanel.substancepainter"
tk-multi-workfiles2: "@settings.tk-multi-workfiles2.substancepainter.project"
tk-multi-pythonconsole:
location: "@apps.tk-multi-pythonconsole.location"
menu_favourites:
- {app_instance: tk-multi-workfiles2, name: File Open...}
location: "@engines.tk-substancepainter.location"
# Asset Step Context
settings.tk-substancepainter.asset_step:
compatibility_dialog_min_version: 12
textures_export_work_area: substancepainter_asset_texture_work_area
modeling_root_area: asset_root
modeling_step_name: modeling
windows_path_mappings: []
apps:
tk-multi-about:
location: "@apps.tk-multi-about.location"
tk-multi-loader2: "@settings.tk-multi-loader2.substancepainter"
tk-multi-publish2: "@settings.tk-multi-publish2.substancepainter.asset_step"
tk-multi-shotgunpanel: "@settings.tk-multi-shotgunpanel.substancepainter"
tk-multi-workfiles2: "@settings.tk-multi-workfiles2.substancepainter.asset_step"
tk-multi-breakdown2: "@settings.tk-multi-breakdown2.substancepainter"
tk-multi-pythonconsole:
location: "@apps.tk-multi-pythonconsole.location"
menu_favourites:
- {app_instance: tk-multi-workfiles2, name: File Open...}
- {app_instance: tk-multi-workfiles2, name: File Save...}
- {app_instance: tk-multi-publish2, name: Publish...}
location: "@engines.tk-substancepainter.location"- Launch Substance Painter from Shotgun Desktop
- The engine will initialize and display the Shotgun menu in the application
- Select File Open from the Shotgun menu
- The Workfiles app will open
- Navigate to the texturing task for your asset
- Click + New File
- Configure the "New Substance Project" dialog:
- Select the mesh to texture
- Choose a Substance Painter template (optional)
- Set document resolution
- Configure normal map format
- Set tangent space calculation method
- Enable UV Tiles (UDIMs) if needed (
⚠️ cannot be changed later)
- Save your project using File Save from the Shotgun menu
The Scene Breakdown app (tk-multi-breakdown2) monitors your project's mesh references and will allow you to update the mesh
Note: The Loader app is configured but not implemented in v1.0.1. The configuration is required as tk-multi-breakdown2 depends on it.
The Publisher handles two types of publishes:
Publishes the .spp project file to Shotgun, similar to standard session publishing in other DCCs.
Exports and publishes texture sets.
Due to limitations in the Substance Painter Python API, this engine uses a custom export preset workflow:
How It Works:
- Base Preset: The engine includes a "Shotgrid_base" export preset (located in
resources/export-presets/) - Auto-Installation: On first launch of the engine, this preset is copied to your Substance Painter documents directory
- Preservation: The engine won't overwrite existing presets, allowing you to customize them
- Naming Convention: Use presets starting with "Shotgrid..." to make them available for publishing
Required Filename Pattern for all texture maps:
$textureSet_<MapName>_$colorSpace(.$udim)
Where:
$textureSet- Substance Painter variable for texture set name<MapName>- Your custom map name (e.g., BaseColor, Roughness, Normal)⚠️ Do not use spaces or underscores in map names
$colorSpace- Substance Painter variable for color space(.$udim)- Optional UDIM suffix for tiled workflows
Customization:
- Add additional texture maps to the "Shotgrid_base" preset as needed
- Duplicate the preset to create variations (ensure the name starts with "Shotgrid")
- Select your preferred preset from the dropdown in the Publisher UI
Publishing Process:
- Validation: Checks that filename patterns match the required format
- Export: Textures are exported to a work folder using the selected preset
- Publishing: Files are copied and renamed according to the publish template to the publish location with version numbers
- Database: Each texture map is registered as a PublishedFile in Shotgun
- Texture Set: A parent PublishedFile is created linking all texture maps together
The published texture set can be used downstream in other DCCs (e.g., automatically assigning textures to shader slots in Maya via a custom loader action).
- Tested on: Windows only
- Untested: macOS and Linux (configuration provided but requires validation)
There are visual issues with app interfaces in v1.0.1:
- Some buttons appear overly bright
- Font readability issues in certain dialogs
- Similar to historical issues with
tk-houdini
Contributions to resolve these styling issues are welcome!
The Loader app is not fully implemented. To add functionality:
- Explore the
substance_painter.resourcemodule in the Python API - Implement custom loader actions as needed
- The provided configuration uses YAML-based software paths
- Software Entity system (defining paths in Shotgun) is untested but should work
- Expect potential bugs and edge cases
- Test thoroughly in a development environment before production use
- Report issues on the GitHub repository
Contributions are welcome! Areas where help would be particularly valuable:
- UI styling fixes
- macOS and Linux testing
- Loader app implementation
- Documentation improvements
A big thanks to Diego Garcia Huerta, whose tk-substancepainter engine was my starting point (https://github.com/diegogarciahuerta/tk-substancepainter)
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.