// Copyright (c) Wojciech Figat. All rights reserved. using System; using System.Text; using FlaxEngine; using FlaxEngine.Json; namespace FlaxEditor.Surface.Undo { /// /// The helper structure for Surface context handle. /// [HideInEditor] public struct ContextHandle : IEquatable { private readonly string[] _path; /// /// Initializes a new instance of the struct. /// /// The context. public ContextHandle(VisjectSurfaceContext context) { int count = 0; var parent = context.Parent; while (parent != null) { count++; parent = parent.Parent; } if (count == 0) { // Root context _path = null; } else { _path = new string[count]; for (int i = 0; i < count; i++) { _path[i] = context.Context.SurfaceName; context = context.Parent; } } } /// /// Initializes a new instance of the struct. /// /// The child context provider. public ContextHandle(ISurfaceContext child) { if (child == null) throw new ArgumentNullException(); VisjectSurfaceContext parent = child.ParentContext; VisjectSurfaceContext context = parent; int count = 1; while (parent != null) { count++; parent = parent.Parent; } _path = new string[count]; _path[0] = child.SurfaceName; for (int i = 1; i < count; i++) { _path[i] = context.Context.SurfaceName; context = context.Parent; } } /// /// Gets the context. /// /// The Surface. /// The restored context. public VisjectSurfaceContext Get(VisjectSurface surface) { var context = surface.RootContext; var count = _path?.Length ?? 0; for (int i = count - 1; i >= 0; i--) { var found = false; foreach (var child in context.Children) { if (child.Context.SurfaceName == _path[i]) { found = true; context = child; break; } } if (!found) throw new Exception(string.Format("Missing context \'{0}\' in \'{1}\'", _path[i], context.Context.SurfaceName)); } return context; } /// public bool Equals(ContextHandle other) { return JsonSerializer.ValueEquals(_path, other._path); } /// public override bool Equals(object obj) { return obj is ContextHandle other && Equals(other); } /// public override int GetHashCode() { int hash = 17; if (_path != null) { unchecked { for (var i = 0; i < _path.Length; i++) { var item = _path[i]; hash = hash * 23 + (item != null ? item.GetHashCode() : 0); } } } return hash; } /// public override string ToString() { var sb = new StringBuilder(); if (_path == null) return string.Empty; for (int i = _path.Length - 1; i >= 0; i--) sb.Append(_path[i]).Append('/'); return sb.ToString(); } } }