using SpriteStacker.Properties; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Runtime.Versioning; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace SpriteStacker { public enum RenderMode { Editing, Rendering } public static class Config { public static Color BasePlateColour = Color.FromArgb(255, 255, 255, 255); public static int BackgroundTile = 2; public static List customFonts = new List(); public static int FontSize = 16; public static int RenderIndex = 0; public static RenderMode renderMode = RenderMode.Editing; public static int RenderResolution = 1; } public class ColourPalette { int PaletteSize = 24; public Rectangle Bounds; Rectangle[] ColourTiles; Color[] colors; int TileSize = 2; int hoverIndex = -1; int SelectedIndex = 0; public ColourPalette(int paletteSize, Color[] colors) { PaletteSize = paletteSize; this.colors = colors; } public Color getSelectedColour() { return colors[SelectedIndex]; } public void SelectColour() { if (hoverIndex != -1) { SelectedIndex = hoverIndex; Camera.SelectedColor = colors[SelectedIndex]; } } public void CalculateSize() { Bounds = new Rectangle(0,Camera.Height/8, 7 * (int)(TileSize * Camera.scale), 5); int HorizontalTiles = (int)(Bounds.Width / (TileSize * Camera.scale)) - 2; ColourTiles = new Rectangle[PaletteSize]; int x = 0; int y = 0; for (int i = 0; i < PaletteSize; i++) { ColourTiles[i] = new Rectangle(Bounds.X + (int)Camera.scale + (int)((TileSize * Camera.scale * (x + 1)) / (HorizontalTiles)) + (int)(TileSize * Camera.scale * x),Bounds.Y + (int)(TileSize * Camera.scale * (y + 2)) / HorizontalTiles + (int)(TileSize * Camera.scale * y), (int)(TileSize * Camera.scale), (int)(TileSize * Camera.scale)); x++; if (x >= HorizontalTiles) { x = 0; y++; } if (y * (int)(TileSize * Camera.scale) >= Bounds.Height) { Bounds.Height = (y + 10) * (int)(TileSize * Camera.scale); } } } public void SetHover(Point MouseLocation) { bool Hovering = false; ; for (int i = 0; i < ColourTiles.Length; i++) { if (ColourTiles[i].Contains(MouseLocation)) { Hovering = true; hoverIndex = i; } } if (!Hovering) hoverIndex = -1; } public void Draw(Graphics g) { g.ResetTransform(); g.FillRectangle(Brushes.White, Bounds); g.DrawRectangle(new Pen(new SolidBrush(Color.Wheat), Camera.scale),Bounds); for (int i = 0; i < PaletteSize; i++) { g.ResetTransform(); if (i == hoverIndex) { g.ScaleTransform(1.2f, 1.2f); g.TranslateTransform(-(int)(ColourTiles[i].Left * 0.2), -(int)(ColourTiles[i].Top* 0.2)); } g.FillRectangle(new SolidBrush(colors[i]), ColourTiles[i]); g.DrawRectangle(new Pen(i == SelectedIndex ? Brushes.Blue : Brushes.Black), ColourTiles[i]); } } } public enum BrushType { Square, Circle, Spray } public static class Camera { public static float ViewAngle = 1.0f; public static int CanvasWidth = 25; public static int CanvasHeight = 25; public static int BrushX = 0; public static int BrushY = 0; public static int LocX = 0; public static int LocY = 50; public static float Rotation = 0; public static int BrushSize = 1; public static float scale = 10; public static int Width; public static int Height; public static int SelectedLayer = 0; public static Color SelectedColor = Color.Yellow; public static BrushType type = BrushType.Square; public static double CircleIntensity =1; public static int SprayIntensity =1; public static int BrushIndex = 0; public static bool EditMode = false; public static int square(int a) { return a * a; } public static bool isWithinCircle(int x, int y, int radius, int a, int b) { if (radius <= 2) return true; return square(x - a) + square(y - b) < square(radius)/ CircleIntensity; } } public class Voxel { Color VoxelColor; public Voxel(Color voxelColor) { VoxelColor = voxelColor; } public Color GetColor() { return VoxelColor; } public Color[] GetShadedColors(int[] Shadows) { Color[] sides = new Color[6]; for (int i = 0; i < 6; i++) { sides[i] = Color.FromArgb(Math.Max(Math.Min(VoxelColor.R + Shadows[i], 255), 0), Math.Max(Math.Min(VoxelColor.G + Shadows[i], 255), 0), Math.Max(Math.Min(VoxelColor.B + Shadows[i], 255), 0)); } return sides; } public Color[] GetShadedColors() { Color[] sides = new Color[6]; int[] Shadows = new int[6] { 0, 10, 0, 10, 20, -20 }; for (int i = 0; i < 6; i++) { sides[i] = Color.FromArgb(Math.Max(Math.Min(VoxelColor.R + Shadows[i], 255), 0), Math.Max(Math.Min(VoxelColor.G + Shadows[i], 255), 0), Math.Max(Math.Min(VoxelColor.B + Shadows[i], 255), 0)); } return sides; } } public class Model { public List LayerImages = new List(); List ModelData = new List(); public int Width; public int Length; public List Bounds = new List(); public Bitmap RenderedModel; public Model(int Width, int Length) { this.Width = Width; this.Length = Length; RenderedModel = new Bitmap(Width * 2, Length * 2); AddLayer(); } public void SetCurrentLayer(int Layer) { if(Layer >= ModelData.Count) { AddLayers(Layer + 1 - ModelData.Count); } Camera.SelectedLayer = Layer; } public void AddLayers(int layerCount) { for (int i = 0; i < layerCount; i++) { AddLayer(); } } public void SetBitmapLayers(Bitmap[] images) { LayerImages = images.ToList(); ModelData.Clear(); Bounds.Clear(); for(int i = 0;i < LayerImages.Count; i++) { Width = LayerImages[i].Width; Length = LayerImages[i].Height; ModelData.Add(new Voxel[Width, Length]); Bounds.Add(new Rectangle(new Point(-(int)(Width * Camera.scale) / 2, -(int)(Length * Camera.scale) / 2), new Size((int)(Width * Camera.scale), (int)(Length * Camera.scale)))); for (int x = 0; x < LayerImages[i].Width; x++) { for(int y = 0; y < LayerImages[i].Height; y++) { ModelData[i][x,y] = new Voxel(LayerImages[i].GetPixel(x,y)); } } } } public void UpdateBounds() { for (int i = 0; i < ModelData.Count; i++) { Bounds[i] = new Rectangle(new Point(-(int)(Width * Camera.scale) / 2, -(int)(Length * Camera.scale) / 2), new Size((int)(Width * Camera.scale), (int)(Length * Camera.scale))); } } public void AddLayer() { LayerImages.Add(new Bitmap(Width, Length)); ModelData.Add(new Voxel[Width,Length]); Bounds.Add(new Rectangle(new Point(-(int)(Width * Camera.scale) / 2, -(int)(Length * Camera.scale) / 2), new Size((int)(Width * Camera.scale), (int)(Length * Camera.scale)))); Bitmap Render = new Bitmap(Width * 2, (Length + (int)(ModelData.Count * Camera.ViewAngle)) * 2); } public void RenderModel(Graphics R, int RenderResolution) { RenderResolution = Math.Max(RenderResolution, 1); Bitmap Render = new Bitmap((Width * 2 * RenderResolution), (Length + (int)(ModelData.Count * Camera.ViewAngle)) * 2 * RenderResolution); Graphics G = Graphics.FromImage(Render); G.ResetTransform(); G.TranslateTransform(Render.Width/2, Render.Height/2); G.RotateTransform(Camera.Rotation); float AngleScale = Camera.ViewAngle * RenderResolution; G.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; G.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; G.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; float[][] colorMatrixElements = { new float[] {0.0f, 0, 0, 0, 0},//R new float[] {0, 0.0f, 0, 0, 0},//G new float[] {0, 0, 0.0f, 0, 0},//B new float[] {0, 0, 0, 0.8f, 0}, new float[] {0.0f, 0.0f, 0.0f, 0f, 1}}; ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements); ImageAttributes imageAttributes = new ImageAttributes(); imageAttributes.SetColorMatrix( colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); for (int i = 0; i < ModelData.Count; i++) { G.ResetTransform(); G.TranslateTransform(Render.Width / 2 - ((i * RenderResolution / 1.25f) * (float)Math.Cos(Camera.Rotation * Math.PI / 180.0)), Render.Height / 2 - (((i / 1.25f) * (float)Math.Sin(Camera.Rotation * Math.PI / 180.0)) * AngleScale)); G.RotateTransform(Camera.Rotation); G.DrawImage(LayerImages[i], new Rectangle(-(LayerImages[i].Width / 2) * RenderResolution, -(LayerImages[i].Height / 2) * RenderResolution, LayerImages[i].Width * RenderResolution, LayerImages[i].Height * RenderResolution) , 0, 0, LayerImages[i].Width, LayerImages[i].Height, GraphicsUnit.Pixel, imageAttributes); } for (int i = 0; i < ModelData.Count; i++) { G.ResetTransform(); G.TranslateTransform(Render.Width / 2, Render.Height / 2 - (i * AngleScale)); G.RotateTransform(Camera.Rotation); G.DrawImage(LayerImages[i], new Rectangle(-(LayerImages[i].Width / 2) * RenderResolution, -(LayerImages[i].Height / 2) * RenderResolution, LayerImages[i].Width * RenderResolution, LayerImages[i].Height * RenderResolution)); } int X = Camera.LocX + Camera.Width / 2; int Y = Camera.Height / 2 + Camera.LocY; R.ResetTransform(); R.TranslateTransform(X, Y); R.RotateTransform(Camera.Rotation); R.FillRectangle(new SolidBrush(Config.BasePlateColour), Bounds[0]); int difference = Render.Height - Render.Width; R.ResetTransform(); R.TranslateTransform(X, Y); R.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; R.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; R.DrawImage(Render,( -Render.Width / 2)/ RenderResolution * Camera.scale, (-(Render.Width + difference) / 2)/ RenderResolution * Camera.scale, Render.Width/ RenderResolution * Camera.scale, Render.Height/ RenderResolution * Camera.scale); RenderedModel = Render; } public void DrawSpriteStack(Graphics G) { int X = Camera.LocX + Camera.Width / 2; int Y = Camera.Height / 2 + Camera.LocY; G.ResetTransform(); G.TranslateTransform(X, Y); G.RotateTransform(Camera.Rotation); G.FillRectangle(new SolidBrush(Config.BasePlateColour), Bounds[0]); float AngleScale = Camera.ViewAngle * Camera.scale; G.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; G.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; for (int i = 0; i < ModelData.Count; i++) { if (!Camera.EditMode || Camera.EditMode && i != Camera.SelectedLayer) { G.ResetTransform(); G.TranslateTransform(X, Y - (i * AngleScale)); G.RotateTransform(Camera.Rotation); if (Camera.SelectedLayer == i) { TextureBrush TileBrush = new TextureBrush(Resources.Background); TileBrush.ScaleTransform((1/32.0f) * Camera.scale * (Config.BackgroundTile / 2), (1 / 32.0f) * Camera.scale * (Config.BackgroundTile / 2)); G.FillRectangle(TileBrush, Bounds[Camera.SelectedLayer]); G.DrawRectangle(new Pen(Brushes.Black), Bounds[i]); G.DrawRectangle(new Pen(new SolidBrush(Camera.SelectedColor)), new Rectangle(new Point(-(int)(Width * Camera.scale) / 2 + (int)(Camera.BrushX * Camera.scale) - (int)(Math.Floor(Camera.BrushSize / 2.0) * Camera.scale), -(int)(Length * Camera.scale) / 2 + (int)(Camera.BrushY * Camera.scale) - (int)(Math.Floor(Camera.BrushSize / 2.0) * Camera.scale)), new Size((int)(Camera.BrushSize * Camera.scale), (int)(Camera.BrushSize * Camera.scale)))); } G.DrawImage(LayerImages[i], Bounds[i]); } } if (Camera.EditMode) { G.ResetTransform(); G.TranslateTransform(X, Y); TextureBrush TileBrush = new TextureBrush(Resources.OpaqueBackground); TileBrush.ScaleTransform((1 / 32.0f) * Camera.scale * (Config.BackgroundTile / 2), (1 / 32.0f) * Camera.scale * (Config.BackgroundTile / 2)); G.FillRectangle(TileBrush, Bounds[Camera.SelectedLayer]); G.DrawImage(LayerImages[Camera.SelectedLayer], Bounds[Camera.SelectedLayer]); G.DrawRectangle(new Pen(Brushes.Black), Bounds[Camera.SelectedLayer]); G.DrawRectangle(new Pen(new SolidBrush(Camera.SelectedColor)), new Rectangle(new Point(-(int)(Width * Camera.scale) / 2 + (int)(Camera.BrushX * Camera.scale) - (int)(Math.Floor(Camera.BrushSize / 2.0) * Camera.scale), -(int)(Length * Camera.scale) / 2 + (int)(Camera.BrushY * Camera.scale) - (int)(Math.Floor(Camera.BrushSize / 2.0) * Camera.scale)), new Size((int)(Camera.BrushSize * Camera.scale), (int)(Camera.BrushSize * Camera.scale)))); } } public void DrawSelectedLayerToImage() { Bitmap newImage = new Bitmap(Width, Length); for (int x = 0; x < ModelData[Camera.SelectedLayer].GetLength(0); x++) { for (int y = 0; y < ModelData[Camera.SelectedLayer].GetLength(1); y++) { if (ModelData[Camera.SelectedLayer][x, y] != null) { newImage.SetPixel(x, y, ModelData[Camera.SelectedLayer][x, y].GetColor()); } } } LayerImages[Camera.SelectedLayer] = newImage; } public void DrawLayersToImages() { for (int i = 0; i < ModelData.Count; i++) { Bitmap newImage = new Bitmap(Width, Length); for (int x = 0; x < ModelData[i].GetLength(0); x++) { for (int y = 0; y < ModelData[i].GetLength(1); y++) { if (ModelData[i][x, y] != null) { newImage.SetPixel(x, y, ModelData[i][x, y].GetColor()); } } } LayerImages[i] = newImage; } } public void SetData(int LocX, int LocY, int Layer, Voxel voxel) { if (Layer >= ModelData.Count) AddLayer(); ModelData[Layer][LocX,LocY] = voxel; } } }