first commit
This commit is contained in:
@@ -0,0 +1,336 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Data.Macros;
|
||||
using ClassicAssist.Data.Macros.Commands;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.Shared.Resources;
|
||||
using ClassicAssist.UO;
|
||||
|
||||
namespace ClassicAssist.UI.ViewModels
|
||||
{
|
||||
public class TimerData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public OffsetStopwatch Value { get; set; }
|
||||
}
|
||||
|
||||
public class ActiveObjectsViewModel : BaseViewModel
|
||||
{
|
||||
private ICommand _clearAllAliasesCommand;
|
||||
private ICommand _clearAllListsCommand;
|
||||
private ICommand _clearIgnoreListCommand;
|
||||
private ObservableCollection<int> _ignoreEntries = new ObservableCollection<int>();
|
||||
private ICommand _refreshAliasesCommand;
|
||||
private ICommand _refreshIgnoreListCommand;
|
||||
private ICommand _refreshListsCommand;
|
||||
private ICommand _refreshTimersCommand;
|
||||
private ICommand _removeAliasCommand;
|
||||
private ICommand _removeIgnoreEntryCommand;
|
||||
private ICommand _removeInstanceAliasCommand;
|
||||
private ICommand _removeListCommand;
|
||||
private AliasEntry _selectedAlias;
|
||||
private int _selectedIgnoreEntry;
|
||||
private InstanceAliasEntry _selectedInstanceAlias;
|
||||
private ListEntry _selectedList;
|
||||
private TimerData _selectedTimer;
|
||||
private ICommand _setAliasCommand;
|
||||
private ObservableCollection<TimerData> _timers = new ObservableCollection<TimerData>();
|
||||
|
||||
public ActiveObjectsViewModel()
|
||||
{
|
||||
RefreshAliases();
|
||||
RefreshInstanceAliases();
|
||||
RefreshLists();
|
||||
RefreshTimers();
|
||||
RefreshIgnoreList();
|
||||
}
|
||||
|
||||
public ObservableCollection<AliasEntry> Aliases { get; set; } = new ObservableCollection<AliasEntry>();
|
||||
|
||||
public ICommand ClearAllAliasesCommand =>
|
||||
_clearAllAliasesCommand ?? ( _clearAllAliasesCommand = new RelayCommand( ClearAllAliases, o => true ) );
|
||||
|
||||
public ICommand ClearAllListsCommand =>
|
||||
_clearAllListsCommand ?? ( _clearAllListsCommand = new RelayCommand( ClearAllLists, o => true ) );
|
||||
|
||||
public ICommand ClearIgnoreListCommand =>
|
||||
_clearIgnoreListCommand ?? ( _clearIgnoreListCommand = new RelayCommand( ClearIgnoreList, o => true ) );
|
||||
|
||||
public ObservableCollection<int> IgnoreEntries
|
||||
{
|
||||
get => _ignoreEntries;
|
||||
set => SetProperty( ref _ignoreEntries, value );
|
||||
}
|
||||
|
||||
public ObservableCollection<InstanceAliasEntry> InstanceAliases { get; set; } =
|
||||
new ObservableCollection<InstanceAliasEntry>();
|
||||
|
||||
public ObservableCollection<ListEntry> Lists { get; set; } = new ObservableCollection<ListEntry>();
|
||||
|
||||
public ICommand RefreshAliasesCommand =>
|
||||
_refreshAliasesCommand ?? ( _refreshAliasesCommand = new RelayCommand( o => RefreshAliases(), o => true ) );
|
||||
|
||||
public ICommand RefreshIgnoreListCommand =>
|
||||
_refreshIgnoreListCommand ??
|
||||
( _refreshIgnoreListCommand = new RelayCommand( o => RefreshIgnoreList(), o => true ) );
|
||||
|
||||
public ICommand RefreshListsCommand =>
|
||||
_refreshListsCommand ?? ( _refreshListsCommand = new RelayCommand( o => RefreshLists(), o => true ) );
|
||||
|
||||
public ICommand RefreshTimersCommand =>
|
||||
_refreshTimersCommand ?? ( _refreshTimersCommand = new RelayCommand( o => RefreshTimers(), o => true ) );
|
||||
|
||||
public ICommand RemoveAliasCommand =>
|
||||
_removeAliasCommand ??
|
||||
( _removeAliasCommand = new RelayCommand( RemoveAlias, o => SelectedAlias != null ) );
|
||||
|
||||
public ICommand RemoveIgnoreEntryCommand =>
|
||||
_removeIgnoreEntryCommand ??
|
||||
( _removeIgnoreEntryCommand = new RelayCommand( RemoveIgnoreEntry, o => true ) );
|
||||
|
||||
public ICommand RemoveInstanceAliasCommand =>
|
||||
_removeInstanceAliasCommand ?? ( _removeInstanceAliasCommand =
|
||||
new RelayCommand( RemoveInstanceAlias, o => SelectedInstanceAlias != null ) );
|
||||
|
||||
public ICommand RemoveListCommand =>
|
||||
_removeListCommand ?? ( _removeListCommand = new RelayCommand( RemoveList, o => SelectedList != null ) );
|
||||
|
||||
public AliasEntry SelectedAlias
|
||||
{
|
||||
get => _selectedAlias;
|
||||
set => SetProperty( ref _selectedAlias, value );
|
||||
}
|
||||
|
||||
public int SelectedIgnoreEntry
|
||||
{
|
||||
get => _selectedIgnoreEntry;
|
||||
set => SetProperty( ref _selectedIgnoreEntry, value );
|
||||
}
|
||||
|
||||
public InstanceAliasEntry SelectedInstanceAlias
|
||||
{
|
||||
get => _selectedInstanceAlias;
|
||||
set => SetProperty( ref _selectedInstanceAlias, value );
|
||||
}
|
||||
|
||||
public ListEntry SelectedList
|
||||
{
|
||||
get => _selectedList;
|
||||
set => SetProperty( ref _selectedList, value );
|
||||
}
|
||||
|
||||
public TimerData SelectedTimer
|
||||
{
|
||||
get => _selectedTimer;
|
||||
set => SetProperty( ref _selectedTimer, value );
|
||||
}
|
||||
|
||||
public ICommand SetAliasCommand =>
|
||||
_setAliasCommand ?? ( _setAliasCommand = new RelayCommandAsync( SetAlias, o => o != null ) );
|
||||
|
||||
public ObservableCollection<TimerData> Timers
|
||||
{
|
||||
get => _timers;
|
||||
set => SetProperty( ref _timers, value );
|
||||
}
|
||||
|
||||
private void RefreshInstanceAliases()
|
||||
{
|
||||
InstanceAliases.Clear();
|
||||
|
||||
MacroManager manager = MacroManager.GetInstance();
|
||||
|
||||
foreach ( MacroEntry entry in manager.Items )
|
||||
{
|
||||
foreach ( KeyValuePair<string, int> alias in entry.Aliases )
|
||||
{
|
||||
InstanceAliases.Add( new InstanceAliasEntry
|
||||
{
|
||||
Macro = entry, Name = alias.Key, Serial = alias.Value
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveInstanceAlias( object obj )
|
||||
{
|
||||
if ( !( obj is InstanceAliasEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
entry.Macro.Aliases.Remove( entry.Name );
|
||||
|
||||
RefreshInstanceAliases();
|
||||
}
|
||||
|
||||
private void ClearIgnoreList( object obj )
|
||||
{
|
||||
ObjectCommands.ClearIgnoreList();
|
||||
|
||||
RefreshIgnoreList();
|
||||
}
|
||||
|
||||
private void RemoveIgnoreEntry( object obj )
|
||||
{
|
||||
if ( !( obj is int serial ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectCommands.IgnoreList.Remove( serial );
|
||||
|
||||
RefreshIgnoreList();
|
||||
}
|
||||
|
||||
private void RefreshIgnoreList()
|
||||
{
|
||||
IgnoreEntries.Clear();
|
||||
|
||||
foreach ( int serial in ObjectCommands.IgnoreList )
|
||||
{
|
||||
IgnoreEntries.Add( serial );
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshTimers()
|
||||
{
|
||||
Dictionary<string, OffsetStopwatch> timers = TimerCommands.GetAllTimers();
|
||||
|
||||
if ( timers == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Timers.Clear();
|
||||
|
||||
foreach ( KeyValuePair<string, OffsetStopwatch> timer in timers )
|
||||
{
|
||||
Timers.Add( new TimerData { Name = timer.Key, Value = timer.Value } );
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveList( object obj )
|
||||
{
|
||||
if ( !( obj is ListEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ListCommands.RemoveList( entry.Name );
|
||||
Lists.Remove( entry );
|
||||
}
|
||||
|
||||
private void ClearAllLists( object obj )
|
||||
{
|
||||
string[] lists = ListCommands.GetAllLists().Select( l => l.Key ).ToArray();
|
||||
|
||||
for ( int i = 0; i < lists.Count(); i++ )
|
||||
{
|
||||
ListCommands.RemoveList( lists[i] );
|
||||
}
|
||||
|
||||
RefreshLists();
|
||||
}
|
||||
|
||||
private void RefreshLists()
|
||||
{
|
||||
Lists.Clear();
|
||||
|
||||
foreach ( KeyValuePair<string, List<int>> list in ListCommands.GetAllLists() )
|
||||
{
|
||||
Lists.Add( new ListEntry { Name = list.Key, Serials = list.Value.ToArray() } );
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveAlias( object obj )
|
||||
{
|
||||
if ( !( obj is AliasEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AliasCommands.UnsetAlias( entry.Name );
|
||||
Aliases.Remove( entry );
|
||||
}
|
||||
|
||||
public void RefreshAliases()
|
||||
{
|
||||
Aliases.Clear();
|
||||
|
||||
foreach ( KeyValuePair<string, int> alias in AliasCommands.GetAllAliases() )
|
||||
{
|
||||
Aliases.AddSorted( new AliasEntry { Name = alias.Key, Serial = alias.Value } );
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearAllAliases( object obj )
|
||||
{
|
||||
string[] aliases = AliasCommands.GetAllAliases().Select( a => a.Key ).ToArray();
|
||||
|
||||
// ReSharper disable once ForCanBeConvertedToForeach
|
||||
for ( int i = 0; i < aliases.Length; i++ )
|
||||
{
|
||||
AliasCommands.UnsetAlias( aliases[i] );
|
||||
}
|
||||
|
||||
RefreshAliases();
|
||||
}
|
||||
|
||||
private static async Task SetAlias( object arg )
|
||||
{
|
||||
if ( !( arg is AliasEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int serial =
|
||||
await Shared.UO.Commands.GetTargeSerialAsync( string.Format( Strings.Target_object___0_____, entry.Name ) );
|
||||
|
||||
if ( serial == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AliasCommands.SetAlias( entry.Name, serial );
|
||||
}
|
||||
|
||||
public class InstanceAliasEntry
|
||||
{
|
||||
public MacroEntry Macro { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int Serial { get; set; }
|
||||
}
|
||||
|
||||
public class AliasEntry : IComparable<AliasEntry>
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Serial { get; set; }
|
||||
|
||||
public int CompareTo( AliasEntry other )
|
||||
{
|
||||
if ( ReferenceEquals( this, other ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ReferenceEquals( null, other ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return string.Compare( Name, other.Name, StringComparison.InvariantCultureIgnoreCase );
|
||||
}
|
||||
}
|
||||
|
||||
public class ListEntry
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int[] Serials { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using ClassicAssist.Shared;
|
||||
using ClassicAssist.Data.Chat;
|
||||
using ClassicAssist.Data.Macros.Commands;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.Shared.Resources;
|
||||
using ClassicAssist.Shared.UO;
|
||||
|
||||
namespace ClassicAssist.UI.ViewModels
|
||||
{
|
||||
public class ChatViewModel : BaseViewModel
|
||||
{
|
||||
private readonly SolidColorBrush _defaultBrush =
|
||||
new SolidColorBrush( Color.FromArgb( 0xff, 0xcc, 0xcc, 0xcc ) );
|
||||
|
||||
private readonly SolidColorBrush _enemyBrush = new SolidColorBrush( Colors.Orange );
|
||||
|
||||
private readonly SolidColorBrush _friendBrush = new SolidColorBrush( Colors.LimeGreen );
|
||||
|
||||
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
|
||||
private readonly ChatManager _manager;
|
||||
private ICommand _changeChannelCommand;
|
||||
private ObservableCollection<string> _channels = new ObservableCollection<string>();
|
||||
private string _currentChannel;
|
||||
private ObservableCollection<ChatMessage> _messages = new ObservableCollection<ChatMessage>();
|
||||
private string _selectedChannel;
|
||||
private string _title;
|
||||
private ICommand _toggleOptionCommand;
|
||||
private bool _topmost = true;
|
||||
private ObservableCollection<ChatUser> _users = new ObservableCollection<ChatUser>();
|
||||
|
||||
public ChatViewModel()
|
||||
{
|
||||
_manager = ChatManager.GetInstance();
|
||||
|
||||
_manager.UserJoinedEvent += OnUserJoined;
|
||||
_manager.UserLeftEvent += OnUserLeft;
|
||||
_manager.ClearUsersEvent += OnClearUsers;
|
||||
_manager.JoinedChatChannelEvent += OnJoinedChatChannel;
|
||||
_manager.LeftChatChannelEvent += OnLeftChatChannel;
|
||||
Engine.DisconnectedEvent += () => OnLeftChatChannel( string.Empty );
|
||||
_manager.ChannelCreatedEvent += OnChannelCreated;
|
||||
_manager.ChannelRemovedEvent += OnChannelRemoved;
|
||||
|
||||
if ( !string.IsNullOrEmpty( _manager.CurrentChannel ) )
|
||||
{
|
||||
OnJoinedChatChannel( _manager.CurrentChannel );
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateTitle( Strings.Chat );
|
||||
}
|
||||
|
||||
foreach ( string user in _manager.Users )
|
||||
{
|
||||
//TODO2
|
||||
Users.AddSorted( new ChatUser { Username = user/*, Colour = GetUserColour( user )*/ } );
|
||||
}
|
||||
|
||||
foreach ( string channel in _manager.Channels )
|
||||
{
|
||||
OnChannelCreated( channel );
|
||||
}
|
||||
|
||||
//foreach ( ChatMessage message in _manager.Messages )
|
||||
//{
|
||||
// Messages.Add( message );
|
||||
//}
|
||||
|
||||
_manager.ChatMessageEvent += OnChatMessage;
|
||||
}
|
||||
|
||||
public ICommand ChangeChannelCommand =>
|
||||
_changeChannelCommand ??
|
||||
( _changeChannelCommand = new RelayCommand( ChangeChannel, o => Channels.Count != 0 ) );
|
||||
|
||||
public ObservableCollection<string> Channels
|
||||
{
|
||||
get => _channels;
|
||||
set => SetProperty( ref _channels, value );
|
||||
}
|
||||
|
||||
public string CurrentChannel
|
||||
{
|
||||
get => _currentChannel;
|
||||
set => SetProperty( ref _currentChannel, value );
|
||||
}
|
||||
|
||||
public ObservableCollection<ChatMessage> Messages
|
||||
{
|
||||
get => _messages;
|
||||
set => SetProperty( ref _messages, value );
|
||||
}
|
||||
|
||||
public string SelectedChannel
|
||||
{
|
||||
get => _selectedChannel;
|
||||
set => SetProperty( ref _selectedChannel, value );
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => _title;
|
||||
set => SetProperty( ref _title, value );
|
||||
}
|
||||
|
||||
public ICommand ToggleOptionCommand =>
|
||||
_toggleOptionCommand ?? ( _toggleOptionCommand = new RelayCommand( ToggleOption, o => true ) );
|
||||
|
||||
public bool Topmost
|
||||
{
|
||||
get => _topmost;
|
||||
set => SetProperty( ref _topmost, value );
|
||||
}
|
||||
|
||||
public ObservableCollection<ChatUser> Users
|
||||
{
|
||||
get => _users;
|
||||
set => SetProperty( ref _users, value );
|
||||
}
|
||||
|
||||
private static void ToggleOption( object obj )
|
||||
{
|
||||
}
|
||||
|
||||
private void ChangeChannel( object obj )
|
||||
{
|
||||
if ( !( obj is string channel ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_dispatcher.Invoke( () => { Commands.JoinChatChannel( channel ); } );
|
||||
}
|
||||
|
||||
private void OnChannelRemoved( string channel )
|
||||
{
|
||||
_dispatcher.Invoke( () => { Channels.Remove( channel ); } );
|
||||
}
|
||||
|
||||
private void OnChannelCreated( string channel )
|
||||
{
|
||||
_dispatcher.Invoke( () => { Channels.Add( channel ); } );
|
||||
}
|
||||
|
||||
private void OnChatMessage( string username, string channel, string message )
|
||||
{
|
||||
_dispatcher.Invoke( () => Messages.Add( new ChatMessage
|
||||
{
|
||||
//TODO2
|
||||
Username = username,
|
||||
Channel = channel,
|
||||
Text = message/*, Colour = GetUserColour( username )*/
|
||||
} ) );
|
||||
}
|
||||
|
||||
private void OnLeftChatChannel( string channel )
|
||||
{
|
||||
_dispatcher.Invoke( () =>
|
||||
{
|
||||
Users.Clear();
|
||||
CurrentChannel = null;
|
||||
SelectedChannel = null;
|
||||
UpdateTitle( string.Empty );
|
||||
} );
|
||||
}
|
||||
|
||||
private void UpdateTitle( string channel )
|
||||
{
|
||||
if ( string.IsNullOrEmpty( channel ) )
|
||||
{
|
||||
Title = Strings.Chat;
|
||||
return;
|
||||
}
|
||||
|
||||
Title = $"{Strings.Chat} - {channel}";
|
||||
}
|
||||
|
||||
private void OnJoinedChatChannel( string channel )
|
||||
{
|
||||
_dispatcher.Invoke( () =>
|
||||
{
|
||||
CurrentChannel = channel;
|
||||
SelectedChannel = channel;
|
||||
UpdateTitle( channel );
|
||||
} );
|
||||
}
|
||||
|
||||
private void OnClearUsers()
|
||||
{
|
||||
_dispatcher.Invoke( () => Users.Clear() );
|
||||
}
|
||||
|
||||
private void OnUserLeft( string username, string channel )
|
||||
{
|
||||
_dispatcher.Invoke( () => { Users.Remove( Users.FirstOrDefault( u => u.Username == username ) ); } );
|
||||
}
|
||||
|
||||
private void OnUserJoined( string username, string channel )
|
||||
{
|
||||
_dispatcher.Invoke( () =>
|
||||
{
|
||||
//TODO2
|
||||
ChatUser user = new ChatUser { Username = username/*, Colour = GetUserColour( username )*/ };
|
||||
|
||||
Users.AddSorted( user );
|
||||
} );
|
||||
}
|
||||
|
||||
private SolidColorBrush GetUserColour( string username )
|
||||
{
|
||||
try
|
||||
{
|
||||
Match matches = Regex.Match( username, @"<(.*)>\s*(.*)" );
|
||||
|
||||
if ( !matches.Success )
|
||||
{
|
||||
return _defaultBrush;
|
||||
}
|
||||
|
||||
int serial = int.Parse( matches.Groups[1].Value );
|
||||
|
||||
if ( serial == Engine.Player?.Serial || MobileCommands.InFriendList( serial ) )
|
||||
{
|
||||
return _friendBrush;
|
||||
}
|
||||
|
||||
return serial == AliasCommands.GetAlias( "enemy" ) ? _enemyBrush : _defaultBrush;
|
||||
}
|
||||
catch ( Exception )
|
||||
{
|
||||
return _defaultBrush;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Shared;
|
||||
using ClassicAssist.Data;
|
||||
using ClassicAssist.Shared.Resources;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace ClassicAssist.UI.ViewModels.Debug
|
||||
{
|
||||
public class DebugAssembliesViewModel : BaseViewModel
|
||||
{
|
||||
private ObservableCollection<Assembly> _items = new ObservableCollection<Assembly>();
|
||||
private ICommand _loadCommand;
|
||||
private ICommand _removeCommand;
|
||||
private ICommand _saveCommand;
|
||||
|
||||
public DebugAssembliesViewModel()
|
||||
{
|
||||
if ( AssistantOptions.Assemblies == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( string assemblyName in AssistantOptions.Assemblies )
|
||||
{
|
||||
Assembly assembly = LoadAssembly( assemblyName );
|
||||
|
||||
if ( assembly != null )
|
||||
{
|
||||
Items.Add( assembly );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<Assembly> Items
|
||||
{
|
||||
get => _items;
|
||||
set => SetProperty( ref _items, value );
|
||||
}
|
||||
|
||||
public ICommand LoadCommand => _loadCommand ?? ( _loadCommand = new RelayCommandAsync( Load, o => true ) );
|
||||
|
||||
public ICommand RemoveCommand =>
|
||||
_removeCommand ?? ( _removeCommand = new RelayCommandAsync( Remove, o => true ) );
|
||||
|
||||
public ICommand SaveCommand => _saveCommand ?? ( _saveCommand = new RelayCommandAsync( Save, o => true ) );
|
||||
|
||||
public Assembly SelectedItem { get; set; }
|
||||
|
||||
private async Task Load( object arg )
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog
|
||||
{
|
||||
InitialDirectory = Engine.StartupPath, Filter = "DLL Files|*.dll", CheckFileExists = true
|
||||
};
|
||||
|
||||
bool? result = ofd.ShowDialog();
|
||||
|
||||
if ( result.HasValue && result.Value )
|
||||
{
|
||||
try
|
||||
{
|
||||
Assembly assembly = LoadAssembly( ofd.FileName );
|
||||
|
||||
if ( assembly != null )
|
||||
{
|
||||
await _dispatcher.InvokeAsync( () => Items.Add( assembly ) );
|
||||
}
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
MessageBox.Show( string.Format( Strings.Error_loading_assembly___0_, e.Message ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Assembly LoadAssembly( string fileName )
|
||||
{
|
||||
if ( !File.Exists( fileName ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Assembly.LoadFile( fileName );
|
||||
}
|
||||
|
||||
private async Task Remove( object arg )
|
||||
{
|
||||
if ( !( arg is Assembly assembly ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await _dispatcher.InvokeAsync( () => Items.Remove( assembly ) );
|
||||
}
|
||||
|
||||
private async Task Save( object arg )
|
||||
{
|
||||
AssistantOptions.Assemblies = Items.Select( a => a.Location ).ToArray();
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,620 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media.Imaging;
|
||||
using ClassicAssist.Shared;
|
||||
using ClassicAssist.Data.Autoloot;
|
||||
using ClassicAssist.Data.Macros.Commands;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.Shared.Resources;
|
||||
using ClassicAssist.UI.Models;
|
||||
using ClassicAssist.UI.Views;
|
||||
using ClassicAssist.UO;
|
||||
using ClassicAssist.UO.Data;
|
||||
using ClassicAssist.UO.Network;
|
||||
using ClassicAssist.UO.Network.Packets;
|
||||
using ClassicAssist.UO.Objects;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ClassicAssist.UI.ViewModels
|
||||
{
|
||||
public class EntityCollectionViewerViewModel : BaseViewModel
|
||||
{
|
||||
private ICommand _applyFiltersCommand;
|
||||
private ICommand _cancelActionCommand;
|
||||
private CancellationTokenSource _cancellationToken;
|
||||
private ICommand _changeSortStyleCommand;
|
||||
private ItemCollection _collection;
|
||||
private ICommand _contextContextMenuRequestCommand;
|
||||
private ICommand _contextMoveToBackpackCommand;
|
||||
private ICommand _contextMoveToContainerCommand;
|
||||
private ICommand _contextUseItemCommand;
|
||||
private ObservableCollection<EntityCollectionData> _entities;
|
||||
private ICommand _equipItemCommand;
|
||||
private IEnumerable<EntityCollectionFilter> _filters;
|
||||
private bool _isPerformingAction;
|
||||
private ICommand _itemDoubleClickCommand;
|
||||
private ICommand _refreshCommand;
|
||||
|
||||
private ObservableCollection<EntityCollectionData> _selectedItems =
|
||||
new ObservableCollection<EntityCollectionData>();
|
||||
|
||||
private bool _showProperties;
|
||||
|
||||
private IComparer<Entity> _sorter = new IDThenSerialComparer();
|
||||
private string _statusLabel;
|
||||
private ICommand _togglePropertiesCommand;
|
||||
private bool _topmost;
|
||||
|
||||
public EntityCollectionViewerViewModel()
|
||||
{
|
||||
_collection = new ItemCollection( 0 );
|
||||
|
||||
for ( int i = 0; i < 5; i++ )
|
||||
{
|
||||
_collection.Add( new Item( i + 1 ) { ID = 100 + i } );
|
||||
}
|
||||
|
||||
_collection.Add( new Item( 6 ) { ID = 106, Hue = 2413 } );
|
||||
|
||||
Entities = new ObservableCollection<EntityCollectionData>( _collection.ToEntityCollectionData( _sorter ) );
|
||||
}
|
||||
|
||||
public EntityCollectionViewerViewModel( ItemCollection collection )
|
||||
{
|
||||
_collection = collection;
|
||||
|
||||
Entities = new ObservableCollection<EntityCollectionData>( collection.ToEntityCollectionData( _sorter ) );
|
||||
|
||||
SelectedItems.CollectionChanged += ( sender, args ) =>
|
||||
{
|
||||
if ( !( sender is ObservableCollection<EntityCollectionData> ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateStatusLabel();
|
||||
};
|
||||
|
||||
UpdateStatusLabel();
|
||||
}
|
||||
|
||||
public ICommand ApplyFiltersCommand =>
|
||||
_applyFiltersCommand ?? ( _applyFiltersCommand = new RelayCommand( ApplyFilters, o => true ) );
|
||||
|
||||
public ICommand CancelActionCommand =>
|
||||
_cancelActionCommand ?? ( _cancelActionCommand = new RelayCommandAsync( CancelAction,
|
||||
o => _cancellationToken != null ) );
|
||||
|
||||
public ICommand ChangeSortStyleCommand =>
|
||||
_changeSortStyleCommand ?? ( _changeSortStyleCommand = new RelayCommand( ChangeSortStyle, o => true ) );
|
||||
|
||||
public ICommand ContextContextMenuRequestCommand =>
|
||||
_contextContextMenuRequestCommand ?? ( _contextContextMenuRequestCommand =
|
||||
new RelayCommand( ContextMenuRequest, o => SelectedItems.Count > 0 ) );
|
||||
|
||||
public ICommand ContextMoveToBackpackCommand =>
|
||||
_contextMoveToBackpackCommand ?? ( _contextMoveToBackpackCommand =
|
||||
new RelayCommandAsync( ContextMoveToBackpack, o => SelectedItems != null && !IsPerformingAction ) );
|
||||
|
||||
public ICommand ContextMoveToContainerCommand =>
|
||||
_contextMoveToContainerCommand ?? ( _contextMoveToContainerCommand =
|
||||
new RelayCommandAsync( ContextMoveToContainer, o => SelectedItems != null && !IsPerformingAction ) );
|
||||
|
||||
public ICommand ContextUseItemCommand =>
|
||||
_contextUseItemCommand ?? ( _contextUseItemCommand =
|
||||
new RelayCommandAsync( ContextUseItem, o => SelectedItems != null && !IsPerformingAction ) );
|
||||
|
||||
public ObservableCollection<EntityCollectionData> Entities
|
||||
{
|
||||
get => _entities;
|
||||
set => SetProperty( ref _entities, value );
|
||||
}
|
||||
|
||||
public ICommand EquipItemCommand =>
|
||||
_equipItemCommand ?? ( _equipItemCommand = new RelayCommand( EquipItem, o => SelectedItems != null ) );
|
||||
|
||||
public bool IsPerformingAction
|
||||
{
|
||||
get => _isPerformingAction;
|
||||
set => SetProperty( ref _isPerformingAction, value );
|
||||
}
|
||||
|
||||
public ICommand ItemDoubleClickCommand =>
|
||||
_itemDoubleClickCommand ?? ( _itemDoubleClickCommand = new RelayCommand( ItemDoubleClick, o => true ) );
|
||||
|
||||
public static Lazy<Dictionary<int, int>> MountIDEntries { get; set; } =
|
||||
new Lazy<Dictionary<int, int>>( LoadMountIDEntries );
|
||||
|
||||
public ICommand RefreshCommand =>
|
||||
_refreshCommand ?? ( _refreshCommand = new RelayCommand( Refresh, o => _collection?.Serial != 0 ) );
|
||||
|
||||
public ObservableCollection<EntityCollectionData> SelectedItems
|
||||
{
|
||||
get => _selectedItems;
|
||||
set => SetProperty( ref _selectedItems, value );
|
||||
}
|
||||
|
||||
public bool ShowProperties
|
||||
{
|
||||
get => _showProperties;
|
||||
set => SetProperty( ref _showProperties, value );
|
||||
}
|
||||
|
||||
public static Lazy<int[]> ShrinkEntries { get; set; } = new Lazy<int[]>( LoadShrinkTable );
|
||||
|
||||
public string StatusLabel
|
||||
{
|
||||
get => _statusLabel;
|
||||
set => SetProperty( ref _statusLabel, value );
|
||||
}
|
||||
|
||||
public ICommand TogglePropertiesCommand =>
|
||||
_togglePropertiesCommand ?? ( _togglePropertiesCommand = new RelayCommand( ToggleProperties, o => true ) );
|
||||
|
||||
public bool Topmost
|
||||
{
|
||||
get => _topmost;
|
||||
set => SetProperty( ref _topmost, value );
|
||||
}
|
||||
|
||||
private static Dictionary<int, int> LoadMountIDEntries()
|
||||
{
|
||||
Dictionary<int, int> entries = new Dictionary<int, int>();
|
||||
|
||||
string fileName = Path.Combine( Engine.StartupPath, "Data", "MountID.json" );
|
||||
|
||||
if ( !File.Exists( fileName ) )
|
||||
{
|
||||
return entries;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
entries = JsonConvert.DeserializeObject<Dictionary<int, int>>( File.ReadAllText( fileName ) );
|
||||
}
|
||||
catch ( Exception )
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
private static int[] LoadShrinkTable()
|
||||
{
|
||||
int[] table = new int[ushort.MaxValue];
|
||||
|
||||
using ( StringReader reader = new StringReader( Properties.Resources.Shrink ) )
|
||||
{
|
||||
string line;
|
||||
|
||||
while ( ( line = reader.ReadLine() ) != null )
|
||||
{
|
||||
if ( line.Length == 0 || line.StartsWith( "#" ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] split = line.Split( '\t' );
|
||||
|
||||
if ( split.Length < 2 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int body = Convert.ToInt32( split[0] );
|
||||
int item = Convert.ToInt32( split[1], 16 );
|
||||
|
||||
if ( body >= 0 && body < table.Length )
|
||||
{
|
||||
table[body] = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
private void EquipItem( object obj )
|
||||
{
|
||||
foreach ( EntityCollectionData item in SelectedItems )
|
||||
{
|
||||
StaticTile td = TileData.GetStaticTile( item.Entity.ID );
|
||||
|
||||
if ( !td.Flags.HasFlag( TileFlags.Wearable ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Layer layer = (Layer) td.Quality;
|
||||
|
||||
if ( layer == Layer.Invalid )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( item.Entity is Item equipItem )
|
||||
{
|
||||
Shared.UO.Commands.EquipItem( equipItem, layer );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyFilters( object obj )
|
||||
{
|
||||
if ( !( obj is IEnumerable<EntityCollectionFilter> list ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_filters = list;
|
||||
|
||||
Entities.Clear();
|
||||
|
||||
Entities = new ObservableCollection<EntityCollectionData>( _collection.Filter( _filters )
|
||||
.ToEntityCollectionData( _sorter ) );
|
||||
|
||||
UpdateStatusLabel();
|
||||
}
|
||||
|
||||
private void ChangeSortStyle( object obj )
|
||||
{
|
||||
if ( !( obj is EntityCollectionSortStyle val ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( val )
|
||||
{
|
||||
case EntityCollectionSortStyle.Name:
|
||||
_sorter = new NameThenSerialComparer();
|
||||
|
||||
break;
|
||||
|
||||
case EntityCollectionSortStyle.Serial:
|
||||
_sorter = new SerialComparer();
|
||||
|
||||
break;
|
||||
|
||||
case EntityCollectionSortStyle.Hue:
|
||||
_sorter = new HueThenAmountComparer();
|
||||
|
||||
break;
|
||||
|
||||
case EntityCollectionSortStyle.ID:
|
||||
_sorter = new IDThenSerialComparer();
|
||||
|
||||
break;
|
||||
|
||||
case EntityCollectionSortStyle.Quantity:
|
||||
_sorter = new QuantityThenSerialComparer();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
Entities = new ObservableCollection<EntityCollectionData>( _collection.ToEntityCollectionData( _sorter ) );
|
||||
}
|
||||
|
||||
private void UpdateStatusLabel()
|
||||
{
|
||||
StatusLabel = string.Format( Strings._0__items___1__selected___2__total_amount, Entities.Count,
|
||||
SelectedItems?.Count ?? 0,
|
||||
SelectedItems?.Select( i => i.Entity ).Where( i => i is Item ).Cast<Item>().Sum( i => i.Count ) );
|
||||
}
|
||||
|
||||
private void Refresh( object obj )
|
||||
{
|
||||
ItemCollection collection = new ItemCollection( _collection.Serial );
|
||||
|
||||
Entity entity = Engine.Items.GetItem( _collection.Serial ) ??
|
||||
(Entity) Engine.Mobiles.GetMobile( _collection.Serial );
|
||||
|
||||
if ( entity == null )
|
||||
{
|
||||
Shared.UO.Commands.SystemMessage( Strings.Cannot_find_item___ );
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( entity )
|
||||
{
|
||||
case Item item:
|
||||
if ( item.Container == null )
|
||||
{
|
||||
Shared.UO.Commands.WaitForContainerContents( item.Serial, 1000 );
|
||||
}
|
||||
|
||||
collection = item.Container;
|
||||
break;
|
||||
case Mobile mobile:
|
||||
collection = new ItemCollection( entity.Serial ) { mobile.GetEquippedItems() };
|
||||
break;
|
||||
}
|
||||
|
||||
if ( collection == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_collection = collection;
|
||||
|
||||
Entities = new ObservableCollection<EntityCollectionData>( _collection.ToEntityCollectionData( _sorter ) );
|
||||
}
|
||||
|
||||
private async Task ContextUseItem( object arg )
|
||||
{
|
||||
_cancellationToken = new CancellationTokenSource();
|
||||
|
||||
try
|
||||
{
|
||||
IsPerformingAction = true;
|
||||
|
||||
await Task.Run( () =>
|
||||
{
|
||||
int[] items = SelectedItems.Select( i => i.Entity.Serial ).ToArray();
|
||||
|
||||
foreach ( int item in items )
|
||||
{
|
||||
ObjectCommands.UseObject( item );
|
||||
|
||||
if ( _cancellationToken.Token.IsCancellationRequested )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsPerformingAction = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ContextMoveToContainer( object arg )
|
||||
{
|
||||
_cancellationToken = new CancellationTokenSource();
|
||||
|
||||
int serial = 0;
|
||||
|
||||
if ( arg is int s )
|
||||
{
|
||||
serial = s;
|
||||
}
|
||||
|
||||
if ( serial == 0 )
|
||||
{
|
||||
serial = await Shared.UO.Commands.GetTargeSerialAsync( Strings.Target_container___ );
|
||||
}
|
||||
|
||||
if ( serial == 0 )
|
||||
{
|
||||
Shared.UO.Commands.SystemMessage( Strings.Invalid_container___ );
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IsPerformingAction = true;
|
||||
|
||||
int[] items = SelectedItems.Select( i => i.Entity.Serial ).ToArray();
|
||||
|
||||
foreach ( int item in items )
|
||||
{
|
||||
await ActionPacketQueue.EnqueueDragDrop( item, -1, serial );
|
||||
|
||||
if ( _cancellationToken.Token.IsCancellationRequested )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsPerformingAction = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ContextMoveToBackpack( object arg )
|
||||
{
|
||||
await ContextMoveToContainer( Engine.Player.Backpack.Serial );
|
||||
}
|
||||
|
||||
private async Task CancelAction( object arg )
|
||||
{
|
||||
_cancellationToken?.Cancel();
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void ToggleProperties( object obj )
|
||||
{
|
||||
if ( !( obj is bool showProperties ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShowProperties = showProperties;
|
||||
}
|
||||
|
||||
private static void ItemDoubleClick( object obj )
|
||||
{
|
||||
if ( !( obj is EntityCollectionData ecd ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectInspectorWindow window =
|
||||
new ObjectInspectorWindow { DataContext = new ObjectInspectorViewModel( ecd.Entity ) };
|
||||
|
||||
window.ShowDialog();
|
||||
}
|
||||
|
||||
private void ContextMenuRequest( object obj )
|
||||
{
|
||||
int[] items = SelectedItems.Select( i => i.Entity.Serial ).ToArray();
|
||||
|
||||
foreach ( int serial in items )
|
||||
{
|
||||
Engine.SendPacketToServer( new ContextMenuRequest( serial ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class EntityCollectionData
|
||||
{
|
||||
public BitmapSource Bitmap
|
||||
{
|
||||
get
|
||||
{
|
||||
BitmapSource result = Art.GetStatic( Entity.ID, Entity.Hue ).ToBitmapSource();
|
||||
|
||||
if ( !( Entity is Item item ) || item.Layer != Layer.Mount )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if ( !( EntityCollectionViewerViewModel.MountIDEntries.Value?.ContainsKey( Entity.ID ) ?? false ) )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
int id = (int) EntityCollectionViewerViewModel.MountIDEntries.Value?[Entity.ID];
|
||||
|
||||
result = Art.GetStatic( id, Entity.Hue ).ToBitmapSource();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public Entity Entity { get; set; }
|
||||
public string FullName => GetProperties( Entity );
|
||||
public string Name => GetName( Entity );
|
||||
|
||||
private static string GetProperties( Entity entity )
|
||||
{
|
||||
return entity.Properties == null
|
||||
? GetName( entity )
|
||||
: entity.Properties.Aggregate( "",
|
||||
( current, entityProperty ) => current + entityProperty.Text + "\r\n" ).TrimTrailingNewLine();
|
||||
}
|
||||
|
||||
private static string GetName( Entity entity )
|
||||
{
|
||||
if ( !( entity is Item item ) || item.Layer != Layer.Mount )
|
||||
{
|
||||
return entity.Name;
|
||||
}
|
||||
|
||||
if ( !( EntityCollectionViewerViewModel.MountIDEntries.Value?.ContainsKey( entity.ID ) ?? false ) )
|
||||
{
|
||||
return entity.Name;
|
||||
}
|
||||
|
||||
int id = (int) EntityCollectionViewerViewModel.MountIDEntries.Value?[entity.ID];
|
||||
|
||||
if ( id == 0 )
|
||||
{
|
||||
return entity.Name;
|
||||
}
|
||||
|
||||
StaticTile tileData = TileData.GetStaticTile( id );
|
||||
|
||||
return !string.IsNullOrEmpty( tileData.Name ) ? tileData.Name : entity.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExtensionMethods
|
||||
{
|
||||
public static ItemCollection Filter( this ItemCollection collection,
|
||||
IEnumerable<EntityCollectionFilter> filterList )
|
||||
{
|
||||
ItemCollection newCollection = new ItemCollection( collection.Serial );
|
||||
|
||||
IEnumerable<Predicate<Item>> predicates = FiltersToPredicates( filterList ).ToList();
|
||||
|
||||
if ( !predicates.Any() )
|
||||
{
|
||||
return collection;
|
||||
}
|
||||
|
||||
foreach ( Item item in collection.GetItems() )
|
||||
{
|
||||
if ( predicates.All( p => p( item ) ) )
|
||||
{
|
||||
newCollection.Add( item );
|
||||
}
|
||||
}
|
||||
|
||||
return newCollection;
|
||||
}
|
||||
|
||||
private static IEnumerable<Predicate<Item>> FiltersToPredicates(
|
||||
IEnumerable<EntityCollectionFilter> filterList )
|
||||
{
|
||||
List<Predicate<Item>> predicates = new List<Predicate<Item>>();
|
||||
|
||||
foreach ( EntityCollectionFilter filter in filterList )
|
||||
{
|
||||
PropertyEntry constraint = filter.Constraint;
|
||||
|
||||
switch ( constraint.ConstraintType )
|
||||
{
|
||||
case PropertyType.Properties:
|
||||
{
|
||||
predicates.Add( i => i.Properties != null && constraint.Clilocs.Any( cliloc =>
|
||||
i.Properties.Any( p => AutolootHelpers.MatchProperty( p, cliloc,
|
||||
constraint, filter.Operator, filter.Value ) ) ) );
|
||||
|
||||
break;
|
||||
}
|
||||
case PropertyType.Object:
|
||||
{
|
||||
predicates.Add( i =>
|
||||
AutolootHelpers.ItemHasObjectProperty( i, constraint.Name ) && AutolootHelpers.Operation(
|
||||
filter.Operator, AutolootHelpers.GetItemObjectPropertyValue<int>( i, constraint.Name ),
|
||||
filter.Value ) );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
return predicates;
|
||||
}
|
||||
|
||||
public static string TrimTrailingNewLine( this string s )
|
||||
{
|
||||
return s.TrimEnd( '\r', '\n' );
|
||||
}
|
||||
|
||||
public static List<EntityCollectionData> ToEntityCollectionData( this ItemCollection itemCollection,
|
||||
IComparer<Entity> comparer )
|
||||
{
|
||||
if ( itemCollection == null )
|
||||
{
|
||||
return new List<EntityCollectionData>();
|
||||
}
|
||||
|
||||
Item[] items = itemCollection.GetItems();
|
||||
|
||||
IEnumerable<Item> noNames = items.Where( i => string.IsNullOrEmpty( i.Name ) );
|
||||
|
||||
foreach ( Item item in noNames )
|
||||
{
|
||||
item.Name = $"0x{item.Serial:x8}";
|
||||
}
|
||||
|
||||
return items.OrderBy( i => i, comparer ).Select( item => new EntityCollectionData { Entity = item } )
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Data.Filters;
|
||||
using ClassicAssist.UO.Data;
|
||||
|
||||
namespace ClassicAssist.UI.ViewModels.Filters
|
||||
{
|
||||
public class ClilocFilterConfigureViewModel : BaseViewModel
|
||||
{
|
||||
private ICommand _addItemCommand;
|
||||
private ObservableCollection<ClilocEntry> _allClilocs = new ObservableCollection<ClilocEntry>();
|
||||
private ObservableCollection<ClilocEntry> _filteredClilocs = new ObservableCollection<ClilocEntry>();
|
||||
private string _filterText;
|
||||
private ObservableCollection<FilterClilocEntry> _items = new ObservableCollection<FilterClilocEntry>();
|
||||
private ICommand _removeItemCommand;
|
||||
private ICommand _saveItemsCommand;
|
||||
private ClilocEntry _selectedClilocEntry;
|
||||
private FilterClilocEntry _selectedItem;
|
||||
|
||||
public ClilocFilterConfigureViewModel()
|
||||
{
|
||||
foreach ( KeyValuePair<int, string> kvp in Cliloc.GetItems() )
|
||||
{
|
||||
AllClilocs.Add( new ClilocEntry { Key = kvp.Key, Value = kvp.Value } );
|
||||
}
|
||||
|
||||
foreach ( KeyValuePair<int, string> filterFilter in ClilocFilter.Filters )
|
||||
{
|
||||
Items.Add( new FilterClilocEntry { Cliloc = filterFilter.Key, Replacement = filterFilter.Value } );
|
||||
}
|
||||
|
||||
UpdateEntries( _filterText );
|
||||
}
|
||||
|
||||
public ICommand AddItemCommand => _addItemCommand ?? ( _addItemCommand = new RelayCommand( AddItem ) );
|
||||
|
||||
public ObservableCollection<ClilocEntry> AllClilocs
|
||||
{
|
||||
get => _allClilocs;
|
||||
set => SetProperty( ref _allClilocs, value );
|
||||
}
|
||||
|
||||
public ObservableCollection<ClilocEntry> FilteredClilocs
|
||||
{
|
||||
get => _filteredClilocs;
|
||||
set => SetProperty( ref _filteredClilocs, value );
|
||||
}
|
||||
|
||||
public string FilterText
|
||||
{
|
||||
get => _filterText;
|
||||
set
|
||||
{
|
||||
SetProperty( ref _filterText, value );
|
||||
UpdateEntries( _filterText );
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<FilterClilocEntry> Items
|
||||
{
|
||||
get => _items;
|
||||
set => SetProperty( ref _items, value );
|
||||
}
|
||||
|
||||
public ICommand RemoveItemCommand =>
|
||||
_removeItemCommand ?? ( _removeItemCommand = new RelayCommand( RemoveItem, o => SelectedItem != null ) );
|
||||
|
||||
public ICommand SaveItemsCommand =>
|
||||
_saveItemsCommand ?? ( _saveItemsCommand = new RelayCommand( SaveItems, o => true ) );
|
||||
|
||||
public ClilocEntry SelectedClilocEntry
|
||||
{
|
||||
get => _selectedClilocEntry;
|
||||
set => SetProperty( ref _selectedClilocEntry, value );
|
||||
}
|
||||
|
||||
public FilterClilocEntry SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set => SetProperty( ref _selectedItem, value );
|
||||
}
|
||||
|
||||
private void RemoveItem( object obj )
|
||||
{
|
||||
if ( !( obj is FilterClilocEntry entry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Items.Remove( entry );
|
||||
}
|
||||
|
||||
private void SaveItems( object obj )
|
||||
{
|
||||
ClilocFilter.Filters.Clear();
|
||||
|
||||
foreach ( FilterClilocEntry entry in Items )
|
||||
{
|
||||
if ( !ClilocFilter.Filters.ContainsKey( entry.Cliloc ) )
|
||||
{
|
||||
ClilocFilter.Filters.Add( entry.Cliloc, entry.Replacement );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEntries( string filterText )
|
||||
{
|
||||
IEnumerable<ClilocEntry> matches = AllClilocs.Where( m =>
|
||||
string.IsNullOrEmpty( filterText ) || m.Value.ToLower().Contains( filterText.ToLower() ) );
|
||||
FilteredClilocs.Clear();
|
||||
|
||||
foreach ( ClilocEntry clilocEntry in matches )
|
||||
{
|
||||
FilteredClilocs.Add( clilocEntry );
|
||||
}
|
||||
}
|
||||
|
||||
private void AddItem( object obj )
|
||||
{
|
||||
if ( !( obj is ClilocEntry clilocEntry ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Items.Any( i => i.Cliloc == clilocEntry.Key ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Items.Add( new FilterClilocEntry { Cliloc = clilocEntry.Key, Replacement = clilocEntry.Value } );
|
||||
}
|
||||
|
||||
public class ClilocEntry
|
||||
{
|
||||
public int Key { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class FilterClilocEntry
|
||||
{
|
||||
public int Cliloc { get; set; }
|
||||
public string Original => UO.Data.Cliloc.GetProperty( Cliloc );
|
||||
public string Replacement { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Threading;
|
||||
using AnimatedGif;
|
||||
using ClassicAssist.Shared;
|
||||
using ClassicAssist.UI.Views;
|
||||
using Point = System.Drawing.Point;
|
||||
using Size = System.Drawing.Size;
|
||||
|
||||
namespace ClassicAssist.UI.ViewModels
|
||||
{
|
||||
public class GIFRecorderViewModel : BaseViewModel
|
||||
{
|
||||
private readonly GIFRecorderWindow _window;
|
||||
private bool _isRecording;
|
||||
private MemoryStream _lastStream;
|
||||
private ICommand _recordCommand;
|
||||
private ICommand _saveCommand;
|
||||
private CancellationTokenSource _token;
|
||||
|
||||
public GIFRecorderViewModel( GIFRecorderWindow window ) : this()
|
||||
{
|
||||
_window = window;
|
||||
}
|
||||
|
||||
public GIFRecorderViewModel()
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsRecording
|
||||
{
|
||||
get => _isRecording;
|
||||
set => SetProperty( ref _isRecording, value );
|
||||
}
|
||||
|
||||
public MemoryStream LastStream
|
||||
{
|
||||
get => _lastStream;
|
||||
set => SetProperty( ref _lastStream, value );
|
||||
}
|
||||
|
||||
public ICommand RecordCommand => _recordCommand ?? ( _recordCommand = new RelayCommand( Record, o => true ) );
|
||||
|
||||
public ICommand SaveCommand => _saveCommand ?? ( _saveCommand = new RelayCommand( Save, o => !IsRecording ) );
|
||||
|
||||
private void Save( object obj )
|
||||
{
|
||||
if ( LastStream == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string directory = Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory, "Screenshots" );
|
||||
|
||||
if ( !Directory.Exists( directory ) )
|
||||
{
|
||||
Directory.CreateDirectory( directory );
|
||||
}
|
||||
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
string fileName =
|
||||
$"ClassicAssist-{now.Year}-{now.Month}-{now.Day}-{now.Hour}-{now.Minute}-{now.Second}.gif";
|
||||
|
||||
string fullPath = Path.Combine( directory, fileName );
|
||||
|
||||
using ( FileStream fs = new FileStream( fullPath, FileMode.Create ) )
|
||||
{
|
||||
LastStream.WriteTo( fs );
|
||||
}
|
||||
|
||||
string args = $"/e, /select, \"{fullPath}\"";
|
||||
|
||||
ProcessStartInfo info = new ProcessStartInfo { FileName = "explorer", Arguments = args };
|
||||
Process.Start( info );
|
||||
}
|
||||
|
||||
private void Record( object obj )
|
||||
{
|
||||
if ( IsRecording )
|
||||
{
|
||||
_token.Cancel();
|
||||
}
|
||||
else
|
||||
{
|
||||
IsRecording = true;
|
||||
_token = new CancellationTokenSource();
|
||||
|
||||
Window w = Window.GetWindow( _window );
|
||||
WindowInteropHelper wih = new WindowInteropHelper( w ?? throw new InvalidOperationException() );
|
||||
|
||||
Task.Run( async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
TimeSpan frameInterval = TimeSpan.FromSeconds( 1.0 / 5 );
|
||||
MemoryStream ms = new MemoryStream();
|
||||
|
||||
using ( AnimatedGifCreator gif = new AnimatedGifCreator( ms, frameInterval.Milliseconds ) )
|
||||
{
|
||||
Rectangle rect = new Rectangle();
|
||||
_dispatcher.Invoke( () => GetWindowRect( wih.Handle, ref rect ) );
|
||||
|
||||
Bitmap bmp = new Bitmap( rect.Width - rect.Left - 10, rect.Height - rect.Top - 70 );
|
||||
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
while ( true )
|
||||
{
|
||||
_dispatcher.Invoke( () => GetWindowRect( wih.Handle, ref rect ) );
|
||||
|
||||
using ( Graphics g = Graphics.FromImage( bmp ) )
|
||||
{
|
||||
g.CopyFromScreen( new Point( rect.Left + 5, rect.Top + 50 ), Point.Empty,
|
||||
new Size( bmp.Width, bmp.Height ) );
|
||||
}
|
||||
|
||||
await gif.AddFrameAsync( bmp, -1, GifQuality.Bit8 );
|
||||
|
||||
sw.Stop();
|
||||
|
||||
int wait = frameInterval.Milliseconds - (int) sw.ElapsedMilliseconds;
|
||||
|
||||
if ( wait > 0 )
|
||||
{
|
||||
await Task.Delay( wait );
|
||||
}
|
||||
|
||||
if ( _token.IsCancellationRequested )
|
||||
{
|
||||
return ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_dispatcher.Invoke( () => IsRecording = false );
|
||||
}
|
||||
} ).ContinueWith( t =>
|
||||
{
|
||||
if ( !( t.Result is MemoryStream ms ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( LastStream != null )
|
||||
{
|
||||
LastStream.Dispose();
|
||||
LastStream = null;
|
||||
}
|
||||
|
||||
LastStream = ms;
|
||||
CommandManager.InvalidateRequerySuggested();
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport( "user32.dll" )]
|
||||
private static extern IntPtr GetWindowRect( IntPtr hWnd, ref Rectangle rect );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows.Input;
|
||||
using ClassicAssist.Data.Macros;
|
||||
|
||||
namespace ClassicAssist.UI.ViewModels.Macros
|
||||
{
|
||||
public class CommandsData
|
||||
{
|
||||
public CommandsDisplayAttribute Attribute { get; set; }
|
||||
public string Category { get; set; }
|
||||
public bool IsExpanded { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Tooltip { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
public class MacrosCommandViewModel : BaseViewModel
|
||||
{
|
||||
private readonly MacrosTabViewModel _macrosViewModel;
|
||||
private ICommand _insertCommand;
|
||||
private ObservableCollection<CommandsData> _items = new ObservableCollection<CommandsData>();
|
||||
private CommandsData _selectedItem;
|
||||
|
||||
public MacrosCommandViewModel( MacrosTabViewModel macros ) : this()
|
||||
{
|
||||
_macrosViewModel = macros;
|
||||
}
|
||||
|
||||
public MacrosCommandViewModel()
|
||||
{
|
||||
IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes().Where( t =>
|
||||
t.Namespace != null && t.Namespace.StartsWith( "ClassicAssist.Data.Macros.Commands" ) );
|
||||
|
||||
foreach ( Type type in types )
|
||||
{
|
||||
MemberInfo[] members = type.GetMembers( BindingFlags.Public | BindingFlags.Static );
|
||||
|
||||
foreach ( MemberInfo memberInfo in members )
|
||||
{
|
||||
CommandsDisplayAttribute attr = memberInfo.GetCustomAttribute<CommandsDisplayAttribute>();
|
||||
|
||||
if ( attr == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CommandsData entry = new CommandsData
|
||||
{
|
||||
Category = attr.Category,
|
||||
IsExpanded = false,
|
||||
Name = memberInfo.ToString(),
|
||||
Tooltip = attr.Description,
|
||||
Attribute = attr
|
||||
};
|
||||
|
||||
Items.Add( entry );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand InsertCommand =>
|
||||
_insertCommand ?? ( _insertCommand = new RelayCommand( Insert, o => SelectedItem != null ) );
|
||||
|
||||
public ObservableCollection<CommandsData> Items
|
||||
{
|
||||
get => _items;
|
||||
set => SetProperty( ref _items, value );
|
||||
}
|
||||
|
||||
public CommandsData SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set => SetProperty( ref _selectedItem, value );
|
||||
}
|
||||
|
||||
private void Insert( object obj )
|
||||
{
|
||||
if ( !( obj is CommandsData cd ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( cd.Attribute != null )
|
||||
{
|
||||
//TODO UI
|
||||
//_macrosViewModel?.Document.Insert( _macrosViewModel.CaretPosition, cd.Attribute.InsertText );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user