コード例 #1
0
    public static void CreateCullingCameraCamera()
    {
        string newObjectName = "SECTR Camera";
        string undoString    = "Create " + newObjectName;

        if (Selection.activeGameObject && Selection.activeGameObject.GetComponent <Camera>())
        {
            if (Selection.activeGameObject.GetComponent <SECTR_CullingCamera>())
            {
                Debug.LogWarning("Selected Camera already has a SECTR CullingCamera.");
            }
            else
            {
                SECTR_CullingCamera newCullingCamera = Selection.activeGameObject.AddComponent <SECTR_CullingCamera>();
                SECTR_Undo.Created(newCullingCamera, undoString);
            }
        }
        else
        {
            GameObject newObject = CreateGameObject(newObjectName);
            newObject.AddComponent <SECTR_CullingCamera>();
            SECTR_Undo.Created(newObject, undoString);
            Selection.activeGameObject = newObject;
        }
    }
コード例 #2
0
    public static void CreateTriggerLoader()
    {
        string       newObjectName = "SECTR Trigger Loader";
        string       undoName      = "Created " + newObjectName;
        GameObject   newGameObject;
        SECTR_Portal selectedPortal = Selection.activeGameObject ? Selection.activeGameObject.GetComponent <SECTR_Portal>() : null;

        if (selectedPortal)
        {
            newGameObject = CreateTriggerFromPortal(selectedPortal, newObjectName);
            SECTR_TriggerLoader newLoader = newGameObject.AddComponent <SECTR_TriggerLoader>();
            if (selectedPortal.FrontSector)
            {
                newLoader.Sectors.Add(selectedPortal.FrontSector);
            }
            if (selectedPortal.BackSector)
            {
                newLoader.Sectors.Add(selectedPortal.BackSector);
            }
        }
        else
        {
            newGameObject = CreateGameObject(newObjectName);
            BoxCollider newCollider = newGameObject.AddComponent <BoxCollider>();
            newCollider.isTrigger = true;
            newGameObject.AddComponent <SECTR_TriggerLoader>();
        }

        SECTR_Undo.Created(newGameObject, undoName);
        Selection.activeGameObject = newGameObject;
    }
コード例 #3
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();
     }
 }
コード例 #4
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);
    }
コード例 #5
0
ファイル: SECTR_CoreMenu.cs プロジェクト: kirillsuleac/yes
    public static void CreateMember()
    {
        string     newName       = "SECTR Member";
        string     undoName      = "Create " + newName;
        GameObject newGameObject = CreateGameObject(newName);

        newGameObject.AddComponent <SECTR_Member>();
        SECTR_Undo.Created(newGameObject, undoName);
        Selection.activeGameObject = newGameObject;
    }
コード例 #6
0
    public static void CreateStartLoader()
    {
        string     newObjectName = "SECTR Start Loader";
        string     undoName      = "Created " + newObjectName;
        GameObject newGameObject = CreateGameObject(newObjectName);

        newGameObject.AddComponent <SECTR_StartLoader>();
        SECTR_Undo.Created(newGameObject, undoName);
        Selection.activeGameObject = newGameObject;
    }
コード例 #7
0
    public static void CreateHibernator()
    {
        string     newObjectName = "SECTR Hibernator";
        string     undoName      = "Created " + newObjectName;
        GameObject newGameObject = CreateGameObject(newObjectName);

        newGameObject.AddComponent <SECTR_Hibernator>();
        SECTR_Undo.Created(newGameObject, undoName);
        Selection.activeGameObject = newGameObject;
    }
コード例 #8
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);
     }
 }
コード例 #9
0
ファイル: SECTR_CoreMenu.cs プロジェクト: kirillsuleac/yes
    public static void CreatePortal()
    {
        string       newName       = "SECTR Portal";
        string       undoName      = "Create " + newName;
        GameObject   newGameObject = CreateGameObject(newName);
        SECTR_Portal newPortal     = newGameObject.AddComponent <SECTR_Portal>();

        newPortal.ForceEditHull = true;
        newPortal.CenterOnEdit  = true;
        SECTR_Undo.Created(newGameObject, undoName);
        Selection.activeGameObject = newGameObject;
    }
