From 4bee0c85a747b430be5562d5e0185f88744f0580 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Fri, 22 Dec 2017 20:59:04 +0100 Subject: [PATCH] undo in texture editor --- hyper.h | 3 +++ mapeditor.cpp | 6 +++++ textures.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/hyper.h b/hyper.h index 85f98ec2..a1a64771 100644 --- a/hyper.h +++ b/hyper.h @@ -2397,6 +2397,9 @@ namespace texture { void drawPixel(cell *c, hyperpoint h, int col); void remap(eTextureState old_tstate, eTextureState old_tstate_max); + + void undoLock(); + void undo(); extern cpatterntype cgroup; } diff --git a/mapeditor.cpp b/mapeditor.cpp index b51fbc71..1a4965d7 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -975,6 +975,7 @@ namespace mapeditor { 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); + displayButton(8, 8+fs*9, XLAT("u = undo"), 'u', 0); } #endif else { @@ -1339,10 +1340,15 @@ namespace mapeditor { #if CAP_TEXTURE if(texture::tstate == texture::tsActive) { if(uni == '-') { + if(!holdmouse) texture::undoLock(); texture::drawPixel(mouseover, mouseh, (texture::paint_color >> 8) | ((texture::paint_color & 0xFF) << 24)); holdmouse = true; } + if(uni == 'u') { + texture::undo(); + } + if(uni == 'p') { static unsigned texture_colors[] = { 11, diff --git a/textures.cpp b/textures.cpp index 5a6054a4..38ac9362 100644 --- a/textures.cpp +++ b/textures.cpp @@ -42,6 +42,10 @@ unsigned paint_color = 0x000000FF; vector texture_pixels; +unsigned& get_texture_pixel(int x, int y) { + return texture_pixels[(y&(twidth-1))*twidth+(x&(twidth-1))]; + } + string texturename = "textures/hyperrogue-texture.png"; string configname = "textures/hyperrogue.txc"; @@ -50,6 +54,13 @@ bool saving = false; eTextureState tstate; eTextureState tstate_max; +struct undo { + unsigned* pix; + unsigned last; + }; + +vector> undos; + template void scale_colorarray(int origdim, const T& src, const U& dest) { int ox = 0, tx = 0, partials[4]; int omissing = twidth, tmissing = origdim; @@ -92,6 +103,7 @@ bool loadTextureGL() { } bool whitetexture() { + undos.clear(); texture_pixels.resize(0); texture_pixels.resize(twidth * twidth, 0xFFFFFFFF); return true; @@ -99,6 +111,7 @@ bool whitetexture() { bool readtexture() { + undos.clear(); texture_pixels.resize(twidth * twidth); #if CAP_SDL_IMG @@ -176,10 +189,6 @@ bool readtexture() { ZZ = 0; // outside is black - /* for(int y=0; y half_expanded(twidth * ty); for(int y=0; y= ty ? 0 : half_expanded[x + (base_y + y) * twidth]; }, - [&] (int y, int v) { texture_pixels[twidth * y + x] = v; } + [&] (int y, int v) { get_texture_pixel(x, y) = v; } ); } @@ -206,7 +215,7 @@ void saveRawTexture() { SDL_Surface *sraw = SDL_CreateRGBSurface(SDL_SWSURFACE,twidth,twidth,32,0,0,0,0); for(int y=0; y p1, pair p2) { return max(abs(p1.first-p2.first), abs(p1.second - p2.second)); } +void fillpixel(int x, int y, unsigned col) { + if(x<0 || y<0 || x >= twidth || y >= twidth) return; + auto& pix = get_texture_pixel(x, y); + if(pix != col) { + undos.emplace_back(&pix, pix); + pix = col; + } + } + +void undo() { + while(!undos.empty()) { + auto p = undos.back(); + undos.pop_back(); + if(!p.first) { + loadTextureGL(); + return; + } + *p.first = p.second; + } + } + +void undoLock() { + printf("undos size = %d\n", size(undos)); + if(size(undos) > 2000000) { + // limit undo memory + int moveto = 0; + for(int i=0; i < size(undos) - 1000000; i++) + if(!undos[i].first) moveto = i; + if(moveto) { + for(int i=0; i+moveto < size(undos); i++) + undos[i] = undos[i+moveto]; + undos.resize(size(undos) - moveto); + printf("undos sized to = %d\n", size(undos)); + } + } + + undos.emplace_back(nullptr, 1); + } + void filltriangle(const array& v, const array& p, int col, int lev) { int d2 = near(p[0], p[1]), d1 = near(p[0], p[2]), d0 = near(p[1], p[2]); @@ -950,7 +998,7 @@ void filltriangle(const array& v, const array& p, int c if((d0 <= 1 && d1 <= 1 && d2 <= 1) || lev >= 20) { for(int i=0; i<3; i++) - texture_pixels[((p[i].first) & (twidth-1)) + (p[i].second & (twidth-1)) * twidth] = col; + fillpixel(p[i].first, p[i].second, col); return; } else if(d1 >= d0 && d1 >= d2)