Beispiel #1
0
    public static void MakeSharedChildrenMembers(SECTR_Sector sector, List <SECTR_Member.Child> sharedChildren, string undoName)
    {
        int numSharedChildren = sharedChildren.Count;

        for (int childIndex = 0; childIndex < numSharedChildren; ++childIndex)
        {
            SECTR_Member.Child child  = sharedChildren[childIndex];
            bool      hasMemberParent = false;
            Transform parent          = child.gameObject.transform;
            while (parent != null)
            {
                if (parent.gameObject != sector.gameObject && parent.GetComponent <SECTR_Member>())
                {
                    hasMemberParent = true;
                    break;
                }
                else
                {
                    parent = parent.parent;
                }
            }
            if (!hasMemberParent)
            {
                SECTR_Member newMember = child.gameObject.AddComponent <SECTR_Member>();
                SECTR_Undo.Created(newMember, undoName);
            }
        }
        sector.ForceUpdate(true);
    }
Beispiel #2
0
    public static List <SECTR_Occluder> GetOccludersInSector(SECTR_Sector sector)
    {
        List <SECTR_Occluder> occluders = null;

        occluderTable.TryGetValue(sector, out occluders);
        return(occluders);
    }
Beispiel #3
0
    public override void OnInspectorGUI()
    {
        SECTR_Sector mySector = (SECTR_Sector)target;

        base.OnInspectorGUI();
        List <SECTR_Member.Child> sharedChildren = mySector.GetSharedChildren();

        if (sharedChildren.Count > 0 && GUILayout.Button(new GUIContent("Fix Shared Children", "Adds Member components to any children that extend beyond this Sector and into other sectors.")))
        {
            MakeSharedChildrenMembers(mySector, sharedChildren, "Fix Shared Children");
        }

        if (mySector.GetComponentInChildren <Terrain>())
        {
            terrainFoldout = EditorGUILayout.Foldout(terrainFoldout, "Terrain Connections");
            if (terrainFoldout)
            {
                serializedObject.Update();
                DrawProperty("TopTerrain");
                DrawProperty("BottomTerrain");
                DrawProperty("LeftTerrain");
                DrawProperty("RightTerrain");

                if (GUILayout.Button("Reconnect Neighbors"))
                {
                    mySector.ConnectTerrainNeighbors();
                }
                serializedObject.ApplyModifiedProperties();
            }
        }
    }
    private void ChunkChanged(SECTR_Chunk source, bool loaded)
    {
        int numSectors = Sectors.Count;

        for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
        {
            SECTR_Sector sector = Sectors[sectorIndex];
            if (sector)
            {
                SECTR_Chunk chunk = sector.GetComponent <SECTR_Chunk>();
                if (chunk && chunk != source)
                {
                    // We need to temporarily remove our callback so
                    // that we don't get infinite loops.
                    chunk.ReferenceChange -= ChunkChanged;
                    if (loaded)
                    {
                        chunk.AddReference();
                    }
                    else
                    {
                        chunk.RemoveReference();
                    }
                    chunk.ReferenceChange += ChunkChanged;
                }
            }
        }
    }
    // This needs to be guaranteed happen before other SECTR updates to prevent
    // one frame of falling.
    void FixedUpdate()
    {
        bool allSectorsFrozen = true;
        int  numSectors       = cachedMember.Sectors.Count;

        for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
        {
            SECTR_Sector sector = cachedMember.Sectors[sectorIndex];
            if (!sector.Frozen)
            {
                allSectorsFrozen = false;
                break;
            }
        }

        if (allSectorsFrozen && !hibernating)
        {
            _Hibernate();
        }
        else if (!allSectorsFrozen && hibernating)
        {
            _WakeUp();
        }

        if (hibernating && HibernateUpdate != null)
        {
            HibernateUpdate();
        }
    }
Beispiel #6
0
 void _PickSector(SECTR_Portal myPortal)
 {
     HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
     if (Event.current.type == EventType.MouseMove)
     {
         _ComputeCursorVert();
     }
     else if (Event.current.type == EventType.MouseUp && Event.current.button == 0 && !Event.current.alt && !Event.current.control)
     {
         SECTR_Sector sector = _GetSectorFromSelection();
         if (sector)
         {
             SECTR_Undo.Record(myPortal, "Assign Sector to Portal.");
             if (pickBack)
             {
                 myPortal.BackSector = sector;
             }
             else
             {
                 myPortal.FrontSector = sector;
             }
             EditorUtility.SetDirty(myPortal);
             pickFront = false;
             pickBack  = false;
             _EndSelection();
         }
     }
     else if (Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.Escape)
     {
         pickBack  = false;
         pickFront = false;
         _EndSelection();
     }
 }
Beispiel #7
0
 public static void MakeSharedChildrenMembers(SECTR_Sector sector, List<SECTR_Member.Child> sharedChildren, string undoName)
 {
     int numSharedChildren = sharedChildren.Count;
     for(int childIndex = 0; childIndex < numSharedChildren; ++childIndex)
     {
         SECTR_Member.Child child = sharedChildren[childIndex];
         bool hasMemberParent = false;
         Transform parent = child.gameObject.transform;
         while(parent != null)
         {
             if(parent.gameObject != sector.gameObject && parent.GetComponent<SECTR_Member>())
             {
                 hasMemberParent = true;
                 break;
             }
             else
             {
                 parent = parent.parent;
             }
         }
         if(!hasMemberParent)
         {
             SECTR_Member newMember = child.gameObject.AddComponent<SECTR_Member>();
             SECTR_Undo.Created(newMember, undoName);
         }
     }
     sector.ForceUpdate(true);
 }
    private void ExportUpdate()
    {
        SECTR_Chunk myChunk = (SECTR_Chunk)target;

        if (myChunk)
        {
            SECTR_Sector mySector = myChunk.GetComponent <SECTR_Sector>();
            if (mySector)
            {
                switch (modiferMode)
                {
                case ModifierMode.Export:
                    SECTR_StreamExport.ExportToChunk(mySector);
                    break;

                case ModifierMode.Import:
                    SECTR_StreamExport.ImportFromChunk(mySector);
                    break;

                case ModifierMode.Revert:
                    SECTR_StreamExport.DeleteExportedSector(mySector);
                    myChunk.enabled = true;
                    break;

                case ModifierMode.None:
                default:
                    break;
                }
            }
            modiferMode = ModifierMode.None;
        }
        EditorApplication.update -= ExportUpdate;
    }
 void OnEnable()
 {
     cachedSector = GetComponent <SECTR_Sector>();
     if (cachedSector.Frozen)
     {
         _CreateProxy();
     }
 }
Beispiel #10
0
 private static void _CreatePortal(bool createGeo, SECTR_Sector front, SECTR_Sector back, Transform parent, string undoString)
 {
     if (front && back)
     {
         string       portalName = "SECTR Terrain Portal";
         GameObject   newPortalObject;
         SECTR_Portal newPortal;
                     #if !UNITY_4_0 && !UNITY_4_1
         if (createGeo)
         {
             newPortalObject      = GameObject.CreatePrimitive(PrimitiveType.Quad);
             newPortalObject.name = portalName;
             Mesh quadResource = newPortalObject.GetComponent <MeshFilter>().sharedMesh;
             GameObject.DestroyImmediate(newPortalObject.GetComponent <MeshFilter>());
             GameObject.DestroyImmediate(newPortalObject.GetComponent <MeshRenderer>());
             GameObject.DestroyImmediate(newPortalObject.GetComponent <Collider>());
             newPortal          = newPortalObject.AddComponent <SECTR_Portal>();
             newPortal.HullMesh = quadResource;
         }
         else
                     #endif
         {
             newPortalObject = new GameObject(portalName);
             newPortal       = newPortalObject.AddComponent <SECTR_Portal>();
         }
         newPortal.SetFlag(SECTR_Portal.PortalFlags.PassThrough, true);
         newPortal.FrontSector        = front;
         newPortal.BackSector         = back;
         newPortal.transform.parent   = parent;
         newPortal.transform.position = (front.TotalBounds.center + back.TotalBounds.center) * 0.5f;
         if (createGeo)
         {
             newPortal.transform.LookAt(back.TotalBounds.center);
             Vector3 orientation = newPortal.transform.forward;
             if (Mathf.Abs(orientation.x) >= Mathf.Abs(orientation.y) && Mathf.Abs(orientation.x) >= Mathf.Abs(orientation.z))
             {
                 newPortal.transform.localScale = new Vector3(front.TotalBounds.size.z, front.TotalBounds.size.y, 1f);
             }
             else if (Mathf.Abs(orientation.y) >= Mathf.Abs(orientation.x) && Mathf.Abs(orientation.y) >= Mathf.Abs(orientation.z))
             {
                 newPortal.transform.localScale = new Vector3(front.TotalBounds.size.x, front.TotalBounds.size.z, 1f);
             }
             else if (Mathf.Abs(orientation.z) >= Mathf.Abs(orientation.x) && Mathf.Abs(orientation.z) >= Mathf.Abs(orientation.y))
             {
                 newPortal.transform.localScale = new Vector3(front.TotalBounds.size.x, front.TotalBounds.size.y, 1f);
             }
         }
         else
         {
             newPortal.transform.LookAt(front.TotalBounds.center);
         }
         SECTR_Undo.Created(newPortalObject, undoString);
     }
 }
Beispiel #11
0
    void _SwapSectors(SECTR_Portal myPortal)
    {
        SECTR_Undo.Record(myPortal, "Swap Portal Sectors");
        SECTR_Sector oldFront = myPortal.FrontSector;
        SECTR_Sector oldBack  = myPortal.BackSector;

        myPortal.FrontSector = null;
        myPortal.BackSector  = null;
        myPortal.FrontSector = oldBack;
        myPortal.BackSector  = oldFront;
        EditorUtility.SetDirty(myPortal);
    }
Beispiel #12
0
    SECTR_Sector _GetSectorFromSelection()
    {
        GameObject   selected = lastSelectedObject;
        SECTR_Sector sector   = null;

        while (selected != null && sector == null)
        {
            sector   = selected.GetComponent <SECTR_Sector>();
            selected = selected.transform.parent ? selected.transform.parent.gameObject : null;
        }
        return(sector);
    }
 private bool _IsSectorLoaded(SECTR_Sector sector)
 {
     if (sector && sector.Frozen)
     {
         SECTR_Chunk chunk = sector.GetComponent <SECTR_Chunk>();
         if (chunk && !chunk.IsLoaded())
         {
             return(false);
         }
     }
     return(true);
 }
 private SECTR_Chunk _GetOppositeChunk(Vector3 position)
 {
     if (Portal)
     {
         SECTR_Sector oppositeSector = SECTR_Geometry.IsPointInFrontOfPlane(position, Portal.Center, Portal.Normal) ? Portal.BackSector : Portal.FrontSector;
         if (oppositeSector)
         {
             return(oppositeSector.GetComponent <SECTR_Chunk>());
         }
     }
     return(null);
 }
Beispiel #15
0
 protected static Terrain GetTerrain(SECTR_Sector sector)
 {
     if (sector)
     {
         SECTR_Member realSector = sector.childProxy ? sector.childProxy : sector;
         return(realSector.GetComponentInChildren <Terrain>());
     }
     else
     {
         return(null);
     }
 }
    // Add and removes references to current and neighboring sectors
    // as this component moves around the world.
    private void _MembershipChanged(List <SECTR_Sector> left, List <SECTR_Sector> joined)
    {
        // Add ref to all of the new objects first so that we don't unload and then immeditately load again.
        if (joined != null)
        {
            int numJoined = joined.Count;
            for (int sectorIndex = 0; sectorIndex < numJoined; ++sectorIndex)
            {
                SECTR_Sector sector = joined[sectorIndex];
                if (sector && !currentSectors.Contains(sector))
                {
                    SECTR_Graph.BreadthWalk(ref neighbors, sector, 0, MaxDepth);
                    int numNeighbors = neighbors.Count;
                    for (int neighborIndex = 0; neighborIndex < numNeighbors; ++neighborIndex)
                    {
                        SECTR_Chunk neighborChunk = neighbors[neighborIndex].Sector.GetComponent <SECTR_Chunk>();
                        if (neighborChunk)
                        {
                            neighborChunk.AddReference();
                        }
                    }
                    currentSectors.Add(sector);
                }
            }
        }

        // Dec ref any sectors we're no longer in.
        if (left != null)
        {
            int numLeft = left.Count;
            for (int sectorIndex = 0; sectorIndex < numLeft; ++sectorIndex)
            {
                SECTR_Sector sector = left[sectorIndex];
                // We have to be careful about double-removing on shutdown b/c we don't control
                // order of destruction.
                if (sector && currentSectors.Contains(sector))
                {
                    SECTR_Graph.BreadthWalk(ref neighbors, sector, 0, MaxDepth);
                    int numNeighbors = neighbors.Count;
                    for (int neighborIndex = 0; neighborIndex < numNeighbors; ++neighborIndex)
                    {
                        SECTR_Chunk neighborChunk = neighbors[neighborIndex].Sector.GetComponent <SECTR_Chunk>();
                        if (neighborChunk)
                        {
                            neighborChunk.RemoveReference();
                        }
                    }
                    currentSectors.Remove(sector);
                }
            }
        }
    }
Beispiel #17
0
 /// Called when a Sector is being destroyed
 public void SectorDisabled(SECTR_Sector sector)
 {
     if (sector)
     {
         sectors.Remove(sector);
         if (Changed != null)
         {
             leftSectors.Clear();
             leftSectors.Add(sector);
             Changed(leftSectors, null);
         }
     }
 }
    /// Returns the list of Sectors that intersect an AABB.
    /// Sectors may overlap and are not exclusive, hence the list.
    /// <param name="sectors"> List of sectors to write into.</param>
    /// <param name="bounds">The world space bounding box for which to search.</param>
    /// <returns>The List of Sectors overlapping bounds</returns>
    public static void GetContaining(ref List <SECTR_Sector> sectors, Bounds bounds)
    {
        sectors.Clear();
        int numSectors = allSectors.Count;

        for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
        {
            SECTR_Sector sector = allSectors[sectorIndex];
            if (sector.TotalBounds.Intersects(bounds))
            {
                sectors.Add(sector);
            }
        }
    }
    void OnDrawGizmos()
    {
        Gizmos.color = SECTR_Sector.SectorColor;
        int numSectors = Sectors.Count;

        for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
        {
            SECTR_Sector sector = Sectors[sectorIndex];
            if (sector)
            {
                Gizmos.DrawLine(transform.position, sector.TotalBounds.center);
            }
        }
    }
Beispiel #20
0
    private static SECTR_Sector _FindSectorByName(string name)
    {
        int numSectors = SECTR_Sector.All.Count;

        for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
        {
            SECTR_Sector sector = SECTR_Sector.All[sectorIndex];
            if (sector.name == name)
            {
                return(sector);
            }
        }
        return(null);
    }
Beispiel #21
0
    void Update()
    {
        if (waypoints.Count == 0 && SECTR_Sector.All.Count > 0 && MovementSpeed > 0f)
        {
            SECTR_Sector goal = SECTR_Sector.All[Random.Range(0, SECTR_Sector.All.Count)];
            SECTR_Graph.FindShortestPath(ref path, transform.position, goal.transform.position, SECTR_Portal.PortalFlags.Locked);
            Vector3  height     = Vector3.zero;
            Collider myCollider = GetComponent <Collider>();
            if (myCollider)
            {
                height.y += myCollider.bounds.extents.y;
            }
            waypoints.Clear();
            int numNodes = path.Count;
            for (int nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex)
            {
                SECTR_Graph.Node node = path[nodeIndex];
                waypoints.Add(node.Sector.transform.position + height);
                if (node.Portal)
                {
                    waypoints.Add(node.Portal.transform.position);
                }
            }
            waypoints.Add(goal.transform.position + height);
            currentWaypointIndex = 0;
        }

        if (waypoints.Count > 0 && MovementSpeed > 0)
        {
            Vector3 nextWaypoint    = waypoints[currentWaypointIndex];
            Vector3 vecToGoal       = nextWaypoint - transform.position;
            float   sqrGoalDistance = vecToGoal.sqrMagnitude;
            if (sqrGoalDistance > SECTR_Geometry.kVERTEX_EPSILON)
            {
                float distanceToGoal = Mathf.Sqrt(sqrGoalDistance);
                vecToGoal          /= distanceToGoal;
                vecToGoal          *= Mathf.Min(MovementSpeed * Time.deltaTime, distanceToGoal);
                transform.position += vecToGoal;
            }
            else
            {
                ++currentWaypointIndex;
                if (currentWaypointIndex >= waypoints.Count)
                {
                    waypoints.Clear();
                }
            }
        }
    }
