@@ -1,5 +1,13 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## v0.16.11
|
||||||
|
|
||||||
|
- 增加 shift 切换缩放倍数
|
||||||
|
- 改善后台性能
|
||||||
|
- 修复字体显示颜色问题
|
||||||
|
- 调整浏览目录参数保存至用户状态
|
||||||
|
- 调整浏览面板至最后
|
||||||
|
|
||||||
## v0.16.10
|
## v0.16.10
|
||||||
|
|
||||||
- 增加 Linux 平台 CLI 工具构建
|
- 增加 Linux 平台 CLI 工具构建
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ Mouse interactions in the preview panel:
|
|||||||
|
|
||||||
- **Left click**: select and drag models. Hold `Ctrl` for multi-selection (synchronized with the model list).
|
- **Left click**: select and drag models. Hold `Ctrl` for multi-selection (synchronized with the model list).
|
||||||
- **Right click**: drag the entire canvas.
|
- **Right click**: drag the entire canvas.
|
||||||
- **Mouse wheel**: zoom in/out. Hold `Ctrl` to scale selected models together.
|
- **Mouse wheel**: zoom in/out. Hold `Ctrl` to scale selected models together, use `Shift` to switch zoom factor.
|
||||||
- **Render selected only**: preview only the selected models, selection can only be changed via the left panel.
|
- **Render selected only**: preview only the selected models, selection can only be changed via the left panel.
|
||||||
|
|
||||||
Playback controls below the preview allow time adjustment, acting as a simple player.
|
Playback controls below the preview allow time adjustment, acting as a simple player.
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ https://github.com/user-attachments/assets/37b6b730-088a-4352-827a-c338127a16f0
|
|||||||
|
|
||||||
- 左键可以选择和拖拽模型, 按下 `Ctrl` 键可以实现多选, 与左侧列表选择是联动的.
|
- 左键可以选择和拖拽模型, 按下 `Ctrl` 键可以实现多选, 与左侧列表选择是联动的.
|
||||||
- 右键对整体画面进行拖动.
|
- 右键对整体画面进行拖动.
|
||||||
- 滚轮进行画面缩放, 按住 `Ctrl` 可以对选中的模型进行批量缩放.
|
- 滚轮进行画面缩放, 按住 `Ctrl` 可以对选中的模型进行批量缩放, `Shift` 可以切换缩放倍数.
|
||||||
- 仅渲染选中模式, 在该模式下, 预览画面仅包含被选中的模型, 并且只能通过左侧列表改变选中状态.
|
- 仅渲染选中模式, 在该模式下, 预览画面仅包含被选中的模型, 并且只能通过左侧列表改变选中状态.
|
||||||
|
|
||||||
预览画面下方按钮支持对画面时间进行调整, 可以当作一个简易的播放器.
|
预览画面下方按钮支持对画面时间进行调整, 可以当作一个简易的播放器.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
<Version>0.16.10</Version>
|
<Version>0.16.11</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ namespace SpineViewer
|
|||||||
public partial class App : Application
|
public partial class App : Application
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
public const bool IsDebug = true;
|
||||||
public const string AppName = "SpineViewer_D";
|
public const string AppName = "SpineViewer_D";
|
||||||
public const string ProgId = "SpineViewer_D.skel";
|
public const string ProgId = "SpineViewer_D.skel";
|
||||||
#else
|
#else
|
||||||
|
public const bool IsDebug = false;
|
||||||
public const string AppName = "SpineViewer";
|
public const string AppName = "SpineViewer";
|
||||||
public const string ProgId = "SpineViewer.skel";
|
public const string ProgId = "SpineViewer.skel";
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -33,6 +33,12 @@ namespace SpineViewer.Models
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 浏览页面状态
|
||||||
|
|
||||||
|
public string? ExploringDirectory { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region 预览画面状态
|
#region 预览画面状态
|
||||||
|
|
||||||
public uint ResolutionX { get; set; } = 1500;
|
public uint ResolutionX { get; set; } = 1500;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ namespace SpineViewer.Models
|
|||||||
{
|
{
|
||||||
public class WorkspaceModel
|
public class WorkspaceModel
|
||||||
{
|
{
|
||||||
public string? ExploringDirectory { get; set; }
|
|
||||||
public RendererWorkspaceConfigModel RendererConfig { get; set; } = new();
|
public RendererWorkspaceConfigModel RendererConfig { get; set; } = new();
|
||||||
public List<SpineObjectWorkspaceConfigModel> LoadedSpineObjects { get; set; } = [];
|
public List<SpineObjectWorkspaceConfigModel> LoadedSpineObjects { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
<Version>0.16.10</Version>
|
<Version>0.16.11</Version>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -27,7 +27,24 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
_preferenceViewModel = new(this);
|
_preferenceViewModel = new(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Title => $"SpineViewer - v{App.Version}";
|
public bool IsDebug => App.IsDebug;
|
||||||
|
|
||||||
|
public string Title => $"{App.AppName} - v{App.Version}";
|
||||||
|
|
||||||
|
public Visibility Visibility
|
||||||
|
{
|
||||||
|
get => _visibility;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref _visibility, value))
|
||||||
|
{
|
||||||
|
OnPropertyChanged(nameof(IsVisible));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Visibility _visibility = Visibility.Visible;
|
||||||
|
|
||||||
|
public bool IsVisible => _visibility == Visibility.Visible;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 指示是否通过托盘图标进行退出
|
/// 指示是否通过托盘图标进行退出
|
||||||
@@ -164,14 +181,12 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
{
|
{
|
||||||
return new()
|
return new()
|
||||||
{
|
{
|
||||||
ExploringDirectory = _explorerListViewModel.CurrentDirectory,
|
|
||||||
RendererConfig = _sfmlRendererViewModel.WorkspaceConfig,
|
RendererConfig = _sfmlRendererViewModel.WorkspaceConfig,
|
||||||
LoadedSpineObjects = _spineObjectListViewModel.LoadedSpineObjects
|
LoadedSpineObjects = _spineObjectListViewModel.LoadedSpineObjects
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_explorerListViewModel.CurrentDirectory = value.ExploringDirectory;
|
|
||||||
_sfmlRendererViewModel.WorkspaceConfig = value.RendererConfig;
|
_sfmlRendererViewModel.WorkspaceConfig = value.RendererConfig;
|
||||||
_spineObjectListViewModel.LoadedSpineObjects = value.LoadedSpineObjects;
|
_spineObjectListViewModel.LoadedSpineObjects = value.LoadedSpineObjects;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
public uint MaxFps
|
public uint MaxFps
|
||||||
{
|
{
|
||||||
get => _renderer.MaxFps;
|
get => _renderer.MaxFps;
|
||||||
set => SetProperty(_renderer.MaxFps, value, v => _renderer.MaxFps = value);
|
set => SetProperty(_renderer.MaxFps, value, v => _renderer.MaxFps = _wallpaperRenderer.MaxFps = value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float Speed
|
public float Speed
|
||||||
@@ -320,7 +320,8 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
|
|
||||||
public void CanvasMouseWheelScrolled(object? s, SFML.Window.MouseWheelScrollEventArgs e)
|
public void CanvasMouseWheelScrolled(object? s, SFML.Window.MouseWheelScrollEventArgs e)
|
||||||
{
|
{
|
||||||
var factor = e.Delta > 0 ? 1.1f : 0.9f;
|
float delta = ((Keyboard.Modifiers & ModifierKeys.Shift) == 0) ? 0.1f : 0.01f;
|
||||||
|
var factor = e.Delta > 0 ? (1f + delta) : (1f - delta);
|
||||||
if ((Keyboard.Modifiers & ModifierKeys.Control) == 0)
|
if ((Keyboard.Modifiers & ModifierKeys.Control) == 0)
|
||||||
{
|
{
|
||||||
Zoom = Math.Clamp(Zoom * factor, 0.001f, 1000f); // 滚轮缩放限制一下缩放范围
|
Zoom = Math.Clamp(Zoom * factor, 0.001f, 1000f); // 滚轮缩放限制一下缩放范围
|
||||||
@@ -484,21 +485,17 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
_forwardDelta = 0;
|
_forwardDelta = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
using var v = _renderer.GetView();
|
using var view = _renderer.GetView();
|
||||||
_renderer.Clear(_backgroundColor);
|
_wallpaperRenderer.SetView(view);
|
||||||
|
|
||||||
if (_wallpaperView)
|
if (_vmMain.IsVisible) _renderer.Clear(_backgroundColor);
|
||||||
{
|
if (_wallpaperView) _wallpaperRenderer.Clear(_backgroundColor);
|
||||||
_wallpaperRenderer.SetView(v);
|
|
||||||
_wallpaperRenderer.Clear(_backgroundColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 渲染背景
|
// 渲染背景
|
||||||
lock (_bgLock)
|
lock (_bgLock)
|
||||||
{
|
{
|
||||||
if (_backgroundImageSprite is not null)
|
if (_backgroundImageSprite is not null)
|
||||||
{
|
{
|
||||||
using var view = _renderer.GetView();
|
|
||||||
var bg = _backgroundImageSprite;
|
var bg = _backgroundImageSprite;
|
||||||
var viewSize = view.Size;
|
var viewSize = view.Size;
|
||||||
var bgSize = bg.Texture.Size;
|
var bgSize = bg.Texture.Size;
|
||||||
@@ -521,16 +518,13 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
bg.Scale = new(signX * scaleX, signY * scaleY);
|
bg.Scale = new(signX * scaleX, signY * scaleY);
|
||||||
bg.Position = view.Center;
|
bg.Position = view.Center;
|
||||||
bg.Rotation = view.Rotation;
|
bg.Rotation = view.Rotation;
|
||||||
_renderer.Draw(bg);
|
|
||||||
|
|
||||||
if (_wallpaperView)
|
if (_vmMain.IsVisible) _renderer.Draw(bg);
|
||||||
{
|
if (_wallpaperView) _wallpaperRenderer.Draw(bg);
|
||||||
_wallpaperRenderer.Draw(bg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_showAxis)
|
if (_showAxis && _vmMain.IsVisible)
|
||||||
{
|
{
|
||||||
// 画一个很长的坐标轴, 用 1e9 比较合适
|
// 画一个很长的坐标轴, 用 1e9 比较合适
|
||||||
_axisVertices[0] = new(new(-1e9f, 0), _axisColor);
|
_axisVertices[0] = new(new(-1e9f, 0), _axisColor);
|
||||||
@@ -551,35 +545,30 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
sp.Update(0); // 避免物理效果出现问题
|
sp.Update(0); // 避免物理效果出现问题
|
||||||
sp.Update(delta * _speed);
|
sp.Update(delta * _speed);
|
||||||
|
|
||||||
// 为选中对象绘制一个半透明背景
|
if (_vmMain.IsVisible)
|
||||||
if (sp.IsSelected)
|
|
||||||
{
|
{
|
||||||
var rc = sp.GetCurrentBounds().ToFloatRect();
|
// 为选中对象绘制一个半透明背景
|
||||||
_selectedBackgroundVertices[0] = new(new(rc.Left, rc.Top), _selectedBackgroundColor);
|
if (sp.IsSelected)
|
||||||
_selectedBackgroundVertices[1] = new(new(rc.Left + rc.Width, rc.Top), _selectedBackgroundColor);
|
{
|
||||||
_selectedBackgroundVertices[2] = new(new(rc.Left + rc.Width, rc.Top + rc.Height), _selectedBackgroundColor);
|
var rc = sp.GetCurrentBounds().ToFloatRect();
|
||||||
_selectedBackgroundVertices[3] = new(new(rc.Left, rc.Top + rc.Height), _selectedBackgroundColor);
|
_selectedBackgroundVertices[0] = new(new(rc.Left, rc.Top), _selectedBackgroundColor);
|
||||||
_renderer.Draw(_selectedBackgroundVertices);
|
_selectedBackgroundVertices[1] = new(new(rc.Left + rc.Width, rc.Top), _selectedBackgroundColor);
|
||||||
}
|
_selectedBackgroundVertices[2] = new(new(rc.Left + rc.Width, rc.Top + rc.Height), _selectedBackgroundColor);
|
||||||
|
_selectedBackgroundVertices[3] = new(new(rc.Left, rc.Top + rc.Height), _selectedBackgroundColor);
|
||||||
|
_renderer.Draw(_selectedBackgroundVertices);
|
||||||
|
}
|
||||||
|
|
||||||
// 仅在预览画面临时启用调试模式
|
// 仅在预览画面临时启用调试模式
|
||||||
sp.EnableDebug = true;
|
sp.EnableDebug = true;
|
||||||
_renderer.Draw(sp);
|
_renderer.Draw(sp);
|
||||||
sp.EnableDebug = false;
|
sp.EnableDebug = false;
|
||||||
|
|
||||||
if (_wallpaperView)
|
|
||||||
{
|
|
||||||
_wallpaperRenderer.Draw(sp);
|
|
||||||
}
|
}
|
||||||
|
if (_wallpaperView) _wallpaperRenderer.Draw(sp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderer.Display();
|
if (_vmMain.IsVisible) _renderer.Display();
|
||||||
|
if (_wallpaperView) _wallpaperRenderer.Display();
|
||||||
if (_wallpaperView)
|
|
||||||
{
|
|
||||||
_wallpaperRenderer.Display();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
Height="720"
|
Height="720"
|
||||||
Background="{DynamicResource RegionBrush}"
|
Background="{DynamicResource RegionBrush}"
|
||||||
WindowStartupLocation="CenterScreen"
|
WindowStartupLocation="CenterScreen"
|
||||||
|
Visibility="{Binding Visibility, Mode=OneWayToSource}"
|
||||||
PreviewKeyDown="MainWindow_PreviewKeyDown"
|
PreviewKeyDown="MainWindow_PreviewKeyDown"
|
||||||
LocationChanged="MainWindow_LocationChanged"
|
LocationChanged="MainWindow_LocationChanged"
|
||||||
SizeChanged="MainWindow_SizeChanged">
|
SizeChanged="MainWindow_SizeChanged">
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
MouseDoubleClick="_notifyIcon_MouseDoubleClick">
|
MouseDoubleClick="_notifyIcon_MouseDoubleClick">
|
||||||
<hc:NotifyIcon.ContextMenu>
|
<hc:NotifyIcon.ContextMenu>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
|
<MenuItem Header="{DynamicResource Str_Debug}" Click="DebugMenuItem_Click" Visibility="{Binding IsDebug, Mode=OneWay, Converter={StaticResource Boolean2VisibilityConverter}}"/>
|
||||||
<MenuItem Header="{DynamicResource Str_WallpaperView}" Command="{Binding Cmd_SwitchWallpaperView}" IsChecked="{Binding PreferenceViewModel.WallpaperView}"/>
|
<MenuItem Header="{DynamicResource Str_WallpaperView}" Command="{Binding Cmd_SwitchWallpaperView}" IsChecked="{Binding PreferenceViewModel.WallpaperView}"/>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
<MenuItem Header="{DynamicResource Str_Exit}" Command="{Binding Cmd_ExitFromTray}"/>
|
<MenuItem Header="{DynamicResource Str_Exit}" Command="{Binding Cmd_ExitFromTray}"/>
|
||||||
@@ -63,7 +65,7 @@
|
|||||||
<MenuItem Header="{DynamicResource Str_Diagnostics}" Command="{Binding Cmd_ShowDiagnosticsDialog}"/>
|
<MenuItem Header="{DynamicResource Str_Diagnostics}" Command="{Binding Cmd_ShowDiagnosticsDialog}"/>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
<MenuItem Header="{DynamicResource Str_Abount}" Command="{Binding Cmd_ShowAboutDialog}"/>
|
<MenuItem Header="{DynamicResource Str_Abount}" Command="{Binding Cmd_ShowAboutDialog}"/>
|
||||||
<MenuItem Header="{DynamicResource Str_Debug}" Click="DebugMenuItem_Click"/>
|
<MenuItem Header="{DynamicResource Str_Debug}" Click="DebugMenuItem_Click" Visibility="{Binding IsDebug, Mode=OneWay, Converter={StaticResource Boolean2VisibilityConverter}}"/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<!--<MenuItem Header="{DynamicResource Str_Experiment}"/>-->
|
<!--<MenuItem Header="{DynamicResource Str_Experiment}"/>-->
|
||||||
</Menu>
|
</Menu>
|
||||||
@@ -682,125 +684,6 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
||||||
<!-- 浏览页 -->
|
|
||||||
<TabItem DataContext="{Binding ExplorerListViewModel}">
|
|
||||||
<TabItem.Header>
|
|
||||||
<Border Style="{StaticResource MyTabItemHeaderContainerStyle}"
|
|
||||||
MouseLeftButtonDown="MainTabControlHeader_MouseLeftButtonDown">
|
|
||||||
<Viewbox Width="24" Height="24" ToolTip="{DynamicResource Str_Explorer}">
|
|
||||||
<Path Data="{StaticResource Geo_Image}" Style="{StaticResource MyTabItemHeaderPathStyle}"/>
|
|
||||||
</Viewbox>
|
|
||||||
</Border>
|
|
||||||
</TabItem.Header>
|
|
||||||
<Grid x:Name="_explorerGrid">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<DockPanel>
|
|
||||||
<Grid DockPanel.Dock="Top">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<hc:TextBox hc:InfoElement.Placeholder="{DynamicResource Str_Filter}"
|
|
||||||
Text="{Binding FilterString, UpdateSourceTrigger=PropertyChanged}"/>
|
|
||||||
<Button Grid.Column="1"
|
|
||||||
hc:IconElement.Geometry="{StaticResource Geo_Folder}"
|
|
||||||
Command="{Binding Cmd_ChangeCurrentDirectory}"
|
|
||||||
ToolTip="{DynamicResource Str_ChangeCurrentDirectoryTooltip}"/>
|
|
||||||
<Button Grid.Column="2"
|
|
||||||
hc:IconElement.Geometry="{StaticResource Geo_ArrowRotateRight}"
|
|
||||||
Command="{Binding Cmd_RefreshItems}"
|
|
||||||
ToolTip="{DynamicResource Str_RefreshItemsTooltip}"/>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<StatusBar DockPanel.Dock="Bottom">
|
|
||||||
<TextBlock>
|
|
||||||
<TextBlock.Text>
|
|
||||||
<MultiBinding Converter="{StaticResource StrFmtCvter}" ConverterParameter="Str_ListViewStatusBar">
|
|
||||||
<Binding Path="Items.Count" ElementName="_spineFilesListBox"/>
|
|
||||||
<Binding Path="SelectedItems.Count" ElementName="_spineFilesListBox"/>
|
|
||||||
</MultiBinding>
|
|
||||||
</TextBlock.Text>
|
|
||||||
</TextBlock>
|
|
||||||
</StatusBar>
|
|
||||||
|
|
||||||
<ListBox x:Name="_spineFilesListBox"
|
|
||||||
VirtualizingPanel.IsVirtualizing="True"
|
|
||||||
ItemsSource="{Binding ShownItems}"
|
|
||||||
DisplayMemberPath="FileName"
|
|
||||||
MouseLeftButtonDown="SpineFilesListBox_MouseLeftButtonDown">
|
|
||||||
<i:Interaction.Triggers>
|
|
||||||
<i:EventTrigger EventName="SelectionChanged">
|
|
||||||
<i:InvokeCommandAction Command="{Binding Cmd_SelectionChanged}"
|
|
||||||
CommandParameter="{Binding SelectedItems, ElementName=_spineFilesListBox}"/>
|
|
||||||
</i:EventTrigger>
|
|
||||||
</i:Interaction.Triggers>
|
|
||||||
|
|
||||||
<ListBox.ContextMenu>
|
|
||||||
<ContextMenu>
|
|
||||||
<MenuItem Header="{DynamicResource Str_AddSelectedItems}"
|
|
||||||
Command="{Binding Cmd_AddSelectedItems}"
|
|
||||||
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
|
|
||||||
<Separator/>
|
|
||||||
<MenuItem Header="{DynamicResource Str_GeneratePreviewForSelected}"
|
|
||||||
Command="{Binding Cmd_GeneratePreviews}"
|
|
||||||
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
|
|
||||||
<MenuItem Header="{DynamicResource Str_DeletePreviewsForSelected}"
|
|
||||||
Command="{Binding Cmd_DeletePreviews}"
|
|
||||||
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
|
|
||||||
</ContextMenu>
|
|
||||||
</ListBox.ContextMenu>
|
|
||||||
</ListBox>
|
|
||||||
</DockPanel>
|
|
||||||
|
|
||||||
<GridSplitter Grid.Row="1" ResizeDirection="Rows"/>
|
|
||||||
|
|
||||||
<Grid Grid.Row="2" DataContext="{Binding SelectedItem}">
|
|
||||||
<Grid.Resources>
|
|
||||||
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource LabelDefault}">
|
|
||||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Right"/>
|
|
||||||
</Style>
|
|
||||||
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxBaseStyle}">
|
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Right"/>
|
|
||||||
</Style>
|
|
||||||
</Grid.Resources>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<!-- 文件目录 -->
|
|
||||||
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_FileDirectory}"/>
|
|
||||||
<TextBox Grid.Row="0" Grid.Column="1"
|
|
||||||
Text="{Binding FileDirectory, Mode=OneWay}"
|
|
||||||
IsReadOnly="True"
|
|
||||||
ToolTip="{Binding Text, RelativeSource={RelativeSource Mode=Self}}"/>
|
|
||||||
|
|
||||||
<!-- 文件名 -->
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_FileName}"/>
|
|
||||||
<TextBox Grid.Row="1" Grid.Column="1"
|
|
||||||
Text="{Binding FileName, Mode=OneWay}"
|
|
||||||
IsReadOnly="True"/>
|
|
||||||
|
|
||||||
<!-- 预览图 -->
|
|
||||||
<Border Grid.Row="2" Grid.ColumnSpan="2" Background="{DynamicResource DarkDefaultBrush}">
|
|
||||||
<Image Source="{Binding PreviewImage, Mode=OneWay}" Stretch="Uniform"/>
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<!-- 画面参数页 -->
|
<!-- 画面参数页 -->
|
||||||
<TabItem DataContext="{Binding SFMLRendererViewModel}">
|
<TabItem DataContext="{Binding SFMLRendererViewModel}">
|
||||||
<TabItem.Header>
|
<TabItem.Header>
|
||||||
@@ -991,6 +874,126 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
||||||
|
<!-- 浏览页 -->
|
||||||
|
<TabItem DataContext="{Binding ExplorerListViewModel}">
|
||||||
|
<TabItem.Header>
|
||||||
|
<Border Style="{StaticResource MyTabItemHeaderContainerStyle}"
|
||||||
|
MouseLeftButtonDown="MainTabControlHeader_MouseLeftButtonDown">
|
||||||
|
<Viewbox Width="24" Height="24" ToolTip="{DynamicResource Str_Explorer}">
|
||||||
|
<Path Data="{StaticResource Geo_Image}" Style="{StaticResource MyTabItemHeaderPathStyle}"/>
|
||||||
|
</Viewbox>
|
||||||
|
</Border>
|
||||||
|
</TabItem.Header>
|
||||||
|
<Grid x:Name="_explorerGrid">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<DockPanel>
|
||||||
|
<Grid DockPanel.Dock="Top">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<hc:TextBox hc:InfoElement.Placeholder="{DynamicResource Str_Filter}"
|
||||||
|
Text="{Binding FilterString, UpdateSourceTrigger=PropertyChanged}"/>
|
||||||
|
<Button Grid.Column="1"
|
||||||
|
hc:IconElement.Geometry="{StaticResource Geo_Folder}"
|
||||||
|
Command="{Binding Cmd_ChangeCurrentDirectory}"
|
||||||
|
ToolTip="{DynamicResource Str_ChangeCurrentDirectoryTooltip}"/>
|
||||||
|
<Button Grid.Column="2"
|
||||||
|
hc:IconElement.Geometry="{StaticResource Geo_ArrowRotateRight}"
|
||||||
|
Command="{Binding Cmd_RefreshItems}"
|
||||||
|
ToolTip="{DynamicResource Str_RefreshItemsTooltip}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<StatusBar DockPanel.Dock="Bottom">
|
||||||
|
<TextBlock Foreground="{DynamicResource PrimaryTextBrush}">
|
||||||
|
<TextBlock.Text>
|
||||||
|
<MultiBinding Converter="{StaticResource StrFmtCvter}" ConverterParameter="Str_ListViewStatusBar">
|
||||||
|
<Binding Path="Items.Count" ElementName="_spineFilesListBox"/>
|
||||||
|
<Binding Path="SelectedItems.Count" ElementName="_spineFilesListBox"/>
|
||||||
|
</MultiBinding>
|
||||||
|
</TextBlock.Text>
|
||||||
|
</TextBlock>
|
||||||
|
</StatusBar>
|
||||||
|
|
||||||
|
<ListBox x:Name="_spineFilesListBox"
|
||||||
|
VirtualizingPanel.IsVirtualizing="True"
|
||||||
|
ItemsSource="{Binding ShownItems}"
|
||||||
|
DisplayMemberPath="FileName"
|
||||||
|
MouseLeftButtonDown="SpineFilesListBox_MouseLeftButtonDown">
|
||||||
|
<i:Interaction.Triggers>
|
||||||
|
<i:EventTrigger EventName="SelectionChanged">
|
||||||
|
<i:InvokeCommandAction Command="{Binding Cmd_SelectionChanged}"
|
||||||
|
CommandParameter="{Binding SelectedItems, ElementName=_spineFilesListBox}"/>
|
||||||
|
</i:EventTrigger>
|
||||||
|
</i:Interaction.Triggers>
|
||||||
|
|
||||||
|
<ListBox.ContextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<MenuItem Header="{DynamicResource Str_AddSelectedItems}"
|
||||||
|
Command="{Binding Cmd_AddSelectedItems}"
|
||||||
|
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
|
||||||
|
<Separator/>
|
||||||
|
<MenuItem Header="{DynamicResource Str_GeneratePreviewForSelected}"
|
||||||
|
Command="{Binding Cmd_GeneratePreviews}"
|
||||||
|
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
|
||||||
|
<MenuItem Header="{DynamicResource Str_DeletePreviewsForSelected}"
|
||||||
|
Command="{Binding Cmd_DeletePreviews}"
|
||||||
|
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
|
||||||
|
</ContextMenu>
|
||||||
|
</ListBox.ContextMenu>
|
||||||
|
</ListBox>
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<GridSplitter Grid.Row="1" ResizeDirection="Rows"/>
|
||||||
|
|
||||||
|
<Grid Grid.Row="2" DataContext="{Binding SelectedItem}">
|
||||||
|
<Grid.Resources>
|
||||||
|
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource LabelDefault}">
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Right"/>
|
||||||
|
</Style>
|
||||||
|
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxBaseStyle}">
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Right"/>
|
||||||
|
</Style>
|
||||||
|
</Grid.Resources>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- 文件目录 -->
|
||||||
|
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_FileDirectory}"/>
|
||||||
|
<TextBox Grid.Row="0" Grid.Column="1"
|
||||||
|
Text="{Binding FileDirectory, Mode=OneWay}"
|
||||||
|
IsReadOnly="True"
|
||||||
|
ToolTip="{Binding Text, RelativeSource={RelativeSource Mode=Self}}"/>
|
||||||
|
|
||||||
|
<!-- 文件名 -->
|
||||||
|
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_FileName}"/>
|
||||||
|
<TextBox Grid.Row="1" Grid.Column="1"
|
||||||
|
Text="{Binding FileName, Mode=OneWay}"
|
||||||
|
IsReadOnly="True"/>
|
||||||
|
|
||||||
|
<!-- 预览图 -->
|
||||||
|
<Border Grid.Row="2" Grid.ColumnSpan="2" Background="{DynamicResource DarkDefaultBrush}">
|
||||||
|
<Image Source="{Binding PreviewImage, Mode=OneWay}" Stretch="Uniform"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
</TabControl>
|
</TabControl>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ public partial class MainWindow : Window
|
|||||||
_userStateWatchers.Add(PropertyWatcher.Watch(_rightPanelGrid.RowDefinitions[0], RowDefinition.HeightProperty, DelayedSaveUserState));
|
_userStateWatchers.Add(PropertyWatcher.Watch(_rightPanelGrid.RowDefinitions[0], RowDefinition.HeightProperty, DelayedSaveUserState));
|
||||||
_userStateWatchers.Add(PropertyWatcher.Watch(_rightPanelGrid.RowDefinitions[2], RowDefinition.HeightProperty, DelayedSaveUserState));
|
_userStateWatchers.Add(PropertyWatcher.Watch(_rightPanelGrid.RowDefinitions[2], RowDefinition.HeightProperty, DelayedSaveUserState));
|
||||||
|
|
||||||
|
_vm.ExplorerListViewModel.PropertyChanged += ExplorerListUserStateChanged;
|
||||||
_vm.SFMLRendererViewModel.PropertyChanged += SFMLRendererUserStateChanged;
|
_vm.SFMLRendererViewModel.PropertyChanged += SFMLRendererUserStateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,6 +235,7 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
// 撤除所有状态监听器
|
// 撤除所有状态监听器
|
||||||
_vm.SFMLRendererViewModel.PropertyChanged -= SFMLRendererUserStateChanged;
|
_vm.SFMLRendererViewModel.PropertyChanged -= SFMLRendererUserStateChanged;
|
||||||
|
_vm.ExplorerListViewModel.PropertyChanged -= ExplorerListUserStateChanged;
|
||||||
foreach (var w in _userStateWatchers) w.Dispose();
|
foreach (var w in _userStateWatchers) w.Dispose();
|
||||||
_userStateWatchers.Clear();
|
_userStateWatchers.Clear();
|
||||||
|
|
||||||
@@ -284,6 +286,8 @@ public partial class MainWindow : Window
|
|||||||
_rightPanelGrid.RowDefinitions[0].Height = new(m.RightPanelGridRow0Height, GridUnitType.Star);
|
_rightPanelGrid.RowDefinitions[0].Height = new(m.RightPanelGridRow0Height, GridUnitType.Star);
|
||||||
_rightPanelGrid.RowDefinitions[2].Height = new(m.RightPanelGridRow2Height, GridUnitType.Star);
|
_rightPanelGrid.RowDefinitions[2].Height = new(m.RightPanelGridRow2Height, GridUnitType.Star);
|
||||||
|
|
||||||
|
_vm.ExplorerListViewModel.CurrentDirectory = m.ExploringDirectory;
|
||||||
|
|
||||||
_vm.SFMLRendererViewModel.SetResolution(m.ResolutionX, m.ResolutionY);
|
_vm.SFMLRendererViewModel.SetResolution(m.ResolutionX, m.ResolutionY);
|
||||||
_vm.SFMLRendererViewModel.MaxFps = m.MaxFps;
|
_vm.SFMLRendererViewModel.MaxFps = m.MaxFps;
|
||||||
_vm.SFMLRendererViewModel.Speed = m.Speed;
|
_vm.SFMLRendererViewModel.Speed = m.Speed;
|
||||||
@@ -317,6 +321,8 @@ public partial class MainWindow : Window
|
|||||||
RightPanelGridRow0Height = _rightPanelGrid.RowDefinitions[0].Height.Value,
|
RightPanelGridRow0Height = _rightPanelGrid.RowDefinitions[0].Height.Value,
|
||||||
RightPanelGridRow2Height = _rightPanelGrid.RowDefinitions[2].Height.Value,
|
RightPanelGridRow2Height = _rightPanelGrid.RowDefinitions[2].Height.Value,
|
||||||
|
|
||||||
|
ExploringDirectory = _vm.ExplorerListViewModel.CurrentDirectory,
|
||||||
|
|
||||||
ResolutionX = _vm.SFMLRendererViewModel.ResolutionX,
|
ResolutionX = _vm.SFMLRendererViewModel.ResolutionX,
|
||||||
ResolutionY = _vm.SFMLRendererViewModel.ResolutionY,
|
ResolutionY = _vm.SFMLRendererViewModel.ResolutionY,
|
||||||
MaxFps = _vm.SFMLRendererViewModel.MaxFps,
|
MaxFps = _vm.SFMLRendererViewModel.MaxFps,
|
||||||
@@ -356,6 +362,18 @@ public partial class MainWindow : Window
|
|||||||
_saveUserStateTimer.Start();
|
_saveUserStateTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ExplorerListUserStateChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
switch (e.PropertyName)
|
||||||
|
{
|
||||||
|
case nameof(ExplorerListViewModel.CurrentDirectory):
|
||||||
|
DelayedSaveUserState();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SFMLRendererUserStateChanged(object? sender, PropertyChangedEventArgs e)
|
private void SFMLRendererUserStateChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
switch (e.PropertyName)
|
switch (e.PropertyName)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
<Version>0.16.10</Version>
|
<Version>0.16.11</Version>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user