Skip to content

Commit 35fffac

Browse files
committed
Release v1.3.7: title-bar version + first-selection preview zoom + parameter-node UI on add
- Move app version + effect-library version from status-bar to title bar so the FPS / timing readout has room on the right. - First selection of a node now defers FitPreviewToView until the next eval populates cachedOutput; previously the immediate fit measured an empty rect and produced the wrong zoom until the user re-selected. - Clock / parameter nodes now show their on-node UI (play button, seek slider) immediately on add. The add path now sets m_forceRender = true so the post-eval RebuildLayout runs once with live analysis output instead of waiting for the user to click the node.
1 parent 5c76ecd commit 35fffac

5 files changed

Lines changed: 53 additions & 22 deletions

File tree

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,30 @@
33
All notable changes to ShaderLab will be documented in this file.
44
Format follows [Keep a Changelog](https://keepachangelog.com/).
55

6+
## [1.3.7] - 2026-05-05
7+
8+
### Changed
9+
- Moved the version + effect-library version readout from the bottom-status-bar to the title bar. Frees the right side of the status bar so the FPS / frame-timing readout has room to breathe (it had been clipping against the version text on smaller windows).
10+
11+
### Fixed
12+
- First selection of a node in a freshly-loaded graph or a freshly-added node would render the preview at the wrong zoom (whatever the previous viewport happened to be). Subsequent selections were correct because by then the cached output existed. Now click defers `FitPreviewToView` until the next eval has populated `cachedOutput`, so the very first fit measures real bounds.
13+
- Newly-added Clock and other parameter nodes did not show their on-node UI (play/pause button, seek slider) until the user clicked them. The post-eval `RebuildLayout` only fired on user-forced renders; the add-node path now sets `m_forceRender = true`, triggering the same path so the controls appear on the first frame after add.
14+
15+
## [1.3.6] - 2026-05-05
16+
17+
### Fixed
18+
- Save / load of `.effectgraph` archives with embedded media froze the UI for tens of seconds while miniz compressed/decompressed. The ProgressBar painted once at the initial 16 ms yield then sat unchanged because the work ran synchronously on the UI thread. The save/load now runs on a threadpool thread (miniz is pure native, no WinRT marshalling concerns) and the progress callback marshals each update back through `DispatcherQueue` so the bar animates smoothly.
19+
- Video sources bound to a paused Clock free-ran in a ~1 s loop instead of holding a static frame. Cause: `TickAndUploadVideos` advanced the decoder via `provider->Tick(deltaSec)` whenever the bound `Time` value didn't differ from the current decode position by more than one frame, then the next iteration's "small forward gap" branch let it drift further. Fixed by remembering each provider's previous bound `Time` value — if it didn't change between ticks, hold the frame at exactly that position rather than ticking.
20+
21+
### Internal
22+
- Resolved compiler warnings: `C4456` (shadowed `first` local in `WriteNodeJson`), `C4189` (unused `slashPos`, `imgDipX/Y`, `isPixelTraceTab`), `C4100` (unreferenced `sender` parameter on `OnPreviewPointerMoved`).
23+
24+
## [1.3.5] - 2026-05-05
25+
26+
### Fixed
27+
- Right-hand properties panel jittered horizontally during video playback. Cause: every 250 ms while ANY graph node was dirty (always true while a video was playing) we rebuilt the entire properties panel, re-creating Slider + NumberBox pairs whose auto widths varied frame to frame. Now the rebuild only fires when the selected node has at least one `propertyBinding` whose live value can change between ticks.
28+
- Visual Assets (app tile, splash, badges) were broken in shipped MSIX. The `Assets/` directory contained 21 corrupted `*.scale-200.scale-N.png` files (VS regenerated them by feeding existing scale-200 PNGs back as source — none of those names match any MRT lookup pattern), plus several 0-byte placeholder files. Cleaned them out and stripped the matching entries from `ShaderLab.vcxproj` / `.filters`. The remaining originals will resolve through MRT correctly; user-supplied bear artwork still needs to be dropped over the placeholder PNGs to actually appear.
29+
630
## [1.2.7] - 2026-05-04
731

832
### Added

MainWindow.xaml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -293,15 +293,12 @@
293293
Style="{StaticResource CaptionTextBlockStyle}"
294294
FontFamily="Cascadia Mono, Consolas, Courier New" />
295295

296-
<TextBlock x:Name="AppVersionText" Grid.Column="6"
297-
Text="v1.1.0"
298-
Margin="0,0,16,0"
299-
Foreground="{ThemeResource TextFillColorTertiaryBrush}"
300-
Style="{StaticResource CaptionTextBlockStyle}" />
301-
<TextBlock x:Name="FpsText" Grid.Column="7"
296+
<TextBlock x:Name="FpsText" Grid.Column="6"
302297
Text="FPS: --"
303298
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
304299
Style="{StaticResource CaptionTextBlockStyle}" />
300+
<TextBlock x:Name="AppVersionText" Grid.Column="7"
301+
Visibility="Collapsed" />
305302
</Grid>
306303
</Grid>
307304
</Window>

MainWindow.xaml.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ namespace winrt::ShaderLab::implementation
2424
Title(std::wstring(L"ShaderLab v") + ::ShaderLab::VersionString + L" \u2014 HDR Shader Effect Development");
2525
// After Title() we'll refresh from RefreshTitleBar() once a graph
2626
// is loaded; the initial state is "Untitled".
27-
AppVersionText().Text(std::wstring(L"v") + ::ShaderLab::VersionString);
2827

2928
m_hwnd = GetWindowHandle();
3029

@@ -465,12 +464,9 @@ namespace winrt::ShaderLab::implementation
465464

466465
UpdateStatusBar();
467466

468-
// Set version text: app version + effect library version.
469-
{
470-
auto& lib = ::ShaderLab::Effects::ShaderLabEffects::Instance();
471-
AppVersionText().Text(std::wstring(L"v") + ::ShaderLab::VersionString
472-
+ L" (effects lib v" + std::to_wstring(lib.LibraryVersion()) + L")");
473-
}
467+
// Refresh title bar now that the effect library is loaded so the
468+
// title shows both the app and effect-library version.
469+
RefreshTitleBar();
474470

475471
m_nodeGraphController.SetGraph(&m_graph);
476472
m_nodeGraphController.SetConnectionCallback(
@@ -1182,14 +1178,17 @@ namespace winrt::ShaderLab::implementation
11821178

11831179
void MainWindow::RefreshTitleBar()
11841180
{
1185-
// Title format: "<filename>[*] - ShaderLab <version>". The
1186-
// unsaved star is the standard editor convention; the
1187-
// filename is derived from m_currentFilePath if known, else
1188-
// "Untitled".
1181+
// Title format: "<filename>[*] - ShaderLab <version> (effects lib vN)".
1182+
// The unsaved star is the standard editor convention; the filename
1183+
// is derived from m_currentFilePath if known, else "Untitled". The
1184+
// effect-library version moved here from the status bar to free up
1185+
// room for the FPS readout on the right.
11891186
std::wstring base = m_currentFilePath.empty() ? std::wstring(L"Untitled") :
11901187
std::filesystem::path(m_currentFilePath).filename().wstring();
1188+
auto& lib = ::ShaderLab::Effects::ShaderLabEffects::Instance();
11911189
std::wstring title = base + (m_unsavedChanges ? L"*" : L"")
1192-
+ L" - ShaderLab " + ::ShaderLab::VersionString;
1190+
+ L" - ShaderLab " + ::ShaderLab::VersionString
1191+
+ L" (effects lib v" + std::to_wstring(lib.LibraryVersion()) + L")";
11931192
try { Title(winrt::hstring(title)); } catch (...) {}
11941193
}
11951194

@@ -2010,6 +2009,12 @@ namespace winrt::ShaderLab::implementation
20102009
m_graph.MarkAllDirty();
20112010
m_nodeGraphController.RebuildLayout();
20122011
PopulatePreviewNodeSelector();
2012+
// Force a render tick that triggers the post-eval
2013+
// RebuildLayout, which is what reveals on-node UI
2014+
// (Clock play/pause + slider) for newly-added
2015+
// parameter nodes. Without this the user has to
2016+
// click the node before the controls appear.
2017+
m_forceRender = true;
20132018
});
20142019

