SE drawing library (version 2)
public class ColorUtils { | |
private static double oo64 = 1.0/64.0; | |
private static double[][] map = new double[][] { | |
new double[] { 0*oo64, 48*oo64, 12*oo64, 60*oo64, 3*oo64, 51*oo64, 15*oo64, 63*oo64}, | |
new double[] {32*oo64, 16*oo64, 44*oo64, 28*oo64, 35*oo64, 19*oo64, 47*oo64, 31*oo64}, | |
new double[] { 8*oo64, 56*oo64, 4*oo64, 52*oo64, 11*oo64, 59*oo64, 7*oo64, 55*oo64}, | |
new double[] {40*oo64, 24*oo64, 36*oo64, 20*oo64, 43*oo64, 27*oo64, 39*oo64, 23*oo64}, | |
new double[] { 2*oo64, 50*oo64, 14*oo64, 62*oo64, 1*oo64, 49*oo64, 13*oo64, 61*oo64}, | |
new double[] {34*oo64, 18*oo64, 46*oo64, 30*oo64, 33*oo64, 17*oo64, 45*oo64, 29*oo64}, | |
new double[] {10*oo64, 58*oo64, 6*oo64, 54*oo64, 9*oo64, 57*oo64, 5*oo64, 53*oo64}, | |
new double[] {42*oo64, 26*oo64, 38*oo64, 22*oo64, 41*oo64, 25*oo64, 37*oo64, 21*oo64} | |
}; | |
private static int zero = 0; //because space engineers is stupid | |
private static int[][] palette = new int[][] { | |
new int[] { 255+zero, 255+zero, zero}, | |
new int[] { 255+zero, zero, zero}, | |
new int[] { zero, zero, 255+zero}, | |
new int[] { zero, 255+zero, zero}, | |
new int[] { 255+zero, 255+zero, 255+zero}, | |
new int[] { 97+zero, 97+zero, 97+zero}, | |
new int[] { zero, zero, zero} | |
}; | |
private static string[] colorStrings = new string[] { | |
"\uE004", //oh but it works fine with *strings* -_- | |
"\uE003", | |
"\uE002", | |
"\uE001", | |
"\uE007\u0458", | |
"\uE00D", | |
"\u2014\u0060" | |
}; | |
//magic numbers yay | |
private static double dontHateBlueAsMuch = 1.5; | |
private static double howMuchDoWeHateGrey = 0.01; //not ideal but it seems to work okay | |
private static double compareColors(int r1, int g1, int b1, int r2, int g2, int b2) { | |
double luma1 = (r1*299 + g1*587 + b1*114) / (255.0*1000); | |
double luma2 = (r2*299 + g2*587 + b2*114) / (255.0*1000); | |
double dl = luma1-luma2; | |
double dr = (r1-r2)/255.0, dg = (g1-g2)/255.0, db = (b1-b2)/255.0; | |
return (dr*dr*0.299 + dg*dg*0.587 + db*db*0.114*dontHateBlueAsMuch)*0.75 + dl*dl; | |
} | |
private static double calcError(int[] color, int r0, int g0, int b0, int[] color1, int[] color2, double ratio) { | |
return compareColors(color[0], color[1], color[2], r0,g0,b0) + | |
compareColors(color1[0], color1[1], color1[2], color2[0], color2[1], color2[2]) * 0.1 * (Math.Abs(ratio-0.5)+0.5) + | |
((color1[0]==color1[1] && color1[1]==color1[2]) || (color2[0]==color2[1] && color2[1]==color2[2]) ? howMuchDoWeHateGrey : 0); | |
} | |
public static int[] createMix(int[] rgb) { | |
int r = rgb[0]; | |
int g = rgb[1]; | |
int b = rgb[2]; | |
int[] result = new int[] { zero, zero, 1+zero, 2+zero }; | |
double minPenalty = 99999999999999999; | |
for (int i = 0; i < palette.Length; i++) { | |
for (int j = i; j < palette.Length; j++) { | |
int[] color1 = palette[i]; | |
int[] color2 = palette[j]; | |
int r1 = color1[0]; | |
int g1 = color1[1]; | |
int b1 = color1[2]; | |
int r2 = color2[0]; | |
int g2 = color2[1]; | |
int b2 = color2[2]; | |
int ratio = 32; | |
if (r1 != r2 || g1 != g2 || b1 != b2) | |
ratio = ((r2 != r1 ? 299*64 * (int)(r - r1) / (int)(r2-r1) : 0) + | |
(g2 != g1 ? 587*64 * (int)(g - g1) / (int)(g2-g1) : 0) + | |
(b1 != b2 ? (int) (114*dontHateBlueAsMuch*64) * (int)(b - b1) / (int)(b2-b1) : 0))/ | |
((r2 != r1 ? 299 : 0)+ | |
(g2 != g1 ? 587 : 0)+ | |
(b2 != b1 ? (int) (114*dontHateBlueAsMuch) : 0)); | |
if (ratio < 0) | |
ratio = 0; | |
else if (ratio > 63) | |
ratio = 63; | |
int r0 = r1 + ratio * (int)(r2-r1) / 64; | |
int g0 = g1 + ratio * (int)(g2-g1) / 64; | |
int b0 = b1 + ratio * (int)(b2-b1) / 64; | |
double penalty = calcError( | |
rgb, r0,g0,b0, color1, color2, | |
(double)ratio/64.0); | |
if (penalty < minPenalty) { | |
minPenalty = penalty; | |
result[0] = i; | |
result[1] = j; | |
result[2] = ratio; | |
result[3] = 64; | |
} | |
} | |
} | |
return result; | |
} | |
public static string[][] genDitherPattern(int[] mix) { | |
string[][] dithered = new string[8][]; | |
for (int x = 0; x < 8; x++) { | |
dithered[x] = new string[8]; | |
for (int y = 0; y < 8; y++) { | |
double mapValue = map[y&7][x&7]; | |
double ratio = ((double) mix[2])/((double) mix[3]); | |
dithered[x][y] = colorStrings[mix[ mapValue < ratio ? 1 : 0 ]]; | |
} | |
} | |
return dithered; | |
} | |
} | |
public class Ascii { | |
public static readonly int width = 3; | |
public static readonly int height = 5; | |
private static int offset = 0x21; | |
//debigulate this later | |
private static string[] glyphs = new string[] { | |
" @ " + | |
" @ " + | |
" @ " + | |
" " + | |
" @ ", | |
"@ @" + | |
"@ @" + | |
" " + | |
" " + | |
" ", | |
"@ @" + | |
"@@@" + | |
"@ @" + | |
"@@@" + | |
"@ @", | |
" @@" + | |
"@@ " + | |
" @@" + | |
"@@ " + | |
" @ ", | |
"@ " + | |
" @" + | |
" @ " + | |
"@ " + | |
" @", | |
" @ " + | |
"@ @" + | |
" @ " + | |
"@ @" + | |
" @@", | |
" @ " + | |
" @ " + | |
" " + | |
" " + | |
" ", | |
" @" + | |
" @ " + | |
" @ " + | |
" @ " + | |
" @", | |
"@ " + | |
" @ " + | |
" @ " + | |
" @ " + | |
"@ ", | |
"@ @" + | |
" @ " + | |
"@ @" + | |
" " + | |
" ", | |
" " + | |
" @ " + | |
"@@@" + | |
" @ " + | |
" ", | |
" " + | |
" " + | |
" " + | |
" @ " + | |
"@ ", | |
" " + | |
" " + | |
"@@@" + | |
" " + | |
" ", | |
" " + | |
" " + | |
" " + | |
" " + | |
" @ ", | |
" " + | |
" @" + | |
" @ " + | |
"@ " + | |
" ", | |
"@@@" + | |
"@ @" + | |
"@ @" + | |
"@ @" + | |
"@@@", | |
" @ " + | |
"@@ " + | |
" @ " + | |
" @ " + | |
"@@@", | |
"@@ " + | |
" @" + | |
" @ " + | |
"@ " + | |
"@@@", | |
"@@@" + | |
" @" + | |
" @ " + | |
" @" + | |
"@@ ", | |
"@ @" + | |
"@ @" + | |
"@@@" + | |
" @" + | |
" @", | |
"@@@" + | |
"@ " + | |
"@@ " + | |
" @" + | |
"@@ ", | |
" @ " + | |
"@ " + | |
"@@ " + | |
"@ @" + | |
" @ ", | |
"@@@" + | |
" @" + | |
" @ " + | |
"@@@" + | |
" @ ", | |
" @ " + | |
"@ @" + | |
" @ " + | |
"@ @" + | |
" @ ", | |
" @ " + | |
"@ @" + | |
" @@" + | |
" @" + | |
" @ ", | |
" " + | |
" @ " + | |
" " + | |
" @ " + | |
" ", | |
" " + | |
" @ " + | |
" " + | |
" @ " + | |
"@ ", | |
" @" + | |
" @ " + | |
"@ " + | |
" @ " + | |
" @", | |
" " + | |
"@@@" + | |
" " + | |
"@@@" + | |
" ", | |
"@ " + | |
" @ " + | |
" @" + | |
" @ " + | |
"@ ", | |
"@@ " + | |
" @" + | |
" @ " + | |
" " + | |
" @ ", | |
" @@" + | |
"@ @" + | |
"@ @" + | |
"@ " + | |
" @@", | |
" @ " + | |
"@ @" + | |
"@@@" + | |
"@ @" + | |
"@ @", | |
"@@ " + | |
"@ @" + | |
"@@ " + | |
"@ @" + | |
"@@ ", | |
" @@" + | |
"@ " + | |
"@ " + | |
"@ " + | |
" @@", | |
"@@ " + | |
"@ @" + | |
"@ @" + | |
"@ @" + | |
"@@ ", | |
"@@@" + | |
"@ " + | |
"@@ " + | |
"@ " + | |
"@@@", | |
"@@@" + | |
"@ " + | |
"@@ " + | |
"@ " + | |
"@ ", | |
" @@" + | |
"@ " + | |
"@@@" + | |
"@ @" + | |
" @@", | |
"@ @" + | |
"@ @" + | |
"@@@" + | |
"@ @" + | |
"@ @", | |
"@@@" + | |
" @ " + | |
" @ " + | |
" @ " + | |
"@@@", | |
" @@" + | |
" @" + | |
" @" + | |
"@ @" + | |
" @ ", | |
"@ @" + | |
"@ @" + | |
"@@ " + | |
"@ @" + | |
"@ @", | |
"@ " + | |
"@ " + | |
"@ " + | |
"@ " + | |
"@@@", | |
"@ @" + | |
"@@@" + | |
"@@@" + | |
"@ @" + | |
"@ @", | |
"@@ " + | |
"@ @" + | |
"@ @" + | |
"@ @" + | |
"@ @", | |
" @ " + | |
"@ @" + | |
"@ @" + | |
"@ @" + | |
" @ ", | |
"@@ " + | |
"@ @" + | |
"@@ " + | |
"@ " + | |
"@ ", | |
" @ " + | |
"@ @" + | |
"@ @" + | |
"@@@" + | |
" @@", | |
"@@ " + | |
"@ @" + | |
"@@ " + | |
"@ @" + | |
"@ @", | |
" @@" + | |
"@ " + | |
" @ " + | |
" @" + | |
"@@ ", | |
"@@@" + | |
" @ " + | |
" @ " + | |
" @ " + | |
" @ ", | |
"@ @" + | |
"@ @" + | |
"@ @" + | |
"@ @" + | |
" @@", | |
"@ @" + | |
"@ @" + | |
"@ @" + | |
" @ " + | |
" @ ", | |
"@ @" + | |
"@ @" + | |
"@@@" + | |
"@@@" + | |
"@ @", | |
"@ @" + | |
"@ @" + | |
" @ " + | |
"@ @" + | |
"@ @", | |
"@ @" + | |
"@ @" + | |
" @ " + | |
" @ " + | |
" @ ", | |
"@@@" + | |
" @" + | |
" @ " + | |
"@ " + | |
"@@@", | |
" @@" + | |
" @ " + | |
" @ " + | |
" @ " + | |
" @@", | |
" " + | |
"@ " + | |
" @ " + | |
" @" + | |
" ", | |
"@@ " + | |
" @ " + | |
" @ " + | |
" @ " + | |
"@@ ", | |
" @ " + | |
"@ @" + | |
" " + | |
" " + | |
" ", | |
" " + | |
" " + | |
" " + | |
" " + | |
"@@@", | |
"@ " + | |
" @ " + | |
" " + | |
" " + | |
" ", | |
" " + | |
" " + | |
" @@" + | |
"@ @" + | |
"@@@", | |
"@ " + | |
"@ " + | |
"@@ " + | |
"@ @" + | |
"@@ ", | |
" " + | |
" " + | |
" @@" + | |
"@ " + | |
" @@", | |
" @" + | |
" @" + | |
" @@" + | |
"@ @" + | |
" @@", | |
" " + | |
" @ " + | |
"@ @" + | |
"@@ " + | |
" @@", | |
" @@" + | |
"@ " + | |
"@@ " + | |
"@ " + | |
"@ ", | |
" " + | |
" @@" + | |
"@ @" + | |
" @@" + | |
"@@ ", | |
"@ " + | |
"@ " + | |
"@@ " + | |
"@ @" + | |
"@ @", | |
" @ " + | |
" " + | |
"@@ " + | |
" @ " + | |
" @@", | |
" @" + | |
" " + | |
" @@" + | |
" @" + | |
"@@ ", | |
"@ " + | |
"@ " + | |
"@ @" + | |
"@@ " + | |
"@ @", | |
"@@ " + | |
" @ " + | |
" @ " + | |
" @ " + | |
" @", | |
" " + | |
" " + | |
"@@@" + | |
"@@@" + | |
"@ @", | |
" " + | |
" " + | |
"@@ " + | |
"@ @" + | |
"@ @", | |
" " + | |
" " + | |
" @ " + | |
"@ @" + | |
" @ ", | |
" " + | |
" @ " + | |
"@ @" + | |
"@@ " + | |
"@ ", | |
" " + | |
" @ " + | |
"@ @" + | |
" @@" + | |
" @", | |
" " + | |
" " + | |
" @@" + | |
"@ " + | |
"@ ", | |
" " + | |
" @@" + | |
"@@ " + | |
" @" + | |
"@@ ", | |
"@ " + | |
"@ " + | |
"@@ " + | |
"@ " + | |
" @@", | |
" " + | |
" " + | |
"@ @" + | |
"@ @" + | |
" @@", | |
" " + | |
" " + | |
"@ @" + | |
"@ @" + | |
" @ ", | |
" " + | |
" " + | |
"@ @" + | |
"@@@" + | |
"@@@", | |
" " + | |
" " + | |
"@ @" + | |
" @ " + | |
"@ @", | |
" " + | |
"@ @" + | |
" @@" + | |
" @" + | |
"@@ ", | |
" " + | |
"@@@" + | |
" @" + | |
" @ " + | |
"@@@", | |
" @" + | |
" @ " + | |
"@@ " + | |
" @ " + | |
" @", | |
" @ " + | |
" @ " + | |
" " + | |
" @ " + | |
" @ ", | |
"@ " + | |
" @ " + | |
" @@" + | |
" @ " + | |
"@ ", | |
" " + | |
" @@" + | |
"@@ " + | |
" " + | |
" " | |
}; | |
public static string getGlyph(char code) { | |
return glyphs[code-offset]; | |
} | |
} | |
public class Graphics { | |
public readonly int width; | |
public readonly int height; | |
private IMyTextPanel console; | |
private string[] screen; | |
public int[] bgc; | |
public int[] fgc; | |
private int[] fgMix; | |
private int[] bgMix; | |
private string[][] fgDither; | |
private string[][] bgDither; | |
public Graphics(int w, int h, IMyTextPanel c) { | |
width = w; | |
height = h; | |
console = c; | |
screen = new string[height*width]; | |
setFG(255,255,255); | |
setBG(0,0,0); | |
} | |
public void setFG(int r, int g, int b) { | |
fgc = new int[3]; | |
fgc[0] = r; | |
fgc[1] = g; | |
fgc[2] = b; | |
fgMix = ColorUtils.createMix(fgc); | |
fgDither = ColorUtils.genDitherPattern(fgMix); | |
} | |
public void setBG(int r, int g, int b) { | |
bgc = new int[3]; | |
bgc[0] = r; | |
bgc[1] = g; | |
bgc[2] = b; | |
bgMix = ColorUtils.createMix(bgc); | |
bgDither = ColorUtils.genDitherPattern(bgMix); | |
} | |
public void paint() { | |
string[] s = new string[width*height+height-1]; | |
int o = 0; | |
for (int i=0; i < width*height; i++) { | |
int x = i%width; | |
if (x == 0 && i > 0) { | |
s[o++] = "\n"; | |
} | |
s[o++] = screen[i]; | |
} | |
console.WritePublicText(string.Concat(s)); | |
console.ShowTextureOnScreen(); | |
console.ShowPublicTextOnScreen(); | |
} | |
public void clear() { | |
for (int i = 0; i < width*height; i++) { | |
screen[i] = bgDither[(i%width)&7][(i/width)&7]; | |
} | |
} | |
public void pixel(int x, int y) { | |
if (x > 0 && x < width && y > 0 && y < height) { | |
screen[width*y + x] = fgDither[x&7][y&7]; | |
} | |
} | |
public void line(int x0, int y0, int x1, int y1) { | |
if (x0 == x1) { | |
for (int y = y0; y <= y1; y++) { | |
pixel(x0,y); | |
} | |
} else if (y0 == y1) { | |
for (int x = x0; x <= x1; x++) { | |
pixel(x,y0); | |
} | |
} else { //add a case for 45 degree lines at some point | |
double dy = y1 - y0; | |
double err = 0; | |
double slope = Math.Abs(dy / (x1 - x0)); | |
int ndy = Math.Sign(dy); | |
int y = y0; | |
for (int x = x0; x <= x1; x++) { | |
pixel(x,y); | |
err = err + slope; | |
while (err >= 0.5) { | |
pixel(x,y); | |
y += ndy; | |
err--; | |
} | |
} | |
} | |
} | |
public void rect(string m, int xb, int yb, int w, int h) { | |
if (m == "line") { | |
line(xb, yb, xb, yb+h-1); | |
line(xb, yb, xb+w-1, yb); | |
line(xb+w-1, yb, xb+w-1, yb+h-1); | |
line(xb, yb+h-1, xb+w-1, yb+h-1); | |
} else if (m == "fill") { | |
for (int x = xb; x < xb+w; x++) { | |
for (int y = yb; y < yb+h; y++) { | |
pixel(x,y); | |
} | |
} | |
} | |
} | |
public void ellipse(string m, int cx, int cy, int rx, int ry) { | |
int rx2 = rx*rx; | |
int ry2 = ry*ry; | |
if (m == "fill") { | |
int rxsys = rx2*ry2; | |
pixel(cx, cy); | |
for (int i=1; i < rx*ry; i++) { | |
int x = i % rx; | |
int y = i / rx; | |
if (ry2*x*x+rx2*y*y <= rxsys) { | |
pixel(cx+x, cy+y); | |
pixel(cx-x, cy-y); | |
//if (x && y) { //unnecessary (prevents overdrawing pixels) | |
pixel(cx+x, cy-y); | |
pixel(cx-x, cy+y); | |
//} | |
} | |
} | |
} else if (m == "line") { | |
int frx2 = 4 * rx2; | |
int fry2 = 4 * ry2; | |
int s = 2*ry2+rx2*(1-2*ry); | |
int y = ry; | |
for (int x = 0; ry2*x <= rx2*y; x++) { | |
pixel(cx + x, cy + y); | |
pixel(cx - x, cy + y); | |
pixel(cx + x, cy - y); | |
pixel(cx - x, cy - y); | |
if (s >= 0) { | |
s += frx2 * (1 - y); | |
y--; | |
} | |
s += ry2 * ((4 * x) + 6); | |
} | |
y = 0; | |
s = 2*rx2+ry2*(1-2*rx); | |
for (int x = rx; rx2*y <= ry2*x; y++) { | |
pixel(cx + x, cy + y); | |
pixel(cx - x, cy + y); | |
pixel(cx + x, cy - y); | |
pixel(cx - x, cy - y); | |
if (s >= 0) { | |
s += fry2 * (1 - x); | |
x--; | |
} | |
s += rx2 * ((4 * y) + 6); | |
} | |
} | |
} | |
public void circle(string m, int cx, int cy, int r) { | |
if (m == "fill") { | |
int rr = r*r; | |
pixel(cx, cy); | |
for (int i=1; i < r*r; i++) { | |
int x = i % r; | |
int y = i / r; | |
if (x*x+y*y < rr) { | |
pixel(cx+x, cy+y); | |
pixel(cx-x, cy-y); | |
if (x>0 && y>0) { | |
pixel(cx+x, cy-y); | |
pixel(cx-x, cy+y); | |
} | |
} | |
} | |
} else if (m == "line") { | |
int x = r; | |
int y = 0; | |
int do2 = 1 - x; | |
while (y <= x) { | |
pixel(cx+x, cy+y); | |
pixel(cx+y, cy+x); | |
pixel(cx-x, cy+y); | |
pixel(cx-y, cy+x); | |
pixel(cx-x, cy-y); | |
pixel(cx-y, cy-x); | |
pixel(cx+x, cy-y); | |
pixel(cx+y, cy-x); | |
y++; | |
if (do2 <= 0) { | |
do2 += 2 * y + 1; | |
} else { | |
do2 += 2 * (y - --x) + 1; | |
} | |
} | |
} | |
} | |
public void print(int x, int y, string text) { | |
int x1 = x; | |
int y1 = y; | |
for (int i = 0; i < text.Length; i++) { | |
switch(text[i]) { | |
case '\n': | |
y1 += 6; | |
x1 = x; | |
break; | |
case ' ': | |
x1 += 4; | |
break; | |
default: | |
string glyph = Ascii.getGlyph(text[i]); | |
for (int j = 0; j < 15; j++) { | |
if (glyph[j] == '@') { | |
pixel(x1+j%3, y1-4+j/3); | |
} | |
} | |
x1 += 4; | |
break; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment