static void CheckOperationHierarchy(CSGOperation op)
        {
            if (External == null)
            {
                return;
            }

            if (!op || !op.gameObject.activeInHierarchy)
            {
                return;
            }

            // make sure the node has already been initialized,
            // otherwise ignore it
            if (!op.IsRegistered)
            {
                return;
            }

            // NOTE: returns default model when it can't find parent model
            CSGModel     parentModel;
            CSGOperation parentOp;

            FindParentOperationAndModel(op.transform, out parentOp, out parentModel);

            if (op.ChildData.Parent == parentOp &&
                op.ChildData.Model == parentModel)
            {
                return;
            }

            SetCSGOperationHierarchy(op, parentOp, parentModel);
        }
        static void UpdateChildrenParent(CSGOperation parent, Transform container, bool forceSet = false)
        {
            if (External == null)
            {
                return;
            }
            for (int i = 0; i < container.childCount; i++)
            {
                var child   = container.GetChild(i);
                var nodeObj = child.GetComponent(TypeConstants.CSGNodeType);
                if (nodeObj)
                {
                    var op = nodeObj as CSGOperation;
                    if (op &&
                        !op.PassThrough)
                    {
                        // make sure the node has already been initialized, otherwise
                        // assume it'll still get initialized at some point, in which
                        // case we shouldn't update it's hierarchy here
                        if (!op.IsRegistered)
                        {
                            continue;
                        }

                        if (op.ChildData != null)
                        {
                            if ((forceSet || op.ChildData.Parent != parent) &&
                                op.ChildData.Model)                                     // assume we're still initializing
                            {
                                SetCSGOperationHierarchy(op, parent, op.ChildData.Model);
                            }
                        }
                        continue;
                    }

                    var brush = nodeObj as CSGBrush;
                    if (brush)
                    {
                        // make sure the node has already been initialized, otherwise
                        // assume it'll still get initialized at some point, in which
                        // case we shouldn't update it's hierarchy here
                        if (!brush.IsRegistered)
                        {
                            continue;
                        }

                        if (brush.ChildData != null)
                        {
                            if ((forceSet || brush.ChildData.Parent != parent) &&
                                brush.ChildData.Model)                                  // assume we're still initializing
                            {
                                SetCSGBrushHierarchy(brush, parent, brush.ChildData.Model);
                            }
                        }
                        continue;
                    }
                }
                UpdateChildrenParent(parent, child);
            }
        }
 public void Reset()
 {
     Parent          = null;
     Model           = null;
     OwnerParentData = null;
     ModelTransform  = null;
 }
        static void SetCSGBrushHierarchy(CSGBrush brush, CSGOperation parentOp, CSGModel parentModel)
        {
            SetNodeParent(brush.ChildData, brush.hierarchyItem, parentOp, parentModel);

/*
 *                      if (!brushCache.childData.Model)
 *                              return;
 *
 *                      External.SetBrushHierarchy(brush.brushNodeID,
 *                                                                         brushCache.childData.modelNodeID,
 *                                                                         brushCache.childData.parentNodeID);*/
        }
        static void SetCSGOperationHierarchy(CSGOperation op, CSGOperation parentOp, CSGModel parentModel)
        {
            SetNodeParent(op.ChildData, op.ParentData, parentOp, parentModel);

/*
 *                      if (!operationCache.ChildData.Model)
 *                              return;
 *
 *                      External.SetOperationHierarchy(op.operationNodeID,
 *                                                                                 operationCache.ChildData.modelNodeID,
 *                                                                                 operationCache.ChildData.parentNodeID);*/
        }
        internal static void FindParentOperationAndModel(Transform opTransform, out CSGOperation parentOp, out CSGModel parentModel)
        {
            parentOp    = null;
            parentModel = null;
            if (!opTransform)
            {
                return;
            }
            var iterator = opTransform.parent;

            while (iterator)
            {
                var currentNodeObj = iterator.GetComponent(TypeConstants.CSGNodeType);
                if (currentNodeObj)
                {
                    parentModel = currentNodeObj as CSGModel;
                    if (parentModel)
                    {
                        parentOp = null;
                        return;
                    }

                    var tempParentOp = currentNodeObj as CSGOperation;
                    if (tempParentOp)
                    {
                        if (tempParentOp.operationNodeID != CSGNode.InvalidNodeID && !tempParentOp.PassThrough)
                        {
                            parentOp = tempParentOp;
                            break;
                        }
                    }
                }

                iterator = iterator.parent;
            }

            while (iterator)
            {
                var currentNodeObj = iterator.GetComponent(TypeConstants.CSGModelType);
                if (currentNodeObj)
                {
                    parentModel = currentNodeObj as CSGModel;
                    return;
                }

                iterator = iterator.parent;
            }
            parentModel = GetDefaultCSGModelForObject(opTransform);
        }
        static void FindParentOperation(Transform opTransform, out CSGOperation parentOp)
        {
            if (opTransform)
            {
                var iterator = opTransform.parent;
                while (iterator)
                {
                    var currentNodeObj = iterator.GetComponent(TypeConstants.CSGOperationType);
                    if (currentNodeObj)
                    {
                        var currentParent = currentNodeObj as CSGOperation;
                        if (!currentParent.PassThrough)
                        {
                            parentOp = currentParent;
                            return;
                        }
                    }

                    iterator = iterator.parent;
                }
            }
            parentOp = null;
        }
        static void SetNodeParent(ChildNodeData childData, HierarchyItem hierarchyItem, CSGOperation parentOp, CSGModel parentModel)
        {
            var oldParentData = childData.OwnerParentData;

            childData.Parent = parentOp;
            childData.Model  = parentModel;
            var newParentData = GetParentData(childData);

            if (oldParentData != newParentData)
            {
                if (oldParentData != null)
                {
                    oldParentData.RemoveNode(hierarchyItem);
                }
                if (newParentData != null)
                {
                    newParentData.AddNode(hierarchyItem);
                }
                childData.OwnerParentData = newParentData;
                childData.ModelTransform  = (!childData.Model) ? null : childData.Model.transform;
            }
        }
 public static void OnOperationTransformChanged(CSGOperation op)
 {
     // unfortunately this event is sent before it's destroyed, so we need to defer it.
     OperationTransformChanged.Add(op);
 }