Example #1
0
        public static Bitmap RenderBitmapFromBlueprint(CancellationToken?worker, BlueprintPA blueprint, out int?textureSize)
        {
            // TODO: Make sure this value is saved to the render panel instance somehow or else there will be horrible issues
            textureSize = RenderedImagePanel.CalculateTextureSize(blueprint);
            if (textureSize == null)
            {
                return(null);
            }

            if (blueprint != null)
            {
                try
                {
                    TaskManager.SafeReport(0, "Preparing canvas for textures");
                    bool   isSelectiveLayerViewEnabled = Options.Get.IsEnabled(Constants.RenderedZIndexFilter, false);
                    bool   isMaterialFilterViewEnabled = Options.Get.SelectedMaterialFilter.Any();
                    bool   isSide = Options.Get.IsSideView;
                    double origW  = blueprint.Width;
                    double origH  = blueprint.Height;
                    //int w = (int) (origW * MainForm.PanZoomSettings.zoomLevel);
                    //int h = (int) (origH * MainForm.PanZoomSettings.zoomLevel);
                    //int zoom = (int) (MainForm.PanZoomSettings.zoomLevel);

                    SolidBrush brush = new SolidBrush(Color.Black);
                    Pen        pen   = new Pen(brush);

                    bool isMaterialIncludedInFilter = true;
                    int  mWidth  = blueprint.Width;
                    int  mHeight = blueprint.Height;
                    int  mDepth  = Options.Get.IsMultiLayer ? 2 : 1;

                    int calcW = mWidth * textureSize.Value;
                    int calcH = mHeight * textureSize.Value;
                    TaskManager.SafeReport(20, "Preparing canvas for textures");

                    Bitmap bm = new Bitmap(
                        width: calcW,
                        height: calcH,
                        format: PixelFormat.Format32bppArgb);

                    TaskManager.SafeReport(50, "Preparing canvas for textures");
                    var  selectedMaterials      = Options.Get.SelectedMaterialFilter.AsEnumerable().ToList(); // clone
                    bool _IsSolidColors         = Options.Get.Rendered_IsSolidColors;
                    bool _IsColorPalette        = Options.Get.Rendered_IsColorPalette;
                    bool _IsMultiLayer          = Options.Get.IsMultiLayer;
                    bool _isSkipShadowRendering = Options.Get.IsShadowRenderingSkipped;
                    int  _RenderedZIndexToShow  = Options.Get.Rendered_RenderedZIndexToShow;
                    bool _isFrugalAesthetic     = Options.Get.IsExtraShadowDepthEnabled && !selectedMaterials.Any();

                    using (Graphics gImg = Graphics.FromImage(bm))
                    {
                        gImg.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                        gImg.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.None;
                        gImg.PixelOffsetMode   = System.Drawing.Drawing2D.PixelOffsetMode.Half;


                        #region Regular
                        for (int z = 0; z < mDepth; z++)
                        {
                            TaskManager.SafeReport(0, "Applying textures... (Layer " + z + ")");

                            if (isSelectiveLayerViewEnabled)
                            {
                                if (z != _RenderedZIndexToShow)
                                {
                                    continue;
                                }
                            }

                            for (int x = 0; x < mWidth; x++)
                            {
                                TaskManager.SafeReport(100 * x / mWidth);
                                worker?.SafeThrowIfCancellationRequested();
                                for (int y = 0; y < mHeight; y++)
                                {
                                    int xi = x * textureSize.Value;
                                    int yi = y * textureSize.Value;
                                    //if (xi + MainForm.PanZoomSettings.zoomLevel >= 0 && yi + MainForm.PanZoomSettings.zoomLevel >= 0)
                                    {
                                        Material m = blueprint.GetMaterialAt(x, y, z, !_isFrugalAesthetic);

                                        if (isMaterialFilterViewEnabled)
                                        {
                                            string blockId = m.PixelStackerID;
                                            isMaterialIncludedInFilter = Options.Get.SelectedMaterialFilter.Any(xm => xm == blockId);
                                        }

                                        if (m.BlockID != 0)
                                        {
                                            if (_IsSolidColors)
                                            {
                                                if (isMaterialIncludedInFilter)
                                                {
                                                    brush.Color = blueprint.GetColor(x, y);
                                                    gImg.FillRectangle(brush, xi, yi, textureSize.Value, textureSize.Value);
                                                }
                                            }
                                            else if (_IsColorPalette)
                                            {
                                                if (isMaterialIncludedInFilter)
                                                {
                                                    brush.Color = blueprint.GetColor(x, y);
                                                    gImg.DrawImage(m.getImage(isSide), xi, yi, textureSize.Value, textureSize.Value);
                                                    gImg.FillRectangle(brush, xi, yi, textureSize.Value / 2, textureSize.Value / 2);
                                                    brush.Color = Color.Black;
                                                    gImg.DrawRectangle(pen, xi, yi, textureSize.Value / 2, textureSize.Value / 2);
                                                }
                                            }
                                            else
                                            {
                                                if (isMaterialIncludedInFilter)
                                                {
                                                    gImg
                                                    .DrawImage(m.getImage(isSide), xi, yi, textureSize.Value, textureSize.Value);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        #endregion

                        #region SHADOW_NEW
                        if (!_isSkipShadowRendering)
                        {
                            Bitmap bmShadeSprites = ShadowHelper.GetSpriteSheet(Constants.TextureSize);

                            Bitmap bmShadow = new Bitmap(
                                width: calcW,
                                height: calcH,
                                format: PixelFormat.Format32bppArgb);

                            byte[,] shadowMap = new byte[mWidth, mHeight];
                            {
                                #region Initialize shadow map (booleans basically)
                                TaskManager.SafeReport(0, "Calculating shadow placement map");
                                for (int xShadeMap = 0; xShadeMap < mWidth; xShadeMap++)
                                {
                                    TaskManager.SafeReport(100 * xShadeMap / mWidth);
                                    worker?.SafeThrowIfCancellationRequested();

                                    for (int yShadeMap = 0; yShadeMap < mHeight; yShadeMap++)
                                    {
                                        Material mBottom       = blueprint.GetMaterialAt(xShadeMap, yShadeMap, 0, true);
                                        bool     isBottomShown = mBottom.BlockID != 0 && (selectedMaterials.Count == 0 || selectedMaterials.Any(xm => xm == mBottom.PixelStackerID));

                                        Material mTop       = blueprint.GetMaterialAt(xShadeMap, yShadeMap, 1, !_isFrugalAesthetic);
                                        bool     isTopShown = mTop.BlockID != 0 && (selectedMaterials.Count == 0 || selectedMaterials.Any(xm => xm == mTop.PixelStackerID));

                                        if (isTopShown && isBottomShown)
                                        {
                                            shadowMap[xShadeMap, yShadeMap] = SHOWN_TOP_AND_BOTTOM;
                                        }
                                        else if (isTopShown)
                                        {
                                            shadowMap[xShadeMap, yShadeMap] = SHOWN_TOP;
                                        }
                                        else if (isBottomShown)
                                        {
                                            shadowMap[xShadeMap, yShadeMap] = SHOWN_BOTTOM;
                                        }
                                        else
                                        {
                                            shadowMap[xShadeMap, yShadeMap] = SHOWN_NONE;
                                        }
                                    }
                                }
                                #endregion

                                using (Graphics gShadow = Graphics.FromImage(bmShadow))
                                {
                                    gShadow.CompositingMode   = CompositingMode.SourceOver; // over is slower but better...
                                    gShadow.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                                    gShadow.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                                    gShadow.PixelOffsetMode   = System.Drawing.Drawing2D.PixelOffsetMode.Half;

                                    var brushTransparentCover = new SolidBrush(Color.FromArgb(40, 127, 127, 127));
                                    {
                                        TaskManager.SafeReport(0, "Rendering shadows");
                                        for (int x = 0; x < mWidth; x++)
                                        {
                                            TaskManager.SafeReport(100 * x / mWidth);
                                            worker?.SafeThrowIfCancellationRequested();
                                            for (int y = 0; y < mHeight; y++)
                                            {
                                                int xi = x * textureSize.Value;
                                                int yi = y * textureSize.Value;

                                                bool isTopShown    = shadowMap[x, y] == SHOWN_TOP || shadowMap[x, y] == SHOWN_TOP_AND_BOTTOM;
                                                bool isBottomShown = shadowMap[x, y] == SHOWN_BOTTOM || shadowMap[x, y] == SHOWN_TOP_AND_BOTTOM;
                                                bool isBottomCoveredByInvisibleTop = isBottomShown && !isTopShown;

                                                // The thing that makes it slightly less saturated on bottom layer
                                                if (isBottomCoveredByInvisibleTop && _IsMultiLayer)
                                                {
                                                    gShadow.FillRectangle(brushTransparentCover, xi, yi, textureSize.Value, textureSize.Value);
                                                }

                                                if (isTopShown && isBottomShown)
                                                {
                                                    continue; // No shade required
                                                }

                                                // AIR block (or block we aint rendering)
                                                if (!isTopShown)
                                                {
                                                    ShadeFrom sFrom              = ShadeFrom.EMPTY;
                                                    bool      isBlockTop         = y > 0 && isShaded(shadowMap[x, y], shadowMap[x, y - 1]);
                                                    bool      isBlockLeft        = x > 0 && isShaded(shadowMap[x, y], shadowMap[x - 1, y]);
                                                    bool      isBlockRight       = x < mWidth - 1 && isShaded(shadowMap[x, y], shadowMap[x + 1, y]);
                                                    bool      isBlockBottom      = (y < mHeight - 1 && isShaded(shadowMap[x, y], shadowMap[x, y + 1]));
                                                    bool      isBlockTopLeft     = (y > 0 && x > 0 && isShaded(shadowMap[x, y], shadowMap[x - 1, y - 1]));
                                                    bool      isBlockTopRight    = (y > 0 && x < mWidth - 1 && isShaded(shadowMap[x, y], shadowMap[x + 1, y - 1]));
                                                    bool      isBlockBottomLeft  = (y < mHeight - 1 && x > 0 && isShaded(shadowMap[x, y], shadowMap[x - 1, y + 1]));
                                                    bool      isBlockBottomRight = (y < mHeight - 1 && x < mWidth - 1 && isShaded(shadowMap[x, y], shadowMap[x + 1, y + 1]));

                                                    if (isBlockTop)
                                                    {
                                                        sFrom |= ShadeFrom.T;
                                                    }
                                                    if (isBlockLeft)
                                                    {
                                                        sFrom |= ShadeFrom.L;
                                                    }
                                                    if (isBlockRight)
                                                    {
                                                        sFrom |= ShadeFrom.R;
                                                    }
                                                    if (isBlockBottom)
                                                    {
                                                        sFrom |= ShadeFrom.B;
                                                    }
                                                    if (isBlockTopLeft)
                                                    {
                                                        sFrom |= ShadeFrom.TL;
                                                    }
                                                    if (isBlockTopRight)
                                                    {
                                                        sFrom |= ShadeFrom.TR;
                                                    }
                                                    if (isBlockBottomLeft)
                                                    {
                                                        sFrom |= ShadeFrom.BL;
                                                    }
                                                    if (isBlockBottomRight)
                                                    {
                                                        sFrom |= ShadeFrom.BR;
                                                    }

                                                    var shadeImg = ShadowHelper.GetSpriteIndividual(Constants.TextureSize, sFrom);
                                                    gShadow.DrawImage(image: shadeImg, xi, yi, textureSize.Value, textureSize.Value);
                                                }
                                            }
                                        }
                                    }

                                    brushTransparentCover.Dispose();
                                }

                                gImg.CompositingMode = CompositingMode.SourceOver;
                                gImg.DrawImage(bmShadow, 0, 0, calcW, calcH);
                            }
                        }

                        #endregion
                        brush.DisposeSafely();
                        pen.DisposeSafely();
                    }


                    return(bm);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                    blueprint = null;
                }
            }

            return(null);
        }