diff --git a/control.cpp b/control.cpp index 99d2ebae..b54027e0 100644 --- a/control.cpp +++ b/control.cpp @@ -663,6 +663,7 @@ void mainloopiter() { mousepressed = ev.type == SDL_MOUSEBUTTONDOWN; if(mousepressed) flashMessages(); mousing = true; + bool was_holdmouse = holdmouse; holdmouse = false; bool act = false; @@ -675,7 +676,10 @@ void mainloopiter() { actonrelease = ev.type == SDL_MOUSEBUTTONDOWN; } - if(ev.type != SDL_MOUSEMOTION) fix_mouseh(); + fix_mouseh(); + + if(was_holdmouse && ev.type == SDL_MOUSEBUTTONUP) + sym = uni = PSEUDOKEY_RELEASE; if(!act) ; diff --git a/hyper.h b/hyper.h index 25c13d1d..7cc78dee 100644 --- a/hyper.h +++ b/hyper.h @@ -2391,6 +2391,11 @@ namespace texture { void update(); void drawPixel(cell *c, hyperpoint h, int col); + + extern cell *where; + // compute 'c' automatically, based on the hint in 'where' + void drawPixel(hyperpoint h, int col); + void drawLine(hyperpoint h1, hyperpoint h2, int col, int steps = 10); void remap(eTextureState old_tstate, eTextureState old_tstate_max); @@ -2399,6 +2404,7 @@ namespace texture { void undoLock(); void undo(); extern bool texturesym; + extern cpatterntype cgroup; } diff --git a/hyperpoint.cpp b/hyperpoint.cpp index 062b72e0..9bd4c352 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -407,6 +407,12 @@ double hdist0(const hyperpoint& mh) { return asinh(d); } +ld circlelength(ld r) { + if(euclid) return 2 * M_PI * r; + else if(hyperbolic) return 2 * M_PI * sinh(r); + else return 2 * M_PI * sin(r); + } + // distance between two points double hdist(const hyperpoint& h1, const hyperpoint& h2) { return hdist0(gpushxto0(h1) * h2); diff --git a/init.cpp b/init.cpp index ba916450..bef92804 100644 --- a/init.cpp +++ b/init.cpp @@ -154,6 +154,7 @@ #define PSEUDOKEY_WHEELDOWN 2501 #define PSEUDOKEY_WHEELUP 2502 +#define PSEUDOKEY_RELEASE 2503 #ifndef CAP_PNG #define CAP_PNG (!ISMOBWEB && !ISMAC && CAP_SDLGFX) diff --git a/mapeditor.cpp b/mapeditor.cpp index 1bf4e5b6..3f11a9fd 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -987,9 +987,15 @@ namespace mapeditor { #if CAP_TEXTURE else if(texture::tstate == texture::tsActive) { displayButton(8, 8+fs*2, XLAT(texture::texturesym ? "0 = symmetry" : "0 = asymmetry"), '0', 0); - displayButton(8, 8+fs*3, XLAT("p = color"), 'p', 0); + if(mousekey == 'g') + displayButton(8, 8+fs*16, XLAT("p = grid color"), 'p', 0); + else + displayButton(8, 8+fs*16, XLAT("p = color"), 'p', 0); displayButton(8, 8+fs*4, XLAT("b = brush size: %1", fts4(texture::penwidth)), 'b', 0); displayButton(8, 8+fs*5, XLAT("u = undo"), 'u', 0); + displaymm('d', 8, 8+fs*7, 2, vid.fsize, XLAT("d = draw"), 0); + displaymm('l', 8, 8+fs*8, 2, vid.fsize, XLAT("l = line"), 0); + displaymm('c', 8, 8+fs*9, 2, vid.fsize, XLAT("c = circle"), 0); } #endif else { @@ -1347,6 +1353,9 @@ namespace mapeditor { } #endif } + + hyperpoint lstart; + cell *lstartcell; void drawHandleKey(int sym, int uni) { @@ -1367,6 +1376,8 @@ namespace mapeditor { hyperpoint mh = inverse(drawtrans) * mouseh; + bool clickused = false; + if((uni == 'p' && mousekey == 'g') || (uni == 'g' && coldcenter == ccenter && ccenter == mh)) { static unsigned grid_colors[] = { 8, @@ -1380,14 +1391,16 @@ namespace mapeditor { 0x0000F080, }; dialog::openColorDialog(gridcolor, grid_colors); + clickused = true; } char mkuni = uni == '-' ? mousekey : uni; - bool clickused = false; - if(mkuni == 'g') coldcenter = ccenter, ccenter = mh, clickused = true; + + if(uni == 'd' || uni == 'l' || uni == 'c') + mousekey = uni; if(uni == ' ' && cheater) { popScreen(); @@ -1420,10 +1433,40 @@ namespace mapeditor { #if CAP_TEXTURE if(texture::tstate == texture::tsActive) { + + int tcolor = (texture::paint_color >> 8) | ((texture::paint_color & 0xFF) << 24); + if(uni == '-' && !clickused) { - if(!holdmouse) texture::undoLock(); - texture::drawPixel(mouseover, mouseh, (texture::paint_color >> 8) | ((texture::paint_color & 0xFF) << 24)); - holdmouse = true; + if(mousekey == 'l' || mousekey == 'c') { + if(!holdmouse) lstart = mouseh, lstartcell = mouseover, holdmouse = true; + } + else { + if(!holdmouse) texture::undoLock(); + texture::drawPixel(mouseover, mouseh, tcolor); + holdmouse = true; lstartcell = NULL; + } + } + + if(sym == PSEUDOKEY_RELEASE) { + printf("release\n"); + if(mousekey == 'l') { + texture::undoLock(); + texture::where = mouseover; + texture::drawPixel(mouseover, mouseh, tcolor); + texture::drawLine(mouseh, lstart, tcolor); + lstartcell = NULL; + } + if(mousekey == 'c') { + texture::undoLock(); + ld rad = hdist(lstart, mouseh); + int circp = int(1 + 3 * (circlelength(rad) / texture::penwidth)); + if(circp > 1000) circp = 1000; + transmatrix T = rgpushxto0(lstart); + texture::where = lstartcell; + for(int i=0; i= 1000 && uni < 1010) @@ -1440,7 +1483,8 @@ namespace mapeditor { } if(uni == 'p') { - dialog::openColorDialog(texture::paint_color, texture_colors); + if(!clickused) + dialog::openColorDialog(texture::paint_color, texture_colors); } if(uni == 'b') @@ -1537,6 +1581,18 @@ namespace mapeditor { } transmatrix textrans; + + void queue_hcircle(transmatrix Ctr, ld radius) { + vector pts; + int circp = 6; + if(radius > 0.04) circp *= 2; + if(radius > .1) circp *= 2; + + for(int j=0; jtype; i += sih.symmetries) { - transmatrix M2 = V * spin(2*M_PI*i/c->type); + transmatrix M2 = V * applyPatterndir(c, sih) * spin(2*M_PI*i/c->type); if(j) M2 = M2 * Mirror; - M2 = M2 * mh; - array 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); + switch(holdmouse ? mousekey : 'd') { + case 'c': + queue_hcircle(M2 * ml, hdist(lstart, mouseh)); + break; + case 'l': + queueline(M2 * mh * C0, M2 * ml * C0, texture::paint_color, 4, PPR_LINE); + break; + default: + queue_hcircle(M2 * mh, texture::penwidth); + } } - } + } } #endif diff --git a/textures.cpp b/textures.cpp index b4cbcf93..0c3f2b27 100644 --- a/textures.cpp +++ b/textures.cpp @@ -1171,6 +1171,40 @@ void drawPixel(cell *c, hyperpoint h, int col) { pixels_to_draw.emplace_back(c, h, col); } +cell *where; + +void drawPixel(hyperpoint h, int col) { + try { + again: + transmatrix g0 = gmatrix[where]; + ld cdist0 = hdist(tC0(g0), h); + + forCellEx(c, where) + try { + transmatrix g = gmatrix[c]; + ld cdist = hdist(tC0(g), h); + if(cdist < cdist0) { + cdist0 = cdist; + where = c; g0 = g; + goto again; + } + } + catch(out_of_range) {} + drawPixel(where, h, col); + } + catch(out_of_range) {} + } + +void drawLine(hyperpoint h1, hyperpoint h2, int col, int steps) { + if(steps > 0 && hdist(h1, h2) > penwidth / 3) { + hyperpoint h3 = mid(h1, h2); + drawLine(h1, h3, col, steps-1); + drawLine(h3, h2, col, steps-1); + } + else + drawPixel(h2, col); + } + void remap(eTextureState old_tstate, eTextureState old_tstate_max) { texture_map.clear(); if(old_tstate == tsActive && patterns::compatible(texture::cgroup, patterns::cgroup)) {