Converting into a parent RectTransform's Coordinates (and back again)

I’m having a bit of a problem converting between coordinate systems at different levels of UI hierarchy and I was wondering if you could help me.

I’m trying to write a technology tree and I’ve got it working providing the anchors are arranged very specifically and the elements that make up the technology tree are all children of the tree container.

I’d like it to be a bit more flexible than that and at the heart of it seems to be a problem writing a generic function that will convert from child to parent UI elements and back again.

One part of it seems to be the way anchors work. As far as I understand it, I think anchors are the points in the parent object’s space that are where the anchorPosition vector works from, with differences for strech anchors. How that fits all together, I’m not too sure.

These are the functions I’ve got working for one layer. Many thanks for any help.

		public static Vector2	TransformMyToAncestorSpace( GameObject me, GameObject ancestor, Vector2 point )
		{
			Vector2 ret = point;

			GameObject GO=me, parentGO=Hierarchy.Parent(GO);
			RectTransform RT, parentRT;
			while (GO != ancestor && parentGO != null) {
				Debug.Log ("TMtAS: Debug: ");
				RT = GO.GetComponent<RectTransform> ();
				parentRT = parentGO.GetComponent<RectTransform> ();
				//Vector2 pos;
				if (parentRT.anchorMax == parentRT.anchorMin) {
					ret = RT.anchoredPosition + ret + new Vector2 (parentRT.sizeDelta.x * parentRT.anchorMin.x, parentRT.sizeDelta.y * parentRT.anchorMin.y);
				} else {
					ret = RT.anchoredPosition + ret + parentRT.pivot;
				}

				//ret = ret + RT.anchoredPosition;
				GO = Hierarchy.Parent (GO);
				parentGO = Hierarchy.Parent (GO);
			}

			if (GO == ancestor)
				return ret;
			else
				return default(Vector2);
		}

		public static Vector2	TransformAncestorToMySpace( GameObject ancestor, GameObject me, Vector2 point )
		{
			Vector2 ret = point;

			GameObject GO=me, parentGO=Hierarchy.Parent(GO);
			RectTransform RT, parentRT;
			while (GO != ancestor && parentGO != null) {
				Debug.Log ("TAtMS: Debug");
				RT = GO.GetComponent<RectTransform> ();
				parentRT = parentGO.GetComponent<RectTransform> ();
				if (parentRT.anchorMax == parentRT.anchorMin) {
					ret = -RT.anchoredPosition + ret - new Vector2 (parentRT.sizeDelta.x * parentRT.anchorMin.x, parentRT.sizeDelta.y * parentRT.anchorMin.y);
				} else {
					ret = -RT.anchoredPosition + ret - parentRT.pivot;
				}
				//ret = ret - RT.anchoredPosition;
				GO = Hierarchy.Parent (GO);
			}

			if (GO == ancestor)
				return ret;
			else
				return default(Vector2);
		}

I’ve made a script that reverse engineers the unity’s rect transforms when you’re changing how they are parented. Only handles th normal pivot presets.
Hope it helps for anyone who had a go at this.
P.S: m_MidAnchor = Vector2(0.5,0.5)

