diff --git a/AdamController.Controls/CustomControls.Services/ControlHelper.cs b/AdamController.Controls/CustomControls.Services/ControlHelper.cs index 9c21f18..cc43b74 100644 --- a/AdamController.Controls/CustomControls.Services/ControlHelper.cs +++ b/AdamController.Controls/CustomControls.Services/ControlHelper.cs @@ -6,8 +6,12 @@ namespace AdamController.Controls.CustomControls.Services public class ControlHelper : BindableBase, IControlHelper { public event BlocklyColumnWidthChangeEventHandler RaiseBlocklyColumnWidthChangeEvent; + public event IsVideoShowChangeEventHandler IsVideoShowChangeEvent; - public ControlHelper() {} + public ControlHelper(bool isVideoShowLastValue) + { + IsShowVideo = isVideoShowLastValue; + } private double mainGridActualWidth = double.NaN; public double MainGridActualWidth @@ -60,6 +64,19 @@ public BlocklyViewMode CurrentBlocklyViewMode } } + private bool isShowVideo; + public bool IsShowVideo + { + get => isShowVideo; + set + { + bool isNewValue = SetProperty(ref isShowVideo, value); + + if (isNewValue) + OnRaiseIsVideoShowChangeEvent(); + } + } + private void UpdateBlocklyColumnWidth() { var dividedScreen = MainGridActualWidth/2; @@ -104,5 +121,12 @@ protected virtual void OnRaiseBlocklyColumnWidthChangeEvent() BlocklyColumnWidthChangeEventHandler raiseEvent = RaiseBlocklyColumnWidthChangeEvent; raiseEvent?.Invoke(this); } + + protected virtual void OnRaiseIsVideoShowChangeEvent() + { + IsVideoShowChangeEventHandler raiseEvent = IsVideoShowChangeEvent; + raiseEvent?.Invoke(this); + + } } } diff --git a/AdamController.Controls/CustomControls.Services/IControlHelper.cs b/AdamController.Controls/CustomControls.Services/IControlHelper.cs index 81ad806..26608e5 100644 --- a/AdamController.Controls/CustomControls.Services/IControlHelper.cs +++ b/AdamController.Controls/CustomControls.Services/IControlHelper.cs @@ -6,6 +6,8 @@ namespace AdamController.Controls.CustomControls.Services public delegate void BlocklyColumnWidthChangeEventHandler(object sender); + public delegate void IsVideoShowChangeEventHandler(object sender); + #endregion public interface IControlHelper : IDisposable @@ -14,11 +16,14 @@ public interface IControlHelper : IDisposable public event BlocklyColumnWidthChangeEventHandler RaiseBlocklyColumnWidthChangeEvent; + public event IsVideoShowChangeEventHandler IsVideoShowChangeEvent; + #endregion public double MainGridActualWidth { get; set; } public double BlocklyColumnActualWidth { get; set; } public double BlocklyColumnWidth { get; set; } public BlocklyViewMode CurrentBlocklyViewMode { get; set; } + public bool IsShowVideo { get; set; } } } diff --git a/AdamController.Core/App.config b/AdamController.Core/App.config index b3fa840..44952b7 100644 --- a/AdamController.Core/App.config +++ b/AdamController.Core/App.config @@ -280,6 +280,9 @@ 0.7 + + True + diff --git a/AdamController.Core/Converters/BoolToViewModeIconsConverter.cs b/AdamController.Core/Converters/BoolToViewModeIconsConverter.cs new file mode 100644 index 0000000..929b2c6 --- /dev/null +++ b/AdamController.Core/Converters/BoolToViewModeIconsConverter.cs @@ -0,0 +1,31 @@ +using MahApps.Metro.IconPacks; +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace AdamController.Core.Converters +{ + [ValueConversion(typeof(bool?), typeof(Visibility))] + public class BoolToViewModeIconsConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + bool? booleanNulableValue = null; + + if (value != null) + booleanNulableValue = (bool)value; + + if (booleanNulableValue == true) + return PackIconFeatherIconsKind.Video; + + return PackIconRemixIconKind.BillLine; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException("Convert only one way"); + } + + } +} diff --git a/AdamController.Core/Converters/BoolToVisibilityConverter.cs b/AdamController.Core/Converters/BoolToVisibilityConverter.cs index b05d282..056d435 100644 --- a/AdamController.Core/Converters/BoolToVisibilityConverter.cs +++ b/AdamController.Core/Converters/BoolToVisibilityConverter.cs @@ -13,17 +13,12 @@ public object Convert(object value, Type targetType, object parameter, CultureIn bool? booleanNulableValue = null; if (value != null) - { booleanNulableValue = (bool)value; - } - if (booleanNulableValue == true) - return Visibility.Hidden; - if(booleanNulableValue == null) - return Visibility.Hidden; + return Visibility.Visible; - return Visibility.Visible; + return Visibility.Collapsed; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) diff --git a/AdamController.Core/Converters/BoolToVisibilityReConverter.cs b/AdamController.Core/Converters/BoolToVisibilityReConverter.cs new file mode 100644 index 0000000..dd42ce4 --- /dev/null +++ b/AdamController.Core/Converters/BoolToVisibilityReConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace AdamController.Core.Converters +{ + [ValueConversion(typeof(bool?), typeof(Visibility))] + public class BoolToVisibilityReConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + bool? booleanNulableValue = null; + + if (value != null) + booleanNulableValue = (bool)value; + + if (booleanNulableValue == true) + return Visibility.Collapsed; + + return Visibility.Visible; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException("Convert only one way"); + } + + } +} diff --git a/AdamController.Core/Converters/SelectedItemToContentConverter.cs b/AdamController.Core/Converters/SelectedItemToContentConverter.cs index 0f37800..93e7824 100644 --- a/AdamController.Core/Converters/SelectedItemToContentConverter.cs +++ b/AdamController.Core/Converters/SelectedItemToContentConverter.cs @@ -5,7 +5,7 @@ namespace AdamController.Core.Converters { - public class SelectedItemToContentConverter : IMultiValueConverter + /*public class SelectedItemToContentConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { @@ -17,5 +17,5 @@ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, { return targetTypes.Select(t => Binding.DoNothing).ToArray(); } - } + }*/ } diff --git a/AdamController.Core/Converters/StringToViewRegionIconsConverter.cs b/AdamController.Core/Converters/StringToViewRegionIconsConverter.cs new file mode 100644 index 0000000..c0a3ecc --- /dev/null +++ b/AdamController.Core/Converters/StringToViewRegionIconsConverter.cs @@ -0,0 +1,34 @@ +using MahApps.Metro.IconPacks; +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace AdamController.Core.Converters +{ + [ValueConversion(typeof(bool?), typeof(Visibility))] + public class StringToViewRegionIconsConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + string stringValue = string.Empty; + + if (value != null) + stringValue = (string)value; + + if (stringValue == SubRegionNames.SubRegionVisualSettings) + return PackIconSimpleIconsKind.Scratch; + + if (stringValue == SubRegionNames.SubRegionScratch) + return PackIconFeatherIconsKind.Settings; + + return PackIconSimpleIconsKind.AbbRobotStudio; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException("Convert only one way"); + } + + } +} diff --git a/AdamController.Core/Model/VectorModel.cs b/AdamController.Core/Model/VectorModel.cs index fde0ef9..d60974d 100644 --- a/AdamController.Core/Model/VectorModel.cs +++ b/AdamController.Core/Model/VectorModel.cs @@ -1,23 +1,23 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace AdamController.Core.Model { public class VectorModel { - [JsonProperty("move")] + [JsonPropertyName("move")] public VectorItem Move { get; set; } } public class VectorItem { - [JsonProperty("x")] + [JsonPropertyName("x")] public float X { get; set; } - [JsonProperty("y")] + [JsonPropertyName("y")] public float Y { get; set; } - [JsonProperty("z")] + [JsonPropertyName("z")] public float Z { get; set; } } diff --git a/AdamController.Core/Properties/Settings.Designer.cs b/AdamController.Core/Properties/Settings.Designer.cs index 2b71097..382f0ea 100644 --- a/AdamController.Core/Properties/Settings.Designer.cs +++ b/AdamController.Core/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace AdamController.Core.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0")] public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -1126,5 +1126,17 @@ public double WebViewZoomFactor { this["WebViewZoomFactor"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool ShowVideo { + get { + return ((bool)(this["ShowVideo"])); + } + set { + this["ShowVideo"] = value; + } + } } } diff --git a/AdamController.Core/Properties/Settings.settings b/AdamController.Core/Properties/Settings.settings index 7201d65..467bddf 100644 --- a/AdamController.Core/Properties/Settings.settings +++ b/AdamController.Core/Properties/Settings.settings @@ -278,5 +278,8 @@ 0.7 + + True + \ No newline at end of file diff --git a/AdamController/AdamController - Backup.csproj b/AdamController/AdamController - Backup.csproj deleted file mode 100644 index 59724d1..0000000 --- a/AdamController/AdamController - Backup.csproj +++ /dev/null @@ -1,124 +0,0 @@ - - - net6.0-windows10.0.22000.0 - WinExe - 9.0 - false - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - false - true - true - true - MinimumRecommendedRules.ruleset - - - bin\x64\Debug\ - 9.0 - MinimumRecommendedRules.ruleset - - - bin\x64\Release\ - 9.0 - MinimumRecommendedRules.ruleset - - - AdamController.App - - - Images\Icons\AdamIconAndRGBPageIcon.ico - MIT-Modern-Variant - 7.0 - 1.0.1.1 - 1.0.1.1 - - - 1701;1702;CA1416 - - - 1701;1702;CA1416 - - - - - - - - - - - - - Always - - - - - - - - False - Microsoft .NET Framework 4.8 %28x86 и x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - True - True - Settings.settings - - - - - PublicResXFileCodeGenerator - Resources.Designer.cs - - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - \ No newline at end of file diff --git a/AdamController/AdamController.csproj b/AdamController/AdamController.csproj index e9c1874..5088f3a 100644 --- a/AdamController/AdamController.csproj +++ b/AdamController/AdamController.csproj @@ -3,8 +3,8 @@ Dynamic False MIT-Modern-Variant - 2.0.0.7 - 2.0.0.7 + 2.0.0.8 + 2.0.0.8 net8.0-windows7.0 diff --git a/AdamController/App.xaml.cs b/AdamController/App.xaml.cs index fae2fa6..870c58e 100644 --- a/AdamController/App.xaml.cs +++ b/AdamController/App.xaml.cs @@ -214,7 +214,12 @@ protected override void RegisterTypes(IContainerRegistry containerRegistry) }); containerRegistry.RegisterSingleton(); - containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(containerRegistry => + { + bool isVideoShowLastValue = Settings.Default.ShowVideo; + return new ControlHelper(isVideoShowLastValue); + }); + containerRegistry.RegisterSingleton(); RegisterDialogs(containerRegistry); diff --git a/AdamController/ViewModels/MainWindowViewModel.cs b/AdamController/ViewModels/MainWindowViewModel.cs index 9d37953..62c5da7 100644 --- a/AdamController/ViewModels/MainWindowViewModel.cs +++ b/AdamController/ViewModels/MainWindowViewModel.cs @@ -8,6 +8,7 @@ using AdamController.Services.Interfaces; using Prism.Commands; using Prism.Regions; +using System; using System.Globalization; using System.Linq; using System.Reflection; @@ -18,16 +19,20 @@ namespace AdamController.ViewModels public class MainWindowViewModel : ViewModelBase { #region DelegateCommands - - public DelegateCommand ShowRegionCommand { get; private set; } - public DelegateCommand MoveSplitterDelegateCommand { get; private set; } + + public DelegateCommand ShowRegionCommand { get; } + public DelegateCommand MoveSplitterDelegateCommand { get; } + public DelegateCommand SwitchToVideoDelegateCommand { get; } + public DelegateCommand SwitchToSettingsViewDelegateCommand { get; } #endregion #region Services - public IRegionManager RegionManager { get; } - private readonly ISubRegionChangeAwareService mSubRegionChangeAwareService; + public ISubRegionChangeAwareService SubRegionChangeAwareService { get; } + public IControlHelper ControlHelper { get; } + + private readonly IRegionManager mRegionManager; private readonly IStatusBarNotificationDeliveryService mStatusBarNotification; private readonly ICommunicationProviderService mCommunicationProviderService; private readonly IFolderManagmentService mFolderManagment; @@ -35,8 +40,7 @@ public class MainWindowViewModel : ViewModelBase private readonly IAvalonEditService mAvalonEditService; private readonly IThemeManagerService mThemeManager; private readonly ICultureProvider mCultureProvider; - private readonly IControlHelper mControlHelper; - private readonly IVideoViewProvider mVideoViewProvider; + #endregion #region ~ @@ -44,23 +48,27 @@ public class MainWindowViewModel : ViewModelBase public MainWindowViewModel(IRegionManager regionManager, ISubRegionChangeAwareService subRegionChangeAwareService, IStatusBarNotificationDeliveryService statusBarNotification, ICommunicationProviderService communicationProviderService, IFolderManagmentService folderManagment, IWebApiService webApiService, IAvalonEditService avalonEditService, IThemeManagerService themeManager, ICultureProvider cultureProvider, - IControlHelper controlHelper, IVideoViewProvider videoViewProvider) + IControlHelper controlHelper) { - RegionManager = regionManager; + mRegionManager = regionManager; mWebApiService = webApiService; - mSubRegionChangeAwareService = subRegionChangeAwareService; + SubRegionChangeAwareService = subRegionChangeAwareService; mStatusBarNotification = statusBarNotification; mCommunicationProviderService = communicationProviderService; mFolderManagment = folderManagment; mAvalonEditService = avalonEditService; mThemeManager = themeManager; mCultureProvider = cultureProvider; - mControlHelper = controlHelper; - mVideoViewProvider = videoViewProvider; + ControlHelper = controlHelper; ShowRegionCommand = new DelegateCommand(ShowRegion); MoveSplitterDelegateCommand = new DelegateCommand(MoveSplitter, MoveSplitterCanExecute); + SwitchToVideoDelegateCommand = new DelegateCommand(SwitchToVideo, SwitchToVideoCanExecute); + SwitchToSettingsViewDelegateCommand = new DelegateCommand(SwitchToSettingsView, SwitchToSettingsViewCanExecute); + + RestroreLastSelectedView(); + Subscribe(); } @@ -70,43 +78,6 @@ public MainWindowViewModel(IRegionManager regionManager, ISubRegionChangeAwareSe public string WindowTitle => $"AdamStudio {Assembly.GetExecutingAssembly().GetName().Version}"; - /// - /// -1 is not selected - /// - private int hamburgerMenuSelectedIndex = -1; - public int HamburgerMenuSelectedIndex - { - get { return hamburgerMenuSelectedIndex; } - set - { - bool isNewValue = SetProperty(ref hamburgerMenuSelectedIndex, value); - - if(isNewValue) - MoveSplitterDelegateCommand.RaiseCanExecuteChanged(); - } - } - - /// - /// -1 is not selected - /// - private int hamburgerMenuSelectedOptionsIndex = -1; - - public int HamburgerMenuSelectedOptionsIndex - { - get { return hamburgerMenuSelectedOptionsIndex; } - - set - { - SetProperty(ref hamburgerMenuSelectedOptionsIndex, value); - } - } - - private string videoFrameRate; - public string VideoFrameRate - { - get { return videoFrameRate; } - set { SetProperty(ref videoFrameRate, value); } - } #endregion @@ -114,66 +85,95 @@ public string VideoFrameRate private void MoveSplitter(string commandArg) { - BlocklyViewMode currentViewMode = mControlHelper.CurrentBlocklyViewMode; + BlocklyViewMode currentViewMode = ControlHelper.CurrentBlocklyViewMode; if (commandArg == "Left") { if (currentViewMode == BlocklyViewMode.FullScreen) - mControlHelper.CurrentBlocklyViewMode = BlocklyViewMode.MiddleScreen; + ControlHelper.CurrentBlocklyViewMode = BlocklyViewMode.MiddleScreen; if (currentViewMode == BlocklyViewMode.MiddleScreen) - mControlHelper.CurrentBlocklyViewMode = BlocklyViewMode.Hidden; + ControlHelper.CurrentBlocklyViewMode = BlocklyViewMode.Hidden; } if (commandArg == "Right") { if (currentViewMode == BlocklyViewMode.Hidden) - mControlHelper.CurrentBlocklyViewMode = BlocklyViewMode.MiddleScreen; + ControlHelper.CurrentBlocklyViewMode = BlocklyViewMode.MiddleScreen; if (currentViewMode == BlocklyViewMode.MiddleScreen) - mControlHelper.CurrentBlocklyViewMode = BlocklyViewMode.FullScreen; + ControlHelper.CurrentBlocklyViewMode = BlocklyViewMode.FullScreen; } } private bool MoveSplitterCanExecute(string arg) { - return HamburgerMenuSelectedIndex == 0; + var regionName = SubRegionChangeAwareService.InsideRegionNavigationRequestName; + return regionName == SubRegionNames.SubRegionScratch; } - #endregion + private void SwitchToVideo() + { + if (ControlHelper.IsShowVideo) + { + ControlHelper.IsShowVideo = false; + return; + } + + ControlHelper.IsShowVideo = true; + return; + } - #region Private methods + private bool SwitchToVideoCanExecute() + { + var regionName = SubRegionChangeAwareService.InsideRegionNavigationRequestName; + return regionName == SubRegionNames.SubRegionScratch; + } - private void ChangeSelectedIndexByRegionName(string subRegionName) + private void SwitchToSettingsView() { - switch (subRegionName) + + var regionName = SubRegionChangeAwareService.InsideRegionNavigationRequestName; + + if (regionName == SubRegionNames.SubRegionScratch) { - case SubRegionNames.SubRegionScratch: - HamburgerMenuSelectedIndex = 0; - break; - case SubRegionNames.SubRegionComputerVisionControl: - HamburgerMenuSelectedIndex = 1; - break; - case SubRegionNames.SubRegionVisualSettings: - HamburgerMenuSelectedOptionsIndex = 0; - break; + ShowRegion(SubRegionNames.SubRegionVisualSettings); + return; } + + if(regionName == SubRegionNames.SubRegionVisualSettings) + { + ShowRegion(SubRegionNames.SubRegionScratch); + return; + } + } + + private bool SwitchToSettingsViewCanExecute() + { + return true; } + #endregion + + #region Private methods + private void ShowRegion(string subRegionName) { switch (subRegionName) { case SubRegionNames.SubRegionScratch: - RegionManager.RequestNavigate(RegionNames.ContentRegion, SubRegionNames.SubRegionScratch); + mRegionManager.RequestNavigate(RegionNames.ContentRegion, SubRegionNames.SubRegionScratch); break; case SubRegionNames.SubRegionComputerVisionControl: - RegionManager.RequestNavigate(RegionNames.ContentRegion, SubRegionNames.SubRegionComputerVisionControl); + mRegionManager.RequestNavigate(RegionNames.ContentRegion, SubRegionNames.SubRegionComputerVisionControl); break; case SubRegionNames.SubRegionVisualSettings: - RegionManager.RequestNavigate(RegionNames.ContentRegion, SubRegionNames.SubRegionVisualSettings); + mRegionManager.RequestNavigate(RegionNames.ContentRegion, SubRegionNames.SubRegionVisualSettings); break; } + + MoveSplitterDelegateCommand.RaiseCanExecuteChanged(); + SwitchToVideoDelegateCommand.RaiseCanExecuteChanged(); } /// @@ -205,6 +205,11 @@ private void ParseSyslogMessage(string message) } } + private void RestroreLastSelectedView() + { + //mControlHelper.IsShowVideo = Settings.Default.ShowVideo; + } + /// /// Register highlighting for AvalonEdit. You need to call before loading the regions /// @@ -236,23 +241,25 @@ private void LoadDefaultCultureInfo() /// private void Subscribe() { - mSubRegionChangeAwareService.RaiseSubRegionChangeEvent += RaiseSubRegionChangeEvent; mCommunicationProviderService.RaiseTcpServiceCientConnectedEvent += RaiseTcpServiceCientConnectedEvent; mCommunicationProviderService.RaiseUdpServiceServerReceivedEvent += RaiseUdpServiceServerReceivedEvent; - mVideoViewProvider.RaiseFrameRateUpdateEvent += RaiseFrameRateUpdateEvent; Application.Current.MainWindow.Loaded += MainWindowLoaded; } + private void IsVideoShowChangeEvent(object sender) + { + SwitchToVideo(); + } + /// /// #20 /// private void Unsubscribe() { - mSubRegionChangeAwareService.RaiseSubRegionChangeEvent -= RaiseSubRegionChangeEvent; mCommunicationProviderService.RaiseTcpServiceCientConnectedEvent -= RaiseTcpServiceCientConnectedEvent; mCommunicationProviderService.RaiseUdpServiceServerReceivedEvent -= RaiseUdpServiceServerReceivedEvent; - mVideoViewProvider.RaiseFrameRateUpdateEvent -= RaiseFrameRateUpdateEvent; + Application.Current.MainWindow.Loaded -= MainWindowLoaded; } @@ -284,15 +291,6 @@ private void MainWindowLoaded(object sender, RoutedEventArgs e) mCommunicationProviderService.ConnectAllAsync(); } - /// - /// Changes the selected section in the hamburger menu - /// - private void RaiseSubRegionChangeEvent(object sender) - { - var changeRegionName = mSubRegionChangeAwareService.InsideRegionNavigationRequestName; - ChangeSelectedIndexByRegionName(changeRegionName); - } - /// /// It is not clear where to put this, so it will not get lost here. /// @@ -308,19 +306,6 @@ private void RaiseUdpServiceServerReceivedEvent(object sender, string message) ParseSyslogMessage(message); } - private void RaiseFrameRateUpdateEvent(object sender) - { - double rate = double.Round(mVideoViewProvider.FrameRate, 2); - - if (double.IsNaN(rate)) - { - VideoFrameRate = string.Empty; - return; - } - - VideoFrameRate = $"{rate} FPS"; - } - #endregion } } diff --git a/AdamController/Views/MainWindow.xaml b/AdamController/Views/MainWindow.xaml index e03fece..d964123 100644 --- a/AdamController/Views/MainWindow.xaml +++ b/AdamController/Views/MainWindow.xaml @@ -8,6 +8,7 @@ xmlns:prism="http://prismlibrary.com/" xmlns:customusercontrol="clr-namespace:AdamController.Controls.CustomControls;assembly=AdamController.Controls" prism:ViewModelLocator.AutoWireViewModel="True" + xmlns:converters="clr-namespace:AdamController.Core.Converters;assembly=AdamController.Core" WindowTitleBrush="{DynamicResource MahApps.Brushes.Control.Background}" NonActiveWindowTitleBrush="{DynamicResource MahApps.Brushes.Control.Background}" NonActiveBorderBrush="{DynamicResource MahApps.Brushes.Text}" @@ -15,6 +16,15 @@ Title="{Binding WindowTitle}" SaveWindowPosition="True" TitleBarHeight="25"> + + + + + + + + + @@ -22,7 +32,6 @@ - @@ -60,7 +69,7 @@ - + - + + + @@ -99,56 +117,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -163,88 +131,11 @@ To unlock, delete the parameters: CompactPaneLength="30" and MaximumOpenPaneLength="30" --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + public DelegateCommand DirectionButtonCommandDown => directionButtonCommandDown ??= new DelegateCommand(obj => { - var vectorSource = JsonConvert.DeserializeObject(obj); - + //var vectorSource = JsonConvert.DeserializeObject(obj); + var vectorSource = JsonSerializer.Deserialize(obj); + if (vectorSource.Move.X == 1) { vectorSource.Move.X = SliderValue; @@ -91,8 +93,9 @@ public override void OnNavigatedFrom(NavigationContext navigationContext) { vectorSource.Move.Z = -SliderValue; } - - var json = JsonConvert.SerializeObject(vectorSource); + + //var json = JsonConvert.SerializeObject(vectorSource); + var json = JsonSerializer.Serialize(vectorSource); mCommunicationProvider.WebSocketSendTextMessage(json); }, canExecute => mCommunicationProvider.IsTcpClientConnected); @@ -112,7 +115,8 @@ public override void OnNavigatedFrom(NavigationContext navigationContext) } }; - var json = JsonConvert.SerializeObject(vector); + //var json = JsonConvert.SerializeObject(vector); + var json = JsonSerializer.Serialize(vector); mCommunicationProvider.WebSocketSendTextMessage(json); }, canExecute => mCommunicationProvider.IsTcpClientConnected); diff --git a/Modules/AdamController.Modules.ContentRegion/ViewModels/ScratchControlViewModel.cs b/Modules/AdamController.Modules.ContentRegion/ViewModels/ScratchControlViewModel.cs index 53b9990..4dcdc37 100644 --- a/Modules/AdamController.Modules.ContentRegion/ViewModels/ScratchControlViewModel.cs +++ b/Modules/AdamController.Modules.ContentRegion/ViewModels/ScratchControlViewModel.cs @@ -3,8 +3,10 @@ using AdamBlocklyLibrary.Struct; using AdamBlocklyLibrary.Toolbox; using AdamBlocklyLibrary.ToolboxSets; +using AdamController.Controls.CustomControls.Services; using AdamController.Core; using AdamController.Core.Extensions; +using AdamController.Core.Model; using AdamController.Core.Mvvm; using AdamController.Core.Properties; using AdamController.Services.Interfaces; @@ -18,6 +20,7 @@ using Prism.Services.Dialogs; using System; using System.IO; +using System.Text.Json; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; @@ -35,7 +38,9 @@ public class ScratchControlViewModel : RegionViewModelBase public DelegateCommand CleanExecuteEditorDelegateCommand { get; } public DelegateCommand RunPythonCodeDelegateCommand { get; } public DelegateCommand StopPythonCodeExecuteDelegateCommand { get; } - public DelegateCommand ToZeroPositionDelegateCommand { get; } + public DelegateCommand ToZeroPositionDelegateCommand { get; } + public DelegateCommand DirectionButtonDownDelegateCommand { get; } + public DelegateCommand DirectionButtonUpDelegateCommand { get; } #endregion @@ -49,6 +54,8 @@ public class ScratchControlViewModel : RegionViewModelBase private readonly IWebApiService mWebApiService; private readonly ICultureProvider mCultureProvider; private readonly ISystemDialogService mSystemDialog; + private readonly IControlHelper mControlHelper; + private readonly IVideoViewProvider mVideoViewProvider; #endregion @@ -93,7 +100,8 @@ public class ScratchControlViewModel : RegionViewModelBase public ScratchControlViewModel(IRegionManager regionManager, ICommunicationProviderService communicationProvider, IPythonRemoteRunnerService pythonRemoteRunner, IStatusBarNotificationDeliveryService statusBarNotificationDelivery, IWebViewProvider webViewProvider, IFileManagmentService fileManagment, IWebApiService webApiService, IAvalonEditService avalonEditService, - ICultureProvider cultureProvider, ISystemDialogService systemDialogService) : base(regionManager) + ICultureProvider cultureProvider, ISystemDialogService systemDialogService, IControlHelper controlHelper, + IVideoViewProvider videoViewProvider) : base(regionManager) { mCommunicationProvider = communicationProvider; @@ -104,6 +112,8 @@ public ScratchControlViewModel(IRegionManager regionManager, ICommunicationProvi mWebApiService = webApiService; mCultureProvider = cultureProvider; mSystemDialog = systemDialogService; + mControlHelper = controlHelper; + mVideoViewProvider = videoViewProvider; ShowSaveFileDialogDelegateCommand = new DelegateCommand(ShowSaveFileDialog, ShowSaveFileDialogCanExecute); ShowOpenFileDialogDelegateCommand = new DelegateCommand(ShowOpenFileDialog, ShowOpenFileDialogCanExecute); @@ -115,6 +125,9 @@ public ScratchControlViewModel(IRegionManager regionManager, ICommunicationProvi StopPythonCodeExecuteDelegateCommand = new DelegateCommand(StopPythonCodeExecute, StopPythonCodeExecuteCanExecute); ToZeroPositionDelegateCommand = new DelegateCommand(ToZeroPosition, ToZeroPositionCanExecute); + DirectionButtonDownDelegateCommand = new DelegateCommand(DirectionButtonDown, DirectionButtonDownCanExecute); + DirectionButtonUpDelegateCommand = new DelegateCommand(DirectionButtonUp, DirectionButtonUpCanExecute); + HighlightingDefinition = avalonEditService.GetDefinition(HighlightingName.AdamPython); } @@ -131,8 +144,8 @@ public override void OnNavigatedTo(NavigationContext navigationContext) { Subscribe(); LoadResources(); + UpdateIsShowVideo(Settings.Default.ShowVideo); - //#29 mWebViewProvider.ReloadWebView(); base.OnNavigatedTo(navigationContext); @@ -149,6 +162,28 @@ public override void OnNavigatedFrom(NavigationContext navigationContext) #region Public fields + private string videoFrameRate; + public string VideoFrameRate + { + get { return videoFrameRate; } + set { SetProperty(ref videoFrameRate, value); } + } + + private bool isShowVideo; //= Settings.Default.ShowVideo; + public bool IsShowVideo + { + get => isShowVideo; + set + { + bool isNewValue = SetProperty(ref isShowVideo, value); + + if (isNewValue) + { + Settings.Default.ShowVideo = IsShowVideo; + } + } + } + private bool isTcpClientConnected; public bool IsTcpClientConnected { @@ -229,6 +264,13 @@ public string PythonVersion set => SetProperty(ref pythonVersion, value); } + private float sliderValue; + public float SliderValue + { + get => sliderValue; + set => SetProperty(ref sliderValue, value); + } + /*private string pythonBinPath; public string PythonBinPath { @@ -250,6 +292,24 @@ public IHighlightingDefinition HighlightingDefinition set => SetProperty(ref highlightingDefinition, value); } + public string StopDirrection { get; private set; } = "{\"move\":{\"x\": 0, \"y\": 0, \"z\": 0}}"; + + // left/right/up/down + + public string ForwardDirection { get; private set; } = "{\"move\":{\"x\": 0, \"y\": 1, \"z\": 0}}"; + public string BackDirection { get; private set; } = "{\"move\":{\"x\": 0, \"y\": -1, \"z\": 0}}"; + public string LeftDirection { get; private set; } = "{\"move\":{\"x\": -1, \"y\": 0, \"z\": 0}}"; + public string RightDirection { get; private set; } = "{\"move\":{\"x\": 1, \"y\": 0, \"z\": 0}}"; + + // + public string ForwardLeftDirection { get; private set; } = "{\"move\":{\"x\": -1, \"y\": 1, \"z\": 0}}"; + public string ForwardRightDirection { get; private set; } = "{\"move\":{\"x\": 1, \"y\": 1, \"z\": 0}}"; + public string BackLeftDirection { get; private set; } = "{\"move\":{\"x\": -1, \"y\": -1, \"z\": 0}}"; + public string BackRightDirection { get; private set; } = "{\"move\":{\"x\": 1, \"y\": -1, \"z\": 0}}"; + + //rotate + + public string RotateRightDirrection { get; private set; } = "{\"move\":{\"x\": 0.0, \"y\": 0.0, \"z\": 1.0 }}"; + public string RotateLeftDirrection { get; private set; } = "{\"move\":{\"x\": 0.0, \"y\": 0.0, \"z\": -1.0}}"; + #endregion #region Subscribes @@ -265,6 +325,10 @@ private void Subscribe() mWebViewProvider.RaiseWebViewMessageReceivedEvent += RaiseWebViewbMessageReceivedEvent; mWebViewProvider.RaiseWebViewNavigationCompleteEvent += RaiseWebViewNavigationCompleteEvent; + + mControlHelper.IsVideoShowChangeEvent += OnRaiseIsVideoShowChangeEvent; + + mVideoViewProvider.RaiseFrameRateUpdateEvent += RaiseFrameRateUpdateEvent; } private void Unsubscribe() @@ -278,6 +342,10 @@ private void Unsubscribe() mWebViewProvider.RaiseWebViewMessageReceivedEvent -= RaiseWebViewbMessageReceivedEvent; mWebViewProvider.RaiseWebViewNavigationCompleteEvent -= RaiseWebViewNavigationCompleteEvent; + + mControlHelper.IsVideoShowChangeEvent -= OnRaiseIsVideoShowChangeEvent; + + mVideoViewProvider.RaiseFrameRateUpdateEvent -= RaiseFrameRateUpdateEvent; } #endregion @@ -481,11 +549,79 @@ private bool ToZeroPositionCanExecute() return isTcpConnected && isPythonCodeNotExecute; } + private void DirectionButtonDown(string obj) + { + VectorModel vectorSource = JsonSerializer.Deserialize(obj); + + if (vectorSource == null) + return; + + if (vectorSource.Move.X == 1) + { + vectorSource.Move.X = SliderValue; + } + else if (vectorSource.Move.X == -1) + { + vectorSource.Move.X = -SliderValue; + } + + if (vectorSource.Move.Y == 1) + { + vectorSource.Move.Y = SliderValue; + } + else if (vectorSource.Move.Y == -1) + { + vectorSource.Move.Y = -SliderValue; + } + + if (vectorSource.Move.Z == 1) + { + vectorSource.Move.Z = SliderValue; + } + else if (vectorSource.Move.Z == -1) + { + vectorSource.Move.Z = -SliderValue; + } + + var json = JsonSerializer.Serialize(vectorSource); + mCommunicationProvider.WebSocketSendTextMessage(json); + } + + private bool DirectionButtonDownCanExecute(string arg) + { + return true; + } + + private void DirectionButtonUp(string obj) + { + VectorModel vector = new() + { + Move = new VectorItem + { + X = 0, + Y = 0, + Z = 0 + } + }; + + var json = JsonSerializer.Serialize(vector); + mCommunicationProvider.WebSocketSendTextMessage(json); + } + + private bool DirectionButtonUpCanExecute(string arg) + { + return true; + } #endregion #region Private methods + private void UpdateIsShowVideo(bool isShowVideo) + { + IsShowVideo = isShowVideo; + } + private void UpdateResultText(string text, bool isFinishMessage = false) { Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => @@ -731,6 +867,24 @@ private void OnRaisePythonScriptExecuteFinish(object sender, ExtendedCommandExec UpdateResultExecutionTimeText(remoteCommandExecuteResult); } + private void OnRaiseIsVideoShowChangeEvent(object sender) + { + UpdateIsShowVideo(mControlHelper.IsShowVideo); + } + + private void RaiseFrameRateUpdateEvent(object sender) + { + double rate = double.Round(mVideoViewProvider.FrameRate, 2); + + if (double.IsNaN(rate)) + { + VideoFrameRate = string.Empty; + return; + } + + VideoFrameRate = $"{rate} FPS"; + } + #endregion #region Initialize Blockly diff --git a/Modules/AdamController.Modules.ContentRegion/Views/ComputerVisionControlView.xaml b/Modules/AdamController.Modules.ContentRegion/Views/ComputerVisionControlView.xaml index a15b3d3..542fdc7 100644 --- a/Modules/AdamController.Modules.ContentRegion/Views/ComputerVisionControlView.xaml +++ b/Modules/AdamController.Modules.ContentRegion/Views/ComputerVisionControlView.xaml @@ -71,7 +71,7 @@ + Height="200"> @@ -101,7 +101,7 @@ diff --git a/Modules/AdamController.Modules.ContentRegion/Views/ComputerVisionControlView.xaml.cs b/Modules/AdamController.Modules.ContentRegion/Views/ComputerVisionControlView.xaml.cs index 391043b..aabbf56 100644 --- a/Modules/AdamController.Modules.ContentRegion/Views/ComputerVisionControlView.xaml.cs +++ b/Modules/AdamController.Modules.ContentRegion/Views/ComputerVisionControlView.xaml.cs @@ -12,7 +12,7 @@ public partial class ComputerVisionControlView : UserControl { #region Service - private readonly IWebSocketClientService mWebSocketClient; + //private readonly IWebSocketClientService mWebSocketClient; private readonly IVideoViewProvider mVideoViewProvider; #endregion @@ -21,7 +21,7 @@ public ComputerVisionControlView(IWebSocketClientService webSocketClient, IVideo { InitializeComponent(); - mWebSocketClient = webSocketClient; + //mWebSocketClient = webSocketClient; mVideoViewProvider = videoViewProvider; VideoView.Loaded += VideoViewLoaded; @@ -32,24 +32,15 @@ public ComputerVisionControlView(IWebSocketClientService webSocketClient, IVideo private void VideoViewVideoFrameDecoded(object sender, FrameDecodedEventArgs e) { - //double rate = VideoView.VideoFrameRate; mVideoViewProvider.FrameRate = VideoView.VideoFrameRate; } private void VideoViewMediaOpening(object sender, MediaOpeningEventArgs e) { - //var isStream = VideoView.IsNetworkStream; - - e.Options.IsTimeSyncDisabled = true; e.Options.IsAudioDisabled = true; e.Options.MinimumPlaybackBufferPercent = 0; - e.Options.DecoderParams.EnableFastDecoding = true; - - - //e.Options.DecoderParams.EnableLowDelayDecoding = true; - //e.Options.VideoForcedFps = 30; } private async void VideoViewLoaded(object sender, RoutedEventArgs e) @@ -63,10 +54,6 @@ private async void VideoViewLoaded(object sender, RoutedEventArgs e) //var uri = new Uri($"{docPath}"); await VideoView.Open(uri); - - //mMediaPlayer.EnableHardwareDecoding = true; - //mMediaPlayer.NetworkCaching = 1000; - //mMediaPlayer.Scale = 0.72f; } private async void UserControlUnloaded(object sender, RoutedEventArgs e) @@ -74,11 +61,13 @@ private async void UserControlUnloaded(object sender, RoutedEventArgs e) await VideoView.Close(); mVideoViewProvider.ClearFrameRate(); } - public string DownRightDirection { get; private set; } = "{\"move\":{\"x\": 0, \"y\": 1, \"z\": 0}}"; - private void Button_KeyDown(object sender, KeyEventArgs e) - { - mWebSocketClient.SendTextAsync(DownRightDirection); - } + //? + //public string DownRightDirection { get; private set; } = "{\"move\":{\"x\": 0, \"y\": 1, \"z\": 0}}"; + + //private void Button_KeyDown(object sender, KeyEventArgs e) + //{ + // mWebSocketClient.SendTextAsync(DownRightDirection); + //} } } diff --git a/Modules/AdamController.Modules.ContentRegion/Views/ScratchControlView.xaml b/Modules/AdamController.Modules.ContentRegion/Views/ScratchControlView.xaml index 6b1cc11..00d2b77 100644 --- a/Modules/AdamController.Modules.ContentRegion/Views/ScratchControlView.xaml +++ b/Modules/AdamController.Modules.ContentRegion/Views/ScratchControlView.xaml @@ -10,11 +10,14 @@ xmlns:behaviors="clr-namespace:AdamController.Core.Behaviors;assembly=AdamController.Core" xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" xmlns:prism="http://prismlibrary.com/" - prism:ViewModelLocator.AutoWireViewModel="True"> + prism:ViewModelLocator.AutoWireViewModel="True" + xmlns:ffme="clr-namespace:Unosquare.FFME;assembly=ffme.win"> + + @@ -49,49 +52,429 @@ - + - + + + - + - + + + + + - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + diff --git a/Modules/AdamController.Modules.ContentRegion/Views/ScratchControlView.xaml.cs b/Modules/AdamController.Modules.ContentRegion/Views/ScratchControlView.xaml.cs index 2d9df93..749670c 100644 --- a/Modules/AdamController.Modules.ContentRegion/Views/ScratchControlView.xaml.cs +++ b/Modules/AdamController.Modules.ContentRegion/Views/ScratchControlView.xaml.cs @@ -11,6 +11,7 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Threading; +using Unosquare.FFME.Common; namespace AdamController.Modules.ContentRegion.Views { @@ -21,6 +22,8 @@ public partial class ScratchControlView : UserControl private readonly IWebViewProvider mWebViewProvider; private readonly IStatusBarNotificationDeliveryService mStatusBarNotification; private readonly IControlHelper mControlHelper; + private readonly IWebSocketClientService mWebSocketClient; + private readonly IVideoViewProvider mVideoViewProvider; #endregion @@ -30,7 +33,8 @@ public partial class ScratchControlView : UserControl #endregion - public ScratchControlView(IWebViewProvider webViewProvider, IStatusBarNotificationDeliveryService statusBarNotification, IFolderManagmentService folderManagment, IControlHelper controlHelper) + public ScratchControlView(IWebViewProvider webViewProvider, IStatusBarNotificationDeliveryService statusBarNotification, + IFolderManagmentService folderManagment, IControlHelper controlHelper, IWebSocketClientService webSocketClient, IVideoViewProvider videoViewProvider) { InitializeComponent(); InitializeWebViewCore(); @@ -55,6 +59,49 @@ public ScratchControlView(IWebViewProvider webViewProvider, IStatusBarNotificati /* service event */ mControlHelper.RaiseBlocklyColumnWidthChangeEvent += RaiseBlocklyColumnWidthChangeEvent; + + /* video */ + mWebSocketClient = webSocketClient; + mVideoViewProvider = videoViewProvider; + + VideoView.MediaOpening += VideoViewMediaOpening; + VideoView.VideoFrameDecoded += VideoViewVideoFrameDecoded; + VideoView.IsVisibleChanged += VideoViewIsVisibleChanged; + } + + private async void VideoViewIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) + { + if (VideoView.IsVisible) + { + + string ip = Settings.Default.ServerIP; + string port = Settings.Default.VideoDataExchangePort; + + var uri = new Uri($"http://{ip}:{port}/stream/0.mjpeg"); + //var docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\test.avi"; + //var uri = new Uri($"{docPath}"); + + await VideoView.Open(uri); + return; + } + + await VideoView.Close(); + mVideoViewProvider.ClearFrameRate(); + } + + private void VideoViewVideoFrameDecoded(object sender, FrameDecodedEventArgs e) + { + mVideoViewProvider.FrameRate = VideoView.VideoFrameRate; + } + + private void VideoViewMediaOpening(object sender, MediaOpeningEventArgs e) + { + + e.Options.IsTimeSyncDisabled = true; + e.Options.IsAudioDisabled = true; + e.Options.MinimumPlaybackBufferPercent = 0; + + e.Options.DecoderParams.EnableFastDecoding = true; } private void RaiseBlocklyColumnWidthChangeEvent(object sender) diff --git a/Modules/AdamController.Modules.MenuRegion/Views/MenuRegionView.xaml b/Modules/AdamController.Modules.MenuRegion/Views/MenuRegionView.xaml index 1bb61cd..ef8a0e7 100644 --- a/Modules/AdamController.Modules.MenuRegion/Views/MenuRegionView.xaml +++ b/Modules/AdamController.Modules.MenuRegion/Views/MenuRegionView.xaml @@ -24,11 +24,6 @@ CommandParameter="{x:Static core:SubRegionNames.SubRegionScratch}" IsChecked="{Binding IsCheckedScratchMenuItem}" /> - -