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; }
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; } } } }
private void _TrySceneActivation() { if (chunkActivating == null && asyncLoadOp != null && !asyncLoadOp.allowSceneActivation && asyncLoadOp.progress >= 0.9f && activationQueue.Count > 0 && activationQueue.First.Value == this) { chunkActivating = this; asyncLoadOp.allowSceneActivation = true; } }
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); }
// 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); } } } }
protected override void OnTriggerEnter(Collider other) { base.OnTriggerEnter(other); if (Portal && ((LoadLayers & 1 << other.gameObject.layer) != 0)) { SECTR_Chunk oppositeChunk = _GetOppositeChunk(other.transform.position); if (oppositeChunk) { LoadRequest loadRequest; SECTR_Chunk postUnload = null; if (loadRequests.TryGetValue(other, out loadRequest)) { if (loadRequest.chunkToUnload) { postUnload = loadRequest.chunkToUnload; loadRequest.chunkToUnload = null; } } else { loadRequest = new LoadRequest(); } if (FadeBeforeLoad && !oppositeChunk.IsLoaded()) { loadRequest.fadeMode = FadeMode.FadeOut; } loadRequest.enteredFront = oppositeChunk.Sector == Portal.BackSector; loadRequest.enteredBack = oppositeChunk.Sector == Portal.FrontSector; if (FadeBeforeLoad) { loadRequest.chunkToLoad = oppositeChunk; } else { oppositeChunk.AddReference(); loadRequest.loadedChunk = oppositeChunk; } loadRequests[other] = loadRequest; if (postUnload) { postUnload.RemoveReference(); } } } }
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() { 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; }
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; } }
protected override void OnTriggerExit(Collider other) { base.OnTriggerExit(other); if (Portal && ((LoadLayers & 1 << other.gameObject.layer) != 0)) { SECTR_Chunk oppositeChunk = _GetOppositeChunk(other.transform.position); if (oppositeChunk) { LoadRequest loadRequest = loadRequests[other]; if (FadeBeforeLoad && loadRequest.fadeMode == FadeMode.FadeOut) { loadRequest.fadeMode = FadeMode.FadeIn; } bool exitedBack = oppositeChunk.Sector == Portal.FrontSector; bool exitedFront = oppositeChunk.Sector == Portal.BackSector; if (loadRequest.loadedChunk && ((loadRequest.enteredFront && exitedFront) || (loadRequest.enteredBack && exitedBack))) { loadRequest.chunkToUnload = loadRequest.loadedChunk; } else if ((loadRequest.enteredFront && exitedBack) || (loadRequest.enteredBack && exitedFront)) { loadRequest.chunkToUnload = oppositeChunk; } else { loadRequest.chunkToUnload = loadRequest.loadedChunk; } if (loadRequests.Count > 1 || IsClosed()) { if (loadRequest.chunkToUnload) { loadRequest.chunkToUnload.RemoveReference(); } loadRequests.Remove(other); } } } }
private void _DestoryChunk(bool createProxy, bool fromDisable) { if (cachedSector.TopTerrain || cachedSector.BottomTerrain || cachedSector.RightTerrain || cachedSector.LeftTerrain) { cachedSector.DisonnectTerrainNeighbors(); } #if UNITY_5_LATE #pragma warning disable CS0618 // Typ lub sk³adowa jest przestarza³a Application.UnloadLevel(ScenePath); #pragma warning restore CS0618 // Typ lub sk³adowa jest przestarza³a #else GameObject.Destroy(chunkRoot); #endif chunkRoot = null; chunkSector = null; recenterChunk = false; if (asyncLoadOp != null) { if (chunkActivating == this) { chunkActivating = null; } activationQueue.Remove(this); asyncLoadOp = null; } if (fromDisable || quitting) { _UnloadResources(); } else if (!requestedDeferredUnload) { requestedDeferredUnload = true; StartCoroutine("_DeferredUnload"); } loadState = LoadState.Unloaded; if (createProxy && ProxyMesh) { _CreateProxy(); } }
void FixedUpdate() { switch (loadState) { case LoadState.Loading: _TrySceneActivation(); if (asyncLoadOp == null || asyncLoadOp.isDone) { if (asyncLoadOp != null) { chunkActivating = null; activationQueue.RemoveFirst(); asyncLoadOp = null; } loadState = LoadState.Loaded; // Run update again to try to parent the chunk right away. FixedUpdate(); } break; case LoadState.Loaded: // Unity takes a frame to create the objects, so fix them up here. _SetupChunk(); break; case LoadState.Active: // Do nothing. break; case LoadState.Unloading: _TrySceneActivation(); _FindChunkRoot(); if (chunkRoot) { _DestoryChunk(true, false); } break; } }
/// Reverts all imported Sectors into the scene. Safe to call from the command line. public static void RevertSceneChunks() { int numSectors = SECTR_Sector.All.Count; for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex) { SECTR_Sector sector = SECTR_Sector.All[sectorIndex]; SECTR_Chunk chunk = sector.GetComponent <SECTR_Chunk>(); if (!sector.Frozen && chunk && System.IO.File.Exists(SECTR_Asset.UnityToOSPath(chunk.NodeName))) { EditorUtility.DisplayProgressBar("Reverting Scene Chunks", "Reverting " + sector.name, (float)sectorIndex / (float)numSectors); DeleteExportedSector(sector); } } if (SECTR_VC.CheckOut(EditorApplication.currentScene)) { EditorApplication.SaveScene(); SECTR_VC.WaitForVC(); } EditorUtility.ClearProgressBar(); }
public override void OnInspectorGUI() { SECTR_Chunk myChunk = (SECTR_Chunk)target; SECTR_Sector mySector = myChunk.GetComponent <SECTR_Sector>(); EditorGUILayout.BeginHorizontal(); bool editMode = !EditorApplication.isPlaying && !EditorApplication.isPaused; bool alreadyExported = myChunk && System.IO.File.Exists(SECTR_Asset.UnityToOSPath(myChunk.NodeName)); GUI.enabled = editMode; if (mySector.Frozen) { // Import if (alreadyExported && GUILayout.Button(new GUIContent("Import", "Imports this Sector into the scene."))) { modiferMode = ModifierMode.Import; } // Export GUI.enabled = false; GUILayout.Button(new GUIContent("Export", "Exports this Sector into a Chunk scene.")); GUI.enabled = editMode; } else { // Revert if (alreadyExported && GUILayout.Button(new GUIContent("Revert", "Discards changes to this Sector."))) { modiferMode = ModifierMode.Revert; } // Export if (GUILayout.Button(new GUIContent("Export", "Exports this Sector into a Chunk scene."))) { modiferMode = ModifierMode.Export; } } EditorGUILayout.EndHorizontal(); base.OnInspectorGUI(); if (!mySector.Frozen) { proxyFoldout = EditorGUILayout.Foldout(proxyFoldout, "Proxy Mesh Tool"); if (proxyFoldout) { EditorGUILayout.BeginVertical(); _BuildChildControls(myChunk.transform, true); if (GUILayout.Button("Create Proxy Mesh")) { Dictionary <Material, List <CombineInstance> > meshHash = new Dictionary <Material, List <CombineInstance> >(); Matrix4x4 chunkWorldToLocal = myChunk.transform.worldToLocalMatrix; foreach (Renderer renderer in checkState.Keys) { if (checkState[renderer]) { MeshFilter meshFilter = renderer.GetComponent <MeshFilter>(); int numSubMeshes = meshFilter.sharedMesh.subMeshCount; for (int submeshIndex = 0; submeshIndex < numSubMeshes; ++submeshIndex) { Material material = renderer.sharedMaterials[submeshIndex]; List <CombineInstance> materialMeshes = null; if (!meshHash.TryGetValue(material, out materialMeshes)) { materialMeshes = new List <CombineInstance>(); meshHash[material] = materialMeshes; } CombineInstance instance = new CombineInstance(); instance.transform = chunkWorldToLocal * renderer.transform.localToWorldMatrix; instance.mesh = renderer.GetComponent <MeshFilter>().sharedMesh; instance.subMeshIndex = submeshIndex; materialMeshes.Add(instance); } } } if (meshHash.Count > 0) { List <CombineInstance> combinedMeshes = new List <CombineInstance>(); List <Material> combinedMaterials = new List <Material>(); foreach (Material material in meshHash.Keys) { CombineInstance instance = new CombineInstance(); instance.mesh = new Mesh(); instance.mesh.CombineMeshes(meshHash[material].ToArray(), true, true); combinedMeshes.Add(instance); combinedMaterials.Add(material); } string sceneDir; string sceneName; string exportFolder = SECTR_Asset.MakeExportFolder("Proxies", false, out sceneDir, out sceneName); myChunk.ProxyMesh = SECTR_Asset.Create <Mesh>(exportFolder, myChunk.name + "_Proxy", new Mesh()); myChunk.ProxyMesh.CombineMeshes(combinedMeshes.ToArray(), false, false); myChunk.ProxyMaterials = combinedMaterials.ToArray(); int numCombined = combinedMeshes.Count; for (int combinedIndex = 0; combinedIndex < numCombined; ++combinedIndex) { Mesh.DestroyImmediate(combinedMeshes[combinedIndex].mesh); } SECTR_VC.WaitForVC(); } else { EditorUtility.DisplayDialog("Proxy Error", "Must have at least one mesh selected to create a proxy.", "Ok"); } } EditorGUILayout.EndVertical(); } } GUI.enabled = true; if (modiferMode != ModifierMode.None) { EditorApplication.update += ExportUpdate; } }
void Update() { Vector3 position = transform.position; Bounds loadBounds = new Bounds(position, LoadSize); Bounds unloadBounds = new Bounds(position, LoadSize * (1f + UnloadBuffer)); SECTR_Sector.GetContaining(ref loadSectors, loadBounds); SECTR_Sector.GetContaining(ref unloadSectors, unloadBounds); int sectorIndex = 0; int numSectors = sectors.Count; while (sectorIndex < numSectors) { SECTR_Sector oldSector = sectors[sectorIndex]; if (loadSectors.Contains(oldSector)) { loadSectors.Remove(oldSector); ++sectorIndex; } else if (!unloadSectors.Contains(oldSector)) { SECTR_Chunk oldChunk = oldSector.GetComponent <SECTR_Chunk>(); if (oldChunk) { oldChunk.RemoveReference(); } sectors.RemoveAt(sectorIndex); --numSectors; } else { ++sectorIndex; } } numSectors = loadSectors.Count; int layerMaskValue = LayersToLoad.value; if (numSectors > 0) { for (sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex) { SECTR_Sector newSector = loadSectors[sectorIndex]; if (newSector.Frozen && ((layerMaskValue & (1 << newSector.gameObject.layer)) != 0)) { SECTR_Chunk newChunk = newSector.GetComponent <SECTR_Chunk>(); if (newChunk) { newChunk.AddReference(); } sectors.Add(newSector); } } } if (locked && Loaded) { LockSelf(false); } updated = true; }
protected override void OnGUI() { base.OnGUI(); List <SECTR_Sector> sortedSectors = new List <SECTR_Sector>(SECTR_Sector.All); sortedSectors.Sort(delegate(SECTR_Sector a, SECTR_Sector b) { return(a.name.CompareTo(b.name)); }); int numSectors = sortedSectors.Count; bool sceneHasSectors = numSectors > 0; EditorGUILayout.BeginVertical(); DrawHeader("SECTORS", ref sectorSearch, 100, true); Rect r = EditorGUILayout.BeginVertical(); r.y -= lineHeight; scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); bool wasEnabled = GUI.enabled; GUI.enabled = false; GUI.Button(r, sceneHasSectors ? "" : "Current Scene Has No Sectors"); GUI.enabled = wasEnabled; bool allExported = true; bool allImported = true; bool someImported = false; SECTR_Sector newSelectedSector = Selection.activeGameObject ? Selection.activeGameObject.GetComponent <SECTR_Sector>() : null;; bool mouseDown = Event.current.type == EventType.MouseDown && Event.current.button == 0; if (mouseDown) { newSelectedSector = null; } for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex) { SECTR_Sector sector = sortedSectors[sectorIndex]; if (sector.name.ToLower().Contains(sectorSearch.ToLower())) { bool selected = sector == selectedSector; Rect clipRect = EditorGUILayout.BeginHorizontal(); if (selected) { Rect selectionRect = clipRect; selectionRect.y += 1; selectionRect.height -= 1; GUI.Box(selectionRect, "", selectionBoxStyle); } if (sector.Frozen) { allImported = false; } else { if (sector.GetComponent <SECTR_Chunk>()) { someImported = true; } allExported = false; } elementStyle.normal.textColor = selected ? Color.white : UnselectedItemColor; elementStyle.alignment = TextAnchor.MiddleCenter; EditorGUILayout.LabelField(sector.name, elementStyle); EditorGUILayout.EndHorizontal(); if (sector.gameObject.isStatic) { float buttonWidth = 50; SECTR_Chunk chunk = sector.GetComponent <SECTR_Chunk>(); bool alreadyExported = chunk && System.IO.File.Exists(SECTR_Asset.UnityToOSPath(chunk.NodeName)); if (sector.Frozen) { // Import if (alreadyExported && GUI.Button(new Rect(0, clipRect.yMin, buttonWidth, clipRect.height), new GUIContent("Import", "Imports this Sector into the scene."))) { SECTR_StreamExport.ImportFromChunk(sector); break; } } else { // Revert if (alreadyExported && GUI.Button(new Rect(0, clipRect.yMin, buttonWidth, clipRect.height), new GUIContent("Revert", "Discards changes to this Sector."))) { SECTR_StreamExport.DeleteExportedSector(sector); chunk.enabled = true; break; } // Export if (GUI.Button(new Rect(clipRect.xMax - buttonWidth, clipRect.yMin, buttonWidth, clipRect.height), new GUIContent("Export", "Exports this Sector into a Chunk scene."))) { SECTR_StreamExport.ExportToChunk(sector); break; } } } if (mouseDown && clipRect.Contains(Event.current.mousePosition)) { newSelectedSector = sector; } } } if (newSelectedSector != selectedSector) { selectedSector = newSelectedSector; Selection.activeGameObject = selectedSector ? selectedSector.gameObject : null; if (SceneView.lastActiveSceneView) { SceneView.lastActiveSceneView.FrameSelected(); } Repaint(); } EditorGUILayout.EndScrollView(); EditorGUILayout.EndVertical(); string nullSearch = null; GUI.enabled = true; DrawHeader("EXPORT AND IMPORT", ref nullSearch, 0, true); wasEnabled = GUI.enabled; bool editMode = !EditorApplication.isPlaying && !EditorApplication.isPaused; GUI.enabled = sceneHasSectors && !allExported && wasEnabled && editMode; if (GUILayout.Button(new GUIContent("Export All Sectors", "Exports all static Sectors into Chunk scenes and prepares them for streaming."))) { SECTR_StreamExport.ExportSceneChunksUI(); Repaint(); } GUI.enabled = sceneHasSectors && !allImported && wasEnabled && editMode; if (GUILayout.Button(new GUIContent("Import All Sectors", "Imports all exported Chunks back into the scene."))) { SECTR_StreamExport.ImportSceneChunksUI(); Repaint(); } GUI.enabled = sceneHasSectors && !allExported && someImported && wasEnabled && editMode; if (GUILayout.Button(new GUIContent("Revert All Sectors", "Reverts all exported Chunks to their exported state."))) { SECTR_StreamExport.RevertSceneChunksUI(); Repaint(); } GUI.enabled = true; DrawHeader("LIGHTMAPPING", ref nullSearch, 0, true); #if UNITY_5_LATE GUI.enabled = sceneHasSectors && selectedSector && allExported && wasEnabled && editMode; if (GUILayout.Button(new GUIContent("Lightmap Selected Sector", "Lightmaps selected Sector in isolation."))) { if (EditorUtility.DisplayDialog("Confirm Lightmap Bake", "Are you sure you want to bake lightmaps for " + selectedSector.name + "? Its lighting will not be affected by any other Sectors.", "Yes", "No")) { string[] paths = new string[2]; paths[0] = EditorApplication.currentScene; paths[1] = selectedSector.GetComponent <SECTR_Chunk>().NodeName; Lightmapping.BakeMultipleScenes(paths); } } GUI.enabled = sceneHasSectors && allExported && wasEnabled && editMode; if (GUILayout.Button(new GUIContent("Lightmap All Sectors", "Lightmaps all exported Chunks."))) { if (EditorUtility.DisplayDialog("Confirm Lightmap Bake", "Are you sure you want to bake lightmaps for all subscenes? This may take quite a while.", "Yes", "No")) { string[] paths = new string[numSectors + 1]; paths[0] = EditorApplication.currentScene; for (int sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex) { paths[sectorIndex + 1] = sortedSectors[sectorIndex].GetComponent <SECTR_Chunk>().NodeName; } Lightmapping.BakeMultipleScenes(paths); } } #endif GUI.enabled = true; DrawHeader("EXTRA", ref nullSearch, 0, true); GUI.enabled = sceneHasSectors; if (GUILayout.Button(new GUIContent("Export Sector Graph Visualization", "Writes out a .dot file of the Sector/Portal graph, which can be visualized in GraphViz."))) { SECTR_StreamExport.WriteGraphDot(); } GUI.enabled = wasEnabled; EditorGUILayout.EndVertical(); }
/// Re-adds the data from the specified Sector to the current scene. Safe to call from command line. /// <param name="sector">The Sector to import.</param> /// <returns>Returns true if Sector was successfully imported, false otherwise.</returns> public static bool ImportFromChunk(SECTR_Sector sector) { if (sector == null) { Debug.LogError("Cannot import invalid Sector."); return(false); } if (!sector.Frozen) { Debug.Log("Skipping import of unfrozen Sector"); return(true); } if (!sector.gameObject.isStatic) { Debug.Log("Skipping import of dynamic Sector " + sector.name + "."); return(true); } SECTR_Chunk chunk = sector.GetComponent <SECTR_Chunk>(); if (chunk) { EditorApplication.OpenSceneAdditive(chunk.NodeName); GameObject newNode = GameObject.Find(chunk.NodeName); if (newNode == null) { Debug.LogError("Exported data does not match scene. Skipping import of " + sector.name + "."); return(false); } SECTR_ChunkRef chunkRef = newNode.GetComponent <SECTR_ChunkRef>(); if (chunkRef && chunkRef.RealSector) { newNode = chunkRef.RealSector.gameObject; if (chunkRef.Recentered) { newNode.transform.parent = sector.transform; newNode.transform.localPosition = Vector3.zero; newNode.transform.localRotation = Quaternion.identity; newNode.transform.localScale = Vector3.one; } newNode.transform.parent = null; GameObject.DestroyImmediate(chunkRef.gameObject); } while (newNode.transform.childCount > 0) { newNode.transform.GetChild(0).parent = sector.transform; } // Merge lightmaps into the scene #if !UNITY_STREAM_ENLIGHTEN SECTR_LightmapRef newRef = newNode.GetComponent <SECTR_LightmapRef>(); if (newRef) { int numLightmaps = LightmapSettings.lightmaps.Length; LightmapData[] newLightmaps = new LightmapData[numLightmaps]; for (int lightmapIndex = 0; lightmapIndex < numLightmaps; ++lightmapIndex) { newLightmaps[lightmapIndex] = LightmapSettings.lightmaps[lightmapIndex]; } foreach (SECTR_LightmapRef.RefData refData in newRef.LightmapRefs) { if (refData.index >= 0 && refData.index < numLightmaps) { LightmapData newData = new LightmapData(); newData.lightmapNear = refData.NearLightmap; newData.lightmapFar = refData.FarLightmap; newLightmaps[refData.index] = newData; } } LightmapSettings.lightmaps = newLightmaps; #if !UNITY_4 foreach (SECTR_LightmapRef.RenderData indexData in newRef.LightmapRenderers) { if (indexData.renderer) { indexData.renderer.lightmapIndex = indexData.rendererLightmapIndex; indexData.renderer.lightmapScaleOffset = indexData.rendererLightmapScaleOffset; GameObjectUtility.SetStaticEditorFlags(indexData.renderer.gameObject, GameObjectUtility.GetStaticEditorFlags(indexData.renderer.gameObject) | StaticEditorFlags.BatchingStatic); } if (indexData.terrain) { indexData.terrain.lightmapIndex = indexData.terrainLightmapIndex; } } #endif GameObject.DestroyImmediate(newRef); } #endif // Copy terrain component specially because the generic routine doesn't work for some reason. Terrain terrain = newNode.GetComponent <Terrain>(); if (terrain) { Terrain terrainClone = sector.gameObject.AddComponent <Terrain>(); terrainClone.terrainData = terrain.terrainData; terrainClone.basemapDistance = terrain.basemapDistance; terrainClone.castShadows = terrain.castShadows; terrainClone.detailObjectDensity = terrain.detailObjectDensity; terrainClone.detailObjectDistance = terrain.detailObjectDistance; terrainClone.heightmapMaximumLOD = terrain.heightmapMaximumLOD; terrainClone.heightmapPixelError = terrain.heightmapPixelError; terrainClone.lightmapIndex = terrain.lightmapIndex; terrainClone.treeBillboardDistance = terrain.treeBillboardDistance; terrainClone.treeCrossFadeLength = terrain.treeCrossFadeLength; terrainClone.treeDistance = terrain.treeDistance; terrainClone.treeMaximumFullLODCount = terrain.treeMaximumFullLODCount; terrainClone.Flush(); } // Destroy the placeholder Member if there is one. // It's theoretically possible to have multiple members, so remove them all. SECTR_Member[] oldMembers = newNode.GetComponents <SECTR_Member>(); int numOldMembers = oldMembers.Length; for (int oldIndex = 0; oldIndex < numOldMembers; ++oldIndex) { GameObject.DestroyImmediate(oldMembers[oldIndex]); } // Copy all remaining components over Component[] remainingComponents = newNode.GetComponents <Component>(); int numRemaining = remainingComponents.Length; for (int componentIndex = 0; componentIndex < numRemaining; ++componentIndex) { Component component = remainingComponents[componentIndex]; if (component != newNode.transform && component.GetType() != typeof(Terrain)) { Component componentClone = sector.gameObject.AddComponent(component.GetType()); EditorUtility.CopySerialized(component, componentClone); } } // Enable a TerrainComposer node if there is one. MonoBehaviour terrainNeighbors = sector.GetComponent("TerrainNeighbors") as MonoBehaviour; if (terrainNeighbors) { terrainNeighbors.enabled = true; } GameObject.DestroyImmediate(newNode); sector.Frozen = false; sector.ForceUpdate(true); chunk.enabled = false; return(true); } return(false); }
/// Exports the specific Sector into an external level file, deleting the current scene copy in the process. Safe to call from command line. /// <param name="sector">The Sector to export.</param> /// <returns>Returns true if Sector was successfully exported, false otherwise.</returns> public static bool ExportToChunk(SECTR_Sector sector) { if (string.IsNullOrEmpty(EditorApplication.currentScene)) { Debug.LogError("Scene must be saved befor export."); return(false); } if (sector == null) { Debug.LogError("Cannot export null Sector."); return(false); } if (!sector.gameObject.activeInHierarchy) { Debug.LogError("Cannot export inactive Sectors."); return(false); } if (!sector.gameObject.isStatic) { Debug.Log("Skipping export of dynamic sector" + sector.name + "."); return(true); } if (sector.Frozen) { // Already exported Debug.Log("Skipping frozen sector " + sector.name); return(true); } string sceneDir; string sceneName; string exportDir = SECTR_Asset.MakeExportFolder("Chunks", false, out sceneDir, out sceneName); if (string.IsNullOrEmpty(exportDir)) { Debug.LogError("Could not create Chunks folder."); return(false); } // Delete the previous export, if there is one. // Prevents duplicate names piling up. SECTR_Chunk oldChunk = sector.GetComponent <SECTR_Chunk>(); if (oldChunk) { AssetDatabase.DeleteAsset(oldChunk.NodeName); SECTR_VC.WaitForVC(); } // Sectors are not guaranteed to be uniquely named, so always generate a unique name. string originalSectorName = sector.name; string newAssetPath = AssetDatabase.GenerateUniqueAssetPath(exportDir + sceneName + "_" + originalSectorName + ".unity"); sector.name = newAssetPath; // Make sure the current scene is saved, preserving all changes. EditorApplication.SaveScene(); SECTR_VC.WaitForVC(); string originalScene = EditorApplication.currentScene; List <EditorBuildSettingsScene> sceneSettings = new List <EditorBuildSettingsScene>(EditorBuildSettings.scenes); // SaveScene can cause crashes w/ version control, so we work around it with a copy. AssetDatabase.CopyAsset(originalScene, newAssetPath); SECTR_VC.WaitForVC(); EditorApplication.OpenScene(newAssetPath); SECTR_VC.WaitForVC(); sector = _FindSectorByName(newAssetPath); // Make sure to force update all members so that membership info is correct. List <SECTR_Member> allMembers = FindAllOfType <SECTR_Member>(); for (int memberIndex = 0; memberIndex < allMembers.Count; ++memberIndex) { allMembers[memberIndex].ForceUpdate(true); } // Multi-sector members need to stay in the master scene. foreach (SECTR_Member member in allMembers) { if (member.Sectors.Count > 1 && member.transform.IsChildOf(sector.transform)) { bool unparentMember = true; // Only affect the first member in the hierarchy below the sector Transform parent = member.transform.parent; while (parent != sector.transform) { if (parent.GetComponent <SECTR_Member>() != null) { unparentMember = false; break; } parent = parent.parent; } if (unparentMember) { if (PrefabUtility.GetPrefabType(sector.gameObject) != PrefabType.None) { Debug.LogWarning("Export is unparenting shared member " + member.name + " from prefab Sector " + sector.name + ". This will break the prefab."); } member.transform.parent = null; } } } // Unparent the sector from anything sector.transform.parent = null; // Any children of this sector should be exported. // The rest should be destroyed. List <Transform> allXforms = FindAllOfType <Transform>(); #if !UNITY_STREAM_ENLIGHTEN List <int> referencedLightmaps = new List <int>(LightmapSettings.lightmaps.Length); #endif foreach (Transform transform in allXforms) { if (transform && transform.IsChildOf(sector.transform)) { #if !UNITY_STREAM_ENLIGHTEN Renderer childRenderer = transform.GetComponent <Renderer>(); if (childRenderer && childRenderer.lightmapIndex >= 0 && !referencedLightmaps.Contains(childRenderer.lightmapIndex)) { referencedLightmaps.Add(childRenderer.lightmapIndex); } Terrain childTerrain = transform.GetComponent <Terrain>();; if (childTerrain && childTerrain.lightmapIndex >= 0 && !referencedLightmaps.Contains(childTerrain.lightmapIndex)) { referencedLightmaps.Add(childTerrain.lightmapIndex); } #endif } else if (transform) { GameObject.DestroyImmediate(transform.gameObject); } } #if !UNITY_STREAM_ENLIGHTEN if (referencedLightmaps.Count > 0) { SECTR_LightmapRef newRef = sector.GetComponent <SECTR_LightmapRef>(); if (!newRef) { newRef = sector.gameObject.AddComponent <SECTR_LightmapRef>(); } newRef.ReferenceLightmaps(referencedLightmaps); } // Nuke global data like nav meshes and lightmaps // Lightmap indexes will be preserved on export. NavMeshBuilder.ClearAllNavMeshes(); #if !UNITY_4 SerializedObject serialObj = new SerializedObject(GameObject.FindObjectOfType <LightmapSettings>()); SerializedProperty snapshotProp = serialObj.FindProperty("m_LightmapSnapshot"); snapshotProp.objectReferenceValue = null; serialObj.ApplyModifiedProperties(); #endif LightmapSettings.lightmaps = new LightmapData[0]; LightmapSettings.lightProbes = new LightProbes(); #endif GameObject dummyParent = new GameObject(newAssetPath); SECTR_ChunkRef chunkRef = dummyParent.AddComponent <SECTR_ChunkRef>(); chunkRef.RealSector = sector.transform; sector.transform.parent = dummyParent.transform; // If the sector has a chunk marked for re-use, perform some special work. SECTR_Chunk originalChunk = sector.GetComponent <SECTR_Chunk>(); if (originalChunk && originalChunk.ExportForReuse) { chunkRef.Recentered = true; sector.transform.localPosition = Vector3.zero; sector.transform.localRotation = Quaternion.identity; sector.transform.localScale = Vector3.one; sector.gameObject.SetActive(false); } // Rename the real chunk root with a clear name. sector.name = originalSectorName + "_Chunk"; // Strip off any functional objects that will be preserved in the root scene. // Destroy the chunk first because it has dependencies on Sector. GameObject.DestroyImmediate(originalChunk); Component[] components = sector.GetComponents <Component>(); foreach (Component component in components) { if (component.GetType().IsSubclassOf(typeof(MonoBehaviour)) && component.GetType() != typeof(Terrain) && component.GetType() != typeof(SECTR_LightmapRef)) { GameObject.DestroyImmediate(component); } } // Re-add a member that will persist all of the references and save us work post load. SECTR_Member refMember = chunkRef.RealSector.gameObject.AddComponent <SECTR_Member>(); refMember.NeverJoin = true; refMember.BoundsUpdateMode = SECTR_Member.BoundsUpdateModes.Static; refMember.ForceUpdate(true); // Save scene and append it to the build settings. EditorApplication.SaveScene(); SECTR_VC.WaitForVC(); EditorBuildSettingsScene sectorSceneSettings = new EditorBuildSettingsScene(newAssetPath, true); bool sceneExists = false; foreach (EditorBuildSettingsScene oldScene in sceneSettings) { if (oldScene.path == newAssetPath) { sceneExists = true; oldScene.enabled = true; break; } } if (!sceneExists) { sceneSettings.Add(sectorSceneSettings); } string[] pathParts = newAssetPath.Split('/'); string sectorPath = pathParts[pathParts.Length - 1].Replace(".unity", ""); // Update the master scene with exported info. EditorApplication.OpenScene(originalScene); SECTR_VC.WaitForVC(); sector = _FindSectorByName(newAssetPath); sector.name = originalSectorName; DeleteExportedSector(sector); // Make sure Sectors has a Chunk SECTR_Chunk newChunk = sector.GetComponent <SECTR_Chunk>(); if (!newChunk) { newChunk = sector.gameObject.AddComponent <SECTR_Chunk>(); } newChunk.ScenePath = sectorPath; newChunk.NodeName = newAssetPath; newChunk.enabled = true; // Disable a TerrainComposer node if there is one. MonoBehaviour terrainNeighbors = sector.GetComponent("TerrainNeighbors") as MonoBehaviour; if (terrainNeighbors) { terrainNeighbors.enabled = false; } // Save off the accumulated build settings EditorBuildSettings.scenes = sceneSettings.ToArray(); AssetDatabase.Refresh(); EditorApplication.SaveScene(); SECTR_VC.WaitForVC(); return(true); }