增加背景图案选项
This commit is contained in:
@@ -33,6 +33,8 @@ namespace SpineViewer.Models
|
||||
public float Speed { get; set; } = 1f;
|
||||
public bool ShowAxis { get; set; } = true;
|
||||
public Color BackgroundColor { get; set; } = Color.FromRgb(105, 105, 105);
|
||||
public string BackgroundImagePath { get; set; }
|
||||
public Stretch BackgroundImageMode { get; set; } = Stretch.Uniform;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -121,7 +121,8 @@
|
||||
<s:String x:Key="Str_RenderSelectedOnly">Render Selected Only</s:String>
|
||||
<s:String x:Key="Str_ShowAxis">Show Axis</s:String>
|
||||
<s:String x:Key="Str_BackgroundColor">Background Color</s:String>
|
||||
<s:String x:Key="Str_BackgroundImage">Background Image</s:String>
|
||||
<s:String x:Key="Str_BackgroundImagePath">Background Image Path</s:String>
|
||||
<s:String x:Key="Str_BackgroundImageMode">Background Image Mode</s:String>
|
||||
|
||||
<!-- 渲染画面按钮组 -->
|
||||
<s:String x:Key="Str_StopTooltip">Stop</s:String>
|
||||
|
||||
@@ -121,7 +121,8 @@
|
||||
<s:String x:Key="Str_RenderSelectedOnly">選択のみレンダリング</s:String>
|
||||
<s:String x:Key="Str_ShowAxis">座標軸を表示</s:String>
|
||||
<s:String x:Key="Str_BackgroundColor">背景色</s:String>
|
||||
<s:String x:Key="Str_BackgroundImage">背景画像</s:String>
|
||||
<s:String x:Key="Str_BackgroundImagePath">背景画像のパス</s:String>
|
||||
<s:String x:Key="Str_BackgroundImageMode">背景画像のモード</s:String>
|
||||
|
||||
<!-- 渲染画面按钮组 -->
|
||||
<s:String x:Key="Str_StopTooltip">停止</s:String>
|
||||
|
||||
@@ -121,7 +121,8 @@
|
||||
<s:String x:Key="Str_RenderSelectedOnly">仅渲染选中</s:String>
|
||||
<s:String x:Key="Str_ShowAxis">显示坐标轴</s:String>
|
||||
<s:String x:Key="Str_BackgroundColor">背景颜色</s:String>
|
||||
<s:String x:Key="Str_BackgroundImage">背景图片</s:String>
|
||||
<s:String x:Key="Str_BackgroundImagePath">背景图片路径</s:String>
|
||||
<s:String x:Key="Str_BackgroundImageMode">背景图片模式</s:String>
|
||||
|
||||
<!-- 渲染画面按钮组 -->
|
||||
<s:String x:Key="Str_StopTooltip">停止</s:String>
|
||||
|
||||
@@ -90,6 +90,22 @@ namespace SpineViewer.Services
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ShowOpenSFMLImageDialog(out string? fileName, string initialDirectory = "")
|
||||
{
|
||||
var dialog = new OpenFileDialog()
|
||||
{
|
||||
InitialDirectory = initialDirectory,
|
||||
Filter = "SFML Image|*.png;*.jpg;*.jpeg;*.bmp;*.tga|All|*.*"
|
||||
};
|
||||
if (dialog.ShowDialog() is true)
|
||||
{
|
||||
fileName = dialog.FileName;
|
||||
return true;
|
||||
}
|
||||
fileName = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ShowOpenJsonDialog(out string? fileName, string initialDirectory = "")
|
||||
{
|
||||
var dialog = new OpenFileDialog()
|
||||
|
||||
@@ -10,8 +10,10 @@ using SpineViewer.Services;
|
||||
using SpineViewer.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
@@ -23,6 +25,8 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
{
|
||||
public class SFMLRendererViewModel : ObservableObject
|
||||
{
|
||||
public ImmutableArray<Stretch> StretchOptions { get; } = Enum.GetValues<Stretch>().ToImmutableArray();
|
||||
|
||||
/// <summary>
|
||||
/// 日志器
|
||||
/// </summary>
|
||||
@@ -69,6 +73,13 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
private float _forwardDelta = 0;
|
||||
private readonly object _forwardDeltaLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// 背景图片
|
||||
/// </summary>
|
||||
private SFML.Graphics.Sprite? _backgroundImageSprite; // XXX: 暂时未使用 Dispose 释放
|
||||
private SFML.Graphics.Texture? _backgroundImageTexture; // XXX: 暂时未使用 Dispose 释放
|
||||
private readonly object _bgLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// 临时变量, 记录拖放世界源点
|
||||
/// </summary>
|
||||
@@ -169,6 +180,62 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
}
|
||||
private SFML.Graphics.Color _backgroundColor = new(105, 105, 105);
|
||||
|
||||
public string BackgroundImagePath
|
||||
{
|
||||
get => _backgroundImagePath;
|
||||
set => SetProperty(_backgroundImagePath, value, v =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(v))
|
||||
{
|
||||
lock (_bgLock)
|
||||
{
|
||||
_backgroundImageSprite?.Dispose();
|
||||
_backgroundImageTexture?.Dispose();
|
||||
_backgroundImageTexture = null;
|
||||
_backgroundImageSprite = null;
|
||||
}
|
||||
_backgroundImagePath = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!File.Exists(v))
|
||||
{
|
||||
_logger.Warn("Omit non-existed background image path, {0}", v);
|
||||
return;
|
||||
}
|
||||
SFML.Graphics.Texture tex = null;
|
||||
SFML.Graphics.Sprite sprite = null;
|
||||
try
|
||||
{
|
||||
tex = new(v);
|
||||
sprite = new(tex) { Origin = new(tex.Size.X / 2f, tex.Size.Y / 2f) };
|
||||
lock (_bgLock)
|
||||
{
|
||||
_backgroundImageSprite?.Dispose();
|
||||
_backgroundImageTexture?.Dispose();
|
||||
_backgroundImageTexture = tex;
|
||||
_backgroundImageSprite = sprite;
|
||||
}
|
||||
_backgroundImagePath = v;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
sprite?.Dispose();
|
||||
tex?.Dispose();
|
||||
_logger.Error("Failed to load background image from path: {0}, {1}", v, ex.Message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
private string _backgroundImagePath;
|
||||
|
||||
public Stretch BackgroundImageMode
|
||||
{
|
||||
get => _backgroundImageMode;
|
||||
set => SetProperty(ref _backgroundImageMode, value);
|
||||
}
|
||||
private Stretch _backgroundImageMode = Stretch.Uniform;
|
||||
|
||||
public bool RenderSelectedOnly
|
||||
{
|
||||
get => _renderSelectedOnly;
|
||||
@@ -189,6 +256,14 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
}
|
||||
private bool _isUpdating = true;
|
||||
|
||||
public RelayCommand Cmd_SelectBackgroundImage => _cmd_SelectBackgroundImage ??= new(() =>
|
||||
{
|
||||
if (!DialogService.ShowOpenSFMLImageDialog(out var fileName))
|
||||
return;
|
||||
BackgroundImagePath = fileName;
|
||||
});
|
||||
private RelayCommand? _cmd_SelectBackgroundImage;
|
||||
|
||||
public RelayCommand Cmd_Stop => _cmd_Stop ??= new(() =>
|
||||
{
|
||||
IsUpdating = false;
|
||||
@@ -386,6 +461,38 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
|
||||
_renderer.Clear(_backgroundColor);
|
||||
|
||||
// 渲染背景
|
||||
lock (_bgLock)
|
||||
{
|
||||
if (_backgroundImageSprite is not null)
|
||||
{
|
||||
using var view = _renderer.GetView();
|
||||
var bg = _backgroundImageSprite;
|
||||
var viewSize = view.Size;
|
||||
var bgSize = bg.Texture.Size;
|
||||
var scaleX = Math.Abs(viewSize.X / bgSize.X);
|
||||
var scaleY = Math.Abs(viewSize.Y / bgSize.Y);
|
||||
var signX = Math.Sign(viewSize.X);
|
||||
var signY = Math.Sign(viewSize.Y);
|
||||
if (_backgroundImageMode == Stretch.None)
|
||||
{
|
||||
scaleX = scaleY = 1f / _renderer.Zoom;
|
||||
}
|
||||
else if (_backgroundImageMode == Stretch.Uniform)
|
||||
{
|
||||
scaleX = scaleY = Math.Min(scaleX, scaleY);
|
||||
}
|
||||
else if (_backgroundImageMode == Stretch.UniformToFill)
|
||||
{
|
||||
scaleX = scaleY = Math.Max(scaleX, scaleY);
|
||||
}
|
||||
bg.Scale = new(signX * scaleX, signY * scaleY);
|
||||
bg.Position = view.Center;
|
||||
bg.Rotation = view.Rotation;
|
||||
_renderer.Draw(bg);
|
||||
}
|
||||
}
|
||||
|
||||
if (_showAxis)
|
||||
{
|
||||
// 画一个很长的坐标轴, 用 1e9 比较合适
|
||||
|
||||
@@ -727,6 +727,8 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 水平分辨率 -->
|
||||
@@ -780,7 +782,15 @@
|
||||
<TextBox Grid.Row="12" Grid.Column="1" Text="{Binding BackgroundColor}" ToolTip="#AARRGGBB"/>
|
||||
|
||||
<!-- 背景图案 -->
|
||||
<Label Grid.Row="13" Grid.Column="0" Content="{DynamicResource Str_BackgroundImagePath}"/>
|
||||
<DockPanel Grid.Row="13" Grid.Column="1" >
|
||||
<Button DockPanel.Dock="Right" Content="..." Command="{Binding Cmd_SelectBackgroundImage}"/>
|
||||
<TextBox Text="{Binding BackgroundImagePath}"/>
|
||||
</DockPanel>
|
||||
|
||||
<!-- 背景图案模式 -->
|
||||
<Label Grid.Row="14" Grid.Column="0" Content="{DynamicResource Str_BackgroundImageMode}"/>
|
||||
<ComboBox Grid.Row="14" Grid.Column="1" SelectedValue="{Binding BackgroundImageMode}" ItemsSource="{Binding StretchOptions}"/>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
@@ -157,6 +157,8 @@ public partial class MainWindow : Window
|
||||
_vm.SFMLRendererViewModel.Speed = m.Speed;
|
||||
_vm.SFMLRendererViewModel.ShowAxis = m.ShowAxis;
|
||||
_vm.SFMLRendererViewModel.BackgroundColor = m.BackgroundColor;
|
||||
_vm.SFMLRendererViewModel.BackgroundImagePath = m.BackgroundImagePath;
|
||||
_vm.SFMLRendererViewModel.BackgroundImageMode = m.BackgroundImageMode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,6 +183,8 @@ public partial class MainWindow : Window
|
||||
Speed = _vm.SFMLRendererViewModel.Speed,
|
||||
ShowAxis = _vm.SFMLRendererViewModel.ShowAxis,
|
||||
BackgroundColor = _vm.SFMLRendererViewModel.BackgroundColor,
|
||||
BackgroundImagePath = _vm.SFMLRendererViewModel.BackgroundImagePath,
|
||||
BackgroundImageMode = _vm.SFMLRendererViewModel.BackgroundImageMode,
|
||||
};
|
||||
|
||||
JsonHelper.Serialize(m, LastStateFilePath);
|
||||
@@ -596,5 +600,4 @@ public partial class MainWindow : Window
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user