Created
July 11, 2015 19:23
-
-
Save sarkahn/57037c2a5d5c48a21992 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine.UI; | |
using UnityEngine.EventSystems; | |
/// <summary> | |
/// Node Behaviour representing a node. Assumes it's parent has a Layout Group. | |
/// </summary> | |
[RequireComponent(typeof(Image)),RequireComponent(typeof(VerticalLayoutGroup))] | |
public class NodeBehaviour : MonoBehaviour, IPointerDownHandler | |
{ | |
Node root_; | |
/// <summary> | |
/// Layout Group for child nodes. Will be a sibling of this NodeBehaviour's gameobject so | |
/// the nodes can be offset from the left visually using padding | |
/// </summary> | |
VerticalLayoutGroup childrenLayout_ = null; | |
public int indentSize_ = 10; | |
public int indentLevel_ = 1; | |
// Text object to represent the node. Created on awake | |
GameObject textGO_; | |
// Could be cached | |
public Text text_ { get { return textGO_.GetComponent<Text>(); } } | |
RectTransform rt_ { get { return GetComponent<RectTransform>(); } } | |
VerticalLayoutGroup layout_ { get { return GetComponent<VerticalLayoutGroup>(); } } | |
Image image_ { get { return GetComponent<Image>(); } } | |
void Awake() | |
{ | |
// Create our text object and reparent it | |
textGO_ = new GameObject("Node text", typeof(Text)); | |
text_.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); | |
textGO_.transform.SetParent(transform, false); | |
textGO_.transform.localPosition = Vector3.zero; | |
// No expanding | |
layout_.childForceExpandHeight = false; | |
layout_.childForceExpandWidth = false; | |
} | |
// Populate our visuals and create the nodebehaviours for any children of this node | |
public void BuildVisualTree() | |
{ | |
textGO_.name = root_.name_ + " Text"; | |
text_.text = root_.name_; | |
image_.sprite = null; | |
image_.type = Image.Type.Sliced; | |
Color color = Color.grey; | |
color.a = .392f; | |
image_.color = color; | |
if (root_.children_.Count == 0) | |
return; | |
for (int i = 0; i < root_.children_.Count; ++i) | |
{ | |
var behaviour = AddBehaviourNode(root_[i]); | |
behaviour.BuildVisualTree(); | |
} | |
} | |
// Add a behaviour node as a child of this node, using the given node as the root for the new behaviour | |
NodeBehaviour AddBehaviourNode( Node n ) | |
{ | |
if (childrenLayout_ == null) | |
MakeChildrenLayout(); | |
var nodeGO = new GameObject(n.name_, typeof(NodeBehaviour)); | |
var nodeBehaviour = nodeGO.GetComponent<NodeBehaviour>(); | |
// Increment our indent level so children will be offset appropriately | |
++nodeBehaviour.indentLevel_; | |
nodeBehaviour.root_ = n; | |
// Reparent the new child node to the childrenLayout | |
nodeGO.transform.SetParent(childrenLayout_.transform, false); | |
return nodeBehaviour; | |
} | |
// Left click to collapse a node, right click to add a new child to the node | |
public void OnPointerDown(PointerEventData eventData) | |
{ | |
if( eventData.button == PointerEventData.InputButton.Left ) | |
if( childrenLayout_ != null ) | |
childrenLayout_.gameObject.SetActive(!childrenLayout_.gameObject.activeInHierarchy); | |
if( eventData.button == PointerEventData.InputButton.Right ) | |
{ | |
var newNode = new Node(root_.name_ + "-> dynamic " + (root_.children_.Count - 1) ); | |
root_.children_.Add(newNode); | |
var newBehaviour = AddBehaviourNode(newNode); | |
newBehaviour.BuildVisualTree(); | |
} | |
} | |
void MakeChildrenLayout() | |
{ | |
// Create the layout group for our children. Note that it's created as a sibling of this nodebehaviour. | |
// That way we can use the padding of the childrenLayout and they will appear to be a sub-group of this | |
childrenLayout_ = new GameObject(name + " childrenLayout", typeof(VerticalLayoutGroup)).GetComponent<VerticalLayoutGroup>(); | |
childrenLayout_.transform.SetParent(transform.parent, false); | |
// Ensure the childrenLayout is directly below this Node Behaviour | |
childrenLayout_.transform.SetSiblingIndex(transform.GetSiblingIndex() + 1); | |
childrenLayout_.padding.left = indentLevel_ * indentSize_; | |
childrenLayout_.childForceExpandHeight = false; | |
childrenLayout_.childForceExpandWidth = false; | |
} | |
void PopulateNode(Node n, int count) | |
{ | |
n.children_.Clear(); | |
for (int i = 0; i < count; ++i) | |
{ | |
n.children_.Add(new Node(n.name_ + "->" + " child " + i)); | |
} | |
} | |
void PopulateRoot() | |
{ | |
PopulateNode( root_, 3 ); | |
PopulateNode( root_[1], 2 ); | |
PopulateNode(root_[1], 3); | |
PopulateNode(root_[1][1], 2); | |
} | |
[ContextMenu("RebuildVisualTree")] | |
void RebuildTree() | |
{ | |
if( childrenLayout_ != null ) | |
GameObject.DestroyImmediate(childrenLayout_); | |
root_ = new Node("Root"); | |
PopulateRoot(); | |
BuildVisualTree(); | |
} | |
} | |
public class Node | |
{ | |
public Node(string name) { name_ = name; } | |
public string name_; | |
public List<Node> children_ = new List<Node>(); | |
public Node this[int i] { get { return children_[i]; } } | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment