Compare commits

..

13 Commits

Author SHA1 Message Date
ww-rm
8e1f586d4f Merge pull request #86 from ww-rm/dev/wpf
fix bug
2025-08-20 22:44:47 +08:00
ww-rm
5dd1b84943 fix bug 2025-08-20 22:42:38 +08:00
ww-rm
ad190d8952 Merge pull request #85 from ww-rm/dev/wpf
v0.15.11
2025-08-20 22:36:14 +08:00
ww-rm
ddb11808a7 update to v0.15.11 2025-08-20 22:33:25 +08:00
ww-rm
9b1e26b2ac udpate changelog 2025-08-20 22:33:02 +08:00
ww-rm
c8e35a9aed 增加mov格式 2025-08-20 22:31:49 +08:00
ww-rm
4786b0434c 修复自定义导出参数构造错误 2025-08-19 18:02:21 +08:00
ww-rm
40bde84648 Merge pull request #81 from ww-rm/dev/wpf
v0.15.10
2025-08-18 18:54:13 +08:00
ww-rm
ebb2593526 update to v0.15.10 2025-08-18 18:52:16 +08:00
ww-rm
6a74204ba1 update readme 2025-08-18 18:51:33 +08:00
ww-rm
78c6c47300 update changelog 2025-08-18 18:48:55 +08:00
ww-rm
746a3decc8 补充插槽可见性属性值拷贝 2025-08-18 18:47:39 +08:00
ww-rm
6dfd25b760 修复插槽禁用功能 2025-08-18 18:39:27 +08:00
30 changed files with 716 additions and 437 deletions

View File

@@ -1,5 +1,14 @@
# CHANGELOG
## v0.15.11
- 修复自定义导出中参数构造错误
- 增加 mov 格式及参数说明
## v0.15.10
- 增加插槽可见性参数, 允许任何情况下对插槽启用和禁用对插槽的渲染
## v0.15.9
- 添加 V34 和 V35 版本支持

View File

@@ -19,6 +19,7 @@ A simple and user-friendly Spine file viewer and exporter with multi-language su
* Batch adjustment of skeleton parameters using multi-selection.
* Multi-track animation settings.
* Skin and custom slot attachment settings.
* Custom slot visibility settings.
* Debug rendering support.
* Fullscreen preview mode.
* Export to single frame/image sequence/animated GIF/video formats.

View File

@@ -19,6 +19,7 @@
- 支持列表多选批量设置骨骼参数
- 支持多轨道动画设置
- 支持皮肤/自定义插槽附件设置
- 支持自定义插槽可见性
- 支持调试渲染
- 支持全屏预览
- 支持单帧/动图/视频文件导出

View File

@@ -60,8 +60,9 @@ namespace Spine.Exporters
if (!string.IsNullOrEmpty(_codec)) options.WithVideoCodec(_codec);
if (!string.IsNullOrEmpty(_pixelFormat)) options.ForcePixelFormat(_pixelFormat);
if (!string.IsNullOrEmpty(_bitrate)) options.WithCustomArgument($"-b:v {_bitrate}");
if (!string.IsNullOrEmpty(_filter)) options.WithCustomArgument($"-vf unpremultiply=inplace=1, {_customArgs}");
if (!string.IsNullOrEmpty(_filter)) options.WithCustomArgument($"-vf \"unpremultiply=inplace=1, {_filter}\"");
else options.WithCustomArgument("-vf unpremultiply=inplace=1");
if (!string.IsNullOrEmpty(_customArgs)) options.WithCustomArgument($"{_customArgs}");
}
/// <summary>

View File

@@ -31,6 +31,7 @@ namespace Spine.Exporters
Mp4,
Webm,
Mkv,
Mov,
}
/// <summary>
@@ -40,29 +41,35 @@ namespace Spine.Exporters
private VideoFormat _format = VideoFormat.Mp4;
/// <summary>
/// 动图是否循环
/// 动图是否循环 [Gif/Webp]
/// </summary>
public bool Loop { get => _loop; set => _loop = value; }
private bool _loop = true;
/// <summary>
/// 质量
/// 质量 [Webp]
/// </summary>
public int Quality { get => _quality; set => _quality = Math.Clamp(value, 0, 100); }
private int _quality = 75;
/// <summary>
/// 无损压缩 (Webp)
/// 无损压缩 [Webp]
/// </summary>
public bool Lossless { get => _lossless; set => _lossless = value; }
private bool _lossless = false;
/// <summary>
/// CRF
/// CRF [Mp4/Webm/Mkv]
/// </summary>
public int Crf { get => _crf; set => _crf = Math.Clamp(value, 0, 63); }
private int _crf = 23;
/// <summary>
/// prores_ks 编码器的配置等级, -1 是自动, 越高质量越好, 只有 4 及以上才有透明通道 [Mov]
/// </summary>
public int Profile { get => _profile; set => _profile = Math.Clamp(value, -1, 5); }
private int _profile = 5;
/// <summary>
/// 获取的一帧, 结果是预乘的
/// </summary>
@@ -89,6 +96,7 @@ namespace Spine.Exporters
VideoFormat.Mp4 => SetMp4Options,
VideoFormat.Webm => SetWebmOptions,
VideoFormat.Mkv => SetMkvOptions,
VideoFormat.Mov => SetMovOptions,
_ => throw new NotImplementedException(),
};
@@ -110,8 +118,8 @@ namespace Spine.Exporters
{
// Gif 固定使用 256 调色板和 128 透明度阈值
var v = "split [s0][s1]";
var s0 = "[s0] palettegen=reserve_transparent=1:max_colors=256 [p]";
var s1 = "[s1][p] paletteuse=dither=bayer:alpha_threshold=128";
var s0 = "[s0] palettegen=max_colors=256 [p]";
var s1 = "[s1][p] paletteuse=alpha_threshold=128";
var customArgs = $"-vf \"unpremultiply=inplace=1, {v};{s0};{s1}\" -loop {(_loop ? 0 : -1)}";
options.ForceFormat("gif")
.WithCustomArgument(customArgs);
@@ -151,5 +159,13 @@ namespace Spine.Exporters
.WithCustomArgument(customArgs);
}
private void SetMovOptions(FFMpegArgumentOptions options)
{
var customArgs = "-vf unpremultiply=inplace=1";
options.ForceFormat("mov").WithVideoCodec("prores_ks").ForcePixelFormat("yuva444p10le")
.WithFastStart()
.WithCustomArgument($"-profile {_profile}")
.WithCustomArgument(customArgs);
}
}
}

View File

@@ -66,6 +66,8 @@ namespace Spine.Implementations.SpineWrappers.V21
}
}
public bool Disabled { get; set; }
public override string ToString() => _o.ToString();
}
}

View File

@@ -73,6 +73,8 @@ namespace Spine.Implementations.SpineWrappers.V34
}
}
public bool Disabled { get; set; }
public override string ToString() => _o.ToString();
}
}

View File

@@ -73,6 +73,8 @@ namespace Spine.Implementations.SpineWrappers.V35
}
}
public bool Disabled { get; set; }
public override string ToString() => _o.ToString();
}
}

View File

@@ -73,6 +73,8 @@ namespace Spine.Implementations.SpineWrappers.V36
}
}
public bool Disabled { get; set; }
public override string ToString() => _o.ToString();
}
}

View File

@@ -73,6 +73,8 @@ namespace Spine.Implementations.SpineWrappers.V37
}
}
public bool Disabled { get; set; }
public override string ToString() => _o.ToString();
}
}

View File

@@ -74,6 +74,8 @@ namespace Spine.Implementations.SpineWrappers.V38
}
}
public bool Disabled { get; set; }
public override string ToString() => _o.ToString();
}
}

View File

@@ -73,6 +73,8 @@ namespace Spine.Implementations.SpineWrappers.V40
}
}
public bool Disabled { get; set; }
public override string ToString() => _o.ToString();
}
}

View File

@@ -73,6 +73,8 @@ namespace Spine.Implementations.SpineWrappers.V41
}
}
public bool Disabled { get; set; }
public override string ToString() => _o.ToString();
}
}