20152020
subItem.Items().Append(menuItem);
@@ -3150,7 +3155,12 @@ namespace winrt::ShaderLab::implementation
31503155
m_previewNodeId = hitNodeId;
31513156

31523157
m_forceRender = true;
3153-
FitPreviewToView();
3158+
// Defer the fit until the next eval populates cachedOutput. On
3159+
// the very first selection of a node (before its first eval),
3160+
// GetPreviewImageBounds() returns an empty rect, so an immediate
3161+
// FitPreviewToView() lands on the wrong zoom. The deferred path
3162+
// in OnRenderTick re-fits once bounds are available.
3163+
m_needsFitPreview = true;
31543164
UpdatePreviewOverlay();
31553165
}
31563166
else

Package.appxmanifest

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<Identity
1010
Name="ShaderLab"
1111
Publisher="CN=ShaderLab"
12-
Version="1.3.6.0" />
12+
Version="1.3.7.0" />
1313

1414
<mp:PhoneIdentity PhoneProductId="a1b2c3d4-e5f6-7890-abcd-ef1234567890" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
1515

Version.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ namespace ShaderLab
1414
{
1515
constexpr uint32_t VersionMajor = 1;
1616
constexpr uint32_t VersionMinor = 3;
17-
constexpr uint32_t VersionPatch = 6;
17+
constexpr uint32_t VersionPatch = 7;
1818

1919
// Human-readable version string.
20-
constexpr const wchar_t* VersionString = L"1.3.6";
20+
constexpr const wchar_t* VersionString = L"1.3.7";
2121

2222
// Graph format version. Increment when serialization format changes.
2323
// Graphs saved with a higher format version cannot be loaded by older apps.

0 commit comments

Comments
 (0)