1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-01-11 18:00:34 +00:00

texture editing improved

This commit is contained in:
Zeno Rogue 2017-12-18 23:42:08 +01:00
parent c003dda811
commit e5c22834fe
3 changed files with 111 additions and 33 deletions

View File

@ -656,7 +656,7 @@ inline void popScreenAll() { while(size(screens)>1) popScreen(); }
extern transmatrix View; // current rotation, relative to viewctr extern transmatrix View; // current rotation, relative to viewctr
extern transmatrix cwtV; // player-relative view extern transmatrix cwtV; // player-relative view
extern cell *mouseover, *mouseover2; extern cell *mouseover, *mouseover2, *lmouseover;
extern string mouseovers; extern string mouseovers;
extern struct SDL_Surface *s; extern struct SDL_Surface *s;
@ -2377,6 +2377,9 @@ namespace texture {
}; };
extern eTextureState tstate; extern eTextureState tstate;
extern unsigned paint_color;
extern ld penwidth;
extern transmatrix itt;
void showMenu(); void showMenu();

View File

@ -933,7 +933,7 @@ namespace mapeditor {
break; break;
} }
usershape *us =usershapes[drawcellShapeGroup()][drawcellShapeID()]; us =usershapes[drawcellShapeGroup()][drawcellShapeID()];
} }
int fs = min(vid.fsize + 5, vid.yres/28); int fs = min(vid.fsize + 5, vid.yres/28);
@ -970,6 +970,8 @@ namespace mapeditor {
} }
else if(texture::tstate == texture::tsActive) { else if(texture::tstate == texture::tsActive) {
displayButton(8, 8+fs*7, XLAT("p = color"), 'p', 0);
displayButton(8, 8+fs*8, XLAT("w = pen size: %1", fts4(texture::penwidth)), 'w', 0);
} }
else { else {
displaymm('n', 8, 8+fs*5, 2, vid.fsize, XLAT("'n' to start"), 0); displaymm('n', 8, 8+fs*5, 2, vid.fsize, XLAT("'n' to start"), 0);
@ -1286,8 +1288,8 @@ namespace mapeditor {
hyperpoint mh = inverse(drawtrans) * mouseh; hyperpoint mh = inverse(drawtrans) * mouseh;
if(uni == 'g') coldcenter = ccenter, ccenter = mh; if(uni == 'g') coldcenter = ccenter, ccenter = mh;
if(uni == 'z') vid.scale *= 2; if(uni == 'z') vid.scale *= 2, texture::itt = xyscale(texture::itt, .5);
if(uni == 'o') vid.scale /= 2; if(uni == 'o') vid.scale /= 2, texture::itt = xyscale(texture::itt, 2);
if(uni == ' ' && cheater) { if(uni == ' ' && cheater) {
popScreen(); popScreen();
@ -1320,9 +1322,33 @@ namespace mapeditor {
if(texture::tstate == texture::tsActive) { if(texture::tstate == texture::tsActive) {
if(uni == '-') { if(uni == '-') {
texture::drawPixel(mouseover, mouseh, colortouse); texture::drawPixel(mouseover, mouseh, (texture::paint_color >> 8) | ((texture::paint_color & 0xFF) << 24));
holdmouse = true; holdmouse = true;
} }
if(uni == 'p') {
static unsigned texture_colors[] = {
11,
0x000000FF,
0xFFFFFFFF,
0xFF0000FF,
0xFFFF00FF,
0x00FF00FF,
0x00FFFFFF,
0x0000FFFF,
0xFF00FFFF,
0xC0C0C0FF,
0x808080FF,
0x404040FF,
0x804000FF
};
dialog::openColorDialog(colortouse, texture_colors);
dialog::openColorDialog(texture::paint_color);
colorkey = true;
}
if(uni == 'w')
dialog::editNumber(texture::penwidth, 0, 0.1, 0.005, 0.02, XLAT("pen width"), XLAT("pen width"));
} }
else { else {
@ -1430,18 +1456,23 @@ namespace mapeditor {
} }
} }
if(cmode & sm::DRAW) { if(cmode & sm::DRAW) if(!holdmouse) {
if(texture::tstate == texture::tsActive && mouseover && !mouseout()) { if(texture::tstate == texture::tsActive && lmouseover && !mouseout()) {
auto sio = patterns::getpatterninfo0(mouseover); auto sio = patterns::getpatterninfo0(lmouseover);
auto sih = patterns::getpatterninfo0(c); auto sih = patterns::getpatterninfo0(c);
if(sio.id == sih.id) { if(sio.id == sih.id) {
if(c == mouseover) textrans = V * applyPatterndir(mouseover, sio); if(c == lmouseover)
hyperpoint mh = inverse(mapeditor::textrans) * mouseh; textrans = inverse(V * applyPatterndir(mouseover, sio));
transmatrix mh = textrans * rgpushxto0(mouseh);
for(int i=0; i<c->type; i += sih.symmetries) { for(int i=0; i<c->type; i += sih.symmetries) {
hyperpoint P2 = V * spin(2*M_PI*i/c->type) * mh; transmatrix M2 = V * spin(2*M_PI*i/c->type) * mh;
queuechr(P2, 10, 'x', 0xFF00FF); array<hyperpoint, 6> pts;
for(int j=0; j<6; j++)
pts[j] = M2 * tC0(spin(M_PI*j/3) * xpush(texture::penwidth));
for(int j=0; j<6; j++)
queueline(pts[j], pts[(j+1)%6], texture::paint_color, 0, PPR_LINE);
} }
} }
} }

View File

@ -31,6 +31,8 @@ SDL_Surface *convertSurface(SDL_Surface* s) {
int twidth = 2048; int twidth = 2048;
unsigned paint_color = 0x000000FF;
vector<int> expanded_data; vector<int> expanded_data;
string texturename = "hyperrogue-texture.png"; string texturename = "hyperrogue-texture.png";
@ -275,7 +277,8 @@ void perform_mapping() {
if(gsplits > 4) gsplits = 4; if(gsplits > 4) gsplits = 4;
using namespace patterns; using namespace patterns;
texture_map.clear(); texture_map.clear();
for(auto p: gmatrix) {
for(auto& p: gmatrix) {
cell *c = p.first; cell *c = p.first;
auto si = getpatterninfo0(c); auto si = getpatterninfo0(c);
bool replace = false; bool replace = false;
@ -292,10 +295,22 @@ void perform_mapping() {
mapTexture(c, mi, si, p.second); mapTexture(c, mi, si, p.second);
mi.texture_id = textureid; mi.texture_id = textureid;
} }
texture_map[si.id].matrices.push_back(p.second);
} }
models.clear(); models.clear();
for(auto& t: texture_map) models.insert(t.second.c); for(auto& t: texture_map) models.insert(t.second.c);
for(auto& p: gmatrix) {
cell *c = p.first;
bool nearmodel = models.count(c);
forCellEx(c2, c)
if(models.count(c2))
nearmodel = true;
if(nearmodel) {
auto si = getpatterninfo0(c);
texture_map[si.id].matrices.push_back(p.second * applyPatterndir(c, si));
}
}
} }
int forgeArgs() { int forgeArgs() {
@ -739,7 +754,6 @@ void showMenu() {
if(whitetexture() && loadTextureGL()) { if(whitetexture() && loadTextureGL()) {
tstate = tstate_max = tsActive; tstate = tstate_max = tsActive;
perform_mapping(); perform_mapping();
mapeditor::colortouse = 0xFFFF00FF;
mapeditor::initdraw(cwt.c); mapeditor::initdraw(cwt.c);
pushScreen(mapeditor::showDrawEditor); pushScreen(mapeditor::showDrawEditor);
} }
@ -788,13 +802,15 @@ void showMenu() {
int lastupdate; int lastupdate;
void update() { void update() {
if(lastupdate && ticks > lastupdate + 100) { if(lastupdate && ticks > lastupdate + 50) {
loadTextureGL(); loadTextureGL();
lastupdate = 0; lastupdate = 0;
} }
} }
pair<int,int> ptc(hyperpoint h) { typedef pair<int,int> point;
point ptc(hyperpoint h) {
hyperpoint inmodel; hyperpoint inmodel;
applymodel(h, inmodel); applymodel(h, inmodel);
inmodel = itt * inmodel; inmodel = itt * inmodel;
@ -805,42 +821,72 @@ pair<int,int> ptc(hyperpoint h) {
return make_pair(x,y); return make_pair(x,y);
} }
array<point, 3> ptc(const array<hyperpoint, 3>& h) {
return {ptc(h[0]), ptc(h[1]), ptc(h[2])};
}
ld penwidth = .02;
int near(pair<int, int> p1, pair<int, int> p2) { int near(pair<int, int> p1, pair<int, int> p2) {
return max(abs(p1.first-p2.first), abs(p1.second - p2.second)); return max(abs(p1.first-p2.first), abs(p1.second - p2.second));
} }
void filltriangle(array<hyperpoint, 3> v, int col, int lev) { void filltriangle(const array<hyperpoint, 3>& v, const array<point, 3>& p, int col, int lev) {
pair<int,int> p[3] = {ptc(v[0]), ptc(v[1]), ptc(v[2])};
if(0) for(int i=0; i<3; i++)
printf("#%d fillt #%d %s -> %d,%d\n", lev, i, display(v[i]), p[i].first, p[i].second);
int d2 = near(p[0], p[1]), d1 = near(p[0], p[2]), d0 = near(p[1], p[2]); int d2 = near(p[0], p[1]), d1 = near(p[0], p[2]), d0 = near(p[1], p[2]);
if((d0 <= 1 && d1 <= 1 && d2 <= 1) || lev >= 5) { int a, b, c;
if((d0 <= 1 && d1 <= 1 && d2 <= 1) || lev >= 20) {
for(int i=0; i<3; i++) for(int i=0; i<3; i++)
expanded_data[((p[i].first) & (twidth-1)) + (p[i].second & (twidth-1)) * twidth] = col; expanded_data[((p[i].first) & (twidth-1)) + (p[i].second & (twidth-1)) * twidth] = col;
return; return;
} }
else if(d1 >= d0 && d1 >= d2) else if(d1 >= d0 && d1 >= d2)
swap(v[0], v[1]); a = 0, b = 2, c = 1;
else if(d2 >= d0 && d2 >= d1) else if(d2 >= d0 && d2 >= d1)
swap(v[0], v[2]); a = 0, b = 1, c = 2;
else
a = 1, b = 2, c = 0;
hyperpoint v3 = mid(v[1], v[2]); hyperpoint v3 = mid(v[a], v[b]);
filltriangle({v[0], v[1], v3}, col, lev+1); point p3 = ptc(v3);
filltriangle({v[0], v[2], v3}, col, lev+1); filltriangle({v[c], v[a], v3}, {p[c], p[a], p3}, col, lev+1);
filltriangle({v[c], v[b], v3}, {p[c], p[b], p3}, col, lev+1);
}
void splitseg(const transmatrix& A, const array<ld, 2>& angles, const array<hyperpoint, 2>& h, const array<point, 2>& p, int col, int lev) {
ld newangle = (angles[0] + angles[1]) / 2;
hyperpoint nh = A * spin(newangle) * xpush(penwidth) * C0;
auto np = ptc(nh);
filltriangle({h[0],h[1],nh}, {p[0],p[1],np}, col, lev);
if(lev < 10) {
if(near(p[0],np) > 1)
splitseg(A, {angles[0], newangle}, {h[0], nh}, {p[0], np}, col, lev+1);
if(near(np,p[1]) > 1)
splitseg(A, {newangle, angles[1]}, {nh, h[1]}, {np, p[1]}, col, lev+1);
}
} }
void fillcircle(hyperpoint h, int col) { void fillcircle(hyperpoint h, int col) {
transmatrix A = rgpushxto0(h); transmatrix A = rgpushxto0(h);
ld step = M_PI * 2/3;
array<hyperpoint, 3> mh = {A * xpush(penwidth) * C0, A * spin(step) * xpush(penwidth) * C0, A * spin(-step) * xpush(penwidth) * C0};
auto mp = ptc(mh);
ld rad = .02; filltriangle(mh, mp, col, 0);
filltriangle({A * xpush(rad) * C0, A * spin(M_PI * 2/3) * C0, A * spin(-M_PI * 2/3) * C0}, col, 0); for(int i=0; i<3; i++) {
int j = (i+1) % 3;
if(near(mp[i], mp[j]) > 1)
splitseg(A, {step*i, step*(i+1)}, {mh[i], mh[j]}, {mp[i], mp[j]}, col, 1);
}
} }
void drawPixel(cell *c, hyperpoint h, int col) { void drawPixel(cell *c, hyperpoint h, int col) {
printf("s = %d\n", size(gmatrix));
try { try {
transmatrix M = gmatrix.at(c); transmatrix M = gmatrix.at(c);
@ -848,8 +894,6 @@ void drawPixel(cell *c, hyperpoint h, int col) {
h = inverse(M * applyPatterndir(c, si)) * h; h = inverse(M * applyPatterndir(c, si)) * h;
auto& tinf = texture_map[si.id]; auto& tinf = texture_map[si.id];
for(auto& M2: tinf.matrices) for(int i = 0; i<c->type; i += si.symmetries) { for(auto& M2: tinf.matrices) for(int i = 0; i<c->type; i += si.symmetries) {
hyperpoint inmodel;
fillcircle(M2 * spin(2 * M_PI * i / c->type) * h, col); fillcircle(M2 * spin(2 * M_PI * i / c->type) * h, col);
lastupdate = ticks; lastupdate = ticks;
} }