diff --git a/Commands/building/CmdImageprint.cs b/Commands/building/CmdImageprint.cs index 00e0be03c..345f19b02 100644 --- a/Commands/building/CmdImageprint.cs +++ b/Commands/building/CmdImageprint.cs @@ -21,6 +21,7 @@ using System.IO; using System.Net; using System.Threading; using MCGalaxy.Drawing; +using MCGalaxy.Drawing.Ops; using MCGalaxy.Generator; namespace MCGalaxy.Commands.Building { @@ -84,19 +85,13 @@ namespace MCGalaxy.Commands.Building { bool DoImage(Player p, Vec3S32[] m, object state, byte type, byte extType) { if (m[0].X == m[1].X && m[0].Z == m[1].Z) { Player.Message(p, "No direction was selected"); return false; } - int dir; - if (Math.Abs(m[1].X - m[0].X) > Math.Abs(m[1].Z - m[0].Z)) - dir = m[1].X <= m[0].X ? 1 : 0; - else - dir = m[1].Z <= m[0].Z ? 3 : 2; - - Thread thread = new Thread(() => DoDrawImage(p, m[0], (DrawArgs)state, dir)); + Thread thread = new Thread(() => DoDrawImage(p, m, (DrawArgs)state)); thread.Name = "MCG_ImagePrint"; thread.Start(); return false; } - void DoDrawImage(Player p, Vec3S32 p0, DrawArgs dArgs, int direction) { + void DoDrawImage(Player p, Vec3S32[] m, DrawArgs dArgs) { Bitmap bmp = HeightmapGen.ReadBitmap(dArgs.name, "extra/images/", p); if (bmp == null) return; try { @@ -106,75 +101,29 @@ namespace MCGalaxy.Commands.Building { bmp.Dispose(); return; } - - byte popType = dArgs.popType; - bool layer = dArgs.layer; - if (layer) { - if (popType == 1) popType = 2; - if (popType == 3) popType = 4; + + ImagePrintDrawOp op = new ImagePrintDrawOp(); + if (Math.Abs(m[1].X - m[0].X) > Math.Abs(m[1].Z - m[0].Z)) { + op.Direction = m[1].X <= m[0].X ? 1 : 0; + } else { + op.Direction = m[1].Z <= m[0].Z ? 3 : 2; } - PaletteEntry[] palette = ImagePalette.GetPalette(popType); - PaletteEntry cur = default(PaletteEntry); - IPalette selector = null; - if (popType == 6) selector = new GrayscalePalette(); - else selector = new RgbPalette(); - selector.SetAvailableBlocks(palette); + op.Source = bmp; + op.Layer = dArgs.layer; + op.Mode = dArgs.popType; + if (op.Layer) { + if (op.Mode == 1) op.Mode = 2; + if (op.Mode == 3) op.Mode = 4; + } - Vec3S32 dx, dy, adj; - CalcMul(layer, direction, out dx, out dy, out adj); - - for (int yy = 0; yy < bmp.Height; yy++) - for (int xx = 0; xx < bmp.Width; xx++) - { - ushort X = (ushort)(p0.X + dx.X * xx + dy.X * yy); - ushort Y = (ushort)(p0.Y + dx.Y * xx + dy.Y * yy); - ushort Z = (ushort)(p0.Z + dx.Z * xx + dy.Z * yy); - - Color col = bmp.GetPixel(xx, yy); - cur.R = col.R; cur.G = col.G; cur.B = col.B; - int position; - cur.Block = selector.BestMatch(cur, out position); - if (popType == 1 || popType == 3) { - int threshold = popType == 1 ? 20 : 3; - // Back layer block - if (position <= threshold) { - X = (ushort)(X + adj.X); - Z = (ushort)(Z + adj.Z); - } - } - - if (col.A < 20) cur.Block = Block.air; - p.level.UpdateBlock(p, X, Y, Z, cur.Block, 0, true); + foreach (var b in op.Perform(m, p, p.level, null)) { + p.level.UpdateBlock(p, b.X, b.Y, b.Z, b.Block, b.ExtBlock, true); } if (dArgs.name == "tempImage_" + p.name) File.Delete("extra/images/tempImage_" + p.name + ".bmp"); - Player.Message(p, "Finished printing image using " + ImagePalette.Names[popType]); - } - - void CalcMul(bool layer, int dir, - out Vec3S32 signX, out Vec3S32 signY, out Vec3S32 adj) { - signX = default(Vec3S32); signY = default(Vec3S32); adj = default(Vec3S32); - - // Calculate back layer offset - if (dir == 0) adj.Z = 1; - if (dir == 1) adj.Z = -1; - if (dir == 2) adj.X = -1; - if (dir == 3) adj.X = 1; - - if (layer) { - if (dir == 0) { signX.X = 1; signY.Z = -1; } - if (dir == 1) { signX.X = -1; signY.Z = 1; } - if (dir == 2) { signX.Z = 1; signY.X = 1; } - if (dir == 3) { signX.Z = -1; signY.X = -1; } - } else { - signY.Y = 1; // Oriented upwards - if (dir == 0) signX.X = 1; - if (dir == 1) signX.X = -1; - if (dir == 2) signX.Z = 1; - if (dir == 3) signX.Z = -1; - } + Player.Message(p, "Finished printing image using " + ImagePalette.Names[op.Mode]); } public override void Help(Player p) { diff --git a/Drawing/Image/ImagePalette.cs b/Drawing/Image/ImagePalette.cs index 896db146f..102a8d7fe 100644 --- a/Drawing/Image/ImagePalette.cs +++ b/Drawing/Image/ImagePalette.cs @@ -25,7 +25,7 @@ namespace MCGalaxy.Drawing { null, "2-layer color", "1-layer color", "2-layer grayscale", "1-layer grayscale", "Black and White", "Mathematical grayscale" }; - public static PaletteEntry[] GetPalette(byte type) { + public static PaletteEntry[] GetPalette(int type) { if (type == 1) return Color_2; if (type == 2) return Color_1; if (type == 3) return Grayscale_2; diff --git a/Drawing/Image/ImagePrintDrawOp.cs b/Drawing/Image/ImagePrintDrawOp.cs new file mode 100644 index 000000000..f90cb3c17 --- /dev/null +++ b/Drawing/Image/ImagePrintDrawOp.cs @@ -0,0 +1,100 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using System.Collections.Generic; +using Draw = System.Drawing; +using MCGalaxy.Drawing.Brushes; + +namespace MCGalaxy.Drawing.Ops { + + public class ImagePrintDrawOp : DrawOp { + public override string Name { get { return "ImagePrint"; } } + + public override long BlocksAffected(Level lvl, Vec3S32[] marks) { + return Source.Width * Source.Height; + } + + internal Draw.Bitmap Source; + internal int Mode, Direction; + internal bool Layer; + + public override IEnumerable Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { + Vec3U16 p0 = Clamp(marks[0]); + PaletteEntry[] palette = ImagePalette.GetPalette(Mode); + PaletteEntry cur = default(PaletteEntry); + + IPalette selector = null; + if (Mode == 6) selector = new GrayscalePalette(); + else selector = new RgbPalette(); + selector.SetAvailableBlocks(palette); + + Vec3S32 dx, dy, adj; + CalcMul(Layer, Direction, out dx, out dy, out adj); + + for (int yy = 0; yy < Source.Height; yy++) + for (int xx = 0; xx < Source.Width; xx++) + { + ushort X = (ushort)(p0.X + dx.X * xx + dy.X * yy); + ushort Y = (ushort)(p0.Y + dx.Y * xx + dy.Y * yy); + ushort Z = (ushort)(p0.Z + dx.Z * xx + dy.Z * yy); + + Draw.Color col = Source.GetPixel(xx, yy); + cur.R = col.R; cur.G = col.G; cur.B = col.B; + int position; + cur.Block = selector.BestMatch(cur, out position); + if (Mode == 1 || Mode == 3) { + int threshold = Mode == 1 ? 20 : 3; + // Back layer block + if (position <= threshold) { + X = (ushort)(X + adj.X); + Z = (ushort)(Z + adj.Z); + } + } + + if (col.A < 20) cur.Block = Block.air; + yield return Place(X, Y, Z, cur.Block, 0); + } + Source = null; + yield break; + } + + void CalcMul(bool layer, int dir, + out Vec3S32 signX, out Vec3S32 signY, out Vec3S32 adj) { + signX = default(Vec3S32); signY = default(Vec3S32); adj = default(Vec3S32); + + // Calculate back layer offset + if (dir == 0) adj.Z = 1; + if (dir == 1) adj.Z = -1; + if (dir == 2) adj.X = -1; + if (dir == 3) adj.X = 1; + + if (layer) { + if (dir == 0) { signX.X = 1; signY.Z = -1; } + if (dir == 1) { signX.X = -1; signY.Z = 1; } + if (dir == 2) { signX.Z = 1; signY.X = 1; } + if (dir == 3) { signX.Z = -1; signY.X = -1; } + } else { + signY.Y = 1; // Oriented upwards + if (dir == 0) signX.X = 1; + if (dir == 1) signX.X = -1; + if (dir == 2) signX.Z = 1; + if (dir == 3) signX.Z = -1; + } + } + } +} diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index f1bf5dce0..aefe86053 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -452,6 +452,7 @@ +