From 3bdd199ad2ec49e1d02fa0e89967429c69348e8f Mon Sep 17 00:00:00 2001 From: ac-stef Date: Fri, 29 May 2015 19:42:40 +0200 Subject: [PATCH] include and translate texture slots during copy&paste When blocks of map geometry are copy-pasted between maps (or xmaps), this commit translates the texture slot numbers between different texture config sets. Missing textures are assigned a slot in the target map. When texture slots are added, automapconfig gets enabled. If the paste gets removed by the undo function, the newly assigned texture slots will NOT be removed. This is by design. --- source/src/editing.cpp | 14 +++++++++++- source/src/protos.h | 9 ++++++-- source/src/texture.cpp | 48 +++++++++++++++++++++++++++++++++++++++ source/src/worldlight.cpp | 29 +++++++++++++++++++++-- 4 files changed, 95 insertions(+), 5 deletions(-) diff --git a/source/src/editing.cpp b/source/src/editing.cpp index 0445ccee..57b122c1 100644 --- a/source/src/editing.cpp +++ b/source/src/editing.cpp @@ -531,17 +531,25 @@ int backupeditundo(vector &buf, int undolimit, int redolimit) } vector copybuffers; +void *copytexconfig = NULL; void resetcopybuffers() { loopv(copybuffers) freeblock(copybuffers[i]); copybuffers.shrink(0); + if(copytexconfig) + { + texconfig_delete(copytexconfig); + copytexconfig = NULL; + } } void copy() { EDITSELMP; resetcopybuffers(); + copytexconfig = texconfig_copy(); + loopv(sels) { block *b = blockcopy(sels[i]); @@ -556,6 +564,10 @@ void paste() EDITSELMP; if(!copybuffers.length()) { conoutf("nothing to paste"); return; } + uchar usedslots[256] = { 0 }, *texmap = NULL; + loopv(copybuffers) blocktexusage(*copybuffers[i], usedslots); + if(sels.length() && copytexconfig) texmap = texconfig_paste(copytexconfig, usedslots); + loopv(sels) { block sel = sels[i]; @@ -573,7 +585,7 @@ void paste() sel.y = sely + dy; if(!correctsel(sel) || sel.xs!=copyblock->xs || sel.ys!=copyblock->ys) { conoutf("incorrect selection"); return; } makeundo(sel); - blockpaste(*copyblock, sel.x, sel.y, true); + blockpaste(*copyblock, sel.x, sel.y, true, texmap); } } } diff --git a/source/src/protos.h b/source/src/protos.h index 66bf146d..b3f04618 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -305,7 +305,10 @@ extern const char *gettextureslot(int i); extern bool reloadtexture(Texture &t); extern void reloadtextures(); extern void blitsurface(SDL_Surface *dst, SDL_Surface *src, int x, int y); -void loadskymap(bool reload); +extern void loadskymap(bool reload); +extern void *texconfig_copy(); +extern void texconfig_delete(void *s); +extern uchar *texconfig_paste(void *_s, uchar *usedslots); static inline Texture *lookupworldtexture(int tex, bool trydl = true) { return lookuptexture(tex, noworldtexture, trydl); } @@ -502,7 +505,8 @@ extern void undodynlights(); extern void cleardynlights(); extern void removedynlights(physent *owner); extern block *blockcopy(const block &b); -extern void blockpaste(const block &b, int bx, int by, bool light); +extern void blocktexusage(const block &b, uchar *used); +extern void blockpaste(const block &b, int bx, int by, bool light, uchar *texmap); extern void blockpaste(const block &b); extern void freeblockp(block *b); extern void freeblock(block *&b); @@ -688,6 +692,7 @@ extern uchar *readmcfggz(char *name, int *size, int *sizegz); extern void rlencodecubes(vector &f, sqr *s, int len, bool preservesolids); extern void rldecodecubes(ucharbuf &f, sqr *s, int len, int version, bool silent); extern void clearheaderextras(); +extern void automapconfig(); extern void flagmapconfigchange(); extern void getcurrentmapconfig(vector &f, bool onlysounds); extern void xmapbackup(const char *nickprefix, const char *nick); diff --git a/source/src/texture.cpp b/source/src/texture.cpp index 9d7c9216..5f5b3e32 100644 --- a/source/src/texture.cpp +++ b/source/src/texture.cpp @@ -1036,3 +1036,51 @@ void edittextureslot(int *n, char *scale, char *name) // edit slot parameters != } COMMAND(edittextureslot, "iss"); +// helper functions to allow copy&paste between different maps while keeping the proper textures assigned +// (pasting will add any missing texture slots) + +void *texconfig_copy() +{ + vector *s = new vector; + loopv(slots) s->add(slots[i]); + return (void *)s; +} + +void texconfig_delete(void *s) +{ + delete (vector *)s; +} + +uchar *texconfig_paste(void *_s, uchar *usedslots) // create mapping table to translate pasted geometry to this maps texture list - add any missing textures +{ + vector *s = (vector *)_s; + static uchar res[256]; + loopi(256) res[i] = i; + loopi(256) if(usedslots[i] && s->inrange(i)) + { + Slot &os = (*s)[i]; + bool found = false; + loopvj(slots) + { + if(slots[j].scale == os.scale && !strcmp(slots[j].name, os.name)) + { + res[i] = j; + found = true; + break; + } + } + if(!found) + { + if(slots.length() < 255) + { + res[i] = slots.length(); + _texture(slots.add(), &os.scale, os.name); + conoutf("added texture \"%s\" (scale %.7g) in slot #%d", os.name, os.scale, res[i]); + if(!(hdr.flags & MHF_AUTOMAPCONFIG)) automapconfig(); // make sure, the new texture slots will be saved with the map + } + else conoutf("\f3failed to add texture \"%s\" (scale %.7g): no texture slot available", os.name, os.scale); + } + } + return res; +} + diff --git a/source/src/worldlight.cpp b/source/src/worldlight.cpp index 5b5826bf..f2049f74 100644 --- a/source/src/worldlight.cpp +++ b/source/src/worldlight.cpp @@ -360,7 +360,23 @@ block *blockcopy(const block &s) return b; } -void blockpaste(const block &b, int bx, int by, bool light) // slow version, editmode only +void blocktexusage(const block &b, uchar *used) +{ + const sqr *q = (const sqr *)((&b)+1); + loopirev(b.xs * b.ys) + { // collect used texture slots in block + used[q->wtex] = 1; + if(q->type != SOLID) + { + used[q->ctex] = 1; + used[q->ftex] = 1; + used[q->utex] = 1; + } + q++; + } +} + +void blockpaste(const block &b, int bx, int by, bool light, uchar *texmap) // slow version, editmode only { const sqr *q = (const sqr *)((&b)+1); sqr *dest = 0; @@ -376,7 +392,15 @@ void blockpaste(const block &b, int bx, int by, bool light) // slow version, ed tg = dest->g; tb = dest->b; - *dest = *q++; + *dest = *q; + + if(texmap) + { // translate texture slot numbers + dest->wtex = texmap[q->wtex]; + dest->ctex = texmap[q->ctex]; + dest->ftex = texmap[q->ftex]; + dest->utex = texmap[q->utex]; + } if (light) //edit mode paste { @@ -384,6 +408,7 @@ void blockpaste(const block &b, int bx, int by, bool light) // slow version, ed dest->g = tg; dest->b = tb; } + q++; } block bb = { bx, by, b.xs, b.ys }; remipmore(bb);