1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-06-29 08:33:25 +00:00

texture editing

This commit is contained in:
Zeno Rogue 2017-12-18 00:24:56 +01:00
parent e50ee323e8
commit 3e0f751a2c
3 changed files with 374 additions and 218 deletions

View File

@ -1967,6 +1967,7 @@ struct textureinfo {
vector<GLfloat> vertices; vector<GLfloat> vertices;
vector<GLfloat> tvertices; vector<GLfloat> tvertices;
cell *c; cell *c;
vector<transmatrix> matrices;
// these are required to adjust to geometry changes // these are required to adjust to geometry changes
int current_geometry, current_type, symmetries, current_trunc; int current_geometry, current_type, symmetries, current_trunc;
@ -2378,6 +2379,9 @@ namespace texture {
extern eTextureState tstate; extern eTextureState tstate;
void showMenu(); void showMenu();
void update();
void drawPixel(cell *c, hyperpoint h, int col);
} }
void queueline(const hyperpoint& H1, const hyperpoint& H2, int col, int prf = 0, int prio = PPR_LINE); void queueline(const hyperpoint& H1, const hyperpoint& H2, int col, int prf = 0, int prio = PPR_LINE);
@ -2400,3 +2404,4 @@ inline hyperpoint tC0(const transmatrix &T) {
transmatrix actualV(const heptspin& hs, const transmatrix& V); transmatrix actualV(const heptspin& hs, const transmatrix& V);
transmatrix cview(); transmatrix cview();

View File

@ -889,39 +889,52 @@ namespace mapeditor {
if(!mouseout()) getcstat = '-'; if(!mouseout()) getcstat = '-';
int sg = drawcellShapeGroup(); int sg;
string line1, line2; string line1, line2;
switch(sg) { usershape *us = NULL;
case 0:
line1 = XLAT("character");
line2 = csname(vid.cs);
break;
case 1: if(texture::tstate == texture::tsActive) {
line1 = XLAT("monster"); sg = 16;
line2 = XLAT1(minf[drawcell->monst].name); line1 = "texture";
break; line2 = "";
texture::update();
case 2:
line1 = XLAT("item");
line2 = XLAT1(iinf[drawcell->item].name);
break;
case 3:
line1 = XLAT("floor");
line2 = XLAT(ishept(drawcell) ? "heptagonal" :
ishex1(drawcell) ? "hexagonal #1" : "hexagonal");
break;
default:
line1 = XLAT("floor/pattern");
line2 = "#" + its(patterns::getpatterninfo0(drawcell).id);
break;
} }
usershape *us =usershapes[drawcellShapeGroup()][drawcellShapeID()]; else {
int sg = drawcellShapeGroup();
switch(sg) {
case 0:
line1 = XLAT("character");
line2 = csname(vid.cs);
break;
case 1:
line1 = XLAT("monster");
line2 = XLAT1(minf[drawcell->monst].name);
break;
case 2:
line1 = XLAT("item");
line2 = XLAT1(iinf[drawcell->item].name);
break;
case 3:
line1 = XLAT("floor");
line2 = XLAT(ishept(drawcell) ? "heptagonal" :
ishex1(drawcell) ? "hexagonal #1" : "hexagonal");
break;
default:
line1 = XLAT("floor/pattern");
line2 = "#" + its(patterns::getpatterninfo0(drawcell).id);
break;
}
usershape *us =usershapes[drawcellShapeGroup()][drawcellShapeID()];
}
int fs = min(vid.fsize + 5, vid.yres/28); int fs = min(vid.fsize + 5, vid.yres/28);
@ -932,6 +945,7 @@ namespace mapeditor {
else else
displayfr(8, 8+fs*2, 2, vid.fsize, line2, 0xC0C0C0, 0); displayfr(8, 8+fs*2, 2, vid.fsize, line2, 0xC0C0C0, 0);
displayButton(8, 8+fs*3, XLAT("l = layers: %1", its(dslayer)), 'l', 0); displayButton(8, 8+fs*3, XLAT("l = layers: %1", its(dslayer)), 'l', 0);
if(us && size(us->d[dslayer].list)) { if(us && size(us->d[dslayer].list)) {
usershapelayer& ds(us->d[dslayer]); usershapelayer& ds(us->d[dslayer]);
displayButton(8, 8+fs*4, XLAT("1-9 = rotations: %1", its(ds.rots)), '1' + (ds.rots % 9), 0); displayButton(8, 8+fs*4, XLAT("1-9 = rotations: %1", its(ds.rots)), '1' + (ds.rots % 9), 0);
@ -954,6 +968,8 @@ namespace mapeditor {
displayfr(8, 8+fs*15, 2, vid.fsize, XLAT("y = spin"), 0xC0C0C0, 0); displayfr(8, 8+fs*15, 2, vid.fsize, XLAT("y = spin"), 0xC0C0C0, 0);
displayButton(8, 8+fs*16, XLAT("p = paint"), 'p', 0); displayButton(8, 8+fs*16, XLAT("p = paint"), 'p', 0);
}
else if(texture::tstate == texture::tsActive) {
} }
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);
@ -965,7 +981,9 @@ namespace mapeditor {
displaymm('g', vid.xres-8, 8+fs*4, 2, vid.fsize, XLAT("g = grid"), 16); displaymm('g', vid.xres-8, 8+fs*4, 2, vid.fsize, XLAT("g = grid"), 16);
displayButton(vid.xres-8, 8+fs*3, XLAT("z = zoom in"), 'z', 16); displayButton(vid.xres-8, 8+fs*3, XLAT("z = zoom in"), 'z', 16);
displayButton(vid.xres-8, 8+fs*2, XLAT("o = zoom out"), 'o', 16); displayButton(vid.xres-8, 8+fs*2, XLAT("o = zoom out"), 'o', 16);
displaymm('e', vid.xres-8, 8+fs, 2, vid.fsize, XLAT("e = edit this"), 16);
if(texture::tstate != texture::tsActive)
displaymm('e', vid.xres-8, 8+fs, 2, vid.fsize, XLAT("e = edit this"), 16);
if(!mouseout()) { if(!mouseout()) {
hyperpoint mh = inverse(drawtrans * rgpushxto0(ccenter)) * mouseh; hyperpoint mh = inverse(drawtrans * rgpushxto0(ccenter)) * mouseh;
@ -1259,46 +1277,14 @@ namespace mapeditor {
if(uni == SETMOUSEKEY) mousekey = newmousekey; if(uni == SETMOUSEKEY) mousekey = newmousekey;
dslayer %= USERLAYERS;
hyperpoint mh = inverse(drawtrans) * mouseh;
int sg = drawcellShapeGroup();
for(int i=0; i<USERSHAPEIDS; i++) if(editingShape(sg, i))
applyToShape(sg, i, uni, mh);
if(uni == 'e' || (uni == '-' && mousekey == 'e')) {
initdraw(mouseover ? mouseover : cwt.c);
}
if(uni == 'l') { dslayer++; dslayer %= USERLAYERS; }
if(uni == 'L') { dslayer--; if(dslayer < 0) dslayer += USERLAYERS; }
if(uni == 'l' - 96) onelayeronly = !onelayeronly;
if(uni == 'g') coldcenter = ccenter, ccenter = mh;
if(uni == 'c') ew = ewsearch;
if(uni == 'b') autochoose = !autochoose;
if(uni == 'r') { if(uni == 'r') {
pushScreen(patterns::showPattern); pushScreen(patterns::showPattern);
if(drawplayer) if(drawplayer)
addMessage(XLAT("Hint: use F7 to edit floor under the player")); addMessage(XLAT("Hint: use F7 to edit floor under the player"));
} }
if(uni == 'S') { hyperpoint mh = inverse(drawtrans) * mouseh;
for(int i=0; i<USERSHAPEGROUPS; i++) for(int j=0; j<USERSHAPEIDS; j++) { if(uni == 'g') coldcenter = ccenter, ccenter = mh;
usershape *us = usershapes[i][j];
if(!us) continue;
for(int l=0; l<USERLAYERS; l++) if(size(us->d[l].list)) {
usershapelayer& ds(us->d[l]);
printf("// %d %d %d [%06X]\n", i, j, l, ds.color);
printf(" ID, %d, %d, ", us->d[l].rots, us->d[l].sym?2:1);
for(int i=0; i<size(us->d[l].list); i++)
printf("%lf,%lf, ", double(us->d[l].list[i][0]), double(us->d[l].list[i][1]));
printf("\n");
}
}
}
if(uni == 'z') vid.scale *= 2; if(uni == 'z') vid.scale *= 2;
if(uni == 'o') vid.scale /= 2; if(uni == 'o') vid.scale /= 2;
@ -1308,23 +1294,6 @@ namespace mapeditor {
pushScreen(showMapEditor); pushScreen(showMapEditor);
} }
if(uni == 'p') {
dialog::openColorDialog(colortouse);
colorkey = true;
}
if(sym == SDLK_F2)
dialog::openFileDialog(picfile, XLAT("pics to save/load:"), ".pic",
[] () {
return savePicFile(picfile);
});
if(sym == SDLK_F3)
dialog::openFileDialog(picfile, XLAT("pics to save/load:"), ".pic",
[] () {
return loadPicFile(picfile);
});
if(sym == SDLK_F7) { if(sym == SDLK_F7) {
drawplayer = !drawplayer; drawplayer = !drawplayer;
} }
@ -1341,12 +1310,6 @@ namespace mapeditor {
} }
#endif #endif
if(sym == SDLK_F5) {
for(int i=0; i<USERSHAPEGROUPS; i++)
for(int j=0; j<USERSHAPEIDS; j++)
if(usershapes[i][j]) delete usershapes[i][j];
}
if(sym == SDLK_ESCAPE) popScreen(); if(sym == SDLK_ESCAPE) popScreen();
if(sym == SDLK_F1) { if(sym == SDLK_F1) {
@ -1355,6 +1318,71 @@ namespace mapeditor {
if(sym == SDLK_F10) popScreen(); if(sym == SDLK_F10) popScreen();
if(texture::tstate == texture::tsActive) {
if(uni == '-') {
texture::drawPixel(mouseover, mouseh, colortouse);
holdmouse = true;
}
}
else {
dslayer %= USERLAYERS;
int sg = drawcellShapeGroup();
for(int i=0; i<USERSHAPEIDS; i++) if(editingShape(sg, i))
applyToShape(sg, i, uni, mh);
if(uni == 'e' || (uni == '-' && mousekey == 'e')) {
initdraw(mouseover ? mouseover : cwt.c);
}
if(uni == 'l') { dslayer++; dslayer %= USERLAYERS; }
if(uni == 'L') { dslayer--; if(dslayer < 0) dslayer += USERLAYERS; }
if(uni == 'l' - 96) onelayeronly = !onelayeronly;
if(uni == 'c') ew = ewsearch;
if(uni == 'b') autochoose = !autochoose;
if(uni == 'S') {
for(int i=0; i<USERSHAPEGROUPS; i++) for(int j=0; j<USERSHAPEIDS; j++) {
usershape *us = usershapes[i][j];
if(!us) continue;
for(int l=0; l<USERLAYERS; l++) if(size(us->d[l].list)) {
usershapelayer& ds(us->d[l]);
printf("// %d %d %d [%06X]\n", i, j, l, ds.color);
printf(" ID, %d, %d, ", us->d[l].rots, us->d[l].sym?2:1);
for(int i=0; i<size(us->d[l].list); i++)
printf("%lf,%lf, ", double(us->d[l].list[i][0]), double(us->d[l].list[i][1]));
printf("\n");
}
}
}
if(uni == 'p') {
dialog::openColorDialog(colortouse);
colorkey = true;
}
if(sym == SDLK_F2)
dialog::openFileDialog(picfile, XLAT("pics to save/load:"), ".pic",
[] () {
return savePicFile(picfile);
});
if(sym == SDLK_F3)
dialog::openFileDialog(picfile, XLAT("pics to save/load:"), ".pic",
[] () {
return loadPicFile(picfile);
});
if(sym == SDLK_F5) {
for(int i=0; i<USERSHAPEGROUPS; i++)
for(int j=0; j<USERSHAPEIDS; j++)
if(usershapes[i][j]) delete usershapes[i][j];
}
}
if(rebuildPolys) if(rebuildPolys)
buildpolys(), rebuildPolys = false; buildpolys(), rebuildPolys = false;
} }
@ -1381,6 +1409,8 @@ namespace mapeditor {
ewsearch = ew; ewsearch = ew;
} }
transmatrix textrans;
bool drawUserShape(transmatrix V, int group, int id, int color, cell *c) { bool drawUserShape(transmatrix V, int group, int id, int color, cell *c) {
#if !CAP_EDIT #if !CAP_EDIT
return false; return false;
@ -1400,99 +1430,116 @@ namespace mapeditor {
} }
} }
if((cmode & sm::DRAW) && mapeditor::editingShape(group, id)) { if(cmode & sm::DRAW) {
/* for(int a=0; a<size(ds.list); a++) { if(texture::tstate == texture::tsActive && mouseover && !mouseout()) {
hyperpoint P2 = V * ds.list[a]; auto sio = patterns::getpatterninfo0(mouseover);
auto sih = patterns::getpatterninfo0(c);
int xc, yc, sc; if(sio.id == sih.id) {
getcoord(P2, xc, yc, sc); if(c == mouseover) textrans = V * applyPatterndir(mouseover, sio);
queuechr(xc, yc, sc, 10, 'x', hyperpoint mh = inverse(mapeditor::textrans) * mouseh;
a == 0 ? 0x00FF00 : for(int i=0; i<c->type; i += sih.symmetries) {
a == size(ds.list)-1 ? 0xFF0000 : hyperpoint P2 = V * spin(2*M_PI*i/c->type) * mh;
0xFFFF00); queuechr(P2, 10, 'x', 0xFF00FF);
} */ }
}
if(c == ew.c) mapeditor::drawtrans = V;
if(!us) return false;
usershapelayer &ds(us->d[mapeditor::dslayer]);
hyperpoint mh = inverse(mapeditor::drawtrans) * mouseh;
for(int a=0; a<ds.rots; a++)
for(int b=0; b<(ds.sym?2:1); b++) {
if(mouseout()) break;
hyperpoint P2 = V * spin(2*M_PI*a/ds.rots) * (b?Mirror*mh:mh);
queuechr(P2, 10, 'x', 0xFF00FF);
} }
if(size(ds.list) == 0) return us; if(mapeditor::editingShape(group, id)) {
hyperpoint Plast = V * spin(-2*M_PI/ds.rots) * (ds.sym?Mirror*ds.list[0]:ds.list[size(ds.list)-1]); /* for(int a=0; a<size(ds.list); a++) {
int state = 0; hyperpoint P2 = V * ds.list[a];
int gstate = 0;
double dist2 = 0;
hyperpoint lpsm;
for(int a=0; a<ds.rots; a++) int xc, yc, sc;
for(int b=0; b<(ds.sym?2:1); b++) { getcoord(P2, xc, yc, sc);
queuechr(xc, yc, sc, 10, 'x',
a == 0 ? 0x00FF00 :
a == size(ds.list)-1 ? 0xFF0000 :
0xFFFF00);
} */
hyperpoint mh2 = spin(2*M_PI*-ew.rotid/ds.rots) * mh; if(c == ew.c) mapeditor::drawtrans = V;
if(ew.symid) mh2 = Mirror * mh2;
hyperpoint pseudomouse = V * spin(2*M_PI*a/ds.rots) * mirrorif(mh2, b);
for(int t=0; t<size(ds.list); t++) { if(!us) return false;
int ti = b ? size(ds.list)-1-t : t;
hyperpoint P2 = V * spin(2*M_PI*a/ds.rots) * mirrorif(ds.list[ti], b); usershapelayer &ds(us->d[mapeditor::dslayer]);
if(!mouseout()) { hyperpoint mh = inverse(mapeditor::drawtrans) * mouseh;
double d = hdist(mouseh, P2);
if(d < ewsearch.dist)
ewsearch.dist = d,
ewsearch.rotid = a,
ewsearch.symid = b,
ewsearch.pointid = ti,
ewsearch.c = c,
ewsearch.side = b,
state = 1,
dist2 = d + hdist(mouseh, Plast) - hdist(P2, Plast);
else if(state == 1) { for(int a=0; a<ds.rots; a++)
double dist3 = d + hdist(mouseh, Plast) - hdist(P2, Plast); for(int b=0; b<(ds.sym?2:1); b++) {
if(dist3 < dist2)
ewsearch.side = !ewsearch.side;
state = 2;
}
}
queuechr(P2, 10, 'o', if(mouseout()) break;
0xC000C0);
if(!mouseout()) { hyperpoint P2 = V * spin(2*M_PI*a/ds.rots) * (b?Mirror*mh:mh);
if(gstate == 1) queueline(lpsm, P2, 0x90000080), gstate = 0;
if(ti == ew.pointid) {
queueline(pseudomouse, P2, 0xF0000080);
if(ew.side == b) queueline(pseudomouse, Plast, 0x90000080);
else gstate = 1, lpsm = pseudomouse;
}
}
Plast = P2; queuechr(P2, 10, 'x', 0xFF00FF);
} }
} if(size(ds.list) == 0) return us;
if(gstate == 1) queueline(lpsm, V * ds.list[0], 0x90000080), gstate = 0; hyperpoint Plast = V * spin(-2*M_PI/ds.rots) * (ds.sym?Mirror*ds.list[0]:ds.list[size(ds.list)-1]);
if(state == 1) { int state = 0;
hyperpoint P2 = V * ds.list[0]; int gstate = 0;
if(hdist(mouseh, P2) + hdist(mouseh, Plast) - hdist(P2, Plast) < dist2) double dist2 = 0;
ewsearch.side = 1; hyperpoint lpsm;
for(int a=0; a<ds.rots; a++)
for(int b=0; b<(ds.sym?2:1); b++) {
hyperpoint mh2 = spin(2*M_PI*-ew.rotid/ds.rots) * mh;
if(ew.symid) mh2 = Mirror * mh2;
hyperpoint pseudomouse = V * spin(2*M_PI*a/ds.rots) * mirrorif(mh2, b);
for(int t=0; t<size(ds.list); t++) {
int ti = b ? size(ds.list)-1-t : t;
hyperpoint P2 = V * spin(2*M_PI*a/ds.rots) * mirrorif(ds.list[ti], b);
if(!mouseout()) {
double d = hdist(mouseh, P2);
if(d < ewsearch.dist)
ewsearch.dist = d,
ewsearch.rotid = a,
ewsearch.symid = b,
ewsearch.pointid = ti,
ewsearch.c = c,
ewsearch.side = b,
state = 1,
dist2 = d + hdist(mouseh, Plast) - hdist(P2, Plast);
else if(state == 1) {
double dist3 = d + hdist(mouseh, Plast) - hdist(P2, Plast);
if(dist3 < dist2)
ewsearch.side = !ewsearch.side;
state = 2;
}
}
queuechr(P2, 10, 'o',
0xC000C0);
if(!mouseout()) {
if(gstate == 1) queueline(lpsm, P2, 0x90000080), gstate = 0;
if(ti == ew.pointid) {
queueline(pseudomouse, P2, 0xF0000080);
if(ew.side == b) queueline(pseudomouse, Plast, 0x90000080);
else gstate = 1, lpsm = pseudomouse;
}
}
Plast = P2;
}
}
if(gstate == 1) queueline(lpsm, V * ds.list[0], 0x90000080), gstate = 0;
if(state == 1) {
hyperpoint P2 = V * ds.list[0];
if(hdist(mouseh, P2) + hdist(mouseh, Plast) - hdist(P2, Plast) < dist2)
ewsearch.side = 1;
}
} }
} }