View File

@@ -73,6 +73,8 @@ namespace Spine.Implementations.SpineWrappers.V42
}
}
public bool Disabled { get; set; }
public override string ToString() => _o.ToString();
}
}

View File

@@ -7,7 +7,7 @@
<TargetFramework>net8.0-windows</TargetFramework>
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<Version>0.15.9</Version>
<Version>0.15.11</Version>
</PropertyGroup>
<PropertyGroup>

View File

@@ -172,9 +172,12 @@ namespace Spine
_skinLoadStatus = other._skinLoadStatus.ToDictionary();
ReloadSkins();
// 拷贝自定义插槽附件加载情况
// 拷贝插槽属性值
for (int i = 0; i < other._skeleton.Slots.Length; i++)
{
_skeleton.Slots[i].Attachment = other._skeleton.Slots[i].Attachment;
_skeleton.Slots[i].Disabled = other._skeleton.Slots[i].Disabled;
}
// 拷贝调试属性
EnableDebug = other.EnableDebug;
@@ -299,6 +302,30 @@ namespace Spine
/// </summary>
public bool DebugClippings { get; set; }
/// <summary>
/// 获取插槽可见性, 如果不存在则默认返回 false
/// </summary>
public bool GetSlotVisible(string slotName)
{
if (_skeleton.SlotsByName.TryGetValue(slotName, out var slot))
return !slot.Disabled;
return false;
}
/// <summary>
/// 设置插槽可见性, 插槽不可见后将不会在任何渲染中出现, 插槽不存在则忽略操作
/// </summary>
/// <returns>操作是否成功, 插槽不存在则返回 false</returns>
public bool SetSlotVisible(string slotName, bool visible)
{
if (_skeleton.SlotsByName.TryGetValue(slotName, out var slot))
{
slot.Disabled = !visible;
return true;
}
return false;
}
/// <summary>
/// 获取某个插槽上的附件名, 插槽不存在或者无附件均返回 null
/// </summary>
@@ -310,7 +337,7 @@ namespace Spine
}
/// <summary>
/// 设置某个插槽的附件, 如果不存在则忽略, 可以使用 null 来清除附件
/// 设置某个插槽的附件, 如果不存在则忽略, 可以使用 null 来尝试清除附件
/// </summary>
/// <returns>是否操作成功</returns>
public bool SetAttachment(string slotName, string? attachmentName)
@@ -471,7 +498,7 @@ namespace Spine
foreach (var slot in _skeleton.IterDrawOrder())
{
if (slot.A <= 0 || !slot.Bone.Active)
if (slot.A <= 0 || !slot.Bone.Active || slot.Disabled)
{
_clipping.ClipEnd(slot);
continue;
@@ -602,7 +629,7 @@ namespace Spine
if (DebugRegions)
{
vt.Color = AttachmentLineColor;
foreach (var slot in _skeleton.Slots.Where(s => s.Bone.Active))
foreach (var slot in _skeleton.Slots.Where(s => s.Bone.Active && !s.Disabled))
{
if (slot.Attachment is IRegionAttachment regionAttachment)
{
@@ -634,7 +661,7 @@ namespace Spine
if (DebugMeshes)
{
vt.Color = MeshLineColor;
foreach (var slot in _skeleton.Slots.Where(s => s.Bone.Active))
foreach (var slot in _skeleton.Slots.Where(s => s.Bone.Active && !s.Disabled))
{
if (slot.Attachment is IMeshAttachment meshAttachment)
{
@@ -698,7 +725,7 @@ namespace Spine
if (DebugMeshHulls)
{
vt.Color = AttachmentLineColor;
foreach (var slot in _skeleton.Slots.Where(s => s.Bone.Active))
foreach (var slot in _skeleton.Slots.Where(s => s.Bone.Active && !s.Disabled))
{
if (slot.Attachment is IMeshAttachment meshAttachment)
{
@@ -767,7 +794,7 @@ namespace Spine
if (DebugClippings)
{
vt.Color = ClippingLineColor;
foreach (var slot in _skeleton.Slots.Where(s => s.Bone.Active))
foreach (var slot in _skeleton.Slots.Where(s => s.Bone.Active && !s.Disabled))
{
if (slot.Attachment is IClippingAttachment clippingAttachment)
{

View File

@@ -53,5 +53,10 @@ namespace Spine.SpineWrappers
/// 使用的附件, 可以设置为 null 清空附件
/// </summary>
public IAttachment? Attachment { get; set; }
/// <summary>
/// 是否已禁用渲染该插槽
/// </summary>
public bool Disabled { get; set; }
}
}

View File

@@ -31,6 +31,8 @@ namespace SpineViewer.Models
public Dictionary<string, string?> SlotAttachment { get; set; } = [];
public List<string> DisabledSlots { get; set; } = [];
public List<string?> Animations { get; set; } = [];
public bool DebugTexture { get; set; } = true;

View File

@@ -85,6 +85,8 @@ namespace SpineViewer.Models
public event EventHandler<SkinStatusChangedEventArgs>? SkinStatusChanged;
public event EventHandler<SlotVisibleChangedEventArgs>? SlotVisibleChanged;
public event EventHandler<SlotAttachmentChangedEventArgs>? SlotAttachmentChanged;
public event EventHandler<AnimationChangedEventArgs>? AnimationChanged;
@@ -200,6 +202,19 @@ namespace SpineViewer.Models
public FrozenDictionary<string, ImmutableArray<string>> SlotAttachments => _slotAttachments;
public bool GetSlotVisible(string slotName)
{
lock (_lock) return _spineObject.GetSlotVisible(slotName);
}
public bool SetSlotVisible(string slotName, bool visible)
{
bool changed = false;
lock (_lock) changed = _spineObject.SetSlotVisible(slotName, visible);
if (changed) SlotVisibleChanged?.Invoke(this, new(slotName, visible));
return changed;
}
public string? GetAttachment(string slotName)
{
lock (_lock) return _spineObject.GetAttachment(slotName);
@@ -390,6 +405,8 @@ namespace SpineViewer.Models
foreach (var slot in _spineObject.Skeleton.Slots) config.SlotAttachment[slot.Name] = slot.Attachment?.Name;
config.DisabledSlots = _spineObject.Skeleton.Slots.Where(it => it.Disabled).Select(it => it.Name).ToList();
// XXX: 处理空动画
config.Animations.AddRange(_spineObject.AnimationState.IterTracks().Select(tr => tr?.Animation.Name));
@@ -422,6 +439,10 @@ namespace SpineViewer.Models
if (_spineObject.SetAttachment(slotName, attachmentName))
SlotAttachmentChanged?.Invoke(this, new(slotName, attachmentName));
foreach (var slotName in value.DisabledSlots)
if (_spineObject.SetSlotVisible(slotName, false))
SlotVisibleChanged?.Invoke(this, new(slotName, false));
// XXX: 处理空动画
_spineObject.AnimationState.ClearTracks();
int trackIndex = 0;
@@ -507,6 +528,12 @@ namespace SpineViewer.Models
public bool Status { get; } = status;
}
public class SlotVisibleChangedEventArgs(string slotName, bool visible) : EventArgs
{
public string SlotName { get; } = slotName;
public bool Visible { get; } = visible;
}
public class SlotAttachmentChangedEventArgs(string slotName, string? attachmentName) : EventArgs
{
public string SlotName { get; } = slotName;

View File

@@ -78,6 +78,8 @@
<s:String x:Key="Str_Slot">Slot</s:String>
<s:String x:Key="Str_ClearSlotsAttachment">Clear Slots Attachment</s:String>
<s:String x:Key="Str_EnableSlots">Enable Slots</s:String>
<s:String x:Key="Str_DisableSlots">Disable Slots</s:String>
<s:String x:Key="Str_Animation">Animation</s:String>
<s:String x:Key="Str_AppendTrack">Add</s:String>
@@ -147,6 +149,10 @@
<s:String x:Key="Str_InvalidMaxResolution">Valid max resolution required when using auto resolution</s:String>
<s:String x:Key="Str_FFmpegFormatRequired">FFmpeg export format is required</s:String>
<s:String x:Key="Str_ExportBaseArgs">Base Parameters</s:String>
<s:String x:Key="Str_ExportVideoArgs">Video Parameters</s:String>
<s:String x:Key="Str_ExportOtherArgs">Other Parameters</s:String>
<s:String x:Key="Str_ResolutionTooltip">Screen resolution; adjust related parameters in the render settings panel</s:String>
<s:String x:Key="Str_ExportSingle">Export Single</s:String>
<s:String x:Key="Str_ExportSingleTooltip">When checked, export selected models in a single frame; output folder is required</s:String>
@@ -174,13 +180,15 @@
<s:String x:Key="Str_VideoFormat">Video Format</s:String>
<s:String x:Key="Str_LoopPlay">Loop Play</s:String>
<s:String x:Key="Str_LoopPlayTooltip">Loop animation; only effective for GIF/WebP formats</s:String>
<s:String x:Key="Str_LoopPlayTooltip" xml:space="preserve">[Gif/Webp]&#x0A;Whether the animation loops</s:String>
<s:String x:Key="Str_QualityParameter">Quality Parameter</s:String>
<s:String x:Key="Str_QualityParameterTooltip">Range 0100; higher is better; only for WebP format</s:String>
<s:String x:Key="Str_QualityParameterTooltip" xml:space="preserve">[Webp]&#x0A;Quality parameter, range 0-100, higher value means better quality</s:String>
<s:String x:Key="Str_LosslessParam">Lossless Compression</s:String>
<s:String x:Key="Str_LosslessParamTooltip">Lossless compression. Ignores the quality parameter and only applies to WebP format.</s:String>
<s:String x:Key="Str_LosslessParamTooltip" xml:space="preserve">[Webp]&#x0A;Lossless compression, quality parameter will be ignored</s:String>
<s:String x:Key="Str_CrfParameter">CRF Parameter</s:String>
<s:String x:Key="Str_CrfParameterTooltip">Range 063; lower is higher quality; only for MP4/WebM/MKV formats</s:String>
<s:String x:Key="Str_CrfParameterTooltip" xml:space="preserve">[Mp4/Webm/Mkv]&#x0A;CRF parameter, range 0-63, lower value means higher quality</s:String>
<s:String x:Key="Str_ProfileParameter">Profile Parameter</s:String>
<s:String x:Key="Str_ProfileParameterTooltip" xml:space="preserve">[Mov]&#x0A;Profile parameter, integer between -1 and 5,&#x0A;-1 means automatic, higher values indicate higher quality,&#x0A;Alpha channel encoding is only available when value is 4 or higher</s:String>
<s:String x:Key="Str_FFmpegFormat">Export Format</s:String>
<s:String x:Key="Str_FFmpegFormatTooltip">FFmpeg export format (equivalent to "-f"), e.g. "mp4", "webm"</s:String>

View File

@@ -78,6 +78,8 @@
<s:String x:Key="Str_Slot">スロット</s:String>
<s:String x:Key="Str_ClearSlotsAttachment">アタッチメントをクリア</s:String>
<s:String x:Key="Str_EnableSlots">有効</s:String>
<s:String x:Key="Str_DisableSlots">無効</s:String>
<s:String x:Key="Str_Animation">アニメーション</s:String>
<s:String x:Key="Str_AppendTrack">追加</s:String>
@@ -147,6 +149,10 @@
<s:String x:Key="Str_InvalidMaxResolution">自動解像度使用時は有効な最大解像度を指定する必要があります</s:String>
<s:String x:Key="Str_FFmpegFormatRequired">FFmpegエクスポートフォーマットを指定する必要があります</s:String>
<s:String x:Key="Str_ExportBaseArgs">基本パラメータ</s:String>
<s:String x:Key="Str_ExportVideoArgs">ビデオパラメータ</s:String>
<s:String x:Key="Str_ExportOtherArgs">その他のパラメータ</s:String>
<s:String x:Key="Str_ResolutionTooltip">画面解像度。関連パラメーターは画面パネルで調整してください</s:String>
<s:String x:Key="Str_ExportSingle">単一エクスポート</s:String>
<s:String x:Key="Str_ExportSingleTooltip">チェックすると、選択モデルを同一画面でエクスポートし、出力フォルダーの指定が必要になります</s:String>
@@ -174,13 +180,15 @@
<s:String x:Key="Str_VideoFormat">ビデオフォーマット</s:String>
<s:String x:Key="Str_LoopPlay">ループ再生</s:String>
<s:String x:Key="Str_LoopPlayTooltip">アニメーションをループ再生するか。Gif/Webp形式のみ有効です</s:String>
<s:String x:Key="Str_QualityParameter">品質パラメータ</s:String>
<s:String x:Key="Str_QualityParameterTooltip">品質パラメーター。値の範囲は0-100。値が大きいほど品質が高くなります。Webp形式のみ有効です</s:String>
<s:String x:Key="Str_LosslessParam">可逆圧縮</s:String>
<s:String x:Key="Str_LosslessParamTooltip">可逆圧縮を行います。品質パラメータは無視され、WebP形式にのみ適用されます</s:String>
<s:String x:Key="Str_CrfParameter">CRFパラメータ</s:String>
<s:String x:Key="Str_CrfParameterTooltip">CRFパラメーター。値の範囲0-63。値が小さいほど品質が高くなります。Mp4/Webm/Mkv形式のみ有効です</s:String>
<s:String x:Key="Str_LoopPlayTooltip" xml:space="preserve">[Gif/Webp]&#x0A;アニメーションをループ再生するかどうか</s:String>
<s:String x:Key="Str_QualityParameter">品質パラメータ</s:String>
<s:String x:Key="Str_QualityParameterTooltip" xml:space="preserve">[Webp]&#x0A;品質パラメータ範囲は0-100。値がいほど品質が良い</s:String>
<s:String x:Key="Str_LosslessParam">無損失圧縮</s:String>
<s:String x:Key="Str_LosslessParamTooltip" xml:space="preserve">[Webp]&#x0A;無損失圧縮、品質パラメータは無視されます</s:String>
<s:String x:Key="Str_CrfParameter">CRF パラメータ</s:String>
<s:String x:Key="Str_CrfParameterTooltip" xml:space="preserve">[Mp4/Webm/Mkv]&#x0A;CRF パラメータ範囲0-63。値が小さいほど品質が高</s:String>
<s:String x:Key="Str_ProfileParameter">プロファイルパラメータ</s:String>
<s:String x:Key="Str_ProfileParameterTooltip" xml:space="preserve">[Mov]&#x0A;プロファイルパラメータ、-1から5の整数、&#x0A;-1は自動、値が大きいほど品質が高い、&#x0A;値が4以上の場合のみアルファチャンネルをエンコード可能</s:String>
<s:String x:Key="Str_FFmpegFormat">エクスポートフォーマット</s:String>
<s:String x:Key="Str_FFmpegFormatTooltip">FFmpegエクスポートフォーマット。パラメーター“-f”に相当します。例: “mp4”、“webm”</s:String>

View File

@@ -78,6 +78,8 @@
<s:String x:Key="Str_Slot">插槽</s:String>
<s:String x:Key="Str_ClearSlotsAttachment">清除附件</s:String>
<s:String x:Key="Str_EnableSlots">启用</s:String>
<s:String x:Key="Str_DisableSlots">禁用</s:String>
<s:String x:Key="Str_Animation">动画</s:String>
<s:String x:Key="Str_AppendTrack">添加</s:String>
@@ -147,6 +149,10 @@
<s:String x:Key="Str_InvalidMaxResolution">使用自动分辨率时需要提供有效的最大分辨率</s:String>
<s:String x:Key="Str_FFmpegFormatRequired">必须指定 FFmpeg 导出格式</s:String>
<s:String x:Key="Str_ExportBaseArgs">基本参数</s:String>
<s:String x:Key="Str_ExportVideoArgs">视频参数</s:String>
<s:String x:Key="Str_ExportOtherArgs">其他参数</s:String>
<s:String x:Key="Str_ResolutionTooltip">画面分辨率,相关参数请在画面参数面板进行调整</s:String>
<s:String x:Key="Str_ExportSingle">导出单个</s:String>
<s:String x:Key="Str_ExportSingleTooltip">勾选后将所选模型在同一个画面上进行导出,且必须提供输出文件夹</s:String>
@@ -168,19 +174,21 @@
<s:String x:Key="Str_Fps">帧率</s:String>
<s:String x:Key="Str_ExportSpeed">导出速度</s:String>
<s:String x:Key="Str_ExportSpeedTooltip">导出速度因子, 仅影响模型的动作速度, 不影响导出时长和帧率等参数</s:String>
<s:String x:Key="Str_ExportSpeedTooltip">导出速度因子仅影响模型的动作速度不影响导出时长和帧率等参数</s:String>
<s:String x:Key="Str_KeepLastFrame">保留最后一帧</s:String>
<s:String x:Key="Str_KeepLastFrameTooltip">当设置保留最后一帧时,动图会更为连贯,但是帧数可能比预期帧数多 1</s:String>
<s:String x:Key="Str_VideoFormat">视频格式</s:String>
<s:String x:Key="Str_LoopPlay">循环播放</s:String>
<s:String x:Key="Str_LoopPlayTooltip">动图是否循环播放,仅对 Gif/Webp 格式生效</s:String>
<s:String x:Key="Str_LoopPlayTooltip" xml:space="preserve">[Gif/Webp]&#x0A;动图是否循环播放</s:String>
<s:String x:Key="Str_QualityParameter">质量参数</s:String>
<s:String x:Key="Str_QualityParameterTooltip">质量参数,取值范围 0-100越高质量越好, 仅对 Webp 格式生效</s:String>
<s:String x:Key="Str_QualityParameterTooltip" xml:space="preserve">[Webp]&#x0A;质量参数,取值范围 0-100越高质量越好</s:String>
<s:String x:Key="Str_LosslessParam">无损压缩</s:String>
<s:String x:Key="Str_LosslessParamTooltip">无损压缩, 会忽略质量参数, 仅对 Webp 格式生效</s:String>
<s:String x:Key="Str_LosslessParamTooltip" xml:space="preserve">[Webp]&#x0A;无损压缩会忽略质量参数</s:String>
<s:String x:Key="Str_CrfParameter">CRF 参数</s:String>
<s:String x:Key="Str_CrfParameterTooltip">CRF 参数,取值范围 0-63越小质量越高,仅对 Mp4/Webm/Mkv 格式生效</s:String>
<s:String x:Key="Str_CrfParameterTooltip" xml:space="preserve">[Mp4/Webm/Mkv]&#x0A;CRF 参数,取值范围 0-63越小质量越高</s:String>
<s:String x:Key="Str_ProfileParameter">Profile 参数</s:String>
<s:String x:Key="Str_ProfileParameterTooltip" xml:space="preserve">[Mov]&#x0A;Profile 参数,取值集合为 -1 到 5 之间的整数,&#x0A;-1 表示自动0-5 取值越高质量越高,&#x0A;仅在取值大于等于 4 时可以编码透明度通道</s:String>
<s:String x:Key="Str_FFmpegFormat">导出格式</s:String>
<s:String x:Key="Str_FFmpegFormatTooltip">FFmpeg 导出格式,等价于参数 “-f”例如 “mp4”、“webm”</s:String>

View File

@@ -7,7 +7,7 @@
<TargetFramework>net8.0-windows</TargetFramework>
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<Version>0.15.9</Version>
<Version>0.15.11</Version>
<OutputType>WinExe</OutputType>
<UseWPF>true</UseWPF>
</PropertyGroup>

View File

@@ -35,6 +35,9 @@ namespace SpineViewer.ViewModels.Exporters
public int Crf { get => _crf; set => SetProperty(ref _crf, Math.Clamp(value, 0, 63)); }
protected int _crf = 23;
public int Profile { get => _profile; set => SetProperty(ref _profile, Math.Clamp(value, -1, 5)); }
protected int _profile = 5;
private string FormatSuffix => $".{_format.ToString().ToLower()}";
protected override void Export(SpineObjectModel[] models)
@@ -60,7 +63,8 @@ namespace SpineViewer.ViewModels.Exporters
Loop = _loop,
Quality = _quality,
Lossless = _lossless,
Crf = _crf
Crf = _crf,
Profile = _profile,
};
// 非自动分辨率则直接用预览画面的视区参数

View File

@@ -15,7 +15,7 @@ namespace SpineViewer.ViewModels.MainWindow
{
private SpineObjectModel[] _selectedObjects = [];
private readonly ObservableCollection<SkinViewModel> _skins = [];
private readonly ObservableCollection<SlotAttachmentViewModel> _slots = [];
private readonly ObservableCollection<SlotViewModel> _slots = [];
private readonly ObservableCollection<AnimationTrackViewModel> _animationTracks = [];
public ImmutableArray<ISkeleton.Physics> PhysicsOptions { get; } = Enum.GetValues<ISkeleton.Physics>().ToImmutableArray();
@@ -324,11 +324,16 @@ namespace SpineViewer.ViewModels.MainWindow
args => { return args is not null && args.OfType<SkinViewModel>().Any(); }
);
public ObservableCollection<SlotAttachmentViewModel> Slots => _slots;
public ObservableCollection<SlotViewModel> Slots => _slots;
public RelayCommand<IList?> Cmd_ClearSlotsAttachment { get; } = new(
args => { if (args is null) return; foreach (var s in args.OfType<SlotAttachmentViewModel>()) s.AttachmentName = null; },
args => { return args is not null && args.OfType<SlotAttachmentViewModel>().Any(); }
public RelayCommand<IList?> Cmd_EnableSlots { get; } = new(
args => { if (args is null) return; foreach (var s in args.OfType<SlotViewModel>()) s.Visible = true; },
args => { return args is not null && args.OfType<SlotViewModel>().Any(); }
);
public RelayCommand<IList?> Cmd_DisableSlots { get; } = new(
args => { if (args is null) return; foreach (var s in args.OfType<SlotViewModel>()) s.Visible = false; },
args => { return args is not null && args.OfType<SlotViewModel>().Any(); }
);
public ObservableCollection<AnimationTrackViewModel> AnimationTracks => _animationTracks;
@@ -672,13 +677,13 @@ namespace SpineViewer.ViewModels.MainWindow
}
}
public class SlotAttachmentViewModel : ObservableObject
public class SlotViewModel : ObservableObject
{
private readonly SpineObjectModel[] _spines;
private readonly string[] _attachmentNames = [];
private readonly string _slotName;
public SlotAttachmentViewModel(string slotName, SpineObjectModel[] spines)
public SlotViewModel(string slotName, SpineObjectModel[] spines)
{
_spines = spines;
_slotName = slotName;
@@ -694,6 +699,11 @@ namespace SpineViewer.ViewModels.MainWindow
// 使用弱引用, 则此 ViewModel 被释放时无需显式退订事件
foreach (var sp in _spines)
{
WeakEventManager<SpineObjectModel, SlotVisibleChangedEventArgs>.AddHandler(
sp,
nameof(sp.SlotVisibleChanged),
SingleModel_SlotVisibleChanged
);
WeakEventManager<SpineObjectModel, SlotAttachmentChangedEventArgs>.AddHandler(
sp,
nameof(sp.SlotAttachmentChanged),
@@ -707,9 +717,6 @@ namespace SpineViewer.ViewModels.MainWindow
}
}
public RelayCommand Cmd_ClearAttachment => _cmd_ClearAttachment ??= new(() => AttachmentName = null);
private RelayCommand? _cmd_ClearAttachment;
public ReadOnlyCollection<string> AttachmentNames => _attachmentNames.AsReadOnly();
public string SlotName => _slotName;
@@ -733,6 +740,30 @@ namespace SpineViewer.ViewModels.MainWindow
}
}
public bool? Visible
{
get
{
if (_spines.Length <= 0) return null;
var val = _spines[0].GetSlotVisible(_slotName);
if (_spines.Skip(1).Any(it => it.GetSlotVisible(_slotName) != val)) return null;
return val;
}
set
{
if (_spines.Length <= 0) return;
if (value is null) return;
foreach (var sp in _spines) sp.SetSlotVisible(_slotName, (bool)value);
OnPropertyChanged();
}
}
private void SingleModel_SlotVisibleChanged(object? sender, SlotVisibleChangedEventArgs e)
{
if (e.SlotName == _slotName) OnPropertyChanged(nameof(Visible));
}
private void SingleModel_SlotAttachmentChanged(object? sender, SlotAttachmentChangedEventArgs e)
{
if (e.SlotName == _slotName) OnPropertyChanged(nameof(AttachmentName));

View File

@@ -3,13 +3,14 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:local="clr-namespace:SpineViewer.Views.ExporterDialogs"
xmlns:exporters="clr-namespace:SpineViewer.ViewModels.Exporters"
d:DataContext="{d:DesignInstance Type=exporters:CustomFFmpegExporterViewModel}"
mc:Ignorable="d"
Title="{DynamicResource Str_CustomFFmpegExporterTitle}"
Width="450"
Height="650"
Height="800"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner">
<DockPanel>
@@ -27,145 +28,186 @@
</Border>
<Border>
<Border.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>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource ComboBoxBaseStyle}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MyToggleButton}">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type GroupBox}" BasedOn="{StaticResource GroupBoxTab}">
<Setter Property="BorderBrush" Value="LightGray"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="hc:TitleElement.Background" Value="Transparent"/>
<Setter Property="Margin" Value="0 5 0 10"/>
</Style>
</Border.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Grid Margin="30 10">
<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>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource ComboBoxBaseStyle}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MyToggleButton}">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<StackPanel Grid.IsSharedSizeScope="True">
<GroupBox Header="{DynamicResource Str_ExportBaseArgs}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 水平分辨率 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_ResolutionX}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionX, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 水平分辨率 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_ResolutionX}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionX, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 垂直分辨率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_ResolutionY}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionY, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 垂直分辨率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_ResolutionY}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionY, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 是否导出单个 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<!-- 是否导出单个 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<!-- 输出文件夹 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
<DockPanel Grid.Row="3" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonSelectOutputDir_Click"/>
<TextBox Text="{Binding OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
</DockPanel>
<!-- 输出文件夹 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
<DockPanel Grid.Row="3" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonSelectOutputDir_Click"/>
<TextBox Text="{Binding OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
</DockPanel>
<!-- 背景颜色 -->
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_BackgroundColor}" ToolTip="#AARRGGBB"/>
<DockPanel Grid.Row="4" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonPickColor_Click">
<Button.Background>
<SolidColorBrush Color="{Binding BackgroundColor}"/>
</Button.Background>
</Button>
<TextBox x:Name="_colorTextBox" Text="{Binding BackgroundColor}" ToolTip="#AARRGGBB"/>
</DockPanel>
<!-- 背景颜色 -->
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_BackgroundColor}" ToolTip="#AARRGGBB"/>
<DockPanel Grid.Row="4" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonPickColor_Click">
<Button.Background>
<SolidColorBrush Color="{Binding BackgroundColor}"/>
</Button.Background>
</Button>
<TextBox x:Name="_colorTextBox" Text="{Binding BackgroundColor}" ToolTip="#AARRGGBB"/>
</DockPanel>
<!-- 四周边距 -->
<Label Grid.Row="5" Grid.Column="0" Content="{DynamicResource Str_Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<!-- 四周边距 -->
<Label Grid.Row="5" Grid.Column="0" Content="{DynamicResource Str_Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<!-- 自动分辨率 -->
<Label Grid.Row="6" Grid.Column="0" Content="{DynamicResource Str_AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<ToggleButton Grid.Row="6" Grid.Column="1" IsChecked="{Binding AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<!-- 自动分辨率 -->
<Label Grid.Row="6" Grid.Column="0" Content="{DynamicResource Str_AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<ToggleButton Grid.Row="6" Grid.Column="1" IsChecked="{Binding AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<!-- 最大分辨率 -->
<Label Grid.Row="7" Grid.Column="0" Content="{DynamicResource Str_MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<!-- 最大分辨率 -->
<Label Grid.Row="7" Grid.Column="0" Content="{DynamicResource Str_MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
</Grid>
</GroupBox>
<Separator Grid.Row="8" Grid.ColumnSpan="2" Height="10"/>
<GroupBox Header="{DynamicResource Str_ExportVideoArgs}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 导出时长 -->
<Label Grid.Row="9" Grid.Column="0" Content="{DynamicResource Str_Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<TextBox Grid.Row="9" Grid.Column="1" Text="{Binding Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<!-- 导出时长 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<!-- 导出帧率 -->
<Label Grid.Row="10" Grid.Column="0" Content="{DynamicResource Str_Fps}"/>
<TextBox Grid.Row="10" Grid.Column="1" Text="{Binding Fps}"/>
<!-- 导出帧率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_Fps}"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Fps}"/>
<!-- 导出速度 -->
<Label Grid.Row="11" Grid.Column="0" Content="{DynamicResource Str_ExportSpeed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<TextBox Grid.Row="11" Grid.Column="1" Text="{Binding Speed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<!-- 导出速度 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSpeed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Speed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<!-- 是否保留最后一帧 -->
<Label Grid.Row="12" Grid.Column="0" Content="{DynamicResource Str_KeepLastFrame}" ToolTip="{DynamicResource Str_KeepLastFrameTooltip}"/>
<ToggleButton Grid.Row="12" Grid.Column="1" IsChecked="{Binding KeepLast}" ToolTip="{DynamicResource Str_KeelLastFrameTooltip}"/>
<!-- 是否保留最后一帧 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_KeepLastFrame}" ToolTip="{DynamicResource Str_KeepLastFrameTooltip}"/>
<ToggleButton Grid.Row="3" Grid.Column="1" IsChecked="{Binding KeepLast}" ToolTip="{DynamicResource Str_KeelLastFrameTooltip}"/>
</Grid>
</GroupBox>
<Separator Grid.Row="13" Grid.ColumnSpan="2" Height="10"/>
<GroupBox Header="{DynamicResource Str_ExportOtherArgs}">
<Grid>
<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>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource ComboBoxBaseStyle}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MyToggleButton}">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<!-- 导出格式 -->
<Label Grid.Row="14" Grid.Column="0" Content="{DynamicResource Str_FFmpegFormat}" ToolTip="{DynamicResource Str_FFmpegFormatTooltip}"/>
<TextBox Grid.Row="14" Grid.Column="1" Text="{Binding Format}" ToolTip="{DynamicResource Str_FFmpegFormatTooltip}"/>
<!-- 导出格式 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_FFmpegFormat}" ToolTip="{DynamicResource Str_FFmpegFormatTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Format}" ToolTip="{DynamicResource Str_FFmpegFormatTooltip}"/>
<!-- 编码器 -->
<Label Grid.Row="15" Grid.Column="0" Content="{DynamicResource Str_FFmpegCodec}" ToolTip="{DynamicResource Str_FFmpegCodecTooltip}"/>
<TextBox Grid.Row="15" Grid.Column="1" Text="{Binding Codec}" ToolTip="{DynamicResource Str_FFmpegCodecTooltip}"/>
<!-- 编码器 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_FFmpegCodec}" ToolTip="{DynamicResource Str_FFmpegCodecTooltip}"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Codec}" ToolTip="{DynamicResource Str_FFmpegCodecTooltip}"/>
<!-- 像素格式 -->
<Label Grid.Row="16" Grid.Column="0" Content="{DynamicResource Str_FFmpegPixelFormat}" ToolTip="{DynamicResource Str_FFmpegPixelFormatTooltip}"/>
<TextBox Grid.Row="16" Grid.Column="1" Text="{Binding PixelFormat}" ToolTip="{DynamicResource Str_FFmpegPixelFormatTooltip}"/>
<!-- 像素格式 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_FFmpegPixelFormat}" ToolTip="{DynamicResource Str_FFmpegPixelFormatTooltip}"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding PixelFormat}" ToolTip="{DynamicResource Str_FFmpegPixelFormatTooltip}"/>
<!-- 比特率 -->
<Label Grid.Row="17" Grid.Column="0" Content="{DynamicResource Str_FFmpegBitrate}" ToolTip="{DynamicResource Str_FFmpegBitrateTooltip}"/>
<TextBox Grid.Row="17" Grid.Column="1" Text="{Binding Bitrate}" ToolTip="{DynamicResource Str_FFmpegBitrateTooltip}"/>
<!-- 比特率 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_FFmpegBitrate}" ToolTip="{DynamicResource Str_FFmpegBitrateTooltip}"/>
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Bitrate}" ToolTip="{DynamicResource Str_FFmpegBitrateTooltip}"/>
<!-- 滤镜 -->
<Label Grid.Row="18" Grid.Column="0" Content="{DynamicResource Str_FFmpegFilter}" ToolTip="{DynamicResource Str_FFmpegFilterTooltip}"/>
<TextBox Grid.Row="18" Grid.Column="1" Text="{Binding Filter}" ToolTip="{DynamicResource Str_FFmpegFilterTooltip}"/>
<!-- 滤镜 -->
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_FFmpegFilter}" ToolTip="{DynamicResource Str_FFmpegFilterTooltip}"/>
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Filter}" ToolTip="{DynamicResource Str_FFmpegFilterTooltip}"/>
<!-- 自定义参数 -->
<Label Grid.Row="19" Grid.Column="0"
VerticalAlignment="Top"
Content="{DynamicResource Str_FFmpegCustomArgs}"
ToolTip="{DynamicResource Str_FFmpegCustomArgsTooltip}"/>
<TextBox Grid.Row="19" Grid.Column="1"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Top"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto"
Text="{Binding CustomArgs}"
ToolTip="{DynamicResource Str_FFmpegCustomArgsTooltip}"/>
</Grid>
<!-- 自定义参数 -->
<Label Grid.Row="5" Grid.Column="0"
VerticalAlignment="Top"
Content="{DynamicResource Str_FFmpegCustomArgs}"
ToolTip="{DynamicResource Str_FFmpegCustomArgsTooltip}"/>
<TextBox Grid.Row="5" Grid.Column="1"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Top"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto"
Text="{Binding CustomArgs}"
ToolTip="{DynamicResource Str_FFmpegCustomArgsTooltip}"/>
</Grid>
</GroupBox>
</StackPanel>
</ScrollViewer>
</Border>
</DockPanel>