コード例 #10
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);
    }
コード例 #11
0
    public static void CreateOccluder()
    {
        string         newObjectName = "SECTR Occluder";
        string         undoString    = "Create " + newObjectName;
        GameObject     newObject     = CreateGameObject(newObjectName);
        SECTR_Occluder newOccluder   = newObject.AddComponent <SECTR_Occluder>();

        newOccluder.ForceEditHull = true;
        newOccluder.CenterOnEdit  = true;
        SECTR_Undo.Created(newObject, undoString);
        Selection.activeGameObject = newObject;
    }
コード例 #12
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);
            }
        }
    }
コード例 #13
0
    public static void CreateLOD()
    {
        string     newObjectName = "SECTR LOD";
        string     undoString    = "Create " + newObjectName;
        GameObject newObject     = CreateGameObject(newObjectName);

        newObject.AddComponent <SECTR_LOD>();
        int numSelected = Selection.gameObjects.Length;

        SECTR_Undo.Created(newObject, undoString);
        for (int selectedIndex = 0; selectedIndex < numSelected; ++selectedIndex)
        {
            SECTR_Undo.Parent(newObject, Selection.gameObjects[selectedIndex], undoString);
        }
        Selection.activeGameObject = newObject;
    }
コード例 #14
0
    protected static GameObject CreateDoor <T>(string newName) where T : SECTR_Door
    {
        string       undoName = "Create " + newName;
        GameObject   newGameObject;
        SECTR_Portal selectedPortal = Selection.activeGameObject ? Selection.activeGameObject.GetComponent <SECTR_Portal>() : null;

        if (selectedPortal)
        {
            newGameObject = CreateTriggerFromPortal(selectedPortal, newName);
            T newDoor = newGameObject.AddComponent <T>();
            newDoor.Portal = selectedPortal;
        }
        else
        {
            newGameObject = CreateGameObject(newName);
            BoxCollider newCollider = newGameObject.AddComponent <BoxCollider>();
            newCollider.isTrigger = true;
            newGameObject.AddComponent <T>();
        }

        SECTR_Undo.Created(newGameObject, undoName);
        Selection.activeGameObject = newGameObject;
        return(newGameObject);
    }
コード例 #15
0
    void _CompleteHull(SECTR_Hull myHull)
    {
        int numNewVerts = newHullVerts.Count;

        if (numNewVerts >= 3)
        {
            Plane   hullPlane  = new Plane(newHullVerts[0], newHullVerts[1], newHullVerts[2]);
            Vector3 hullNormal = hullPlane.normal;

            // For new hulls, set their xform to match the hull geo.
            if (myHull.ForceEditHull && myHull.CenterOnEdit)
            {
                Vector3 newPos = Vector3.zero;
                for (int vertIndex = 0; vertIndex < numNewVerts; ++vertIndex)
                {
                    newPos += newHullVerts[vertIndex];
                }
                newPos /= newHullVerts.Count;
                myHull.transform.position = newPos;
                myHull.transform.forward  = hullNormal;
            }

            // Constructu a new mesh.
            Mesh newMesh = new Mesh();
            newMesh.name = myHull.name;
            Vector3[] newVerts   = new Vector3[numNewVerts];
            Vector3[] newNormals = new Vector3[numNewVerts];
            Vector2[] newUVs     = new Vector2[numNewVerts];

            // Compute new positions and normals, which are always in hull local space.
            Vector3 localNormal = myHull.transform.worldToLocalMatrix.MultiplyVector(hullNormal);
            Vector3 min         = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
            Vector3 max         = new Vector3(float.MinValue, float.MinValue, float.MinValue);
            for (int vertIndex = 0; vertIndex < numNewVerts; ++vertIndex)
            {
                Vector3 localPosition = myHull.transform.worldToLocalMatrix.MultiplyPoint3x4(newHullVerts[vertIndex]);
                newVerts[vertIndex]   = localPosition;
                newNormals[vertIndex] = localNormal;
                min = Vector3.Min(min, localPosition);
                max = Vector3.Max(max, localPosition);
            }
            // Compute a planar projection for the UVs.
            Vector3 uvScalar = new Vector3(1f / max.x - min.x, 1f / max.y - min.y, 1);
            for (int vertIndex = 0; vertIndex < numNewVerts; ++vertIndex)
            {
                newUVs[vertIndex] = Vector3.Scale(newVerts[vertIndex], uvScalar);
            }
            // Triangle indices assume a CW sorting of the verts.
            int   numTriangles = numNewVerts - 2;
            int[] triangles    = new int[numTriangles * 3];
            for (int triIndex = 0; triIndex < numTriangles; ++triIndex)
            {
                triangles[triIndex * 3]     = 0;
                triangles[triIndex * 3 + 1] = triIndex + 1;
                triangles[triIndex * 3 + 2] = triIndex + 2;
            }
            // Fill out the mesh stuffs.
            newMesh.vertices  = newVerts;
            newMesh.normals   = newNormals;
            newMesh.uv        = newUVs;
            newMesh.triangles = triangles;

            // Now create a new, unique mesh asset for the hull.
            // We use assets instead of storing geometry in the scene to ensure that everything serializes properly.
            string sceneDir     = null;
            string sceneName    = null;
            string exportDir    = SECTR_Asset.MakeExportFolder("Portals", false, out sceneDir, out sceneName);
            string newAssetName = exportDir + newMesh.name + ".asset";
            newAssetName = AssetDatabase.GenerateUniqueAssetPath(newAssetName);
            AssetDatabase.CreateAsset(newMesh, newAssetName);

            // Let the hull know that we've modified it in an undo friendly way.
            SECTR_Undo.Record(myHull, "Created Portal");
            myHull.HullMesh = newMesh;
        }
        _EndNewHull(myHull, false);
    }