View File

@ -65,10 +65,29 @@ template<class T, class U> void scale_colorarray(int origdim, const T& src, cons
} }
} }
bool readtexture() { bool loadTextureGL() {
if(textureid == 0) glGenTextures(1, &textureid ); if(textureid == 0) glGenTextures(1, &textureid );
glBindTexture( GL_TEXTURE_2D, textureid);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, twidth, twidth, 0,
GL_BGRA, GL_UNSIGNED_BYTE,
&expanded_data[0] );
return true;
}
bool whitetexture() {
expanded_data.resize(0);
expanded_data.resize(twidth * twidth, 0xFFFFFFFF);
return true;
}
bool readtexture() {
SDL_Surface *txt = IMG_Load(texturename.c_str()); SDL_Surface *txt = IMG_Load(texturename.c_str());
if(!txt) { if(!txt) {
addMessage(XLAT("Failed to load %1", texturename)); addMessage(XLAT("Failed to load %1", texturename));
@ -86,12 +105,19 @@ bool readtexture() {
int origdim = max(tx, ty); int origdim = max(tx, ty);
int base_x = tx/2 - origdim/2; int base_x = tx/2 - origdim/2;
int base_y = ty/2 - origdim/2; int base_y = ty/2 - origdim/2;
ZZ = 0;
ZZ = 0; // outside is black
/* for(int y=0; y<twidth; y++) /* for(int y=0; y<twidth; y++)
for(int x=0; x<twidth; x++) for(int x=0; x<twidth; x++)
expanded_data[y*twidth+x] = qpixel(txt2, y%ty, x%tx); */ expanded_data[y*twidth+x] = qpixel(txt2, y%ty, x%tx); */
for(int x=0; x<twidth; x++)
scale_colorarray(origdim,
[&] (int y) { return base_y+y < 0 || base_y+y >= ty ? 0 : half_expanded[x + (base_y + y) * twidth]; },
[&] (int y, int v) { expanded_data[twidth * y + x] = v; }
);
for(int y=0; y<ty; y++) for(int y=0; y<ty; y++)
scale_colorarray(origdim, scale_colorarray(origdim,
[&] (int x) { return qpixel(txt2, base_x + x, y); }, [&] (int x) { return qpixel(txt2, base_x + x, y); },
@ -100,30 +126,17 @@ bool readtexture() {
SDL_FreeSurface(txt2); SDL_FreeSurface(txt2);
for(int x=0; x<twidth; x++)
scale_colorarray(origdim,
[&] (int y) { return base_y+y < 0 || base_y+y >= ty ? 0 : half_expanded[x + (base_y + y) * twidth]; },
[&] (int y, int v) { expanded_data[twidth * y + x] = v; }
);
glBindTexture( GL_TEXTURE_2D, textureid);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, twidth, twidth, 0,
GL_BGRA, GL_UNSIGNED_BYTE,
&expanded_data[0] );
return true; return true;
} }
transmatrix itt = Id; transmatrix itt = Id;
int grid_alpha = 0; unsigned grid_color = 0;
int mesh_alpha = 0; unsigned mesh_color = 0;
int color_alpha = 0; unsigned master_color = 0xFFFFFF10;
unsigned slave_color = 0xFF000008;
unsigned int glc = 0xFFFFFFDD; int color_alpha = 0;
int gsplits = 1; int gsplits = 1;
@ -198,9 +211,9 @@ bool apply(cell *c, const transmatrix &V, int col) {
if(tstate == tsAdjusting) { if(tstate == tsAdjusting) {
queuepolyat(V, shFullCross[ctof(c)], 0, PPR_LINE); queuepolyat(V, shFullCross[ctof(c)], 0, PPR_LINE);
lastptd().u.poly.outline = models.count(c) ? 0xFFFFFF08 : 0xFF000008; lastptd().u.poly.outline = models.count(c) ? master_color : slave_color;
queuepolyat(V, shFullFloor[ctof(c)], 0, PPR_LINE); queuepolyat(V, shFullFloor[ctof(c)], 0, PPR_LINE);
lastptd().u.poly.outline = models.count(c) ? 0xFFFFFF10 : 0xFF000010; lastptd().u.poly.outline = models.count(c) ? master_color : slave_color;
return false; return false;
} }
try { try {
@ -237,16 +250,16 @@ bool apply(cell *c, const transmatrix &V, int col) {
if(chasmg == 2) return false; if(chasmg == 2) return false;
else if(chasmg && wmspatial) { else if(chasmg && wmspatial) {
if(detaillevel == 0) return false; if(detaillevel == 0) return false;
queuetable(V * qfi.spin, &mi.vertices[0], n, mesh_alpha, recolor(c->land == laCocytus ? 0x080808FF : 0x101010FF), PPR_LAKEBOTTOM); queuetable(V * qfi.spin, &mi.vertices[0], n, mesh_color, recolor(c->land == laCocytus ? 0x080808FF : 0x101010FF), PPR_LAKEBOTTOM);
} }
else { else {
queuetable(V * qfi.spin, &mi.vertices[0], n, mesh_alpha, recolor(col), PPR_FLOOR); queuetable(V * qfi.spin, &mi.vertices[0], n, mesh_color, recolor(col), PPR_FLOOR);
} }
lastptd().u.poly.tinf = &mi; lastptd().u.poly.tinf = &mi;
if(grid_alpha) { if(grid_color) {
queuepolyat(V, shFullFloor[ctof(c)], 0, PPR_FLOOR); queuepolyat(V, shFullFloor[ctof(c)], 0, PPR_FLOOR);
lastptd().u.poly.outline = grid_alpha; lastptd().u.poly.outline = grid_color;
} }
return true; return true;
@ -279,6 +292,7 @@ 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);
@ -523,9 +537,9 @@ void init_textureconfig() {
addsaver(twidth, "texture resolution", 2048); addsaver(twidth, "texture resolution", 2048);
addsaver(gsplits, "precision", 1); addsaver(gsplits, "precision", 1);
addsaver(grid_alpha, "alpha grid", 0); addsaver(grid_color, "grid color", 0);
addsaver(color_alpha, "alpha color", 0); addsaver(color_alpha, "alpha color", 0);
addsaver(mesh_alpha, "alpha mesh", 0); addsaver(mesh_color, "mesh color", 0);
addsaver(vid.alpha, "projection", 1); addsaver(vid.alpha, "projection", 1);
addsaver(vid.scale, "scale", 1); addsaver(vid.scale, "scale", 1);
@ -576,6 +590,7 @@ bool load_textureconfig() {
} }
if(!readtexture()) return false; if(!readtexture()) return false;
if(!loadTextureGL()) return false;
calcparam(); calcparam();
drawthemap(); drawthemap();
perform_mapping(); perform_mapping();
@ -612,6 +627,9 @@ void showMenu() {
dialog::addBoolItem(XLAT("affine transformations"), panstate == tpsAffine, 'y'); dialog::addBoolItem(XLAT("affine transformations"), panstate == tpsAffine, 'y');
dialog::addBoolItem(XLAT("magic"), panstate == tpsMagic, 'A'); dialog::addBoolItem(XLAT("magic"), panstate == tpsMagic, 'A');
dialog::addBoolItem(XLAT("grid color (master)"), "...", 'M');
dialog::addBoolItem(XLAT("grid color (copy)"), "...", 'C');
if(panstate == tpsMagic) { if(panstate == tpsMagic) {
dialog::addSelItem(XLAT("delete markers"), its(size(amp)), 'D'); dialog::addSelItem(XLAT("delete markers"), its(size(amp)), 'D');
dialog::addSelItem(XLAT("perform auto-adjustment"), "...", 'R'); dialog::addSelItem(XLAT("perform auto-adjustment"), "...", 'R');
@ -627,8 +645,8 @@ void showMenu() {
dialog::addSelItem(XLAT("texture position Y"), fts(iy), 'y'); */ dialog::addSelItem(XLAT("texture position Y"), fts(iy), 'y'); */
dialog::addBoolItem(XLAT("deactivate the texture"), true, 't'); dialog::addBoolItem(XLAT("deactivate the texture"), true, 't');
dialog::addBoolItem(XLAT("readjust the texture"), true, 'r'); dialog::addBoolItem(XLAT("readjust the texture"), true, 'r');
dialog::addSelItem(XLAT("grid alpha"), its(grid_alpha), 'g'); dialog::addSelItem(XLAT("grid alpha"), "...", 'g');
dialog::addSelItem(XLAT("mesh alpha"), its(mesh_alpha), 'm'); dialog::addSelItem(XLAT("mesh alpha"), "...", 'm');
dialog::addSelItem(XLAT("color alpha"), its(color_alpha), 'c'); dialog::addSelItem(XLAT("color alpha"), its(color_alpha), 'c');
dialog::addSelItem(XLAT("save the texture config"), "...", 's'); dialog::addSelItem(XLAT("save the texture config"), "...", 's');
} }
@ -708,7 +726,7 @@ void showMenu() {
else if(uni == 'o' && tstate == tsOff) else if(uni == 'o' && tstate == tsOff)
dialog::openFileDialog(texturename, XLAT("texture to load:"), ".png", dialog::openFileDialog(texturename, XLAT("texture to load:"), ".png",
[] () { [] () {
if(readtexture()) { if(readtexture() && loadTextureGL()) {
if(tstate_max == tsOff) tstate_max = tsAdjusting; if(tstate_max == tsOff) tstate_max = tsAdjusting;
tstate = tstate_max; tstate = tstate_max;
return true; return true;
@ -716,6 +734,17 @@ void showMenu() {
else return false; else return false;
}); });
else if(uni == 'n' && tstate == tsOff) {
addMessage("white");
if(whitetexture() && loadTextureGL()) {
tstate = tstate_max = tsActive;
perform_mapping();
mapeditor::colortouse = 0xFFFF00FF;
mapeditor::initdraw(cwt.c);
pushScreen(mapeditor::showDrawEditor);
}
}
else if(uni == 't' && tstate == tsOff) else if(uni == 't' && tstate == tsOff)
tstate = tstate_max; tstate = tstate_max;
@ -732,14 +761,16 @@ void showMenu() {
texture_map.clear(); texture_map.clear();
} }
else if(uni == 'g' && tstate == tsActive) { else if(uni == 'g' && tstate == tsActive)
dialog::editNumber(grid_alpha, 0, 255, 15, 0, XLAT("grid alpha"), dialog::openColorDialog(grid_color, NULL);
XLAT("Grid alpha.")); else if(uni == 'm' && tstate == tsActive)
} dialog::openColorDialog(mesh_color, NULL);
else if(uni == 'm' && tstate == tsActive) {
dialog::editNumber(mesh_alpha, 0, 255, 15, 0, XLAT("mesh alpha"), else if(uni == 'M' && tstate == tsAdjusting)
XLAT("Mesh alpha.")); dialog::openColorDialog(master_color, NULL);
} else if(uni == 'C' && tstate == tsActive)
dialog::openColorDialog(slave_color, NULL);
else if(uni == 'c' && tstate == tsActive) { else if(uni == 'c' && tstate == tsActive) {
dialog::editNumber(color_alpha, 0, 255, 15, 0, XLAT("color alpha"), dialog::editNumber(color_alpha, 0, 255, 15, 0, XLAT("color alpha"),
XLAT("The higher the value, the less important the color of underlying terrain is.")); XLAT("The higher the value, the less important the color of underlying terrain is."));
@ -754,7 +785,80 @@ void showMenu() {
}; };
} }
int lastupdate;
void update() {
if(lastupdate && ticks > lastupdate + 100) {
loadTextureGL();
lastupdate = 0;
}
}
pair<int,int> ptc(hyperpoint h) {
hyperpoint inmodel;
applymodel(h, inmodel);
inmodel = itt * inmodel;
inmodel[0] *= vid.radius * 1. / vid.scrsize;
inmodel[1] *= vid.radius * 1. / vid.scrsize;
int x = (1 + inmodel[0]) * twidth / 2;
int y = (1 + inmodel[1]) * twidth / 2;
return make_pair(x,y);
}
int near(pair<int, int> p1, pair<int, int> p2) {
return max(abs(p1.first-p2.first), abs(p1.second - p2.second));
}
void filltriangle(array<hyperpoint, 3> v, 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]);
if((d0 <= 1 && d1 <= 1 && d2 <= 1) || lev >= 5) {
for(int i=0; i<3; i++)
expanded_data[((p[i].first) & (twidth-1)) + (p[i].second & (twidth-1)) * twidth] = col;
return;
}
else if(d1 >= d0 && d1 >= d2)
swap(v[0], v[1]);
else if(d2 >= d0 && d2 >= d1)
swap(v[0], v[2]);
hyperpoint v3 = mid(v[1], v[2]);
filltriangle({v[0], v[1], v3}, col, lev+1);
filltriangle({v[0], v[2], v3}, col, lev+1);
}
void fillcircle(hyperpoint h, int col) {
transmatrix A = rgpushxto0(h);
ld rad = .02;
filltriangle({A * xpush(rad) * C0, A * spin(M_PI * 2/3) * C0, A * spin(-M_PI * 2/3) * C0}, col, 0);
}
void drawPixel(cell *c, hyperpoint h, int col) {
printf("s = %d\n", size(gmatrix));
try {
transmatrix M = gmatrix.at(c);
auto si = patterns::getpatterninfo0(c);
h = inverse(M * applyPatterndir(c, si)) * h;
auto& tinf = texture_map[si.id];
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);
lastupdate = ticks;
}
}
catch(out_of_range) {}
}
} }
// todo texture editor // todo texture editor
// todo `three octagons` with two colors // todo `three octagons` with two colors