public void RegeneratePatch()
        {
            if (GenerateDebugGrid)
            {
                var root          = new GameObject("rootGrid");
                var segmentLength = 90;
                for (int x = -3; x < 3; x++)
                {
                    for (int y = -3; y < 3; y++)
                    {
                        var inGamePosition = new MyRectangle(x * segmentLength, y * segmentLength, segmentLength, segmentLength);
                        var flatLod        = new FlatLod(1, 0);
                        var detailPack     = _provider.ProvideSurfaceDetailAsync(inGamePosition, flatLod).Result;

                        var quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
                        //StandardMaterialUtils.SetMaterialRenderingModeToAlphablend(quad.GetComponent<MeshRenderer>().material);
                        quad.name = $"Plate {x} : {y}";
                        quad.transform.rotation      = Quaternion.Euler(90, 0, 0);
                        quad.transform.localScale    = new Vector3(segmentLength, segmentLength, 1);
                        quad.transform.localPosition = new Vector3(inGamePosition.X + inGamePosition.Width / 2, 1, inGamePosition.Y + inGamePosition.Height / 2);
                        quad.transform.SetParent(root.transform);
                        if (detailPack != null)
                        {
                            quad.GetComponent <MeshRenderer>().GetComponent <MeshRenderer>().material.mainTexture = detailPack.MainTexture;
                        }
                        else
                        {
                            GameObject.Destroy(quad);
                        }
                    }
                }
            }
            else
            {
                MyRectangle inGamePosition = new MyRectangle(PatchArea.x, PatchArea.y, PatchArea.z - PatchArea.x, PatchArea.w - PatchArea.y);
                var         flatLod        = new FlatLod(1, 0);

                var detailPack = _provider.ProvideSurfaceDetailAsync(inGamePosition, flatLod).Result;
                DummyPlate1.GetComponent <MeshRenderer>().material.mainTexture = detailPack.MainTexture;
                //DummyPlate2.GetComponent<MeshRenderer>().material.SetTexture("_BumpMap", detailPack.NormalTexture);

                //var devisedPatches = _patchesCreatorProxy.CreatePatchAsync(inGamePosition.ToRectangle(), flatLod.ScalarValue).Result;
                //var onlyPatch = devisedPatches.First();

                //var repositioner = Repositioner.Default; //todo
                //var templates = new List<Ring2PlateStampTemplate>();
                //foreach (var sliceInfo in onlyPatch.SliceInfos)
                //{
                //    var propertyBlock = sliceInfo.Uniforms.ToPropertyBlockTemplate();

                //    templates.Add(new Ring2PlateStampTemplate( new MaterialTemplate(
                //            Ring2ShaderNames.RuntimeTerrainTexture, sliceInfo.Keywords, propertyBlock), repositioner.Move(onlyPatch.SliceArea), flatLod.ScalarValue));
                //}

                //var material = Ring2PlateStamper_CreateRenderMaterial(templates.First());
                //material.EnableKeyword("GENERATE_COLOR");
                //DummyPlate2.GetComponent<MeshRenderer>().material = material;
            }
        }
        public async Task <TokenizedESurfaceTexturesPackToken> ProvideSurfaceDetail(MyRectangle inGamePosition, FlatLod flatLod)
        {
            var internalToken = GenerateInternalToken(inGamePosition, flatLod);
            var queryOutput   = await _cache.TryRetriveAsync(internalToken);

            if (queryOutput.Asset != null)
            {
                return(new TokenizedESurfaceTexturesPackToken()
                {
                    Pack = queryOutput.Asset.Pack,
                    Token = internalToken
                });
            }
            else
            {
                var detailElement = await _provider.ProvideSurfaceDetailAsync(inGamePosition, flatLod);

                var  queryOutputCreationObligationToken = queryOutput.CreationObligationToken.Value;
                bool wasAdded = await _cache.AddAssetAsync(queryOutputCreationObligationToken, internalToken, new NullableESurfaceTexturesPack()
                {
                    Pack = detailElement
                });

                var tokenToPassOut = internalToken;
                if (!wasAdded)
                {
                    tokenToPassOut = null;
                }
                return(new TokenizedESurfaceTexturesPackToken()
                {
                    Pack = detailElement,
                    Token = tokenToPassOut
                });
            }
        }