From b2c89d7060e99a36c8c7ac897b7386686c74deac Mon Sep 17 00:00:00 2001 From: xolatile Date: Thu, 7 Aug 2025 08:30:30 +0200 Subject: Removed undo and prefab... --- src/engine/octaedit.cpp | 508 +----------------------------------------------- 1 file changed, 1 insertion(+), 507 deletions(-) (limited to 'src/engine/octaedit.cpp') diff --git a/src/engine/octaedit.cpp b/src/engine/octaedit.cpp index 7947e67..80e2b03 100644 --- a/src/engine/octaedit.cpp +++ b/src/engine/octaedit.cpp @@ -116,12 +116,9 @@ VAR(passthroughsel, 0, 0, 1); VAR(editing, 1, 0, 0); VAR(selectcorners, 0, 0, 1); -void forcenextundo() { lastsel.orient = -1; } - void cubecancel() { havesel = false; moving = dragging = passthroughsel = 0; - forcenextundo(); } void cancelsel() { @@ -234,7 +231,7 @@ cube &blockcube(int x, int y, int z, const block3 &b, int rgrid) { // looks up a #define loopxy(b) loop(y,(b).s[C[dimension((b).orient)]]) loop(x,(b).s[R[dimension((b).orient)]]) #define loopxyz(b, r, f) { loop(z,(b).s[D[dimension((b).orient)]]) loopxy((b)) { cube &c = blockcube(x,y,z,b,r); f; } } -#define loopselxyz(f) { if(local) makeundo(); loopxyz(sel, sel.grid, f); changed(sel); } +#define loopselxyz(f) { loopxyz(sel, sel.grid, f); changed(sel); } #define selcube(x, y, z) blockcube(x, y, z, sel, sel.grid) ////////////// cursor /////////////// @@ -498,7 +495,6 @@ void changed(const block3 &sel, bool commit = true) { if(commit) commitchanges(); } -//////////// copy and undo ///////////// static inline void copycube(const cube &src, cube &dst) { dst = src; dst.visible = 0; @@ -539,119 +535,8 @@ void selgridmap(selinfo &sel, uchar *g) { // generates a map of the cube loopxyz(sel, -sel.grid, (*g++ = bitscan(lusize), (void)c)); } -void freeundo(undoblock *u) { - if(!u->numents) freeblock(u->block(), false); - delete[] (uchar *)u; -} - -void pasteundoblock(block3 *b, uchar *g) { - cube *s = b->c(); - loopxyz(*b, 1<numents) pasteundoents(u); - else pasteundoblock(u->block(), u->gridmap()); -} - -static inline int undosize(undoblock *u) { - if(u->numents) return u->numents*sizeof(undoent); - else { - block3 *b = u->block(); - cube *q = b->c(); - int size = b->size(), total = size; - loopj(size) total += familysize(*q++)*sizeof(cube); - return total; - } -} - -struct undolist { - undoblock *first, *last; - undolist() : first(NULL), last(NULL) {} - bool empty() { return !first; } - void add(undoblock *u) { - u->next = NULL; - u->prev = last; - if(!first) first = last = u; - else { - last->next = u; - last = u; - } - } - undoblock *popfirst() { - undoblock *u = first; - first = first->next; - if(first) first->prev = NULL; - else last = NULL; - return u; - } - undoblock *poplast() { - undoblock *u = last; - last = last->prev; - if(last) last->next = NULL; - else first = NULL; - return u; - } -}; - -undolist undos, redos; -VARP(undomegs, 0, 8, 100); // bounded by n megs -int totalundos = 0; - -void pruneundos(int maxremain) { // bound memory { - while(totalundos > maxremain && !undos.empty()) { - undoblock *u = undos.popfirst(); - totalundos -= u->size; - freeundo(u); - } - //conoutf(CON_DEBUG, "undo: %d of %d(%%%d)", totalundos, undomegs<<20, totalundos*100/(undomegs<<20)); - while(!redos.empty()) { - undoblock *u = redos.popfirst(); - totalundos -= u->size; - freeundo(u); - } -} - -void clearundos() { pruneundos(0); } - -COMMAND(clearundos, ""); - -undoblock *newundocube(selinfo &s) { - int ssize = s.size(), - selgridsize = ssize, - blocksize = sizeof(block3)+ssize*sizeof(cube); - if(blocksize <= 0 || blocksize > (undomegs<<20)) return NULL; - undoblock *u = (undoblock *)new (false) uchar[sizeof(undoblock) + blocksize + selgridsize]; - if(!u) return NULL; - u->numents = 0; - block3 *b = u->block(); - blockcopy(s, -s.grid, b); - uchar *g = u->gridmap(); - selgridmap(s, g); - return u; -} - -void addundo(undoblock *u) { - u->size = undosize(u); - u->timestamp = totalmillis; - undos.add(u); - totalundos += u->size; - pruneundos(undomegs<<20); -} - VARP(nompedit, 0, 1, 1); -void makeundo(selinfo &s) { - undoblock *u = newundocube(s); - if(u) addundo(u); -} - -void makeundo() { // stores state of selected cubes before editing { - if(lastsel==sel || sel.s.iszero()) return; - lastsel=sel; - makeundo(sel); -} - static inline int countblock(cube *c, int n = 8) { int r = 0; loopi(n) if(c[i].children) r += countblock(c[i].children); else ++r; @@ -660,57 +545,6 @@ static inline int countblock(cube *c, int n = 8) { static int countblock(block3 *b) { return countblock(b->c(), b->size()); } -void swapundo(undolist &a, undolist &b, int op) { - if(noedit()) return; - if(a.empty()) { conoutf(CON_WARN, "nothing more to %s", op == EDIT_REDO ? "redo" : "undo"); return; } - int ts = a.last->timestamp; - if(multiplayer(false)) { - int n = 0, ops = 0; - for(undoblock *u = a.last; u && ts==u->timestamp; u = u->prev) { - ++ops; - n += u->numents ? u->numents : countblock(u->block()); - if(ops > 10 || n > 2500) { - conoutf(CON_WARN, "undo too big for multiplayer"); - if(nompedit) { multiplayer(); return; } - op = -1; - break; - } - } - } - selinfo l = sel; - while(!a.empty() && ts==a.last->timestamp) { - if(op >= 0) game::edittrigger(sel, op); - undoblock *u = a.poplast(), *r; - if(u->numents) r = copyundoents(u); - else { - block3 *ub = u->block(); - l.o = ub->o; - l.s = ub->s; - l.grid = ub->grid; - l.orient = ub->orient; - r = newundocube(l); - } - if(r) { - r->size = u->size; - r->timestamp = totalmillis; - b.add(r); - } - pasteundo(u); - if(!u->numents) changed(*u->block(), false); - freeundo(u); - } - commitchanges(); - sel = l; - reorient(); - forcenextundo(); -} - -void editundo() { swapundo(undos, redos, EDIT_UNDO); } -void editredo() { swapundo(redos, undos, EDIT_REDO); } - -// guard against subdivision -#define protectsel(f) { undoblock *_u = newundocube(sel); f; if(_u) { pasteundo(_u); freeundo(_u); } } - vector editinfos; editinfo *localedit = NULL; @@ -900,138 +734,6 @@ void freeeditinfo(editinfo *&e) { e = NULL; } -bool packundo(undoblock *u, int &inlen, uchar *&outbuf, int &outlen) { - vector buf; - buf.reserve(512); - *(ushort *)buf.pad(2) = lilswap(ushort(u->numents)); - if(u->numents) { - undoent *ue = u->ents(); - loopi(u->numents) { - *(ushort *)buf.pad(2) = lilswap(ushort(ue[i].i)); - entity &e = *(entity *)buf.pad(sizeof(entity)); - e = ue[i].e; - lilswap(&e.o.x, 3); - lilswap(&e.attr1, 5); - } - } - else { - block3 &b = *u->block(); - if(!packblock(b, buf)) return false; - buf.put(u->gridmap(), b.size()); - packvslots(b, buf); - } - inlen = buf.length(); - return compresseditinfo(buf.getbuf(), buf.length(), outbuf, outlen); -} - -bool unpackundo(const uchar *inbuf, int inlen, int outlen) { - uchar *outbuf = NULL; - if(!uncompresseditinfo(inbuf, inlen, outbuf, outlen)) return false; - ucharbuf buf(outbuf, outlen); - if(buf.remaining() < 2) { - delete[] outbuf; - return false; - } - int numents = lilswap(*(const ushort *)buf.pad(2)); - if(numents) { - if(buf.remaining() < numents*int(2 + sizeof(entity))) { - delete[] outbuf; - return false; - } - loopi(numents) { - int idx = lilswap(*(const ushort *)buf.pad(2)); - entity &e = *(entity *)buf.pad(sizeof(entity)); - lilswap(&e.o.x, 3); - lilswap(&e.attr1, 5); - pasteundoent(idx, e); - } - } - else { - block3 *b = NULL; - if(!unpackblock(b, buf) || b->grid >= worldsize || buf.remaining() < b->size()) { - freeblock(b); - delete[] outbuf; - return false; - } - uchar *g = buf.pad(b->size()); - unpackvslots(*b, buf); - pasteundoblock(b, g); - changed(*b, false); - freeblock(b); - } - delete[] outbuf; - commitchanges(); - return true; -} - -bool packundo(int op, int &inlen, uchar *&outbuf, int &outlen) { - switch(op) { - case EDIT_UNDO: return !undos.empty() && packundo(undos.last, inlen, outbuf, outlen); - case EDIT_REDO: return !redos.empty() && packundo(redos.last, inlen, outbuf, outlen); - default: return false; - } -} - -struct prefabheader { - char magic[4]; - int version; -}; - -struct prefab : editinfo { - char *name; - GLuint ebo, vbo; - int numtris, numverts; - prefab() : name(NULL), ebo(0), vbo(0), numtris(0), numverts(0) {} - ~prefab() { DELETEA(name); if(copy) freeblock(copy); } - void cleanup() { - if(ebo) { glDeleteBuffers_(1, &ebo); ebo = 0; } - if(vbo) { glDeleteBuffers_(1, &vbo); vbo = 0; } - numtris = numverts = 0; - } -}; - -static hashnameset prefabs; - -void cleanupprefabs() { - enumerate(prefabs, prefab, p, p.cleanup()); -} - -void delprefab(char *name) { - prefab *p = prefabs.access(name); - if(p) { - p->cleanup(); - prefabs.remove(name); - conoutf("deleted prefab %s", name); - } -} -COMMAND(delprefab, "s"); - -void saveprefab(char *name) { - if(!name[0] || noedit(true) || (nompedit && multiplayer())) return; - prefab *b = prefabs.access(name); - if(!b) { - b = &prefabs[name]; - b->name = newstring(name); - } - if(b->copy) freeblock(b->copy); - protectsel(b->copy = blockcopy(block3(sel), sel.grid)); - changed(sel); - defformatstring(filename, strpbrk(name, "/\\") ? "packages/%s.obr" : "packages/prefab/%s.obr", name); - path(filename); - stream *f = opengzfile(filename, "wb"); - if(!f) { conoutf(CON_ERROR, "could not write prefab to %s", filename); return; } - prefabheader hdr; - memcpy(hdr.magic, "OEBR", 4); - hdr.version = 0; - lilswap(&hdr.version, 1); - f->write(&hdr, sizeof(hdr)); - streambuf s(f); - if(!packblock(*b->copy, s)) { delete f; conoutf(CON_ERROR, "could not pack prefab %s", filename); return; } - delete f; - conoutf("wrote prefab file %s", filename); -} -COMMAND(saveprefab, "s"); - void pasteblock(block3 &b, selinfo &sel, bool local) { sel.s = b.s; int o = sel.orient; @@ -1041,211 +743,13 @@ void pasteblock(block3 &b, selinfo &sel, bool local) { sel.orient = o; } -bool prefabloaded(const char *name) { - return prefabs.access(name) != NULL; -} - -prefab *loadprefab(const char *name, bool msg = true) { - prefab *b = prefabs.access(name); - if(b) return b; - - defformatstring(filename, strpbrk(name, "/\\") ? "packages/%s.obr" : "packages/prefab/%s.obr", name); - path(filename); - stream *f = opengzfile(filename, "rb"); - if(!f) { if(msg) conoutf(CON_ERROR, "could not read prefab %s", filename); return NULL; } - prefabheader hdr; - if(f->read(&hdr, sizeof(hdr)) != sizeof(prefabheader) || memcmp(hdr.magic, "OEBR", 4)) { delete f; if(msg) conoutf(CON_ERROR, "prefab %s has malformatted header", filename); return NULL; } - lilswap(&hdr.version, 1); - if(hdr.version != 0) { delete f; if(msg) conoutf(CON_ERROR, "prefab %s uses unsupported version", filename); return NULL; } - streambuf s(f); - block3 *copy = NULL; - if(!unpackblock(copy, s)) { delete f; if(msg) conoutf(CON_ERROR, "could not unpack prefab %s", filename); return NULL; } - delete f; - - b = &prefabs[name]; - b->name = newstring(name); - b->copy = copy; - - return b; -} - -void pasteprefab(char *name) { - if(!name[0] || noedit() || (nompedit && multiplayer())) return; - prefab *b = loadprefab(name, true); - if(b) pasteblock(*b->copy, sel, true); -} -COMMAND(pasteprefab, "s"); - -struct prefabmesh { - struct vertex { vec pos; bvec4 norm; }; - static const int SIZE = 1<<9; - int table[SIZE]; - vector verts; - vector chain; - vector tris; - prefabmesh() { memset(table, -1, sizeof(table)); } - int addvert(const vertex &v) { - uint h = hthash(v.pos)&(SIZE-1); - for(int i = table[h]; i>=0; i = chain[i]) { - const vertex &c = verts[i]; - if(c.pos==v.pos && c.norm==v.norm) return i; - } - if(verts.length() >= USHRT_MAX) return -1; - verts.add(v); - chain.add(table[h]); - return table[h] = verts.length()-1; - } - int addvert(const vec &pos, const bvec &norm) { - vertex vtx; - vtx.pos = pos; - vtx.norm = norm; - return addvert(vtx); - } - void setup(prefab &p) { - if(tris.empty()) return; - p.cleanup(); - loopv(verts) verts[i].norm.flip(); - if(!p.vbo) glGenBuffers_(1, &p.vbo); - gle::bindvbo(p.vbo); - glBufferData_(GL_ARRAY_BUFFER, verts.length()*sizeof(vertex), verts.getbuf(), GL_STATIC_DRAW); - gle::clearvbo(); - p.numverts = verts.length(); - if(!p.ebo) glGenBuffers_(1, &p.ebo); - gle::bindebo(p.ebo); - glBufferData_(GL_ELEMENT_ARRAY_BUFFER, tris.length()*sizeof(ushort), tris.getbuf(), GL_STATIC_DRAW); - gle::clearebo(); - p.numtris = tris.length()/3; - } - -}; - -static void genprefabmesh(prefabmesh &r, cube &c, const ivec &co, int size) { - if(c.children) { - neighbourstack[++neighbourdepth] = c.children; - loopi(8) { - ivec o(i, co, size/2); - genprefabmesh(r, c.children[i], o, size/2); - } - --neighbourdepth; - } - else if(!isempty(c)) { - int vis; - loopi(6) if((vis = visibletris(c, i, co, size))) { - ivec v[4]; - genfaceverts(c, i, v); - int convex = 0; - if(!flataxisface(c, i)) convex = faceconvexity(v); - int order = vis&4 || convex < 0 ? 1 : 0, numverts = 0; - vec vo(co), pos[4], norm[4]; - pos[numverts++] = vec(v[order]).mul(size/8.0f).add(vo); - if(vis&1) pos[numverts++] = vec(v[order+1]).mul(size/8.0f).add(vo); - pos[numverts++] = vec(v[order+2]).mul(size/8.0f).add(vo); - if(vis&2) pos[numverts++] = vec(v[(order+3)&3]).mul(size/8.0f).add(vo); - guessnormals(pos, numverts, norm); - int index[4]; - loopj(numverts) index[j] = r.addvert(pos[j], bvec(norm[j])); - loopj(numverts-2) if(index[0]!=index[j+1] && index[j+1]!=index[j+2] && index[j+2]!=index[0]) { - r.tris.add(index[0]); - r.tris.add(index[j+1]); - r.tris.add(index[j+2]); - } - } - } -} - -void genprefabmesh(prefab &p) { - block3 b = *p.copy; - b.o = ivec(0, 0, 0); - cube *oldworldroot = worldroot; - int oldworldscale = worldscale, oldworldsize = worldsize; - worldroot = newcubes(); - worldscale = 1; - worldsize = 2; - while(worldsize < max(max(b.s.x, b.s.y), b.s.z)*b.grid) { - worldscale++; - worldsize *= 2; - } - cube *s = p.copy->c(); - loopxyz(b, b.grid, if(!isempty(*s) || s->children) pastecube(*s, c); s++); - prefabmesh r; - neighbourstack[++neighbourdepth] = worldroot; - loopi(8) genprefabmesh(r, worldroot[i], ivec(i, ivec(0, 0, 0), worldsize/2), worldsize/2); - --neighbourdepth; - r.setup(p); - freeocta(worldroot); - worldroot = oldworldroot; - worldscale = oldworldscale; - worldsize = oldworldsize; - useshaderbyname("prefab"); -} - extern int outlinecolour; -static void renderprefab(prefab &p, const vec &o, float yaw, float pitch, float roll, float size, const vec &color) { - if(!p.numtris) { - genprefabmesh(p); - if(!p.numtris) return; - } - block3 &b = *p.copy; - matrix4 m; - m.identity(); - m.settranslation(o); - if(yaw) m.rotate_around_z(yaw*RAD); - if(pitch) m.rotate_around_x(pitch*RAD); - if(roll) m.rotate_around_y(-roll*RAD); - matrix3 w(m); - if(size > 0 && size != 1) m.scale(size); - m.translate(vec(b.s).mul(-b.grid*0.5f)); - gle::bindvbo(p.vbo); - gle::bindebo(p.ebo); - gle::enablevertex(); - gle::enablenormal(); - prefabmesh::vertex *v = (prefabmesh::vertex *)0; - gle::vertexpointer(sizeof(prefabmesh::vertex), v->pos.v); - gle::normalpointer(sizeof(prefabmesh::vertex), v->norm.v, GL_BYTE); - matrix4 pm; - pm.mul(camprojmatrix, m); - GLOBALPARAM(prefabmatrix, pm); - GLOBALPARAM(prefabworld, w); - SETSHADER(prefab); - gle::color(color); - glDrawRangeElements_(GL_TRIANGLES, 0, p.numverts-1, p.numtris*3, GL_UNSIGNED_SHORT, (ushort *)0); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - enablepolygonoffset(GL_POLYGON_OFFSET_LINE); - pm.mul(camprojmatrix, m); - GLOBALPARAM(prefabmatrix, pm); - SETSHADER(prefab); - gle::color(vec::hexcolor(outlinecolour)); - glDrawRangeElements_(GL_TRIANGLES, 0, p.numverts-1, p.numtris*3, GL_UNSIGNED_SHORT, (ushort *)0); - disablepolygonoffset(GL_POLYGON_OFFSET_LINE); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - gle::disablevertex(); - gle::disablenormal(); - gle::clearebo(); - gle::clearvbo(); -} - -void renderprefab(const char *name, const vec &o, float yaw, float pitch, float roll, float size, const vec &color) { - prefab *p = loadprefab(name, false); - if(p) renderprefab(*p, o, yaw, pitch, roll, size, color); -} - -void previewprefab(const char *name, const vec &color) { - prefab *p = loadprefab(name, false); - if(p) { - block3 &b = *p->copy; - float yaw; - vec o = calcmodelpreviewpos(vec(b.s).mul(b.grid*0.5f), yaw); - renderprefab(*p, o, yaw, 0, 0, 1, color); - } -} - void mpcopy(editinfo *&e, selinfo &sel, bool local) { if(local) game::edittrigger(sel, EDIT_COPY); if(e==NULL) e = editinfos.add(new editinfo); if(e->copy) freeblock(e->copy); e->copy = NULL; - protectsel(e->copy = blockcopy(block3(sel), sel.grid)); changed(sel); } @@ -1275,8 +779,6 @@ void paste() { COMMAND(copy, ""); COMMAND(pastehilite, ""); COMMAND(paste, ""); -COMMANDN(undo, editundo, ""); -COMMANDN(redo, editredo, ""); static vector editingvslots; struct vslotref { @@ -1292,12 +794,6 @@ void compacteditvslots() { editinfo *e = editinfos[i]; compactvslots(e->copy->c(), e->copy->size()); } - for(undoblock *u = undos.first; u; u = u->next) - if(!u->numents) - compactvslots(u->block()->c(), u->block()->size()); - for(undoblock *u = redos.first; u; u = u->next) - if(!u->numents) - compactvslots(u->block()->c(), u->block()->size()); } ///////////// main cube edit //////////////// @@ -1895,7 +1391,6 @@ void rotatecube(cube &c, int d) { // rotates cube clockwise. see pics in cvs f void mpflip(selinfo &sel, bool local) { if(local) { game::edittrigger(sel, EDIT_FLIP); - makeundo(); } int zs = sel.s[dimension(sel.orient)]; loopxy(sel) { @@ -1920,7 +1415,6 @@ void mprotate(int cw, selinfo &sel, bool local) { if(!dimcoord(sel.orient)) cw = -cw; int m = sel.s[C[d]] < sel.s[R[d]] ? C[d] : R[d]; int ss = sel.s[m] = max(sel.s[R[d]], sel.s[C[d]]); - if(local) makeundo(); loop(z,sel.s[D[d]]) loopi(cw>0 ? 1 : 3) { loopxy(sel) rotatecube(selcube(x,y,z), d); loop(y,ss/2) loop(x,ss-1-y*2) rotatequad -- cgit v1.2.3