using Aurora.Api; using VisionCommon; using System; using System.Windows; using System.Windows.Controls; using System.Collections.Generic; using System.Windows.Controls.Primitives; using VisionCommonUI.Resources; using System.Windows.Media; using DevExpress.Xpf.Core; using AuroraUIComponent.UserControls; using Aurora; using Hermes; using System.IO; using System.Threading; using System.Drawing; namespace VisionCommonUI { public partial class ChildImageSettingView : UserControl { private Logger _Logger = new Logger(typeof(ChildImageSettingView).Name); private FovInfo _FovInfo; private eCamId _CamId; private CameraAgentBase _CameraAgent; private CamConfig _CamConfig; private ICameraDisplay _CameraDisplay; private object _GrabImage; private const int ROW_COL_MAX_CNT = 10; public ChildImageSettingView(FovInfo fovInfo, ICameraDisplay cameraDisplay) { _FovInfo = fovInfo; _CamId = VisionRecipeManager.GetCamRecipe(_FovInfo).CamId; _CameraAgent = CameraAgentManager.GetCameraAgent(_FovInfo); _CameraDisplay = cameraDisplay; UpdateCamConfig(); InitializeComponent(); } private void UserControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { bool isVisible = (bool)e.NewValue; if (isVisible == true) { UpdateView(); } } public void UpdateView() { try { ClearView(); AddRowColumnDefinitions(); for (int rowIdx = 0; rowIdx < _CamConfig.ChildImage.RowCnt; rowIdx++) { for (int colIdx = 0; colIdx < _CamConfig.ChildImage.ColCnt; colIdx++) { var toggleBtn = new ToggleButton() { //Style = FindResource("defaultToggleButton") as Style, Content = GetToggleButtonContent(rowIdx, colIdx), IsChecked = IsChecked(rowIdx, colIdx), Tag = GetRowColIdxString(rowIdx, colIdx) }; Grid.SetRow(toggleBtn, rowIdx); Grid.SetColumn(toggleBtn, colIdx); gridRowCols.Children.Add(toggleBtn); } } } catch (Exception e) { _Logger.FuncE(e.Message); } } private Viewbox GetToggleButtonContent(int rowIdx, int colIdx) { var viewBox = new Viewbox(); viewBox.Stretch = Stretch.Uniform; try { var grid = new Grid(); var rowDef1 = new RowDefinition(); var rowDef2 = new RowDefinition(); var rowDef3 = new RowDefinition(); var rowDef4 = new RowDefinition(); grid.RowDefinitions.Add(rowDef1); grid.RowDefinitions.Add(rowDef2); grid.RowDefinitions.Add(rowDef3); grid.RowDefinitions.Add(rowDef4); ChildBufRowCol childBufRowCol = GetChildBufRowCol(rowIdx, colIdx); // Row, Col 인덱스 var tbRowCols = new TextBlock() { Text = GetRowColIdxString(rowIdx, colIdx), // 3x3 예시 : 00, 01, 02, ... 22 FontSize = 20, FontWeight = FontWeights.SemiBold, Margin = new Thickness(5) }; // 플라잉 순서 인덱스 var tbIdx = new TextBox() { FontSize = 20, FontWeight = FontWeights.SemiBold, Width = 55, Text = (childBufRowCol != null) ? childBufRowCol.PosIdx.ToString() : GetDefaultIndexFromRowCols(rowIdx, colIdx).ToString(), // 3x3 예시 : 0, 1, 2, ... 8 Foreground = new SolidColorBrush(Colors.Orange), Background = new SolidColorBrush(Colors.Gray), Margin = new Thickness(5) }; // 플라잉 모터 위치 var spMotorPos = new StackPanel() { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Right }; var motorPosX = new UCKeyValue() { KeyText = "M.X", FontWeight = FontWeights.Light, ValueTextSize = 13, ValueTextWidth = "100", DecimalPlaces = 4, Value = (childBufRowCol != null) ? (decimal)childBufRowCol.MotorPos.X : 0, ValueTextFgColor = new SolidColorBrush(Colors.Orange) }; var motorPosY = new UCKeyValue() { KeyText = "M.Y", FontWeight = FontWeights.Light, ValueTextSize = 13, ValueTextWidth = "100", DecimalPlaces = 4, Value = (childBufRowCol != null) ? (decimal)childBufRowCol.MotorPos.Y : 0, ValueTextFgColor = new SolidColorBrush(Colors.Orange) }; spMotorPos.Children.Add(motorPosX); spMotorPos.Children.Add(motorPosY); // 플라잉 모터 위치 오프셋 var spMotorPosOffset = new StackPanel() { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Right }; var motorPosOffsetX = new UCKeyValue() { KeyText = "O.X", FontWeight = FontWeights.Light, ValueTextSize = 13, ValueTextWidth = "100", DecimalPlaces = 4, Value = (childBufRowCol != null) ? (decimal)childBufRowCol.MotorPosOffset.X : 0, ValueTextFgColor = new SolidColorBrush(Colors.Orange) }; var motorPosOffsetY = new UCKeyValue() { KeyText = "O.Y", FontWeight = FontWeights.Light, ValueTextSize = 13, ValueTextWidth = "100", DecimalPlaces = 4, Value = (childBufRowCol != null) ? (decimal)childBufRowCol.MotorPosOffset.Y : 0, ValueTextFgColor = new SolidColorBrush(Colors.Orange) }; spMotorPosOffset.Children.Add(motorPosOffsetX); spMotorPosOffset.Children.Add(motorPosOffsetY); Grid.SetRow(tbRowCols, 0); Grid.SetRow(tbIdx, 1); Grid.SetRow(spMotorPos, 2); Grid.SetRow(spMotorPosOffset, 3); grid.Children.Add(tbRowCols); grid.Children.Add(tbIdx); grid.Children.Add(spMotorPos); grid.Children.Add(spMotorPosOffset); viewBox.Child = grid; } catch (Exception e) { _Logger.FuncE(e.Message); } return viewBox; } private bool IsChecked(int rowIdx, int colIdx) { foreach (ChildBufRowCol bufRowCol in _CamConfig.ChildImage.ChildBufRowCols) { if (bufRowCol.RowIdx == rowIdx && bufRowCol.ColIdx == colIdx) { if (bufRowCol.Enabled) { return true; } } } return false; } private ChildBufRowCol GetChildBufRowCol(int rowIdx, int colIdx) { foreach (ChildBufRowCol childBufRowCol in _CamConfig.ChildImage.ChildBufRowCols) { if (childBufRowCol.RowIdx == rowIdx && childBufRowCol.ColIdx == colIdx) { return childBufRowCol; } } return null; } private int GetDefaultIndexFromRowCols(int rowIdx, int colIdx) { var rowCols = _CamConfig.ChildImage.ChildBufRowCols; for (int i = 0; i < rowCols.Count; i++) { if (rowCols[i].RowIdx == rowIdx && rowCols[i].ColIdx == colIdx) { return i; } } return _CamConfig.ChildImage.ColCnt * rowIdx + colIdx; } private string GetRowColIdxString(int rowIdx, int colIdx) { return string.Format($"{rowIdx}{colIdx}"); } private (int, int) GetRowColIdxFromTag(object tag) { var tagStr = (string)tag; int rowIdx = Convert.ToInt16(tagStr[0] - '0'); int colIdx = Convert.ToInt16(tagStr[1] - '0'); return (rowIdx, colIdx); } private void ClearView() { gridRowCols.Children.Clear(); gridRowCols.RowDefinitions.Clear(); gridRowCols.ColumnDefinitions.Clear(); } private void AddRowColumnDefinitions() { var rows = GetUiPosRows(); var cols = GetUiPosCols(); foreach (var row in rows) { gridRowCols.RowDefinitions.Add(new RowDefinition()); } foreach (var col in cols) { gridRowCols.ColumnDefinitions.Add(new ColumnDefinition()); } } private List GetUiPosRows() { var rows = new SortedSet(); for (int rowIdx = 0; rowIdx < _CamConfig.ChildImage.RowCnt; rowIdx++) { rows.Add(rowIdx); } return new List(rows); } private List GetUiPosCols() { var cols = new SortedSet(); for (int colIdx = 0; colIdx < _CamConfig.ChildImage.ColCnt; colIdx++) { cols.Add(colIdx); } return new List(cols); } private void UpdateCamConfig() { var camConfig = VisionEnv.AuroraEnv.DeviceManager.GetDeviceConfig(_CamId.ToString()) as CamConfig; _CamConfig = camConfig.Clone(); } private void Click_RemoveRow(object sender, RoutedEventArgs e) { if (_CamConfig.ChildImage.RowCnt == 1) { return; } _CamConfig.ChildImage.RowCnt--; UpdateView(); } private void Click_AddRow(object sender, RoutedEventArgs e) { if (_CamConfig.ChildImage.RowCnt == ROW_COL_MAX_CNT) { _Logger.FuncE($"Row count exceeds the maximum number {ROW_COL_MAX_CNT}"); return; } _CamConfig.ChildImage.RowCnt++; UpdateView(); } private void Click_RemoveCol(object sender, RoutedEventArgs e) { if (_CamConfig.ChildImage.ColCnt == 1) { return; } _CamConfig.ChildImage.ColCnt--; UpdateView(); } private void Click_AddCol(object sender, RoutedEventArgs e) { if (_CamConfig.ChildImage.ColCnt == ROW_COL_MAX_CNT) { _Logger.FuncE($"Column count exceeds the maximum number {ROW_COL_MAX_CNT}."); return; } _CamConfig.ChildImage.ColCnt++; UpdateView(); } private void Click_Reload(object sender, RoutedEventArgs e) { UpdateCamConfig(); UpdateView(); } private void Click_FlyingGrab(object sender, RoutedEventArgs e) { if (_CameraAgent.IsLiveRunning()) { _CameraAgent.StopLive(); } _CameraAgent.StartFlying(_FovInfo); EquipAdapter.Instance.EquipTrigger.SetTrigger(); EquipAdapter.Instance.EquipTrigger.TriggerOn(); Thread.Sleep(_CamConfig.HwTrigConfig.OffDelay_Ms); EquipAdapter.Instance.EquipTrigger.TriggerOff(); if (_GrabImage == null) { _GrabImage = _CameraAgent.CloneImageBuffer(); } int res = _CameraAgent.GetGrabImageFromBuffer(_CameraDisplay, ref _GrabImage); if (res == E1.OK) { _Logger.FuncI("[HwTrigger] Grab Success."); } else { _Logger.FuncE("[HwTrigger] Grab Failed."); } _CameraAgent.StopFlying(); } private void Click_Verify(object sender, RoutedEventArgs e) { object parentImage = null; if (_CameraAgent.VerifyChildImage(_CameraDisplay, ref parentImage) == E1.OK) { var filePath = Path.Combine(ApplicationExt.DataPath, "1_VerifyParentImage.png"); IpAdapter.Instance.IpEnvironment.SaveImage(filePath, parentImage); VerifyParentImageWindow.Instance.Show(filePath); VerifyParentImageWindow.Instance.Activate(); } else { _Logger.FuncE("Failed to create the verify parent image."); } } private void Click_Save(object sender, RoutedEventArgs e) { try { var camConfig = VisionEnv.AuroraEnv.DeviceManager.GetDeviceConfig(_CamId.ToString()) as CamConfig; camConfig.ChildImage.RowCnt = _CamConfig.ChildImage.RowCnt; camConfig.ChildImage.ColCnt = _CamConfig.ChildImage.ColCnt; camConfig.ChildImage.ChildBufRowCols.Clear(); var imageSizeWidthChild = (int)(camConfig.ImageSize.Width * camConfig.ImageSizeRatioX); var mageSizeHeightChild = (int)(camConfig.ImageSize.Height * camConfig.ImageSizeRatioY); foreach (ToggleButton toggleBtn in gridRowCols.Children) { // Enabled 추출 var childBufRowCol = new ChildBufRowCol(); childBufRowCol.Enabled = ((bool)toggleBtn.IsChecked) ? true : false; // Row & Col Idx 추출 (int rowIdx, int colIdx) = GetRowColIdxFromTag(toggleBtn.Tag); childBufRowCol.RowIdx = rowIdx; childBufRowCol.ColIdx = colIdx; Viewbox content = (Viewbox)toggleBtn.Content; Grid child = (Grid)content.Child; // PosIdx 추출 (Flying 순서) TextBox tb = (TextBox)child.Children[1]; int posIdx = Convert.ToInt16(tb.Text); if (IsValidPosIdx(posIdx)) { childBufRowCol.PosIdx = posIdx; } else { int minPosIdx = 0; _Logger.FuncE($"The range of pos idx must be between 0 and {camConfig.ChildImage.ChildBufRowCols.Count - 1}."); tb.Text = minPosIdx.ToString(); childBufRowCol.PosIdx = minPosIdx; // Min 값으로 대체 } // MotorPos 추출 StackPanel spMotorPos = (StackPanel)child.Children[2]; childBufRowCol.MotorPos.X = (double)(spMotorPos.Children[0] as UCKeyValue).Value; childBufRowCol.MotorPos.Y = (double)(spMotorPos.Children[1] as UCKeyValue).Value; // MotorPosOffset 추출 StackPanel spMotorPosOffset = (StackPanel)child.Children[3]; childBufRowCol.MotorPosOffset.X = (double)(spMotorPosOffset.Children[0] as UCKeyValue).Value; childBufRowCol.MotorPosOffset.Y = (double)(spMotorPosOffset.Children[1] as UCKeyValue).Value; // Rect 복원 childBufRowCol.Rect = new Rectangle( imageSizeWidthChild * childBufRowCol.ColIdx, mageSizeHeightChild * childBufRowCol.RowIdx, imageSizeWidthChild, mageSizeHeightChild); camConfig.ChildImage.ChildBufRowCols.Add(childBufRowCol); } _CamConfig = camConfig.Clone(); // 저장된 camConfig와 Sync를 맞춰주기 위함 VisionEnv.AuroraEnv.DeviceManager.SaveDeviceConfig(_CamId.ToString()); MessageBoxUtil.ShowMessageBoxOk(StrTokens.MSG_O_SaveCompleted); _CameraAgent.Deactivate(); _CameraAgent.Activate(); VisionEnv.AuroraEnv.EventPublisher.Publish(new EventMessage(_CamId.ToString(), VisionEventId.SAVE_CHILD_IMAGE_SETTING)); } catch (Exception ex) { _Logger.FuncE(ex.Message); } } private bool IsValidPosIdx(int posIdx) { if (posIdx >= 0 && posIdx < _CamConfig.ChildImage.ChildBufRowCols.Count) { return true; } else { return false; } } private IEnumerable ToEnumerable(Func> getEnumerator) { var enumerator = getEnumerator(); while (enumerator.MoveNext()) { yield return enumerator.Current; } } private void Click_Close(object sender, RoutedEventArgs e) { var rootParent = this.GetRootParent(); if (rootParent != null) { var window = rootParent as Window; window?.Close(); } } } }