Remove legacy WPF app, flatten WinUI project to repo root, rename namespace
The repo carried two parallel UIs (WPF + WinUI) sharing Models/Services via
cross-directory Link includes. Now that WinUI is the only frontend, collapse
the structure so the WinUI project IS the repo root instead of a nested
sibling folder:
- Delete the WPF project entirely (App.xaml, MainWindow.xaml, csproj) and its
bin/obj output
- Move AmiReel.WinUI/* up to the repo root (App, MainWindow, MainPage,
DialogHelper, Assets, Package.appxmanifest, app.manifest, Properties,
.github/instructions, AGENTS.md) via git mv, preserving history
- Rename AmiReel.WinUI.csproj -> AmiReel.csproj; regenerate the solution as
AmiReel.slnx (the newer XML solution format) with a single project
- Rename namespace AmigaDB.VideoRenderer.{Models,Services} -> AmiReel.{...}
and AmiReel_WinUI -> AmiReel across all files, including the embedded
ffmpeg/ffprobe resource logical names in the csproj and ToolExtractor
- Models/ and Services/ no longer need the Link-based cross-directory
<Compile Include>; they're picked up by the SDK's default globbing now
that they live under the project directory
- Rename assets/ -> branding/ (source icon art) to avoid a case-insensitive
collision with Assets/ (packaged tile art) once both sit at repo root
- Merge the two .gitignore files into one; track the PublishProfiles pubxml
files instead of ignoring them (no secrets, and they keep publish
reproducible across machines) as branding, gitignore, etc.
- Simplify publish-win-x64.ps1 (drop the -Target Wpf/WinUI switch, there's
only one target now) and rewrite README.md to describe the single-project
layout, build/run/publish commands, and file structure
Verified: dotnet build succeeds for both AmiReel.csproj and AmiReel.slnx, and
the built exe launches and renders identically to before the move.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@@ -1,14 +1,55 @@
|
|||||||
bin/
|
# Build output
|
||||||
obj/
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Dd]ebug/
|
||||||
|
[Rr]elease/
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# IDE / tooling
|
||||||
.vs/
|
.vs/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
_ReSharper*/
|
||||||
|
*.DotSettings.user
|
||||||
|
*.dotCover
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# MSBuild / user files
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
*.pdb
|
*.pdb
|
||||||
*.cache
|
*.cache
|
||||||
*.tmp
|
*.tmp
|
||||||
*.log
|
*.log
|
||||||
*.userosscache
|
*.binlog
|
||||||
|
|
||||||
|
# Test results
|
||||||
TestResults/
|
TestResults/
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
*.trx
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NuGet
|
||||||
|
*.nupkg
|
||||||
|
*.snupkg
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
project.lock.json
|
||||||
|
|
||||||
|
# MSIX packaging output
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
*.msix
|
||||||
|
*.msixupload
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Local dev signing certificate
|
||||||
|
devcert.pfx
|
||||||
|
|
||||||
|
# Embedded third-party binaries (fetched separately, see ThirdParty/README.md)
|
||||||
ThirdParty/ffmpeg.exe
|
ThirdParty/ffmpeg.exe
|
||||||
ThirdParty/ffprobe.exe
|
ThirdParty/ffprobe.exe
|
||||||
*.user
|
|
||||||
*.suo
|
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
## .NET / Visual Studio
|
|
||||||
[Bb]in/
|
|
||||||
[Oo]bj/
|
|
||||||
[Dd]ebug/
|
|
||||||
[Rr]elease/
|
|
||||||
.vs/
|
|
||||||
*.user
|
|
||||||
*.suo
|
|
||||||
*.userosscache
|
|
||||||
*.sln.docstates
|
|
||||||
artifacts/
|
|
||||||
|
|
||||||
# Build logs
|
|
||||||
[Ll]og/
|
|
||||||
[Ll]ogs/
|
|
||||||
*.log
|
|
||||||
*.binlog
|
|
||||||
|
|
||||||
# Test results
|
|
||||||
[Tt]est[Rr]esult*/
|
|
||||||
*.trx
|
|
||||||
*.coverage
|
|
||||||
*.coveragexml
|
|
||||||
|
|
||||||
# NuGet
|
|
||||||
*.nupkg
|
|
||||||
*.snupkg
|
|
||||||
*.nuget.props
|
|
||||||
*.nuget.targets
|
|
||||||
project.lock.json
|
|
||||||
|
|
||||||
# MSIX packaging output
|
|
||||||
AppPackages/
|
|
||||||
BundleArtifacts/
|
|
||||||
*.msix
|
|
||||||
*.msixupload
|
|
||||||
*.appx
|
|
||||||
*.appxbundle
|
|
||||||
*.appxupload
|
|
||||||
|
|
||||||
# Publish output
|
|
||||||
publish/
|
|
||||||
*.pubxml
|
|
||||||
PublishScripts/
|
|
||||||
|
|
||||||
# Code analysis and tooling
|
|
||||||
_ReSharper*/
|
|
||||||
*.DotSettings.user
|
|
||||||
*.dotCover
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
# Generated files
|
|
||||||
Generated\ Files/
|
|
||||||
*_wpftmp.csproj
|
|
||||||
@@ -1,269 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Application
|
|
||||||
x:Class="AmiReel_WinUI.App"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:local="using:AmiReel_WinUI">
|
|
||||||
<Application.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary.ThemeDictionaries>
|
|
||||||
<ResourceDictionary x:Key="Dark">
|
|
||||||
<SolidColorBrush x:Key="PageBrush" Color="#0E1525"/>
|
|
||||||
<SolidColorBrush x:Key="PanelBrush" Color="#162033"/>
|
|
||||||
<SolidColorBrush x:Key="PanelAltBrush" Color="#1A2740"/>
|
|
||||||
<SolidColorBrush x:Key="FieldBrush" Color="#1D2940"/>
|
|
||||||
<SolidColorBrush x:Key="BorderBrush" Color="#2B3A58"/>
|
|
||||||
<SolidColorBrush x:Key="AccentBrush" Color="#4AB8FF"/>
|
|
||||||
<SolidColorBrush x:Key="AccentSoftBrush" Color="#13324F"/>
|
|
||||||
<SolidColorBrush x:Key="TextBrush" Color="#F5F7FB"/>
|
|
||||||
<SolidColorBrush x:Key="MutedBrush" Color="#9FB1CC"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonBrush" Color="#243554"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonHoverBrush" Color="#2E446C"/>
|
|
||||||
<SolidColorBrush x:Key="PrimaryTextBrush" Color="#07111D"/>
|
|
||||||
|
|
||||||
<!-- Fluent control theme-brush overrides so built-in controls match the palette -->
|
|
||||||
<SolidColorBrush x:Key="TextControlBackground" Color="#1D2940"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlBackgroundPointerOver" Color="#233252"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlBackgroundFocused" Color="#1D2940"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlBorderBrush" Color="#2B3A58"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver" Color="#4AB8FF"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlBorderBrushFocused" Color="#4AB8FF"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlForeground" Color="#F5F7FB"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlForegroundFocused" Color="#F5F7FB"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlHeaderForeground" Color="#9FB1CC"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlPlaceholderForeground" Color="#7488A6"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="ComboBoxBackground" Color="#1D2940"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxBackgroundPointerOver" Color="#233252"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxBorderBrush" Color="#2B3A58"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxForeground" Color="#F5F7FB"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxHeaderForeground" Color="#9FB1CC"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxItemBackgroundSelected" Color="#13324F"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxDropDownBackground" Color="#10192B"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="ButtonBackground" Color="#243554"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="#2E446C"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="#1B2A44"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonForeground" Color="#F5F7FB"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="#F5F7FB"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonBorderBrush" Color="#2B3A58"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="ContentDialogBackground" Color="#162033"/>
|
|
||||||
<SolidColorBrush x:Key="ContentDialogForeground" Color="#F5F7FB"/>
|
|
||||||
<SolidColorBrush x:Key="ContentDialogBorderBrush" Color="#35507D"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="ListViewItemBackgroundSelected" Color="#13324F"/>
|
|
||||||
<SolidColorBrush x:Key="ListViewItemBackgroundPointerOver" Color="#1A2740"/>
|
|
||||||
<SolidColorBrush x:Key="ListViewItemForeground" Color="#F5F7FB"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="CheckBoxCheckBackgroundFillUnchecked" Color="#1D2940"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeUnchecked" Color="#2B3A58"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked" Color="#4AB8FF"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked" Color="#4AB8FF"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked" Color="#07111D"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxForegroundUnchecked" Color="#F5F7FB"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxForegroundChecked" Color="#F5F7FB"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="ProgressBarForeground" Color="#4AB8FF"/>
|
|
||||||
<SolidColorBrush x:Key="ProgressBarBackground" Color="#1D2940"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="HeroBorderBrush" Color="#35507D"/>
|
|
||||||
</ResourceDictionary>
|
|
||||||
<ResourceDictionary x:Key="Light">
|
|
||||||
<SolidColorBrush x:Key="PageBrush" Color="#F4F7FB"/>
|
|
||||||
<SolidColorBrush x:Key="PanelBrush" Color="#FFFFFF"/>
|
|
||||||
<SolidColorBrush x:Key="PanelAltBrush" Color="#EEF4FB"/>
|
|
||||||
<SolidColorBrush x:Key="FieldBrush" Color="#F7FAFD"/>
|
|
||||||
<SolidColorBrush x:Key="BorderBrush" Color="#C7D3E3"/>
|
|
||||||
<SolidColorBrush x:Key="AccentBrush" Color="#0E9AEF"/>
|
|
||||||
<SolidColorBrush x:Key="AccentSoftBrush" Color="#D6EEFF"/>
|
|
||||||
<SolidColorBrush x:Key="TextBrush" Color="#122033"/>
|
|
||||||
<SolidColorBrush x:Key="MutedBrush" Color="#5F7390"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonBrush" Color="#E5EDF7"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonHoverBrush" Color="#D7E4F4"/>
|
|
||||||
<SolidColorBrush x:Key="PrimaryTextBrush" Color="#FFFFFF"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="TextControlBackground" Color="#F7FAFD"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlBackgroundPointerOver" Color="#EEF4FB"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlBackgroundFocused" Color="#FFFFFF"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlBorderBrush" Color="#C7D3E3"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver" Color="#0E9AEF"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlBorderBrushFocused" Color="#0E9AEF"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlForeground" Color="#122033"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlForegroundFocused" Color="#122033"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlHeaderForeground" Color="#5F7390"/>
|
|
||||||
<SolidColorBrush x:Key="TextControlPlaceholderForeground" Color="#8194AC"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="ComboBoxBackground" Color="#F7FAFD"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxBackgroundPointerOver" Color="#EEF4FB"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxBorderBrush" Color="#C7D3E3"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxForeground" Color="#122033"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxHeaderForeground" Color="#5F7390"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxItemBackgroundSelected" Color="#D6EEFF"/>
|
|
||||||
<SolidColorBrush x:Key="ComboBoxDropDownBackground" Color="#FFFFFF"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="ButtonBackground" Color="#E5EDF7"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="#D7E4F4"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="#C7D9EE"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonForeground" Color="#122033"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="#122033"/>
|
|
||||||
<SolidColorBrush x:Key="ButtonBorderBrush" Color="#C7D3E3"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="ContentDialogBackground" Color="#FFFFFF"/>
|
|
||||||
<SolidColorBrush x:Key="ContentDialogForeground" Color="#122033"/>
|
|
||||||
<SolidColorBrush x:Key="ContentDialogBorderBrush" Color="#C7D3E3"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="ListViewItemBackgroundSelected" Color="#D6EEFF"/>
|
|
||||||
<SolidColorBrush x:Key="ListViewItemBackgroundPointerOver" Color="#EEF4FB"/>
|
|
||||||
<SolidColorBrush x:Key="ListViewItemForeground" Color="#122033"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="CheckBoxCheckBackgroundFillUnchecked" Color="#F7FAFD"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeUnchecked" Color="#C7D3E3"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked" Color="#0E9AEF"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked" Color="#0E9AEF"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked" Color="#FFFFFF"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxForegroundUnchecked" Color="#122033"/>
|
|
||||||
<SolidColorBrush x:Key="CheckBoxForegroundChecked" Color="#122033"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="ProgressBarForeground" Color="#0E9AEF"/>
|
|
||||||
<SolidColorBrush x:Key="ProgressBarBackground" Color="#F7FAFD"/>
|
|
||||||
|
|
||||||
<SolidColorBrush x:Key="HeroBorderBrush" Color="#A9C4E4"/>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
|
||||||
|
|
||||||
<!-- Global corner rounding so built-in Fluent controls match the WPF app's rounded look -->
|
|
||||||
<CornerRadius x:Key="ControlCornerRadius">10</CornerRadius>
|
|
||||||
<CornerRadius x:Key="OverlayCornerRadius">18</CornerRadius>
|
|
||||||
|
|
||||||
<x:Double x:Key="ContentDialogMaxWidth">460</x:Double>
|
|
||||||
|
|
||||||
<Style TargetType="Page">
|
|
||||||
<Setter Property="Background" Value="{ThemeResource PageBrush}" />
|
|
||||||
<Setter Property="FontFamily" Value="Bahnschrift" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style x:Key="CardBorderStyle" TargetType="Border">
|
|
||||||
<Setter Property="Background" Value="{ThemeResource PanelBrush}" />
|
|
||||||
<Setter Property="BorderBrush" Value="{ThemeResource BorderBrush}" />
|
|
||||||
<Setter Property="BorderThickness" Value="1" />
|
|
||||||
<Setter Property="CornerRadius" Value="16" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style x:Key="SectionTitleStyle" TargetType="TextBlock">
|
|
||||||
<Setter Property="Foreground" Value="{ThemeResource TextBrush}" />
|
|
||||||
<Setter Property="FontSize" Value="15" />
|
|
||||||
<Setter Property="FontWeight" Value="SemiBold" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style x:Key="MutedTextStyle" TargetType="TextBlock">
|
|
||||||
<Setter Property="Foreground" Value="{ThemeResource MutedBrush}" />
|
|
||||||
<Setter Property="FontSize" Value="13" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style x:Key="FieldLabelStyle" TargetType="TextBlock">
|
|
||||||
<Setter Property="Foreground" Value="{ThemeResource MutedBrush}" />
|
|
||||||
<Setter Property="FontSize" Value="12" />
|
|
||||||
<Setter Property="Margin" Value="0,0,0,4" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style TargetType="TextBlock">
|
|
||||||
<Setter Property="Foreground" Value="{ThemeResource TextBrush}" />
|
|
||||||
<Setter Property="FontSize" Value="13" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style TargetType="Button">
|
|
||||||
<Setter Property="Padding" Value="16,9" />
|
|
||||||
<Setter Property="FontSize" Value="13" />
|
|
||||||
<Setter Property="CornerRadius" Value="10" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style x:Key="PrimaryButtonStyle" TargetType="Button">
|
|
||||||
<Setter Property="Background" Value="{ThemeResource AccentBrush}" />
|
|
||||||
<Setter Property="Foreground" Value="{ThemeResource PrimaryTextBrush}" />
|
|
||||||
<Setter Property="BorderBrush" Value="{ThemeResource AccentBrush}" />
|
|
||||||
<Setter Property="FontWeight" Value="SemiBold" />
|
|
||||||
<Setter Property="Padding" Value="22,10" />
|
|
||||||
<Setter Property="CornerRadius" Value="10" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style x:Key="IconButtonStyle" TargetType="Button">
|
|
||||||
<Setter Property="Width" Value="40" />
|
|
||||||
<Setter Property="Height" Value="40" />
|
|
||||||
<Setter Property="Padding" Value="0" />
|
|
||||||
<Setter Property="FontSize" Value="16" />
|
|
||||||
<Setter Property="CornerRadius" Value="10" />
|
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
|
||||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<!-- Explicit styles bound to ContentDialog.PrimaryButtonStyle / CloseButtonStyle so its
|
|
||||||
built-in buttons match the app's own Button look instead of the default Fluent
|
|
||||||
accent-pill / plain styles. -->
|
|
||||||
<Style x:Key="DialogPrimaryButtonStyle" TargetType="Button">
|
|
||||||
<Setter Property="Background" Value="{ThemeResource AccentBrush}" />
|
|
||||||
<Setter Property="Foreground" Value="{ThemeResource PrimaryTextBrush}" />
|
|
||||||
<Setter Property="BorderBrush" Value="{ThemeResource AccentBrush}" />
|
|
||||||
<Setter Property="BorderThickness" Value="1" />
|
|
||||||
<Setter Property="FontWeight" Value="SemiBold" />
|
|
||||||
<Setter Property="FontSize" Value="13" />
|
|
||||||
<Setter Property="Padding" Value="22,10" />
|
|
||||||
<Setter Property="CornerRadius" Value="10" />
|
|
||||||
<Setter Property="MinHeight" Value="40" />
|
|
||||||
<Setter Property="MinWidth" Value="110" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style x:Key="DialogCloseButtonStyle" TargetType="Button">
|
|
||||||
<Setter Property="Background" Value="{ThemeResource ButtonBrush}" />
|
|
||||||
<Setter Property="Foreground" Value="{ThemeResource TextBrush}" />
|
|
||||||
<Setter Property="BorderBrush" Value="{ThemeResource BorderBrush}" />
|
|
||||||
<Setter Property="BorderThickness" Value="1" />
|
|
||||||
<Setter Property="FontSize" Value="13" />
|
|
||||||
<Setter Property="Padding" Value="16,9" />
|
|
||||||
<Setter Property="CornerRadius" Value="10" />
|
|
||||||
<Setter Property="MinHeight" Value="40" />
|
|
||||||
<Setter Property="MinWidth" Value="110" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style TargetType="TextBox">
|
|
||||||
<Setter Property="FontSize" Value="13" />
|
|
||||||
<Setter Property="MinHeight" Value="38" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style TargetType="ComboBox">
|
|
||||||
<Setter Property="FontSize" Value="13" />
|
|
||||||
<Setter Property="MinHeight" Value="38" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style TargetType="CheckBox">
|
|
||||||
<Setter Property="FontSize" Value="13" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style TargetType="ProgressBar">
|
|
||||||
<Setter Property="MinHeight" Value="8" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style TargetType="ListView">
|
|
||||||
<Setter Property="Background" Value="{ThemeResource FieldBrush}" />
|
|
||||||
<Setter Property="BorderBrush" Value="{ThemeResource BorderBrush}" />
|
|
||||||
<Setter Property="BorderThickness" Value="1" />
|
|
||||||
<Setter Property="CornerRadius" Value="10" />
|
|
||||||
<Setter Property="FontSize" Value="13" />
|
|
||||||
<Setter Property="Padding" Value="4" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style TargetType="ListViewItem">
|
|
||||||
<Setter Property="MinHeight" Value="32" />
|
|
||||||
<Setter Property="Padding" Value="8,6" />
|
|
||||||
<Setter Property="CornerRadius" Value="6" />
|
|
||||||
</Style>
|
|
||||||
|
|
||||||
<Style TargetType="ContentDialog">
|
|
||||||
<Setter Property="CornerRadius" Value="18" />
|
|
||||||
</Style>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</Application.Resources>
|
|
||||||
</Application>
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
using Windows.ApplicationModel;
|
|
||||||
using Windows.ApplicationModel.Activation;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Microsoft.UI.Xaml;
|
|
||||||
using Microsoft.UI.Xaml.Controls;
|
|
||||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
|
||||||
using Microsoft.UI.Xaml.Data;
|
|
||||||
using Microsoft.UI.Xaml.Input;
|
|
||||||
using Microsoft.UI.Xaml.Media;
|
|
||||||
using Microsoft.UI.Xaml.Navigation;
|
|
||||||
using Microsoft.UI.Xaml.Shapes;
|
|
||||||
using WinRT.Interop;
|
|
||||||
|
|
||||||
// To learn more about WinUI, the WinUI project structure,
|
|
||||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
|
||||||
|
|
||||||
namespace AmiReel_WinUI;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides application-specific behavior to supplement the default Application class.
|
|
||||||
/// </summary>
|
|
||||||
public partial class App : Application
|
|
||||||
{
|
|
||||||
private Window? _window;
|
|
||||||
public static IntPtr MainWindowHandle { get; private set; }
|
|
||||||
public static MainWindow? MainWindowInstance { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes the singleton application object. This is the first line of authored code
|
|
||||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
|
||||||
/// </summary>
|
|
||||||
public App()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invoked when the application is launched.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="args">Details about the launch request and process.</param>
|
|
||||||
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
|
|
||||||
{
|
|
||||||
_window = new MainWindow();
|
|
||||||
MainWindowHandle = WindowNative.GetWindowHandle(_window);
|
|
||||||
_window.Activate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<Window
|
|
||||||
x:Class="AmiReel_WinUI.MainWindow"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:local="using:AmiReel_WinUI"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
Title="AmiReel"
|
|
||||||
mc:Ignorable="d">
|
|
||||||
<Grid Background="{ThemeResource PageBrush}">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Grid x:Name="AppTitleBar" Grid.Row="0" Height="44" Background="{ThemeResource PanelBrush}">
|
|
||||||
<StackPanel Orientation="Horizontal" Spacing="10" VerticalAlignment="Center" Margin="14,0,0,0">
|
|
||||||
<Image Source="ms-appx:///Assets/Square44x44Logo.scale-200.png"
|
|
||||||
Width="20"
|
|
||||||
Height="20"
|
|
||||||
Stretch="Uniform" />
|
|
||||||
<TextBlock Text="AmiReel"
|
|
||||||
FontFamily="Bahnschrift"
|
|
||||||
FontSize="14"
|
|
||||||
FontWeight="SemiBold"
|
|
||||||
VerticalAlignment="Center" />
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
The Frame hosts pages for your application content. Add your UI to
|
|
||||||
MainPage.xaml rather than here so you can use Page features such as
|
|
||||||
navigation events and the Loaded lifecycle.
|
|
||||||
-->
|
|
||||||
<Frame x:Name="RootFrame" Grid.Row="1" />
|
|
||||||
</Grid>
|
|
||||||
</Window>
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
using Microsoft.UI;
|
|
||||||
using Microsoft.UI.Windowing;
|
|
||||||
using Microsoft.UI.Xaml;
|
|
||||||
using Microsoft.UI.Xaml.Controls;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Windows.Graphics;
|
|
||||||
using Windows.UI;
|
|
||||||
using WinRT.Interop;
|
|
||||||
|
|
||||||
// To learn more about WinUI, the WinUI project structure,
|
|
||||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
|
||||||
|
|
||||||
namespace AmiReel_WinUI;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The application window. This hosts a Frame that displays pages. Add your
|
|
||||||
/// UI and logic to MainPage.xaml / MainPage.xaml.cs instead of here so you
|
|
||||||
/// can use Page features such as navigation events and the Loaded lifecycle.
|
|
||||||
/// </summary>
|
|
||||||
public sealed partial class MainWindow : Window
|
|
||||||
{
|
|
||||||
private bool _exitConfirmed;
|
|
||||||
|
|
||||||
public MainWindow()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
App.MainWindowInstance = this;
|
|
||||||
|
|
||||||
ExtendsContentIntoTitleBar = true;
|
|
||||||
SetTitleBar(AppTitleBar);
|
|
||||||
|
|
||||||
string? executablePath = Environment.ProcessPath;
|
|
||||||
if (!string.IsNullOrWhiteSpace(executablePath) && File.Exists(executablePath))
|
|
||||||
AppWindow.SetIcon(executablePath);
|
|
||||||
|
|
||||||
SetDefaultSizeAndPosition();
|
|
||||||
|
|
||||||
// Navigate the root frame to the main page on startup.
|
|
||||||
RootFrame.Navigate(typeof(MainPage));
|
|
||||||
|
|
||||||
AppWindow.Closing += AppWindow_Closing;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetDefaultSizeAndPosition()
|
|
||||||
{
|
|
||||||
const int DefaultWidth = 1280;
|
|
||||||
const int DefaultHeight = 860;
|
|
||||||
const int MinWidth = 1100;
|
|
||||||
const int MinHeight = 780;
|
|
||||||
|
|
||||||
IntPtr hwnd = WindowNative.GetWindowHandle(this);
|
|
||||||
double scale = GetDpiForWindow(hwnd) / 96.0;
|
|
||||||
int width = (int)(DefaultWidth * scale);
|
|
||||||
int height = (int)(DefaultHeight * scale);
|
|
||||||
|
|
||||||
AppWindow.Resize(new SizeInt32(width, height));
|
|
||||||
|
|
||||||
if (AppWindow.Presenter is OverlappedPresenter presenter)
|
|
||||||
{
|
|
||||||
presenter.PreferredMinimumWidth = (int)(MinWidth * scale);
|
|
||||||
presenter.PreferredMinimumHeight = (int)(MinHeight * scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayArea? displayArea = DisplayArea.GetFromWindowId(Win32Interop.GetWindowIdFromWindow(hwnd), DisplayAreaFallback.Primary);
|
|
||||||
if (displayArea is not null)
|
|
||||||
{
|
|
||||||
int centerX = displayArea.WorkArea.X + (displayArea.WorkArea.Width - width) / 2;
|
|
||||||
int centerY = displayArea.WorkArea.Y + (displayArea.WorkArea.Height - height) / 2;
|
|
||||||
AppWindow.Move(new PointInt32(centerX, centerY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
private static extern int GetDpiForWindow(IntPtr hwnd);
|
|
||||||
|
|
||||||
public void ApplyTheme(bool isDark)
|
|
||||||
{
|
|
||||||
if (Content is FrameworkElement root)
|
|
||||||
root.RequestedTheme = isDark ? ElementTheme.Dark : ElementTheme.Light;
|
|
||||||
|
|
||||||
AppWindowTitleBar titleBar = AppWindow.TitleBar;
|
|
||||||
Color foreground = isDark ? Color.FromArgb(255, 0xF5, 0xF7, 0xFB) : Color.FromArgb(255, 0x12, 0x20, 0x33);
|
|
||||||
Color hoverBackground = isDark ? Color.FromArgb(255, 0x2E, 0x44, 0x6C) : Color.FromArgb(255, 0xD7, 0xE4, 0xF4);
|
|
||||||
|
|
||||||
titleBar.ButtonBackgroundColor = Colors.Transparent;
|
|
||||||
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
|
||||||
titleBar.ButtonForegroundColor = foreground;
|
|
||||||
titleBar.ButtonInactiveForegroundColor = foreground;
|
|
||||||
titleBar.ButtonHoverBackgroundColor = hoverBackground;
|
|
||||||
titleBar.ButtonHoverForegroundColor = foreground;
|
|
||||||
titleBar.ButtonPressedBackgroundColor = hoverBackground;
|
|
||||||
titleBar.ButtonPressedForegroundColor = foreground;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
|
||||||
{
|
|
||||||
if (_exitConfirmed) return;
|
|
||||||
args.Cancel = true;
|
|
||||||
|
|
||||||
FrameworkElement root = (FrameworkElement)Content;
|
|
||||||
ContentDialog dialog = DialogHelper.CreateStyled(RootFrame.XamlRoot, root.RequestedTheme);
|
|
||||||
dialog.Title = "Exit AmiReel?";
|
|
||||||
dialog.Content = "Are you sure you want to close the application?";
|
|
||||||
dialog.PrimaryButtonText = "Exit";
|
|
||||||
dialog.CloseButtonText = "Cancel";
|
|
||||||
dialog.DefaultButton = ContentDialogButton.Primary;
|
|
||||||
|
|
||||||
ContentDialogResult result = await dialog.ShowAsync();
|
|
||||||
if (result != ContentDialogResult.Primary) return;
|
|
||||||
|
|
||||||
_exitConfirmed = true;
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
|
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
|
||||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||||
<RootNamespace>AmiReel_WinUI</RootNamespace>
|
<RootNamespace>AmiReel</RootNamespace>
|
||||||
<AssemblyName>AmiReel</AssemblyName>
|
<AssemblyName>AmiReel</AssemblyName>
|
||||||
<ApplicationIcon>..\assets\AmiReel.ico</ApplicationIcon>
|
<ApplicationIcon>branding\AmiReel.ico</ApplicationIcon>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<Platforms>x86;x64;ARM64</Platforms>
|
<Platforms>x86;x64;ARM64</Platforms>
|
||||||
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == ''">win-$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant())</RuntimeIdentifier>
|
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == ''">win-$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant())</RuntimeIdentifier>
|
||||||
@@ -36,13 +36,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\Models\*.cs" Link="Shared\Models\%(Filename)%(Extension)" />
|
<EmbeddedResource Include="ThirdParty\ffmpeg.exe" Condition="Exists('ThirdParty\ffmpeg.exe')" LogicalName="AmiReel.Tools.ffmpeg.exe" />
|
||||||
<Compile Include="..\Services\*.cs" Link="Shared\Services\%(Filename)%(Extension)" />
|
<EmbeddedResource Include="ThirdParty\ffprobe.exe" Condition="Exists('ThirdParty\ffprobe.exe')" LogicalName="AmiReel.Tools.ffprobe.exe" />
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="..\ThirdParty\ffmpeg.exe" Condition="Exists('..\ThirdParty\ffmpeg.exe')" LogicalName="AmigaDB.VideoRenderer.Tools.ffmpeg.exe" />
|
|
||||||
<EmbeddedResource Include="..\ThirdParty\ffprobe.exe" Condition="Exists('..\ThirdParty\ffprobe.exe')" LogicalName="AmigaDB.VideoRenderer.Tools.ffprobe.exe" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<Solution>
|
||||||
|
<Project Path="AmiReel.csproj" />
|
||||||
|
</Solution>
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>WinExe</OutputType>
|
|
||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
|
||||||
<UseWPF>true</UseWPF>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<ApplicationIcon Condition="Exists('assets\\AmiReel.ico')">assets\AmiReel.ico</ApplicationIcon>
|
|
||||||
<AssemblyName>AmiReel</AssemblyName>
|
|
||||||
<RootNamespace>AmigaDB.VideoRenderer</RootNamespace>
|
|
||||||
<Product>AmiReel</Product>
|
|
||||||
<Title>AmiReel</Title>
|
|
||||||
<Version>0.1.0</Version>
|
|
||||||
<PublishSingleFile>true</PublishSingleFile>
|
|
||||||
<SelfContained>true</SelfContained>
|
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
|
||||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
|
||||||
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Remove="AmiReel.WinUI\**\*.cs" />
|
|
||||||
<EmbeddedResource Remove="AmiReel.WinUI\**\*" />
|
|
||||||
<None Remove="AmiReel.WinUI\**\*" />
|
|
||||||
<Page Remove="AmiReel.WinUI\**\*.xaml" />
|
|
||||||
<ApplicationDefinition Remove="AmiReel.WinUI\App.xaml" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="ThirdParty\ffmpeg.exe" Condition="Exists('ThirdParty\ffmpeg.exe')" LogicalName="AmigaDB.VideoRenderer.Tools.ffmpeg.exe" />
|
|
||||||
<EmbeddedResource Include="ThirdParty\ffprobe.exe" Condition="Exists('ThirdParty\ffprobe.exe')" LogicalName="AmigaDB.VideoRenderer.Tools.ffprobe.exe" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Resource Include="assets\AmiReel.ico" Condition="Exists('assets\AmiReel.ico')" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="RequireFfmpegForPublish" BeforeTargets="Publish">
|
|
||||||
<Error Condition="!Exists('ThirdParty\ffmpeg.exe')" Text="ThirdParty\ffmpeg.exe is required for a portable publish." />
|
|
||||||
<Error Condition="!Exists('ThirdParty\ffprobe.exe')" Text="ThirdParty\ffprobe.exe is required for a portable publish." />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 17
|
|
||||||
VisualStudioVersion = 17.0.31903.59
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmigaDB.VideoRenderer", "AmigaDB.VideoRenderer.csproj", "{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmiReel.WinUI", "AmiReel.WinUI\AmiReel.WinUI.csproj", "{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Debug|x64 = Debug|x64
|
|
||||||
Debug|x86 = Debug|x86
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
Release|x64 = Release|x64
|
|
||||||
Release|x86 = Release|x86
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{7DF2BA53-4031-45EA-B4EF-27B86111FBFA}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Debug|Any CPU.ActiveCfg = Debug|x86
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Debug|Any CPU.Build.0 = Debug|x86
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Release|Any CPU.ActiveCfg = Release|x86
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Release|Any CPU.Build.0 = Release|x86
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Release|x64.Build.0 = Release|x64
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{7F1B3264-98F5-4B31-812F-7A4FB2A447BB}.Release|x86.Build.0 = Release|x86
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,423 +1,269 @@
|
|||||||
<Application x:Class="AmigaDB.VideoRenderer.App"
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
<Application
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
x:Class="AmiReel.App"
|
||||||
StartupUri="MainWindow.xaml">
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:AmiReel">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<SolidColorBrush x:Key="PageBrush" Color="#0E1525"/>
|
<ResourceDictionary>
|
||||||
<SolidColorBrush x:Key="PanelBrush" Color="#162033"/>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
<SolidColorBrush x:Key="PanelAltBrush" Color="#1A2740"/>
|
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||||
<SolidColorBrush x:Key="FieldBrush" Color="#1D2940"/>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
<SolidColorBrush x:Key="BorderBrush" Color="#2B3A58"/>
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
<SolidColorBrush x:Key="AccentBrush" Color="#4AB8FF"/>
|
<ResourceDictionary x:Key="Dark">
|
||||||
<SolidColorBrush x:Key="AccentSoftBrush" Color="#13324F"/>
|
<SolidColorBrush x:Key="PageBrush" Color="#0E1525"/>
|
||||||
<SolidColorBrush x:Key="TextBrush" Color="#F5F7FB"/>
|
<SolidColorBrush x:Key="PanelBrush" Color="#162033"/>
|
||||||
<SolidColorBrush x:Key="MutedBrush" Color="#9FB1CC"/>
|
<SolidColorBrush x:Key="PanelAltBrush" Color="#1A2740"/>
|
||||||
<SolidColorBrush x:Key="ButtonBrush" Color="#243554"/>
|
<SolidColorBrush x:Key="FieldBrush" Color="#1D2940"/>
|
||||||
<SolidColorBrush x:Key="ButtonHoverBrush" Color="#2E446C"/>
|
<SolidColorBrush x:Key="BorderBrush" Color="#2B3A58"/>
|
||||||
<SolidColorBrush x:Key="ButtonDisabledBrush" Color="#2A3140"/>
|
<SolidColorBrush x:Key="AccentBrush" Color="#4AB8FF"/>
|
||||||
<SolidColorBrush x:Key="ButtonDisabledTextBrush" Color="#7E8BA1"/>
|
<SolidColorBrush x:Key="AccentSoftBrush" Color="#13324F"/>
|
||||||
<SolidColorBrush x:Key="PrimaryTextBrush" Color="#07111D"/>
|
<SolidColorBrush x:Key="TextBrush" Color="#F5F7FB"/>
|
||||||
<SolidColorBrush x:Key="SelectionBrush" Color="#295C87"/>
|
<SolidColorBrush x:Key="MutedBrush" Color="#9FB1CC"/>
|
||||||
<SolidColorBrush x:Key="SelectionTextBrush" Color="#FFFFFF"/>
|
<SolidColorBrush x:Key="ButtonBrush" Color="#243554"/>
|
||||||
<SolidColorBrush x:Key="ScrollTrackBrush" Color="#11192B"/>
|
<SolidColorBrush x:Key="ButtonHoverBrush" Color="#2E446C"/>
|
||||||
<SolidColorBrush x:Key="ScrollThumbBrush" Color="#31476D"/>
|
<SolidColorBrush x:Key="PrimaryTextBrush" Color="#07111D"/>
|
||||||
<SolidColorBrush x:Key="ScrollThumbHoverBrush" Color="#42608F"/>
|
|
||||||
<SolidColorBrush x:Key="PopupBrush" Color="#10192B"/>
|
|
||||||
<SolidColorBrush x:Key="HeroBorderBrush" Color="#35507D"/>
|
|
||||||
<LinearGradientBrush x:Key="HeroBrush" StartPoint="0,0" EndPoint="1,1">
|
|
||||||
<GradientStop Offset="0" Color="#122441"/>
|
|
||||||
<GradientStop Offset="0.55" Color="#0F1830"/>
|
|
||||||
<GradientStop Offset="1" Color="#1A2D4D"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
<LinearGradientBrush x:Key="PageOverlayBrush" StartPoint="0,0" EndPoint="1,1">
|
|
||||||
<GradientStop Offset="0" Color="#12000000"/>
|
|
||||||
<GradientStop Offset="1" Color="#00000000"/>
|
|
||||||
</LinearGradientBrush>
|
|
||||||
|
|
||||||
<Style TargetType="Window">
|
<!-- Fluent control theme-brush overrides so built-in controls match the palette -->
|
||||||
<Setter Property="Background" Value="{DynamicResource PageBrush}"/>
|
<SolidColorBrush x:Key="TextControlBackground" Color="#1D2940"/>
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
<SolidColorBrush x:Key="TextControlBackgroundPointerOver" Color="#233252"/>
|
||||||
<Setter Property="FontFamily" Value="Bahnschrift"/>
|
<SolidColorBrush x:Key="TextControlBackgroundFocused" Color="#1D2940"/>
|
||||||
</Style>
|
<SolidColorBrush x:Key="TextControlBorderBrush" Color="#2B3A58"/>
|
||||||
<Style TargetType="ScrollViewer">
|
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver" Color="#4AB8FF"/>
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
<SolidColorBrush x:Key="TextControlBorderBrushFocused" Color="#4AB8FF"/>
|
||||||
<Setter Property="Template">
|
<SolidColorBrush x:Key="TextControlForeground" Color="#F5F7FB"/>
|
||||||
<Setter.Value>
|
<SolidColorBrush x:Key="TextControlForegroundFocused" Color="#F5F7FB"/>
|
||||||
<ControlTemplate TargetType="ScrollViewer">
|
<SolidColorBrush x:Key="TextControlHeaderForeground" Color="#9FB1CC"/>
|
||||||
<Grid Background="{TemplateBinding Background}">
|
<SolidColorBrush x:Key="TextControlPlaceholderForeground" Color="#7488A6"/>
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<ScrollContentPresenter Grid.Row="0" Grid.Column="0" Margin="{TemplateBinding Padding}"/>
|
<SolidColorBrush x:Key="ComboBoxBackground" Color="#1D2940"/>
|
||||||
|
<SolidColorBrush x:Key="ComboBoxBackgroundPointerOver" Color="#233252"/>
|
||||||
|
<SolidColorBrush x:Key="ComboBoxBorderBrush" Color="#2B3A58"/>
|
||||||
|
<SolidColorBrush x:Key="ComboBoxForeground" Color="#F5F7FB"/>
|
||||||
|
<SolidColorBrush x:Key="ComboBoxHeaderForeground" Color="#9FB1CC"/>
|
||||||
|
<SolidColorBrush x:Key="ComboBoxItemBackgroundSelected" Color="#13324F"/>
|
||||||
|
<SolidColorBrush x:Key="ComboBoxDropDownBackground" Color="#10192B"/>
|
||||||
|
|
||||||
<ScrollBar x:Name="PART_VerticalScrollBar"
|
<SolidColorBrush x:Key="ButtonBackground" Color="#243554"/>
|
||||||
Grid.Row="0"
|
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="#2E446C"/>
|
||||||
Grid.Column="1"
|
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="#1B2A44"/>
|
||||||
Orientation="Vertical"
|
<SolidColorBrush x:Key="ButtonForeground" Color="#F5F7FB"/>
|
||||||
Value="{TemplateBinding VerticalOffset}"
|
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="#F5F7FB"/>
|
||||||
Maximum="{TemplateBinding ScrollableHeight}"
|
<SolidColorBrush x:Key="ButtonBorderBrush" Color="#2B3A58"/>
|
||||||
ViewportSize="{TemplateBinding ViewportHeight}"
|
|
||||||
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
|
|
||||||
|
|
||||||
<ScrollBar x:Name="PART_HorizontalScrollBar"
|
<SolidColorBrush x:Key="ContentDialogBackground" Color="#162033"/>
|
||||||
Grid.Row="1"
|
<SolidColorBrush x:Key="ContentDialogForeground" Color="#F5F7FB"/>
|
||||||
Grid.Column="0"
|
<SolidColorBrush x:Key="ContentDialogBorderBrush" Color="#35507D"/>
|
||||||
Orientation="Horizontal"
|
|
||||||
Value="{TemplateBinding HorizontalOffset}"
|
|
||||||
Maximum="{TemplateBinding ScrollableWidth}"
|
|
||||||
ViewportSize="{TemplateBinding ViewportWidth}"
|
|
||||||
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
|
|
||||||
|
|
||||||
<Border x:Name="CornerBox"
|
<SolidColorBrush x:Key="ListViewItemBackgroundSelected" Color="#13324F"/>
|
||||||
Grid.Row="1"
|
<SolidColorBrush x:Key="ListViewItemBackgroundPointerOver" Color="#1A2740"/>
|
||||||
Grid.Column="1"
|
<SolidColorBrush x:Key="ListViewItemForeground" Color="#F5F7FB"/>
|
||||||
Width="14"
|
|
||||||
Height="14"
|
<SolidColorBrush x:Key="CheckBoxCheckBackgroundFillUnchecked" Color="#1D2940"/>
|
||||||
Background="{DynamicResource ScrollTrackBrush}"
|
<SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeUnchecked" Color="#2B3A58"/>
|
||||||
Visibility="Collapsed"/>
|
<SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked" Color="#4AB8FF"/>
|
||||||
</Grid>
|
<SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked" Color="#4AB8FF"/>
|
||||||
<ControlTemplate.Triggers>
|
<SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked" Color="#07111D"/>
|
||||||
<MultiTrigger>
|
<SolidColorBrush x:Key="CheckBoxForegroundUnchecked" Color="#F5F7FB"/>
|
||||||
<MultiTrigger.Conditions>
|
<SolidColorBrush x:Key="CheckBoxForegroundChecked" Color="#F5F7FB"/>
|
||||||
<Condition Property="ComputedVerticalScrollBarVisibility" Value="Visible"/>
|
|
||||||
<Condition Property="ComputedHorizontalScrollBarVisibility" Value="Visible"/>
|
<SolidColorBrush x:Key="ProgressBarForeground" Color="#4AB8FF"/>
|
||||||
</MultiTrigger.Conditions>
|
<SolidColorBrush x:Key="ProgressBarBackground" Color="#1D2940"/>
|
||||||
<Setter TargetName="CornerBox" Property="Visibility" Value="Visible"/>
|
|
||||||
</MultiTrigger>
|
<SolidColorBrush x:Key="HeroBorderBrush" Color="#35507D"/>
|
||||||
</ControlTemplate.Triggers>
|
</ResourceDictionary>
|
||||||
</ControlTemplate>
|
<ResourceDictionary x:Key="Light">
|
||||||
</Setter.Value>
|
<SolidColorBrush x:Key="PageBrush" Color="#F4F7FB"/>
|
||||||
</Setter>
|
<SolidColorBrush x:Key="PanelBrush" Color="#FFFFFF"/>
|
||||||
</Style>
|
<SolidColorBrush x:Key="PanelAltBrush" Color="#EEF4FB"/>
|
||||||
<Style x:Key="ScrollBarThumbStyle" TargetType="Thumb">
|
<SolidColorBrush x:Key="FieldBrush" Color="#F7FAFD"/>
|
||||||
<Setter Property="Template">
|
<SolidColorBrush x:Key="BorderBrush" Color="#C7D3E3"/>
|
||||||
<Setter.Value>
|
<SolidColorBrush x:Key="AccentBrush" Color="#0E9AEF"/>
|
||||||
<ControlTemplate TargetType="Thumb">
|
<SolidColorBrush x:Key="AccentSoftBrush" Color="#D6EEFF"/>
|
||||||
<Border Background="{DynamicResource ScrollThumbBrush}" CornerRadius="6" Margin="2"/>
|
<SolidColorBrush x:Key="TextBrush" Color="#122033"/>
|
||||||
</ControlTemplate>
|
<SolidColorBrush x:Key="MutedBrush" Color="#5F7390"/>
|
||||||
</Setter.Value>
|
<SolidColorBrush x:Key="ButtonBrush" Color="#E5EDF7"/>
|
||||||
</Setter>
|
<SolidColorBrush x:Key="ButtonHoverBrush" Color="#D7E4F4"/>
|
||||||
<Style.Triggers>
|
<SolidColorBrush x:Key="PrimaryTextBrush" Color="#FFFFFF"/>
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter Property="Opacity" Value="1"/>
|
<SolidColorBrush x:Key="TextControlBackground" Color="#F7FAFD"/>
|
||||||
</Trigger>
|
<SolidColorBrush x:Key="TextControlBackgroundPointerOver" Color="#EEF4FB"/>
|
||||||
</Style.Triggers>
|
<SolidColorBrush x:Key="TextControlBackgroundFocused" Color="#FFFFFF"/>
|
||||||
</Style>
|
<SolidColorBrush x:Key="TextControlBorderBrush" Color="#C7D3E3"/>
|
||||||
<Style TargetType="RepeatButton" x:Key="ScrollBarButtonStyle">
|
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver" Color="#0E9AEF"/>
|
||||||
<Setter Property="Focusable" Value="False"/>
|
<SolidColorBrush x:Key="TextControlBorderBrushFocused" Color="#0E9AEF"/>
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
<SolidColorBrush x:Key="TextControlForeground" Color="#122033"/>
|
||||||
<Setter Property="BorderBrush" Value="Transparent"/>
|
<SolidColorBrush x:Key="TextControlForegroundFocused" Color="#122033"/>
|
||||||
<Setter Property="BorderThickness" Value="0"/>
|
<SolidColorBrush x:Key="TextControlHeaderForeground" Color="#5F7390"/>
|
||||||
<Setter Property="Template">
|
<SolidColorBrush x:Key="TextControlPlaceholderForeground" Color="#8194AC"/>
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="RepeatButton">
|
<SolidColorBrush x:Key="ComboBoxBackground" Color="#F7FAFD"/>
|
||||||
<Border Background="{TemplateBinding Background}" CornerRadius="6"/>
|
<SolidColorBrush x:Key="ComboBoxBackgroundPointerOver" Color="#EEF4FB"/>
|
||||||
</ControlTemplate>
|
<SolidColorBrush x:Key="ComboBoxBorderBrush" Color="#C7D3E3"/>
|
||||||
</Setter.Value>
|
<SolidColorBrush x:Key="ComboBoxForeground" Color="#122033"/>
|
||||||
</Setter>
|
<SolidColorBrush x:Key="ComboBoxHeaderForeground" Color="#5F7390"/>
|
||||||
</Style>
|
<SolidColorBrush x:Key="ComboBoxItemBackgroundSelected" Color="#D6EEFF"/>
|
||||||
<Style TargetType="ScrollBar">
|
<SolidColorBrush x:Key="ComboBoxDropDownBackground" Color="#FFFFFF"/>
|
||||||
<Setter Property="Width" Value="14"/>
|
|
||||||
<Setter Property="Background" Value="{DynamicResource ScrollTrackBrush}"/>
|
<SolidColorBrush x:Key="ButtonBackground" Color="#E5EDF7"/>
|
||||||
<Setter Property="Template">
|
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="#D7E4F4"/>
|
||||||
<Setter.Value>
|
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="#C7D9EE"/>
|
||||||
<ControlTemplate TargetType="ScrollBar">
|
<SolidColorBrush x:Key="ButtonForeground" Color="#122033"/>
|
||||||
<Grid Background="Transparent" Width="{TemplateBinding Width}">
|
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="#122033"/>
|
||||||
<Border Background="{DynamicResource ScrollTrackBrush}" CornerRadius="7" Margin="2"/>
|
<SolidColorBrush x:Key="ButtonBorderBrush" Color="#C7D3E3"/>
|
||||||
<Track x:Name="PART_Track" IsDirectionReversed="True" Margin="1">
|
|
||||||
<Track.DecreaseRepeatButton>
|
<SolidColorBrush x:Key="ContentDialogBackground" Color="#FFFFFF"/>
|
||||||
<RepeatButton Style="{StaticResource ScrollBarButtonStyle}" Command="ScrollBar.PageUpCommand"/>
|
<SolidColorBrush x:Key="ContentDialogForeground" Color="#122033"/>
|
||||||
</Track.DecreaseRepeatButton>
|
<SolidColorBrush x:Key="ContentDialogBorderBrush" Color="#C7D3E3"/>
|
||||||
<Track.Thumb>
|
|
||||||
<Thumb Style="{StaticResource ScrollBarThumbStyle}"/>
|
<SolidColorBrush x:Key="ListViewItemBackgroundSelected" Color="#D6EEFF"/>
|
||||||
</Track.Thumb>
|
<SolidColorBrush x:Key="ListViewItemBackgroundPointerOver" Color="#EEF4FB"/>
|
||||||
<Track.IncreaseRepeatButton>
|
<SolidColorBrush x:Key="ListViewItemForeground" Color="#122033"/>
|
||||||
<RepeatButton Style="{StaticResource ScrollBarButtonStyle}" Command="ScrollBar.PageDownCommand"/>
|
|
||||||
</Track.IncreaseRepeatButton>
|
<SolidColorBrush x:Key="CheckBoxCheckBackgroundFillUnchecked" Color="#F7FAFD"/>
|
||||||
</Track>
|
<SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeUnchecked" Color="#C7D3E3"/>
|
||||||
</Grid>
|
<SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked" Color="#0E9AEF"/>
|
||||||
<ControlTemplate.Triggers>
|
<SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked" Color="#0E9AEF"/>
|
||||||
<Trigger Property="Orientation" Value="Horizontal">
|
<SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked" Color="#FFFFFF"/>
|
||||||
<Setter Property="Height" Value="14"/>
|
<SolidColorBrush x:Key="CheckBoxForegroundUnchecked" Color="#122033"/>
|
||||||
<Setter TargetName="PART_Track" Property="IsDirectionReversed" Value="False"/>
|
<SolidColorBrush x:Key="CheckBoxForegroundChecked" Color="#122033"/>
|
||||||
</Trigger>
|
|
||||||
</ControlTemplate.Triggers>
|
<SolidColorBrush x:Key="ProgressBarForeground" Color="#0E9AEF"/>
|
||||||
</ControlTemplate>
|
<SolidColorBrush x:Key="ProgressBarBackground" Color="#F7FAFD"/>
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
<SolidColorBrush x:Key="HeroBorderBrush" Color="#A9C4E4"/>
|
||||||
</Style>
|
</ResourceDictionary>
|
||||||
<Style TargetType="TextBox">
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
<Setter Property="Background" Value="{DynamicResource FieldBrush}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
<!-- Global corner rounding applied to built-in Fluent controls -->
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
|
<CornerRadius x:Key="ControlCornerRadius">10</CornerRadius>
|
||||||
<Setter Property="CaretBrush" Value="{DynamicResource TextBrush}"/>
|
<CornerRadius x:Key="OverlayCornerRadius">18</CornerRadius>
|
||||||
<Setter Property="SelectionBrush" Value="{DynamicResource SelectionBrush}"/>
|
|
||||||
<Setter Property="SelectionTextBrush" Value="{DynamicResource SelectionTextBrush}"/>
|
<x:Double x:Key="ContentDialogMaxWidth">460</x:Double>
|
||||||
<Setter Property="BorderThickness" Value="1"/>
|
|
||||||
<Setter Property="Padding" Value="9,7"/>
|
<Style TargetType="Page">
|
||||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
<Setter Property="Background" Value="{ThemeResource PageBrush}" />
|
||||||
<Setter Property="SnapsToDevicePixels" Value="True"/>
|
<Setter Property="FontFamily" Value="Bahnschrift" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="ComboBox">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource FieldBrush}"/>
|
<Style x:Key="CardBorderStyle" TargetType="Border">
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
<Setter Property="Background" Value="{ThemeResource PanelBrush}" />
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
|
<Setter Property="BorderBrush" Value="{ThemeResource BorderBrush}" />
|
||||||
<Setter Property="BorderThickness" Value="1"/>
|
<Setter Property="BorderThickness" Value="1" />
|
||||||
<Setter Property="Padding" Value="8,0"/>
|
<Setter Property="CornerRadius" Value="16" />
|
||||||
<Setter Property="Height" Value="42"/>
|
</Style>
|
||||||
<Setter Property="MinHeight" Value="42"/>
|
|
||||||
<Setter Property="Template">
|
<Style x:Key="SectionTitleStyle" TargetType="TextBlock">
|
||||||
<Setter.Value>
|
<Setter Property="Foreground" Value="{ThemeResource TextBrush}" />
|
||||||
<ControlTemplate TargetType="ComboBox">
|
<Setter Property="FontSize" Value="15" />
|
||||||
<Grid>
|
<Setter Property="FontWeight" Value="SemiBold" />
|
||||||
<Border x:Name="OuterBorder"
|
</Style>
|
||||||
Background="{TemplateBinding Background}"
|
|
||||||
BorderBrush="{TemplateBinding BorderBrush}"
|
<Style x:Key="MutedTextStyle" TargetType="TextBlock">
|
||||||
BorderThickness="{TemplateBinding BorderThickness}"
|
<Setter Property="Foreground" Value="{ThemeResource MutedBrush}" />
|
||||||
CornerRadius="12"
|
<Setter Property="FontSize" Value="13" />
|
||||||
Height="{TemplateBinding Height}"
|
</Style>
|
||||||
MinHeight="{TemplateBinding MinHeight}">
|
|
||||||
<Grid>
|
<Style x:Key="FieldLabelStyle" TargetType="TextBlock">
|
||||||
<Grid.ColumnDefinitions>
|
<Setter Property="Foreground" Value="{ThemeResource MutedBrush}" />
|
||||||
<ColumnDefinition Width="*"/>
|
<Setter Property="FontSize" Value="12" />
|
||||||
<ColumnDefinition Width="42"/>
|
<Setter Property="Margin" Value="0,0,0,4" />
|
||||||
</Grid.ColumnDefinitions>
|
</Style>
|
||||||
<ContentPresenter Margin="12,0,8,0"
|
|
||||||
VerticalAlignment="Center"
|
<Style TargetType="TextBlock">
|
||||||
HorizontalAlignment="Left"
|
<Setter Property="Foreground" Value="{ThemeResource TextBrush}" />
|
||||||
Content="{TemplateBinding SelectionBoxItem}"
|
<Setter Property="FontSize" Value="13" />
|
||||||
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
|
</Style>
|
||||||
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
|
|
||||||
<Border Grid.Column="1" Background="{DynamicResource AccentSoftBrush}" CornerRadius="0,12,12,0" BorderBrush="{DynamicResource BorderBrush}" BorderThickness="1,0,0,0">
|
<Style TargetType="Button">
|
||||||
<Path HorizontalAlignment="Center"
|
<Setter Property="Padding" Value="16,9" />
|
||||||
VerticalAlignment="Center"
|
<Setter Property="FontSize" Value="13" />
|
||||||
Fill="{DynamicResource AccentBrush}"
|
<Setter Property="CornerRadius" Value="10" />
|
||||||
Data="M 0 0 L 4 4 L 8 0 Z"/>
|
</Style>
|
||||||
</Border>
|
|
||||||
</Grid>
|
<Style x:Key="PrimaryButtonStyle" TargetType="Button">
|
||||||
</Border>
|
<Setter Property="Background" Value="{ThemeResource AccentBrush}" />
|
||||||
<Popup x:Name="PART_Popup"
|
<Setter Property="Foreground" Value="{ThemeResource PrimaryTextBrush}" />
|
||||||
Placement="Bottom"
|
<Setter Property="BorderBrush" Value="{ThemeResource AccentBrush}" />
|
||||||
AllowsTransparency="True"
|
<Setter Property="FontWeight" Value="SemiBold" />
|
||||||
Focusable="False"
|
<Setter Property="Padding" Value="22,10" />
|
||||||
IsOpen="{TemplateBinding IsDropDownOpen}"
|
<Setter Property="CornerRadius" Value="10" />
|
||||||
PopupAnimation="Fade">
|
</Style>
|
||||||
<Border Margin="0,8,0,0"
|
|
||||||
Background="{DynamicResource PopupBrush}"
|
<Style x:Key="IconButtonStyle" TargetType="Button">
|
||||||
BorderBrush="{DynamicResource BorderBrush}"
|
<Setter Property="Width" Value="40" />
|
||||||
BorderThickness="1"
|
<Setter Property="Height" Value="40" />
|
||||||
CornerRadius="14"
|
<Setter Property="Padding" Value="0" />
|
||||||
MinWidth="{TemplateBinding ActualWidth}">
|
<Setter Property="FontSize" Value="16" />
|
||||||
<ScrollViewer Margin="6" SnapsToDevicePixels="True" MaxHeight="280">
|
<Setter Property="CornerRadius" Value="10" />
|
||||||
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Contained"/>
|
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||||
</ScrollViewer>
|
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||||
</Border>
|
</Style>
|
||||||
</Popup>
|
|
||||||
<ToggleButton x:Name="HitTarget" Opacity="0" Focusable="False" IsChecked="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"/>
|
<!-- Explicit styles bound to ContentDialog.PrimaryButtonStyle / CloseButtonStyle so its
|
||||||
</Grid>
|
built-in buttons match the app's own Button look instead of the default Fluent
|
||||||
<ControlTemplate.Triggers>
|
accent-pill / plain styles. -->
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
<Style x:Key="DialogPrimaryButtonStyle" TargetType="Button">
|
||||||
<Setter TargetName="OuterBorder" Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
|
<Setter Property="Background" Value="{ThemeResource AccentBrush}" />
|
||||||
</Trigger>
|
<Setter Property="Foreground" Value="{ThemeResource PrimaryTextBrush}" />
|
||||||
<Trigger Property="IsKeyboardFocusWithin" Value="True">
|
<Setter Property="BorderBrush" Value="{ThemeResource AccentBrush}" />
|
||||||
<Setter TargetName="OuterBorder" Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
|
<Setter Property="BorderThickness" Value="1" />
|
||||||
</Trigger>
|
<Setter Property="FontWeight" Value="SemiBold" />
|
||||||
<Trigger Property="IsEnabled" Value="False">
|
<Setter Property="FontSize" Value="13" />
|
||||||
<Setter Property="Opacity" Value="0.65"/>
|
<Setter Property="Padding" Value="22,10" />
|
||||||
</Trigger>
|
<Setter Property="CornerRadius" Value="10" />
|
||||||
</ControlTemplate.Triggers>
|
<Setter Property="MinHeight" Value="40" />
|
||||||
</ControlTemplate>
|
<Setter Property="MinWidth" Value="110" />
|
||||||
</Setter.Value>
|
</Style>
|
||||||
</Setter>
|
|
||||||
</Style>
|
<Style x:Key="DialogCloseButtonStyle" TargetType="Button">
|
||||||
<Style TargetType="ComboBoxItem">
|
<Setter Property="Background" Value="{ThemeResource ButtonBrush}" />
|
||||||
<Setter Property="Background" Value="{DynamicResource FieldBrush}"/>
|
<Setter Property="Foreground" Value="{ThemeResource TextBrush}" />
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
<Setter Property="BorderBrush" Value="{ThemeResource BorderBrush}" />
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
<Setter Property="BorderThickness" Value="1" />
|
||||||
<Setter Property="Padding" Value="10,8"/>
|
<Setter Property="FontSize" Value="13" />
|
||||||
<Setter Property="Template">
|
<Setter Property="Padding" Value="16,9" />
|
||||||
<Setter.Value>
|
<Setter Property="CornerRadius" Value="10" />
|
||||||
<ControlTemplate TargetType="ComboBoxItem">
|
<Setter Property="MinHeight" Value="40" />
|
||||||
<Border x:Name="ItemBorder" Background="{TemplateBinding Background}" CornerRadius="10" Padding="{TemplateBinding Padding}">
|
<Setter Property="MinWidth" Value="110" />
|
||||||
<ContentPresenter/>
|
</Style>
|
||||||
</Border>
|
|
||||||
<ControlTemplate.Triggers>
|
<Style TargetType="TextBox">
|
||||||
<Trigger Property="IsHighlighted" Value="True">
|
<Setter Property="FontSize" Value="13" />
|
||||||
<Setter TargetName="ItemBorder" Property="Background" Value="{DynamicResource AccentSoftBrush}"/>
|
<Setter Property="MinHeight" Value="38" />
|
||||||
</Trigger>
|
</Style>
|
||||||
<Trigger Property="IsSelected" Value="True">
|
|
||||||
<Setter TargetName="ItemBorder" Property="Background" Value="{DynamicResource AccentBrush}"/>
|
<Style TargetType="ComboBox">
|
||||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
|
<Setter Property="FontSize" Value="13" />
|
||||||
</Trigger>
|
<Setter Property="MinHeight" Value="38" />
|
||||||
</ControlTemplate.Triggers>
|
</Style>
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
<Style TargetType="CheckBox">
|
||||||
</Setter>
|
<Setter Property="FontSize" Value="13" />
|
||||||
<Style.Triggers>
|
</Style>
|
||||||
<Trigger Property="IsHighlighted" Value="True">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource AccentSoftBrush}"/>
|
<Style TargetType="ProgressBar">
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
<Setter Property="MinHeight" Value="8" />
|
||||||
</Trigger>
|
</Style>
|
||||||
<Trigger Property="IsSelected" Value="True">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource AccentBrush}"/>
|
<Style TargetType="ListView">
|
||||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
|
<Setter Property="Background" Value="{ThemeResource FieldBrush}" />
|
||||||
</Trigger>
|
<Setter Property="BorderBrush" Value="{ThemeResource BorderBrush}" />
|
||||||
</Style.Triggers>
|
<Setter Property="BorderThickness" Value="1" />
|
||||||
</Style>
|
<Setter Property="CornerRadius" Value="10" />
|
||||||
<Style TargetType="ListBox">
|
<Setter Property="FontSize" Value="13" />
|
||||||
<Setter Property="Background" Value="{DynamicResource FieldBrush}"/>
|
<Setter Property="Padding" Value="4" />
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
</Style>
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
|
|
||||||
<Setter Property="BorderThickness" Value="1"/>
|
<Style TargetType="ListViewItem">
|
||||||
</Style>
|
<Setter Property="MinHeight" Value="32" />
|
||||||
<Style TargetType="ListBoxItem">
|
<Setter Property="Padding" Value="8,6" />
|
||||||
<Setter Property="Padding" Value="8,6"/>
|
<Setter Property="CornerRadius" Value="6" />
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
</Style>
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
|
||||||
<Style.Triggers>
|
<Style TargetType="ContentDialog">
|
||||||
<Trigger Property="IsSelected" Value="True">
|
<Setter Property="CornerRadius" Value="18" />
|
||||||
<Setter Property="Background" Value="{DynamicResource AccentSoftBrush}"/>
|
</Style>
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
</ResourceDictionary>
|
||||||
</Trigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
<Style TargetType="Button">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource ButtonBrush}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
|
|
||||||
<Setter Property="BorderThickness" Value="1"/>
|
|
||||||
<Setter Property="Padding" Value="14,8"/>
|
|
||||||
<Setter Property="Cursor" Value="Hand"/>
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="Button">
|
|
||||||
<Border Background="{TemplateBinding Background}"
|
|
||||||
BorderBrush="{TemplateBinding BorderBrush}"
|
|
||||||
BorderThickness="{TemplateBinding BorderThickness}"
|
|
||||||
CornerRadius="10">
|
|
||||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"
|
|
||||||
Margin="{TemplateBinding Padding}"/>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
<Style.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource ButtonHoverBrush}"/>
|
|
||||||
</Trigger>
|
|
||||||
<Trigger Property="IsEnabled" Value="False">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource ButtonDisabledBrush}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource ButtonDisabledTextBrush}"/>
|
|
||||||
</Trigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
<Style x:Key="PrimaryButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource AccentBrush}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
|
|
||||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
|
||||||
<Setter Property="Padding" Value="22,11"/>
|
|
||||||
</Style>
|
|
||||||
<Style x:Key="IconButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
|
|
||||||
<Setter Property="Width" Value="46"/>
|
|
||||||
<Setter Property="Height" Value="46"/>
|
|
||||||
<Setter Property="Padding" Value="0"/>
|
|
||||||
<Setter Property="FontSize" Value="20"/>
|
|
||||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
|
||||||
</Style>
|
|
||||||
<Style x:Key="SecondaryPanel" TargetType="Border">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource PanelBrush}"/>
|
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
|
|
||||||
<Setter Property="BorderThickness" Value="1"/>
|
|
||||||
<Setter Property="CornerRadius" Value="18"/>
|
|
||||||
</Style>
|
|
||||||
<Style TargetType="GroupBox">
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
|
|
||||||
<Setter Property="Background" Value="{DynamicResource PanelBrush}"/>
|
|
||||||
<Setter Property="Padding" Value="12"/>
|
|
||||||
<Setter Property="Margin" Value="0,0,0,16"/>
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="GroupBox">
|
|
||||||
<Border Background="{TemplateBinding Background}"
|
|
||||||
BorderBrush="{TemplateBinding BorderBrush}"
|
|
||||||
BorderThickness="1"
|
|
||||||
CornerRadius="18"
|
|
||||||
Padding="16">
|
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<TextBlock Text="{TemplateBinding Header}"
|
|
||||||
FontSize="16"
|
|
||||||
FontWeight="SemiBold"
|
|
||||||
Foreground="{DynamicResource TextBrush}"
|
|
||||||
Margin="0,0,0,12"/>
|
|
||||||
<ContentPresenter Grid.Row="1"/>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
<Style TargetType="ProgressBar">
|
|
||||||
<Setter Property="Background" Value="{DynamicResource FieldBrush}"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource AccentBrush}"/>
|
|
||||||
<Setter Property="Height" Value="12"/>
|
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
|
|
||||||
<Setter Property="BorderThickness" Value="1"/>
|
|
||||||
</Style>
|
|
||||||
<Style TargetType="TextBlock">
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
|
||||||
</Style>
|
|
||||||
<Style x:Key="TitleBarButton" TargetType="Button">
|
|
||||||
<Setter Property="Width" Value="46"/>
|
|
||||||
<Setter Property="Height" Value="40"/>
|
|
||||||
<Setter Property="Background" Value="Transparent"/>
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
|
|
||||||
<Setter Property="BorderThickness" Value="0"/>
|
|
||||||
<Setter Property="FontFamily" Value="Segoe Fluent Icons, Segoe MDL2 Assets"/>
|
|
||||||
<Setter Property="FontSize" Value="11"/>
|
|
||||||
<Setter Property="Cursor" Value="Arrow"/>
|
|
||||||
<Setter Property="Focusable" Value="False"/>
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="Button">
|
|
||||||
<Border x:Name="Bg" Background="{TemplateBinding Background}">
|
|
||||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
|
||||||
</Border>
|
|
||||||
<ControlTemplate.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter TargetName="Bg" Property="Background" Value="{DynamicResource ButtonHoverBrush}"/>
|
|
||||||
</Trigger>
|
|
||||||
</ControlTemplate.Triggers>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
<Style x:Key="TitleBarCloseButton" TargetType="Button" BasedOn="{StaticResource TitleBarButton}">
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="Button">
|
|
||||||
<Border x:Name="Bg" Background="{TemplateBinding Background}">
|
|
||||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
|
||||||
</Border>
|
|
||||||
<ControlTemplate.Triggers>
|
|
||||||
<Trigger Property="IsMouseOver" Value="True">
|
|
||||||
<Setter TargetName="Bg" Property="Background" Value="#E81123"/>
|
|
||||||
<Setter Property="Foreground" Value="White"/>
|
|
||||||
</Trigger>
|
|
||||||
</ControlTemplate.Triggers>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
</Application.Resources>
|
</Application.Resources>
|
||||||
</Application>
|
</Application>
|
||||||
|
|||||||
@@ -1,5 +1,48 @@
|
|||||||
namespace AmigaDB.VideoRenderer;
|
using Windows.ApplicationModel;
|
||||||
|
using Windows.ApplicationModel.Activation;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Foundation.Collections;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||||
|
using Microsoft.UI.Xaml.Data;
|
||||||
|
using Microsoft.UI.Xaml.Input;
|
||||||
|
using Microsoft.UI.Xaml.Media;
|
||||||
|
using Microsoft.UI.Xaml.Navigation;
|
||||||
|
using Microsoft.UI.Xaml.Shapes;
|
||||||
|
using WinRT.Interop;
|
||||||
|
|
||||||
public partial class App : System.Windows.Application
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|
||||||
|
namespace AmiReel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application
|
||||||
{
|
{
|
||||||
|
private Window? _window;
|
||||||
|
public static IntPtr MainWindowHandle { get; private set; }
|
||||||
|
public static MainWindow? MainWindowInstance { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the singleton application object. This is the first line of authored code
|
||||||
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||||
|
/// </summary>
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when the application is launched.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">Details about the launch request and process.</param>
|
||||||
|
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
|
||||||
|
{
|
||||||
|
_window = new MainWindow();
|
||||||
|
MainWindowHandle = WindowNative.GetWindowHandle(_window);
|
||||||
|
_window.Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 200 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
@@ -2,7 +2,7 @@ using Microsoft.UI.Xaml;
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Media;
|
using Microsoft.UI.Xaml.Media;
|
||||||
|
|
||||||
namespace AmiReel_WinUI;
|
namespace AmiReel;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Builds ContentDialogs styled to match the app's own palette and button shapes,
|
/// Builds ContentDialogs styled to match the app's own palette and button shapes,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<Page
|
<Page
|
||||||
x:Class="AmiReel_WinUI.MainPage"
|
x:Class="AmiReel.MainPage"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
@@ -2,8 +2,8 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using AmigaDB.VideoRenderer.Models;
|
using AmiReel.Models;
|
||||||
using AmigaDB.VideoRenderer.Services;
|
using AmiReel.Services;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
@@ -12,7 +12,7 @@ using Windows.Storage;
|
|||||||
using Windows.Storage.Pickers;
|
using Windows.Storage.Pickers;
|
||||||
using WinRT.Interop;
|
using WinRT.Interop;
|
||||||
|
|
||||||
namespace AmiReel_WinUI;
|
namespace AmiReel;
|
||||||
|
|
||||||
public sealed partial class MainPage : Page
|
public sealed partial class MainPage : Page
|
||||||
{
|
{
|
||||||
@@ -1,279 +1,38 @@
|
|||||||
<Window x:Class="AmigaDB.VideoRenderer.MainWindow"
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
<Window
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
x:Class="AmiReel.MainWindow"
|
||||||
Title="AmiReel" Height="860" Width="1280" MinHeight="780" MinWidth="1100"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
WindowStartupLocation="CenterScreen"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
WindowStyle="None"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
ResizeMode="CanResize"
|
xmlns:local="using:AmiReel"
|
||||||
Icon="assets/AmiReel.ico">
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
<WindowChrome.WindowChrome>
|
Title="AmiReel"
|
||||||
<WindowChrome CaptionHeight="40"
|
mc:Ignorable="d">
|
||||||
ResizeBorderThickness="6"
|
<Grid Background="{ThemeResource PageBrush}">
|
||||||
GlassFrameThickness="0"
|
|
||||||
UseAeroCaptionButtons="False"/>
|
|
||||||
</WindowChrome.WindowChrome>
|
|
||||||
<Grid Background="{DynamicResource PageBrush}">
|
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid Grid.Row="0" Background="{DynamicResource PanelBrush}" Height="40">
|
<Grid x:Name="AppTitleBar" Grid.Row="0" Height="44" Background="{ThemeResource PanelBrush}">
|
||||||
<Grid.ColumnDefinitions>
|
<StackPanel Orientation="Horizontal" Spacing="10" VerticalAlignment="Center" Margin="14,0,0,0">
|
||||||
<ColumnDefinition Width="Auto"/>
|
<Image Source="ms-appx:///Assets/Square44x44Logo.scale-200.png"
|
||||||
<ColumnDefinition Width="*"/>
|
Width="20"
|
||||||
<ColumnDefinition Width="Auto"/>
|
Height="20"
|
||||||
<ColumnDefinition Width="Auto"/>
|
Stretch="Uniform" />
|
||||||
<ColumnDefinition Width="Auto"/>
|
<TextBlock Text="AmiReel"
|
||||||
</Grid.ColumnDefinitions>
|
FontFamily="Bahnschrift"
|
||||||
|
FontSize="14"
|
||||||
<Image Source="assets/AmiReel.ico" Width="18" Height="18" Margin="14,0,8,0" VerticalAlignment="Center"
|
FontWeight="SemiBold"
|
||||||
WindowChrome.IsHitTestVisibleInChrome="False"/>
|
VerticalAlignment="Center" />
|
||||||
<TextBlock Grid.Column="1" Text="AmiReel" VerticalAlignment="Center" FontWeight="SemiBold"
|
</StackPanel>
|
||||||
Foreground="{DynamicResource TextBrush}" WindowChrome.IsHitTestVisibleInChrome="False"/>
|
|
||||||
|
|
||||||
<Button x:Name="MinimizeButton" Grid.Column="2" Content="" Style="{StaticResource TitleBarButton}"
|
|
||||||
Click="Minimize_Click" ToolTip="Minimize" WindowChrome.IsHitTestVisibleInChrome="True"/>
|
|
||||||
<Button x:Name="MaximizeButton" Grid.Column="3" Content="" Style="{StaticResource TitleBarButton}"
|
|
||||||
Click="MaximizeRestore_Click" ToolTip="Maximize" WindowChrome.IsHitTestVisibleInChrome="True"/>
|
|
||||||
<Button x:Name="CloseWindowButton" Grid.Column="4" Content="" Style="{StaticResource TitleBarCloseButton}"
|
|
||||||
Click="CloseWindowButton_Click" ToolTip="Close" WindowChrome.IsHitTestVisibleInChrome="True"/>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid Grid.Row="1">
|
<!--
|
||||||
<Grid>
|
The Frame hosts pages for your application content. Add your UI to
|
||||||
<Grid.Background>
|
MainPage.xaml rather than here so you can use Page features such as
|
||||||
<DrawingBrush Stretch="None" Viewport="0,0,36,36" ViewportUnits="Absolute" Opacity="0.08">
|
navigation events and the Loaded lifecycle.
|
||||||
<DrawingBrush.Drawing>
|
-->
|
||||||
<GeometryDrawing Brush="{DynamicResource PageOverlayBrush}">
|
<Frame x:Name="RootFrame" Grid.Row="1" />
|
||||||
<GeometryDrawing.Geometry>
|
|
||||||
<GeometryGroup>
|
|
||||||
<EllipseGeometry Center="10,10" RadiusX="1.2" RadiusY="1.2"/>
|
|
||||||
<EllipseGeometry Center="28,18" RadiusX="1.2" RadiusY="1.2"/>
|
|
||||||
</GeometryGroup>
|
|
||||||
</GeometryDrawing.Geometry>
|
|
||||||
</GeometryDrawing>
|
|
||||||
</DrawingBrush.Drawing>
|
|
||||||
</DrawingBrush>
|
|
||||||
</Grid.Background>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid Margin="18">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
<ColumnDefinition Width="14"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<GroupBox Header="Source recordings">
|
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="98"/><RowDefinition Height="Auto"/></Grid.RowDefinitions>
|
|
||||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
||||||
<Button Content="Add video files…" Click="AddInputs_Click" Margin="0,0,8,0"/>
|
|
||||||
<Button Content="Clear" Click="ClearInputs_Click"/>
|
|
||||||
</StackPanel>
|
|
||||||
<ListBox x:Name="InputList" Grid.Row="1" SelectionChanged="InputList_SelectionChanged"
|
|
||||||
AllowDrop="True" DragEnter="InputList_DragEnter" DragOver="InputList_DragEnter" Drop="InputList_Drop"
|
|
||||||
ToolTip="Drag and drop video files here to add them"/>
|
|
||||||
<Button x:Name="PreviewSourceButton" Grid.Row="2" Content="Preview selected" Click="PreviewSource_Click"
|
|
||||||
HorizontalAlignment="Left" Margin="0,10,0,0" IsEnabled="False"/>
|
|
||||||
</Grid>
|
|
||||||
</GroupBox>
|
|
||||||
|
|
||||||
<GroupBox Grid.Column="2" Header="End card and output">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="Auto"/></Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="55"/><RowDefinition Height="55"/><RowDefinition Height="55"/></Grid.RowDefinitions>
|
|
||||||
<TextBlock Text="Leave blank to use a built-in black end card." Foreground="{DynamicResource MutedBrush}" Margin="0,0,0,6"/>
|
|
||||||
<TextBox x:Name="EndCardBox" Grid.Row="1" Margin="0,0,8,8" ToolTip="Optional end-card image"/>
|
|
||||||
<Button Grid.Row="1" Grid.Column="1" Content="Browse…" Click="BrowseEndCard_Click" Margin="0,0,0,8"/>
|
|
||||||
<TextBox x:Name="OutputFolderBox" Grid.Row="2" Margin="0,0,8,8" ToolTip="Output folder"/>
|
|
||||||
<Button Grid.Row="2" Grid.Column="1" Content="Browse…" Click="BrowseOutput_Click" Margin="0,0,0,8"/>
|
|
||||||
<TextBox x:Name="OutputNameBox" Grid.Row="3" Grid.ColumnSpan="2" Text="amigadb_intro" ToolTip="Output filename prefix"/>
|
|
||||||
</Grid>
|
|
||||||
</GroupBox>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<GroupBox Grid.Row="1" Header="Render progress" Margin="0,14,0,0">
|
|
||||||
<StackPanel>
|
|
||||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
||||||
<TextBlock x:Name="StageText" Text="Ready" FontWeight="SemiBold"/>
|
|
||||||
<TextBlock x:Name="PercentText" Text="0%" Foreground="{DynamicResource AccentBrush}" Margin="6,0,0,0"/>
|
|
||||||
</StackPanel>
|
|
||||||
<ProgressBar x:Name="RenderProgress" Minimum="0" Maximum="100" Foreground="{DynamicResource AccentBrush}"/>
|
|
||||||
<TextBlock x:Name="StatusText" Text="Select the recordings and start the render. The end card is optional."
|
|
||||||
Foreground="{DynamicResource MutedBrush}" TextWrapping="Wrap" Margin="0,8,0,0"/>
|
|
||||||
</StackPanel>
|
|
||||||
</GroupBox>
|
|
||||||
|
|
||||||
<GroupBox Grid.Row="2" Header="FFmpeg log" Margin="0,14,0,0">
|
|
||||||
<TextBox x:Name="LogBox" IsReadOnly="True" AcceptsReturn="True"
|
|
||||||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
|
|
||||||
FontFamily="Consolas" FontSize="11" TextWrapping="NoWrap"/>
|
|
||||||
</GroupBox>
|
|
||||||
|
|
||||||
<DockPanel Grid.Row="3" Margin="0,12,0,0" LastChildFill="False">
|
|
||||||
<StackPanel Orientation="Horizontal" DockPanel.Dock="Left">
|
|
||||||
<Button x:Name="OpenOutputButton" Content="Open output folder" Click="OpenOutput_Click" IsEnabled="False" Margin="0,0,10,0"/>
|
|
||||||
<Button x:Name="PreviewRenderedButton" Content="Preview render" Click="PreviewRendered_Click" IsEnabled="False"/>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" DockPanel.Dock="Right">
|
|
||||||
<Button x:Name="OpenSettingsButton" Content="⚙" Click="OpenSettings_Click" Style="{StaticResource IconButton}" Margin="0,0,10,0" ToolTip="Settings"/>
|
|
||||||
<Button x:Name="CancelButton" Content="Cancel" Click="Cancel_Click" IsEnabled="False" Margin="0,0,10,0"/>
|
|
||||||
<Button x:Name="RenderButton" Content="Start render" Style="{StaticResource PrimaryButton}" Click="Render_Click"/>
|
|
||||||
</StackPanel>
|
|
||||||
</DockPanel>
|
|
||||||
|
|
||||||
<Border x:Name="SettingsOverlay" Grid.RowSpan="4" Background="#88060B14" Visibility="Collapsed">
|
|
||||||
<Grid Margin="40">
|
|
||||||
<Border Width="760"
|
|
||||||
MaxHeight="720"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Background="{DynamicResource PanelBrush}"
|
|
||||||
BorderBrush="{DynamicResource HeroBorderBrush}"
|
|
||||||
BorderThickness="1.5"
|
|
||||||
CornerRadius="24"
|
|
||||||
Padding="20">
|
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<TextBlock Text="Settings" FontSize="24" FontWeight="SemiBold" Margin="0,0,0,14"/>
|
|
||||||
|
|
||||||
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
|
|
||||||
<StackPanel>
|
|
||||||
<GroupBox Header="Appearance">
|
|
||||||
<StackPanel>
|
|
||||||
<TextBlock Text="Theme" Foreground="{DynamicResource MutedBrush}" Margin="0,0,0,4"/>
|
|
||||||
<ComboBox x:Name="ThemeBox" SelectionChanged="ThemeBox_SelectionChanged">
|
|
||||||
<ComboBoxItem Content="Dark" Tag="Dark"/>
|
|
||||||
<ComboBoxItem Content="Light" Tag="Light"/>
|
|
||||||
</ComboBox>
|
|
||||||
</StackPanel>
|
|
||||||
</GroupBox>
|
|
||||||
|
|
||||||
<GroupBox Header="Timing and screenshots">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions><RowDefinition/><RowDefinition/></Grid.RowDefinitions>
|
|
||||||
<StackPanel Margin="0,0,8,10">
|
|
||||||
<TextBlock Text="Trim start (seconds)" Foreground="{DynamicResource MutedBrush}"/>
|
|
||||||
<TextBox x:Name="TrimBox"/>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Grid.Column="1" Margin="8,0,0,10">
|
|
||||||
<TextBlock Text="Fade (seconds)" Foreground="{DynamicResource MutedBrush}"/>
|
|
||||||
<TextBox x:Name="FadeBox"/>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Grid.Row="1" Margin="0,0,8,0">
|
|
||||||
<TextBlock Text="End-card hold (seconds)" Foreground="{DynamicResource MutedBrush}"/>
|
|
||||||
<TextBox x:Name="HoldBox"/>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Grid.Row="1" Grid.Column="1" Margin="8,0,0,0">
|
|
||||||
<TextBlock Text="Thumbnail interval (seconds)" Foreground="{DynamicResource MutedBrush}"/>
|
|
||||||
<TextBox x:Name="IntervalBox"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</GroupBox>
|
|
||||||
|
|
||||||
<GroupBox Header="Source files">
|
|
||||||
<StackPanel>
|
|
||||||
<CheckBox x:Name="MoveSourcesBox"
|
|
||||||
Content="Move source videos to destination\originals"
|
|
||||||
IsChecked="True"
|
|
||||||
Margin="0,0,0,6"/>
|
|
||||||
<TextBlock Foreground="{DynamicResource MutedBrush}"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
Text="After a successful render, original recordings are moved into an originals subfolder of the output folder. Uncheck to leave them where they are."/>
|
|
||||||
</StackPanel>
|
|
||||||
</GroupBox>
|
|
||||||
|
|
||||||
<GroupBox Header="Video encoding">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions><RowDefinition/><RowDefinition/></Grid.RowDefinitions>
|
|
||||||
<StackPanel Margin="0,0,8,8">
|
|
||||||
<TextBlock Text="Encoder" Foreground="{DynamicResource MutedBrush}" Margin="0,0,0,4"/>
|
|
||||||
<ComboBox x:Name="EncoderBox" SelectedIndex="0">
|
|
||||||
<ComboBoxItem Content="Auto (NVENC → CPU fallback)" Tag="Auto"/>
|
|
||||||
<ComboBoxItem Content="NVIDIA NVENC" Tag="NvidiaNvenc"/>
|
|
||||||
<ComboBoxItem Content="CPU libx264" Tag="CpuX264"/>
|
|
||||||
</ComboBox>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Grid.Column="1" Margin="8,0,0,8">
|
|
||||||
<TextBlock Text="Output" Foreground="{DynamicResource MutedBrush}" Margin="0,0,0,4"/>
|
|
||||||
<TextBox Text="3840 × 2160 · 50 FPS" IsReadOnly="True"/>
|
|
||||||
</StackPanel>
|
|
||||||
<TextBlock Grid.Row="1" Grid.ColumnSpan="2" Foreground="{DynamicResource MutedBrush}"
|
|
||||||
Text="NVENC: preset P6 / CQ 16 · CPU: slow / CRF 13"/>
|
|
||||||
</Grid>
|
|
||||||
</GroupBox>
|
|
||||||
|
|
||||||
<GroupBox Header="FFmpeg tools">
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="Auto"/></Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions>
|
|
||||||
<TextBlock Text="Optional override. Leave blank to auto-detect FFmpeg and FFprobe from PATH, then use the embedded fallback."
|
|
||||||
Foreground="{DynamicResource MutedBrush}" Margin="0,0,0,6"/>
|
|
||||||
<TextBox x:Name="FfmpegPathBox" Grid.Row="1" Margin="0,0,8,8" ToolTip="Path to ffmpeg.exe"/>
|
|
||||||
<Button Grid.Row="1" Grid.Column="1" Content="Browse…" Click="BrowseFfmpeg_Click" Margin="0,0,0,8"/>
|
|
||||||
<TextBox x:Name="FfprobePathBox" Grid.Row="2" Margin="0,0,8,8" ToolTip="Path to ffprobe.exe"/>
|
|
||||||
<Button Grid.Row="2" Grid.Column="1" Content="Browse…" Click="BrowseFfprobe_Click" Margin="0,0,0,8"/>
|
|
||||||
<TextBox x:Name="PreviewPlayerPathBox" Grid.Row="3" Margin="0,0,8,0" ToolTip="Optional path to mpv.exe or another video player"/>
|
|
||||||
<Button Grid.Row="3" Grid.Column="1" Content="Browse…" Click="BrowsePreviewPlayer_Click"/>
|
|
||||||
</Grid>
|
|
||||||
</GroupBox>
|
|
||||||
</StackPanel>
|
|
||||||
</ScrollViewer>
|
|
||||||
|
|
||||||
<Grid Grid.Row="2" Margin="0,14,0,0">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<TextBlock Text="Advanced settings are saved automatically." Foreground="{DynamicResource MutedBrush}" VerticalAlignment="Center"/>
|
|
||||||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
|
|
||||||
<Button Content="Close" Click="CloseSettings_Click" MinWidth="140" Margin="0,0,10,0"/>
|
|
||||||
<Button Content="Done" Style="{StaticResource PrimaryButton}" Click="CloseSettings_Click" MinWidth="140"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Border x:Name="ExitConfirmOverlay" Grid.RowSpan="2" Background="#88060B14" Visibility="Collapsed">
|
|
||||||
<Border Width="420"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Background="{DynamicResource PanelBrush}"
|
|
||||||
BorderBrush="{DynamicResource HeroBorderBrush}"
|
|
||||||
BorderThickness="1.5"
|
|
||||||
CornerRadius="20"
|
|
||||||
Padding="24">
|
|
||||||
<StackPanel>
|
|
||||||
<TextBlock Text="Exit AmiReel?" FontSize="20" FontWeight="SemiBold" Margin="0,0,0,10"/>
|
|
||||||
<TextBlock Text="Are you sure you want to close the application?"
|
|
||||||
Foreground="{DynamicResource MutedBrush}" TextWrapping="Wrap" Margin="0,0,0,20"/>
|
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
|
||||||
<Button Content="Cancel" Click="CancelExit_Click" MinWidth="110" Margin="0,0,10,0"/>
|
|
||||||
<Button Content="Exit" Style="{StaticResource PrimaryButton}" Click="ConfirmExit_Click" MinWidth="110"/>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@@ -1,425 +1,116 @@
|
|||||||
using System.Collections.ObjectModel;
|
using Microsoft.UI;
|
||||||
using System.Diagnostics;
|
using Microsoft.UI.Windowing;
|
||||||
using System.Globalization;
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using Windows.Graphics;
|
||||||
using System.Windows;
|
using Windows.UI;
|
||||||
using System.Windows.Controls;
|
using WinRT.Interop;
|
||||||
using System.Windows.Interop;
|
|
||||||
using AmigaDB.VideoRenderer.Models;
|
|
||||||
using AmigaDB.VideoRenderer.Services;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using System.Windows.Media;
|
|
||||||
|
|
||||||
namespace AmigaDB.VideoRenderer;
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|
||||||
public partial class MainWindow : Window
|
namespace AmiReel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The application window. This hosts a Frame that displays pages. Add your
|
||||||
|
/// UI and logic to MainPage.xaml / MainPage.xaml.cs instead of here so you
|
||||||
|
/// can use Page features such as navigation events and the Loaded lifecycle.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
private readonly ObservableCollection<string> _inputs = [];
|
|
||||||
private readonly AppSettings _loadedSettings;
|
|
||||||
private readonly StringBuilder _pendingLog = new();
|
|
||||||
private readonly object _logLock = new();
|
|
||||||
private CancellationTokenSource? _renderCancellation;
|
|
||||||
private string? _lastRenderedFile;
|
|
||||||
private bool _logFlushScheduled;
|
|
||||||
private bool _titleBarIsLight;
|
|
||||||
private bool _exitConfirmed;
|
private bool _exitConfirmed;
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
InputList.ItemsSource = _inputs;
|
App.MainWindowInstance = this;
|
||||||
_loadedSettings = AppSettingsStore.Load();
|
|
||||||
OutputFolderBox.Text = _loadedSettings.OutputFolder;
|
ExtendsContentIntoTitleBar = true;
|
||||||
EndCardBox.Text = _loadedSettings.EndCardPath;
|
SetTitleBar(AppTitleBar);
|
||||||
FfmpegPathBox.Text = _loadedSettings.FfmpegPath;
|
|
||||||
FfprobePathBox.Text = _loadedSettings.FfprobePath;
|
string? executablePath = Environment.ProcessPath;
|
||||||
PreviewPlayerPathBox.Text = _loadedSettings.PreviewPlayerPath;
|
if (!string.IsNullOrWhiteSpace(executablePath) && File.Exists(executablePath))
|
||||||
TrimBox.Text = _loadedSettings.TrimStart;
|
AppWindow.SetIcon(executablePath);
|
||||||
FadeBox.Text = _loadedSettings.FadeSeconds;
|
|
||||||
HoldBox.Text = _loadedSettings.EndCardHoldSeconds;
|
SetDefaultSizeAndPosition();
|
||||||
IntervalBox.Text = _loadedSettings.ThumbnailInterval;
|
|
||||||
SelectEncoder(_loadedSettings.Encoder);
|
// Navigate the root frame to the main page on startup.
|
||||||
SelectTheme(_loadedSettings.Theme);
|
RootFrame.Navigate(typeof(MainPage));
|
||||||
ApplyTheme(_loadedSettings.Theme);
|
|
||||||
MoveSourcesBox.IsChecked = _loadedSettings.ShouldMoveSourcesToOriginals;
|
AppWindow.Closing += AppWindow_Closing;
|
||||||
Closing += MainWindow_Closing;
|
|
||||||
SourceInitialized += (_, _) => UpdateTitleBarTheme(_titleBarIsLight);
|
|
||||||
StateChanged += (_, _) => MaximizeButton.Content = WindowState == WindowState.Maximized ? "\uE923" : "\uE922";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Minimize_Click(object sender, RoutedEventArgs e) => WindowState = WindowState.Minimized;
|
private void SetDefaultSizeAndPosition()
|
||||||
|
{
|
||||||
|
const int DefaultWidth = 1280;
|
||||||
|
const int DefaultHeight = 860;
|
||||||
|
const int MinWidth = 1100;
|
||||||
|
const int MinHeight = 780;
|
||||||
|
|
||||||
private void MaximizeRestore_Click(object sender, RoutedEventArgs e)
|
IntPtr hwnd = WindowNative.GetWindowHandle(this);
|
||||||
=> WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
|
double scale = GetDpiForWindow(hwnd) / 96.0;
|
||||||
|
int width = (int)(DefaultWidth * scale);
|
||||||
|
int height = (int)(DefaultHeight * scale);
|
||||||
|
|
||||||
private void CloseWindowButton_Click(object sender, RoutedEventArgs e) => Close();
|
AppWindow.Resize(new SizeInt32(width, height));
|
||||||
|
|
||||||
private void MainWindow_Closing(object? sender, System.ComponentModel.CancelEventArgs e)
|
if (AppWindow.Presenter is OverlappedPresenter presenter)
|
||||||
|
{
|
||||||
|
presenter.PreferredMinimumWidth = (int)(MinWidth * scale);
|
||||||
|
presenter.PreferredMinimumHeight = (int)(MinHeight * scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayArea? displayArea = DisplayArea.GetFromWindowId(Win32Interop.GetWindowIdFromWindow(hwnd), DisplayAreaFallback.Primary);
|
||||||
|
if (displayArea is not null)
|
||||||
|
{
|
||||||
|
int centerX = displayArea.WorkArea.X + (displayArea.WorkArea.Width - width) / 2;
|
||||||
|
int centerY = displayArea.WorkArea.Y + (displayArea.WorkArea.Height - height) / 2;
|
||||||
|
AppWindow.Move(new PointInt32(centerX, centerY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern int GetDpiForWindow(IntPtr hwnd);
|
||||||
|
|
||||||
|
public void ApplyTheme(bool isDark)
|
||||||
|
{
|
||||||
|
if (Content is FrameworkElement root)
|
||||||
|
root.RequestedTheme = isDark ? ElementTheme.Dark : ElementTheme.Light;
|
||||||
|
|
||||||
|
AppWindowTitleBar titleBar = AppWindow.TitleBar;
|
||||||
|
Color foreground = isDark ? Color.FromArgb(255, 0xF5, 0xF7, 0xFB) : Color.FromArgb(255, 0x12, 0x20, 0x33);
|
||||||
|
Color hoverBackground = isDark ? Color.FromArgb(255, 0x2E, 0x44, 0x6C) : Color.FromArgb(255, 0xD7, 0xE4, 0xF4);
|
||||||
|
|
||||||
|
titleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||||
|
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||||
|
titleBar.ButtonForegroundColor = foreground;
|
||||||
|
titleBar.ButtonInactiveForegroundColor = foreground;
|
||||||
|
titleBar.ButtonHoverBackgroundColor = hoverBackground;
|
||||||
|
titleBar.ButtonHoverForegroundColor = foreground;
|
||||||
|
titleBar.ButtonPressedBackgroundColor = hoverBackground;
|
||||||
|
titleBar.ButtonPressedForegroundColor = foreground;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void AppWindow_Closing(AppWindow sender, AppWindowClosingEventArgs args)
|
||||||
{
|
{
|
||||||
if (_exitConfirmed) return;
|
if (_exitConfirmed) return;
|
||||||
e.Cancel = true;
|
args.Cancel = true;
|
||||||
ExitConfirmOverlay.Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CancelExit_Click(object sender, RoutedEventArgs e) => ExitConfirmOverlay.Visibility = Visibility.Collapsed;
|
FrameworkElement root = (FrameworkElement)Content;
|
||||||
|
ContentDialog dialog = DialogHelper.CreateStyled(RootFrame.XamlRoot, root.RequestedTheme);
|
||||||
|
dialog.Title = "Exit AmiReel?";
|
||||||
|
dialog.Content = "Are you sure you want to close the application?";
|
||||||
|
dialog.PrimaryButtonText = "Exit";
|
||||||
|
dialog.CloseButtonText = "Cancel";
|
||||||
|
dialog.DefaultButton = ContentDialogButton.Primary;
|
||||||
|
|
||||||
|
ContentDialogResult result = await dialog.ShowAsync();
|
||||||
|
if (result != ContentDialogResult.Primary) return;
|
||||||
|
|
||||||
private void ConfirmExit_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
_exitConfirmed = true;
|
_exitConfirmed = true;
|
||||||
SaveSettings();
|
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InputList_DragEnter(object sender, DragEventArgs e)
|
|
||||||
{
|
|
||||||
e.Effects = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None;
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InputList_Drop(object sender, DragEventArgs e)
|
|
||||||
{
|
|
||||||
if (!e.Data.GetDataPresent(DataFormats.FileDrop)) return;
|
|
||||||
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop)!;
|
|
||||||
foreach (string file in files.Where(Models.SupportedVideoFormats.IsSupported).OrderBy(NaturalKey))
|
|
||||||
if (!_inputs.Contains(file, StringComparer.OrdinalIgnoreCase)) _inputs.Add(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddInputs_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
OpenFileDialog dialog = new() { Filter = $"Video files|{Models.SupportedVideoFormats.PickerFilter}", Multiselect = true };
|
|
||||||
if (dialog.ShowDialog(this) != true) return;
|
|
||||||
foreach (string file in dialog.FileNames.OrderBy(NaturalKey))
|
|
||||||
if (!_inputs.Contains(file, StringComparer.OrdinalIgnoreCase)) _inputs.Add(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ClearInputs_Click(object sender, RoutedEventArgs e) => _inputs.Clear();
|
|
||||||
|
|
||||||
private void BrowseEndCard_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
OpenFileDialog dialog = new() { Filter = "Images|*.png;*.jpg;*.jpeg;*.webp;*.bmp|All files|*.*" };
|
|
||||||
if (dialog.ShowDialog(this) == true) EndCardBox.Text = dialog.FileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BrowseOutput_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
OpenFolderDialog dialog = new() { InitialDirectory = OutputFolderBox.Text };
|
|
||||||
if (dialog.ShowDialog(this) == true) OutputFolderBox.Text = dialog.FolderName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BrowseFfmpeg_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
OpenFileDialog dialog = new() { Filter = "FFmpeg executable (ffmpeg.exe)|ffmpeg.exe|Executable files (*.exe)|*.exe|All files|*.*" };
|
|
||||||
if (dialog.ShowDialog(this) == true) FfmpegPathBox.Text = dialog.FileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BrowseFfprobe_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
OpenFileDialog dialog = new() { Filter = "FFprobe executable (ffprobe.exe)|ffprobe.exe|Executable files (*.exe)|*.exe|All files|*.*" };
|
|
||||||
if (dialog.ShowDialog(this) == true) FfprobePathBox.Text = dialog.FileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BrowsePreviewPlayer_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
OpenFileDialog dialog = new() { Filter = "Video player (*.exe)|*.exe|All files|*.*" };
|
|
||||||
if (dialog.ShowDialog(this) == true) PreviewPlayerPathBox.Text = dialog.FileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OpenSettings_Click(object sender, RoutedEventArgs e) => SettingsOverlay.Visibility = Visibility.Visible;
|
|
||||||
|
|
||||||
private void CloseSettings_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
SettingsOverlay.Visibility = Visibility.Collapsed;
|
|
||||||
SaveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Render_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
RenderSettings settings = ReadSettings();
|
|
||||||
SaveSettings();
|
|
||||||
SetRendering(true);
|
|
||||||
LogBox.Clear();
|
|
||||||
_renderCancellation = new CancellationTokenSource();
|
|
||||||
Progress<RenderProgress> progress = new(UpdateProgress);
|
|
||||||
IReadOnlyList<string> resolvedInputs = await new RenderPipeline().RenderAsync(settings, progress, AppendLog, _renderCancellation.Token);
|
|
||||||
ReplaceInputs(resolvedInputs);
|
|
||||||
_lastRenderedFile = Path.Combine(settings.OutputDirectory, settings.OutputName + "_final.mp4");
|
|
||||||
OpenOutputButton.IsEnabled = true;
|
|
||||||
PreviewRenderedButton.IsEnabled = File.Exists(_lastRenderedFile);
|
|
||||||
MessageBox.Show(this, "The AmiReel render completed successfully.", "Render complete",
|
|
||||||
MessageBoxButton.OK, MessageBoxImage.Information);
|
|
||||||
}
|
|
||||||
catch (OperationCanceledException)
|
|
||||||
{
|
|
||||||
UpdateProgress(new(RenderProgress.Value, "Cancelled", "The render was cancelled."));
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
AppendLog("ERROR: " + exception);
|
|
||||||
MessageBox.Show(this, UserFacingErrors.Summarize(exception), "Render failed", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
StageText.Text = "Failed";
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_renderCancellation?.Dispose();
|
|
||||||
_renderCancellation = null;
|
|
||||||
SetRendering(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private RenderSettings ReadSettings()
|
|
||||||
{
|
|
||||||
static double Number(string text, string name)
|
|
||||||
{
|
|
||||||
if (!double.TryParse(text.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out double value) || value < 0)
|
|
||||||
throw new ArgumentException($"Enter a valid non-negative value for {name}.");
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
if (!int.TryParse(IntervalBox.Text, out int interval) || interval < 1)
|
|
||||||
throw new ArgumentException("Thumbnail interval must be at least one second.");
|
|
||||||
EncoderMode encoder = Enum.Parse<EncoderMode>(((ComboBoxItem)EncoderBox.SelectedItem).Tag!.ToString()!);
|
|
||||||
return new(_inputs.ToList(), EndCardBox.Text.Trim(), OutputFolderBox.Text.Trim(), OutputNameBox.Text.Trim(),
|
|
||||||
FfmpegPathBox.Text.Trim(), FfprobePathBox.Text.Trim(),
|
|
||||||
encoder, Number(TrimBox.Text, "trim start"), Number(FadeBox.Text, "fade"), Number(HoldBox.Text, "end-card hold"), interval,
|
|
||||||
MoveSourcesBox.IsChecked == true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ReplaceInputs(IReadOnlyList<string> paths)
|
|
||||||
{
|
|
||||||
_inputs.Clear();
|
|
||||||
foreach (string path in paths)
|
|
||||||
_inputs.Add(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Cancel_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
CancelButton.IsEnabled = false;
|
|
||||||
StatusText.Text = "Stopping FFmpeg…";
|
|
||||||
_renderCancellation?.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OpenOutput_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
if (Directory.Exists(OutputFolderBox.Text))
|
|
||||||
Process.Start(new ProcessStartInfo("explorer.exe", OutputFolderBox.Text) { UseShellExecute = true });
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PreviewSource_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
if (InputList.SelectedItem is string path)
|
|
||||||
OpenPreview(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PreviewRendered_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(_lastRenderedFile) && File.Exists(_lastRenderedFile))
|
|
||||||
OpenPreview(_lastRenderedFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InputList_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
||||||
=> PreviewSourceButton.IsEnabled = InputList.SelectedItem is string;
|
|
||||||
|
|
||||||
private void SetRendering(bool rendering)
|
|
||||||
{
|
|
||||||
RenderButton.IsEnabled = !rendering;
|
|
||||||
CancelButton.IsEnabled = rendering;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateProgress(RenderProgress value)
|
|
||||||
{
|
|
||||||
RenderProgress.Value = value.Percent;
|
|
||||||
PercentText.Text = $"{value.Percent:0}%";
|
|
||||||
StageText.Text = value.Stage;
|
|
||||||
StatusText.Text = value.Message;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AppendLog(string line)
|
|
||||||
{
|
|
||||||
lock (_logLock)
|
|
||||||
{
|
|
||||||
_pendingLog.AppendLine(line);
|
|
||||||
if (_logFlushScheduled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_logFlushScheduled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = Dispatcher.BeginInvoke(() =>
|
|
||||||
{
|
|
||||||
string chunk;
|
|
||||||
lock (_logLock)
|
|
||||||
{
|
|
||||||
chunk = _pendingLog.ToString();
|
|
||||||
_pendingLog.Clear();
|
|
||||||
_logFlushScheduled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunk.Length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LogBox.AppendText(chunk);
|
|
||||||
LogBox.ScrollToEnd();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string NaturalKey(string path)
|
|
||||||
{
|
|
||||||
string name = Path.GetFileNameWithoutExtension(path);
|
|
||||||
int underscore = name.LastIndexOf('_');
|
|
||||||
return underscore >= 0 && int.TryParse(name[(underscore + 1)..], out int number)
|
|
||||||
? name[..underscore] + number.ToString("D10")
|
|
||||||
: name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThemeBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (!IsLoaded) return;
|
|
||||||
string theme = SelectedTheme();
|
|
||||||
ApplyTheme(theme);
|
|
||||||
SaveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveSettings()
|
|
||||||
{
|
|
||||||
AppSettingsStore.Save(new AppSettings(
|
|
||||||
OutputFolderBox.Text.Trim(),
|
|
||||||
EndCardBox.Text.Trim(),
|
|
||||||
FfmpegPathBox.Text.Trim(),
|
|
||||||
FfprobePathBox.Text.Trim(),
|
|
||||||
PreviewPlayerPathBox.Text.Trim(),
|
|
||||||
SelectedTheme(),
|
|
||||||
SelectedEncoder(),
|
|
||||||
TrimBox.Text.Trim(),
|
|
||||||
FadeBox.Text.Trim(),
|
|
||||||
HoldBox.Text.Trim(),
|
|
||||||
IntervalBox.Text.Trim(),
|
|
||||||
MoveSourcesBox.IsChecked == true));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OpenPreview(string mediaPath)
|
|
||||||
{
|
|
||||||
if (!File.Exists(mediaPath))
|
|
||||||
{
|
|
||||||
MessageBox.Show(this, "The selected media file was not found.", "Preview unavailable",
|
|
||||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string playerPath = PreviewPlayerPathBox.Text.Trim();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(playerPath))
|
|
||||||
{
|
|
||||||
if (!File.Exists(playerPath))
|
|
||||||
throw new FileNotFoundException("Configured preview player was not found.", playerPath);
|
|
||||||
|
|
||||||
ProcessStartInfo customPlayer = new()
|
|
||||||
{
|
|
||||||
FileName = playerPath,
|
|
||||||
UseShellExecute = false
|
|
||||||
};
|
|
||||||
customPlayer.ArgumentList.Add(mediaPath);
|
|
||||||
Process.Start(customPlayer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Process.Start(new ProcessStartInfo(mediaPath) { UseShellExecute = true });
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
MessageBox.Show(this, exception.Message, "Preview failed", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string SelectedTheme() => ((ComboBoxItem)ThemeBox.SelectedItem).Tag!.ToString()!;
|
|
||||||
private string SelectedEncoder() => ((ComboBoxItem)EncoderBox.SelectedItem).Tag!.ToString()!;
|
|
||||||
|
|
||||||
private void SelectTheme(string theme)
|
|
||||||
{
|
|
||||||
foreach (ComboBoxItem item in ThemeBox.Items)
|
|
||||||
{
|
|
||||||
if (string.Equals(item.Tag?.ToString(), theme, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
ThemeBox.SelectedItem = item;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ThemeBox.SelectedIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SelectEncoder(string encoder)
|
|
||||||
{
|
|
||||||
foreach (ComboBoxItem item in EncoderBox.Items)
|
|
||||||
{
|
|
||||||
if (string.Equals(item.Tag?.ToString(), encoder, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
EncoderBox.SelectedItem = item;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EncoderBox.SelectedIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ApplyTheme(string theme)
|
|
||||||
{
|
|
||||||
bool light = string.Equals(theme, "Light", StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
SetBrush("PageBrush", light ? "#F4F7FB" : "#0E1525");
|
|
||||||
SetBrush("PanelBrush", light ? "#FFFFFF" : "#162033");
|
|
||||||
SetBrush("PanelAltBrush", light ? "#EEF4FB" : "#1A2740");
|
|
||||||
SetBrush("FieldBrush", light ? "#F7FAFD" : "#1D2940");
|
|
||||||
SetBrush("BorderBrush", light ? "#C7D3E3" : "#2B3A58");
|
|
||||||
SetBrush("AccentBrush", light ? "#0E9AEF" : "#4AB8FF");
|
|
||||||
SetBrush("AccentSoftBrush", light ? "#D6EEFF" : "#13324F");
|
|
||||||
SetBrush("TextBrush", light ? "#122033" : "#F5F7FB");
|
|
||||||
SetBrush("MutedBrush", light ? "#5F7390" : "#9FB1CC");
|
|
||||||
SetBrush("ButtonBrush", light ? "#E5EDF7" : "#243554");
|
|
||||||
SetBrush("ButtonHoverBrush", light ? "#D7E4F4" : "#2E446C");
|
|
||||||
SetBrush("ButtonDisabledBrush", light ? "#EEF2F7" : "#2A3140");
|
|
||||||
SetBrush("ButtonDisabledTextBrush", light ? "#8C99AB" : "#7E8BA1");
|
|
||||||
SetBrush("PrimaryTextBrush", light ? "#FFFFFF" : "#07111D");
|
|
||||||
SetBrush("SelectionBrush", light ? "#BEE4FF" : "#295C87");
|
|
||||||
SetBrush("SelectionTextBrush", light ? "#122033" : "#FFFFFF");
|
|
||||||
|
|
||||||
_titleBarIsLight = light;
|
|
||||||
UpdateTitleBarTheme(light);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetBrush(string key, string color)
|
|
||||||
{
|
|
||||||
Application.Current.Resources[key] = new SolidColorBrush((Color)ColorConverter.ConvertFromString(color));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateTitleBarTheme(bool light)
|
|
||||||
{
|
|
||||||
IntPtr hwnd = new WindowInteropHelper(this).Handle;
|
|
||||||
if (hwnd == IntPtr.Zero) return;
|
|
||||||
|
|
||||||
int useImmersiveDarkMode = light ? 0 : 1;
|
|
||||||
DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, ref useImmersiveDarkMode, sizeof(int));
|
|
||||||
|
|
||||||
int captionColor = ToColorRef(light ? "#F4F7FB" : "#0E1525");
|
|
||||||
int textColor = ToColorRef(light ? "#122033" : "#F5F7FB");
|
|
||||||
DwmSetWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, ref captionColor, sizeof(int));
|
|
||||||
DwmSetWindowAttribute(hwnd, DWMWA_TEXT_COLOR, ref textColor, sizeof(int));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int ToColorRef(string hexColor)
|
|
||||||
{
|
|
||||||
Color color = (Color)ColorConverter.ConvertFromString(hexColor);
|
|
||||||
return color.R | (color.G << 8) | (color.B << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
|
|
||||||
private const int DWMWA_CAPTION_COLOR = 35;
|
|
||||||
private const int DWMWA_TEXT_COLOR = 36;
|
|
||||||
|
|
||||||
[DllImport("dwmapi.dll", PreserveSig = true)]
|
|
||||||
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attribute, ref int value, int size);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace AmigaDB.VideoRenderer.Models;
|
namespace AmiReel.Models;
|
||||||
|
|
||||||
public sealed record AppSettings(
|
public sealed record AppSettings(
|
||||||
string OutputFolder,
|
string OutputFolder,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace AmigaDB.VideoRenderer.Models;
|
namespace AmiReel.Models;
|
||||||
|
|
||||||
public enum EncoderMode
|
public enum EncoderMode
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace AmigaDB.VideoRenderer.Models;
|
namespace AmiReel.Models;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Video file extensions accepted as render sources. FFmpeg can demux far more than this,
|
/// Video file extensions accepted as render sources. FFmpeg can demux far more than this,
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||||
|
-->
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
|
<Platform>ARM64</Platform>
|
||||||
|
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||||
|
<PublishDir>bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\</PublishDir>
|
||||||
|
<SelfContained>true</SelfContained>
|
||||||
|
<PublishSingleFile>False</PublishSingleFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||||
|
-->
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
|
<PublishDir>bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\</PublishDir>
|
||||||
|
<SelfContained>true</SelfContained>
|
||||||
|
<PublishSingleFile>False</PublishSingleFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||||
|
-->
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
|
<Platform>x86</Platform>
|
||||||
|
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
|
||||||
|
<PublishDir>bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\</PublishDir>
|
||||||
|
<SelfContained>true</SelfContained>
|
||||||
|
<PublishSingleFile>False</PublishSingleFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"AmiReel.WinUI (Package)": {
|
"AmiReel (Package)": {
|
||||||
"commandName": "MsixPackage"
|
"commandName": "MsixPackage"
|
||||||
},
|
},
|
||||||
"AmiReel.WinUI (Unpackaged)": {
|
"AmiReel (Unpackaged)": {
|
||||||
"commandName": "Project"
|
"commandName": "Project"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,111 +1,90 @@
|
|||||||
# AmiReel
|
# AmiReel
|
||||||
|
|
||||||
AmiReel is a Windows video-rendering tool for turning Amiga AVI captures into:
|
AmiReel is a Windows desktop app for turning Amiga (or any) screen recordings into:
|
||||||
|
|
||||||
- a 4K 50 FPS final video,
|
- a 4K 50 FPS final video,
|
||||||
- PNG/JPG thumbnails,
|
- PNG/JPG thumbnails,
|
||||||
- an animated WebP preview,
|
- an animated WebP preview.
|
||||||
- and a publishable Windows desktop app workflow.
|
|
||||||
|
|
||||||
The repository currently contains two desktop frontends that share the same render pipeline:
|
Built with **WinUI 3** on the Windows App SDK, driving FFmpeg under the hood.
|
||||||
|
|
||||||
- `AmiReel.WinUI`
|
|
||||||
The newer WinUI 3 application. This is the default publish target.
|
|
||||||
- `AmigaDB.VideoRenderer.csproj`
|
|
||||||
The existing WPF application.
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- multiple ordered AVI inputs
|
- Multiple ordered video inputs — `.avi`, `.mp4`, `.m4v`, `.mov`, `.mkv`, `.webm`, `.wmv`, `.flv`, `.mpg`, `.mpeg`, `.ts`, `.3gp`
|
||||||
|
- Drag-and-drop or file-picker source selection
|
||||||
- 3840×2160 output at 50 FPS
|
- 3840×2160 output at 50 FPS
|
||||||
- NVIDIA NVENC with automatic CPU `libx264` fallback
|
- NVIDIA NVENC with automatic CPU `libx264` fallback
|
||||||
- configurable trim, fade, end-card hold, and thumbnail interval
|
- Configurable trim, fade, end-card hold, and thumbnail interval
|
||||||
- optional end-card image
|
- Optional end-card image
|
||||||
- live render progress with frame counters
|
- Live render progress with frame counters and FFmpeg log output
|
||||||
- FFmpeg log output
|
- Source and final-render preview (built-in or a custom player)
|
||||||
- source video preview and final render preview
|
- Dark and light themes
|
||||||
- dark and light themes
|
- Optional move of source recordings into `originals/` in the output folder
|
||||||
- optional move of source recordings into `originals` in the output folder
|
- Optional custom `ffmpeg.exe` / `ffprobe.exe` paths, with automatic detection from `PATH`
|
||||||
- optional custom `ffmpeg.exe` / `ffprobe.exe` paths
|
- Self-contained single-file publish for easy distribution
|
||||||
- automatic FFmpeg detection from `PATH`
|
|
||||||
- single-file WinUI publish for easier distribution
|
## Project Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
AmiReel.csproj Project file
|
||||||
|
AmiReel.slnx Solution file
|
||||||
|
App.xaml(.cs) Application entry point
|
||||||
|
MainWindow.xaml(.cs) Window shell: custom title bar, theming, exit confirmation
|
||||||
|
MainPage.xaml(.cs) Main UI: source list, settings, render controls
|
||||||
|
DialogHelper.cs Shared ContentDialog styling (Settings, exit, error dialogs)
|
||||||
|
Package.appxmanifest MSIX packaging identity and tile/icon declarations
|
||||||
|
app.manifest Win32 manifest (DPI awareness, OS compatibility)
|
||||||
|
Assets/ Packaged app icons and tiles (all required sizes)
|
||||||
|
branding/ Source artwork the Assets/ tiles are generated from
|
||||||
|
Models/
|
||||||
|
AppSettings.cs Persisted user settings
|
||||||
|
RenderSettings.cs Render job parameters
|
||||||
|
SupportedVideoFormats.cs Accepted input file extensions
|
||||||
|
Services/
|
||||||
|
RenderPipeline.cs Main render workflow (FFmpeg orchestration)
|
||||||
|
ProcessRunner.cs FFmpeg process execution and progress parsing
|
||||||
|
ToolExtractor.cs FFmpeg resolution, extraction, and fallback logic
|
||||||
|
MediaProbe.cs Duration/audio-stream probing via ffprobe
|
||||||
|
FfmpegLibraryProbe.cs NVENC capability probing
|
||||||
|
AppSettingsStore.cs Settings load/save (JSON in %LOCALAPPDATA%)
|
||||||
|
UserFacingErrors.cs Exception-to-message translation
|
||||||
|
ThirdParty/ Embedded ffmpeg.exe / ffprobe.exe (not checked in, see below)
|
||||||
|
publish-win-x64.ps1 Publish script
|
||||||
|
```
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
For development:
|
For development:
|
||||||
|
|
||||||
- Windows 10 or Windows 11
|
- Windows 10 or Windows 11
|
||||||
- .NET SDK
|
- .NET 10 SDK with WinUI 3 / Windows App SDK workload
|
||||||
- WPF project: .NET 8 SDK
|
- Windows x64 FFmpeg binaries in `ThirdParty/`:
|
||||||
- WinUI project: .NET 10 SDK and WinUI/Windows App SDK support
|
|
||||||
- Windows x64 FFmpeg binaries in `ThirdParty`
|
|
||||||
- `ThirdParty\ffmpeg.exe`
|
- `ThirdParty\ffmpeg.exe`
|
||||||
- `ThirdParty\ffprobe.exe`
|
- `ThirdParty\ffprobe.exe`
|
||||||
|
|
||||||
For end users:
|
For end users:
|
||||||
|
|
||||||
- Windows 10 or Windows 11 x64
|
- Windows 10 or Windows 11 x64
|
||||||
- the published AmiReel executable
|
- The published `AmiReel.exe` — FFmpeg is not required separately if you distribute AmiReel with the embedded `ThirdParty` binaries
|
||||||
- FFmpeg is not required separately if you distribute AmiReel with embedded `ThirdParty` FFmpeg binaries
|
|
||||||
|
|
||||||
## Project Layout
|
|
||||||
|
|
||||||
- `AmiReel.WinUI\`
|
|
||||||
WinUI 3 frontend
|
|
||||||
- `MainWindow.xaml` and `MainWindow.xaml.cs`
|
|
||||||
WPF frontend
|
|
||||||
- `Services\RenderPipeline.cs`
|
|
||||||
Main render workflow
|
|
||||||
- `Services\ProcessRunner.cs`
|
|
||||||
FFmpeg process execution and progress parsing
|
|
||||||
- `Services\ToolExtractor.cs`
|
|
||||||
FFmpeg resolution, extraction, and fallback logic
|
|
||||||
- `publish-win-x64.ps1`
|
|
||||||
Publish script
|
|
||||||
|
|
||||||
## Run in Development
|
## Run in Development
|
||||||
|
|
||||||
### WinUI
|
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
dotnet build .\AmiReel.WinUI\AmiReel.WinUI.csproj
|
dotnet build .\AmiReel.csproj
|
||||||
dotnet run --project .\AmiReel.WinUI\AmiReel.WinUI.csproj
|
dotnet run --project .\AmiReel.csproj
|
||||||
```
|
|
||||||
|
|
||||||
### WPF
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
dotnet build .\AmigaDB.VideoRenderer.csproj
|
|
||||||
dotnet run --project .\AmigaDB.VideoRenderer.csproj
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Publish
|
## Publish
|
||||||
|
|
||||||
### Default: WinUI
|
|
||||||
|
|
||||||
The publish script now defaults to the WinUI application:
|
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\publish-win-x64.ps1
|
.\publish-win-x64.ps1
|
||||||
```
|
```
|
||||||
|
|
||||||
This publishes the WinUI app as a self-contained single-file executable.
|
This publishes a self-contained, single-file `win-x64` executable. At the end of the script
|
||||||
|
you'll see the release folder and final executable path, for example:
|
||||||
At the end of the script you will see:
|
|
||||||
|
|
||||||
- the release folder path
|
|
||||||
- the final executable path
|
|
||||||
|
|
||||||
Example output path:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
AmiReel.WinUI\bin\Release\net10.0-windows10.0.26100.0\win-x64\publish\AmiReel.exe
|
bin\Release\net10.0-windows10.0.26100.0\win-x64\publish\AmiReel.exe
|
||||||
```
|
|
||||||
|
|
||||||
### Publish WPF instead
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
.\publish-win-x64.ps1 -Target Wpf
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
@@ -113,42 +92,33 @@ AmiReel.WinUI\bin\Release\net10.0-windows10.0.26100.0\win-x64\publish\AmiReel.ex
|
|||||||
### For developers
|
### For developers
|
||||||
|
|
||||||
1. Clone the repository.
|
1. Clone the repository.
|
||||||
2. Add `ffmpeg.exe` and `ffprobe.exe` to `ThirdParty`.
|
2. Add `ffmpeg.exe` and `ffprobe.exe` to `ThirdParty\`.
|
||||||
3. Restore and build the desired app:
|
3. Restore and build:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
dotnet build .\AmigaDB.VideoRenderer.sln
|
dotnet build .\AmiReel.slnx
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Run either the WinUI or WPF project.
|
|
||||||
|
|
||||||
### For end users
|
### For end users
|
||||||
|
|
||||||
1. Copy the published `AmiReel.exe` from the publish folder to any location, for example:
|
1. Copy the published `AmiReel.exe` to any location, for example `C:\Apps\AmiReel\`.
|
||||||
|
|
||||||
```text
|
|
||||||
C:\Apps\AmiReel\
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Double-click `AmiReel.exe`.
|
2. Double-click `AmiReel.exe`.
|
||||||
3. If FFmpeg is embedded in the build, no extra setup is required.
|
3. If FFmpeg is embedded in the build, no extra setup is required.
|
||||||
4. If you want to use your own FFmpeg build:
|
4. To use your own FFmpeg build instead, open **Settings** and set:
|
||||||
open `Settings` and select:
|
- `ffmpeg.exe` path
|
||||||
- `ffmpeg.exe`
|
- `ffprobe.exe` path
|
||||||
- `ffprobe.exe`
|
|
||||||
|
|
||||||
### Optional desktop shortcut
|
### Optional desktop shortcut
|
||||||
|
|
||||||
1. Right-click `AmiReel.exe`.
|
Right-click `AmiReel.exe` → **Send to** → **Desktop (create shortcut)**.
|
||||||
2. Choose `Send to` -> `Desktop (create shortcut)`.
|
|
||||||
|
|
||||||
## FFmpeg Behavior
|
## FFmpeg Behavior
|
||||||
|
|
||||||
AmiReel resolves FFmpeg in this order:
|
AmiReel resolves FFmpeg in this order:
|
||||||
|
|
||||||
1. custom paths from settings
|
1. Custom paths from Settings
|
||||||
2. `ffmpeg.exe` and `ffprobe.exe` found on system `PATH`
|
2. `ffmpeg.exe` / `ffprobe.exe` found on the system `PATH`
|
||||||
3. embedded `ThirdParty` binaries
|
3. Embedded `ThirdParty` binaries (extracted to `%LOCALAPPDATA%\AmiReel\tools` on first use)
|
||||||
|
|
||||||
If NVENC cannot be initialized, AmiReel automatically falls back to CPU `libx264`.
|
If NVENC cannot be initialized, AmiReel automatically falls back to CPU `libx264`.
|
||||||
|
|
||||||
@@ -160,41 +130,25 @@ User settings are stored in:
|
|||||||
%LOCALAPPDATA%\AmiReel\settings.json
|
%LOCALAPPDATA%\AmiReel\settings.json
|
||||||
```
|
```
|
||||||
|
|
||||||
This includes values such as:
|
This includes: output folder, end-card path, FFmpeg/preview-player paths, theme, encoder
|
||||||
|
selection, timing settings, and whether source videos are moved into `originals/` after a
|
||||||
- output folder
|
successful render.
|
||||||
- end-card path
|
|
||||||
- FFmpeg paths
|
|
||||||
- theme
|
|
||||||
- encoder selection
|
|
||||||
- timing settings
|
|
||||||
- whether source videos are moved into `originals` after a successful render
|
|
||||||
|
|
||||||
## Notes for Distribution
|
## Notes for Distribution
|
||||||
|
|
||||||
- If you distribute FFmpeg binaries with AmiReel, you are responsible for complying with the license terms of the FFmpeg build you use.
|
- If you distribute FFmpeg binaries with AmiReel, you are responsible for complying with the
|
||||||
- Keep any required notices, source offer, or attribution required by that FFmpeg distribution.
|
license terms of the FFmpeg build you use. Keep any required notices, source offer, or
|
||||||
- Windows Explorer may cache executable icons. If a freshly published build still shows an old icon, rename the file or refresh the icon cache before assuming the embed failed.
|
attribution required by that distribution.
|
||||||
|
- Windows Explorer may cache executable icons. If a freshly published build still shows an old
|
||||||
|
icon, rename the file or refresh the icon cache before assuming the embed failed.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### App falls back to CPU instead of NVENC
|
**App falls back to CPU instead of NVENC** — FFmpeg could not initialize `h264_nvenc`. AmiReel
|
||||||
|
continues automatically with CPU encoding.
|
||||||
|
|
||||||
This usually means FFmpeg could not initialize `h264_nvenc`. AmiReel will continue with CPU encoding automatically.
|
**FFmpeg tool error** — If the embedded FFmpeg is missing or broken, AmiReel tries configured
|
||||||
|
tool paths, then FFmpeg from `PATH`. Set the paths manually in **Settings** if needed.
|
||||||
|
|
||||||
### FFmpeg tool error
|
**Render failed popup** — Shows a short human-readable summary. Full technical details remain
|
||||||
|
available in the **FFmpeg log** panel.
|
||||||
If embedded FFmpeg is missing or broken, AmiReel will try:
|
|
||||||
|
|
||||||
1. configured tool paths
|
|
||||||
2. FFmpeg from `PATH`
|
|
||||||
|
|
||||||
If needed, set the paths manually in `Settings`.
|
|
||||||
|
|
||||||
### Render failed popup
|
|
||||||
|
|
||||||
The popup shows a short human-readable summary. Full technical details remain available in the `FFmpeg log` panel.
|
|
||||||
|
|
||||||
## Current Default Recommendation
|
|
||||||
|
|
||||||
Use the WinUI build for publishing and distribution unless you specifically need the WPF variant.
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using AmigaDB.VideoRenderer.Models;
|
using AmiReel.Models;
|
||||||
|
|
||||||
namespace AmigaDB.VideoRenderer.Services;
|
namespace AmiReel.Services;
|
||||||
|
|
||||||
public static class AppSettingsStore
|
public static class AppSettingsStore
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Runtime.InteropServices;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace AmigaDB.VideoRenderer.Services;
|
namespace AmiReel.Services;
|
||||||
|
|
||||||
internal sealed partial class FfmpegLibraryProbe : IDisposable
|
internal sealed partial class FfmpegLibraryProbe : IDisposable
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace AmigaDB.VideoRenderer.Services;
|
namespace AmiReel.Services;
|
||||||
|
|
||||||
internal sealed class MediaProbe
|
internal sealed class MediaProbe
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Text;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace AmigaDB.VideoRenderer.Services;
|
namespace AmiReel.Services;
|
||||||
|
|
||||||
public sealed partial class ProcessRunner
|
public sealed partial class ProcessRunner
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using AmigaDB.VideoRenderer.Models;
|
using AmiReel.Models;
|
||||||
|
|
||||||
namespace AmigaDB.VideoRenderer.Services;
|
namespace AmiReel.Services;
|
||||||
|
|
||||||
public sealed class RenderPipeline
|
public sealed class RenderPipeline
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using System.IO;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace AmigaDB.VideoRenderer.Services;
|
namespace AmiReel.Services;
|
||||||
|
|
||||||
public sealed record ToolPaths(string Ffmpeg, string Ffprobe);
|
public sealed record ToolPaths(string Ffmpeg, string Ffprobe);
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ public static class ToolExtractor
|
|||||||
private static async Task<string> ExtractOneAsync(string fileName, string destination, CancellationToken token)
|
private static async Task<string> ExtractOneAsync(string fileName, string destination, CancellationToken token)
|
||||||
{
|
{
|
||||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||||
string resourceName = $"AmigaDB.VideoRenderer.Tools.{fileName}";
|
string resourceName = $"AmiReel.Tools.{fileName}";
|
||||||
await using Stream source = assembly.GetManifestResourceStream(resourceName)
|
await using Stream source = assembly.GetManifestResourceStream(resourceName)
|
||||||
?? throw new InvalidOperationException(
|
?? throw new InvalidOperationException(
|
||||||
$"Embedded {fileName} was not found. Add it to ThirdParty and publish the application again.");
|
$"Embedded {fileName} was not found. Add it to ThirdParty and publish the application again.");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace AmigaDB.VideoRenderer.Services;
|
namespace AmiReel.Services;
|
||||||
|
|
||||||
public static class UserFacingErrors
|
public static class UserFacingErrors
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
<assemblyIdentity version="1.0.0.0" name="AmiReel.WinUI.app"/>
|
<assemblyIdentity version="1.0.0.0" name="AmiReel.app"/>
|
||||||
|
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
<application>
|
<application>
|
||||||
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 200 KiB |
@@ -14,9 +14,9 @@ Contents:
|
|||||||
Individual transparent PNG files:
|
Individual transparent PNG files:
|
||||||
16, 24, 32, 48, 64, 128, 256, 512 and 1024 px.
|
16, 24, 32, 48, 64, 128, 256, 512 and 1024 px.
|
||||||
|
|
||||||
Recommended WPF project setting:
|
Referenced from the project file as:
|
||||||
|
|
||||||
<ApplicationIcon>Assets\AmiReel.ico</ApplicationIcon>
|
<ApplicationIcon>branding\AmiReel.ico</ApplicationIcon>
|
||||||
|
|
||||||
Product: AmiReel — Amiga Video Renderer
|
Product: AmiReel — Amiga Video Renderer
|
||||||
Brand: AmigaDB
|
Brand: AmigaDB
|
||||||
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 330 KiB After Width: | Height: | Size: 330 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
@@ -1,8 +1,5 @@
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param()
|
||||||
[ValidateSet('WinUI', 'Wpf')]
|
|
||||||
[string]$Target = 'WinUI'
|
|
||||||
)
|
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
@@ -14,41 +11,21 @@ if (-not (Test-Path $ffmpeg) -or -not (Test-Path $ffprobe)) {
|
|||||||
throw 'Add ffmpeg.exe and ffprobe.exe to ThirdParty before publishing.'
|
throw 'Add ffmpeg.exe and ffprobe.exe to ThirdParty before publishing.'
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($Target) {
|
$projectPath = Join-Path $projectDir 'AmiReel.csproj'
|
||||||
'WinUI' {
|
$releaseDir = Join-Path $projectDir 'bin\Release\net10.0-windows10.0.26100.0\win-x64'
|
||||||
$projectPath = Join-Path $projectDir 'AmiReel.WinUI\AmiReel.WinUI.csproj'
|
$releaseExe = Join-Path $releaseDir 'AmiReel.exe'
|
||||||
$releaseDir = Join-Path $projectDir 'AmiReel.WinUI\bin\Release\net10.0-windows10.0.26100.0\win-x64'
|
$publishDir = Join-Path $releaseDir 'publish'
|
||||||
$releaseExe = Join-Path $releaseDir 'AmiReel.exe'
|
$publishExe = Join-Path $publishDir 'AmiReel.exe'
|
||||||
$publishDir = Join-Path $releaseDir 'publish'
|
$publishArguments = @(
|
||||||
$publishExe = Join-Path $publishDir 'AmiReel.exe'
|
'publish', $projectPath,
|
||||||
$publishArguments = @(
|
'-c', 'Release',
|
||||||
'publish', $projectPath,
|
'-r', 'win-x64',
|
||||||
'-c', 'Release',
|
'--self-contained', 'true',
|
||||||
'-r', 'win-x64',
|
'-p:WindowsPackageType=None',
|
||||||
'--self-contained', 'true',
|
'-p:PublishSingleFile=true',
|
||||||
'-p:WindowsPackageType=None',
|
'-p:IncludeNativeLibrariesForSelfExtract=true',
|
||||||
'-p:PublishSingleFile=true',
|
'-p:EnableCompressionInSingleFile=true'
|
||||||
'-p:IncludeNativeLibrariesForSelfExtract=true',
|
)
|
||||||
'-p:EnableCompressionInSingleFile=true'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
'Wpf' {
|
|
||||||
$projectPath = Join-Path $projectDir 'AmigaDB.VideoRenderer.csproj'
|
|
||||||
$releaseDir = Join-Path $projectDir 'bin\Release\net8.0-windows\win-x64'
|
|
||||||
$releaseExe = Join-Path $releaseDir 'AmiReel.exe'
|
|
||||||
$publishDir = Join-Path $releaseDir 'publish'
|
|
||||||
$publishExe = Join-Path $publishDir 'AmiReel.exe'
|
|
||||||
$publishArguments = @(
|
|
||||||
'publish', $projectPath,
|
|
||||||
'-c', 'Release',
|
|
||||||
'-r', 'win-x64',
|
|
||||||
'--self-contained', 'true',
|
|
||||||
'-p:PublishSingleFile=true',
|
|
||||||
'-p:IncludeNativeLibrariesForSelfExtract=true',
|
|
||||||
'-p:EnableCompressionInSingleFile=true'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Test-Path $releaseExe) -or (Test-Path $publishExe)) {
|
if ((Test-Path $releaseExe) -or (Test-Path $publishExe)) {
|
||||||
$runningReleaseInstances = Get-Process | Where-Object {
|
$runningReleaseInstances = Get-Process | Where-Object {
|
||||||
@@ -59,7 +36,7 @@ if ((Test-Path $releaseExe) -or (Test-Path $publishExe)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($runningReleaseInstances) {
|
if ($runningReleaseInstances) {
|
||||||
Write-Host "Stopping running $Target build before publish..." -ForegroundColor Yellow
|
Write-Host 'Stopping running AmiReel build before publish...' -ForegroundColor Yellow
|
||||||
$runningReleaseInstances | Stop-Process -Force
|
$runningReleaseInstances | Stop-Process -Force
|
||||||
Start-Sleep -Milliseconds 800
|
Start-Sleep -Milliseconds 800
|
||||||
}
|
}
|
||||||
@@ -71,6 +48,6 @@ if (Test-Path $publishDir) {
|
|||||||
|
|
||||||
& dotnet @publishArguments
|
& dotnet @publishArguments
|
||||||
|
|
||||||
Write-Host "Published $Target to $publishDir" -ForegroundColor Green
|
Write-Host "Published AmiReel to $publishDir" -ForegroundColor Green
|
||||||
Write-Host "Release folder: $publishDir" -ForegroundColor Cyan
|
Write-Host "Release folder: $publishDir" -ForegroundColor Cyan
|
||||||
Write-Host "Executable: $publishExe" -ForegroundColor Cyan
|
Write-Host "Executable: $publishExe" -ForegroundColor Cyan
|
||||||
|
|||||||