Beispiel #22
0
    private static void _Encapsulate(SECTR_Sector newSector, List <Transform> rootTransforms, List <Bounds> rootBounds, string undoString)
    {
        int numRoots = rootTransforms.Count;

        for (int rootIndex = numRoots - 1; rootIndex >= 0; --rootIndex)
        {
            Transform rootTransform = rootTransforms[rootIndex];
            if (rootTransform != newSector.transform && SECTR_Geometry.BoundsContainsBounds(newSector.TotalBounds, rootBounds[rootIndex]))
            {
                SECTR_Undo.Parent(newSector.gameObject, rootTransform.gameObject, undoString);
                rootTransforms.RemoveAt(rootIndex);
                rootBounds.RemoveAt(rootIndex);
            }
        }
    }
    void Start()
    {
        cachedMember.ForceUpdate(true);
        int numSectors = cachedMember.Sectors.Count;

        for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
        {
            SECTR_Sector sector = cachedMember.Sectors[sectorIndex];
            SECTR_Chunk  chunk  = sector.GetComponent <SECTR_Chunk>();
            if (chunk)
            {
                chunk.AddReference();
            }
        }

        LockSelf(true);
    }
    void OnDisable()
    {
        int numSectors = Sectors.Count;

        for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
        {
            SECTR_Sector sector = Sectors[sectorIndex];
            if (sector)
            {
                SECTR_Chunk chunk = sector.GetComponent <SECTR_Chunk>();
                if (chunk)
                {
                    chunk.ReferenceChange -= ChunkChanged;
                }
            }
        }
    }
    void OnDisable()
    {
        if (!quitting && asyncLoadOp != null && !asyncLoadOp.isDone)
        {
            Debug.LogError("Chunk unloaded with async operation active. " +
                           "Do not disable chunks until async operations are complete or Unity will likely crash.");
        }

        if (loadState != LoadState.Unloaded)
        {
            _FindChunkRoot();
            if (chunkRoot)
            {
                _DestoryChunk(false, true);
            }
        }
        cachedSector = null;
    }
Beispiel #26
0
    protected virtual void OnDisable()
    {
        if (Changed != null && sectors.Count > 0)
        {
            Changed(sectors, null);
        }

        if (!isSector && !neverJoin)
        {
            int numSectors = sectors.Count;
            for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
            {
                SECTR_Sector sector = sectors[sectorIndex];
                if (sector)
                {
                    sector.Deregister(this);
                }
            }
            sectors.Clear();
        }

        int numChildren = children.Count;

        for (int childIndex = 0; childIndex < numChildren; ++childIndex)
        {
            Child child = children[childIndex];
            child.processed = false;
            childPool.Push(child);
        }
        children.Clear();
        childTable.Clear();
        renderers.Clear();
        lights.Clear();
        terrains.Clear();
        if (SECTR_Modules.VIS)
        {
            shadowLights.Clear();
            shadowCasters.Clear();
        }

        bakedOnlyTable = null;
        allMembers.Remove(this);
        allMemberTable.Remove(transform);
    }
Beispiel #27
0
    private void _MembershipChanged(List <SECTR_Sector> left, List <SECTR_Sector> joined)
    {
        // Add ref to all of the new objects first so that we don't unload and then immeditately load again.
        if (joined != null)
        {
            int numJoined = joined.Count;
            for (int sectorIndex = 0; sectorIndex < numJoined; ++sectorIndex)
            {
                SECTR_Sector sector = joined[sectorIndex];
                if (sector)
                {
                    List <SECTR_Occluder> occluders;
                    if (!occluderTable.TryGetValue(sector, out occluders))
                    {
                        occluders             = new List <SECTR_Occluder>(4);
                        occluderTable[sector] = occluders;
                    }
                    occluders.Add(this);
                    currentSectors.Add(sector);
                }
            }
        }

        // Dec ref any sectors we're no longer in.
        if (left != null)
        {
            int numLeft = left.Count;
            for (int sectorIndex = 0; sectorIndex < numLeft; ++sectorIndex)
            {
                SECTR_Sector sector = left[sectorIndex];
                // We have to be careful about double-removing on shutdown b/c we don't control
                // order of destruction.
                if (sector && currentSectors.Contains(sector))
                {
                    List <SECTR_Occluder> occluders;
                    if (occluderTable.TryGetValue(sector, out occluders))
                    {
                        occluders.Remove(this);
                    }
                    currentSectors.Remove(sector);
                }
            }
        }
    }
Beispiel #28
0
    protected virtual void OnDrawGizmosSelected()
    {
        // Render a cube of the aggregate bounds.
        if (enabled && !isSector)
        {
            // Draw the bounds
            Gizmos.color = MemberColor;
            Gizmos.DrawWireCube(totalBounds.center, totalBounds.size);

            // Render links to neighbor Sectors.
            Gizmos.color = SECTR_Sector.SectorColor;
            int numSectors = sectors.Count;
            for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
            {
                SECTR_Sector sector = sectors[sectorIndex];
                Gizmos.DrawLine(totalBounds.center, sector.TotalBounds.center);
            }
        }
    }
    void OnDisable()
    {
        int numSectors = sectors.Count;

        for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
        {
            SECTR_Sector sector = sectors[sectorIndex];
            if (sector)
            {
                SECTR_Chunk chunk = sector.GetComponent <SECTR_Chunk>();
                if (chunk)
                {
                    chunk.RemoveReference();
                }
            }
        }
        sectors.Clear();
        updated = false;
    }
Beispiel #30
0
    public override void OnInspectorGUI()
    {
        SECTR_Portal myPortal = (SECTR_Portal)target;
        SECTR_Sector newFront = ObjectField <SECTR_Sector>("Front Sector", "Reference to the Sector on the front side of this Portal", myPortal.FrontSector, true);
        SECTR_Sector newBack  = ObjectField <SECTR_Sector>("Back Sector", "Reference to the Sector on the back side of this Portal", myPortal.BackSector, true);

        // Only apply changes if things are actually different.
        // Note that the code below duplicates some functionality from SECTR_Portal's
        // accessors, but I can'f figure out any other way to get the SerializedProperty
        // multi-select compatable Undo to work...
        if (myPortal.FrontSector != newFront || myPortal.BackSector != newBack)
        {
            serializedObject.Update();
            if (myPortal.FrontSector != newFront)
            {
                if (myPortal.FrontSector)
                {
                    myPortal.FrontSector.Deregister(myPortal);
                }
                frontProp.objectReferenceValue = newFront;
                if (myPortal.FrontSector)
                {
                    myPortal.FrontSector.Register(myPortal);
                }
            }
            if (myPortal.BackSector != newBack)
            {
                if (myPortal.BackSector)
                {
                    myPortal.BackSector.Deregister(myPortal);
                }
                backProp.objectReferenceValue = newBack;
                if (myPortal.BackSector)
                {
                    myPortal.BackSector.Register(myPortal);
                }
            }
            serializedObject.ApplyModifiedProperties();
        }

        base.OnInspectorGUI();
    }
