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);