Template_Manager package
Submodules
Template_Manager.main module
Entry point for the Nuke Template Manager.
This module wires together the configuration layer, the scanner, and the PySide frontend to provide the three top-level commands exposed to artists through the Nuke menu:
launch_ui()— open the main Template Manager browser.launch_save_ui()— save the currently-selected nodes as a new template, with smart fast-track behaviour for re-saves.launch_rules_editor()— open the auto-tag rule editor.
Every function in this module is designed to be invoked directly from a Nuke menu callback and assumes a live Nuke session.
- Template_Manager.main.launch_about_dialog() None
Open the Template Manager About dialog from the Nuke menu.
- Template_Manager.main.launch_rules_editor() None
Open the auto-tag rules editor as a modal dialog.
Instantiates
ui.AutoTagRulesDialogparented to Nuke’s main window (located viaui.get_nuke_main_window()) so the dialog floats correctly above the application rather than the desktop. The dialog reads its initial rule set from disk viasaves.load_auto_tag_rules()and writes any changes back viasaves.save_auto_tag_rules()when the user clicks Save.The function blocks until the dialog is dismissed. Rule changes take effect on the next scan; templates already loaded in an open Template Manager window are unaffected until the user re-runs the Re-Evaluate Auto-Tags context-menu action.
- Template_Manager.main.launch_save_ui() None
Save the current Nuke selection as a template, with fast-track logic.
The function is the standalone counterpart of the in-UI Save action: it can be triggered directly from the Nuke menu without first opening the Template Manager browser. The full flow is:
Verify that at least one node is selected in the DAG, aborting with a user-facing message otherwise.
Capture the current script’s root settings (format, fps, colorManagement, OCIO_config) into a
template_contextdict. If the settings match the agnostic defaults (2048x1556, 24fps, “Nuke” colorManagement) the context is set toNoneand no root injection will occur later.Walk the first configured template root to build two structures:
projects_dictmapping display project names to known subfolder paths, andfast_track_dbmapping lowercase template base names to their highest-version on-disk location.Inspect the active Nuke script name. If its base name (after version-suffix stripping) appears in
fast_track_db, present a streamlined “Template Match Found” dialog offering quick options to version-up, overwrite the matched version, save as the script’s own version, or open the full save menu.If the user chooses a fast-track option the template is written directly via
nuke.nodeCopy. Becausenuke.nodeCopyonly copies nodes and not project-level settings, aRoot { ... }block built fromtemplate_contextis then prepended to the saved.nkfile (skipped if the context isNone), and the function returns.Otherwise the full
ui.SaveTemplateDialogis shown so the user can pick a project, subfolder, name, and versioning behaviour.When the save dialog accepts, any selected Read nodes are optionally swapped to Placeholder NoOps via
ui.PlaceholderDialog, the template is copied to disk, the sameRoot { ... }block is injected when a non-agnostic context was captured, and the Read swap is reverted with an undo so the artist’s script is left untouched.
All transient Nuke graph modifications performed during the swap step are bracketed by
nuke.Undo()calls and reverted in thefinallyblock, so a user exception or paste failure cannot leave the artist’s session in a corrupted state.Note
This function uses only message-box dialogs from PySide; it does not require the main
ui.TemplateManagerUIwindow to be open.
- Template_Manager.main.launch_ui() None
Initialise the environment and open the Template Manager browser.
The function performs the full startup sequence required to show the main UI:
Resolve the effective list of template root directories via
settings.get_effective_template_paths().Build the set of node classes available in the current Nuke session via
scanner.get_available_nodes().Probe for the optional Stamps plugin by Adrian Pueyo, storing the result so the UI can offer Stamps-aware shortcuts.
Run
scanner.scan_templates()against every configured root, accumulating the parsed template records.Instantiate
ui.TemplateManagerUIwith the scan results and show it as a non-modal dialog.
Note
A global module-level reference (
tm_window) is retained to prevent Nuke’s Python garbage collector from destroying the window immediately after the function returns. Replacing this reference will close the previous window without animation.
Template_Manager.scanner module
Deep-text scanning and dependency validation module.
This module is responsible for safely parsing Nuke script files (.nk)
without using the heavy Nuke API. By bypassing the application layer it
can scan thousands of files in seconds, even outside a running Nuke
session, and is therefore safe to call before any Nuke import or paste
operation has been attempted.
The parser uses a single compiled regular expression to identify node
class declarations in the raw text. It cross-references those classes
against a baseline of vanilla Nuke nodes (CORE_NODES) to detect
missing OFX plugins and proprietary studio gizmos, and extracts project
settings (FPS, resolution, colour management) from the Root block
when present.
- Template_Manager.scanner.NODE_FINDER
Compiled regular expression matching node class declarations at the start of a line, capturing the leading indentation, the class name, and any trailing text on the opening brace line. Top-level (un-indented) matches are treated as real nodes; indented matches are usually nested entries inside groups and are ignored by the default scanner pass.
- Type:
re.Pattern
- Template_Manager.scanner.CORE_NODES
The complete set of node class names shipped with vanilla Nuke. Any class found in a
.nkfile that is not present in this set, inget_available_nodes()’s output, and does not strip down to a known base by trailing-digit removal is reported as a missing dependency.- Type:
set[str]
- Template_Manager.scanner.IGNORED_WORDS
Tokens the scanner should never treat as node classes even though they match the syntactic pattern. The
Rootblock in particular looks like a node declaration but contains project settings rather than a node.- Type:
set[str]
- Template_Manager.scanner.TemplateStatus
A
Literalof the four status strings aTemplateentry may carry:"OK","MISSING_NODES","READ_ERROR","FILE_TOO_LARGE".
- Template_Manager.scanner.extract_project_settings_from_root(text: str) Tuple[float | None, Tuple[int, int] | None, str | None, str]
Parse project settings from a Nuke script’s
Rootblock.The function delegates to
extract_root_block()to isolate the body of theRootdeclaration, then applies focused regexes to pull out the frame rate, resolution, and colour-management configuration. Missing fields fall back to the module-level defaults (DEFAULT_PROJECT_FPS,DEFAULT_PROJECT_RESOLUTION,DEFAULT_PROJECT_COLORSPACE) rather than being reported asNone, so a partialRootblock is treated as a valid project-settings template.The
OCIO_configknob takes precedence overcolorManagementwhen both are present, mirroring Nuke’s own evaluation order when a template is loaded.- Parameters:
text – Raw contents of a
.nkfile as a single string.- Returns:
A 4-tuple
(fps, resolution, colorspace, mode)where:fpsis a float orNone(onlyNonewhen noRootblock exists),resolutionis a(width, height)tuple orNone,colorspaceis a string orNone,modeis the string"ROOT_SETTINGS"when settings came from aRootblock, or"AGNOSTIC"otherwise.
- Return type:
tuple
- Template_Manager.scanner.extract_root_block(text: str) str | None
Return the inner contents of a Nuke script’s
Root { ... }block.The function walks the text after the opening
Root {looking for the matching closing brace, tracking nesting depth so braces inside expression knobs or string values do not terminate the block early. Only the body between the outermost braces is returned; the enclosingRoot { ... }delimiters themselves are omitted.- Parameters:
text – Raw contents of a
.nkfile as a single string.- Returns:
The body of the
Rootblocßk if one is present, orNonefor project-agnostic templates that contain noRootdeclaration.- Return type:
str | None
- Template_Manager.scanner.get_auto_tags(node_list: List[str]) List[str]
Evaluate the auto-tag rule engine against a list of node classes.
Loads the current rule set from disk via
saves.load_auto_tag_rules()and applies each rule in turn. A rule attaches its tag name to the result if its match condition is satisfied. Three rule types are supported:"any"— the tag applies if any of the rule’s target substrings appears inside any node class name (case-insensitive)."all"— the tag applies only if every one of the rule’s target substrings appears inside at least one node class name."count"— the tag applies when the number of nodes that contain any of the rule’s target substrings reaches or exceeds the rule’sthresholdvalue (default5). Each node is counted at most once even if it matches several targets.
All comparisons are performed in lowercase, so rule authors should use lowercase target substrings.
- Parameters:
node_list – List of node class names harvested from a single template by the scanner pass. Need not be unique.
- Returns:
The tags whose rules matched, in arbitrary order. An empty list is returned when no rule matches.
- Return type:
list[str]
- Template_Manager.scanner.get_available_nodes() Set[str]
Build the set of node class names the current Nuke session can create.
When running inside Nuke the function combines four sources of truth to produce as complete a picture as possible:
CORE_NODES— the vanilla Nuke baseline shipped with the application.nuke.nodeTypes()— the live list of registered node classes, including any loaded via the application’s own startup logic.nuke.plugins(...)filtered to.gizmo,.so,.dyliband.dllextensions, with the extension stripped to recover the bare class name.Every menu item under
nuke.menu("Nodes"), recursively walked and parsed with a regex forcreateNode/createNodeLocalcalls. This catches gizmos that are exposed only through custom menus.
When running outside Nuke the function returns just
CORE_NODES, which is sufficient for offline scanning and development workflows. The returned set is stripped of incidental whitespace.- Returns:
All node class names the scanner should treat as resolvable in the current environment.
- Return type:
set[str]
- Template_Manager.scanner.is_running_in_nuke() bool
Detect whether the current Python process is hosted by Nuke.
The check imports the
nukemodule and verifies that thenodeTypesattribute exists, which is only true inside a real Nuke session. The standalonenukePyPI shim, if installed in a venv for development, lacks this attribute and is correctly rejected.- Returns:
Trueif the script is running inside a live Nuke application instance,Falseif the import fails or the imported module does not expose the Nuke API.- Return type:
bool
- Template_Manager.scanner.list_nk_files(folder_path: str) List[str]
Recursively enumerate every
.nkfile beneath a directory.The walk uses
os.walk(), so symlinked directories are followed according to the platform default. Filename matching is case-insensitive on the.nkextension, allowing files likeTemplate.NKto be found on case-sensitive filesystems.- Parameters:
folder_path – Absolute path of the directory to search. If the path does not exist or is not a directory the function returns an empty list rather than raising.
- Returns:
Absolute paths of every
.nkfile discovered. The order matches the traversal order ofos.walk()and is not explicitly sorted.- Return type:
list[str]
- Template_Manager.scanner.paste_template(tpl: Dict[str, Any]) None
Paste a scanned template into the current Nuke DAG.
Verifies that the template’s source file still exists on disk, then invokes
nuke.nodePasteto insert the nodes at the current cursor position in the node graph. If the file has been moved or deleted since the scan, the function prints a diagnostic and returns without raising. When called outside Nuke (for development) it prints what would have been pasted and returns.- Parameters:
tpl – A
Templaterecord whosepathfield points to the.nkfile to paste. No other fields are consulted.
- Template_Manager.scanner.scan_templates(folder_path: str, available_nodes: Set[str], ignored_words: Set[str] = {'Root'}) List[Dict[str, Any]]
Parse every
.nkfile under a directory and build template records.This is the core scanner entry point. For each
.nkfile found beneathfolder_paththe function:Reads file size and modification time and skips files that exceed
settings.MAX_FILE_SIZE_BYTES, marking them with the"FILE_TOO_LARGE"status.Consults the on-disk cache via
saves.load_cache()and reuses the cached parse result when the file’s modification time matches; otherwise re-parses the file from scratch and updates the cache.Extracts project settings from the
Rootblock when present, falling back to"AGNOSTIC"mode for templates without one.Detects Stamps plugin usage via signature string matching.
Identifies missing nodes by comparing the parsed class names against
available_nodesandCORE_NODES, with a trailing-digit-stripping heuristic to fold versioned node names (for exampleTracker4resolving toTracker).Merges manual user tags from
saves.load_metadata()with auto-tags fromget_auto_tags()for templates that have never been hand-tagged. Manual tags always take precedence once they exist.Bypasses standard Nuke API evaluation entirely, so malformed or untrusted scripts cannot crash the host process during scanning.
Any exception raised during parsing is captured into the template’s
errorsfield, the status is set to"READ_ERROR", and the scan continues with the next file.- Parameters:
folder_path – Absolute path of the directory tree to scan. Non-existent paths simply yield an empty result list.
available_nodes – Set of node class names known to the current Nuke environment, typically the return value of
get_available_nodes(). Used to flag missing dependencies.ignored_words – Tokens that match the node syntax but should not be treated as real nodes (typically just
IGNORED_WORDS).
- Returns:
One
Templaterecord per.nkfile discovered, populated with parsed metadata and a final status. Caller may sort or filter the list freely; the scanner makes no ordering guarantee.- Return type:
list[Template]
Template_Manager.settings module
Configuration and metadata management for the Template Manager.
This module handles disk I/O for JSON configuration files. It establishes a hierarchy for locating the main config file (prioritizing a studio-wide environment variable before falling back to the local user directory) and manages the reading/writing of custom template metadata.
Module-level constants in this file define the on-disk locations of every
database file the plugin uses, as well as fallback defaults used by the
scanner when project metadata cannot be parsed from a .nk file.
- Template_Manager.settings.STUDIO_ENV_VAR
Name of the environment variable consulted first for the location of the configuration file. Setting this to an existing path lets a studio override every artist’s local configuration with a centrally managed file.
- Type:
str
- Template_Manager.settings.CONFIG_ROOT
Absolute path to the directory where Template Manager stores its per-user configuration and database files. Defaults to
~/.nuke/Template_Manager.- Type:
str
- Template_Manager.settings.LOCAL_CONFIG_PATH
Absolute path to the local configuration JSON file used when
STUDIO_ENV_VARis unset or points to a missing file.- Type:
str
- Template_Manager.settings.DEFAULT_TEMPLATE_PATH
Hardcoded fallback directory used to resolve template paths when no path is configured. Defaults to
~/.nuke/templates.- Type:
str
- Template_Manager.settings.CACHE_PATH
Absolute path to the scanner cache JSON file, used by
savesto memoize parsed node data between launches.- Type:
str
- Template_Manager.settings.METADATA_PATH
Absolute path to the manual user tag database JSON file, used by
savesto persist per-template tag overrides.- Type:
str
- Template_Manager.settings.AUTO_TAGS_PATH
Absolute path to the auto-tagging rules JSON file, loaded and saved by
savesand edited via theui.AutoTagRulesDialogUI.- Type:
str
- Template_Manager.settings.MAX_FILE_SIZE_BYTES
Hard limit (in bytes) above which the scanner refuses to parse a
.nkfile. Files exceeding this threshold are flagged with theFILE_TOO_LARGEstatus and skipped.- Type:
int
- Template_Manager.settings.DEFAULT_PROJECT_FPS
Fallback frames-per-second value used when a template’s
Rootblock contains nofpsentry.- Type:
float
- Template_Manager.settings.DEFAULT_PROJECT_RESOLUTION
Fallback
(width, height)used when a template’sRootblock contains noformatentry.- Type:
tuple[int, int]
- Template_Manager.settings.DEFAULT_PROJECT_COLORSPACE
Fallback colour management value used when a template’s
Rootblock contains neitherOCIO_confignorcolorManagemententries.- Type:
str
- Template_Manager.settings.get_config_path() str
Determine the absolute path to the active configuration file.
The function consults two sources, in order of priority:
The environment variable named by
STUDIO_ENV_VAR. If that variable is set and points to a path that exists on disk, the function returns it unchanged. This allows a studio pipeline to deploy a centrally managed config file to every artist without touching their local home directory.The local path
LOCAL_CONFIG_PATHunder the user’s home directory. If the parent directory does not yet exist it is created (along with any missing intermediates) so subsequent writes succeed.
- Returns:
Absolute path to the JSON configuration file the plugin should read from and write to for this session. The returned path may not yet exist on disk; callers must handle missing files themselves.
- Return type:
str
- Template_Manager.settings.get_effective_template_paths() List[str]
Retrieve every existing directory the scanner should index.
The function reads the configuration file via
load_config_data()and resolves the effective list of template root directories using the following fallback chain:The
template_pathskey, expected to be a list of strings.The legacy
template_pathkey, expected to be a single string; wrapped in a one-element list for backward compatibility with configurations produced by earlier plugin versions.If neither key is present or yields any valid directory,
DEFAULT_TEMPLATE_PATHis created on disk (if it does not already exist) and returned as the sole fallback.
All candidate paths are filtered through
os.path.isdir(), so stale entries pointing at deleted directories are silently dropped rather than producing errors during scanning.- Returns:
A list of absolute directory paths that currently exist on disk and should be scanned for
.nktemplates. Always contains at least one entry, sinceDEFAULT_TEMPLATE_PATHis created and returned when no configured path resolves.- Return type:
list[str]
- Template_Manager.settings.get_tags() List[str]
Retrieve the globally configured list of available tag strings.
Reads the
tagskey from the main configuration file. The returned list is intended to serve as the master vocabulary shown in the UI’s tag autocomplete and batch-tagging dialogs. It is independent of the per-template manual tags stored in the metadata database.- Returns:
The list of predefined tag strings, in the order they appear in the configuration file. Returns an empty list if the configuration file is missing or contains no
tagsentry.- Return type:
list[str]
- Template_Manager.settings.load_config_data() dict
Load and parse the main configuration JSON file.
Resolves the active config path via
get_config_path()and reads it as UTF-8 encoded JSON. Any error during file access or JSON decoding is caught and logged to standard output; the function then returns an empty dictionary so the rest of the plugin can continue with default behaviour rather than crashing.- Returns:
The parsed top-level JSON object from the configuration file, or an empty dictionary if the file does not exist, cannot be read, or contains invalid JSON.
- Return type:
dict
- Template_Manager.settings.use_folder_categories() bool
Check whether the UI should group templates by parent folder.
When this setting is enabled, the main Template Manager dialog organises templates into a hierarchical tree mirroring their on-disk folder structure. When disabled, templates are presented in a flat list.
- Returns:
Trueif folder-based categorisation is enabled (the default when the key is absent),Falseif the user has explicitly opted out via the configuration file.- Return type:
bool
Template_Manager.ui module
PySide graphical user interface for the Nuke Template Manager.
This module builds every Qt dialog the plugin exposes to artists. It is designed to work transparently against both PySide6 (newer Nuke releases) and PySide2 (older releases) by attempting the PySide6 import first and falling back if it is unavailable.
The module owns six widget classes:
TemplateManagerUI— the main browser window: a searchable, taggable, hierarchical view of every scanned template.SaveTemplateDialog— the form used to choose a project, subfolder, name, and versioning behaviour for a new template save.BatchTagDialog— the small dialog driving the right-click Batch Tag action on multiple selected templates.PlaceholderDialog— the checklist that lets artists decide which Read nodes to swap with Placeholder NoOps during save or import.AutoTagRulesDialog— the form-based editor for the auto-tagging rule set persisted bysaves.RuleWidget— a single editable row inside the rules dialog.
The free function get_nuke_main_window() provides the parent
widget every dialog uses so the windows float above Nuke rather than
the desktop.
- class Template_Manager.ui.AutoTagRulesDialog(*args: Any, **kwargs: Any)
Bases:
QDialogA form-based editor for the auto-tagging rule set.
Displays the current rule set as a scrollable list of
RuleWidgetrows. The user can add new rules with the “+ Add New Rule” button, remove any existing rule with its row’s X button, and persist the complete edited set with the Save button (which in turn callssaves.save_auto_tag_rules()). The Cancel button discards every change made since the dialog opened.Rule changes take effect on the next scan or on the next use of the Re-Evaluate Auto-Tags context menu action; already-loaded templates in an open browser window are unaffected.
- Parameters:
parent (QWidget, optional) – Parent widget for the dialog, typically Nuke’s main window obtained via
get_nuke_main_window(). Defaults toNone.
- add_empty_rule()
Append a new blank rule row to the dialog.
Wired to the “+ Add New Rule” button. The created row carries no initial tag name and an empty rule dictionary, ready for the user to fill in. The row is appended to the bottom of the scrollable list, never inserted in the middle.
- add_rule_widget(tag_name, rule_data)
Create a single
RuleWidgetand wire its delete button.Instantiates the row widget pre-populated with the supplied tag name and rule data, connects its X button to
remove_rule(), adds it to the scrollable rules layout, and records it inrule_widgetssosave_rules()can iterate over every active row later.- Parameters:
tag_name (str) – Tag name to pre-fill in the row’s tag input. Pass
""for empty rows.rule_data (dict) – Rule dictionary to pre-fill in the row’s controls. Pass
{}for empty rows.
- load_rules()
Load the persisted rule set from disk and populate the dialog.
Calls
saves.load_auto_tag_rules()to read the current on-disk JSON, then creates oneRuleWidgetrow per rule entry by delegating toadd_rule_widget(). Invoked once during initialisation; never called again afterwards.
- remove_rule(rw)
Remove a row widget from the dialog and schedule its destruction.
Wired to each
RuleWidget’s X button via the lambda inadd_rule_widget(). Detaches the widget from the layout, callsdeleteLaterto schedule its disposal on the next event-loop iteration, and removes the reference fromrule_widgetsso it cannot be re-saved.- Parameters:
rw (RuleWidget) – The row to remove.
- save_rules()
Collect every row’s data, persist it, and close the dialog.
Iterates over every
RuleWidgetinrule_widgets, callsRuleWidget.get_data()on each, and assembles the results into a single dictionary suitable forsaves.save_auto_tag_rules(). Rows whose tag name is empty are silently dropped (theirget_datareturn is(None, None)). After the JSON has been written the user is informed vianuke.message()and the dialog accepts.
- class Template_Manager.ui.BatchTagDialog(*args: Any, **kwargs: Any)
Bases:
QDialogModal dialog letting the user batch-tag multiple selected templates.
Presents a single comma-separated tag input and two action buttons:
Overwrite replaces the tag list on every selected template with the typed tags, discarding whatever was there before.
Append merges the typed tags into each template’s existing tag list, deduplicating the result.
The chosen mode is stored in
mode(either"append"or"overwrite") and the parsed tag list intags, ready for the caller to consume after the dialog is accepted.- Parameters:
parent (QWidget, optional) – Parent widget for the dialog. Defaults to
None.
- accept_append()
Set the mode to
"append"and accept the dialog.Wired to the Append button. Records the chosen mode and delegates the actual tag parsing to
_process_tags()before the dialog closes.
- accept_overwrite()
Set the mode to
"overwrite"and accept the dialog.Wired to the Overwrite button. Records the chosen mode and delegates the actual tag parsing to
_process_tags()before the dialog closes.
- class Template_Manager.ui.PlaceholderDialog(*args: Any, **kwargs: Any)
Bases:
QDialogModal checklist for choosing which Read nodes to swap with Placeholders.
Used by both the save flow (where the input list is a sequence of live
nuke.Nodeobjects) and the import flow (where the input list is a sequence of(name, file_path)tuples harvested by parsing the template’s raw text). The dialog transparently handles either input form, presenting each entry as a single check-box item showing the node name alongside its associated file’s basename.Every entry starts in the checked state; the user unchecks any Read nodes that should be preserved as-is. The selected entries are returned by
get_nodes_to_convert()as a list of whichever object form was originally supplied (live nodes or name strings).- Parameters:
read_items (list) – The Read nodes or
(name, file_path)tuples to display. The two forms can be mixed in a single dialog but typically are not.parent (QWidget, optional) – Parent widget. Defaults to
None.
- get_nodes_to_convert()
Return the original objects for every checked entry.
Walks
node_dataand returns the second element of each pair (the originalnuke.Nodeor the node-name string, depending on which form was supplied at construction) for every list item still in the checked state.- Returns:
The subset of the originally-supplied objects that the user left checked, in the same order they were added to the dialog. The empty list is a valid return value and simply means the user unchecked everything.
- Return type:
list
- class Template_Manager.ui.RuleWidget(*args: Any, **kwargs: Any)
Bases:
QWidgetA single editable row inside the auto-tag rules dialog.
Each row exposes four editable fields plus a delete button:
Tag Name — the tag that this rule emits when it matches.
Type — a dropdown choosing between OR (the JSON
anytype), AND (all), and How Many (count).Threshold — an integer spin box, visible only when the type is How Many, controlling the minimum match count.
Nodes — a comma-separated list of lowercase node class substrings to match against the templates being scanned.
X — a remove button that destroys this row.
The widget translates between the rule dictionary schema used by
saves.DEFAULT_TAG_RULESand the UI controls transparently:__init__()deserialises a rule into the widgets, andget_data()serialises the widget state back into a rule.- Parameters:
tag_name (str) – Initial tag name to display in the input field. Defaults to an empty string for new rules.
rule_data (dict, optional) – Initial rule dictionary, with the keys
type,nodesand (for count rules)threshold. Defaults toNone, which is treated as an empty rule.parent (QWidget, optional) – Parent widget. Defaults to
None.
- get_data()
Serialise the row’s UI state into a rule dictionary.
Reads the four user-editable fields, sanitises them (stripping whitespace and splitting the comma-separated node list), and builds a rule dictionary in the schema consumed by
scanner.get_auto_tags()and persisted bysaves.save_auto_tag_rules(). Rows whose tag-name field is empty are treated as deletable and return a pair ofNonevalues so the caller can drop them.- Returns:
A 2-tuple
(tag_name, rule_dict).tag_name(str | None) — the cleaned tag string, orNonewhen the row should be dropped because its tag name is empty.rule_dict(dict | None) — a rule dictionary with the keystype(one of"any","all","count"),nodes(list of substrings), and for the count typethreshold(int).Nonewhen the row should be dropped.
- Return type:
tuple
- on_type_changed(index)
Show or hide the threshold spinner when the rule type changes.
The threshold value is only meaningful for the How Many (
count) rule type, so the spin box stays hidden in every other mode to keep the row visually compact.- Parameters:
index (int) – The newly selected index in the type dropdown.
2corresponds to How Many; any other value hides the spinner.
- class Template_Manager.ui.SaveTemplateDialog(*args: Any, **kwargs: Any)
Bases:
QDialogA dialog for saving new templates from Nuke’s node graph.
The dialog gathers four pieces of information from the user:
The template’s base name (used as the filename stem).
A project, either chosen from the dropdown of existing projects or created on the fly via the “[ + Create New Project ]” option.
An optional subfolder path within the project, selectable from a mini-tree of known subfolders or typed directly.
Whether to auto-version the saved file with a
_v##suffix.
- Parameters:
projects_dict (dict) – Mapping of project display names to sets of known subfolder paths. Used to populate both the project dropdown and the per-project subfolder tree.
project_raw_map (dict) – Mapping of project display names to their raw on-disk folder names. The display name is the title-cased, space-separated form shown to the user; the raw name is the snake-cased folder name used on disk.
detected_project (str | None) – Project name to pre-select in the dropdown, typically derived from the active Nuke script’s filename by
main.launch_save_ui(). PassNoneto leave the dropdown on its first entry.default_root (str) – Filesystem path used as the base directory under which the new template will be written.
parent (QWidget, optional) – Parent widget for the dialog. Defaults to
None, producing a free-floating top-level window.
- get_save_data()
Return the validated save parameters chosen by the user.
Reads every input field, trims whitespace, replaces spaces with underscores in path-bound strings, normalises slashes for cross-platform safety, and assembles the absolute target directory. The returned
base_nameis the template’s filename stem with no extension and no version suffix; the Save Template flow combines it with the path and the version suffix downstream viasaves.get_save_path().- Returns:
A 3-tuple
(base_name, final_folder_path, do_version).base_name(str) — the sanitised template filename stem.final_folder_path(str) — the absolute directory the template should be written into, including the project and subfolder components.do_version(bool) —Trueif auto-versioning is enabled,Falseif the user disabled it.
- Return type:
tuple
- on_project_changed()
Handle a change in the Project dropdown selection.
Shows the new-project text input only when the user selects the synthetic
[ + Create New Project ]entry, hiding it in every other case so the form stays compact. Triggers a rebuild of the subfolder tree to reflect the newly selected project’s known subfolders.
- on_tree_item_clicked(item, column)
Copy a clicked tree path into the subfolder text input.
Reads the full subfolder path stored on the clicked tree node (as
UserRoledata) and writes it into the text input so the user can edit it further or accept it as-is.- Parameters:
item (QtWidgets.QTreeWidgetItem) – The tree node the user clicked.
column (int) – The column index of the click. Unused; the path is stored on column 0 regardless.
- update_subfolder_tree()
Rebuild the subfolder mini-tree from the current project’s data.
Looks up the currently selected project in
projects_dictand populates the tree widget with every known subfolder path beneath that project, splitting on forward slashes to build the hierarchical structure. When the special"My Templates (Root)"entry is selected the tree is disabled entirely because root-level templates have no subfolder. The tree is fully expanded after population so artists can see every known path at a glance.
- class Template_Manager.ui.TemplateManagerUI(*args: Any, **kwargs: Any)
Bases:
QDialogThe main browser window for the Template Manager plugin.
The window presents every scanned template as a row in a multi-column tree view, organised by project (via the dropdown) and by subfolder (as expandable tree nodes). Core features exposed through the UI include:
A live search bar supporting plain text matches against template names and
@tagqueries against tag metadata, with autocomplete suggestions drawn from the union of every tag in the library.A Project Settings column summarising each template’s frame rate, resolution, and colour management, with a one-click prompt to update the current Nuke script’s project settings to match the template at import time.
Inline tag editing in the Tags column, plus right-click batch tagging and a Re-Evaluate Auto-Tags action that re-runs the rule engine against the current template contents.
Procedural per-tag colouring derived from the tag string, keeping similar tags visually consistent across sessions.
Smart auto-detection of the active Nuke script’s project, with matching template rows pre-expanded and scrolled into view on launch.
- Parameters:
templates (list[dict]) – The master list of scanned template dictionaries produced by
scanner.scan_templates().has_stamps (bool) –
Trueif the Stamps plugin was found in the current Python environment. Reserved for future Stamps-aware UI behaviour; carried through from the scanner pass.
- auto_detect_project()
Attempt to guess the active project from the current Nuke script name.
Uses three heuristics in descending priority:
Exact template base-name match against the script filename.
Filename prefix match against template prefixes in each project.
Fallback folder-name match against the script path components.
Sets
auto_target_base_nameandauto_expand_prefixesas instance attributes sorefresh_treecan highlight and expand the relevant rows.
- execute_import(filepath)
Import a template file, optionally swapping Read nodes to Placeholders.
The function does not modify the on-disk template. Instead it reads the
.nksource into memory, optionally rewrites the in-memory text to replace selectedRead { ... }blocks with red-tile-colouredNoOpplaceholders preserving the original node names and DAG positions, writes the modified text to a hidden temporary file under~/.nuke/Template_Manager/.temp_import.nk, and pastes that temporary file vianuke.nodePaste. The temporary file is always deleted before the function returns, even on paste failure.The user is prompted via
PlaceholderDialogto choose which Read nodes (if any) should be converted. Cancelling that dialog aborts the import.- Parameters:
filepath (str) – Absolute path to the source
.nktemplate file. Must be readable; failures during the initial read are logged but do not abort the import (the paste will simply use the original file).- Returns:
Trueif the paste completed successfully,Falseif the user cancelled the placeholder dialog or the Nuke paste call raised an exception.- Return type:
bool
- filter_current_project()
Trigger a tree rebuild when the search bar text changes.
Wired to the search bar’s
textChangedsignal. Delegating torefresh_tree()ensures the filter logic, sort logic, and folder-expansion-preservation logic stay in one place.
- get_tag_color(tag_string)
Generate a procedural QColor derived from a tag string.
The hue is computed by summing position-weighted character ordinals and then multiplying by a prime step to spread values across the 360-degree hue wheel. Saturation and value are fixed to keep colours vivid but consistent with the UI palette.
- Parameters:
tag_string (str) – The tag whose colour should be calculated.
- Returns:
An HSV colour unique to the given tag string.
- Return type:
QtGui.QColor
- group_templates_by_project()
Populate
projects_dictby parsing every template’s path context.Also stores
_hierarchyback onto each template dict and buildsproject_raw_mapfor display-name-to-raw-folder lookups.
- group_versions(template_list)
Group templates by base name and sort each group by version descending.
Templates whose names end in
_v##are clustered together under the un-versioned base name. Templates without a version suffix receive version number0and are keyed by their absolute file path to guarantee uniqueness — same-named templates in different subfolders will never collide. The display label is always read fromtpl['name'], not from the dict key.- Parameters:
template_list (list[dict]) – A filtered list of template metadata dicts.
- Returns:
- Mapping of
base_name→ sorted list of(version, tpl)tuples, highest version first.
- Mapping of
- Return type:
dict
- import_from_button()
Trigger the import flow from the Import Selected button.
Validates that at least one tree item is selected, then delegates to
import_template()with column0as if the user had double-clicked the row directly. When the selection is empty, the user is informed vianuke.message()and no action is taken.
- import_template(item, column)
Import the template represented by a tree item into Nuke.
Triggered by a double-click on the tree widget or by the Import Selected button. The behaviour depends on which column the user double-clicked and on the template’s status:
Clicks on columns 0–3 trigger the import flow. Before the paste, the function compares the template’s project settings (frame rate, resolution, colour management) against the current Nuke script and, if they differ, opens a three-way dialog letting the user update the project, import the template’s nodes without touching the project settings, or cancel.
Clicks on column 4 (Tags) instead put the cell into edit mode so the user can change tags inline.
Templates with a
MISSING_NODESstatus produce an additional confirmation prompt before the paste actually runs.Templates with a
READ_ERRORstatus are silently ignored.
On a successful paste the manager window closes; on a user cancellation or paste failure it stays open so the user can try a different template.
- Parameters:
item (QtWidgets.QTreeWidgetItem) – The tree item the user clicked. Must carry a template dictionary on
UserRolefor column 0; folder rows are ignored.column (int) – The column index of the click.
- natural_sort_key(base_name, template_dict)
Generate a key for natural alphanumeric sorting (e.g., v2 comes before v20).
- Parameters:
base_name (str) – The display name of the template entry.
template_dict (dict) – The template metadata dictionary containing
_hierarchy.
- Returns:
A mixed list of strings and ints suitable for use as a sort key.
- Return type:
list
- on_header_clicked(logical_index)
Intercept header clicks to perform a safe Python sort instead of a destructive Qt sort.
- Parameters:
logical_index (int) – The column index that was clicked.
Show the right-click context menu and dispatch the chosen action.
Builds a context menu offering two actions on the currently selected template rows: Batch Tag (opens
BatchTagDialogto apply or replace tags on every selected row at once) and Re-Evaluate Auto-Tags (re-parses each selected.nkfile and replaces its tags with the output of the current auto-tag rule engine, prompting the user once for confirmation first).Folder rows that carry no template data are filtered out before the menu is built; if no real template rows are selected the menu does not appear.
- Parameters:
position (QtCore.QPoint) – The click position in tree viewport coordinates, used to anchor the popup menu.
- parse_path_context(template_path)
Split a template path into Project Display name, Project Raw name, and Hierarchy.
- Parameters:
template_path (str) – The absolute filesystem path of the template file.
- Returns:
- A 3-tuple of
(proj_display, proj_raw, hierarchy)where hierarchy is a list of sub-folder display names below the project root.
- A 3-tuple of
- Return type:
tuple
- refresh_tree()
Rebuild the tree widget based on the selected project and current search text.
Preserves the expanded state of folder nodes across rebuilds, applies auto-detection highlights set by
auto_detect_project(), and performs a Python-side natural sort so Qt’s built-in sort cannot destroy the folder hierarchy.
- save_inline_tags(item, column)
Update template metadata and sync memory state after inline tag editing.
Called automatically by the
itemChangedsignal. Only processes changes to column 3 (the Tags column). Persists the new tags to disk viasaves.save_metadata()and refreshes the autocomplete model.- Parameters:
item (QTreeWidgetItem) – The item whose cell was edited.
column (int) – The column that changed.
- save_new_template()
Run the in-UI Save Template flow against the current Nuke selection.
Captures the current script’s root settings (format, fps, colorManagement, OCIO_config) into a
template_contextdict, or sets it toNonewhen the settings match the agnostic defaults (2048x1556, 24fps, “Nuke” colorManagement).Builds
projects_dict(display name -> set of known subfolder paths) andproject_raw_mapfrom the currently loaded templates, then opensSaveTemplateDialog. On acceptance, resolves the final save path viasaves.get_save_path(), optionally prompts for overwrite confirmation, and writes the nodes withnuke.nodeCopy. Becausenuke.nodeCopyonly copies nodes and not project-level settings, aRoot { ... }block built fromtemplate_contextis then prepended to the saved.nkfile when a non-agnostic context was captured.It also intercepts Read nodes and prompts the user to convert them to Placeholders.
Any Read-to-Placeholder swap performed during the save is reverted by an undo in the
finallyblock so the artist’s Nuke script is left exactly as it was before the save.
- update_autocomplete()
Refresh the search-bar QCompleter model with current tags.
Recomputes the set of every tag attached to any template in
alltemplates, prefixes each with@, sorts the result, and installs it as the completer’s data source so newly-added tags appear in autocomplete suggestions immediately after they are saved.
- Template_Manager.ui.delete_on_close(widget)
Mark a Qt widget for deletion when closed.
- Template_Manager.ui.exec_dialog(dialog)
Compatible dialog exec for PySide2 and PySide6.
Compatible menu exec for PySide2 and PySide6.
- Template_Manager.ui.get_nuke_main_window()
Locate Nuke’s main dock window so dialogs can parent themselves to it.
Walks every top-level widget known to the running Qt application and returns the first one whose class name matches Nuke’s internal dock-main-window class. Parenting plugin dialogs to this widget ensures they float on top of the host application and respect Nuke’s window-stacking rules rather than the desktop’s.
- Returns:
The detected main window instance, or
Noneif no widget matches (for example when running outside Nuke). Callers should tolerate theNonecase by parenting their dialogs toNone, which produces a free-floating top-level window.- Return type:
QtWidgets.QMainWindow | None
- Template_Manager.ui.show_about_dialog(parent=None)
Display a native Qt About dialog with tool and contact details.