123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace CommonLang.Geometry.SceneGraph2D
- {
- public class DisplayNode : IDisposable
- {
- public string Name { get; set; }
- public DisplayNode()
- {
- }
- //-------------------------------------------------------------------------------------------------------------
- #region Tint
- public float Alpha { get; set; }
- /// <summary>
- /// Color RGB
- /// </summary>
- public uint Color { get; set; }
- #endregion
- //-------------------------------------------------------------------------------------------------------------
- #region Transform
- private ITransform transform = Factory.Instance.CreateTransform();
- private Vector2[] temp_pts = new Vector2[1];
- public Vector2 Translation
- {
- get { return transform.Translation; }
- set { transform.Translation = value; }
- }
- public float Rotation
- {
- get { return transform.Rotation; }
- set { transform.Rotation = value; }
- }
- public Vector2 Scale
- {
- get { return transform.Scale; }
- set { transform.Scale = value; }
- }
-
- public Vector2 LocalToParent(Vector2 p)
- {
- temp_pts[0] = p;
- transform.LocalToParent(temp_pts);
- return temp_pts[0];
- }
- public Vector2 ParentToLocal(Vector2 p)
- {
- temp_pts[0] = p;
- transform.ParentToLocal(temp_pts);
- return temp_pts[0];
- }
- public Vector2 LocalToRoot(Vector2 p)
- {
- temp_pts[0] = p;
- this.TransformLocalToRoot(temp_pts);
- return temp_pts[0];
- }
- public Vector2 RootToLocal(Vector2 p)
- {
- temp_pts[0] = p;
- this.TransformRootToLocal(temp_pts);
- return temp_pts[0];
- }
- /// <summary>
- /// 本地坐标转换为父节点坐标
- /// </summary>
- public void TransformLocalToParent(Vector2[] pts)
- {
- transform.LocalToParent(pts);
- }
- /// <summary>
- /// 父节点坐标转换为本地坐标
- /// </summary>
- public void TransformParentToLocal(Vector2[] pts)
- {
- transform.ParentToLocal(pts);
- }
- /// <summary>
- /// 屏幕坐标转换为本地坐标
- /// </summary>
- public void TransformRootToLocal(Vector2[] pts)
- {
- if (parent != null)
- {
- using (var path = ListObjectPool<DisplayNode>.AllocAutoRelease())
- {
- SceneGraphTreePath(path);
- foreach (var node in path)
- {
- node.transform.ParentToLocal(pts);
- }
- }
- }
- }
- /// <summary>
- /// 本地坐标转换为屏幕坐标
- /// </summary>
- public void TransformLocalToRoot(Vector2[] pts)
- {
- if (parent != null)
- {
- var curnode = this;
- do
- {
- curnode.transform.LocalToParent(pts);
- curnode = curnode.Parent;
- }
- while (curnode != null);
- }
- }
- #endregion
- //-------------------------------------------------------------------------------------------------------------
- #region IDisposable
- private bool disposedValue = false; // 要检测冗余调用
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- // TODO: 释放托管状态(托管对象)。
- }
- // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
- // TODO: 将大型字段设置为 null。
- disposedValue = true;
- }
- }
- // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
- // ~DisplayNode() {
- // // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
- // Dispose(false);
- // }
- // 添加此代码以正确实现可处置模式。
- public void Dispose()
- {
- // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
- Dispose(true);
- // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
- // GC.SuppressFinalize(this);
- }
- #endregion
- //-------------------------------------------------------------------------------------------------------------
- #region Children
- private readonly List<DisplayNode> children = new List<DisplayNode>();
- internal DisplayNode parent;
- public DisplayNode Parent { get { return parent; } }
- public int NumChildren { get { return children.Count; } }
- public DisplayRoot Root
- {
- get
- {
- var currentObject = this;
- do
- {
- if (currentObject is DisplayRoot)
- {
- return currentObject as DisplayRoot;
- }
- currentObject = currentObject.parent;
- }
- while (currentObject != null);
- return null;
- }
- }
- internal void InternalSetParent(DisplayNode node)
- {
- // check for a recursion
- DisplayNode ancestor = node;
- while (ancestor != this && ancestor != null)
- ancestor = ancestor.parent;
- if (ancestor == this)
- throw new Exception("An object cannot be added as a child to itself or one of its children (or children's children, etc.)");
- else
- parent = node;
- }
- internal void InternalAddChild(DisplayNode child, int index)
- {
- child.RemoveFromParent();
- child.InternalSetParent(this);
- children.Insert(index, child);
- }
- internal void InternalRemoveChild(DisplayNode child, bool dispose)
- {
- children.Remove(child);
- child.parent = null;
- }
- public bool ContainsChild(DisplayNode child)
- {
- while (child != null)
- {
- if (child == this)
- return true;
- else
- child = child.Parent;
- }
- return false;
- }
- public void AddChildAt(DisplayNode child, int index)
- {
- if (child == null || index < 0)
- {
- //LogError("AddChildAt Error :Child can not be null or index < 0");
- return;
- }
- if (child.Parent == this)
- {
- SetChildIndex(child, index);
- }
- else
- {
- InternalAddChild(child, index);
- }
- }
- public void AddChild(DisplayNode child)
- {
- AddChildAt(child, NumChildren);
- }
- public void RemoveChildByName(string name, bool dispose = true)
- {
- foreach (DisplayNode child in children)
- {
- if (child.Name.Equals(name))
- {
- InternalRemoveChild(child, dispose);
- break;
- }
- }
- }
- public void RemoveChild(DisplayNode child, bool dispose = true)
- {
- int result = children.IndexOf(child);
- if (result != -1)
- {
- RemoveChildAt(result, dispose);
- }
- }
- public void RemoveChildAt(int index, bool dispose = true)
- {
- if (index >= 0 && index < children.Count)
- {
- DisplayNode child = children[index];
- if (child.parent == this)
- {
- InternalRemoveChild(child, dispose);
- }
- }
- else
- {
- throw new Exception("RemoveChild Error :: mChildren Out of Bounds");
- }
- }
- public void RemoveChildren(int beginIndex, int endIndex, bool dispose = true)
- {
- if (endIndex < 0 || endIndex >= NumChildren)
- endIndex = NumChildren - 1;
- for (int i = beginIndex; i <= endIndex; ++i)
- RemoveChildAt(beginIndex, dispose);
- }
- public void RemoveAllChildren(bool dispose = true)
- {
- RemoveChildren(0, -1, dispose);
- }
- public void RemoveFromParent(bool dispose = true)
- {
- if (parent != null)
- {
- parent.RemoveChild(this, dispose);
- }
- }
- public void SetChildIndex(DisplayNode child, int index)
- {
- int oldIndex = GetChildIndex(child);
- if (oldIndex == -1)
- {
- //LogError("SetChildIndex Error: oldIndex = -1");
- return;
- }
- //logic list.
- children.RemoveAt(oldIndex);
- if (index > children.Count)
- {
- index = children.Count;
- }
- children.Insert(index, child);
- }
- public int GetChildIndex(DisplayNode child)
- {
- if (child == null)
- {
- //LogError("UIBase GetChildIndex() child == null");
- return -1;
- }
- return children.IndexOf(child);
- }
- public DisplayNode GetChildAt(int index)
- {
- if (index >= 0 && index < NumChildren)
- return children[index];
- else
- throw new Exception("Invalid child index");
- }
- public void SwapChildren(DisplayNode child1, DisplayNode child2)
- {
- int index1 = GetChildIndex(child1);
- int index2 = GetChildIndex(child2);
- if (index1 == -1 || index2 == -1)
- throw new Exception("Not a child of this container");
- SwapChildrenAt(index1, index2);
- }
- public void SwapChildrenAt(int index1, int index2)
- {
- DisplayNode child1 = GetChildAt(index1);
- DisplayNode child2 = GetChildAt(index2);
- if (child1 != null && child2 != null)
- {
- children[index1] = child2;
- children[index2] = child1;
- }
- }
- /// <summary>
- /// 获取所有节点
- /// </summary>
- /// <param name="list"></param>
- /// <param name="recursion"></param>
- public void GetChildren(List<DisplayNode> list, bool recursion = false)
- {
- list.AddRange(children);
- if (recursion)
- {
- foreach (var c in children)
- {
- c.GetChildren(list, recursion);
- }
- }
- }
- /// <summary>
- /// 获取场景数路径,从当前节点一直到根节点
- /// </summary>
- public void SceneGraphTreePath(List<DisplayNode> ret)
- {
- var curnode = this;
- do
- {
- ret.Insert(0, curnode);
- curnode = curnode.Parent;
- }
- while (curnode != null);
- }
- #endregion
- //-------------------------------------------------------------------------------------------------------------
- #region Visit
- /// <summary>
- /// 遍历所有节点
- /// </summary>
- /// <param name="action">return true for break</param>
- /// <param name="recursion"></param>
- public bool ForEachChildren(Predicate<DisplayNode> action, bool recursion = false)
- {
- using (var list = ListObjectPool<DisplayNode>.AllocAutoRelease())
- {
- list.AddRange(children);
- for (int i = 0; i < list.Count; ++i)
- {
- if (action(list[i])) { return true; }
- }
- if (recursion)
- {
- for (int i = 0; i < list.Count; ++i)
- {
- if (list[i].ForEachChildren(action, recursion))
- {
- return true;
- }
- }
- }
- }
- return false;
- }
- public virtual void Visit(IGraphics g)
- {
- g.PushTransform();
- try
- {
- g.Transform(this.transform);
- OnDrawBegin(g);
- for (int i = 0; i < children.Count; ++i)
- {
- children[i].Visit(g);
- }
- OnDrawAfter(g);
- }
- finally
- {
- g.PopTransform();
- }
- }
- /// <summary>
- /// 子节点前渲染
- /// </summary>
- /// <param name="g"></param>
- protected virtual void OnDrawBegin(IGraphics g) { }
- /// <summary>
- /// 子节点后渲染
- /// </summary>
- /// <param name="g"></param>
- protected virtual void OnDrawAfter(IGraphics g) { }
- public virtual DisplayNode HitTest(Vector2 point)
- {
- for (int i = children.Count - 1; i >= 0; --i)
- {
- var child = children[i];
- temp_pts[0] = point;
- var local = child.ParentToLocal(point);
- var hit = child.HitTest(local);
- if (hit != null)
- {
- return hit;
- }
- }
- if (OnHitTest(ref point))
- {
- return this;
- }
- return null;
- }
- protected virtual bool OnHitTest(ref Vector2 localPoint) { return false; }
- #endregion
-
- }
- }
|