Files
FlaxEngine/Source/Editor/Surface/Undo/ContextHandle.cs

142 lines
4.1 KiB
C#

// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Text;
using FlaxEngine;
using FlaxEngine.Json;
namespace FlaxEditor.Surface.Undo
{
/// <summary>
/// The helper structure for Surface context handle.
/// </summary>
[HideInEditor]
public struct ContextHandle : IEquatable<ContextHandle>
{
private readonly string[] _path;
/// <summary>
/// Initializes a new instance of the <see cref="ContextHandle"/> struct.
/// </summary>
/// <param name="context">The context.</param>
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;
}
}
}
/// <summary>
/// Initializes a new instance of the <see cref="ContextHandle"/> struct.
/// </summary>
/// <param name="child">The child context provider.</param>
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;
}
}
/// <summary>
/// Gets the context.
/// </summary>
/// <param name="surface">The Surface.</param>
/// <returns>The restored context.</returns>
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;
}
/// <inheritdoc />
public bool Equals(ContextHandle other)
{
return JsonSerializer.ValueEquals(_path, other._path);
}
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is ContextHandle other && Equals(other);
}
/// <inheritdoc />
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;
}
/// <inheritdoc />
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();
}
}
}