feat(utility): add printf-style frame pattern support (%04d)#235
Open
throb wants to merge 18 commits intoAcademySoftwareFoundation:mainfrom
Open
feat(utility): add printf-style frame pattern support (%04d)#235throb wants to merge 18 commits intoAcademySoftwareFoundation:mainfrom
throb wants to merge 18 commits intoAcademySoftwareFoundation:mainfrom
Conversation
…e loading
Three issues prevented image sequences (EXR, etc.) from loading on Windows:
1. Broken backslash regex in scan_posix_path() - the character class [\]
matched ']' instead of '\', leaving backslashes in scanned file paths.
2. pad_size() returned 0 for non-zero-padded frame numbers (e.g. "1000"),
producing invalid %00d / {:00d} format specifiers that failed extension
matching in is_file_supported().
3. posix_path_to_uri() did not normalise backslashes to forward slashes on
Windows, leaking them into file: URIs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add --review / -v CLI flag to launch xstudio in "Present" layout (viewport only, no playlists or timeline). This overrides saved user layout preferences on startup. Also add drag-drop handling to the viewport panel so files can be dropped directly onto the viewer in any layout. Previously drops were only handled by the media list panel, which doesn't exist in the Present layout. Bump version to 1.1.1. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove Gamma and Saturation from the default hidden toolbar items so they are visible by default in the viewport toolbar. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EXR Performance: - Dispatch up to 4 concurrent precache requests in do_precache() - Add configurable EXR decompression thread count preference (default 16) - Fix off-by-one in EXR resolution reporting (max-min → max-min+1) - Crop data window to display window by default (0% overscan) - Add standalone EXR benchmark tool Hotkey Editor: - Replace read-only hotkey viewer with full interactive editor - Click-to-capture key rebinding with conflict detection and warnings - Persistent hotkey overrides saved to %LOCALAPPDATA%/xstudio/ - Search filtering, per-key and reset-all functionality - Scrollbar for overflow content Viewport Fixes: - Fix SSBO shader debug colors (red/blue → black) for out-of-bounds pixels - Fix FBO texture wrap mode (GL_CLAMP_TO_EDGE → GL_CLAMP_TO_BORDER) - Fix overscan display: crop EXR data window to display window by default Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a Layer dropdown to the OCIO colour pipeline plugin that lets users switch between EXR layers/AOVs (e.g. RGBA, sky, mask, displace) directly from the viewport toolbar and right-click context menu. The backend stream switching already existed — this wires it to the UI: - New StringChoiceAttribute populated dynamically from media streams - Sends current_media_stream_atom on selection change - Base ColourPipeline stores media source actor ref for stream queries - CLAUDE.md updated with correct plugin deployment paths Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extracted from PR AcademySoftwareFoundation#198 and adapted for Windows. Provides a VFX-oriented filesystem browser panel with directory tree, file sequence detection (via fileseq), version grouping, and thumbnail generation. Key Windows fixes: - Drive letter enumeration under virtual "/" root ("This PC") - Case-insensitive path comparison throughout QML tree - Forward-slash normalization on all path returns - Fixed shadowed `time` import in _get_subdirs - Direct attribute write from DirectoryTree (bypasses signal chain) - Tree auto-syncs to current path on launch - Up-directory button in path bar - Depth spinner persists across sessions (title mismatch fix) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Cache dump_json_headers() per part index — metadata is identical across all frames in a sequence, eliminates ~400 RTTI dynamic_casts per frame - Cache MultiPartInputFile handle — reuse when same file path is re-read (scrub-back, multi-stream), avoids repeated open+header-parse syscalls - Batch precache cache checks — single preserve_atom message per group instead of N individual request/response round-trips to cache actor - Bump max_in_flight from 4 to 8 for better pipeline saturation on multi-core CPUs (benchmark: 83→88 fps on 32-thread system) Benchmark on 4312x2274 ZIPS EXR (NVMe): confirms no regression, app-level overhead reduced by eliminating per-frame redundant work. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ions - Add missing single-click directory navigation in file list view (onClicked only handled files, completely ignored folder clicks) - Add folder navigation to thumbnail view click handler - Fix directory tree command channel race: change_path and get_subdirs fired simultaneously through same attribute, one stomping the other. Added 100ms sync delay so get_subdirs waits for change_path to finish. - Clear file list immediately on path change for instant visual feedback (previously old results lingered until new scan completed) - Auto-expand selected node in directory tree on navigation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add right-click "Add/Remove from Favorites" on folders in file list and directory tree, fix add_pin bug (missing name parameter) - Add multi-select: Ctrl+click toggles, Shift+click range selects - Add "Load N Selected Files" context menu and batch double-click - Add directory tree right-click context menu with favorites and scan - Remove duplicate unreachable remove_pin handler Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Show trim/move drag handles on clip hover in Select mode - Suppress slip handles (leftleft/rightright) in Select mode to avoid visual doubling with basic trim handles - Add clip:true to XsClipItem to prevent handle overflow - Fix rightright drag indicator height when reparented to ancestor - Add Fit Selection and Fit All menu items to timeline context menu Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Alt+wheel zoom centered on cursor position in timeline - Shift+Z hotkey to zoom-to-fit all clips - Ctrl+wheel zoom improved with multiplicative scaling - Drag files from filesystem browser directly onto timeline tracks - Auto-create video/audio tracks when dropping on Stack - Compare Items: select multiple files, right-click to load in A/B or Grid compare mode Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add "Add to Timeline" right-click menu item in filesystem browser that creates clips directly on the active sequence (or creates a new one) - Fix Playlist type checking: use isinstance(item, Playlist) instead of hasattr(item, 'add_media') to prevent Timeline/Subset crashes - Fix drag-drop URI format: use file:/// (three slashes) for Windows paths - Add text/uri-list detection in global drag handler for Drag.Internal drops - Add External source handling in timeline drag handler - Document QML rebuild requirement in CLAUDE.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EXR files with hierarchical channel names (e.g. bg_wall.Combined.R, fg_rocks.Diffuse Direct.B) were causing "Unable to choose decoder routines" errors. The layer grouping split on the first dot, creating layers with 30+ channels, but the reader only supports 4 channels per layer (RGBA). Reading past the 4-element pix_type array produced garbage pixel types that OpenEXR's decoder rejected. Fix: split on the last dot (rfind) so bg_wall.Combined.R produces layer "bg_wall.Combined" with channel "R". Also add defensive caps to prevent array out-of-bounds if a layer still exceeds 4 channels. Also fix filesystem browser sequence path handling for Add to Timeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… Linux Shell script and batch file wrapping CMake configure/build/deploy workflow with auto-detected presets, portable deployment, and QML cache management. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added to .gitignore to keep project-specific AI instructions local only. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three path handling bugs in URI conversion broke session restore:
- reverse_remap_file_path() was passed the original path instead of
the resolved absolute path, discarding relative path resolution
- Drive letter regex only matched uppercase [A-Z], missing lowercase
- file URIs used host("localhost") causing parsing mismatches on
deserialization; switched to host("") for standard file:///C:/ form
Timeline panel also failed to populate on session load due to:
- Model tree container lookup firing before async children arrived;
added re-trigger in processChildren() for Session/Playlist types
- viewedMediaSetChanged() only handled typeRole=="Timeline" but the
restored viewed container is often a Playlist; added logic to find
the first Timeline child inside the Playlist and switch to it
Also updates README to document fork changes and remove the session
restore issue from known issues.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add support for printf-style frame sequence patterns (e.g. %04d, %06d)
in parse_cli_posix_path(), complementing the existing hash (####) and
fmt ({:04d}) pattern support. This is the standard format used by
ShotGrid, Nuke, Houdini, and most VFX production tracking tools.
Changes:
- helpers.cpp: Add regex matching for %0Nd patterns, converting to
{:0Nd} internally. Also handle Nuke-style space-separated frame
ranges ("file.%04d.exr 1000-1080") by normalizing to equals syntax.
- frame_list.cpp: Add defensive %0Nd -> {:0Nd} conversion in
frame_groups_from_sequence_spec() for paths that bypass the main
parser.
All existing patterns continue to work unchanged. New supported inputs:
file.%04d.exr=1000-1080 (printf + equals range)
file.%04d.exr 1000-1080 (printf + space range, Nuke style)
file.1234.%04d.exr (printf with prefix frame number)
/full/path/shot.%06d.exr (variable padding width)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
%04d,%06d, etc.) toparse_cli_posix_path(), complementing existing hash (####) and fmt ({:04d}) patternsfile.%04d.exr 1000-1080) in addition to equals syntax (file.%04d.exr=1000-1080)frame_groups_from_sequence_spec()for paths that bypass the main parserMotivation
Printf-style frame patterns are the standard format used by ShotGrid/Flow Production Tracking, Nuke, Houdini, and most VFX pipeline tools. Without this, integrating xSTUDIO with production tracking systems requires workarounds like directory scanning instead of direct path loading.
Changes
src/utility/src/helpers.cppxstudio_printfandxstudio_prefix_printfregex patterns,printf_to_fmtconverter, space-separated range normalizationsrc/utility/src/frame_list.cpp%0Nd→{:0Nd}conversion inframe_groups_from_sequence_spec()Supported inputs (new)
All existing patterns (
####,{:04d},=range) continue to work unchanged.Test plan
parse_posix_path("test.%04d.exr=1000-1080")→ URItest.{:04d}.exr, FrameList1000-1080parse_posix_path("test.%04d.exr 1000-1080")→ same result (space-separated)parse_posix_path("test.####.exr 1000-1080")→ hash + space also worksparse_posix_path("test.{:04d}.exr 1000-1080")→ fmt + space also worksparse_posix_path("shot.%06d.exr 100-200")→ variable padding width🤖 Generated with Claude Code