diff --git a/config/menus_edit.cfg b/config/menus_edit.cfg index 39b1bf21..a932e094 100644 --- a/config/menus_edit.cfg +++ b/config/menus_edit.cfg @@ -13,6 +13,8 @@ menuitem (_ [Map operations...]) [ showmenu [Map operations] ] menuitem [Map config operations...] [ showmenu [Map config operations] ] menuitem (_ [Bots...]) [ showmenu [Creating bot waypoints] ] menuitem (_ [Settings...]) [ showmenu [Editing settings] ] +menuitem [Deleted entities] [ showmenu "deleted entities" ] + menuitem (_ Help?) [ echo (yellow) (_ [Please read the AssaultCube README which has a detailed guide on mapediting...]) ] tempalias tmp_cradius 12 @@ -287,6 +289,33 @@ menuitemcheckbox (_ [Enable auto save map: ]) "$autosavemap" [ autosavemap = $ar menuitemslider (_ [Time between auto saves (in minutes): ]) 2 60 "(div $timeBetAutoSaves 60000)" 1 [] [ timeBetAutoSaves = (* $arg1 60000) ] menuitemtextinput (_ [Make a map backup (.BAK) every: ]) "$numAutoSaveBackups" [ numAutoSaveBackups = $arg1 ] [ if (! $showedBAKinfo) [ echo This setting effects the number of autosavemaps between making a map backup file. "(.BAK)"; showedBAKinfo = 1 ] ] 4 +// deleted entities +newmenu "deleted entities" +menuinit __rebuilddeletedentitymenu + +tempalias __rebuilddeletedentitymenu [ + delmenu "deleted entities" + newmenu "deleted entities" + if (unlistdeletedentity) [ + push i 0 + looplist (getdeletedentities) [type x y z a1 a2 a3 a4 a5 a6 a7] [ + push desc (concat $type (concatword "[" $x "|" $y "|" $z "]") (concatword "(" $a1 ", " $a2 ", " $a3 ", " $a4 ", " $a5 ", " $a6 ", " $a7 ")")) + if (strcmp $type mapmodel) [desc = (concat $desc (mapmodelslotname $a2))] + if (&& $editing (strcmp $type sound)) [desc = (concat $desc (at (editmapsoundslot $a1) 0))] + if $editing [ + menuitem (pop desc) (concat gotoposition $x $y $z $a1 0 ";" undelent $i) + ][ + menuitem (pop desc) -1 + ] + += i 1 + ] + pop i + menuitem "\f3clear this list" "unlistdeletedentity all" + ] [ + menuitem "no deleted entities" -1 + ] +] + //Mapmodels newmenu Mapmodels menuinit __rebuildmapmodelmenus diff --git a/config/resetbinds.cfg b/config/resetbinds.cfg index 61d3f4f0..342d72f3 100644 --- a/config/resetbinds.cfg +++ b/config/resetbinds.cfg @@ -30,7 +30,7 @@ bind MOUSE3 weapon bind MOUSE4 key_universaldelta_plus bind MOUSE5 key_universaldelta_minus bind BACKSPACE dropflag -editbind BACKSPACE delent +editbind BACKSPACE [if $editmeta2down [showmenu "deleted entities" ; menuselection "deleted entities" (- (unlistdeletedentity) 1)] [if $editmetakeydown undelent delent]] bind TAB key_showscores bind CLEAR [] bind RETURN [] diff --git a/source/src/audiomanager.cpp b/source/src/audiomanager.cpp index 8555b9f3..f4bbbd28 100644 --- a/source/src/audiomanager.cpp +++ b/source/src/audiomanager.cpp @@ -866,6 +866,7 @@ void deletemapsoundslot(int *n, char *opt) // delete mapsound slot - only if unu entity &e = ents[i]; if(e.attr1 == *n) { // delete entity + deleted_ents.add(e); deletesoundentity(e); memset(&e, 0, sizeof(persistent_entity)); e.type = NOTUSED; diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index 950cc1e1..4eb18e59 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -1084,6 +1084,7 @@ void resetmap(bool mrproper) cleardynlights(); pruneundos(); changedents.setsize(0); + deleted_ents.setsize(0); particlereset(); if(mrproper) { diff --git a/source/src/editing.cpp b/source/src/editing.cpp index 3a08f9db..2919229d 100644 --- a/source/src/editing.cpp +++ b/source/src/editing.cpp @@ -1045,6 +1045,7 @@ void transformclipentities() // transforms all clip entities to tag clips, if t } if(!nodelete) { + deleted_ents.add(e); e.type = NOTUSED; // only delete entity, if it is now fully covered in tag clips thisrun++; } diff --git a/source/src/protos.h b/source/src/protos.h index b224bca8..ab3885a5 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -486,11 +486,12 @@ extern void remip(const block &b, int level = 0); extern void remipmore(const block &b, int level = 0); extern int closestent(); extern void deletesoundentity(entity &e); -extern int findtype(char *what); +extern int findtype(const char *what); extern int findentity(int type, int index = 0); extern int findentity(int type, int index, uchar attr2); -extern void newentity(int index, int x, int y, int z, char *what, float v1, float v2, float v3, float v4); +extern void newentity(int index, int x, int y, int z, const char *what, float v1, float v2, float v3, float v4); extern void mapmrproper(bool manual); +extern vector deleted_ents; // worldlight extern int lastcalclight; diff --git a/source/src/rendermodel.cpp b/source/src/rendermodel.cpp index 0f6e35d4..2712e3c5 100644 --- a/source/src/rendermodel.cpp +++ b/source/src/rendermodel.cpp @@ -166,6 +166,7 @@ void deletemapmodelslot(int *n, char *opt) // delete mapmodel slot - only if unu entity &e = ents[i]; if(e.attr2 == *n) { // delete entity + deleted_ents.add(e); memset(&e, 0, sizeof(persistent_entity)); e.type = NOTUSED; deld++; diff --git a/source/src/world.cpp b/source/src/world.cpp index d4fd46f6..97af6e0c 100644 --- a/source/src/world.cpp +++ b/source/src/world.cpp @@ -249,21 +249,19 @@ void deletesoundentity(entity &e) if(loc) loc->drop(); } +vector deleted_ents; + void delent() { int n = closestent(); if(n<0) { conoutf("no more entities"); return; } syncentchanges(true); int t = ents[n].type; - conoutf("%s entity deleted", entnames[t]); + conoutf("%s entity deleted", entnames[t % MAXENTTYPES]); entity &e = ents[n]; - - if (t == SOUND) //stop playing sound - { - deletesoundentity(e); - } - + if(t == SOUND) deletesoundentity(e); //stop playing sound + deleted_ents.add(e); ents[n].type = NOTUSED; addmsg(SV_EDITENT, "ri9i3", n, NOTUSED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); @@ -273,15 +271,66 @@ void delent() } unsavededits++; } +COMMAND(delent, ""); -int findtype(char *what) +void undelent(char *index) +{ + if(noteditmode("undelent")) return; + if(!deleted_ents.length()) { conoutf("no more entities to undelete"); return; } + int n = isdigit(*index) ? strtol(index, NULL, 0) : deleted_ents.length() - 1; + if(deleted_ents.inrange(n)) + { + persistent_entity e = deleted_ents.remove(n); + int t = e.type < MAXENTTYPES ? e.type : NOTUSED; + if(OUTBORD(e.x, e.y)) conoutf("failed to undelete %s entity (coordinates outside map borders)", entnames[t]); + else + { + newentity(-1, e.x, e.y, e.z, entnames[t], float(e.attr1) / entscale[t][0], float(e.attr2) / entscale[t][1], float(e.attr3) / entscale[t][2], float(e.attr4) / entscale[t][3]); + *((persistent_entity *) &ents.last()) = e; + conoutf("%s entity undeleted", entnames[t]); + } + } +} +COMMAND(undelent, "s"); + +void getdeletedentities() +{ + vector res; + loopv(deleted_ents) + { + persistent_entity &e = deleted_ents[i]; + int t = e.type < MAXENTTYPES ? e.type : NOTUSED; + #define AA(x) floatstr(float(e.attr##x) / entscale[t][x - 1], true) + cvecprintf(res,"%s %d %d %d %s %s %s %s %s %s %s\n", entnames[e.type], e.x, e.y, e.z, AA(1), AA(2), AA(3), AA(4), AA(5), AA(6), AA(7)); + #undef AA + } + if(res.length()) res.last() = '\0'; + else res.add('\0'); + result(res.getbuf()); +} +COMMAND(getdeletedentities, ""); + +void unlistdeletedentity(char *which) +{ + if(!strcasecmp(which, "all")) deleted_ents.setsize(0); + else if(!strcasecmp(which, "last")) deleted_ents.pop(); + else if(isdigit(*which)) + { + int n = strtol(which, NULL, 0); + if(deleted_ents.inrange(n)) deleted_ents.remove(n); + } + intret(deleted_ents.length()); +} +COMMAND(unlistdeletedentity, "s"); + +int findtype(const char *what) { int t = getlistindex(what, entnames, true, NOTUSED); if(t == NOTUSED) conoutf("unknown entity type \"%s\"", what); return t; } -void newentity(int index, int x, int y, int z, char *what, float v1f, float v2f, float v3f, float v4f) // add an entity or overwrite an existing one +void newentity(int index, int x, int y, int z, const char *what, float v1f, float v2f, float v3f, float v4f) // add an entity or overwrite an existing one { int type = findtype(what); if(type == NOTUSED) return; @@ -354,7 +403,13 @@ void clearents(char *name) loopv(ents) { entity &e = ents[i]; - if(e.type==type) { e.type = NOTUSED; found = true; } + if(e.type == type) + { + if(type == SOUND) deletesoundentity(e); + deleted_ents.add(e); + e.type = NOTUSED; + found = true; + } } switch(type) { @@ -375,6 +430,7 @@ void deleteentity(char *ns) int t = e.type; if(t == SOUND) deletesoundentity(e); conoutf("deleted entity #%d (%s)", n, entnames[e.type]); + deleted_ents.add(e); memset(&e, 0, sizeof(persistent_entity)); e.type = NOTUSED; if(t == LIGHT) calclight(); @@ -688,7 +744,6 @@ COMMAND(mapenlarge, ""); COMMAND(mapshrink, ""); COMMAND(newmap, "i"); COMMANDN(recalc, calclight, ""); -COMMAND(delent, ""); void countperfectmips(int mip, int xx, int yy, int bs, int *stats) {