View File

@@ -3,13 +3,14 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:local="clr-namespace:SpineViewer.Views.ExporterDialogs"
xmlns:exporters="clr-namespace:SpineViewer.ViewModels.Exporters"
d:DataContext="{d:DesignInstance Type=exporters:FFmpegVideoExporterViewModel}"
mc:Ignorable="d"
Title="{DynamicResource Str_FFmpegVideoExporterTitle}"
Width="450"
Height="580"
Height="750"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner">
<DockPanel>
@@ -27,131 +28,163 @@
</Border>
<Border>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Grid Margin="30 10">
<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>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource ComboBoxBaseStyle}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MyToggleButton}">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border.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>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource ComboBoxBaseStyle}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MyToggleButton}">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type GroupBox}" BasedOn="{StaticResource GroupBoxTab}">
<Setter Property="BorderBrush" Value="LightGray"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="hc:TitleElement.Background" Value="Transparent"/>
<Setter Property="Margin" Value="0 5 0 10"/>
</Style>
</Border.Resources>
<!-- 水平分辨率 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_ResolutionX}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionX, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Grid.IsSharedSizeScope="True">
<GroupBox Header="{DynamicResource Str_ExportBaseArgs}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 垂直分辨率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_ResolutionY}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionY, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 水平分辨率 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_ResolutionX}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionX, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 是否导出单个 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<!-- 垂直分辨率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_ResolutionY}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionY, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 输出文件夹 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
<DockPanel Grid.Row="3" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonSelectOutputDir_Click"/>
<TextBox Text="{Binding OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
</DockPanel>
<!-- 是否导出单个 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<!-- 背景颜色 -->
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_BackgroundColor}" ToolTip="#AARRGGBB"/>
<DockPanel Grid.Row="4" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonPickColor_Click">
<Button.Background>
<SolidColorBrush Color="{Binding BackgroundColor}"/>
</Button.Background>
</Button>
<TextBox x:Name="_colorTextBox" Text="{Binding BackgroundColor}" ToolTip="#AARRGGBB"/>
</DockPanel>
<!-- 输出文件夹 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
<DockPanel Grid.Row="3" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonSelectOutputDir_Click"/>
<TextBox Text="{Binding OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
</DockPanel>
<!-- 四周边距 -->
<Label Grid.Row="5" Grid.Column="0" Content="{DynamicResource Str_Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<!-- 背景颜色 -->
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_BackgroundColor}" ToolTip="#AARRGGBB"/>
<DockPanel Grid.Row="4" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonPickColor_Click">
<Button.Background>
<SolidColorBrush Color="{Binding BackgroundColor}"/>
</Button.Background>
</Button>
<TextBox x:Name="_colorTextBox" Text="{Binding BackgroundColor}" ToolTip="#AARRGGBB"/>
</DockPanel>
<!-- 自动分辨率 -->
<Label Grid.Row="6" Grid.Column="0" Content="{DynamicResource Str_AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<ToggleButton Grid.Row="6" Grid.Column="1" IsChecked="{Binding AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<!-- 四周边距 -->
<Label Grid.Row="5" Grid.Column="0" Content="{DynamicResource Str_Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<!-- 最大分辨率 -->
<Label Grid.Row="7" Grid.Column="0" Content="{DynamicResource Str_MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<!-- 自动分辨率 -->
<Label Grid.Row="6" Grid.Column="0" Content="{DynamicResource Str_AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<ToggleButton Grid.Row="6" Grid.Column="1" IsChecked="{Binding AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<Separator Grid.Row="8" Grid.ColumnSpan="2" Height="10"/>
<!-- 最大分辨率 -->
<Label Grid.Row="7" Grid.Column="0" Content="{DynamicResource Str_MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
</Grid>
</GroupBox>
<!-- 导出时长 -->
<Label Grid.Row="9" Grid.Column="0" Content="{DynamicResource Str_Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<TextBox Grid.Row="9" Grid.Column="1" Text="{Binding Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<GroupBox Header="{DynamicResource Str_ExportVideoArgs}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 导出帧率 -->
<Label Grid.Row="10" Grid.Column="0" Content="{DynamicResource Str_Fps}"/>
<TextBox Grid.Row="10" Grid.Column="1" Text="{Binding Fps}"/>
<!-- 导出时长 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<!-- 导出速度 -->
<Label Grid.Row="11" Grid.Column="0" Content="{DynamicResource Str_ExportSpeed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<TextBox Grid.Row="11" Grid.Column="1" Text="{Binding Speed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<!-- 导出帧率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_Fps}"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Fps}"/>
<!-- 是否保留最后一帧 -->
<Label Grid.Row="12" Grid.Column="0" Content="{DynamicResource Str_KeepLastFrame}" ToolTip="{DynamicResource Str_KeepLastFrameTooltip}"/>
<ToggleButton Grid.Row="12" Grid.Column="1" IsChecked="{Binding KeepLast}" ToolTip="{DynamicResource Str_KeelLastFrameTooltip}"/>
<!-- 导出速度 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSpeed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Speed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<Separator Grid.Row="13" Grid.ColumnSpan="2" Height="10"/>
<!-- 是否保留最后一帧 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_KeepLastFrame}" ToolTip="{DynamicResource Str_KeepLastFrameTooltip}"/>
<ToggleButton Grid.Row="3" Grid.Column="1" IsChecked="{Binding KeepLast}" ToolTip="{DynamicResource Str_KeelLastFrameTooltip}"/>
</Grid>
</GroupBox>
<!-- 视频格式 -->
<Label Grid.Row="14" Grid.Column="0" Content="{DynamicResource Str_VideoFormat}"/>
<ComboBox Grid.Row="14" Grid.Column="1" SelectedItem="{Binding Format}" ItemsSource="{Binding VideoFormatOptions}"/>
<GroupBox Header="{DynamicResource Str_ExportOtherArgs}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 动图是否循环 -->
<Label Grid.Row="15" Grid.Column="0" Content="{DynamicResource Str_LoopPlay}" ToolTip="{DynamicResource Str_LoopPlayTooltip}"/>
<ToggleButton Grid.Row="15" Grid.Column="1" IsChecked="{Binding Loop}" ToolTip="{DynamicResource Str_LoopPlayTooltip}"/>
<!-- 视频格式 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_VideoFormat}"/>
<ComboBox Grid.Row="0" Grid.Column="1" SelectedItem="{Binding Format}" ItemsSource="{Binding VideoFormatOptions}"/>
<!-- 质量参数 -->
<Label Grid.Row="16" Grid.Column="0" Content="{DynamicResource Str_QualityParameter}" ToolTip="{DynamicResource Str_QualityParameterTooltip}"/>
<TextBox Grid.Row="16" Grid.Column="1" Text="{Binding Quality}" ToolTip="{DynamicResource Str_QualityParameterTooltip}"/>
<!-- 动图是否循环 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_LoopPlay}" ToolTip="{DynamicResource Str_LoopPlayTooltip}"/>
<ToggleButton Grid.Row="1" Grid.Column="1" IsChecked="{Binding Loop}" ToolTip="{DynamicResource Str_LoopPlayTooltip}"/>
<!-- 无损压缩 -->
<Label Grid.Row="17" Grid.Column="0" Content="{DynamicResource Str_LosslessParam}" ToolTip="{DynamicResource Str_LosslessParamTooltip}"/>
<ToggleButton Grid.Row="17" Grid.Column="1" IsChecked="{Binding Lossless}" ToolTip="{DynamicResource Str_LosslessParamTooltip}"/>
<!-- 质量参数 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_QualityParameter}" ToolTip="{DynamicResource Str_QualityParameterTooltip}"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Quality}" ToolTip="{DynamicResource Str_QualityParameterTooltip}"/>
<!-- CRF 参数 -->
<Label Grid.Row="18" Grid.Column="0" Content="{DynamicResource Str_CrfParameter}" ToolTip="{DynamicResource Str_CrfParameterTooltip}"/>
<TextBox Grid.Row="18" Grid.Column="1" Text="{Binding Crf}" ToolTip="{DynamicResource Str_CrfParameterTooltip}"/>
</Grid>
<!-- 无损压缩 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_LosslessParam}" ToolTip="{DynamicResource Str_LosslessParamTooltip}"/>
<ToggleButton Grid.Row="3" Grid.Column="1" IsChecked="{Binding Lossless}" ToolTip="{DynamicResource Str_LosslessParamTooltip}"/>
<!-- CRF 参数 -->
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_CrfParameter}" ToolTip="{DynamicResource Str_CrfParameterTooltip}"/>
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Crf}" ToolTip="{DynamicResource Str_CrfParameterTooltip}"/>
<!-- Profile 参数 -->
<Label Grid.Row="5" Grid.Column="0" Content="{DynamicResource Str_ProfileParameter}" ToolTip="{DynamicResource Str_ProfileParameterTooltip}"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Profile}" ToolTip="{DynamicResource Str_ProfileParameterTooltip}"/>
</Grid>
</GroupBox>
</StackPanel>
</ScrollViewer>
</Border>

