diff --git a/config/menus_edit.cfg b/config/menus_edit.cfg index 2fbca8b6..cbbb3610 100644 --- a/config/menus_edit.cfg +++ b/config/menus_edit.cfg @@ -179,6 +179,9 @@ menuitem "Delete ALL unused mapmodel slots" [loop ii 256 [ push i (- 255 $ii) ; menuitem "Delete ALL unused texture slots" [loop ii 251 [ push i (- 255 $ii) ; if (&& (strlen (edittextureslot $i)) (strcmp "" (textureslotusage $i))) [deletetextureslot $i] ; pop i]] menuitem "Delete ALL unused mapsound slots" [loop ii 256 [ push i (- 255 $ii) ; if (&& (strlen (editmapsoundslot $i)) (strcmp "" (mapsoundslotusage $i))) [deletemapsoundslot $i] ; pop i]] menuitem "" -1 +menuitem "Sort all mapmodel slots and merge duplicates" sortmapmodelslots +menuitem "Sort all texture slots and merge duplicates" sorttextureslots +menuitem "" -1 menuitem "Update mapmodel menus" "mapmodelchanged 1" tempalias __lastwatchedmapmodel "" diff --git a/source/src/rendermodel.cpp b/source/src/rendermodel.cpp index b0225bfc..113bd4de 100644 --- a/source/src/rendermodel.cpp +++ b/source/src/rendermodel.cpp @@ -211,6 +211,77 @@ void editmapmodelslot(int *n, char *rad, char *h, char *zoff, char *scale, char } COMMAND(editmapmodelslot, "isssss"); +struct tempmmslot { mapmodelinfo m; vector oldslot; }; + +int tempmmcmp(tempmmslot *a, tempmmslot *b) +{ + int n = strcmp(a->m.name, b->m.name); + if(n) return n; + if(a->m.rad != b->m.rad) return a->m.rad - b->m.rad; + if(a->m.h != b->m.h) return a->m.h - b->m.h; + if(a->m.zoff != b->m.zoff) return a->m.zoff - b->m.zoff; + if(a->m.scale != b->m.scale) return int((a->m.scale - b->m.scale) * 1e6); + return 0; +} + +int tempmmsort(tempmmslot *a, tempmmslot *b) +{ + int n = tempmmcmp(a, b); + return n ? n : a->oldslot[0] - b->oldslot[0]; +} + +void sortmapmodelslots() +{ + if(noteditmode("sortmapmodelslots") || multiplayer(true) || mapmodels.length() < 5) return; + vector tempslots; + loopv(mapmodels) + { + tempslots.add().m = mapmodels[i]; + tempslots.last().oldslot.add(i); + } + tempslots.sort(tempmmsort); + + // remove double entries + loopvrev(tempslots) if(i > 0) + { + tempmmslot &s1 = tempslots[i], &s0 = tempslots[i - 1]; + if(!tempmmcmp(&s0, &s1)) + { + loopvj(s1.oldslot) s0.oldslot.add(s1.oldslot[j]); + tempslots.remove(i); + } + } + + // create translation table + uchar newslot[256]; + loopk(256) newslot[k] = k; + loopv(tempslots) + { + tempmmslot &t = tempslots[i]; + loopvj(t.oldslot) + { + if(t.oldslot[j] < 256) newslot[t.oldslot[j]] = i; + } + } + + // translate all mapmodel entities + loopv(ents) if(ents[i].type == MAPMODEL) ents[i].attr2 = newslot[ents[i].attr2]; + + conoutf("%d mapmodel slots sorted, %d slots merged", tempslots.length(), mapmodels.length() - tempslots.length()); + + // rewrite mapmodel slot list + mapmodels.shrink(tempslots.length()); + loopv(tempslots) + { + mapmodels[i] = tempslots[i].m; + mapmodels[i].m = NULL; + } + unsavededits++; + mapmodelchanged = 1; + hdr.flags |= MHF_AUTOMAPCONFIG; // requires automapcfg +} +COMMAND(sortmapmodelslots, ""); + hashtable mdlregistry; void setmodelattributes(const char *name, mapmodelattributes &ma)