diff --git a/config/menus_edit.cfg b/config/menus_edit.cfg index 3b05b6c2..48919a8a 100644 --- a/config/menus_edit.cfg +++ b/config/menus_edit.cfg @@ -179,8 +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 "Sort mapmodel slots..." [ showmenu [Sort mapmodel slots] ] +menuitem "Sort texture slots..." [ showmenu [Sort texture slots] ] +menuitem "Sort mapsound slots..." [ showmenu [Sort mapsound slots] ] menuitem "" -1 menuitem "Update mapmodel menus" "mapmodelchanged 1" @@ -525,6 +526,27 @@ menuinit [ ] ] +// sort config slots +looplist [__mmsort __mmmerge __texsort __texmerge __sndsort __sndmerge] i [tempalias $i 1] + +newmenu [Sort mapmodel slots] +menuitemcheckbox "Sort slots alphabetically" "$__mmsort" [ __mmsort = $arg1 ] +menuitemslider "Merge " 0 2 "$__mmmerge" 1 ["no slots" "unused identical slots" "all identical slots"] [ __mmmerge = $arg1 ] +menuitem "" -1 +menuitem "\t\t\f0[Start]" [sortmapmodelslots (at [nosort ""] $__mmsort) (at [nomerge "" mergeused] $__mmmerge)] + +newmenu [Sort texture slots] +menuitemcheckbox "Sort slots alphabetically" "$__texsort" [ __texsort = $arg1 ] +menuitemslider "Merge " 0 2 "$__texmerge" 1 ["no slots" "unused identical slots" "all identical slots"] [ __texmerge = $arg1 ] +menuitem "" -1 +menuitem "\t\t\f0[Start]" [sorttextureslots (at [nosort ""] $__texsort) (at [nomerge "" mergeused] $__texmerge)] + +newmenu [Sort mapsound slots] +menuitemcheckbox "Sort slots alphabetically" "$__sndsort" [ __sndsort = $arg1 ] +menuitemslider "Merge " 0 2 "$__sndmerge" 1 ["no slots" "unused identical slots" "all identical slots"] [ __sndmerge = $arg1 ] +menuitem "" -1 +menuitem "\t\t\f0[Start]" [sortmapsoundslots (at [nosort ""] $__sndsort) (at [nomerge "" mergeused] $__sndmerge)] + //Mapmodels newmenu Mapmodels menuinit __rebuildmapmodelmenus diff --git a/source/src/audiomanager.cpp b/source/src/audiomanager.cpp index 225b7f50..e9f0c8af 100644 --- a/source/src/audiomanager.cpp +++ b/source/src/audiomanager.cpp @@ -968,3 +968,91 @@ void getmapsoundlist() // create a list of mapsound filenames result(res.getbuf()); } COMMAND(getmapsoundlist, ""); + +struct tempmsslot { mapsoundline m; vector oldslot; bool used; }; + +int tempmscmp(tempmsslot *a, tempmsslot *b) +{ + int n = strcmp(a->m.name, b->m.name); + if(n) return n; + return a->m.maxuses - b->m.maxuses; +} + +int tempmssort(tempmsslot *a, tempmsslot *b) +{ + int n = tempmscmp(a, b); + return n ? n : a->oldslot[0] - b->oldslot[0]; +} + +int tempmsunsort(tempmsslot *a, tempmsslot *b) +{ + return a->oldslot[0] - b->oldslot[0]; +} + +void sortmapsoundslots(char **args, int numargs) +{ + bool nomerge = false, mergeused = false, nosort = false, unknownarg = false; + loopi(numargs) if(args[i][0]) + { + if(!strcasecmp(args[i], "nomerge")) nomerge = true; + else if(!strcasecmp(args[i], "nosort")) nosort = true; + else if(!strcasecmp(args[i], "mergeused")) mergeused = true; + else { conoutf("sortmapsoundslots: unknown argument \"%s\"", args[i]); unknownarg = true; } + } + + if(noteditmode("sortmapsoundslots") || multiplayer(true) || unknownarg || mapconfigdata.mapsoundlines.length() < 3) return; + + vector tempslots; + loopv(mapconfigdata.mapsoundlines) + { + tempslots.add().m = mapconfigdata.mapsoundlines[i]; + tempslots.last().oldslot.add(i); + tempslots.last().used = false; + } + loopv(ents) if(ents[i].type == SOUND) tempslots[ents[i].attr1 & 255].used = true; + tempslots.sort(tempmssort); + + // remove double entries + if(!nomerge) loopvrev(tempslots) if(i > 0) + { + tempmsslot &s1 = tempslots[i], &s0 = tempslots[i - 1]; + if(!tempmscmp(&s0, &s1) && (mergeused || !s0.used || !s1.used)) + { + if(s1.used) s0.used = true; + loopvj(s1.oldslot) s0.oldslot.add(s1.oldslot[j]); + tempslots.remove(i); + } + } + if(nosort) tempslots.sort(tempmsunsort); + + // create translation table + uchar newslot[256]; + loopk(256) newslot[k] = k; + loopv(tempslots) + { + tempmsslot &t = tempslots[i]; + loopvj(t.oldslot) + { + if(t.oldslot[j] < 256) newslot[t.oldslot[j]] = i; + } + } + + // translate all mapsound entities + loopv(ents) if(ents[i].type == SOUND) ents[i].attr1 = newslot[ents[i].attr1 & 255]; + + conoutf("%d mapsound slots%s, %d %sslots merged", tempslots.length(), nosort ? "" : " sorted", mapconfigdata.mapsoundlines.length() - tempslots.length(), mergeused ? "" : "unused "); + + // rewrite mapmodel slot list + mapconfigdata.mapsoundlines.shrink(tempslots.length()); + loopv(tempslots) + { + mapconfigdata.mapsoundlines[i] = tempslots[i].m; + } + reloadmapsoundconfig(); + unsavededits++; + mapsoundchanged = 1; + hdr.flags |= MHF_AUTOMAPCONFIG; // requires automapcfg +} +COMMAND(sortmapsoundslots, "v"); + + diff --git a/source/src/rendermodel.cpp b/source/src/rendermodel.cpp index 113bd4de..9a382125 100644 --- a/source/src/rendermodel.cpp +++ b/source/src/rendermodel.cpp @@ -211,7 +211,7 @@ void editmapmodelslot(int *n, char *rad, char *h, char *zoff, char *scale, char } COMMAND(editmapmodelslot, "isssss"); -struct tempmmslot { mapmodelinfo m; vector oldslot; }; +struct tempmmslot { mapmodelinfo m; vector oldslot; bool used; }; int tempmmcmp(tempmmslot *a, tempmmslot *b) { @@ -230,27 +230,46 @@ int tempmmsort(tempmmslot *a, tempmmslot *b) return n ? n : a->oldslot[0] - b->oldslot[0]; } -void sortmapmodelslots() +int tempmmunsort(tempmmslot *a, tempmmslot *b) { - if(noteditmode("sortmapmodelslots") || multiplayer(true) || mapmodels.length() < 5) return; + return a->oldslot[0] - b->oldslot[0]; +} + +void sortmapmodelslots(char **args, int numargs) +{ + bool nomerge = false, mergeused = false, nosort = false, unknownarg = false; + loopi(numargs) if(args[i][0]) + { + if(!strcasecmp(args[i], "nomerge")) nomerge = true; + else if(!strcasecmp(args[i], "nosort")) nosort = true; + else if(!strcasecmp(args[i], "mergeused")) mergeused = true; + else { conoutf("sortmapmodelslots: unknown argument \"%s\"", args[i]); unknownarg = true; } + } + + if(noteditmode("sortmapmodelslots") || multiplayer(true) || unknownarg || mapmodels.length() < 3) return; + vector tempslots; loopv(mapmodels) { tempslots.add().m = mapmodels[i]; tempslots.last().oldslot.add(i); + tempslots.last().used = false; } + loopv(ents) if(ents[i].type == MAPMODEL) tempslots[ents[i].attr2].used = true; tempslots.sort(tempmmsort); // remove double entries - loopvrev(tempslots) if(i > 0) + if(!nomerge) loopvrev(tempslots) if(i > 0) { tempmmslot &s1 = tempslots[i], &s0 = tempslots[i - 1]; - if(!tempmmcmp(&s0, &s1)) + if(!tempmmcmp(&s0, &s1) && (mergeused || !s0.used || !s1.used)) { + if(s1.used) s0.used = true; loopvj(s1.oldslot) s0.oldslot.add(s1.oldslot[j]); tempslots.remove(i); } } + if(nosort) tempslots.sort(tempmmunsort); // create translation table uchar newslot[256]; @@ -267,7 +286,7 @@ void sortmapmodelslots() // 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()); + conoutf("%d mapmodel slots%s, %d %sslots merged", tempslots.length(), nosort ? "" : " sorted", mapmodels.length() - tempslots.length(), mergeused ? "" : "unused "); // rewrite mapmodel slot list mapmodels.shrink(tempslots.length()); @@ -280,7 +299,7 @@ void sortmapmodelslots() mapmodelchanged = 1; hdr.flags |= MHF_AUTOMAPCONFIG; // requires automapcfg } -COMMAND(sortmapmodelslots, ""); +COMMAND(sortmapmodelslots, "v"); hashtable mdlregistry; diff --git a/source/src/texture.cpp b/source/src/texture.cpp index 947dce7f..3db20c58 100644 --- a/source/src/texture.cpp +++ b/source/src/texture.cpp @@ -955,28 +955,39 @@ void gettexturelist(char *_filter, char *_exclude, char *_exts) // create a list } COMMAND(gettexturelist, "sss"); +void textureslotusagemapmodels(int *used) +{ + int old0 = used[0]; + loopv(ents) if(ents[i].type == MAPMODEL) used[ents[i].attr4]++; + used[0] = old0; +} + +void textureslotusagegeometry(int *used) +{ + sqr *s = world; + loopirev(cubicsize) + { + used[s->wtex]++; + if(s->type != SOLID) + { + used[s->ctex]++; + used[s->ftex]++; + used[s->utex]++; + } + s++; + } +} + void textureslotusagelist(char *what) { int used[256] = { 0 }; if(strcmp(what, "onlygeometry")) - { // if not only geometry, cound map model usage - loopv(ents) if(ents[i].type == MAPMODEL) used[ents[i].attr4]++; - used[0] = 0; + { // if not only geometry, count map model usage + textureslotusagemapmodels(used); } if(strcmp(what, "onlymodels")) { // if not only models, count map geometry - sqr *s = world; - loopirev(cubicsize) - { - used[s->wtex]++; - if(s->type != SOLID) - { - used[s->ctex]++; - used[s->ftex]++; - used[s->utex]++; - } - s++; - } + textureslotusagegeometry(used); } vector res; loopi(256) cvecprintf(res, "%d ", used[i]); @@ -1158,7 +1169,7 @@ uchar *texconfig_paste(void *_s, uchar *usedslots) // create mapping table to tr return res; } -struct temptexslot { Slot s; vector oldslot; }; +struct temptexslot { Slot s; vector oldslot; bool used; }; int tempslotsort(temptexslot *a, temptexslot *b) { @@ -1169,29 +1180,51 @@ int tempslotsort(temptexslot *a, temptexslot *b) return a->oldslot[0] - b->oldslot[0]; } -void sorttextureslots() +int tempslotunsort(temptexslot *a, temptexslot *b) { - if(noteditmode("sorttextureslots") || multiplayer(true) || slots.length() < 5) return; + return a->oldslot[0] - b->oldslot[0]; +} + +void sorttextureslots(char **args, int numargs) +{ + bool nomerge = false, mergeused = false, nosort = false, unknownarg = false; + loopi(numargs) if(args[i][0]) + { + if(!strcasecmp(args[i], "nomerge")) nomerge = true; + else if(!strcasecmp(args[i], "nosort")) nosort = true; + else if(!strcasecmp(args[i], "mergeused")) mergeused = true; + else { conoutf("sorttextureslots: unknown argument \"%s\"", args[i]); unknownarg = true; } + } + + if(noteditmode("sorttextureslots") || multiplayer(true) || unknownarg || slots.length() < 5) return; + + int used[256] = { 0 }; + textureslotusagemapmodels(used); + textureslotusagegeometry(used); + vector tempslots; loopv(slots) { tempslots.add().s = slots[i]; tempslots.last().oldslot.add(i); + tempslots.last().used = used[i] > 0; } tempslots.sort(tempslotsort); - // remove double entries - loopvrev(tempslots) if(i > 0) + // remove double entries (if requested) + if(!nomerge) loopvrev(tempslots) if(i > 0) { temptexslot &s1 = tempslots[i], &s0 = tempslots[i - 1]; - if(s1.oldslot[0] > 4 && !strcmp(s0.s.name, s1.s.name) && s0.s.scale == s1.s.scale) + if(s1.oldslot[0] > 4 && !strcmp(s0.s.name, s1.s.name) && s0.s.scale == s1.s.scale && (mergeused || !s0.used || !s1.used)) { + if(s1.used) s0.used = true; loopvj(s1.oldslot) s0.oldslot.add(s1.oldslot[j]); tempslots.remove(i); } } - // sort special textures (like skymap) back front + // sort special textures (like skymap) back front - also, revert sorting, if it's unwanted + if(nosort) tempslots.sort(tempslotunsort); loopk(5) { loopv(tempslots) @@ -1252,7 +1285,7 @@ void sorttextureslots() loopi(256) if(d[i]) *pd++ = i; } - conoutf("%d texture slots sorted, %d slots merged", tempslots.length(), slots.length() - tempslots.length()); + conoutf("%d texture slots%s, %d %sslots merged", tempslots.length(), nosort ? "" : " sorted", slots.length() - tempslots.length(), mergeused ? "" : "unused "); // rewrite texture slot list slots.shrink(tempslots.length()); @@ -1264,7 +1297,7 @@ void sorttextureslots() unsavededits++; hdr.flags |= MHF_AUTOMAPCONFIG; // requires automapcfg } -COMMAND(sorttextureslots, ""); +COMMAND(sorttextureslots, "v"); #ifdef _DEBUG