/// <summary> /// TODO: This is a very complicated method. Is there a way to move towards componentisation? /// TODO: Layer filter method should be able to include/exclude arbitrary numbers of layers (currently it is all or one) /// Generally it doesn't make sense to apply only one component for a given layer. While partial recalculation /// might be possible, it doesn't currently exist. So when we recalcualte one component on a layer, we also /// recalculate all other Components on that layer. /// </summary> /// <param name="wrapper">The wrapper to recalculate the Components for</param> /// <param name="layerFilter">A name filter for the layers (for recalculating a single layer)</param> public static void ApplyAllLayerComponents(TerrainWrapper wrapper, string layerFilter = null) { Profiler.BeginSample("ApplyallLayerComponents"); var mappings = SortComponents(wrapper, layerFilter); for (int i = 0; i < mappings.Count; i++) { var layerStampMapping = mappings[i]; for (int j = 0; j < layerStampMapping.Components.Count; j++) { MiscUtilities.ProgressBar(String.Format("PreBake for Component {0}", layerStampMapping.Components[j].name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count); layerStampMapping.Components[j].OnPreBake(); } } mappings = SortComponents(wrapper, layerFilter); if (wrapper.Locked) { Debug.LogWarning(string.Format("Attempted to write to Terrain Wrapper {0} but it was locked.", wrapper.name), wrapper); } else { bool anyLayerWrittenTo = false; // Okay, we've organised our Components in such a way so we can iterate through and execute them. // Iterating the mappings here is equivalent to iterating through the TerrainWrapper layers and executing all the relevant Components for each layer. for (int i = 0; i < mappings.Count; i++) { var layerStampMapping = mappings[i]; var layer = wrapper.GetLayer <MMTerrainLayer>(layerStampMapping.LayerName, false, true); // Is this redundant or just cautious? See line 100 // Here, we copy the flattened information of all layers below this layer to the current layer, to easily blend new data with old data. // A somewhat naive solution, but the best I have found after trying several out. wrapper.CopyCompoundToLayer(layer); anyLayerWrittenTo = true; if (wrapper.WriteHeights) { // Heights are a special type of layer, as layerComponents have the ability to compete with each other and determine who gets control of a point // on the map through their height values. For this reason heights needed to be evaluated first, so winners can be determined. for (int j = 0; j < layerStampMapping.Components.Count; j++) { MiscUtilities.ProgressBar(String.Format("Applying Heights for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count); layerStampMapping.Components[j].ProcessHeights(wrapper, layer, j + 1); } } // The Stencil is a critical component of componenting. Fundament It holds a dual purpose - blending for (int j = 0; j < layerStampMapping.Components.Count; j++) { var stamp = layerStampMapping.Components[j]; MiscUtilities.ProgressBar(String.Format("Applying Stencil for Component {0} : Layer {1}", stamp.name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count); stamp.ProcessStencil(wrapper, layer, j + 1); } MiscUtilities.ClampStencil(layer.Stencil); for (int j = 0; j < layerStampMapping.Components.Count; j++) { var layerComponent = layerStampMapping.Components[j]; var stencilKey = j + 1; if (wrapper.WriteSplats) { MiscUtilities.ProgressBar(String.Format("Applying Splats for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count); layerComponent.ProcessSplats(wrapper, layer, stencilKey); } if (wrapper.WriteObjects) { MiscUtilities.ProgressBar(String.Format("Applying Objects for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count); layerComponent.ProcessObjects(wrapper, layer, stencilKey); } if (wrapper.WriteTrees) { MiscUtilities.ProgressBar(String.Format("Applying Trees for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count); layerComponent.ProcessTrees(wrapper, layer, stencilKey); } if (wrapper.WriteDetails) { MiscUtilities.ProgressBar(String.Format("Applying Details for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count); layerComponent.ProcessDetails(wrapper, layer, stencilKey); } #if VEGETATION_STUDIO if (wrapper.WriteVegetationStudio) { MiscUtilities.ProgressBar(String.Format("Applying Details for Component {0} : Layer {1}", layerStampMapping.Components[j].name, layer.name), String.Format("{0}/{1}", j, layerStampMapping.Components.Count), j / (float)layerStampMapping.Components.Count); layerComponent.ProcessVegetationStudio(wrapper, layer, stencilKey); } #endif layer.Dirty = false; } if (anyLayerWrittenTo) { wrapper.SetDirtyAbove(layer); MiscUtilities.ColoriseStencil(layer.Stencil); wrapper.ClearCompoundCache(layer); #if UNITY_EDITOR UnityEditor.EditorUtility.SetDirty(layer); #endif wrapper.Dirty = true; } } } for (int i = 0; i < mappings.Count; i++) { var layerStampMapping = mappings[i]; for (int j = 0; j < layerStampMapping.Components.Count; j++) { layerStampMapping.Components[j].OnPostBake(); } } MiscUtilities.ClearProgressBar(); Profiler.EndSample(); }