View File

@@ -10,7 +10,7 @@
mc:Ignorable="d"
Title="{DynamicResource Str_FrameExporterTitle}"
Width="450"
Height="400"
Height="480"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner">
<DockPanel>
@@ -28,94 +28,112 @@
</Border>
<Border>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Border.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>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource ComboBoxBaseStyle}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MyToggleButton}">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type GroupBox}" BasedOn="{StaticResource GroupBoxTab}">
<Setter Property="BorderBrush" Value="LightGray"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="hc:TitleElement.Background" Value="Transparent"/>
<Setter Property="Margin" Value="0 5 0 10"/>
</Style>
</Border.Resources>
<Grid Margin="30 10">
<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>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource ComboBoxBaseStyle}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MyToggleButton}">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Grid.IsSharedSizeScope="True">
<GroupBox Header="{DynamicResource Str_ExportBaseArgs}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 水平分辨率 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_ResolutionX}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionX, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 水平分辨率 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_ResolutionX}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionX, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 垂直分辨率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_ResolutionY}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionY, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 垂直分辨率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_ResolutionY}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionY, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 是否导出单个 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<!-- 是否导出单个 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<!-- 输出文件夹 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
<DockPanel Grid.Row="3" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonSelectOutputDir_Click"/>
<TextBox Text="{Binding OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
</DockPanel>
<!-- 输出文件夹 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
<DockPanel Grid.Row="3" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonSelectOutputDir_Click"/>
<TextBox Text="{Binding OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
</DockPanel>
<!-- 背景颜色 -->
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_BackgroundColor}" ToolTip="#AARRGGBB"/>
<DockPanel Grid.Row="4" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonPickColor_Click">
<Button.Background>
<SolidColorBrush Color="{Binding BackgroundColor}"/>
</Button.Background>
</Button>
<TextBox x:Name="_colorTextBox" Text="{Binding BackgroundColor}" ToolTip="#AARRGGBB"/>
</DockPanel>
<!-- 背景颜色 -->
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_BackgroundColor}" ToolTip="#AARRGGBB"/>
<DockPanel Grid.Row="4" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonPickColor_Click">
<Button.Background>
<SolidColorBrush Color="{Binding BackgroundColor}"/>
</Button.Background>
</Button>
<TextBox x:Name="_colorTextBox" Text="{Binding BackgroundColor}" ToolTip="#AARRGGBB"/>
</DockPanel>
<!-- 四周边距 -->
<Label Grid.Row="5" Grid.Column="0" Content="{DynamicResource Str_Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<!-- 四周边距 -->
<Label Grid.Row="5" Grid.Column="0" Content="{DynamicResource Str_Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<!-- 自动分辨率 -->
<Label Grid.Row="6" Grid.Column="0" Content="{DynamicResource Str_AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<ToggleButton Grid.Row="6" Grid.Column="1" IsChecked="{Binding AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<!-- 自动分辨率 -->
<Label Grid.Row="6" Grid.Column="0" Content="{DynamicResource Str_AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<ToggleButton Grid.Row="6" Grid.Column="1" IsChecked="{Binding AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<!-- 最大分辨率 -->
<Label Grid.Row="7" Grid.Column="0" Content="{DynamicResource Str_MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<!-- 最大分辨率 -->
<Label Grid.Row="7" Grid.Column="0" Content="{DynamicResource Str_MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
</Grid>
</GroupBox>
<Separator Grid.Row="8" Grid.ColumnSpan="2" Height="10"/>
<GroupBox Header="{DynamicResource Str_ExportOtherArgs}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 图像格式 -->
<Label Grid.Row="9" Grid.Column="0" Content="{DynamicResource Str_ImageFormat}"/>
<ComboBox Grid.Row="9" Grid.Column="1" SelectedItem="{Binding Format}" ItemsSource="{Binding FrameFormatOptions}"/>
<!-- 图像格式 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_ImageFormat}"/>
<ComboBox Grid.Row="0" Grid.Column="1" SelectedItem="{Binding Format}" ItemsSource="{Binding FrameFormatOptions}"/>
<!-- 图像质量 -->
<Label Grid.Row="10" Grid.Column="0" Content="{DynamicResource Str_ImageQuality}" ToolTip="{DynamicResource Str_ImageQualityTooltip}"/>
<TextBox Grid.Row="10" Grid.Column="1" Text="{Binding Quality}" ToolTip="{DynamicResource Str_ImageQualityTooltip}"/>
</Grid>
<!-- 图像质量 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_ImageQuality}" ToolTip="{DynamicResource Str_ImageQualityTooltip}"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Quality}" ToolTip="{DynamicResource Str_ImageQualityTooltip}"/>
</Grid>
</GroupBox>
</StackPanel>
</ScrollViewer>
</Border>
</DockPanel>

