private static void ProcessDetails(Dictionary <int, int[, ]> details, DslExpression.DslCalculator calc, string proc, int x, int y, int w, int h)
    {
        for (int ix = 0; ix < w; ++ix)
        {
            for (int iy = 0; iy < h; ++iy)
            {
                int xi = x + ix;
                int yi = y + iy;
                foreach (var pair in details)
                {
                    int layer  = pair.Key;
                    var detail = pair.Value[xi, yi];
                    calc.SetGlobalVariable("detail", detail);
                    calc.Calc(proc, xi, yi, layer);
                    pair.Value[xi, yi] = calc.GetGlobalVariable("detail").Get <int>();
                }
            }

            if (DisplayCancelableProgressBar("生成detail数据", ix * h, w * h))
            {
                goto quit;
            }
        }
quit:
        EditorUtility.ClearProgressBar();
    }
    private static void ProcessAlphamaps(float[,,] alphamaps, DslExpression.DslCalculator calc, string proc, int x, int y, int w, int h)
    {
        int alphanum = alphamaps.GetLength(2);

        for (int ix = 0; ix < w; ++ix)
        {
            for (int iy = 0; iy < h; ++iy)
            {
                int     xi     = x + ix;
                int     yi     = y + iy;
                float[] alphas = calc.GetGlobalVariable("alphas").As <float[]>();
                for (int i = 0; i < alphanum; ++i)
                {
                    alphas[i] = alphamaps[xi, yi, i];
                }
                var v = calc.Calc(proc, xi, yi);
                for (int i = 0; i < alphanum; ++i)
                {
                    alphamaps[xi, yi, i] = alphas[i];
                }
            }

            if (DisplayCancelableProgressBar("生成alphamap数据", ix * h, w * h))
            {
                goto quit;
            }
        }
quit:
        EditorUtility.ClearProgressBar();
    }
    private static void ProcessHeights(float[,] datas, DslExpression.DslCalculator calc, string proc, int cx, int cy, int r)
    {
        int x  = cx - r;
        int y  = cy - r;
        int w  = r * 2;
        int h  = r * 2;
        int r2 = r * r;

        for (int ix = 0; ix < w; ++ix)
        {
            for (int iy = 0; iy < h; ++iy)
            {
                int xi = x + ix;
                int yi = y + iy;
                int dx = xi - cx;
                int dy = yi - cy;
                if (dx * dx + dy * dy <= r2)
                {
                    calc.SetGlobalVariable("height", datas[yi, xi]);
                    calc.Calc(proc, xi, yi);
                    datas[yi, xi] = calc.GetGlobalVariable("height").Get <float>();
                }
            }

            if (DisplayCancelableProgressBar("生成高度与对象数据", ix * h, w * h))
            {
                goto quit;
            }
        }
quit:
        EditorUtility.ClearProgressBar();
    }
    private static void ProcessHeights(float[,] datas, DslExpression.DslCalculator calc, string proc, int x, int y, int w, int h)
    {
        for (int ix = 0; ix < w; ++ix)
        {
            for (int iy = 0; iy < h; ++iy)
            {
                int xi = x + ix;
                int yi = y + iy;
                calc.SetGlobalVariable("height", datas[yi, xi]);
                calc.Calc(proc, xi, yi);
                datas[yi, xi] = calc.GetGlobalVariable("height").Get <float>();
            }

            if (DisplayCancelableProgressBar("生成高度与对象数据", ix * h, w * h))
            {
                goto quit;
            }
        }
quit:
        EditorUtility.ClearProgressBar();
    }
 private static void ProcessWithDsl(Dsl.FunctionData funcData, string type, float[,] datas, float[, ,] alphamaps, Dictionary <int, int[, ]> details, DslExpression.DslCalculator calc, string proc, ref bool resetTrees)
 {
     if (null == funcData)
     {
         return;
     }
     if (null != funcData)
     {
         if (type == "height")
         {
             foreach (var comp in funcData.Params)
             {
                 var callData = comp as Dsl.FunctionData;
                 if (null != callData)
                 {
                     string id = callData.GetId();
                     if (id == "resettrees")
                     {
                         resetTrees = bool.Parse(callData.GetParamId(0));
                     }
                     else if (id == "maxcount")
                     {
                         s_MaxObjectCount = int.Parse(callData.GetParamId(0));
                     }
                     else if (id == "rect")
                     {
                         int x = int.Parse(callData.GetParamId(0));
                         int y = int.Parse(callData.GetParamId(1));
                         int w = int.Parse(callData.GetParamId(2));
                         int h = int.Parse(callData.GetParamId(3));
                         ProcessHeights(datas, calc, proc, x, y, w, h);
                     }
                     else if (id == "circle")
                     {
                         int x = int.Parse(callData.GetParamId(0));
                         int y = int.Parse(callData.GetParamId(1));
                         int r = int.Parse(callData.GetParamId(2));
                         ProcessHeights(datas, calc, proc, x, y, r);
                     }
                 }
             }
         }
         else if (type == "alphamap")
         {
             int alphanum = alphamaps.GetLength(2);
             foreach (var comp in funcData.Params)
             {
                 var callData = comp as Dsl.FunctionData;
                 if (null != callData)
                 {
                     string id = callData.GetId();
                     if (id == "resettrees")
                     {
                         resetTrees = bool.Parse(callData.GetParamId(0));
                     }
                     else if (id == "maxcount")
                     {
                         s_MaxObjectCount = int.Parse(callData.GetParamId(0));
                     }
                     else if (id == "rect")
                     {
                         int x = int.Parse(callData.GetParamId(0));
                         int y = int.Parse(callData.GetParamId(1));
                         int w = int.Parse(callData.GetParamId(2));
                         int h = int.Parse(callData.GetParamId(3));
                         ProcessAlphamaps(alphamaps, calc, proc, x, y, w, h);
                     }
                     else if (id == "circle")
                     {
                         int x = int.Parse(callData.GetParamId(0));
                         int y = int.Parse(callData.GetParamId(1));
                         int r = int.Parse(callData.GetParamId(2));
                         ProcessAlphamaps(alphamaps, calc, proc, x, y, r);
                     }
                 }
             }
         }
         else if (type == "detail")
         {
             foreach (var comp in funcData.Params)
             {
                 var callData = comp as Dsl.FunctionData;
                 if (null != callData)
                 {
                     string id = callData.GetId();
                     if (id == "resettrees")
                     {
                         resetTrees = bool.Parse(callData.GetParamId(0));
                     }
                     else if (id == "maxcount")
                     {
                         s_MaxObjectCount = int.Parse(callData.GetParamId(0));
                     }
                     else if (id == "rect")
                     {
                         int x = int.Parse(callData.GetParamId(0));
                         int y = int.Parse(callData.GetParamId(1));
                         int w = int.Parse(callData.GetParamId(2));
                         int h = int.Parse(callData.GetParamId(3));
                         ProcessDetails(details, calc, proc, x, y, w, h);
                     }
                     else if (id == "circle")
                     {
                         int x = int.Parse(callData.GetParamId(0));
                         int y = int.Parse(callData.GetParamId(1));
                         int r = int.Parse(callData.GetParamId(2));
                         ProcessDetails(details, calc, proc, x, y, r);
                     }
                 }
             }
         }
     }
 }
 internal static void Process(GameObject root, Dsl.DslFile file, Dictionary <string, Color32[, ]> samplers, Dictionary <string, Size> cacheInfos, List <ObjectInfo> objects)
 {
     if (null != file)
     {
         List <TreeInstance>          trees  = new List <TreeInstance>();
         Dictionary <string, int[, ]> caches = new Dictionary <string, int[, ]>();
         foreach (var pair in cacheInfos)
         {
             caches.Add(pair.Key, new int[pair.Value.Width, pair.Value.Height]);
         }
         var   terrain     = root.GetComponent <Terrain>();
         var   terrainData = terrain.terrainData;
         var   datas       = terrainData.GetHeights(0, 0, terrainData.heightmapWidth, terrainData.heightmapHeight);
         var   alphamaps   = terrainData.GetAlphamaps(0, 0, terrainData.alphamapWidth, terrainData.alphamapHeight);
         int   alphanum    = alphamaps.GetLength(2);
         int[] layers      = terrainData.GetSupportedLayers(0, 0, terrainData.detailWidth, terrainData.detailHeight);
         Dictionary <int, int[, ]> details = new Dictionary <int, int[, ]>();
         foreach (int layer in layers)
         {
             var ds = terrainData.GetDetailLayer(0, 0, terrainData.detailWidth, terrainData.detailHeight, layer);
             details.Add(layer, ds);
         }
         var calc = new DslExpression.DslCalculator();
         calc.Init();
         calc.Register("getheight", new DslExpression.ExpressionFactoryHelper <GetHeightExp>());
         calc.Register("getalphamap", new DslExpression.ExpressionFactoryHelper <GetAlphamapExp>());
         calc.Register("getalpha", new DslExpression.ExpressionFactoryHelper <GetAlphaExp>());
         calc.Register("setalpha", new DslExpression.ExpressionFactoryHelper <SetAlphaExp>());
         calc.Register("getdetail", new DslExpression.ExpressionFactoryHelper <GetDetailExp>());
         calc.Register("samplered", new DslExpression.ExpressionFactoryHelper <SampleRedExp>());
         calc.Register("samplegreen", new DslExpression.ExpressionFactoryHelper <SampleGreenExp>());
         calc.Register("sampleblue", new DslExpression.ExpressionFactoryHelper <SampleBlueExp>());
         calc.Register("samplealpha", new DslExpression.ExpressionFactoryHelper <SampleAlphaExp>());
         calc.Register("getcache", new DslExpression.ExpressionFactoryHelper <GetCacheExp>());
         calc.Register("setcache", new DslExpression.ExpressionFactoryHelper <SetCacheExp>());
         calc.Register("addtree", new DslExpression.ExpressionFactoryHelper <AddTreeExp>());
         calc.Register("addobject", new DslExpression.ExpressionFactoryHelper <AddObjectExp>());
         calc.SetGlobalVariable("samplers", CalculatorValue.FromObject(samplers));
         calc.SetGlobalVariable("caches", CalculatorValue.FromObject(caches));
         calc.SetGlobalVariable("trees", CalculatorValue.FromObject(trees));
         calc.SetGlobalVariable("objects", CalculatorValue.FromObject(objects));
         calc.SetGlobalVariable("heightscalex", terrainData.heightmapScale.x);
         calc.SetGlobalVariable("heightscaley", terrainData.heightmapScale.y);
         calc.SetGlobalVariable("heightscalez", terrainData.heightmapScale.z);
         calc.SetGlobalVariable("heights", CalculatorValue.FromObject(datas));
         calc.SetGlobalVariable("alphamaps", CalculatorValue.FromObject(alphamaps));
         calc.SetGlobalVariable("alphanum", CalculatorValue.FromObject(alphanum));
         calc.SetGlobalVariable("details", CalculatorValue.FromObject(details));
         calc.SetGlobalVariable("height", 0.0f);
         calc.SetGlobalVariable("alphas", CalculatorValue.FromObject(new float[alphanum]));
         calc.SetGlobalVariable("detail", 0);
         bool resetTrees  = false;
         bool canContinue = true;
         foreach (var comp in file.DslInfos)
         {
             var info = comp as Dsl.StatementData;
             if (null == info)
             {
                 continue;
             }
             bool check = false;
             int  num   = info.GetFunctionNum();
             if (num >= 2)
             {
                 string firstId = info.First.GetId();
                 if (firstId == "input")
                 {
                     check = true;
                     for (int i = 1; i < info.GetFunctionNum(); ++i)
                     {
                         string id = info.GetFunctionId(i);
                         if (id == "height" || id == "alphamap" || id == "detail")
                         {
                         }
                         else
                         {
                             check = false;
                             break;
                         }
                     }
                 }
             }
             if (!check)
             {
                 canContinue = false;
                 Debug.LogErrorFormat("error script:{0}, {1}", info.GetLine(), info.ToScriptString(false));
             }
         }
         if (canContinue)
         {
             int ix = 0;
             foreach (var comp in file.DslInfos)
             {
                 var info = comp as Dsl.StatementData;
                 if (null == info)
                 {
                     continue;
                 }
                 for (int i = 1; i < info.GetFunctionNum(); ++i)
                 {
                     calc.LoadDsl(ix.ToString(), info.GetFunction(i));
                     ++ix;
                 }
             }
             int ix2 = 0;
             foreach (var comp in file.DslInfos)
             {
                 var info = comp as Dsl.StatementData;
                 if (null == info)
                 {
                     continue;
                 }
                 for (int i = 1; i < info.GetFunctionNum(); ++i)
                 {
                     ProcessWithDsl(info.First, info.GetFunctionId(i), datas, alphamaps, details, calc, ix2.ToString(), ref resetTrees);
                     ++ix2;
                 }
             }
         }
         terrainData.SetHeights(0, 0, datas);
         terrainData.SetAlphamaps(0, 0, alphamaps);
         foreach (var pair in details)
         {
             terrainData.SetDetailLayer(0, 0, pair.Key, pair.Value);
         }
         if (resetTrees)
         {
             terrainData.treeInstances = trees.ToArray();
         }
         else
         {
             trees.AddRange(terrainData.treeInstances);
             terrainData.treeInstances = trees.ToArray();
         }
     }
 }