Last active
January 12, 2016 23:35
-
-
Save notanimposter/9f8f87b2c6eeaa92ec8e to your computer and use it in GitHub Desktop.
SE drawing library (version 2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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