12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856 |
- using UnityEngine;
- using UnityEditor;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- namespace UnityVersionControl
- {
- /// <summary>
- /// Enhanced Visual Conflict Resolution Window for Unity Version Control
- /// Provides rich visual comparison and resolution for different asset types
- /// </summary>
- public class VersionControlConflictResolver : EditorWindow
- {
- #region Fields
- private Vector2 conflictListScrollPosition;
- private Vector2 viewerScrollPosition;
- private Vector2 leftScrollPosition;
- private Vector2 rightScrollPosition;
- private int selectedConflictIndex = 0;
-
- private readonly List<MockConflictInfo> mockConflicts = new List<MockConflictInfo>();
- private ConflictViewer currentViewer;
-
- // Enhanced visual comparison
- private int selectedViewMode = 0;
- private readonly string[] viewModeNames = { "Side by Side", "3D Preview", "Properties", "Overlay" };
- private float splitRatio = 0.5f;
- private bool isDraggingSplitter = false;
-
- // 3D Preview system
- private Camera previewCameraLeft;
- private Camera previewCameraRight;
- private RenderTexture leftRenderTexture;
- private RenderTexture rightRenderTexture;
- private GameObject leftPreviewObject;
- private GameObject rightPreviewObject;
- private GameObject previewEnvironment;
- private Light previewLight;
-
- // UI State
- private bool showLineNumbers = true;
- private bool showWhitespace = false;
- private bool wordWrap = false;
- private string searchText = "";
- private Vector3 cameraRotation = new Vector3(15f, -30f, 0f);
- private float cameraDistance = 3f;
-
- // Static callback for when conflicts are resolved
- private static System.Action onConflictsResolved;
-
- // Visual constants
- private static readonly Color backgroundColor = new Color(0.22f, 0.22f, 0.22f);
- private static readonly Color cardColor = new Color(0.28f, 0.28f, 0.28f);
- private static readonly Color accentColor = new Color(0.3f, 0.7f, 1f);
- private static readonly Color successColor = new Color(0.3f, 0.8f, 0.3f);
- private static readonly Color warningColor = new Color(1f, 0.8f, 0.2f);
- private static readonly Color errorColor = new Color(1f, 0.4f, 0.4f);
- private static readonly Color localColor = new Color(0.4f, 0.8f, 0.4f);
- private static readonly Color remoteColor = new Color(0.4f, 0.6f, 1f);
- private static readonly Color conflictColor = new Color(1f, 0.6f, 0.2f);
- private static readonly Color selectedColor = new Color(0.2f, 0.5f, 0.8f, 0.3f);
-
- // Caches
- private readonly Dictionary<string, Texture2D> textureCache = new Dictionary<string, Texture2D>();
- private readonly Dictionary<string, Material> materialCache = new Dictionary<string, Material>();
- private readonly Dictionary<string, GameObject> prefabCache = new Dictionary<string, GameObject>();
- private readonly List<PropertyDifference> currentPropertyDifferences = new List<PropertyDifference>();
- #endregion
- #region Unity Lifecycle
- [MenuItem("Window/Version Control/Conflict Resolver", false, 1)]
- public static void ShowWindow()
- {
- var window = GetWindow<VersionControlConflictResolver>();
- window.minSize = new Vector2(1000, 700);
- window.Initialize();
- }
- public static void ShowWindow(System.Action onResolved)
- {
- onConflictsResolved = onResolved;
- var window = GetWindow<VersionControlConflictResolver>("Visual Conflict Resolver");
- window.minSize = new Vector2(1000, 700);
- window.Initialize();
- }
- private void OnEnable()
- {
- Initialize();
- Setup3DPreviewSystem();
- }
- private void OnDisable()
- {
- CleanupTextures();
- Cleanup3DPreviewSystem();
-
- // Clean up callback to prevent memory leaks
- if (onConflictsResolved != null)
- {
- Debug.LogWarning("Conflict resolver closed without resolving conflicts - cleaning up callback");
- onConflictsResolved = null;
- }
- }
- private void OnGUI()
- {
- try
- {
- HandleEvents();
- DrawBackground();
- DrawEnhancedHeader();
- DrawMainLayout();
- }
- catch (Exception ex)
- {
- Debug.LogError($"Error in ConflictResolver OnGUI: {ex.Message}");
- DrawFallbackUI();
- }
- }
- #endregion
- #region Initialization
- private void Initialize()
- {
- CreateMockConflicts();
- if (mockConflicts.Count > 0)
- {
- SelectConflict(0);
- }
- }
- private void CreateMockConflicts()
- {
- try
- {
- mockConflicts.Clear();
-
- // Script conflict
- mockConflicts.Add(new MockConflictInfo
- {
- fileName = "PlayerController.cs",
- assetType = ConflictAssetType.Script,
- conflictType = ConflictType.PropertyValueDifference,
- description = "Method implementation differs",
- localVersion = "public float speed = 5.0f;\npublic void Move() {\n // Local implementation\n transform.Translate(Vector3.forward * speed);\n}",
- remoteVersion = "public float speed = 7.0f;\npublic void Move() {\n // Remote implementation\n rb.velocity = Vector3.forward * speed;\n}",
- resolution = ConflictResolution.Unresolved
- });
- // Prefab conflict
- mockConflicts.Add(new MockConflictInfo
- {
- fileName = "PlayerPrefab.prefab",
- assetType = ConflictAssetType.Prefab,
- conflictType = ConflictType.ComponentAdded,
- description = "Components differ between versions",
- localVersion = "Components: Transform, MeshRenderer, Rigidbody, BoxCollider",
- remoteVersion = "Components: Transform, MeshRenderer, Rigidbody, AudioSource, ParticleSystem",
- resolution = ConflictResolution.Unresolved
- });
- // Material conflict
- mockConflicts.Add(new MockConflictInfo
- {
- fileName = "PlayerMaterial.mat",
- assetType = ConflictAssetType.Material,
- conflictType = ConflictType.PropertyValueDifference,
- description = "Material properties have different values",
- localVersion = "Albedo: Red (1,0,0), Metallic: 0.5, Smoothness: 0.8",
- remoteVersion = "Albedo: Blue (0,0,1), Metallic: 0.2, Smoothness: 0.6",
- resolution = ConflictResolution.Unresolved
- });
- // Scene conflict
- mockConflicts.Add(new MockConflictInfo
- {
- fileName = "MainScene.unity",
- assetType = ConflictAssetType.Scene,
- conflictType = ConflictType.GameObjectMoved,
- description = "GameObject positions and lighting differ",
- localVersion = "Camera: (0,10,0), Lighting: Realtime GI",
- remoteVersion = "Camera: (5,10,-5), Lighting: Baked GI",
- resolution = ConflictResolution.Unresolved
- });
- // Texture conflict
- mockConflicts.Add(new MockConflictInfo
- {
- fileName = "CharacterTexture.png",
- assetType = ConflictAssetType.Texture,
- conflictType = ConflictType.AssetReplaced,
- description = "Different texture versions",
- localVersion = "Local texture: 512x512, RGB format",
- remoteVersion = "Remote texture: 1024x1024, RGBA format",
- resolution = ConflictResolution.Unresolved
- });
- }
- catch (Exception ex)
- {
- Debug.LogError($"Error creating mock conflicts: {ex.Message}");
- }
- }
- private void CleanupTextures()
- {
- foreach (var texture in textureCache.Values)
- {
- if (texture != null) DestroyImmediate(texture);
- }
- textureCache.Clear();
- }
- #endregion
- #region 3D Preview System
- private void Setup3DPreviewSystem()
- {
- try
- {
- // Create preview environment
- previewEnvironment = new GameObject("ConflictResolver_PreviewEnvironment");
- previewEnvironment.hideFlags = HideFlags.HideAndDontSave;
-
- // Setup lighting
- var lightGO = new GameObject("PreviewLight");
- lightGO.transform.SetParent(previewEnvironment.transform);
- lightGO.hideFlags = HideFlags.HideAndDontSave;
- previewLight = lightGO.AddComponent<Light>();
- previewLight.type = LightType.Directional;
- previewLight.intensity = 1.0f;
- previewLight.color = Color.white;
- previewLight.transform.rotation = Quaternion.Euler(50f, -30f, 0f);
-
- // Setup left camera
- var leftCameraGO = new GameObject("PreviewCamera_Left");
- leftCameraGO.transform.SetParent(previewEnvironment.transform);
- leftCameraGO.hideFlags = HideFlags.HideAndDontSave;
- previewCameraLeft = leftCameraGO.AddComponent<Camera>();
- previewCameraLeft.clearFlags = CameraClearFlags.SolidColor;
- previewCameraLeft.backgroundColor = new Color(0.1f, 0.1f, 0.1f);
- previewCameraLeft.cullingMask = 1 << 30; // Layer 30 for left previews
-
- // Setup right camera
- var rightCameraGO = new GameObject("PreviewCamera_Right");
- rightCameraGO.transform.SetParent(previewEnvironment.transform);
- rightCameraGO.hideFlags = HideFlags.HideAndDontSave;
- previewCameraRight = rightCameraGO.AddComponent<Camera>();
- previewCameraRight.clearFlags = CameraClearFlags.SolidColor;
- previewCameraRight.backgroundColor = new Color(0.1f, 0.1f, 0.1f);
- previewCameraRight.cullingMask = 1 << 31; // Layer 31 for right previews
-
- // Create render textures
- leftRenderTexture = new RenderTexture(256, 256, 16);
- rightRenderTexture = new RenderTexture(256, 256, 16);
-
- previewCameraLeft.targetTexture = leftRenderTexture;
- previewCameraRight.targetTexture = rightRenderTexture;
-
- // Position cameras
- UpdateCameraPositions();
- }
- catch (Exception ex)
- {
- Debug.LogError($"Failed to setup 3D preview system: {ex.Message}");
- }
- }
- private void UpdateCameraPositions()
- {
- if (previewCameraLeft != null && previewCameraRight != null)
- {
- var position = Quaternion.Euler(cameraRotation) * Vector3.back * cameraDistance;
-
- previewCameraLeft.transform.position = position + Vector3.left * 2f;
- previewCameraLeft.transform.LookAt(Vector3.left * 2f);
-
- previewCameraRight.transform.position = position + Vector3.right * 2f;
- previewCameraRight.transform.LookAt(Vector3.right * 2f);
- }
- }
- private void Cleanup3DPreviewSystem()
- {
- try
- {
- if (leftRenderTexture != null)
- {
- leftRenderTexture.Release();
- DestroyImmediate(leftRenderTexture);
- leftRenderTexture = null;
- }
-
- if (rightRenderTexture != null)
- {
- rightRenderTexture.Release();
- DestroyImmediate(rightRenderTexture);
- rightRenderTexture = null;
- }
-
- if (leftPreviewObject != null)
- {
- DestroyImmediate(leftPreviewObject);
- leftPreviewObject = null;
- }
-
- if (rightPreviewObject != null)
- {
- DestroyImmediate(rightPreviewObject);
- rightPreviewObject = null;
- }
-
- if (previewEnvironment != null)
- {
- DestroyImmediate(previewEnvironment);
- previewEnvironment = null;
- }
-
- previewCameraLeft = null;
- previewCameraRight = null;
- previewLight = null;
- }
- catch (Exception ex)
- {
- Debug.LogError($"Failed to cleanup 3D preview system: {ex.Message}");
- }
- }
- private void RefreshPreviewObjects()
- {
- if (selectedViewMode == 1 && selectedConflictIndex >= 0 && selectedConflictIndex < mockConflicts.Count)
- {
- var conflict = mockConflicts[selectedConflictIndex];
- LoadPreviewObjects(conflict);
- }
- }
- private void LoadPreviewObjects(MockConflictInfo conflict)
- {
- try
- {
- // Clean up existing preview objects
- if (leftPreviewObject != null)
- DestroyImmediate(leftPreviewObject);
- if (rightPreviewObject != null)
- DestroyImmediate(rightPreviewObject);
-
- if (conflict.assetType == ConflictAssetType.Prefab)
- {
- leftPreviewObject = CreateMockPrefab(true);
- rightPreviewObject = CreateMockPrefab(false);
-
- // Position objects
- leftPreviewObject.transform.position = Vector3.left * 2f;
- rightPreviewObject.transform.position = Vector3.right * 2f;
-
- // Set layers
- SetLayerRecursively(leftPreviewObject, 30);
- SetLayerRecursively(rightPreviewObject, 31);
- }
- else if (conflict.assetType == ConflictAssetType.Material)
- {
- // Create sphere previews for materials
- leftPreviewObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
- rightPreviewObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
-
- leftPreviewObject.hideFlags = HideFlags.HideAndDontSave;
- rightPreviewObject.hideFlags = HideFlags.HideAndDontSave;
-
- leftPreviewObject.transform.position = Vector3.left * 2f;
- rightPreviewObject.transform.position = Vector3.right * 2f;
-
- // Apply different materials
- var leftRenderer = leftPreviewObject.GetComponent<Renderer>();
- var rightRenderer = rightPreviewObject.GetComponent<Renderer>();
-
- leftRenderer.material.color = Color.red;
- rightRenderer.material.color = Color.blue;
-
- SetLayerRecursively(leftPreviewObject, 30);
- SetLayerRecursively(rightPreviewObject, 31);
- }
- }
- catch (Exception ex)
- {
- Debug.LogError($"Failed to load preview objects: {ex.Message}");
- }
- }
- private GameObject CreateMockPrefab(bool isLocal)
- {
- var prefab = GameObject.CreatePrimitive(PrimitiveType.Cube);
- prefab.hideFlags = HideFlags.HideAndDontSave;
- prefab.name = isLocal ? "LocalPrefab" : "RemotePrefab";
-
- if (isLocal)
- {
- prefab.transform.localScale = Vector3.one;
- var renderer = prefab.GetComponent<Renderer>();
- renderer.material.color = Color.red;
- }
- else
- {
- prefab.transform.localScale = Vector3.one * 1.2f;
- var renderer = prefab.GetComponent<Renderer>();
- renderer.material.color = Color.blue;
-
- // Add additional component to show difference
- var audioSource = prefab.AddComponent<AudioSource>();
- }
-
- return prefab;
- }
- private void SetLayerRecursively(GameObject obj, int layer)
- {
- obj.layer = layer;
- foreach (Transform child in obj.transform)
- {
- SetLayerRecursively(child.gameObject, layer);
- }
- }
- #endregion
- #region Enhanced GUI Drawing
- private void DrawBackground()
- {
- var rect = new Rect(0, 0, position.width, position.height);
- EditorGUI.DrawRect(rect, backgroundColor);
- }
- private void DrawEnhancedHeader()
- {
- DrawCard(() =>
- {
- using (new EditorGUILayout.HorizontalScope())
- {
- var iconRect = GUILayoutUtility.GetRect(24, 24);
- var iconTexture = CreateRoundedTexture(errorColor, 24, 4);
- GUI.DrawTexture(iconRect, iconTexture);
-
- GUILayout.Space(8);
-
- using (new EditorGUILayout.VerticalScope())
- {
- var titleStyle = new GUIStyle(EditorStyles.boldLabel);
- titleStyle.fontSize = 14;
- titleStyle.normal.textColor = Color.white;
- EditorGUILayout.LabelField("Visual Conflict Resolution", titleStyle);
-
- var subtitleStyle = new GUIStyle(EditorStyles.label);
- subtitleStyle.normal.textColor = new Color(0.8f, 0.8f, 0.8f);
- subtitleStyle.fontSize = 11;
- EditorGUILayout.LabelField($"Resolve {mockConflicts.Count(c => c.resolution == ConflictResolution.Unresolved)} conflicts to continue", subtitleStyle);
- }
-
- GUILayout.FlexibleSpace();
-
- DrawViewModeSelector();
-
- GUILayout.Space(8);
-
- DrawResolutionButtons();
- }
- }, 12);
- }
- private void DrawViewModeSelector()
- {
- using (new EditorGUILayout.VerticalScope())
- {
- EditorGUILayout.LabelField("View Mode:", EditorStyles.miniLabel);
-
- var newViewMode = GUILayout.Toolbar(selectedViewMode, viewModeNames, GUILayout.Width(300));
- if (newViewMode != selectedViewMode)
- {
- selectedViewMode = newViewMode;
- RefreshPreviewObjects();
- GenerateCurrentPropertyDifferences();
- Repaint();
- }
- }
- }
- private void DrawResolutionButtons()
- {
- var unresolvedCount = mockConflicts.Count(c => c.resolution == ConflictResolution.Unresolved);
- var canProceed = unresolvedCount == 0;
-
- using (new EditorGUI.DisabledScope(!canProceed))
- {
- var proceedStyle = new GUIStyle(GUI.skin.button);
- proceedStyle.normal.textColor = Color.white;
- proceedStyle.fixedHeight = 28;
- proceedStyle.fontStyle = FontStyle.Bold;
-
- if (canProceed)
- {
- proceedStyle.normal.background = CreateRoundedTexture(successColor, 28, 4);
- }
-
- if (GUILayout.Button("✓ APPLY RESOLUTIONS", proceedStyle, GUILayout.Width(140)))
- {
- ApplyResolutions();
- }
- }
-
- GUILayout.Space(8);
-
- var cancelStyle = new GUIStyle(GUI.skin.button);
- cancelStyle.normal.textColor = errorColor;
- cancelStyle.fixedHeight = 28;
-
- if (GUILayout.Button("✕ CANCEL PULL", cancelStyle, GUILayout.Width(100)))
- {
- Close();
- }
- }
- private void DrawMainLayout()
- {
- EditorGUILayout.Space(8);
-
- using (new EditorGUILayout.HorizontalScope())
- {
- // Left panel - Conflict list
- DrawConflictList();
-
- GUILayout.Space(8);
-
- // Right panel - Conflict viewer
- DrawConflictViewer();
- }
- }
- private void DrawConflictList()
- {
- using (new EditorGUILayout.VerticalScope(GUILayout.Width(280)))
- {
- DrawCard(() =>
- {
- DrawSectionHeader("Conflicting Files", $"{mockConflicts.Count} files need resolution");
-
- EditorGUILayout.Space(8);
-
- using (var scrollView = new EditorGUILayout.ScrollViewScope(conflictListScrollPosition))
- {
- conflictListScrollPosition = scrollView.scrollPosition;
-
- for (int i = 0; i < mockConflicts.Count; i++)
- {
- DrawConflictListItem(mockConflicts[i], i);
- if (i < mockConflicts.Count - 1)
- EditorGUILayout.Space(4);
- }
- }
- }, 12);
- }
- }
- private void DrawConflictListItem(MockConflictInfo conflict, int index)
- {
- var isSelected = selectedConflictIndex == index;
- var itemRect = EditorGUILayout.BeginVertical();
-
- if (isSelected)
- {
- EditorGUI.DrawRect(itemRect, selectedColor);
- }
-
- if (GUI.Button(itemRect, "", GUIStyle.none))
- {
- SelectConflict(index);
- }
-
- GUILayout.Space(8);
-
- using (new EditorGUILayout.HorizontalScope())
- {
- GUILayout.Space(8);
-
- // Asset type icon
- var iconSize = 20;
- var iconRect = GUILayoutUtility.GetRect(iconSize, iconSize);
- var iconColor = GetAssetTypeColor(conflict.assetType);
- var iconTexture = CreateRoundedTexture(iconColor, iconSize, iconSize / 2);
- GUI.DrawTexture(iconRect, iconTexture);
-
- var iconStyle = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
- iconStyle.normal.textColor = Color.white;
- iconStyle.fontSize = 8;
- iconStyle.fontStyle = FontStyle.Bold;
- GUI.Label(iconRect, GetAssetTypeIcon(conflict.assetType), iconStyle);
-
- GUILayout.Space(8);
-
- using (new EditorGUILayout.VerticalScope())
- {
- var fileNameStyle = new GUIStyle(EditorStyles.boldLabel);
- fileNameStyle.fontSize = 12;
- fileNameStyle.normal.textColor = Color.white;
- EditorGUILayout.LabelField(conflict.fileName, fileNameStyle);
-
- var descStyle = new GUIStyle(EditorStyles.label);
- descStyle.normal.textColor = new Color(0.7f, 0.7f, 0.7f);
- descStyle.fontSize = 10;
- descStyle.wordWrap = true;
- EditorGUILayout.LabelField(conflict.description, descStyle);
- }
-
- GUILayout.FlexibleSpace();
-
- // Resolution status
- var statusSize = 16;
- var statusRect = GUILayoutUtility.GetRect(statusSize, statusSize);
- var statusColor = conflict.resolution switch
- {
- ConflictResolution.Unresolved => errorColor,
- ConflictResolution.UseLocal => localColor,
- ConflictResolution.UseRemote => remoteColor,
- _ => warningColor
- };
-
- var statusTexture = CreateRoundedTexture(statusColor, statusSize, statusSize / 2);
- GUI.DrawTexture(statusRect, statusTexture);
-
- var statusIcon = conflict.resolution switch
- {
- ConflictResolution.Unresolved => "!",
- ConflictResolution.UseLocal => "L",
- ConflictResolution.UseRemote => "R",
- _ => "?"
- };
-
- var statusStyle = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
- statusStyle.normal.textColor = Color.white;
- statusStyle.fontSize = 8;
- statusStyle.fontStyle = FontStyle.Bold;
- GUI.Label(statusRect, statusIcon, statusStyle);
-
- GUILayout.Space(8);
- }
-
- GUILayout.Space(8);
- EditorGUILayout.EndVertical();
- }
- private void DrawConflictViewer()
- {
- using (new EditorGUILayout.VerticalScope())
- {
- if (selectedConflictIndex >= 0 && selectedConflictIndex < mockConflicts.Count)
- {
- var selectedConflict = mockConflicts[selectedConflictIndex];
- DrawCard(() =>
- {
- DrawConflictViewerContent(selectedConflict);
- }, 12);
- }
- else
- {
- DrawCard(() =>
- {
- var emptyStyle = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
- emptyStyle.normal.textColor = new Color(0.6f, 0.6f, 0.6f);
- emptyStyle.fontSize = 14;
- EditorGUILayout.LabelField("Select a conflict to view details", emptyStyle);
- }, 32);
- }
- }
- }
- private void DrawConflictViewerContent(MockConflictInfo conflict)
- {
- DrawSectionHeader($"{conflict.fileName} Conflict", $"{conflict.assetType} • {conflict.conflictType}");
-
- EditorGUILayout.Space(8);
-
- // Enhanced conflict viewer based on selected mode
- switch (selectedViewMode)
- {
- case 0: DrawSideBySideComparison(conflict); break;
- case 1: Draw3DPreviewComparison(conflict); break;
- case 2: DrawPropertiesComparison(conflict); break;
- case 3: DrawOverlayComparison(conflict); break;
- }
-
- EditorGUILayout.Space(16);
- DrawResolutionControls(conflict);
- }
- private void DrawSideBySideComparison(MockConflictInfo conflict)
- {
- var viewerRect = EditorGUILayout.BeginHorizontal(GUILayout.Height(400));
-
- // Left panel
- var leftWidth = viewerRect.width * splitRatio;
- using (new EditorGUILayout.VerticalScope(GUILayout.Width(leftWidth)))
- {
- DrawVersionPanel(conflict, true, "LOCAL VERSION");
- }
-
- // Splitter
- DrawSplitter();
-
- // Right panel
- using (new EditorGUILayout.VerticalScope())
- {
- DrawVersionPanel(conflict, false, "REMOTE VERSION");
- }
-
- EditorGUILayout.EndHorizontal();
- }
- private void DrawVersionPanel(MockConflictInfo conflict, bool isLocal, string title)
- {
- var headerColor = isLocal ? localColor : remoteColor;
- var content = isLocal ? conflict.localVersion : conflict.remoteVersion;
-
- var headerStyle = new GUIStyle(EditorStyles.boldLabel);
- headerStyle.normal.textColor = headerColor;
- headerStyle.alignment = TextAnchor.MiddleCenter;
- EditorGUILayout.LabelField(title, headerStyle);
-
- EditorGUILayout.Space(4);
-
- // Enhanced content based on asset type
- switch (conflict.assetType)
- {
- case ConflictAssetType.Material:
- DrawMaterialPreview(conflict, isLocal);
- break;
- case ConflictAssetType.Prefab:
- DrawPrefabPreview(conflict, isLocal);
- break;
- case ConflictAssetType.Texture:
- DrawTexturePreview(conflict, isLocal);
- break;
- case ConflictAssetType.Scene:
- DrawScenePreview(conflict, isLocal);
- break;
- case ConflictAssetType.Script:
- DrawScriptPreview(conflict, isLocal);
- break;
- default:
- DrawGenericPreview(content, headerColor);
- break;
- }
- }
- private void DrawMaterialPreview(MockConflictInfo conflict, bool isLocal)
- {
- // Material sphere preview
- var previewRect = GUILayoutUtility.GetRect(200, 150);
- EditorGUI.DrawRect(previewRect, new Color(0.1f, 0.1f, 0.1f));
-
- // Mock material sphere
- var centerRect = new Rect(previewRect.x + 50, previewRect.y + 25, 100, 100);
- var sphereColor = isLocal ? new Color(0.8f, 0.2f, 0.2f) : new Color(0.2f, 0.2f, 0.8f);
-
- // Draw gradient to simulate sphere lighting
- for (int i = 0; i < 50; i++)
- {
- var t = i / 50f;
- var currentColor = Color.Lerp(sphereColor * 1.5f, sphereColor * 0.3f, t);
- var rect = new Rect(centerRect.x + i, centerRect.y + i * 0.5f, centerRect.width - i * 2, centerRect.height - i);
- EditorGUI.DrawRect(rect, currentColor);
- }
-
- // Material properties
- EditorGUILayout.Space(8);
- var materialData = isLocal ?
- "Albedo: Red (1,0,0)\nMetallic: 0.5\nSmoothness: 0.8\nEmission: Off" :
- "Albedo: Blue (0,0,1)\nMetallic: 0.2\nSmoothness: 0.6\nEmission: On";
-
- var propStyle = new GUIStyle(EditorStyles.textArea);
- propStyle.fontSize = 10;
- propStyle.normal.textColor = new Color(0.9f, 0.9f, 0.9f);
- EditorGUILayout.TextArea(materialData, propStyle, GUILayout.Height(60));
- }
- private void DrawPrefabPreview(MockConflictInfo conflict, bool isLocal)
- {
- // Hierarchy view
- var hierarchyRect = GUILayoutUtility.GetRect(200, 200);
- EditorGUI.DrawRect(hierarchyRect, new Color(0.15f, 0.15f, 0.15f));
-
- GUILayout.BeginArea(hierarchyRect);
- GUILayout.Space(8);
-
- if (isLocal)
- {
- DrawHierarchyItem("Player", 0, true);
- DrawHierarchyItem("Mesh Renderer", 1, false);
- DrawHierarchyItem("Box Collider", 1, false);
- DrawHierarchyItem("Rigidbody", 1, false);
- DrawHierarchyItem("Player Controller", 1, false);
- }
- else
- {
- DrawHierarchyItem("Player", 0, true);
- DrawHierarchyItem("Mesh Renderer", 1, false);
- DrawHierarchyItem("Box Collider", 1, false);
- DrawHierarchyItem("Rigidbody", 1, false);
- DrawHierarchyItem("Audio Source", 1, true); // New component
- DrawHierarchyItem("Particle System", 1, true); // New component
- DrawHierarchyItem("Player Controller", 1, false);
- }
-
- GUILayout.EndArea();
- }
- private void DrawHierarchyItem(string name, int indent, bool isHighlighted)
- {
- using (new EditorGUILayout.HorizontalScope())
- {
- GUILayout.Space(indent * 16 + 8);
-
- var itemStyle = new GUIStyle(EditorStyles.label);
- itemStyle.fontSize = 10;
- itemStyle.normal.textColor = isHighlighted ? conflictColor : Color.white;
-
- var icon = indent == 0 ? "🎮" : "⚙️";
- EditorGUILayout.LabelField($"{icon} {name}", itemStyle, GUILayout.Height(16));
- }
- }
- private void DrawTexturePreview(MockConflictInfo conflict, bool isLocal)
- {
- var previewRect = GUILayoutUtility.GetRect(200, 150);
- EditorGUI.DrawRect(previewRect, new Color(0.1f, 0.1f, 0.1f));
-
- // Mock texture preview with checkerboard pattern
- var textureRect = new Rect(previewRect.x + 25, previewRect.y + 25, 150, 100);
- var textureColor = isLocal ?
- new Color(0.8f, 0.6f, 0.4f) : // Brown texture
- new Color(0.4f, 0.6f, 0.8f); // Blue texture
-
- // Draw checkerboard pattern
- for (int x = 0; x < 15; x++)
- {
- for (int y = 0; y < 10; y++)
- {
- var checkerColor = ((x + y) % 2 == 0) ? textureColor : textureColor * 0.7f;
- var checkerRect = new Rect(textureRect.x + x * 10, textureRect.y + y * 10, 10, 10);
- EditorGUI.DrawRect(checkerRect, checkerColor);
- }
- }
-
- // Texture info
- EditorGUILayout.Space(8);
- var textureInfo = isLocal ?
- "Size: 512x512\nFormat: RGB24\nMipmaps: Yes\nFilter: Bilinear" :
- "Size: 1024x1024\nFormat: RGBA32\nMipmaps: Yes\nFilter: Trilinear";
-
- var infoStyle = new GUIStyle(EditorStyles.textArea);
- infoStyle.fontSize = 10;
- infoStyle.normal.textColor = new Color(0.9f, 0.9f, 0.9f);
- EditorGUILayout.TextArea(textureInfo, infoStyle, GUILayout.Height(60));
- }
- private void DrawScenePreview(MockConflictInfo conflict, bool isLocal)
- {
- var previewRect = GUILayoutUtility.GetRect(200, 150);
- EditorGUI.DrawRect(previewRect, new Color(0.05f, 0.05f, 0.1f)); // Dark blue background
-
- // Mock scene elements
- var cameraPos = isLocal ? new Vector2(50, 50) : new Vector2(100, 80);
- var lightPos = isLocal ? new Vector2(150, 30) : new Vector2(120, 40);
-
- // Draw ground plane
- var groundRect = new Rect(previewRect.x + 20, previewRect.y + 120, previewRect.width - 40, 20);
- EditorGUI.DrawRect(groundRect, new Color(0.3f, 0.5f, 0.3f));
-
- // Draw camera
- var cameraRect = new Rect(previewRect.x + cameraPos.x, previewRect.y + cameraPos.y, 20, 20);
- EditorGUI.DrawRect(cameraRect, Color.yellow);
-
- // Draw light
- var lightRect = new Rect(previewRect.x + lightPos.x, previewRect.y + lightPos.y, 15, 15);
- EditorGUI.DrawRect(lightRect, Color.white);
-
- // Scene info
- EditorGUILayout.Space(8);
- var sceneInfo = isLocal ?
- "Camera: (0,10,0)\nLighting: Realtime GI\nSkybox: Default\nFog: Disabled" :
- "Camera: (5,10,-5)\nLighting: Baked GI\nSkybox: Procedural\nFog: Enabled";
-
- var infoStyle = new GUIStyle(EditorStyles.textArea);
- infoStyle.fontSize = 10;
- infoStyle.normal.textColor = new Color(0.9f, 0.9f, 0.9f);
- EditorGUILayout.TextArea(sceneInfo, infoStyle, GUILayout.Height(60));
- }
- private void DrawScriptPreview(MockConflictInfo conflict, bool isLocal)
- {
- var content = isLocal ? conflict.localVersion : conflict.remoteVersion;
-
- using (var scrollView = new EditorGUILayout.ScrollViewScope(isLocal ? leftScrollPosition : rightScrollPosition, GUILayout.Height(200)))
- {
- if (isLocal) leftScrollPosition = scrollView.scrollPosition;
- else rightScrollPosition = scrollView.scrollPosition;
-
- var codeStyle = new GUIStyle(EditorStyles.textArea);
- codeStyle.wordWrap = wordWrap;
- codeStyle.richText = false;
- codeStyle.font = EditorGUIUtility.Load("Consolas") as Font ?? GUI.skin.font;
- codeStyle.fontSize = 10;
-
- var lines = content.Split('\n');
- for (int i = 0; i < lines.Length; i++)
- {
- using (new EditorGUILayout.HorizontalScope())
- {
- if (showLineNumbers)
- {
- var lineNumStyle = new GUIStyle(EditorStyles.label);
- lineNumStyle.normal.textColor = new Color(0.5f, 0.5f, 0.5f);
- lineNumStyle.fontSize = 9;
- lineNumStyle.alignment = TextAnchor.MiddleRight;
- EditorGUILayout.LabelField((i + 1).ToString(), lineNumStyle, GUILayout.Width(30));
- }
-
- EditorGUILayout.LabelField(lines[i], codeStyle, GUILayout.Height(16));
- }
- }
- }
-
- // Code options
- EditorGUILayout.Space(4);
- using (new EditorGUILayout.HorizontalScope())
- {
- showLineNumbers = EditorGUILayout.Toggle("Lines", showLineNumbers, GUILayout.Width(60));
- wordWrap = EditorGUILayout.Toggle("Wrap", wordWrap, GUILayout.Width(60));
- }
- }
- private void DrawGenericPreview(string content, Color borderColor)
- {
- var rect = EditorGUILayout.BeginVertical();
- EditorGUI.DrawRect(rect, new Color(borderColor.r, borderColor.g, borderColor.b, 0.1f));
-
- GUILayout.Space(8);
-
- using (new EditorGUILayout.HorizontalScope())
- {
- GUILayout.Space(8);
-
- using (new EditorGUILayout.VerticalScope())
- {
- var contentStyle = new GUIStyle(EditorStyles.textArea);
- contentStyle.wordWrap = true;
- contentStyle.normal.textColor = new Color(0.9f, 0.9f, 0.9f);
-
- EditorGUILayout.TextArea(content, contentStyle, GUILayout.Height(200));
- }
-
- GUILayout.Space(8);
- }
-
- GUILayout.Space(8);
- EditorGUILayout.EndVertical();
- }
- private void Draw3DPreviewComparison(MockConflictInfo conflict)
- {
- if (conflict.assetType == ConflictAssetType.Prefab || conflict.assetType == ConflictAssetType.Scene || conflict.assetType == ConflictAssetType.Material)
- {
- EditorGUILayout.LabelField("3D Preview Comparison", EditorStyles.boldLabel);
- EditorGUILayout.Space(8);
-
- using (new EditorGUILayout.HorizontalScope())
- {
- // Left 3D preview
- using (new EditorGUILayout.VerticalScope())
- {
- EditorGUILayout.LabelField("LOCAL VERSION", EditorStyles.centeredGreyMiniLabel);
- Draw3DPreviewPanel(true);
- }
-
- GUILayout.Space(8);
-
- // Right 3D preview
- using (new EditorGUILayout.VerticalScope())
- {
- EditorGUILayout.LabelField("REMOTE VERSION", EditorStyles.centeredGreyMiniLabel);
- Draw3DPreviewPanel(false);
- }
- }
-
- // 3D Controls
- EditorGUILayout.Space(8);
- Draw3DControls();
- }
- else
- {
- EditorGUILayout.HelpBox("3D Preview is only available for Prefabs, Scenes, and Materials.", MessageType.Info);
- DrawSideBySideComparison(conflict);
- }
- }
- private void Draw3DPreviewPanel(bool isLocal)
- {
- var previewRect = GUILayoutUtility.GetRect(300, 200);
- EditorGUI.DrawRect(previewRect, new Color(0.1f, 0.1f, 0.1f));
-
- // Draw render texture if available
- var renderTexture = isLocal ? leftRenderTexture : rightRenderTexture;
- if (renderTexture != null)
- {
- GUI.DrawTexture(previewRect, renderTexture, ScaleMode.ScaleToFit);
- }
- else
- {
- // Fallback: mock 3D preview
- var centerX = previewRect.x + previewRect.width * 0.5f;
- var centerY = previewRect.y + previewRect.height * 0.5f;
-
- var cubeSize = isLocal ? 40 : 50;
- var cubeColor = isLocal ? new Color(0.8f, 0.2f, 0.2f) : new Color(0.2f, 0.2f, 0.8f);
-
- var cubeRect = new Rect(centerX - cubeSize/2, centerY - cubeSize/2, cubeSize, cubeSize);
- EditorGUI.DrawRect(cubeRect, cubeColor);
-
- // Draw simple perspective lines to simulate 3D
- var offset = 10;
- var topRect = new Rect(centerX - cubeSize/2 + offset, centerY - cubeSize/2 - offset, cubeSize, cubeSize);
- EditorGUI.DrawRect(topRect, new Color(cubeColor.r + 0.2f, cubeColor.g + 0.2f, cubeColor.b + 0.2f));
- }
-
- // Preview info
- var infoStyle = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
- infoStyle.normal.textColor = Color.white;
- infoStyle.fontSize = 10;
-
- var infoRect = new Rect(previewRect.x, previewRect.y + previewRect.height - 20, previewRect.width, 20);
- GUI.Label(infoRect, isLocal ? "Local 3D Preview" : "Remote 3D Preview", infoStyle);
- }
- private void Draw3DControls()
- {
- using (new EditorGUILayout.HorizontalScope())
- {
- if (GUILayout.Button("Reset Camera", GUILayout.Width(100)))
- {
- cameraRotation = new Vector3(15f, -30f, 0f);
- cameraDistance = 3f;
- UpdateCameraPositions();
- }
-
- GUILayout.Space(8);
-
- if (GUILayout.Button("Focus on Differences", GUILayout.Width(150)))
- {
- // Focus camera on differences
- Debug.Log("Focusing on differences");
- }
-
- GUILayout.FlexibleSpace();
-
- EditorGUILayout.LabelField("Wireframe:", GUILayout.Width(70));
- var showWireframe = EditorGUILayout.Toggle(false, GUILayout.Width(20));
- }
-
- EditorGUILayout.Space(4);
-
- // Camera controls
- using (new EditorGUILayout.HorizontalScope())
- {
- EditorGUILayout.LabelField("Camera:", GUILayout.Width(60));
-
- cameraDistance = EditorGUILayout.Slider("Distance", cameraDistance, 1f, 10f);
-
- var newRotationY = EditorGUILayout.Slider("Rotation", cameraRotation.y, -180f, 180f);
- if (Math.Abs(newRotationY - cameraRotation.y) > 0.1f)
- {
- cameraRotation.y = newRotationY;
- UpdateCameraPositions();
- }
- }
- }
- private void DrawPropertiesComparison(MockConflictInfo conflict)
- {
- EditorGUILayout.LabelField("Property-by-Property Comparison", EditorStyles.boldLabel);
- EditorGUILayout.Space(8);
-
- // Search bar
- using (new EditorGUILayout.HorizontalScope())
- {
- EditorGUILayout.LabelField("Search:", GUILayout.Width(50));
- searchText = EditorGUILayout.TextField(searchText);
-
- if (GUILayout.Button("Clear", GUILayout.Width(50)))
- searchText = "";
- }
-
- EditorGUILayout.Space(4);
-
- using (var scrollView = new EditorGUILayout.ScrollViewScope(viewerScrollPosition, GUILayout.Height(300)))
- {
- viewerScrollPosition = scrollView.scrollPosition;
-
- var properties = currentPropertyDifferences;
- if (!string.IsNullOrEmpty(searchText))
- {
- properties = properties.Where(p => p.propertyName.ToLower().Contains(searchText.ToLower())).ToList();
- }
-
- foreach (var prop in properties)
- {
- DrawPropertyDifference(prop);
- EditorGUILayout.Space(4);
- }
-
- if (properties.Count == 0)
- {
- EditorGUILayout.LabelField("No properties found", EditorStyles.centeredGreyMiniLabel);
- }
- }
- }
- private void DrawPropertyDifference(PropertyDifference prop)
- {
- var propRect = EditorGUILayout.BeginHorizontal();
-
- // Background color based on change type
- Color bgColor = prop.changeType switch
- {
- PropertyChangeType.Added => new Color(0.2f, 0.6f, 0.2f, 0.3f),
- PropertyChangeType.Removed => new Color(0.6f, 0.2f, 0.2f, 0.3f),
- PropertyChangeType.Modified => new Color(0.6f, 0.4f, 0.2f, 0.3f),
- _ => Color.clear
- };
-
- if (bgColor != Color.clear)
- {
- EditorGUI.DrawRect(propRect, bgColor);
- }
-
- GUILayout.Space(8);
-
- // Property name
- var nameStyle = new GUIStyle(EditorStyles.boldLabel);
- nameStyle.normal.textColor = Color.white;
- nameStyle.fontSize = 11;
- EditorGUILayout.LabelField(prop.propertyName, nameStyle, GUILayout.Width(200));
-
- // Change type icon
- var changeIcon = prop.changeType switch
- {
- PropertyChangeType.Added => "+",
- PropertyChangeType.Removed => "-",
- PropertyChangeType.Modified => "⟳",
- _ => "?"
- };
-
- var iconStyle = new GUIStyle(EditorStyles.label);
- iconStyle.normal.textColor = prop.changeType switch
- {
- PropertyChangeType.Added => Color.green,
- PropertyChangeType.Removed => Color.red,
- PropertyChangeType.Modified => Color.yellow,
- _ => Color.white
- };
- EditorGUILayout.LabelField(changeIcon, iconStyle, GUILayout.Width(20));
-
- // Values comparison
- using (new EditorGUILayout.VerticalScope())
- {
- if (!string.IsNullOrEmpty(prop.localValue))
- {
- var localStyle = new GUIStyle(EditorStyles.label);
- localStyle.normal.textColor = localColor;
- localStyle.fontSize = 10;
- EditorGUILayout.LabelField($"Local: {prop.localValue}", localStyle);
- }
-
- if (!string.IsNullOrEmpty(prop.remoteValue))
- {
- var remoteStyle = new GUIStyle(EditorStyles.label);
- remoteStyle.normal.textColor = remoteColor;
- remoteStyle.fontSize = 10;
- EditorGUILayout.LabelField($"Remote: {prop.remoteValue}", remoteStyle);
- }
- }
-
- GUILayout.FlexibleSpace();
-
- // Individual resolution choice
- if (prop.changeType == PropertyChangeType.Modified)
- {
- using (new EditorGUILayout.VerticalScope(GUILayout.Width(100)))
- {
- var localSelected = prop.resolution == ConflictResolution.UseLocal;
- var remoteSelected = prop.resolution == ConflictResolution.UseRemote;
-
- var localStyle = new GUIStyle(GUI.skin.button);
- if (localSelected) localStyle.normal.background = CreateRoundedTexture(localColor, 18, 4);
-
- if (GUILayout.Button("Use Local", localStyle, GUILayout.Height(18)))
- {
- prop.resolution = ConflictResolution.UseLocal;
- Debug.Log($"Using local value for {prop.propertyName}");
- }
-
- var remoteStyle = new GUIStyle(GUI.skin.button);
- if (remoteSelected) remoteStyle.normal.background = CreateRoundedTexture(remoteColor, 18, 4);
-
- if (GUILayout.Button("Use Remote", remoteStyle, GUILayout.Height(18)))
- {
- prop.resolution = ConflictResolution.UseRemote;
- Debug.Log($"Using remote value for {prop.propertyName}");
- }
- }
- }
-
- GUILayout.Space(8);
- EditorGUILayout.EndHorizontal();
- }
- private void DrawOverlayComparison(MockConflictInfo conflict)
- {
- if (conflict.assetType == ConflictAssetType.Texture)
- {
- DrawTextureOverlay(conflict);
- }
- else if (conflict.assetType == ConflictAssetType.Material)
- {
- DrawMaterialOverlay(conflict);
- }
- else
- {
- EditorGUILayout.HelpBox("Overlay comparison is only available for Textures and Materials.", MessageType.Info);
- DrawSideBySideComparison(conflict);
- }
- }
- private void DrawTextureOverlay(MockConflictInfo conflict)
- {
- EditorGUILayout.LabelField("Texture Overlay Comparison", EditorStyles.boldLabel);
- EditorGUILayout.Space(8);
-
- var overlayRect = GUILayoutUtility.GetRect(400, 300);
- EditorGUI.DrawRect(overlayRect, new Color(0.1f, 0.1f, 0.1f));
-
- // Mock overlay - checkerboard showing differences
- for (int x = 0; x < 40; x++)
- {
- for (int y = 0; y < 30; y++)
- {
- var isLocalPixel = (x + y) % 3 == 0;
- var isDifferent = (x + y) % 7 == 0;
-
- Color pixelColor;
- if (isDifferent)
- {
- pixelColor = conflictColor; // Show differences
- }
- else if (isLocalPixel)
- {
- pixelColor = new Color(0.8f, 0.2f, 0.2f, 0.7f); // Local
- }
- else
- {
- pixelColor = new Color(0.2f, 0.2f, 0.8f, 0.7f); // Remote
- }
-
- var pixelRect = new Rect(overlayRect.x + x * 10, overlayRect.y + y * 10, 10, 10);
- EditorGUI.DrawRect(pixelRect, pixelColor);
- }
- }
-
- // Overlay controls
- EditorGUILayout.Space(8);
- using (new EditorGUILayout.HorizontalScope())
- {
- EditorGUILayout.LabelField("Blend Mode:", GUILayout.Width(80));
- var blendMode = EditorGUILayout.Popup(0, new[] { "Normal", "Difference", "Overlay" }, GUILayout.Width(100));
-
- GUILayout.Space(16);
-
- EditorGUILayout.LabelField("Opacity:", GUILayout.Width(60));
- var opacity = EditorGUILayout.Slider(0.5f, 0f, 1f, GUILayout.Width(100));
- }
- }
- private void DrawMaterialOverlay(MockConflictInfo conflict)
- {
- EditorGUILayout.LabelField("Material Property Overlay", EditorStyles.boldLabel);
- EditorGUILayout.Space(8);
-
- // Side-by-side material spheres with difference highlighting
- using (new EditorGUILayout.HorizontalScope())
- {
- // Local material sphere
- var leftRect = GUILayoutUtility.GetRect(150, 150);
- EditorGUI.DrawRect(leftRect, new Color(0.1f, 0.1f, 0.1f));
- var leftSphere = new Rect(leftRect.x + 25, leftRect.y + 25, 100, 100);
- EditorGUI.DrawRect(leftSphere, new Color(0.8f, 0.2f, 0.2f));
-
- GUILayout.Space(16);
-
- // Remote material sphere
- var rightRect = GUILayoutUtility.GetRect(150, 150);
- EditorGUI.DrawRect(rightRect, new Color(0.1f, 0.1f, 0.1f));
- var rightSphere = new Rect(rightRect.x + 25, rightRect.y + 25, 100, 100);
- EditorGUI.DrawRect(rightSphere, new Color(0.2f, 0.2f, 0.8f));
- }
-
- // Property differences highlight
- EditorGUILayout.Space(8);
- EditorGUILayout.LabelField("Differences:", EditorStyles.boldLabel);
- DrawPropertyDifference(new PropertyDifference
- {
- propertyName = "Albedo Color",
- localValue = "Red (1,0,0)",
- remoteValue = "Blue (0,0,1)",
- changeType = PropertyChangeType.Modified
- });
- }
- private void DrawSplitter()
- {
- var splitterRect = GUILayoutUtility.GetRect(4, 400);
- EditorGUI.DrawRect(splitterRect, new Color(0.5f, 0.5f, 0.5f, 0.5f));
-
- EditorGUIUtility.AddCursorRect(splitterRect, MouseCursor.ResizeHorizontal);
-
- if (Event.current.type == EventType.MouseDown && splitterRect.Contains(Event.current.mousePosition))
- {
- isDraggingSplitter = true;
- Event.current.Use();
- }
-
- if (isDraggingSplitter)
- {
- if (Event.current.type == EventType.MouseDrag)
- {
- splitRatio = Mathf.Clamp(Event.current.mousePosition.x / position.width, 0.2f, 0.8f);
- Event.current.Use();
- Repaint();
- }
- else if (Event.current.type == EventType.MouseUp)
- {
- isDraggingSplitter = false;
- Event.current.Use();
- }
- }
- }
- private void DrawResolutionControls(MockConflictInfo conflict)
- {
- using (new EditorGUILayout.HorizontalScope())
- {
- GUILayout.FlexibleSpace();
-
- var localButtonStyle = new GUIStyle(GUI.skin.button);
- localButtonStyle.normal.textColor = Color.white;
- localButtonStyle.fixedHeight = 32;
- localButtonStyle.fontSize = 12;
- localButtonStyle.fontStyle = FontStyle.Bold;
-
- if (conflict.resolution == ConflictResolution.UseLocal)
- {
- localButtonStyle.normal.background = CreateRoundedTexture(localColor, 32, 4);
- }
-
- if (GUILayout.Button("◀ USE LOCAL", localButtonStyle, GUILayout.Width(120)))
- {
- SetConflictResolution(selectedConflictIndex, ConflictResolution.UseLocal);
- }
-
- GUILayout.Space(8);
-
- var remoteButtonStyle = new GUIStyle(GUI.skin.button);
- remoteButtonStyle.normal.textColor = Color.white;
- remoteButtonStyle.fixedHeight = 32;
- remoteButtonStyle.fontSize = 12;
- remoteButtonStyle.fontStyle = FontStyle.Bold;
-
- if (conflict.resolution == ConflictResolution.UseRemote)
- {
- remoteButtonStyle.normal.background = CreateRoundedTexture(remoteColor, 32, 4);
- }
-
- if (GUILayout.Button("USE REMOTE ▶", remoteButtonStyle, GUILayout.Width(120)))
- {
- SetConflictResolution(selectedConflictIndex, ConflictResolution.UseRemote);
- }
-
- GUILayout.FlexibleSpace();
- }
- }
- #endregion
- #region Helper Methods
- private void DrawCard(System.Action content, int padding = 12)
- {
- var rect = EditorGUILayout.BeginVertical();
- EditorGUI.DrawRect(rect, cardColor);
-
- GUILayout.Space(padding);
- EditorGUILayout.BeginHorizontal();
- GUILayout.Space(padding);
- EditorGUILayout.BeginVertical();
-
- content?.Invoke();
-
- EditorGUILayout.EndVertical();
- GUILayout.Space(padding);
- EditorGUILayout.EndHorizontal();
- GUILayout.Space(padding);
-
- EditorGUILayout.EndVertical();
- }
- private void DrawSectionHeader(string title, string subtitle = "", Color? color = null)
- {
- var headerStyle = new GUIStyle(EditorStyles.boldLabel);
- headerStyle.fontSize = 13;
- headerStyle.normal.textColor = color ?? Color.white;
- EditorGUILayout.LabelField(title, headerStyle);
-
- if (!string.IsNullOrEmpty(subtitle))
- {
- var subtitleStyle = new GUIStyle(EditorStyles.label);
- subtitleStyle.normal.textColor = new Color(0.7f, 0.7f, 0.7f);
- subtitleStyle.fontSize = 10;
- EditorGUILayout.LabelField(subtitle, subtitleStyle);
- }
- }
- private Texture2D CreateRoundedTexture(Color color, int size = 64, int cornerRadius = 8)
- {
- var key = $"{color}_{size}_{cornerRadius}";
- if (textureCache.TryGetValue(key, out var cachedTexture) && cachedTexture != null)
- return cachedTexture;
- var texture = new Texture2D(size, size);
- var pixels = new Color[size * size];
-
- for (int y = 0; y < size; y++)
- {
- for (int x = 0; x < size; x++)
- {
- float distanceToCorner = float.MaxValue;
-
- if (x < cornerRadius && y < cornerRadius)
- distanceToCorner = Vector2.Distance(new Vector2(x, y), new Vector2(cornerRadius, cornerRadius));
- else if (x >= size - cornerRadius && y < cornerRadius)
- distanceToCorner = Vector2.Distance(new Vector2(x, y), new Vector2(size - cornerRadius - 1, cornerRadius));
- else if (x < cornerRadius && y >= size - cornerRadius)
- distanceToCorner = Vector2.Distance(new Vector2(x, y), new Vector2(cornerRadius, size - cornerRadius - 1));
- else if (x >= size - cornerRadius && y >= size - cornerRadius)
- distanceToCorner = Vector2.Distance(new Vector2(x, y), new Vector2(size - cornerRadius - 1, size - cornerRadius - 1));
-
- pixels[y * size + x] = (distanceToCorner <= cornerRadius ||
- (x >= cornerRadius && x < size - cornerRadius) ||
- (y >= cornerRadius && y < size - cornerRadius)) ? color : Color.clear;
- }
- }
-
- texture.SetPixels(pixels);
- texture.Apply();
- textureCache[key] = texture;
- return texture;
- }
- private Color GetAssetTypeColor(ConflictAssetType assetType)
- {
- return assetType switch
- {
- ConflictAssetType.Script => new Color(0.2f, 0.6f, 0.9f),
- ConflictAssetType.Prefab => new Color(0.3f, 0.7f, 0.9f),
- ConflictAssetType.Material => new Color(0.8f, 0.4f, 0.8f),
- ConflictAssetType.Scene => new Color(0.9f, 0.3f, 0.3f),
- ConflictAssetType.Texture => new Color(0.3f, 0.8f, 0.3f),
- ConflictAssetType.ScriptableObject => new Color(0.9f, 0.7f, 0.2f),
- ConflictAssetType.Animation => new Color(1f, 0.6f, 0.2f),
- _ => new Color(0.6f, 0.6f, 0.6f)
- };
- }
- private string GetAssetTypeIcon(ConflictAssetType assetType)
- {
- return assetType switch
- {
- ConflictAssetType.Script => "C#",
- ConflictAssetType.Prefab => "PF",
- ConflictAssetType.Material => "MT",
- ConflictAssetType.Scene => "SC",
- ConflictAssetType.Texture => "TX",
- ConflictAssetType.ScriptableObject => "SO",
- ConflictAssetType.Animation => "AN",
- _ => "??"
- };
- }
- private void SelectConflict(int index)
- {
- selectedConflictIndex = index;
- GenerateCurrentPropertyDifferences();
- RefreshPreviewObjects();
- Repaint();
- }
- private void SetConflictResolution(int conflictIndex, ConflictResolution resolution)
- {
- try
- {
- if (conflictIndex >= 0 && conflictIndex < mockConflicts.Count)
- {
- mockConflicts[conflictIndex].resolution = resolution;
- Debug.Log($"Set resolution for {mockConflicts[conflictIndex].fileName}: {resolution}");
- Repaint();
- }
- else
- {
- Debug.LogError($"Invalid conflict index: {conflictIndex}");
- }
- }
- catch (Exception ex)
- {
- Debug.LogError($"Error setting conflict resolution: {ex.Message}");
- }
- }
- private void GenerateCurrentPropertyDifferences()
- {
- currentPropertyDifferences.Clear();
-
- if (selectedConflictIndex >= 0 && selectedConflictIndex < mockConflicts.Count)
- {
- var conflict = mockConflicts[selectedConflictIndex];
- currentPropertyDifferences.AddRange(GeneratePropertyDifferences(conflict));
- }
- }
- private List<PropertyDifference> GeneratePropertyDifferences(MockConflictInfo conflict)
- {
- return conflict.assetType switch
- {
- ConflictAssetType.Material => GenerateMaterialProperties(),
- ConflictAssetType.Prefab => GeneratePrefabProperties(),
- ConflictAssetType.Texture => GenerateTextureProperties(),
- ConflictAssetType.Scene => GenerateSceneProperties(),
- ConflictAssetType.Script => GenerateScriptProperties(),
- _ => GenerateGenericProperties()
- };
- }
- private List<PropertyDifference> GenerateMaterialProperties()
- {
- return new List<PropertyDifference>
- {
- new PropertyDifference
- {
- propertyName = "Albedo Color",
- localValue = "Red (1.0, 0.0, 0.0, 1.0)",
- remoteValue = "Blue (0.0, 0.0, 1.0, 1.0)",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "Metallic",
- localValue = "0.5",
- remoteValue = "0.2",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "Smoothness",
- localValue = "0.8",
- remoteValue = "0.6",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "Emission",
- localValue = "",
- remoteValue = "Enabled",
- changeType = PropertyChangeType.Added
- }
- };
- }
- private List<PropertyDifference> GeneratePrefabProperties()
- {
- return new List<PropertyDifference>
- {
- new PropertyDifference
- {
- propertyName = "Transform.Scale",
- localValue = "(1.0, 1.0, 1.0)",
- remoteValue = "(1.2, 1.2, 1.2)",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "BoxCollider.Size",
- localValue = "(1.0, 1.0, 1.0)",
- remoteValue = "(1.1, 1.1, 1.1)",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "AudioSource",
- localValue = "",
- remoteValue = "Component Added",
- changeType = PropertyChangeType.Added
- },
- new PropertyDifference
- {
- propertyName = "ParticleSystem",
- localValue = "",
- remoteValue = "Component Added",
- changeType = PropertyChangeType.Added
- }
- };
- }
- private List<PropertyDifference> GenerateTextureProperties()
- {
- return new List<PropertyDifference>
- {
- new PropertyDifference
- {
- propertyName = "Texture Size",
- localValue = "512x512",
- remoteValue = "1024x1024",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "Format",
- localValue = "RGB24",
- remoteValue = "RGBA32",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "Filter Mode",
- localValue = "Bilinear",
- remoteValue = "Trilinear",
- changeType = PropertyChangeType.Modified
- }
- };
- }
- private List<PropertyDifference> GenerateSceneProperties()
- {
- return new List<PropertyDifference>
- {
- new PropertyDifference
- {
- propertyName = "Camera Position",
- localValue = "(0, 10, 0)",
- remoteValue = "(5, 10, -5)",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "Lighting Mode",
- localValue = "Realtime GI",
- remoteValue = "Baked GI",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "Skybox",
- localValue = "Default",
- remoteValue = "Procedural",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "Fog",
- localValue = "",
- remoteValue = "Enabled",
- changeType = PropertyChangeType.Added
- }
- };
- }
- private List<PropertyDifference> GenerateScriptProperties()
- {
- return new List<PropertyDifference>
- {
- new PropertyDifference
- {
- propertyName = "speed variable",
- localValue = "5.0f",
- remoteValue = "7.0f",
- changeType = PropertyChangeType.Modified
- },
- new PropertyDifference
- {
- propertyName = "Move() method",
- localValue = "transform.Translate()",
- remoteValue = "rb.velocity =",
- changeType = PropertyChangeType.Modified
- }
- };
- }
- private List<PropertyDifference> GenerateGenericProperties()
- {
- return new List<PropertyDifference>
- {
- new PropertyDifference
- {
- propertyName = "Generic Property",
- localValue = "Local Value",
- remoteValue = "Remote Value",
- changeType = PropertyChangeType.Modified
- }
- };
- }
- private void HandleEvents()
- {
- if (Event.current.type == EventType.Repaint)
- {
- // Handle any repaint-related operations
- if (selectedViewMode == 1 && previewCameraLeft != null && previewCameraRight != null)
- {
- // Render 3D previews if needed
- previewCameraLeft.Render();
- previewCameraRight.Render();
- }
- }
- }
- private void ApplyResolutions()
- {
- try
- {
- Debug.Log("Applying conflict resolutions:");
- foreach (var conflict in mockConflicts)
- {
- Debug.Log($" {conflict.fileName}: {conflict.resolution}");
- }
-
- EditorUtility.DisplayDialog("Resolutions Applied",
- "All conflicts have been resolved. Pull operation will now continue.",
- "OK");
-
- // Call the callback to notify the main window that conflicts are resolved
- var callback = onConflictsResolved;
- onConflictsResolved = null; // Clear the callback first to prevent issues
-
- callback?.Invoke();
-
- Close();
- }
- catch (Exception ex)
- {
- Debug.LogError($"Error applying resolutions: {ex.Message}");
- EditorUtility.DisplayDialog("Error",
- $"Failed to apply resolutions: {ex.Message}",
- "OK");
- }
- }
- private void DrawFallbackUI()
- {
- EditorGUILayout.LabelField("Visual Conflict Resolver - Error State", EditorStyles.boldLabel);
- if (GUILayout.Button("Restart"))
- {
- Close();
- ShowWindow();
- }
- }
- #endregion
- #region Data Models
- [Serializable]
- public class MockConflictInfo
- {
- public string fileName;
- public ConflictAssetType assetType;
- public ConflictType conflictType;
- public string description;
- public string localVersion;
- public string remoteVersion;
- public ConflictResolution resolution;
- }
- [Serializable]
- public class PropertyDifference
- {
- public string propertyName;
- public string localValue;
- public string remoteValue;
- public PropertyChangeType changeType;
- public ConflictResolution resolution = ConflictResolution.Unresolved;
- }
- public enum PropertyChangeType
- {
- Added,
- Removed,
- Modified
- }
- public enum ConflictAssetType
- {
- Script,
- Prefab,
- Material,
- Scene,
- Texture,
- ScriptableObject,
- Animation,
- Audio,
- Model,
- Unknown
- }
- public enum ConflictType
- {
- PropertyValueDifference,
- PropertyAdded,
- PropertyRemoved,
- ComponentAdded,
- ComponentRemoved,
- ComponentPropertyChanged,
- ChildObjectAdded,
- ChildObjectRemoved,
- ChildObjectReordered,
- GameObjectMoved,
- GameObjectRenamed,
- SceneSettingsChanged,
- AssetReplaced,
- AssetMetadataChanged
- }
- public enum ConflictResolution
- {
- Unresolved,
- UseLocal,
- UseRemote,
- Manual,
- Merged
- }
- public abstract class ConflictViewer
- {
- public abstract bool CanHandle(ConflictAssetType assetType);
- public abstract void DrawConflictView(Rect area, MockConflictInfo conflict);
- public abstract ConflictResolution GetUserChoice();
- }
- #endregion
- }
- }
|