Skip to content

Commit d38ec79

Browse files
committed
Release v1.2.3: .effectgraph zip format, FTA, Ctrl+S accelerators, unsaved-changes guard
1 parent 3f74654 commit d38ec79

12 files changed

Lines changed: 677 additions & 28 deletions

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ The tone mapping system (`Rendering/ToneMapper.h/.cpp`) and color correction are
110110
- **Effect registry**: Singleton with 40+ built-in D2D effects across 9 categories. Case-insensitive name lookup.
111111
- **ShaderLab effects library**: 20+ built-in effects in `Effects/ShaderLabEffects.h/.cpp` (Analysis + Color Processing + Source/Generator + Parameter / Clock / Numeric Expression). Embedded HLSL with shared color math. Auto-compiled at first use.
112112
- **MCP server**: 23-tool JSON-RPC 2.0 server on port 47808 for AI agent integration. Routes in `MainWindow.McpRoutes.cpp`.
113-
- **Versioning**: `Version.h` defines app version (1.2.2) and graph format version (2). Both stored in saved graphs. Forward compatibility check on load.
113+
- **Versioning**: `Version.h` defines app version (1.2.3) and graph format version (2). Both stored in saved graphs. Forward compatibility check on load.
114114
- **Dirty-gated render loop**: `DispatcherQueueTimer` at 16ms (~60 FPS). Skips evaluate when no nodes changed. Analysis readback only on dirty frames.
115115
- **Ctrl+Enter** compiles shader from the editor TextBox.
116116

App.xaml.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,33 @@ namespace winrt::ShaderLab::implementation
128128
impl->SetAutoStartMcp(true);
129129
impl->SetDevicePreference(devicePref);
130130

131+
// File activation: when the user double-clicks a .effectgraph
132+
// file in Explorer, the OS launches us with the file path on
133+
// the command line. We just scan for it here -- proper
134+
// Microsoft.Windows.AppLifecycle activation routing isn't
135+
// worth the WinAppSDK reunion glue for a single argument.
136+
{
137+
int argc = 0;
138+
wchar_t** argv = ::CommandLineToArgvW(GetCommandLineW(), &argc);
139+
if (argv)
140+
{
141+
for (int i = 1; i < argc; ++i)
142+
{
143+
std::wstring a = argv[i];
144+
// Skip our own flags.
145+
if (a.starts_with(L"--")) continue;
146+
auto lower = a;
147+
std::transform(lower.begin(), lower.end(), lower.begin(), ::towlower);
148+
if (lower.ends_with(L".effectgraph"))
149+
{
150+
impl->SetPendingOpenPath(a);
151+
break;
152+
}
153+
}
154+
::LocalFree(argv);
155+
}
156+
}
157+
131158
window = mw;
132159
window.Activate();
133160
}

CHANGELOG.md

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

6+
## [1.2.3] - 2026-05-03
7+
8+
### Added
9+
- **`.effectgraph` file format**: native graph container. Standard ZIP archive (no compression, no third-party libraries — Win32 `CreateFile` + a small in-house store-only writer in `Rendering/EffectGraphFile.cpp`) holding `graph.json` plus a reserved empty `media/` folder for future media embedding (so a shared graph will eventually open with no broken file paths).
10+
- **File type association**: `.effectgraph` is registered in `Package.appxmanifest`. Double-clicking a file in Explorer launches ShaderLab with the graph already loaded. `App::OnLaunched` parses the command line for the file path and hands it to `MainWindow::SetPendingOpenPath` to load after rendering is initialized.
11+
- **Save / Save As keyboard accelerators**: `Ctrl+S` saves over the last picked path (or prompts on first save). `Ctrl+Shift+S` always shows the picker. `Ctrl+O` opens. The Save Graph button advertises both shortcuts in its tooltip.
12+
- **Unsaved-changes guard**: `MainWindow` tracks `m_unsavedChanges` and shows a `Save / Discard / Cancel` `ContentDialog` when the window is closed via `AppWindow.Closing`. Title bar shows the file name with a `*` suffix while edits are unsaved.
13+
14+
### Changed
15+
- `MainWindow::SaveGraphAsync` now overwrites the previously-picked path silently; previously every save reopened the picker.
16+
- App version string in the toolbar now derives from `Version.h` instead of a hard-coded `v1.1.0`.
17+
18+
### Removed
19+
- Legacy `.json` graph save / load support. `.effectgraph` is the only graph container; existing `.json` files from pre-1.2.3 builds will no longer open. There were no released users at the time of the cutover.
20+
21+
### Fixed
22+
- Toolbar version text was stuck on `v1.1.0` regardless of the actual app version.
23+
624
## [1.2.2] - 2026-05-02
725

826
### Added

MainWindow.xaml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,20 @@
2929
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
3030
BorderThickness="0,0,0,1">
3131
<StackPanel Orientation="Horizontal" Spacing="4">
32-
<Button x:Name="SaveGraphButton" ToolTipService.ToolTip="Save Graph">
32+
<Button x:Name="SaveGraphButton" ToolTipService.ToolTip="Save Graph (Ctrl+S, Ctrl+Shift+S = Save As)">
33+
<Button.KeyboardAccelerators>
34+
<KeyboardAccelerator Modifiers="Control" Key="S" Invoked="OnSaveAccelerator" />
35+
<KeyboardAccelerator Modifiers="Control,Shift" Key="S" Invoked="OnSaveAsAccelerator" />
36+
</Button.KeyboardAccelerators>
3337
<StackPanel Orientation="Horizontal" Spacing="6">
3438
<FontIcon Glyph="&#xE74E;" FontSize="14" />
3539
<TextBlock Text="Save Graph" />
3640
</StackPanel>
3741
</Button>
38-
<Button x:Name="LoadGraphButton" ToolTipService.ToolTip="Load Graph">
42+
<Button x:Name="LoadGraphButton" ToolTipService.ToolTip="Load Graph (Ctrl+O)">
43+
<Button.KeyboardAccelerators>
44+
<KeyboardAccelerator Modifiers="Control" Key="O" />
45+
</Button.KeyboardAccelerators>
3946
<StackPanel Orientation="Horizontal" Spacing="6">
4047
<FontIcon Glyph="&#xE8E5;" FontSize="14" />
4148
<TextBlock Text="Load Graph" />

0 commit comments

Comments
 (0)