diff --git a/hyper.h b/hyper.h index 50bfdb32..1ff14d3e 100644 --- a/hyper.h +++ b/hyper.h @@ -1973,7 +1973,7 @@ struct textureinfo { vector matrices; // these are required to adjust to geometry changes - int current_geometry, current_type, symmetries, current_trunc; + int current_type, symmetries; }; struct qpoly { @@ -2379,7 +2379,7 @@ namespace texture { tsOff, tsAdjusting, tsActive }; - extern eTextureState tstate; + extern eTextureState tstate, tstate_max; extern unsigned paint_color; extern ld penwidth; extern transmatrix itt; @@ -2390,6 +2390,8 @@ namespace texture { void update(); void drawPixel(cell *c, hyperpoint h, int col); + + void remap(eTextureState old_tstate, eTextureState old_tstate_max); extern cpatterntype cgroup; } diff --git a/pattern2.cpp b/pattern2.cpp index 9e2427ea..a1d5a137 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -1140,8 +1140,8 @@ namespace patterns { dialog::handleNavigation(sym, uni); if(uni == 'g') { static unsigned c = (canvasback << 8) | 0xFF; - unsigned canvasbacks[] = { - 5, 0xFFFFFFFF, 0x101010FF, 0x404040FF, 0x808080FF, 0x800000FF + static unsigned canvasbacks[] = { + 6, 0xFFFFFFFF, 0x101010FF, 0x404040FF, 0x808080FF, 0x800000FF, unsigned(linf[laCanvas].color >> 2) << 8 }; dialog::openColorDialog(c, canvasbacks); dialog::reaction = [] () { @@ -1361,7 +1361,7 @@ namespace patterns { {"single type", { {gNormal, true, 0, 0}, {gSphere, true, 0, SPF_EXTRASYM}, - {gEuclid, false, 0, SPF_EXTRASYM}, + {gEuclid, false, 0, SPF_EXTRASYM | SPF_ROT}, {gOctagon, true, 0, SPF_EXTRASYM}, {g45, true, 0, 0}, {g46, true, 0, 0}, @@ -1388,8 +1388,11 @@ namespace patterns { gamescreen(0); } dialog::init(); - for(int i=0; i= '0' && uni < '0' + size(cpatterns)) cgroup = cpatterntype(uni - '0'); else if(cgroup != cpUnknown && uni >= 'a' && uni < 'a' + size(cpatterns[cgroup].geometries)) { + auto old_tstate = texture::tstate; + auto old_tstate_max = texture::tstate_max; auto &g = cpatterns[cgroup].geometries[uni - 'a']; if(g.geo != geometry) { targetgeometry = g.geo; restartGame('g', false, true); } if(g.nontrunc != nontruncated) restartGame('7', false, true); whichPattern = g.whichPattern; subpattern_flags = g.subpattern_flags; + texture::remap(old_tstate, old_tstate_max); } else if(doexiton(sym, uni)) popScreen(); diff --git a/system.cpp b/system.cpp index 250cc0e2..f5a828b9 100644 --- a/system.cpp +++ b/system.cpp @@ -1097,6 +1097,10 @@ void restartGame(char switchWhat, bool push, bool keep_screens) { if(euclid6) geometry = gNormal; nontruncated = !nontruncated; resetGeometry(); + if(texture::tstate == texture::tsActive) + texture::tstate = texture::tsAdjusting; + if(texture::tstate_max == texture::tsActive) + texture::tstate = texture::tsAdjusting; } if(switchWhat == 'g') { if(geometry == targetgeometry) geometry = gNormal; @@ -1104,7 +1108,9 @@ void restartGame(char switchWhat, bool push, bool keep_screens) { if(chaosmode && (euclid || sphere || quotient)) chaosmode = false; if(nontruncated && euclid6) nontruncated = false; - resetGeometry(); + resetGeometry(); + if(texture::tstate == texture::tsActive) + texture::tstate = texture::tsOff; } if(switchWhat == 'y') { yendor::on = !yendor::on; diff --git a/textures.cpp b/textures.cpp index 4041847b..03486f5a 100644 --- a/textures.cpp +++ b/textures.cpp @@ -144,23 +144,22 @@ int color_alpha = 0; int gsplits = 1; -void mapTextureTriangle(textureinfo &mi, array vview, array vmap, int splits = gsplits) { +void mapTextureTriangle(textureinfo &mi, array v, int splits = gsplits) { if(splits) { - array vview2 = { mid(vview[1], vview[2]), mid(vview[2], vview[0]), mid(vview[0], vview[1]) }; - array vmap2 = { mid(vmap [1], vmap [2]), mid(vmap [2], vmap [0]), mid(vmap [0], vmap [1]) }; - mapTextureTriangle(mi, {vview[0], vview2[1], vview2[2]}, {vmap[0], vmap2[1], vmap2[2]}, splits-1); - mapTextureTriangle(mi, {vview[1], vview2[2], vview2[0]}, {vmap[1], vmap2[2], vmap2[0]}, splits-1); - mapTextureTriangle(mi, {vview[2], vview2[0], vview2[1]}, {vmap[2], vmap2[0], vmap2[1]}, splits-1); - mapTextureTriangle(mi, {vview2[0], vview2[1], vview2[2]}, {vmap2[0], vmap2[1], vmap2[2]}, splits-1); + array v2 = { mid(v[1], v[2]), mid(v[2], v[0]), mid(v[0], v[1]) }; + mapTextureTriangle(mi, {v[0], v2[1], v2[2]}, splits-1); + mapTextureTriangle(mi, {v[1], v2[2], v2[0]}, splits-1); + mapTextureTriangle(mi, {v[2], v2[0], v2[1]}, splits-1); + mapTextureTriangle(mi, {v2[0], v2[1], v2[2]}, splits-1); return; } for(int i=0; i<3; i++) { for(int j=0; j<3; j++) - mi.vertices.push_back(vview[i][j]); + mi.vertices.push_back(v[i][j]); hyperpoint inmodel; - applymodel(mi.M * vmap[i], inmodel); + applymodel(mi.M * v[i], inmodel); inmodel = itt * inmodel; inmodel[0] *= vid.radius * 1. / vid.scrsize; inmodel[1] *= vid.radius * 1. / vid.scrsize; @@ -170,17 +169,16 @@ void mapTextureTriangle(textureinfo &mi, array vview, array texture_map; +map texture_map, texture_map_orig; + set models; -void mapTexture(cell *c, textureinfo& mi, patterns::patterninfo &si, const transmatrix& T) { +void mapTexture(cell *c, textureinfo& mi, patterns::patterninfo &si, const transmatrix& T, int shift = 0) { mi.c = c; mi.vertices.clear(); mi.tvertices.clear(); mi.symmetries = si.symmetries; mi.current_type = c->type; - mi.current_geometry = geometry; - mi.current_trunc = nontruncated; mi.M = T * applyPatterndir(c, si); @@ -191,11 +189,10 @@ void mapTexture(cell *c, textureinfo& mi, patterns::patterninfo &si, const trans // int sym = si.symmetries; for(int i=0; itype; i++) { - hyperpoint h1 = spin(M_PI + M_PI * (2*i +1) / c->type) * xpush(z) * C0; - hyperpoint h2 = spin(M_PI + M_PI * (2*i -1) / c->type) * xpush(z) * C0; - hyperpoint hm1 = spin(M_PI + M_PI * (2*i +1) / c->type) * xpush(z) * C0; - hyperpoint hm2 = spin(M_PI + M_PI * (2*i -1) / c->type) * xpush(z) * C0; - mapTextureTriangle(mi, {C0, h1, h2}, {C0, hm1, hm2}); + int i2 = i+shift; + hyperpoint h1 = spin(M_PI + M_PI * (2*i2 +1) / c->type) * xpush(z) * C0; + hyperpoint h2 = spin(M_PI + M_PI * (2*i2 -1) / c->type) * xpush(z) * C0; + mapTextureTriangle(mi, {C0, h1, h2}); } } @@ -227,26 +224,6 @@ bool apply(cell *c, const transmatrix &V, int col) { int n = mi.vertices.size() / 3; - if(geometry != mi.current_geometry || nontruncated != mi.current_trunc) { - // we can easily make it more symmetric - mi.symmetries = gcd(mi.symmetries, si.symmetries); - - printf("Redrawing tile #%d from %d to %d\n", si.id, mi.current_type, c->type); - int nbase = n * mi.symmetries / mi.current_type; - int ntarget = nbase * c->type / mi.symmetries; - printf("n = %d nbase = %d ntarget = %d\n", n, nbase, ntarget); - vector new_tvertices = move(mi.tvertices); - new_tvertices.resize(3*ntarget); - for(int i=3*nbase; i<3*ntarget; i++) { - new_tvertices[i] = new_tvertices[i - 3*nbase]; - } - - mapTexture(c, mi, si, Id); - mi.tvertices = move(new_tvertices); - n = mi.vertices.size() / 3; - printf("new n = %d\n", n); - } - qfi.special = false; qfi.shape = &shFullFloor[ctof(c)]; qfi.tinf = &mi; @@ -274,6 +251,12 @@ bool apply(cell *c, const transmatrix &V, int col) { } } +typedef tuple texture_parameters; + +static const auto current_texture_parameters = tie(geometry, nontruncated, patterns::whichPattern, patterns::subpattern_flags, pmodel, vid.scale, vid.alpha); + +texture_parameters orig_texture_parameters; + void perform_mapping() { if(gsplits < 0) gsplits = 0; if(gsplits > 4) gsplits = 4; @@ -316,6 +299,8 @@ void perform_mapping() { computeCgroup(); texture::cgroup = patterns::cgroup; + texture_map_orig = texture_map; + orig_texture_parameters = current_texture_parameters; } int forgeArgs() { @@ -637,6 +622,7 @@ void showMenu() { dialog::addItem(XLAT("load texture config"), 'l'); dialog::addSelItem(XLAT("texture size"), its(twidth), 'w'); dialog::addItem(XLAT("paint a new texture"), 'n'); + dialog::addSelItem(XLAT("precision"), its(gsplits), 'P'); } if(tstate == tsAdjusting) { @@ -659,7 +645,7 @@ void showMenu() { dialog::addItem(XLAT("perform auto-adjustment"), 'R'); } - dialog::addSelItem(XLAT("precision"), its(gsplits), 'p'); + dialog::addSelItem(XLAT("precision"), its(gsplits), 'P'); } if(tstate == tsActive) { @@ -673,6 +659,7 @@ void showMenu() { dialog::addColorItem(XLAT("grid color"), grid_color, 'g'); dialog::addColorItem(XLAT("mesh color"), mesh_color, 'm'); dialog::addSelItem(XLAT("color alpha"), its(color_alpha), 'c'); + dialog::addItem(XLAT("edit the texture"), 'e'); dialog::addItem(XLAT("save the texture image"), 'S'); dialog::addItem(XLAT("save the texture config"), 's'); } @@ -766,6 +753,11 @@ void showMenu() { tstate_max = tsOff; } + else if(uni == 'e' && tstate == tsActive) { + mapeditor::initdraw(cwt.c); + pushScreen(mapeditor::showDrawEditor); + } + else if(uni == 'n' && tstate == tsOff) { addMessage("white"); if(whitetexture() && loadTextureGL()) { @@ -809,7 +801,7 @@ void showMenu() { 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.")); } - else if(uni == 'p' && tstate == tsAdjusting) { + else if(uni == 'P' && tstate <= tsAdjusting) { dialog::editNumber(gsplits, 0, 4, 1, 1, XLAT("precision"), XLAT("precision")); dialog::reaction = perform_mapping; @@ -920,6 +912,66 @@ void drawPixel(cell *c, hyperpoint h, int col) { } catch(out_of_range) {} } + +void remap(eTextureState old_tstate, eTextureState old_tstate_max) { + if(!patterns::compatible(texture::cgroup, patterns::cgroup)) return; + texture_map.clear(); + if(tstate_max == tsActive) { + + tstate = old_tstate; + tstate_max = old_tstate_max; + for(cell *c: dcal) { + auto si = patterns::getpatterninfo0(c); + + if(texture_map.count(si.id)) continue; + + int oldid = si.id; + int pshift = 0; + if(texture::cgroup == cpSingle) oldid = 1; + if(texture::cgroup == cpFootball && patterns::cgroup == cpThree) { + if(si.id == 4) pshift = 1; + oldid = !si.id; + } + + try { + + auto& mi = texture_map_orig.at(oldid); + int ncurr = size(mi.tvertices); + int ntarget = ncurr * c->type / mi.current_type; + vector new_tvertices = mi.tvertices; + new_tvertices.resize(ntarget); + for(int i=ncurr; itype, ntarget); + printf("vertices: "); + for(auto x: mi.vertices) + printf("%lf ", ld(x)); + printf("\n"); + printf("tvertices: "); + for(auto x: mi.tvertices) + printf("%lf ", ld(x)); + printf("\n"); + } + catch(out_of_range) { + printf("Unexpected missing cell #%d/%d", si.id, oldid); + addMessage(XLAT("Unexpected missing cell #%d/%d", its(si.id), its(oldid))); + tstate_max = tstate = tsAdjusting; + return; + } + } + } + } } +// - fix spheres +// - save texture image +// - undo +// - verify