Rewrite /imageprint as a draw operation.

This commit is contained in:
UnknownShadow200 2016-08-30 19:33:04 +10:00
parent 4d73d60e1c
commit b667b38f1a
4 changed files with 121 additions and 71 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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<DrawOpBlock> 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;
}
}
}
}

View File

@ -452,6 +452,7 @@
<Compile Include="Drawing\DrawOps\WriteDrawOp.cs" />
<Compile Include="Drawing\Flip.cs" />
<Compile Include="Drawing\Image\ImagePalette.cs" />
<Compile Include="Drawing\Image\ImagePrintDrawOp.cs" />
<Compile Include="Drawing\Image\IPalette.cs" />
<Compile Include="Drawing\Image\PixelGetter.cs" />
<Compile Include="Drawing\TransformFactories\SimpleTransforms.cs" />