Skip to content
36 changes: 36 additions & 0 deletions OpenUtau.Core/Commands/TrackCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,16 @@ public MoveTrackCommand(UProject project, UTrack track, bool up) {
}
public override string ToString() => "Move track";
public override void Execute() {
if (index < 0 || index + 1 >= project.tracks.Count) {
return;
}
project.tracks.Reverse(index, 2);
UpdateTrackNo();
}
public override void Unexecute() {
if (index < 0 || index + 1 >= project.tracks.Count) {
return;
}
project.tracks.Reverse(index, 2);
UpdateTrackNo();
}
Expand Down Expand Up @@ -113,6 +119,36 @@ public ChangeTrackColorCommand(UProject project, UTrack track, string colorName)
public override void Unexecute() => track.TrackColor = oldName;
}

public class TrackChangeSettingsCommand : TrackCommand {
readonly bool newMute;
readonly bool oldMute;
readonly double newVolume;
readonly double oldVolume;
readonly double newPan;
readonly double oldPan;
public TrackChangeSettingsCommand(UProject project, UTrack track, bool mute, double volume, double pan) {
this.project = project;
this.track = track;
newMute = mute;
newVolume = volume;
newPan = pan;
oldMute = track.Mute;
oldVolume = track.Volume;
oldPan = track.Pan;
}
public override string ToString() => "Change track settings";
public override void Execute() {
track.Mute = newMute;
track.Volume = newVolume;
track.Pan = newPan;
}
public override void Unexecute() {
track.Mute = oldMute;
track.Volume = oldVolume;
track.Pan = oldPan;
}
}