コード例 #16
0
    public override void OnInspectorGUI()
    {
        SECTR_LOD myLOD           = (SECTR_LOD)target;
        float     lodButtonHeight = 50;
        float     lodGutterSize   = 4f;

        if (lodButtonStyle == null)
        {
            lodButtonStyle         = new GUIStyle(GUI.skin.button);
            lodButtonStyle.padding = new RectOffset();
            lodButtonStyle.margin  = new RectOffset();
        }

        if (Event.current.type == EventType.Repaint)
        {
            lodRects.Clear();
        }

        EditorGUILayout.BeginVertical();

        Rect lodListRect = EditorGUILayout.BeginVertical();

        GUI.enabled = false;
        GUILayout.Button(GUIContent.none, GUILayout.Height(lodButtonHeight));
        GUI.enabled = true;
        EditorGUILayout.EndVertical();

        float addButtonSize = lodListRect.width * 0.1f;
        int   numLODs       = myLOD.LODs.Count;
        float minThreshold  = 1;
        float insertPos     = lodListRect.xMin;

        for (int lodIndex = 0; lodIndex < numLODs; ++lodIndex)
        {
            SECTR_LOD.LODSet thisSet     = myLOD.LODs[lodIndex];
            float            buttonScale = 1f - thisSet.Threshold;
            float            percent     = 1f;
            if (lodIndex > 0)
            {
                float prevThreshold = myLOD.LODs[lodIndex - 1].Threshold;
                buttonScale -= 1f - prevThreshold;
                percent      = myLOD.LODs[lodIndex - 1].Threshold;
            }

            float buttonWidth = buttonScale * (lodListRect.width - addButtonSize);
            Rect  buttonRect  = new Rect(insertPos + lodGutterSize * 0.5f, lodListRect.y, buttonWidth - lodGutterSize, lodListRect.height);

            if (GUI.Button(buttonRect, "LOD" + lodIndex + "\n" + percent.ToString("P1"), lodButtonStyle))
            {
                selectedLOD = lodIndex;
            }
            if (Event.current.type == EventType.Repaint)
            {
                lodRects.Add(buttonRect);
            }
            insertPos += buttonWidth;

            minThreshold = Mathf.Min(minThreshold, thisSet.Threshold);
        }

        if (minThreshold > 0f && myLOD.LODs.Count > 0)
        {
            Rect culledRect = new Rect(insertPos + lodGutterSize * 0.5f, lodListRect.y, lodListRect.xMax - insertPos - addButtonSize - lodGutterSize, lodListRect.height);
            if (GUI.Button(culledRect, "Culled\n" + minThreshold.ToString("P1"), lodButtonStyle))
            {
                selectedLOD = -1;
            }

            if (Event.current.type == EventType.Repaint)
            {
                lodRects.Add(culledRect);
            }
        }

        GUI.enabled = minThreshold > 0;
        Rect addRect = myLOD.LODs.Count > 0 ? new Rect(lodListRect.xMax - addButtonSize, lodListRect.y, addButtonSize, lodListRect.height) :
                       new Rect(lodListRect.xMin, lodListRect.y, lodListRect.width, lodListRect.height);

        if (GUI.Button(addRect, myLOD.LODs.Count > 0 ? "+" : "+\n(Add LOD)", lodButtonStyle))
        {
            SECTR_Undo.Record(myLOD, "Added LOD");
            SECTR_LOD.LODSet newSet = new SECTR_LOD.LODSet();
            if (myLOD.LODs.Count == 0)
            {
                Transform[] children    = myLOD.GetComponentsInChildren <Transform>();
                int         numChildren = children.Length;
                for (int childIndex = 0; childIndex < numChildren; ++childIndex)
                {
                    if (children[childIndex] != myLOD.transform)
                    {
                        newSet.Add(children[childIndex].gameObject, null);
                    }
                }
            }
            else
            {
                SECTR_LOD.LODSet prevSet = myLOD.LODs[myLOD.LODs.Count - 1];
                int numEntries           = prevSet.LODEntries.Count;
                for (int entryIndex = 0; entryIndex < numEntries; ++entryIndex)
                {
                    SECTR_LOD.LODEntry prevEntry = prevSet.LODEntries[entryIndex];
                    newSet.Add(prevEntry.gameObject, prevEntry.lightmapSource);
                }
            }
            newSet.Threshold = minThreshold * 0.5f;
            selectedLOD      = myLOD.LODs.Count;
            myLOD.LODs.Add(newSet);
        }
        GUI.enabled = true;

        int lodToRemove = -1;

        if (selectedLOD >= 0 && selectedLOD < myLOD.LODs.Count)
        {
            float sliderMin = 0;
            float sliderMax = 1;

            if (selectedLOD < myLOD.LODs.Count - 1)
            {
                sliderMin = myLOD.LODs[selectedLOD + 1].Threshold;
            }
            if (selectedLOD > 0)
            {
                sliderMax = myLOD.LODs[selectedLOD - 1].Threshold;
            }

            myLOD.LODs[selectedLOD].Threshold = EditorGUILayout.Slider("LOD" + selectedLOD + " Threshold", myLOD.LODs[selectedLOD].Threshold, sliderMin, sliderMax);

            detailsFoldout = EditorGUILayout.Foldout(detailsFoldout, "LOD" + selectedLOD + " Members");
            if (detailsFoldout)
            {
                EditorGUILayout.BeginHorizontal();
                GUILayout.Label("Name");
                GUILayout.Label("Included");
                GUILayout.Label("Lightmap Proxy");
                EditorGUILayout.EndHorizontal();
                _BuildChildControls(myLOD, myLOD.LODs[selectedLOD], myLOD.transform, true);
            }

            if (GUILayout.Button("Remove LOD" + selectedLOD))
            {
                if (EditorUtility.DisplayDialog("Confirm LOD Removal", "Are you sure you wish to remove LOD " + selectedLOD + "?", "Yes", "No"))
                {
                    lodToRemove = selectedLOD;
                }
            }
        }
        else if (selectedLOD == -1)
        {
            serializedObject.Update();
            DrawProperty("CullSiblings");
            serializedObject.ApplyModifiedProperties();
        }

        EditorGUILayout.EndVertical();

        if (lodToRemove >= 0)
        {
            SECTR_Undo.Record(myLOD, "Removed LOD");
            myLOD.LODs.RemoveAt(lodToRemove);
        }

        if (Event.current.type == EventType.Repaint)
        {
            lodListRectPerm = lodListRect;
        }

        int dragLod = -1;

        if (lodListRectPerm.Contains(Event.current.mousePosition))
        {
            for (int lodIndex = 0; lodIndex < lodRects.Count - 1; ++lodIndex)
            {
                if (Event.current.mousePosition.x > lodRects[lodIndex].xMax &&
                    Event.current.mousePosition.x < lodRects[lodIndex + 1].xMin)
                {
                    dragLod = lodIndex;
                    break;
                }
            }
        }

        if (dragLod >= 0 && Event.current.type == EventType.MouseDown)
        {
            dragging    = true;
            selectedLOD = dragLod;
        }
        else if (Event.current.type == EventType.MouseUp)
        {
            dragging = false;
        }

        if (dragging && lodListRectPerm.Contains(Event.current.mousePosition) && Event.current.type == EventType.MouseDrag)
        {
            float newThreshold = 1f - ((Event.current.mousePosition.x - lodListRect.x) / lodListRect.width);
            newThreshold = Mathf.Clamp01(newThreshold);
            if (selectedLOD < myLOD.LODs.Count - 1)
            {
                newThreshold = Mathf.Max(newThreshold, myLOD.LODs[selectedLOD + 1].Threshold);
            }
            if (selectedLOD > 0)
            {
                newThreshold = Mathf.Min(newThreshold, myLOD.LODs[selectedLOD - 1].Threshold);
            }
            myLOD.LODs[selectedLOD].Threshold = newThreshold;
        }

        if (dragging || dragLod >= 0)
        {
            EditorGUIUtility.AddCursorRect(new Rect(Event.current.mousePosition.x - 16,
                                                    Event.current.mousePosition.y - 16, 32, 32),
                                           MouseCursor.ResizeHorizontal);
        }
    }