private Rect TransformToAncestorSpace(RectTransform selectable, RectTransform ancestor)
        {

            Vector2 position = selectable.anchoredPosition;
            string debugString = selectable.name +"

";

            Vector2 currentScale = selectable.localScale;
            RectTransform parentRect = selectable.parent.GetComponent<RectTransform>();

            //Centering the anchor on the selectable
            position = CenterAnchor(selectable, parentRect, position);

            if(selectable.anchoredPosition != position)
                debugString += " Centering ->" + position;


            while (parentRect != ancestor)
            {

                debugString += " parent->" + parentRect.name;
                debugString += " position:" + position;
                currentScale *= parentRect.localScale;

                ScrollRect scroll = parentRect.GetComponent<ScrollRect>();
                if (scroll)
                {
                    m_ScrollableItem.Add(true);
                    if (m_ScrollRect == null)
                    {
                        m_ScrollRect = scroll;
                        RectTransform scrollRectTransform = scroll.GetComponent<RectTransform>();
                        m_ScrollRectTransform = new Rect(scrollRectTransform.anchoredPosition, scrollRectTransform.sizeDelta * new Vector2(1.2f, 1.2f));
                    }
                }
                else m_ScrollableItem.Add(false);

                //non-stretched anchors
                if (!(parentRect.anchorMin == Vector2.zero && parentRect.anchorMax == Vector2.one))
                {
                    RectTransform GrandParentRect = parentRect.transform.parent.GetComponent<RectTransform>();
                    //find the non-stretched parent
                    while (GrandParentRect.anchorMin == Vector2.zero && GrandParentRect.anchorMax == Vector2.one)
                        GrandParentRect = GrandParentRect.transform.parent.GetComponent<RectTransform>();


                    debugString += " GP " + GrandParentRect.name;

                    Vector2 translatedPosition = parentRect.anchoredPosition;
                    Vector2 halfSize = m_MidAnchor * parentRect.sizeDelta * parentRect.localScale;
                    //Centering the pivot
                    if (parentRect.pivot.x != m_MidAnchor.x)
                        translatedPosition.x = parentRect.pivot.x < m_MidAnchor.x ? translatedPosition.x + halfSize.x : translatedPosition.x - halfSize.x;
                    if (parentRect.pivot.y != m_MidAnchor.y)
                        translatedPosition.y = parentRect.pivot.y < m_MidAnchor.y ? translatedPosition.y + halfSize.y : translatedPosition.y - halfSize.y;

                    //Centering the anchor position
                    Vector2 GPHalfSize = m_MidAnchor * GrandParentRect.sizeDelta * GrandParentRect.localScale;
                    if (parentRect.anchorMax.x != m_MidAnchor.x)
                        translatedPosition.x = parentRect.anchorMax.x < m_MidAnchor.x ? translatedPosition.x - GPHalfSize.x : translatedPosition.x + GPHalfSize.x;

                    if (parentRect.anchorMax.y != m_MidAnchor.y)
                        translatedPosition.y = parentRect.anchorMax.y < m_MidAnchor.y ? translatedPosition.y - GPHalfSize.y : translatedPosition.y + GPHalfSize.y;

                    position *= currentScale;
                    position += translatedPosition;

                    debugString += "+ PTP:" + translatedPosition;
                    debugString += "->" + position;
                }
                else
                {
                    debugString += " Stretched";
                    position += parentRect.anchoredPosition;
                }
                parentRect = parentRect.transform.parent.GetComponent<RectTransform>();

                debugString += "

";
}

            Rect theRect = new Rect(position, currentScale * selectable.sizeDelta);
            Debug.Log(debugString + theRect);
            return theRect;

        }

        Vector3 CenterAnchor(RectTransform selectable, RectTransform parentRect, Vector3 position)
        {
            if (selectable.anchorMax != m_MidAnchor)
            {
                Vector2 translatedAnchor = position;

                RectTransform GrandParentRect = parentRect;
                //find the non-stretched parent
                while (GrandParentRect.anchorMin == Vector2.zero && GrandParentRect.anchorMax == Vector2.one)
                    GrandParentRect = GrandParentRect.transform.parent.GetComponent<RectTransform>();



                Vector2 halfSize = m_MidAnchor * GrandParentRect.sizeDelta * GrandParentRect.localScale;

                if (selectable.anchorMax.x != m_MidAnchor.x)
                    translatedAnchor.x = selectable.anchorMax.x < m_MidAnchor.x ? translatedAnchor.x - halfSize.x : translatedAnchor.x + halfSize.x;

                if (selectable.anchorMax.y != m_MidAnchor.y)
                    translatedAnchor.y = selectable.anchorMax.y < m_MidAnchor.y ? translatedAnchor.y - halfSize.y : translatedAnchor.y + halfSize.y;

                position = translatedAnchor;

            }

            return position;

        }

Update:
Now handles streched pivots and scrollable items inside scrollrect