View File

@@ -3,13 +3,14 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:local="clr-namespace:SpineViewer.Views"
xmlns:vmexp="clr-namespace:SpineViewer.ViewModels.Exporters"
d:DataContext="{d:DesignInstance Type=vmexp:FrameSequenceExporterViewModel}"
mc:Ignorable="d"
Title="{DynamicResource Str_FrameSequenceExporterTitle}"
Width="450"
Height="450"
Height="550"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner">
<DockPanel>
@@ -27,104 +28,122 @@
</Border>
<Border>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Border.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>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource ComboBoxBaseStyle}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MyToggleButton}">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type GroupBox}" BasedOn="{StaticResource GroupBoxTab}">
<Setter Property="BorderBrush" Value="LightGray"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="hc:TitleElement.Background" Value="Transparent"/>
<Setter Property="Margin" Value="0 5 0 10"/>
</Style>
</Border.Resources>
<Grid Margin="30 10">
<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>
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource ComboBoxBaseStyle}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MyToggleButton}">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Grid.IsSharedSizeScope="True">
<GroupBox Header="{DynamicResource Str_ExportBaseArgs}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 水平分辨率 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_ResolutionX}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionX, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 水平分辨率 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_ResolutionX}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionX, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 垂直分辨率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_ResolutionY}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionY, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 垂直分辨率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_ResolutionY}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding ResolutionY, Mode=OneWay}" ToolTip="{DynamicResource Str_ResolutionTooltip}"/>
<!-- 是否导出单个 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<!-- 是否导出单个 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding ExportSingle}" ToolTip="{DynamicResource Str_ExportSingleTooltip}"/>
<!-- 输出文件夹 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
<DockPanel Grid.Row="3" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonSelectOutputDir_Click"/>
<TextBox Text="{Binding OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
</DockPanel>
<!-- 输出文件夹 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
<DockPanel Grid.Row="3" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonSelectOutputDir_Click"/>
<TextBox Text="{Binding OutputDir}" ToolTip="{DynamicResource Str_OutputDirTooltip}"/>
</DockPanel>
<!-- 背景颜色 -->
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_BackgroundColor}" ToolTip="#AARRGGBB"/>
<DockPanel Grid.Row="4" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonPickColor_Click">
<Button.Background>
<SolidColorBrush Color="{Binding BackgroundColor}"/>
</Button.Background>
</Button>
<TextBox x:Name="_colorTextBox" Text="{Binding BackgroundColor}" ToolTip="#AARRGGBB"/>
</DockPanel>
<!-- 背景颜色 -->
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_BackgroundColor}" ToolTip="#AARRGGBB"/>
<DockPanel Grid.Row="4" Grid.Column="1">
<Button DockPanel.Dock="Right" Content="..." Click="ButtonPickColor_Click">
<Button.Background>
<SolidColorBrush Color="{Binding BackgroundColor}"/>
</Button.Background>
</Button>
<TextBox x:Name="_colorTextBox" Text="{Binding BackgroundColor}" ToolTip="#AARRGGBB"/>
</DockPanel>
<!-- 四周边距 -->
<Label Grid.Row="5" Grid.Column="0" Content="{DynamicResource Str_Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<!-- 四周边距 -->
<Label Grid.Row="5" Grid.Column="0" Content="{DynamicResource Str_Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Margin}" ToolTip="{DynamicResource Str_MarginTooltip}"/>
<!-- 自动分辨率 -->
<Label Grid.Row="6" Grid.Column="0" Content="{DynamicResource Str_AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<ToggleButton Grid.Row="6" Grid.Column="1" IsChecked="{Binding AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<!-- 自动分辨率 -->
<Label Grid.Row="6" Grid.Column="0" Content="{DynamicResource Str_AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<ToggleButton Grid.Row="6" Grid.Column="1" IsChecked="{Binding AutoResolution}" ToolTip="{DynamicResource Str_AutoResolutionTooltip}"/>
<!-- 最大分辨率 -->
<Label Grid.Row="7" Grid.Column="0" Content="{DynamicResource Str_MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<!-- 最大分辨率 -->
<Label Grid.Row="7" Grid.Column="0" Content="{DynamicResource Str_MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding MaxResolution}" ToolTip="{DynamicResource Str_MaxResolutionTooltip}"/>
</Grid>
</GroupBox>
<Separator Grid.Row="8" Grid.ColumnSpan="2" Height="10"/>
<GroupBox Header="{DynamicResource Str_ExportVideoArgs}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 导出时长 -->
<Label Grid.Row="9" Grid.Column="0" Content="{DynamicResource Str_Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<TextBox Grid.Row="9" Grid.Column="1" Text="{Binding Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<!-- 导出时长 -->
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Duration}" ToolTip="{DynamicResource Str_ExportDurationTooltip}"/>
<!-- 导出帧率 -->
<Label Grid.Row="10" Grid.Column="0" Content="{DynamicResource Str_Fps}"/>
<TextBox Grid.Row="10" Grid.Column="1" Text="{Binding Fps}"/>
<!-- 导出帧率 -->
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_Fps}"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Fps}"/>
<!-- 导出速度 -->
<Label Grid.Row="11" Grid.Column="0" Content="{DynamicResource Str_ExportSpeed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<TextBox Grid.Row="11" Grid.Column="1" Text="{Binding Speed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<!-- 导出速度 -->
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ExportSpeed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Speed}" ToolTip="{DynamicResource Str_ExportSpeedTooltip}"/>
<!-- 是否保留最后一帧 -->
<Label Grid.Row="12" Grid.Column="0" Content="{DynamicResource Str_KeepLastFrame}" ToolTip="{DynamicResource Str_KeepLastFrameTooltip}"/>
<ToggleButton Grid.Row="12" Grid.Column="1" IsChecked="{Binding KeepLast}" ToolTip="{DynamicResource Str_KeelLastFrameTooltip}"/>
</Grid>
<!-- 是否保留最后一帧 -->
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_KeepLastFrame}" ToolTip="{DynamicResource Str_KeepLastFrameTooltip}"/>
<ToggleButton Grid.Row="3" Grid.Column="1" IsChecked="{Binding KeepLast}" ToolTip="{DynamicResource Str_KeelLastFrameTooltip}"/>
</Grid>
</GroupBox>
</StackPanel>
</ScrollViewer>
</Border>
</DockPanel>

View File

@@ -524,8 +524,11 @@
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="{DynamicResource Str_ClearSlotsAttachment}"
Command="{Binding Cmd_ClearSlotsAttachment}"
<MenuItem Header="{DynamicResource Str_EnableSlots}"
Command="{Binding Cmd_EnableSlots}"
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
<MenuItem Header="{DynamicResource Str_DisableSlots}"
Command="{Binding Cmd_DisableSlots}"
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
</ContextMenu>
</ListBox.ContextMenu>
@@ -540,9 +543,7 @@
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding SlotName}" HorizontalAlignment="Left"/>
<ComboBox Grid.Column="1" SelectedValue="{Binding AttachmentName}" ItemsSource="{Binding AttachmentNames}"/>
<Button Grid.Column="2"
Command="{Binding Cmd_ClearAttachment}"
hc:IconElement.Geometry="{StaticResource Geo_Ban}"/>
<ToggleButton Grid.Column="2" IsChecked="{Binding Visible}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>