コード例 #17
0
    private bool _DrawChildControl(SECTR_LOD myLOD, SECTR_LOD.LODSet lodSet, Transform transform, bool hasChildren)
    {
        string undoString   = "Changed LOD";
        bool   expanded     = false;
        float  labelWidth   = Screen.width * 0.3f;
        float  checkWidth   = 30;
        float  buffer       = 5;
        Rect   propertyRect = EditorGUILayout.BeginHorizontal(GUILayout.Width(labelWidth));

        if (hasChildren)
        {
            hierarchyFoldouts.TryGetValue(transform, out expanded);
            hierarchyFoldouts[transform] = EditorGUILayout.Foldout(expanded, transform.name);
        }
        else
        {
            EditorGUILayout.LabelField(transform.name, GUILayout.Width(labelWidth));
        }
        EditorGUILayout.EndHorizontal();

        SECTR_LOD.LODEntry entry = lodSet.GetEntry(transform.gameObject);
        bool isChecked           = entry != null;
        bool newChecked          = GUI.Toggle(new Rect(propertyRect.xMax + buffer,
                                                       propertyRect.y,
                                                       checkWidth,
                                                       propertyRect.height),
                                              isChecked,
                                              GUIContent.none);

        if (newChecked != isChecked)
        {
            SECTR_Undo.Record(myLOD, undoString);
            if (newChecked)
            {
                entry = lodSet.Add(transform.gameObject, null);
            }
            else
            {
                lodSet.Remove(transform.gameObject);
                entry = null;
            }
            isChecked = newChecked;
            myLOD.Reset();
        }

        if (entry != null && transform.GetComponent <Renderer>())
        {
            Renderer newSource = (Renderer)EditorGUI.ObjectField(new Rect(propertyRect.xMax + checkWidth + buffer,
                                                                          propertyRect.y,
                                                                          Screen.width - (propertyRect.xMax + checkWidth + buffer * 2),
                                                                          propertyRect.height),
                                                                 GUIContent.none,
                                                                 entry.lightmapSource,
                                                                 typeof(Renderer),
                                                                 true);
            if (newSource != entry.lightmapSource)
            {
                SECTR_Undo.Record(myLOD, undoString);
                entry.lightmapSource = newSource;
                myLOD.Reset();
            }
        }
        return(expanded);
    }
コード例 #18
0
    private static void _SectorizeConnected(Terrain terrain, bool createPortalGeo, bool includeStatic, bool includeDynamic, Dictionary <Terrain, Terrain> processedTerrains, List <Transform> rootTransforms, List <Bounds> rootBounds)
    {
        if (terrain && !processedTerrains.ContainsKey(terrain))
        {
            string undoString = "Sectorize Connected";
            processedTerrains[terrain]  = terrain;
            terrain.gameObject.isStatic = true;
            GameObject newSectorObject = new GameObject(terrain.name + " Sector");
            newSectorObject.isStatic                = true;
            newSectorObject.transform.parent        = terrain.transform.parent;
            newSectorObject.transform.localPosition = terrain.transform.localPosition;
            newSectorObject.transform.localRotation = terrain.transform.localRotation;
            newSectorObject.transform.localScale    = terrain.transform.localScale;
            terrain.transform.parent                = newSectorObject.transform;
            SECTR_Sector newSector = newSectorObject.AddComponent <SECTR_Sector>();
            newSector.ForceUpdate(true);
            SECTR_Undo.Created(newSectorObject, undoString);
            _Encapsulate(newSector, rootTransforms, rootBounds, undoString);

            Component terrainNeighbors = terrain.GetComponent("TerrainNeighbors");
            if (terrainNeighbors)
            {
                System.Type neighborsType = terrainNeighbors.GetType();
                Terrain     topTerrain    = neighborsType.GetField("top").GetValue(terrainNeighbors) as Terrain;
                if (topTerrain)
                {
                    SECTR_Sector neighborSector = topTerrain.transform.parent ? topTerrain.transform.parent.GetComponent <SECTR_Sector>() : null;
                    if (neighborSector)
                    {
                        newSector.TopTerrain         = neighborSector;
                        neighborSector.BottomTerrain = newSector;
                        _CreatePortal(createPortalGeo, newSector, neighborSector, newSectorObject.transform.parent, undoString);
                    }
                    _SectorizeConnected(topTerrain, createPortalGeo, includeStatic, includeDynamic, processedTerrains, rootTransforms, rootBounds);
                }
                Terrain bottomTerrain = neighborsType.GetField("bottom").GetValue(terrainNeighbors) as Terrain;
                if (bottomTerrain)
                {
                    SECTR_Sector neighborSector = bottomTerrain.transform.parent ? bottomTerrain.transform.parent.GetComponent <SECTR_Sector>() : null;
                    if (neighborSector)
                    {
                        newSector.BottomTerrain   = neighborSector;
                        neighborSector.TopTerrain = newSector;
                        _CreatePortal(createPortalGeo, newSector, neighborSector, newSectorObject.transform.parent, undoString);
                    }
                    _SectorizeConnected(bottomTerrain, createPortalGeo, includeStatic, includeDynamic, processedTerrains, rootTransforms, rootBounds);
                }
                Terrain leftTerrain = neighborsType.GetField("left").GetValue(terrainNeighbors) as Terrain;
                if (leftTerrain)
                {
                    SECTR_Sector neighborSector = leftTerrain.transform.parent ? leftTerrain.transform.parent.GetComponent <SECTR_Sector>() : null;
                    if (neighborSector)
                    {
                        newSector.LeftTerrain       = neighborSector;
                        neighborSector.RightTerrain = newSector;
                        _CreatePortal(createPortalGeo, newSector, neighborSector, newSectorObject.transform.parent, undoString);
                    }
                    _SectorizeConnected(leftTerrain, createPortalGeo, includeStatic, includeDynamic, processedTerrains, rootTransforms, rootBounds);
                }
                Terrain rightTerrain = neighborsType.GetField("right").GetValue(terrainNeighbors) as Terrain;
                if (rightTerrain)
                {
                    SECTR_Sector neighborSector = rightTerrain.transform.parent ? rightTerrain.transform.parent.GetComponent <SECTR_Sector>() : null;
                    if (neighborSector)
                    {
                        newSector.RightTerrain     = neighborSector;
                        neighborSector.LeftTerrain = newSector;
                        _CreatePortal(createPortalGeo, newSector, neighborSector, newSectorObject.transform.parent, undoString);
                    }
                    _SectorizeConnected(rightTerrain, createPortalGeo, includeStatic, includeDynamic, processedTerrains, rootTransforms, rootBounds);
                }
            }
        }
    }