public class TrackChangeSingerCommand : TrackCommand {
readonly USinger newSinger, oldSinger;
public TrackChangeSingerCommand(UProject project, UTrack track, USinger newSinger) {
Expand Down
32 changes: 32 additions & 0 deletions OpenUtau/Controls/ApplyToAllTracksButton.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Media;

namespace OpenUtau.App.Controls {

public class ApplyToAllTracksButton : Button {
public ApplyToAllTracksButton() {
Padding = new Avalonia.Thickness(0);
BorderThickness = new Avalonia.Thickness(0);
Background = Brushes.Transparent;
Focusable = false;
Content = new Path {
Stroke = ThemeManager.AccentBrush2,
StrokeThickness = 1.75,
Data = Geometry.Parse("M3,4 H11 M3,8 H11 M3,12 H11 M10,2 L13,4 L10,6 M10,6 L13,4 L10,2"),
};
Comment thread
rokujyushi marked this conversation as resolved.
}

protected override void OnPointerPressed(PointerPressedEventArgs e) {
base.OnPointerPressed(e);
e.Handled = true;
}

protected override void OnPointerReleased(PointerReleasedEventArgs e) {
base.OnPointerReleased(e);
e.Handled = true;
}
}

}
78 changes: 44 additions & 34 deletions OpenUtau/Controls/FavouriteToggleButton.cs
Original file line number Diff line number Diff line change
@@ -1,44 +1,54 @@
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Media;
using OpenUtau.App;

public class FavouriteToggleButton : ToggleButton
{
private readonly Path _iconPath;

public FavouriteToggleButton()
{
//this.Height = 20;
//this.Width = 20;
// Create icon Path.
_iconPath = new Path
{
Fill = SolidColorBrush.Parse("#00000000"),
Stroke = ThemeManager.AccentBrush3,
StrokeThickness = 2,
Data = Geometry.Parse("M12,21.35L10.55,20.03C5.4,15.36,2,12.28,2,8.5C2,5.42,4.42,3,7.5,3C9.24,3,10.91,3.81,12,5.09C13.09,3.81,14.76,3,16.5,3C19.58,3,22,5.42,22,8.5C22,12.28,18.6,15.36,13.45,20.04L12,21.35Z"),
RenderTransform = new ScaleTransform { ScaleX = 0.6,ScaleY = 0.6}
};

this.Content = _iconPath;

// Change icon on click.
this.PropertyChanged += (sender, e) =>
{
if (e.Property == IsCheckedProperty)
{
UpdateIcon(IsChecked ?? false);
namespace OpenUtau.App.Controls {

public class FavouriteToggleButton : ToggleButton {
private readonly Path _iconPath;

public FavouriteToggleButton() {
Padding = new Avalonia.Thickness(0);
//this.Height = 20;
//this.Width = 20;
// Create icon Path.
_iconPath = new Path {
Fill = SolidColorBrush.Parse("#00000000"),
Stroke = ThemeManager.AccentBrush3,
StrokeThickness = 2,
Data = Geometry.Parse("M12,21.35L10.55,20.03C5.4,15.36,2,12.28,2,8.5C2,5.42,4.42,3,7.5,3C9.24,3,10.91,3.81,12,5.09C13.09,3.81,14.76,3,16.5,3C19.58,3,22,5.42,22,8.5C22,12.28,18.6,15.36,13.45,20.04L12,21.35Z"),
RenderTransform = new ScaleTransform { ScaleX = 0.5, ScaleY = 0.5 }
};

this.Content = _iconPath;

// Change icon on click.
this.PropertyChanged += (sender, e) => {
if (e.Property == IsCheckedProperty) {
UpdateIcon(IsChecked ?? false);
}
};
}

private void UpdateIcon(bool isChecked) {
if (isChecked) {
_iconPath.Fill = ThemeManager.AccentBrush3;
} else {
_iconPath.Fill = SolidColorBrush.Parse("#00000000");
}
};
}
}

private void UpdateIcon(bool isChecked)
{
if (isChecked) {
_iconPath.Fill = ThemeManager.AccentBrush3;
} else {
_iconPath.Fill = SolidColorBrush.Parse("#00000000");
protected override void OnPointerPressed(PointerPressedEventArgs e) {
base.OnPointerPressed(e);
e.Handled = true;
}

protected override void OnPointerReleased(PointerReleasedEventArgs e) {
base.OnPointerReleased(e);
e.Handled = true;
}
}

}
57 changes: 55 additions & 2 deletions OpenUtau/Controls/TrackHeader.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
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:controls="clr-namespace:OpenUtau.App.Controls"
xmlns:vm="using:OpenUtau.App.ViewModels"
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="104"
x:Class="OpenUtau.App.Controls.TrackHeader" Width="300" Height="104" TrackNo="{Binding TrackNo}">
Expand Down Expand Up @@ -77,18 +78,42 @@
HorizontalOffset="-3" ItemsSource="{Binding PhonemizerMenuItems}">
<ContextMenu.Styles>
<Style Selector="MenuItem">
<Setter Property="Header" Value="{Binding Header}"/>
<Setter Property="Header" Value="{Binding HeaderViewModel}"/>
<Setter Property="Command" Value="{Binding Command}"/>
<Setter Property="CommandParameter" Value="{Binding CommandParameter}"/>
<Setter Property="ItemsSource" Value="{Binding Items}"/>
</Style>
</ContextMenu.Styles>
<ContextMenu.DataTemplates>
<DataTemplate DataType="vm:PhonemizerMenuItemViewModel">
<Grid ColumnDefinitions="24,*,24" MinHeight="24">
<TextBlock Grid.Column="1"
Text="{Binding Header}"
VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"/>
<StackPanel Grid.Column="2"
Orientation="Horizontal"
Spacing="2"
Margin="8,0,0,0"
VerticalAlignment="Center">
<controls:ApplyToAllTracksButton
Command="{Binding SecondaryCommand}"
CommandParameter="{Binding CommandParameter}"/>
</StackPanel>
</Grid>
</DataTemplate>
<DataTemplate DataType="vm:MenuItemViewModel">
<TextBlock Text="{Binding Header}"
VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"/>
</DataTemplate>
</ContextMenu.DataTemplates>
</ContextMenu>
<ContextMenu x:Key="SingersMenuRes" Classes="context" Name="SingersMenu" Placement="BottomEdgeAlignedLeft"
HorizontalOffset="-3" ItemsSource="{Binding SingerMenuItems}">
<ContextMenu.Styles>
<Style Selector="MenuItem">
<Setter Property="Header" Value="{Binding Header}"/>
<Setter Property="Header" Value="{Binding HeaderViewModel}"/>
<Setter Property="Command" Value="{Binding Command}"/>
<Setter Property="CommandParameter" Value="{Binding CommandParameter}"/>
<Setter Property="ItemsSource" Value="{Binding Items}"/>
Expand All @@ -98,6 +123,32 @@
<Setter Property="IsEnabled" Value="{Binding IsEnabled}"/>
</Style>
</ContextMenu.Styles>
<ContextMenu.DataTemplates>
<DataTemplate DataType="vm:SingerMenuItemViewModel">
<Grid ColumnDefinitions="24,*,24" MinHeight="24" >
<controls:FavouriteToggleButton Grid.Column="0"
IsChecked="{Binding IsFavourite}"/>
<TextBlock Grid.Column="1"
Text="{Binding Header}"
VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"/>
<StackPanel Grid.Column="2"
Orientation="Horizontal"
Spacing="2"
Margin="8,0,0,0"
VerticalAlignment="Center">
<controls:ApplyToAllTracksButton
Command="{Binding SecondaryCommand}"
CommandParameter="{Binding CommandParameter}"/>
</StackPanel>
</Grid>
</DataTemplate>
<DataTemplate DataType="vm:MenuItemViewModel">
<TextBlock Text="{Binding Header}"
VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"/>
</DataTemplate>
</ContextMenu.DataTemplates>
</ContextMenu>
</UserControl.Resources>
<Border Margin="1,1,1,1" BorderThickness="1" BorderBrush="{Binding HeaderBorderBrush}"
Expand Down Expand Up @@ -255,6 +306,8 @@
<MenuItem Classes="context" Header="{DynamicResource tracks.trackcolor}" Command="{Binding SelectTrackColor}"/>
<MenuItem Classes="context" Header="{DynamicResource tracks.duplicate}" Command="{Binding Duplicate}"/>
<MenuItem Classes="context" Header="{DynamicResource tracks.duplicatesettings}" Command="{Binding DuplicateSettings}"/>
<MenuItem Classes="context" Header="{DynamicResource tracks.standardizesettings}" Command="{Binding StandardizeSettings}"/>
<MenuItem Classes="context" Header="{DynamicResource tracks.rotateselectedtracksingers}" Command="{Binding RotateSelectedTrackSingers}"/>
<MenuItem Classes="context" Header="{DynamicResource dialogs.voicecolorremapping}" Command="{Binding VoiceColorRemapping}"/>
<Separator/>
<MenuItem Classes="context" Header="{DynamicResource tracks.mixfx}" Command="{Binding OpenMixFxDialog}"/>
Expand Down
1 change: 1 addition & 0 deletions OpenUtau/Controls/TrackHeaderCanvas.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public TrackHeaderCanvas() {
}
}
});

MessageBus.Current.Listen<MixFxChangedNotification>()
.Subscribe(e => {
foreach (var (track, header) in trackHeaders) {
Expand Down
4 changes: 3 additions & 1 deletion OpenUtau/Strings/Strings.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ General
Space: Play</system:String>
<system:String x:Key="tip.notes.zoomx">◀ Scroll here to zoom horizontally ▶</system:String>
<system:String x:Key="tip.notes.zoomy">Scroll here to zoom vertically ▶</system:String>

<system:String x:Key="tracks.duplicate">Duplicate Track</system:String>
<system:String x:Key="tracks.duplicatesettings">Duplicate Track Settings</system:String>
<system:String x:Key="tracks.favorite">Favorites</system:String>
Expand All @@ -793,13 +793,15 @@ General
<system:String x:Key="tracks.opensingers">Open singers location</system:String>
<system:String x:Key="tracks.remove">Remove</system:String>
<system:String x:Key="tracks.rename">Rename track</system:String>
<system:String x:Key="tracks.rotateselectedtracksingers">Rotate singers across selected tracks</system:String>
<system:String x:Key="tracks.selectrenderer">Select Renderer</system:String>
<system:String x:Key="tracks.selectsinger">Select Singer</system:String>
<system:String x:Key="tracks.singerdefault">(Singer default) </system:String>
<system:String x:Key="tracks.solo">Solo</system:String>
<system:String x:Key="tracks.solo.add">Solo additionally (which not removes solo from other tracks)</system:String>
<system:String x:Key="tracks.solo.only">Solo this only (which removes solo from other tracks)</system:String>
<system:String x:Key="tracks.solo.unsoloall">Unsolo all</system:String>
<system:String x:Key="tracks.standardizesettings">Standardize Track Settings</system:String>
<system:String x:Key="tracks.trackcolor">Change track color</system:String>
<system:String x:Key="tracks.tracksettings">Track Settings</system:String>

Expand Down
20 changes: 6 additions & 14 deletions OpenUtau/ViewModels/MenuItemViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Windows.Input;
using Avalonia.Controls.Shapes;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Threading;
using OpenUtau.Core.Ustx;
Expand All @@ -10,13 +9,15 @@ namespace OpenUtau.App.ViewModels {
public class MenuItemViewModel {
public string? Header { get; set; }
public ICommand? Command { get; set; }
public ICommand? SecondaryCommand { get; set; }
public object? CommandParameter { get; set; }
public IList<MenuItemViewModel>? Items { get; set; }
public double Height { get; set; } = 24;
public bool IsChecked { get; set; } = false;
public KeyGesture? InputGesture { get; set; }
public bool IsEnabled { get; set; } = true;
public object? Icon { get; set; }
public virtual object HeaderViewModel => this;

public MenuItemViewModel() { }
public MenuItemViewModel(bool isChecked) {
Expand Down Expand Up @@ -44,19 +45,7 @@ public bool IsFavourite {
}
}
}
private object? _icon;
public new object? Icon {
get {
if(_icon == null) {
if (CommandParameter is USinger) {
_icon = new FavouriteToggleButton() {
[!FavouriteToggleButton.IsCheckedProperty] = new Binding("IsFavourite")
};
}
}
return _icon;
}
}

public string? Location {
get {
if (CommandParameter is USinger singer) {
Expand All @@ -66,4 +55,7 @@ public string? Location {
}
}
}

public class PhonemizerMenuItemViewModel : MenuItemViewModel {
}
}
Loading
Loading