Beispiel #31
0
 private void _RefChunks()
 {
     if (!chunksReferenced)
     {
         int numChunks = Sectors.Count;
         for (int chunkIndex = 0; chunkIndex < numChunks; ++chunkIndex)
         {
             SECTR_Sector sector = Sectors[chunkIndex];
             if (sector)
             {
                 SECTR_Chunk chunk = sector.GetComponent <SECTR_Chunk>();
                 if (chunk)
                 {
                     chunk.AddReference();
                 }
             }
         }
         chunksReferenced = true;
     }
 }
Beispiel #32
0
	private SECTR_Portal _CrossedPortal(SECTR_Sector sector)
	{
		if(sector)
		{
			Vector3 rayDirection = transform.position - lastPosition;
			int numPortals = sector.Portals.Count;
			for(int portalIndex = 0; portalIndex < numPortals; ++portalIndex)
			{
				SECTR_Portal portal = sector.Portals[portalIndex];
				if(portal)
				{
					bool forwardTraversal = (portal.FrontSector == sector);
					Plane portalPlane = forwardTraversal ? portal.HullPlane : portal.ReverseHullPlane;
					SECTR_Sector oppositeSector = forwardTraversal ? portal.BackSector : portal.FrontSector;
					if(oppositeSector &&
					   Vector3.Dot(rayDirection, portalPlane.normal) < 0f && 
					   portalPlane.GetSide(transform.position) != portalPlane.GetSide(lastPosition) &&
					   portal.IsPointInHull(transform.position, rayDirection.magnitude))
					{
						return portal;
					}
				}
			}
		}
		return null;
	}
