mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-23 12:42:22 -04:00
Rewrite /imageprint as a draw operation.
This commit is contained in:
parent
4d73d60e1c
commit
b667b38f1a
@ -21,6 +21,7 @@ using System.IO;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using MCGalaxy.Drawing;
|
using MCGalaxy.Drawing;
|
||||||
|
using MCGalaxy.Drawing.Ops;
|
||||||
using MCGalaxy.Generator;
|
using MCGalaxy.Generator;
|
||||||
|
|
||||||
namespace MCGalaxy.Commands.Building {
|
namespace MCGalaxy.Commands.Building {
|
||||||
@ -84,19 +85,13 @@ namespace MCGalaxy.Commands.Building {
|
|||||||
bool DoImage(Player p, Vec3S32[] m, object state, byte type, byte extType) {
|
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; }
|
if (m[0].X == m[1].X && m[0].Z == m[1].Z) { Player.Message(p, "No direction was selected"); return false; }
|
||||||
|
|
||||||
int dir;
|
Thread thread = new Thread(() => DoDrawImage(p, m, (DrawArgs)state));
|
||||||
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.Name = "MCG_ImagePrint";
|
thread.Name = "MCG_ImagePrint";
|
||||||
thread.Start();
|
thread.Start();
|
||||||
return false;
|
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);
|
Bitmap bmp = HeightmapGen.ReadBitmap(dArgs.name, "extra/images/", p);
|
||||||
if (bmp == null) return;
|
if (bmp == null) return;
|
||||||
try {
|
try {
|
||||||
@ -107,74 +102,28 @@ namespace MCGalaxy.Commands.Building {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte popType = dArgs.popType;
|
ImagePrintDrawOp op = new ImagePrintDrawOp();
|
||||||
bool layer = dArgs.layer;
|
if (Math.Abs(m[1].X - m[0].X) > Math.Abs(m[1].Z - m[0].Z)) {
|
||||||
if (layer) {
|
op.Direction = m[1].X <= m[0].X ? 1 : 0;
|
||||||
if (popType == 1) popType = 2;
|
} else {
|
||||||
if (popType == 3) popType = 4;
|
op.Direction = m[1].Z <= m[0].Z ? 3 : 2;
|
||||||
}
|
}
|
||||||
PaletteEntry[] palette = ImagePalette.GetPalette(popType);
|
|
||||||
PaletteEntry cur = default(PaletteEntry);
|
|
||||||
|
|
||||||
IPalette selector = null;
|
op.Source = bmp;
|
||||||
if (popType == 6) selector = new GrayscalePalette();
|
op.Layer = dArgs.layer;
|
||||||
else selector = new RgbPalette();
|
op.Mode = dArgs.popType;
|
||||||
selector.SetAvailableBlocks(palette);
|
if (op.Layer) {
|
||||||
|
if (op.Mode == 1) op.Mode = 2;
|
||||||
|
if (op.Mode == 3) op.Mode = 4;
|
||||||
|
}
|
||||||
|
|
||||||
Vec3S32 dx, dy, adj;
|
foreach (var b in op.Perform(m, p, p.level, null)) {
|
||||||
CalcMul(layer, direction, out dx, out dy, out adj);
|
p.level.UpdateBlock(p, b.X, b.Y, b.Z, b.Block, b.ExtBlock, true);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dArgs.name == "tempImage_" + p.name)
|
if (dArgs.name == "tempImage_" + p.name)
|
||||||
File.Delete("extra/images/tempImage_" + p.name + ".bmp");
|
File.Delete("extra/images/tempImage_" + p.name + ".bmp");
|
||||||
Player.Message(p, "Finished printing image using " + ImagePalette.Names[popType]);
|
Player.Message(p, "Finished printing image using " + ImagePalette.Names[op.Mode]);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Help(Player p) {
|
public override void Help(Player p) {
|
||||||
|
@ -25,7 +25,7 @@ namespace MCGalaxy.Drawing {
|
|||||||
null, "2-layer color", "1-layer color", "2-layer grayscale",
|
null, "2-layer color", "1-layer color", "2-layer grayscale",
|
||||||
"1-layer grayscale", "Black and White", "Mathematical 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 == 1) return Color_2;
|
||||||
if (type == 2) return Color_1;
|
if (type == 2) return Color_1;
|
||||||
if (type == 3) return Grayscale_2;
|
if (type == 3) return Grayscale_2;
|
||||||
|
100
Drawing/Image/ImagePrintDrawOp.cs
Normal file
100
Drawing/Image/ImagePrintDrawOp.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -452,6 +452,7 @@
|
|||||||
<Compile Include="Drawing\DrawOps\WriteDrawOp.cs" />
|
<Compile Include="Drawing\DrawOps\WriteDrawOp.cs" />
|
||||||
<Compile Include="Drawing\Flip.cs" />
|
<Compile Include="Drawing\Flip.cs" />
|
||||||
<Compile Include="Drawing\Image\ImagePalette.cs" />
|
<Compile Include="Drawing\Image\ImagePalette.cs" />
|
||||||
|
<Compile Include="Drawing\Image\ImagePrintDrawOp.cs" />
|
||||||
<Compile Include="Drawing\Image\IPalette.cs" />
|
<Compile Include="Drawing\Image\IPalette.cs" />
|
||||||
<Compile Include="Drawing\Image\PixelGetter.cs" />
|
<Compile Include="Drawing\Image\PixelGetter.cs" />
|
||||||
<Compile Include="Drawing\TransformFactories\SimpleTransforms.cs" />
|
<Compile Include="Drawing\TransformFactories\SimpleTransforms.cs" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user