mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-22 03:55:18 -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.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) {
|
||||
|
@ -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;
|
||||
|
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\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" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user