Beispiel #33
0
	/// Called when a Sector is being destroyed 
	public void SectorDisabled(SECTR_Sector sector)
	{
		if(sector)
		{
			sectors.Remove(sector);
			if(Changed != null)
			{
				leftSectors.Clear();
				leftSectors.Add(sector);
				Changed(leftSectors, null);
			}
		}
	}
	public static void SectorizeTerrain(Terrain terrain, int sectorsWidth, int sectorsLength, int sectorsHeight, bool splitTerrain, bool createPortalGeo, bool includeStatic, bool includeDynamic)
	{
		if(!terrain)
		{
			Debug.LogWarning("Cannot sectorize null terrain.");
			return;
		}
		
		if(terrain.transform.root.GetComponentsInChildren<SECTR_Sector>().Length > 0)
		{
			Debug.LogWarning("Cannot sectorize terrain that is already part of a Sector."); 
		}
		
		string undoString = "Sectorized " + terrain.name;
		
		if(sectorsWidth == 1 && sectorsLength == 1)
		{
			SECTR_Sector newSector = terrain.gameObject.AddComponent<SECTR_Sector>();
			SECTR_Undo.Created(newSector, undoString);
			newSector.ForceUpdate(true);
			return;
		}
		
		if(splitTerrain && (!Mathf.IsPowerOfTwo(sectorsWidth) || !Mathf.IsPowerOfTwo(sectorsLength)))
		{
			Debug.LogWarning("Splitting terrain requires power of two sectors in width and length.");
			splitTerrain = false;
		}
		else if(splitTerrain && sectorsWidth != sectorsLength)
		{
			Debug.LogWarning("Splitting terrain requires same number of sectors in width and length.");
			splitTerrain = false;
		}
		
		Vector3 terrainSize = terrain.terrainData.size;
		float sectorWidth = terrainSize.x / sectorsWidth;
		float sectorHeight = terrainSize.y / sectorsHeight;
		float sectorLength = terrainSize.z / sectorsLength;
		
		int heightmapWidth = (terrain.terrainData.heightmapWidth / sectorsWidth);
		int heightmapLength = (terrain.terrainData.heightmapHeight / sectorsLength);
		int alphaWidth = terrain.terrainData.alphamapWidth / sectorsWidth;
		int alphaLength = terrain.terrainData.alphamapHeight / sectorsLength;
		int detailWidth = terrain.terrainData.detailWidth / sectorsWidth;
		int detailLength = terrain.terrainData.detailHeight / sectorsLength;

		string sceneDir = "";
		string sceneName = "";
		string exportFolder = splitTerrain ? SECTR_Asset.MakeExportFolder("TerrainSplits", false, out sceneDir, out sceneName) : "";
		
		Transform baseTransform = null;
		if(splitTerrain)
		{
			GameObject baseObject = new GameObject(terrain.name);
			baseTransform = baseObject.transform;
			SECTR_Undo.Created(baseObject, undoString);
		}
		
		List<Transform> rootTransforms = new List<Transform>();
		List<Bounds> rootBounds = new List<Bounds>();
		_GetRoots(includeStatic, includeDynamic, rootTransforms, rootBounds);
		
		// Create Sectors
		SECTR_Sector[,,] newSectors = new SECTR_Sector[sectorsWidth,sectorsLength,sectorsHeight];
		Terrain[,] newTerrains = splitTerrain ? new Terrain[sectorsWidth,sectorsLength] : null;
		for(int widthIndex = 0; widthIndex < sectorsWidth; ++widthIndex)
		{
			for(int lengthIndex = 0; lengthIndex < sectorsLength; ++lengthIndex)
			{
				for(int heightIndex = 0; heightIndex < sectorsHeight; ++heightIndex)
				{
					string newName = terrain.name + " " + widthIndex + "-" + lengthIndex + "-" + heightIndex;
					GameObject newSectorObject = new GameObject("SECTR " + newName + " Sector");
					newSectorObject.transform.parent = baseTransform;
					Vector3 sectorCorner = new Vector3(widthIndex * sectorWidth,
					                                   heightIndex * sectorHeight,
					                                   lengthIndex * sectorLength) + terrain.transform.position;
					newSectorObject.transform.position = sectorCorner;
					newSectorObject.isStatic = true;
					SECTR_Sector newSector = newSectorObject.AddComponent<SECTR_Sector>();
					newSector.OverrideBounds = !splitTerrain && (sectorsWidth > 1 || sectorsLength > 1);
					newSector.BoundsOverride = new Bounds(sectorCorner + new Vector3(sectorWidth * 0.5f, sectorHeight * 0.5f, sectorLength * 0.5f),
					                                      new Vector3(sectorWidth, sectorHeight, sectorLength));
					newSectors[widthIndex,lengthIndex,heightIndex] = newSector;
					
					if(splitTerrain && heightIndex == 0)
					{
						GameObject newTerrainObject = new GameObject(newName + " Terrain");
						newTerrainObject.transform.parent = newSectorObject.transform;
						newTerrainObject.transform.localPosition = Vector3.zero;
						newTerrainObject.transform.localRotation = Quaternion.identity;
						newTerrainObject.transform.localScale = Vector3.one;
						newTerrainObject.isStatic = true;
						Terrain newTerrain = newTerrainObject.AddComponent<Terrain>();
						newTerrain.terrainData = SECTR_Asset.Create<TerrainData>(exportFolder, newName, new TerrainData());
						EditorUtility.SetDirty(newTerrain.terrainData);
						SECTR_VC.WaitForVC();
						
						// Copy properties
						// Basic terrain properties
						newTerrain.editorRenderFlags = terrain.editorRenderFlags;
						newTerrain.castShadows = terrain.castShadows;
						newTerrain.heightmapMaximumLOD = terrain.heightmapMaximumLOD;
						newTerrain.heightmapPixelError = terrain.heightmapPixelError;
						newTerrain.lightmapIndex = -1; // Can't set lightmap UVs on terrain.
						newTerrain.materialTemplate = terrain.materialTemplate;
						
						// Copy geometric data
						int heightmapBaseX = widthIndex * heightmapWidth;
						int heightmapBaseY = lengthIndex * heightmapLength;
						int heightmapWidthX = heightmapWidth + (sectorsWidth > 1 ? 1 : 0);
						int heightmapWidthY = heightmapLength + (sectorsLength > 1 ? 1 : 0);	
						newTerrain.terrainData.heightmapResolution = terrain.terrainData.heightmapResolution / sectorsWidth;
						newTerrain.terrainData.size = new Vector3(sectorWidth, terrainSize.y, sectorLength);
						newTerrain.terrainData.SetHeights(0, 0, terrain.terrainData.GetHeights(heightmapBaseX, heightmapBaseY, heightmapWidthX, heightmapWidthY));
						
						// Copy alpha maps
						int alphaBaseX = alphaWidth * widthIndex;
						int alphaBaseY = alphaLength * lengthIndex;
						newTerrain.terrainData.splatPrototypes = terrain.terrainData.splatPrototypes;
						newTerrain.basemapDistance = terrain.basemapDistance;
						newTerrain.terrainData.baseMapResolution = terrain.terrainData.baseMapResolution / sectorsWidth;
						newTerrain.terrainData.alphamapResolution = terrain.terrainData.alphamapResolution / sectorsWidth;
						newTerrain.terrainData.SetAlphamaps(0, 0, terrain.terrainData.GetAlphamaps(alphaBaseX, alphaBaseY, alphaWidth, alphaLength));

						// Copy detail info
						newTerrain.detailObjectDensity = terrain.detailObjectDensity;
						newTerrain.detailObjectDistance = terrain.detailObjectDistance;
						newTerrain.terrainData.detailPrototypes = terrain.terrainData.detailPrototypes;
						newTerrain.terrainData.SetDetailResolution(terrain.terrainData.detailResolution / sectorsWidth, 8); // TODO: extract detailResolutionPerPatch
						
						int detailBaseX = detailWidth * widthIndex;
						int detailBaseY = detailLength * lengthIndex;
						int numLayers = terrain.terrainData.detailPrototypes.Length;
						for(int layer = 0; layer < numLayers; ++layer)
						{
							newTerrain.terrainData.SetDetailLayer(0, 0, layer, terrain.terrainData.GetDetailLayer(detailBaseX, detailBaseY, detailWidth, detailLength, layer)); 
						}
						
						// Copy grass and trees
						newTerrain.terrainData.wavingGrassAmount = terrain.terrainData.wavingGrassAmount;
						newTerrain.terrainData.wavingGrassSpeed = terrain.terrainData.wavingGrassSpeed;
						newTerrain.terrainData.wavingGrassStrength = terrain.terrainData.wavingGrassStrength;
						newTerrain.terrainData.wavingGrassTint = terrain.terrainData.wavingGrassTint;
						newTerrain.treeBillboardDistance = terrain.treeBillboardDistance;
						newTerrain.treeCrossFadeLength = terrain.treeCrossFadeLength;
						newTerrain.treeDistance = terrain.treeDistance;
						newTerrain.treeMaximumFullLODCount = terrain.treeMaximumFullLODCount;
						newTerrain.terrainData.treePrototypes = terrain.terrainData.treePrototypes;
						newTerrain.terrainData.RefreshPrototypes();

						foreach(TreeInstance treeInstace in terrain.terrainData.treeInstances)
						{
							if(treeInstace.prototypeIndex >= 0 && treeInstace.prototypeIndex < newTerrain.terrainData.treePrototypes.Length &&
							   newTerrain.terrainData.treePrototypes[treeInstace.prototypeIndex].prefab)
							{
								Vector3 worldSpaceTreePos = Vector3.Scale(treeInstace.position, terrainSize) + terrain.transform.position;
								if(newSector.BoundsOverride.Contains(worldSpaceTreePos))
								{
									Vector3 localSpaceTreePos = new Vector3((worldSpaceTreePos.x - newTerrain.transform.position.x) / sectorWidth,
									                                        treeInstace.position.y,
									                                        (worldSpaceTreePos.z - newTerrain.transform.position.z) / sectorLength);
									TreeInstance newInstance = treeInstace;
									newInstance.position = localSpaceTreePos;
									newTerrain.AddTreeInstance(newInstance);
								}
							}
						}
						
						// Copy physics
						#if UNITY_4_LATE
						newTerrain.terrainData.physicMaterial = terrain.terrainData.physicMaterial;
						#endif
						
						// Force terrain to rebuild
						newTerrain.Flush();

						UnityEditor.EditorUtility.SetDirty(newTerrain.terrainData);
						SECTR_VC.WaitForVC();
						newTerrain.enabled = false;
						newTerrain.enabled = true;
						
						TerrainCollider terrainCollider = terrain.GetComponent<TerrainCollider>();
						if(terrainCollider)
						{
							TerrainCollider newCollider = newTerrainObject.AddComponent<TerrainCollider>();	
							#if !UNITY_4_LATE
							newCollider.sharedMaterial = terrainCollider.sharedMaterial;
							#endif
							newCollider.terrainData = newTerrain.terrainData;
						}
						
						newTerrains[widthIndex,lengthIndex] = newTerrain;
						SECTR_Undo.Created(newTerrainObject, undoString);
					}
					newSector.ForceUpdate(true);
					SECTR_Undo.Created(newSectorObject, undoString);
					
					_Encapsulate(newSector, rootTransforms, rootBounds, undoString);
				}
			}
		}
		
		// Create portals and neighbors
		for(int widthIndex = 0; widthIndex < sectorsWidth; ++widthIndex)
		{
			for(int lengthIndex = 0; lengthIndex < sectorsLength; ++lengthIndex)
			{
				for(int heightIndex = 0; heightIndex < sectorsHeight; ++heightIndex)
				{
					if(widthIndex < sectorsWidth - 1)
					{
						_CreatePortal(createPortalGeo, newSectors[widthIndex + 1, lengthIndex, heightIndex], newSectors[widthIndex, lengthIndex, heightIndex], baseTransform, undoString);
					}
					
					if(lengthIndex < sectorsLength - 1)
					{
						_CreatePortal(createPortalGeo, newSectors[widthIndex, lengthIndex + 1, heightIndex], newSectors[widthIndex, lengthIndex, heightIndex], baseTransform, undoString);
					}
					
					if(heightIndex > 0)						
					{
						_CreatePortal(createPortalGeo, newSectors[widthIndex, lengthIndex, heightIndex], newSectors[widthIndex, lengthIndex, heightIndex - 1], baseTransform, undoString);
					}
					else if(splitTerrain)
					{
						SECTR_Sector terrainSector = newSectors[widthIndex, lengthIndex, 0];
						terrainSector.LeftTerrain = widthIndex > 0 ? newSectors[widthIndex - 1, lengthIndex, 0] : null;
						terrainSector.RightTerrain = widthIndex < sectorsWidth - 1 ? newSectors[widthIndex + 1, lengthIndex, 0] : null;
						terrainSector.BottomTerrain = lengthIndex > 0 ? newSectors[widthIndex, lengthIndex - 1, 0] : null;
						terrainSector.TopTerrain = lengthIndex < sectorsLength - 1 ? newSectors[widthIndex, lengthIndex + 1, 0] : null;
						terrainSector.ConnectTerrainNeighbors();

						// Blend together the seams of the alpha maps, which requires
						// going through all of the mip maps of all of the layer textures.
						// We have to blend here rather than when we set the alpha data (above)
						// because Unity computes mips and we need to blend all of the mips.
						Terrain newTerrain = newTerrains[widthIndex, lengthIndex];

						// Use reflection trickery to get at the raw texture values.
						System.Reflection.PropertyInfo alphamapProperty = newTerrain.terrainData.GetType().GetProperty("alphamapTextures",
						                                                                                               System.Reflection.BindingFlags.NonPublic | 
						                                                                                               System.Reflection.BindingFlags.Public |
						                                                                                               System.Reflection.BindingFlags.Instance |
						                                                                                               System.Reflection.BindingFlags.Static);
						// Get the texture we'll write into
						Texture2D[] alphaTextures = (Texture2D[])alphamapProperty.GetValue(newTerrain.terrainData, null);
						int numTextures = alphaTextures.Length;

						// Get the textures we'll read from
						Texture2D[] leftNeighborTextures = terrainSector.LeftTerrain != null ? (Texture2D[])alphamapProperty.GetValue(newTerrains[widthIndex - 1, lengthIndex].terrainData, null) : null;
						Texture2D[] rightNeighborTextures = terrainSector.RightTerrain != null ? (Texture2D[])alphamapProperty.GetValue(newTerrains[widthIndex + 1, lengthIndex].terrainData, null) : null;
						Texture2D[] topNeighborTextures = terrainSector.TopTerrain != null ? (Texture2D[])alphamapProperty.GetValue(newTerrains[widthIndex, lengthIndex + 1].terrainData, null) : null;
						Texture2D[] bottomNeighborTextures = terrainSector.BottomTerrain != null ? (Texture2D[])alphamapProperty.GetValue(newTerrains[widthIndex, lengthIndex - 1].terrainData, null) : null;

						for(int textureIndex = 0; textureIndex < numTextures; ++textureIndex)
						{
							Texture2D alphaTexture = alphaTextures[textureIndex];
							Texture2D leftTexture = leftNeighborTextures != null ? leftNeighborTextures[textureIndex] : null;
							Texture2D rightTexture = rightNeighborTextures != null ? rightNeighborTextures[textureIndex] : null;
							Texture2D topTexture = topNeighborTextures != null ? topNeighborTextures[textureIndex] : null;
							Texture2D bottomTexture = bottomNeighborTextures != null ? bottomNeighborTextures[textureIndex] : null;
							int numMips = alphaTexture.mipmapCount;
							for(int mipIndex = 0; mipIndex < numMips; ++mipIndex)
							{
								Color[] alphaTexels = alphaTexture.GetPixels(mipIndex);
								int width = (int)Mathf.Sqrt(alphaTexels.Length);
								int height = width;
								for(int texelWidthIndex = 0; texelWidthIndex < width; ++texelWidthIndex)
								{
									for(int texelHeightIndex = 0; texelHeightIndex < height; ++texelHeightIndex)
									{
										// We can take advantage of the build order to average on the leading edges (right and top)
										// and then copy form the trailing edges (left and bottom)
										if(texelWidthIndex == 0 && leftTexture)
										{
											Color[] neighborTexels = leftTexture.GetPixels(mipIndex);
											alphaTexels[texelWidthIndex + texelHeightIndex * width] = neighborTexels[(width - 1) + (texelHeightIndex * width)];
										}
										else if(texelWidthIndex == width - 1 && rightTexture)
										{
											Color[] neighborTexels = rightTexture.GetPixels(mipIndex);
											alphaTexels[texelWidthIndex + texelHeightIndex * width] += neighborTexels[0 + (texelHeightIndex * width)];
											alphaTexels[texelWidthIndex + texelHeightIndex * width] *= 0.5f;
										}
										else if(texelHeightIndex == 0 && bottomTexture)
										{
											Color[] neighborTexels = bottomTexture.GetPixels(mipIndex);
											alphaTexels[texelWidthIndex + texelHeightIndex * width] = neighborTexels[texelWidthIndex + ((height - 1) * width)];
										}
										else if(texelHeightIndex == height - 1 && topTexture)
										{
											Color[] neighborTexels = topTexture.GetPixels(mipIndex);
											alphaTexels[texelWidthIndex + texelHeightIndex * width] += neighborTexels[texelWidthIndex + (0 * width)];
											alphaTexels[texelWidthIndex + texelHeightIndex * width] *= 0.5f;
										}
									}
								}
								alphaTexture.SetPixels(alphaTexels, mipIndex);
							}
							alphaTexture.Apply(false);
						}
					}
				}
			}
		}
		
		// destroy original terrain
		if(splitTerrain)
		{
			SECTR_Undo.Destroy(terrain.gameObject, undoString);
		}
	}
	private static void _CreatePortal(bool createGeo, SECTR_Sector front, SECTR_Sector back, Transform parent, string undoString)
	{
		if(front && back)
		{
			string portalName = "SECTR Terrain Portal";
			GameObject newPortalObject;
			SECTR_Portal newPortal;
#if !UNITY_4_0 && !UNITY_4_1
			if(createGeo)
			{
				newPortalObject = GameObject.CreatePrimitive(PrimitiveType.Quad);
				newPortalObject.name = portalName;
				Mesh quadResource = newPortalObject.GetComponent<MeshFilter>().sharedMesh;
				GameObject.DestroyImmediate(newPortalObject.GetComponent<MeshFilter>());
				GameObject.DestroyImmediate(newPortalObject.GetComponent<MeshRenderer>());
				GameObject.DestroyImmediate(newPortalObject.GetComponent<Collider>());
				newPortal = newPortalObject.AddComponent<SECTR_Portal>();
				newPortal.HullMesh = quadResource;
			}
			else
#endif
			{
				newPortalObject = new GameObject(portalName);
				newPortal = newPortalObject.AddComponent<SECTR_Portal>();
			}
			newPortal.SetFlag(SECTR_Portal.PortalFlags.PassThrough, true);
			newPortal.FrontSector = front;
			newPortal.BackSector = back;
			newPortal.transform.parent = parent;
			newPortal.transform.position = (front.TotalBounds.center + back.TotalBounds.center) * 0.5f;
			if(createGeo)
			{
				newPortal.transform.LookAt(back.TotalBounds.center);
				Vector3 orientation = newPortal.transform.forward;
				if(Mathf.Abs(orientation.x) >= Mathf.Abs(orientation.y) && Mathf.Abs(orientation.x) >= Mathf.Abs(orientation.z))
				{
					newPortal.transform.localScale = new Vector3(front.TotalBounds.size.z, front.TotalBounds.size.y, 1f);
				}
				else if(Mathf.Abs(orientation.y) >= Mathf.Abs(orientation.x) && Mathf.Abs(orientation.y) >= Mathf.Abs(orientation.z))
				{
					newPortal.transform.localScale = new Vector3(front.TotalBounds.size.x, front.TotalBounds.size.z, 1f);
				}
				else if(Mathf.Abs(orientation.z) >= Mathf.Abs(orientation.x) && Mathf.Abs(orientation.z) >= Mathf.Abs(orientation.y))
				{
					newPortal.transform.localScale = new Vector3(front.TotalBounds.size.x, front.TotalBounds.size.y, 1f);
				}
			}
			else
			{
				newPortal.transform.LookAt(front.TotalBounds.center);
			}
			SECTR_Undo.Created(newPortalObject, undoString);
		}
	}
	private static void _Encapsulate(SECTR_Sector newSector, List<Transform> rootTransforms, List<Bounds> rootBounds, string undoString)
	{
		int numRoots = rootTransforms.Count;
		for(int rootIndex = numRoots - 1; rootIndex >= 0; --rootIndex)
		{
			Transform rootTransform = rootTransforms[rootIndex];
			if(rootTransform != newSector.transform && SECTR_Geometry.BoundsContainsBounds(newSector.TotalBounds, rootBounds[rootIndex]))
			{
				SECTR_Undo.Parent(newSector.gameObject, rootTransform.gameObject, undoString);
				rootTransforms.RemoveAt(rootIndex);
				rootBounds.RemoveAt(rootIndex);
			}
		}
	}