Exemplo n.º 1
0
        private void AddMapping(Hull hull, Collider col, HullPainterChild painterChild)
        {
            HullMapping newMapping = new HullMapping()
            {
                sourceHull        = hull,
                generatedCollider = col,
                targetChild       = painterChild
            };

            this.hullMapping.Add(newMapping);
        }
Exemplo n.º 2
0
        private void RecreateChildCollider <T>(HullMapping mapping) where T : Collider
        {
            if (mapping.sourceHull == null || !mapping.sourceHull.isChildCollider)
            {
                return;
            }

            T col = AddComponent <T>(mapping.targetChild.gameObject);

            mapping.generatedCollider = col;
        }
Exemplo n.º 3
0
        private void RecreateChildCollider(HullMapping mapping)
        {
            if (mapping == null || mapping.sourceHull == null || !mapping.sourceHull.isChildCollider)
            {
                return;
            }

            if (mapping.sourceHull.type == HullType.Box)
            {
                RecreateChildCollider <BoxCollider>(mapping);
            }
            else if (mapping.sourceHull.type == HullType.Sphere)
            {
                RecreateChildCollider <SphereCollider>(mapping);
            }
            else if (mapping.sourceHull.type == HullType.ConvexHull)
            {
                RecreateChildCollider <MeshCollider>(mapping);
            }
            else if (mapping.sourceHull.type == HullType.Face)
            {
                RecreateChildCollider <MeshCollider>(mapping);
            }
        }
