using DA_Assets.DAI; using DA_Assets.Extensions; using DA_Assets.FCU.Model; using DA_Assets.Tools; using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; namespace DA_Assets.FCU { internal class DifferenceCheckerWindow : LinkedEditorWindow { private Dictionary, BlackInspector>> _importScrolls = new Dictionary, BlackInspector>>(); private Dictionary, BlackInspector>> _removeScrolls = new Dictionary, BlackInspector>>(); private List _selectableHambItems = new List(); private UpdateBool _importNew = new UpdateBool(false, false); private UpdateBool _importFigmaChanged = new UpdateBool(false, false); private UpdateBool _importUnityChanged = new UpdateBool(false, false); private UpdateBool _importOther = new UpdateBool(false, false); private Vector2Int _importNewCount = Vector2Int.zero; private Vector2Int _figmaSideChangedCount = Vector2Int.zero; private Vector2Int _unitySideChangedCount = Vector2Int.zero; private Vector2Int _importOtherCount = Vector2Int.zero; private PreImportInput _diffStruct = new PreImportInput(); private Action _callback; private bool inited = false; internal void SetData(PreImportInput diffStruct, Action callback) { _diffStruct = diffStruct; _callback = callback; foreach (SelectableObject item in diffStruct.ToImport.Childs) { var isrw = new InfinityScrollRectWindow, BlackInspector>(4, 100); isrw.SetData(item.Childs, DrawToImportItem); _importScrolls.Add($"toimport_{item.Object.Id}", isrw); } foreach (SelectableObject item in diffStruct.ToRemove.Childs) { var isrw = new InfinityScrollRectWindow, BlackInspector>(11, 40); isrw.SetData(item.Childs, DrawToRemoveItem); _removeScrolls.Add(item.Object.Id, isrw); } UpdateFlags(); inited = true; } private void CheckForClose() { if (_diffStruct.IsDefault()) { Debug.Log($"{this.name} was closed because the scripts were recompiled."); this.Close(); } } public override void DrawGUI() { if (!inited) { return; } else { CheckForClose(); } gui.DrawGroup(new Group { GroupType = GroupType.Vertical, Scroll = true, Style = gui.ColoredStyle.DiffCheckerBackground, Body = () => { gui.DrawSplitGroup(new Group { GroupType = GroupType.Horizontal, SplitterWidth = 5, SplitterStartPos = 500 }, () => { LeftPanel(); }, () => { RightPanel(); }); } }); } private void Footer() { if (gui.OutlineButton(FcuLocKey.label_apply_and_continue.Localize(), FcuLocKey.tooltip_apply_and_continue.Localize())) { Apply_OnClick(); } void Apply_OnClick() { IEnumerable toImportSelected = _diffStruct.ToImport.Childs .SelectRecursive(x => x.Childs) .Where(x => x.Selected) .Select(x => x.Object.Id); IEnumerable toRemoveSelected = _diffStruct.ToRemove.Childs .SelectRecursive(x => x.Childs) .Where(x => x.Selected) .Select(x => x.Object); PreImportOutput result = new PreImportOutput { ToImport = toImportSelected, ToRemove = toRemoveSelected }; _callback.Invoke(result); this.Close(); } } private void LeftPanel() { gui.DrawGroup(new Group { GroupType = GroupType.Vertical, Style = gui.ColoredStyle.DiffCheckerToImportPanel, Body = () => { gui.SectionHeader(FcuLocKey.label_components_to_import.Localize(), FcuLocKey.tooltip_components_to_import.Localize()); gui.DrawGroup(new Group { GroupType = GroupType.Horizontal, Body = () => { DrawToImport(); gui.Space5(); if (gui.OutlineButton(FcuLocKey.label_open_diff_checker.Localize())) { Application.OpenURL("https://www.diffchecker.com/"); } gui.FlexibleSpace(); } }); gui.Space15(); DrawMenuWithChildren(_diffStruct.ToImport); void DrawMenuWithChildren(SelectableObject item) { bool isRoot = item.Object.Id == PreImportDataCreator.TO_IMPORT_MENU_ID; int allCount = item.CountItems(x => x.Childs.IsEmpty()); int selectedCount = item.CountItems(x => x.Childs.IsEmpty() && x.Selected); bool isAllSelected = selectedCount == allCount; GUIContent gc; string menuId = "toimport_"; if (isRoot) { menuId += PreImportDataCreator.TO_IMPORT_MENU_ID; gc = new GUIContent(FcuLocKey.label_components_with_count.Localize(selectedCount, allCount), ""); gui.DrawMenu(_selectableHambItems, new HamburgerItem { Id = menuId, GUIContent = gc, Body = () => { foreach (SelectableObject child in item.Childs) { DrawMenuWithChildren(child); } }, CheckBoxValueChanged = (id, value) => { SetAllChildrenSelected(item, value, false); } }); } else { menuId += item.Object.Id; gc = new GUIContent($"{item.Object.Name} ({selectedCount}/{allCount})", ""); gui.DrawMenu(_selectableHambItems, new HamburgerItem { Id = menuId, GUIContent = gc, Body = () => { _importScrolls[menuId].OnGUI(); }, CheckBoxValueChanged = (id, value) => { SetAllChildrenSelected(item, value, false); } }); } SetCheckboxValue(menuId, isAllSelected); } } }); } private void SetCheckboxValue(string id, bool value) { UpdateBool checkBoxValue = _selectableHambItems.FirstOrDefault(item => item.Id == id)?.CheckBoxValue; if (checkBoxValue != null) { checkBoxValue.Value = value; checkBoxValue.Temp = value; } } private void RightPanel() { gui.DrawGroup(new Group { GroupType = GroupType.Vertical, Style = gui.ColoredStyle.DiffCheckerToRemovePanel, Body = () => { gui.SectionHeader(FcuLocKey.label_remove_from_scene.Localize(), FcuLocKey.tooltip_remove_from_scene.Localize()); gui.Space15(); foreach (SelectableObject item in _diffStruct.ToRemove.Childs) { int selectedCount = item.Childs.Count(x => x.Selected); int allCount = item.Childs.Count; bool isAllSelected = selectedCount == allCount; string menuId = "toremove_"; menuId += item.Object.Id; gui.DrawMenu(_selectableHambItems, new HamburgerItem { Id = menuId, GUIContent = new GUIContent($"{item.Object.Names.ObjectName} ({selectedCount}/{allCount})"), Body = () => _removeScrolls[item.Object.Id].OnGUI(), CheckBoxValueChanged = (id, value) => { SetAllChildrenSelected(item, value, true); } }); SetCheckboxValue(menuId, isAllSelected); } gui.FlexibleSpace(); gui.Line(); gui.Space15(); Footer(); } }); } private void SetAllChildrenSelected(SelectableObject item, bool selected, bool remove) where T : IHaveId { SetAllChildrenSelectedRecursive(item, selected); UpdateFlags(); void SetAllChildrenSelectedRecursive(SelectableObject currentItem, bool value) { currentItem.Selected = value; foreach (SelectableObject child in currentItem.Childs) { SetAllChildrenSelectedRecursive(child, value); } } } private void DrawToRemoveItem(SelectableObject item) { bool oldState = item.Selected; item.Selected = gui.CheckBox(new GUIContent(GetHierarchyWithoutRootFrame(item.Object.NameHierarchy)), item.Selected, false); if (item.Selected != oldState) { UpdateFlags(); } } private string GetHierarchyWithoutRootFrame(string hierarchy) { int index = hierarchy.IndexOf(FcuConfig.HierarchyDelimiter); if (index != -1) { return ".." + hierarchy.Substring(index); } return hierarchy; } private void DrawToImportItem(SelectableObject item) { gui.DrawGroup(new Group { GroupType = GroupType.Horizontal, Body = () => { gui.DrawGroup(new Group { GroupType = GroupType.Vertical, Body = () => { gui.Space5(); string name = item.Object.OldData != null ? item.Object.OldData.NameHierarchy : item.Object.NewData.Data.NameHierarchy; name = GetHierarchyWithoutRootFrame(name); gui.Label12px(name, null, GUILayout.ExpandWidth(true)); gui.Space5(); gui.DrawGroup(new Group { GroupType = GroupType.Horizontal, Body = () => { bool oldState = item.Selected; item.Selected = GUILayout.Toggle(item.Selected, GUIContent.none); if (item.Selected != oldState) { UpdateFlags(); } gui.DrawGroup(new Group { GroupType = GroupType.Vertical, Body = () => { if (gui.Button(new GUIContent(FcuLocKey.label_copy_old_data.Localize()), GUILayout.Width(120))) { GUIUtility.systemCopyBuffer = item.Object.OldData.HashData; } gui.Space5(); if (gui.Button(new GUIContent(FcuLocKey.label_copy_new_data.Localize()), GUILayout.Width(120))) { GUIUtility.systemCopyBuffer = item.Object.NewData.Data.HashData; } } }); gui.Space15(); gui.DrawGroup(new Group { GroupType = GroupType.Vertical, Body = () => { if (item.Object.HasFigmaDiff) { gui.Label12px(FcuLocKey.label_different_component_data.Localize(), null, GUILayout.ExpandWidth(true)); } else { gui.Label12px("_"); } gui.Space5(); if (item.Object.Color.Enabled) { gui.Label12px(FcuLocKey.label_has_differences.Localize( "Color", $"{item.Object.Color.Value1}", $"{item.Object.Color.Value2}"), null, GUILayout.ExpandWidth(true)); } else { gui.Label12px("_"); } gui.Space5(); if (item.Object.Size.Enabled) { gui.Label12px(FcuLocKey.label_has_differences.Localize( "Size", $"{item.Object.Size.Value1}", $"{item.Object.Size.Value2}"), null, GUILayout.ExpandWidth(true)); } else { gui.Label12px("_"); } } }); gui.FlexibleSpace(); } }); gui.Space5(); gui.Line(); } }); } }); } private void UpdateData(Func, bool> condition, bool value) { foreach (SelectableObject item in _diffStruct.ToImport.Childs) { UpdateDataRecursive(item, condition, value); } } private void UpdateDataRecursive(SelectableObject item, Func, bool> condition, bool value) { if (condition(item)) item.Selected = value; foreach (SelectableObject child in item.Childs) { UpdateDataRecursive(child, condition, value); } } private void UpdateFlags() { int importNewCount = _diffStruct.ToImport.CountItems(x => x.Childs.IsEmpty() && x.Object.IsNew); int importNewCountSelected = _diffStruct.ToImport.CountItems(x => x.Childs.IsEmpty() && x.Object.IsNew && x.Selected); _importNewCount = new Vector2Int(importNewCountSelected, importNewCount); _importNew.Value = importNewCount == importNewCountSelected && importNewCount != 0; _importNew.Temp = importNewCount == importNewCountSelected && importNewCount != 0; int figmaChangedCount = _diffStruct.ToImport.CountItems(x => x.Childs.IsEmpty() && x.Object.HasFigmaDiff); int figmaChangedCountSelected = _diffStruct.ToImport.CountItems(x => x.Childs.IsEmpty() && x.Object.HasFigmaDiff && x.Selected); _figmaSideChangedCount = new Vector2Int(figmaChangedCountSelected, figmaChangedCount); _importFigmaChanged.Value = figmaChangedCount == figmaChangedCountSelected && figmaChangedCount != 0; _importFigmaChanged.Temp = figmaChangedCount == figmaChangedCountSelected && figmaChangedCount != 0; int unityChangedCount = _diffStruct.ToImport.CountItems(x => x.Childs.IsEmpty() && x.Object.IsUnitySideChanged()); int unityChangedCountSelected = _diffStruct.ToImport.CountItems(x => x.Childs.IsEmpty() && x.Object.IsUnitySideChanged() && x.Selected); _unitySideChangedCount = new Vector2Int(unityChangedCountSelected, unityChangedCount); _importUnityChanged.Value = unityChangedCount == unityChangedCountSelected && unityChangedCount != 0; _importUnityChanged.Temp = unityChangedCount == unityChangedCountSelected && unityChangedCount != 0; int importSameCount = _diffStruct.ToImport.CountItems(x => x.Object.IsNotChanged() && !x.Object.IsUnitySideChanged()); int importSameCountSelected = _diffStruct.ToImport.CountItems(x => x.Object.IsNotChanged() && x.Selected); _importOtherCount = new Vector2Int(importSameCountSelected, importSameCount); _importOther.Value = importSameCount == importSameCountSelected && importSameCount != 0; _importOther.Temp = importSameCount == importSameCountSelected && importSameCount != 0; } private void ImportFigmaSide_OnChanged() { UpdateData(x => x.Object.HasFigmaDiff, _importFigmaChanged.Value); UpdateFlags(); } private void UnitySide_OnChanged() { UpdateData(x => x.Object.Color.Enabled || x.Object.Size.Enabled, _importUnityChanged.Value); UpdateFlags(); } private void ImportNew_OnChanged() { UpdateData(x => x.Object.IsNew, _importNew.Value); UpdateFlags(); } private void ImportOther_OnChanged() { UpdateData(x => !x.Object.IsNew && !x.Object.HasFigmaDiff && !x.Object.IsUnitySideChanged(), _importOther.Value); UpdateFlags(); } private void DrawToImport() { gui.DrawTable(new Action[4, 3] { { () => { gui.Label12px(FcuLocKey.label_new.Localize(), FcuLocKey.tooltip_new_components.Localize()); }, () => { GUILayout.Label($"{_importNewCount.x}/{_importNewCount.y}", EditorStyles.boldLabel); }, () => { _importNew.Value = GUILayout.Toggle(_importNew.Value, GUIContent.none); if (_importNew.Value != _importNew.Temp) { _importNew.Temp = _importNew.Value; ImportNew_OnChanged(); } } }, { () => { gui.Label12px(FcuLocKey.label_changed_in_figma.Localize(), FcuLocKey.tooltip_changed_in_figma.Localize()); }, () => { GUILayout.Label($"{_figmaSideChangedCount.x}/{_figmaSideChangedCount.y}", EditorStyles.boldLabel); }, () => { _importFigmaChanged.Value = GUILayout.Toggle(_importFigmaChanged.Value, GUIContent.none); if (_importFigmaChanged.Value != _importFigmaChanged.Temp) { _importFigmaChanged.Temp = _importFigmaChanged.Value; ImportFigmaSide_OnChanged(); } } }, { () => { gui.Label12px(FcuLocKey.label_changed_in_unity.Localize(), FcuLocKey.tooltip_changed_in_unity.Localize()); }, () => { GUILayout.Label($"{_unitySideChangedCount.x}/{_unitySideChangedCount.y}", EditorStyles.boldLabel); }, () => { _importUnityChanged.Value = GUILayout.Toggle(_importUnityChanged.Value, GUIContent.none); if (_importUnityChanged.Value != _importUnityChanged.Temp) { _importUnityChanged.Temp = _importUnityChanged.Value; UnitySide_OnChanged(); } } }, { () => { gui.Label12px(FcuLocKey.label_without_changes.Localize(), FcuLocKey.tooltip_label_without_changes.Localize()); }, () => { GUILayout.Label($"{_importOtherCount.x}/{_importOtherCount.y}", EditorStyles.boldLabel); }, () => { _importOther.Value = GUILayout.Toggle(_importOther.Value, GUIContent.none); if (_importOther.Value != _importOther.Temp) { _importOther.Temp = _importOther.Value; ImportOther_OnChanged(); } } }, }); } } internal static class DiffCheckerExtensions { internal static bool IsNotChanged(this DiffInfo diffInfo) { return !diffInfo.IsNew && !diffInfo.HasFigmaDiff && !diffInfo.IsUnitySideChanged(); } internal static bool IsUnitySideChanged(this DiffInfo diffInfo) { return diffInfo.Color.Enabled || diffInfo.Size.Enabled; } internal static int CountItems(this SelectableObject obj, Func, bool> condition) { int count = 0; if (condition(obj)) { count++; } foreach (SelectableObject child in obj.Childs) { count += child.CountItems(condition); } return count; } } }