コード例 #19
0
ファイル: SECTR_CoreMenu.cs プロジェクト: kirillsuleac/yes
    public static void CreateSector()
    {
        List <GameObject> rootObjects     = new List <GameObject>(8);
        List <GameObject> selectedObjects = new List <GameObject>(Selection.gameObjects);
        int numSelectedObjects            = selectedObjects.Count;
        int selectedObjectIndex           = 0;

        while (selectedObjectIndex < numSelectedObjects)
        {
            GameObject gameObject = selectedObjects[selectedObjectIndex];
            // auto remove portals if selected.
            if (gameObject.GetComponent <SECTR_Portal>())
            {
                selectedObjects.RemoveAt(selectedObjectIndex);
                --numSelectedObjects;
            }
            else
            {
                // Check to make sure nothing selected is already in a Sector.
                Transform parent = gameObject.transform;
                while (parent != null)
                {
                    // Bail out if we encounter any classes that shouldn't be part of the list
                    if (parent.GetComponent <SECTR_Sector>() != null)
                    {
                        EditorUtility.DisplayDialog("Sector Safety First", "Some of the selected objects are already in a Sector. Please unparent them from the current Sector before putting them into a new Sector.", "Ok");
                        return;
                    }
                    parent = parent.parent;
                }
                ++selectedObjectIndex;
            }
        }

        // Build a list of common parents from the selection to try to preserve any existing heirarchy
        // but without walking all the way up the tree. Complex scenes may have many Sectors parented
        // under a single transform and we do not want to walk higher than the current selection.
        for (selectedObjectIndex = 0; selectedObjectIndex < numSelectedObjects; ++selectedObjectIndex)
        {
            GameObject gameObject = selectedObjects[selectedObjectIndex];
            Transform  parent     = gameObject.transform;
            while (parent != null)
            {
                if (parent.parent)
                {
                    int  numChildren         = parent.parent.childCount;
                    bool allChildrenSelected = true;
                    for (int childIndex = 0; childIndex < numChildren; ++childIndex)
                    {
                        if (!selectedObjects.Contains(parent.parent.GetChild(childIndex).gameObject))
                        {
                            allChildrenSelected = false;
                            break;
                        }
                    }
                    if (allChildrenSelected)
                    {
                        parent = parent.parent;
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }
            }
            if (parent != null && !rootObjects.Contains(parent.gameObject))
            {
                rootObjects.Add(parent.gameObject);
            }
        }

        int          numRootObjects = rootObjects.Count;
        string       newName        = "SECTR Sector";
        string       undoName       = "Create " + newName;
        SECTR_Sector newSector      = null;

        // If there is just one root, give the open to make that into a Sector. This helps
        // with scenes that are already well organized.
        Transform commonParent = numRootObjects == 1 ? rootObjects[0].transform : null;

        if (commonParent && EditorUtility.DisplayDialog("Common Parent Detected", "Selected objects are all a child of " + commonParent.name + ". " +
                                                        "Would you like to make " + commonParent.name + " into a Sector? If not, a new Sector will be created and " +
                                                        commonParent.name + " will be parented to it.", "Yes", "No"))
        {
            newSector = commonParent.gameObject.AddComponent <SECTR_Sector>();
            if (!commonParent.gameObject.isStatic &&
                EditorUtility.DisplayDialog("Make Sector Static?", "SECTR can perform additional optimizations on Sectors that are marked as static, provided they " +
                                            "do not need to move or change bounds at runtime. Would you like " + commonParent.name + " to be marked as static?", "Yes", "No"))
            {
                commonParent.gameObject.isStatic = true;
            }
            SECTR_Undo.Created(newSector, undoName);
        }
        else
        {
            commonParent = numRootObjects > 0 ? rootObjects[0].transform.parent : null;
            for (int rootIndex = 0; rootIndex < numRootObjects; ++rootIndex)
            {
                if (rootObjects[rootIndex].transform.parent != commonParent)
                {
                    commonParent = null;
                    break;
                }
            }

            GameObject newGameObject = CreateGameObject(newName);
            newGameObject.transform.parent = commonParent;
            newGameObject.isStatic         = true;
            SECTR_Undo.Created(newGameObject, undoName);

            List <Vector3> rootPositions = new List <Vector3>(numRootObjects);
            for (int rootObjectIndex = 0; rootObjectIndex < numRootObjects; ++rootObjectIndex)
            {
                GameObject gameObject = rootObjects[rootObjectIndex];
                rootPositions.Add(gameObject.transform.position);
                SECTR_Undo.Parent(newGameObject, gameObject, undoName);
            }

            newSector = newGameObject.AddComponent <SECTR_Sector>();
            SECTR_Undo.Created(newSector, undoName);

            newSector.transform.position = newSector.TotalBounds.center;
            for (int rootObjectIndex = 0; rootObjectIndex < numRootObjects; ++rootObjectIndex)
            {
                GameObject gameObject = rootObjects[rootObjectIndex];
                gameObject.transform.position = rootPositions[rootObjectIndex];
            }
        }

        List <SECTR_Member.Child> sharedChildren = newSector.GetSharedChildren();

        if (sharedChildren.Count > 0 && EditorUtility.DisplayDialog("Overlap Warning", "Some objects in this Sector overlap other Sectors, which may cause unexpected behavior. Would you like to make them Members instead of children?", "Yes", "No"))
        {
            SECTR_SectorEditor.MakeSharedChildrenMembers(newSector, sharedChildren, undoName);
        }

        Selection.activeGameObject = newSector.gameObject;
    }
コード例 #20
0
    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;
        }

        int     terrainLayer = terrain.gameObject.layer;
        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
        string progressTitle   = "Sectorizing Terrain";
        int    progressCounter = 0;

        EditorUtility.DisplayProgressBar(progressTitle, "Preparing", 0);

        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;

                    EditorUtility.DisplayProgressBar(progressTitle, "Creating sector " + newName, progressCounter++ / (float)(sectorsWidth * sectorsLength * sectorsHeight));

                    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.layer                   = terrainLayer;
                        newTerrainObject.tag                     = terrain.tag;
                        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;
                                                #if !UNITY_4
                        newTerrain.bakeLightProbesForTrees = terrain.bakeLightProbesForTrees;
                        newTerrain.legacyShininess         = terrain.legacyShininess;
                        newTerrain.legacySpecular          = terrain.legacySpecular;
                                                #endif

                        // 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));
                                                #if !UNITY_4
                        newTerrain.terrainData.thickness = terrain.terrainData.thickness;
                                                #endif

                        // 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
                                                #if !UNITY_4
                        newTerrain.collectDetailPatches = terrain.collectDetailPatches;
                                                #endif

                        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
        progressCounter = 0;
        for (int widthIndex = 0; widthIndex < sectorsWidth; ++widthIndex)
        {
            for (int lengthIndex = 0; lengthIndex < sectorsLength; ++lengthIndex)
            {
                for (int heightIndex = 0; heightIndex < sectorsHeight; ++heightIndex)
                {
                    EditorUtility.DisplayProgressBar(progressTitle, "Creating portals...", progressCounter++ / (float)(sectorsWidth * sectorsLength * sectorsHeight));

                    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);
                    }
                }
            }
        }

        if (splitTerrain)
        {
            progressCounter = 0;
            for (int widthIndex = 0; widthIndex < sectorsWidth; ++widthIndex)
            {
                for (int lengthIndex = 0; lengthIndex < sectorsLength; ++lengthIndex)
                {
                    EditorUtility.DisplayProgressBar(progressTitle, "Smoothing split terrain...", progressCounter++ / (float)(sectorsWidth * sectorsLength * sectorsHeight));

                    // 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];

                    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();

                    // 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.wrapMode = TextureWrapMode.Clamp;
                        alphaTexture.Apply(false);
                    }

                    newTerrain.Flush();
                }
            }
        }

        EditorUtility.ClearProgressBar();

        // destroy original terrain
        if (splitTerrain)
        {
            SECTR_Undo.Destroy(terrain.gameObject, undoString);
        }
    }