Exemplo n.º 4
0
        private void CreateHullMapping()
        {
            if (hullMapping == null)
            {
                //	hullMapping = new Dictionary<Hull, Collider>();
                hullMapping = new List <HullMapping>();
            }

            // Remove any invalid entries from the hull mapping
            //	null entries are garbage and can be dropped
            //	null source hull means the hull has been deleted and this mapping is no longer relevant
            //	missing *both* generated collider *and* target child means there's no data to point at, so might as well remove it and regen from scratch
            for (int i = hullMapping.Count - 1; i >= 0; i--)
            {
                HullMapping mapping = hullMapping[i];
                if (mapping == null ||
                    mapping.sourceHull == null ||
                    (mapping.generatedCollider == null && mapping.targetChild == null))
                {
                    hullMapping.RemoveAt(i);
                }
            }

            // Check to see if any existing mappings need updating (hull.type doesn't match Collider type, or child type no longer matches)

            foreach (Hull hull in paintingData.hulls)
            {
                if (IsMapped(hull))
                {
                    // We already have a mapping for this, but is it still of the correct type?

                    Collider value = FindExistingCollider(hullMapping, hull);

                    bool isHullOk   = (hull.type == HullType.ConvexHull && value is MeshCollider);
                    bool isBoxOk    = (hull.type == HullType.Box && value is BoxCollider);
                    bool isSphereOk = (hull.type == HullType.Sphere && value is SphereCollider);
                    bool isFaceOk   = (hull.type == HullType.Face && value is MeshCollider);

                    bool isColliderTypeOk = (isHullOk || isBoxOk || isSphereOk || isFaceOk);
                    bool isChildTypeOk    = value == null || ((hull.isChildCollider) == (value.transform.parent == this.transform));

                    if (isColliderTypeOk && isChildTypeOk)
                    {
                        // All good
                    }
                    else
                    {
                        // Mismatch - hull.type doesn't match collider type
                        // Delete the collider and remove the mapping
                        // This hull will then be orphaned, and a new collider added back in accordingly
                        DestroyImmediateWithUndo(value);
                        RemoveMapping(hull);
                    }
                }
            }

            // Connect orphans
            //
            // Find hulls without a Collider
            // Find Colliders without hulls
            // Try and map the two together

            // First find orphans - hull, colliders or childs that aren't already mapped

            List <Hull>             orphanedHulls     = new List <Hull>();
            List <Collider>         orphanedColliders = new List <Collider>();
            List <HullPainterChild> orphanedChilds    = new List <HullPainterChild>();

            foreach (Hull h in paintingData.hulls)
            {
                if (!IsMapped(h))
                {
                    orphanedHulls.Add(h);
                }
            }

            foreach (Collider c in FindLocal <Collider>())
            {
                if (!IsMapped(c))
                {
                    orphanedColliders.Add(c);
                }
            }

            foreach (HullPainterChild c in FindLocal <HullPainterChild>())
            {
                if (!IsMapped(c))
                {
                    orphanedChilds.Add(c);
                }
            }

            // Try and connect orphaned hulls with orphaned colliders

            for (int i = orphanedHulls.Count - 1; i >= 0; i--)
            {
                Hull h = orphanedHulls[i];

                for (int j = orphanedColliders.Count - 1; j >= 0; j--)
                {
                    Collider c = orphanedColliders[j];

                    // Find the HullPainterChild adjacent to the collider (if a child collider)
                    HullPainterChild child = null;
                    if (c.transform.parent == this.transform)
                    {
                        child = c.gameObject.GetComponent <HullPainterChild>();
                    }

                    // todo needs better handling
                    bool isMatchingChild = h.isChildCollider && c.transform.parent == this.transform;
                    if (isMatchingChild)
                    {
                        BoxCollider    boxCol    = c as BoxCollider;
                        SphereCollider sphereCol = c as SphereCollider;
                        MeshCollider   meshCol   = c as MeshCollider;

                        bool isMatchingBox        = h.type == HullType.Box && c is BoxCollider && Approximately(h.collisionBox.center, boxCol.center) && Approximately(h.collisionBox.size, boxCol.size);
                        bool isMatchingSphere     = h.type == HullType.Sphere && c is SphereCollider && h.collisionSphere != null && Approximately(h.collisionSphere.center, sphereCol.center) && Approximately(h.collisionSphere.radius, sphereCol.radius);
                        bool isMatchingConvexHull = h.type == HullType.ConvexHull && c is MeshCollider && meshCol.sharedMesh == h.collisionMesh;
                        bool isMatchingFace       = h.type == HullType.Face && c is MeshCollider && meshCol.sharedMesh == h.faceCollisionMesh;

                        if (isMatchingBox || isMatchingSphere || isMatchingConvexHull || isMatchingFace)
                        {
                            // Found a pair, so add a mapping and remove the orphans
                            AddMapping(h, c, child);

                            // These are no longer orphaned, so remove them from these lists
                            orphanedHulls.RemoveAt(i);
                            orphanedColliders.RemoveAt(j);

                            // Remove the no-longer orphaned child
                            for (int k = 0; k < orphanedChilds.Count; k++)
                            {
                                if (orphanedChilds[k] == child)
                                {
                                    orphanedChilds.RemoveAt(k);
                                    break;
                                }
                            }

                            break;
                        }
                    }
                }
            }


            // We've tried to connect hulls to existing colliders, now try and connect hulls to existing HullPainterChilds
            // These will be child without a collider (as otherwise they'd have be picked up earlier)
            for (int i = orphanedHulls.Count - 1; i >= 0; i--)
            {
                Hull h = orphanedHulls[i];

                if (!h.isChildCollider)
                {
                    continue;
                }

                for (int j = orphanedChilds.Count - 1; j >= 0; j--)
                {
                    HullPainterChild child   = orphanedChilds[j];
                    HullMapping      mapping = FindMapping(child);

                    if (mapping != null && mapping.sourceHull != null)
                    {
                        // Found a match for hull-mapping-child

                        // Ensure this still has a collider
                        if (mapping.generatedCollider == null)
                        {
                            // Recreate the collider of the correct type with the existing hull-mapping-child

                            RecreateChildCollider(mapping);
                        }

                        orphanedHulls.RemoveAt(i);
                        orphanedChilds.RemoveAt(j);
                        break;
                    }
                }
            }

            // Create colliders for any hull mapping children without colliders
            foreach (HullMapping mapping in hullMapping)
            {
                if (mapping.targetChild != null && mapping.generatedCollider == null)
                {
                    RecreateChildCollider(mapping);
                }
            }

            // Create child components for child colliders without them
            foreach (HullMapping mapping in hullMapping)
            {
                if (mapping.targetChild == null && mapping.generatedCollider != null && mapping.generatedCollider.transform.parent == this.transform)
                {
                    // Mapping has a child collider but no HullPainterChild
                    // Recreate the child component
                    HullPainterChild newChild = AddComponent <HullPainterChild>(mapping.generatedCollider.gameObject);
                    newChild.parent     = this;
                    mapping.targetChild = newChild;
                }
            }

            // Create colliders for any left over hulls

            foreach (Hull h in orphanedHulls)
            {
                if (h.type == HullType.Box)
                {
                    CreateCollider <BoxCollider>(h);
                }
                else if (h.type == HullType.Sphere)
                {
                    CreateCollider <SphereCollider>(h);
                }
                else if (h.type == HullType.ConvexHull)
                {
                    CreateCollider <MeshCollider>(h);
                }
                else if (h.type == HullType.Face)
                {
                    CreateCollider <MeshCollider>(h);
                }
            }

            // Delete any left over colliders
            // TODO: This probably isn't properly undo-aware

            foreach (Collider c in orphanedColliders)
            {
                if (c.gameObject == this.gameObject)
                {
                    DestroyImmediateWithUndo(c);
                }
                else
                {
                    // Child collider - delete collider, HullPainterChild (if any) and GameObject (if empty)

                    GameObject go = c.gameObject;
                    DestroyImmediateWithUndo(c);
                    DestroyImmediateWithUndo(go.GetComponent <HullPainterChild>());
                    if (IsDeletable(go))
                    {
                        DestroyImmediateWithUndo(go);
                    }
                }
            }

            // Delete any left over hull painter childs
            // TODO: This probably isn't undo-aware

            foreach (HullPainterChild child in orphanedChilds)
            {
                if (child == null)
                {
                    continue;
                }

                // Delete child, collider (if any) and GameObject (if empty)
                GameObject go = child.gameObject;
                DestroyImmediateWithUndo(child);
                DestroyImmediateWithUndo(go.GetComponent <Collider>());
                if (IsDeletable(go))
                {
                    DestroyImmediateWithUndo(go);
                }
            }

            // Sanity check - all hull mappings should have a collider of the right type now
            //	foreach (HullMapping mapping in hullMapping)
            //	{
            //		if (mapping.generatedCollider == null)
            //			Debug.LogWarning("Null collider for hull: " + mapping.sourceHull.name);
            //	}
        }