From 460066f7daa8bfaa73ec053add4f9612ac40195a Mon Sep 17 00:00:00 2001 From: ac-stef Date: Wed, 31 May 2017 12:15:32 +0200 Subject: [PATCH] cleanup closestent - make sure, nextclosestent works for pinned entities - menu entries for nextclosestent - highlight closest ent - have closestenttype return the current value and not change the value if the argument is "-" - recognise manually changed closestenttypes in the menu DOCREF closestenttype --- config/menus_edit.cfg | 7 +++---- source/src/entities.cpp | 25 +++++++++++------------ source/src/world.cpp | 44 ++++++++++++++++++++--------------------- 3 files changed, 35 insertions(+), 41 deletions(-) diff --git a/config/menus_edit.cfg b/config/menus_edit.cfg index ae0ecb1b..05787b18 100644 --- a/config/menus_edit.cfg +++ b/config/menus_edit.cfg @@ -659,17 +659,15 @@ menuinit [ //// Main > Editing > Map operations //// newmenu [Map operations] -alias _closestenttypestatus 0 menuitem "Newmap (128x128 cubes - recommended)" [ newmap 7 ] menuitem "Newmap (256x256 cubes)" [ newmap 8 ] menuitem "Increase mapsize (2x)" [ mapenlarge; echo The map size has been increased by 2. However, the new space is solid. To utilize it, you will need to turn it into non-solid space, by selecting it and pressing G. ] menuitem "Print entity stats" entstats -menuitem "Select the next closest entity" nextclosestent menuitem "Copy the current closest entity" copyent menuitem "Paste a previously copied entity" pasteent -menuitemslider "Select only these entities: " 0 15 "$_closestenttypestatus" 1 [All Light Playerstart Pistol Ammobox Grenades Health Armour Akimbo Mapmodel Ladder CTF-flag Sound Clip Helmet PlayerClip] [ _closestentslider $arg1 ] +menuitem "Cycle through multiple closest entities" nextclosestent +menuitemslider "Select only entities of this type: " 0 (listlen (listoptions ents)) "(closestenttype -)" 1 (concat all (listoptions ents)) [ if $arg1 [ closestenttype $arg1 ] [ closestenttype ] ] menuitem "Hide entity sparklies\i\3" [ showmenu [Hide entity sparklies] ] -_closestentslider = [ closestenttype (at ["" light playerstart pistol ammobox grenades health armour akimbo mapmodel ladder ctf-flag sound clip helmet plclip] $arg1); _closestenttypestatus = $arg1 ] //// Main > Editing > Map operations > Hide entity sparklies //// @@ -1250,6 +1248,7 @@ menuitemeditkeyinput [Redo: ] redo menuitem "" -1 menuitemeditkeyinput [Pin/unpin closest entity: ] toggleclosestentpin menuitemeditkeyinput [Point to select entity: ] editkey_pointatents +menuitemeditkeyinput [Cycle through closest entities: ] nextclosestent menuitemeditkeyinput [Delete entity: ] editkey_delete_entity menuitemeditkeyinput [Copy entity: ] copyent menuitemeditkeyinput [Paste entity: ] pasteent diff --git a/source/src/entities.cpp b/source/src/entities.cpp index 325f845b..225a866f 100644 --- a/source/src/entities.cpp +++ b/source/src/entities.cpp @@ -122,7 +122,6 @@ void renderentities() if(lastmillis - lastsparkle >= 20) { lastsparkle = lastmillis - (lastmillis%20); - // closest see above loopv(ents) { entity &e = ents[i]; @@ -130,33 +129,31 @@ void renderentities() if(edithideentmask & (1 << (e.type - 1))) continue; vec v(e.x, e.y, e.z); if(vec(v).sub(camera1->o).dot(camdir) < 0) continue; - //particle_splash(i == closest ? PART_ELIGHT : PART_ECLOSEST, 2, 40, v); - int sc = PART_ECARROT; // "carrot" (orange) - entity slot currently unused, possibly "reserved" - if(i==closest) + int sc = PART_ECARROT; // use "carrot" for unknown types + if(i == closest) { sc = PART_ECLOSEST; // blue } else switch(e.type) { - case LIGHT : sc = PART_ELIGHT; break; // white - case PLAYERSTART: sc = PART_ESPAWN; break; // green + case LIGHT: sc = PART_ELIGHT; break; // white + case PLAYERSTART: sc = PART_ESPAWN; break; // green case I_CLIPS: case I_AMMO: - case I_GRENADE: sc = PART_EAMMO; break; // red + case I_GRENADE: sc = PART_EAMMO; break; // red case I_HEALTH: case I_HELMET: case I_ARMOUR: - case I_AKIMBO: sc = PART_EPICKUP; break; // yellow + case I_AKIMBO: sc = PART_EPICKUP; break; // yellow case MAPMODEL: - case SOUND: sc = PART_EMODEL; break; // magenta + case SOUND: sc = PART_EMODEL; break; // magenta case LADDER: case CLIP: - case PLCLIP: sc = PART_ELADDER; break; // grey - case CTF_FLAG: sc = PART_EFLAG; break; // turquoise + case PLCLIP: sc = PART_ELADDER; break; // grey + case CTF_FLAG: sc = PART_EFLAG; break; // turquoise default: break; } - //particle_splash(sc, i==closest?6:2, i==closest?120:40, v); - particle_splash(sc, 2, 40, v); + particle_splash(sc, i == closest ? 14 : 2, i == closest ? 50 : 40, v); } } } @@ -208,7 +205,7 @@ void renderentities() rendermodel("playermodels", ANIM_IDLE, -(int)textureload(skin)->id, 1.5f, o, 0, e.attr1 / ENTSCALE10 + 90, 0); } } - if(editmode && i==closest && !stenciling)//closest see above + if(editmode && i == closest && !stenciling) { switch(e.type) { diff --git a/source/src/world.cpp b/source/src/world.cpp index 1b4d28ed..40af53f2 100644 --- a/source/src/world.cpp +++ b/source/src/world.cpp @@ -123,7 +123,8 @@ COMMANDF(nextclosestent, "", () { clentsel++; } ); void closestenttype(char *what) { - clenttype = what[0] ? findtype(what) : NOTUSED; + if(strcmp(what, "-")) clenttype = what[0] ? findtype(what) : NOTUSED; + intret(clenttype); } COMMAND(closestenttype, "s"); @@ -160,39 +161,36 @@ bool intersectangular(const vec &from, vec ray, vec ent, float maxangle, float & int closestent() // used for delent and edit mode ent display { if(noteditmode("closestent")) return -1; + int best = -1, enttypemask = clenttype == NOTUSED ? ((~edithideentmask) << 1) : (1 << clenttype); // bitmask of selectable ent types + float bdist = 99999, dist, maxangle = pointingatents ? cosf(pointatentmaxangle * RAD) : -SQRT3; if(pinnedclosestent) { - if(ents.inrange(pinnedent) && ents[pinnedent].type != NOTUSED) return pinnedent; - pinnedclosestent = false; // release lock when ent is deleted + if(ents.inrange(pinnedent) && (enttypemask & (1 << ents[pinnedent].type))) best = pinnedent; + else pinnedclosestent = false; // release lock when ent is deleted or no longer selectable } - int best = -1, bcnt = 0; - float bdist = 99999, dist, maxangle = pointingatents ? cosf(pointatentmaxangle * RAD) : -SQRT3; - loopj(3) - { - bcnt = 0; + if(best < 0) + { // find entity of closest distance in desired solid angle loopv(ents) { entity &e = ents[i]; - if(e.type==NOTUSED) continue; - if(clenttype != NOTUSED && e.type != clenttype) continue; - if(edithideentmask & (1 << (e.type - 1))) continue; - if(!intersectangular(camera1->o, worldpos, vec(e.x, e.y, e.z), maxangle, dist)) continue; - if(j) - { - if(ents[best].x == e.x && ents[best].y == e.y && ents[best].z == e.z) - { - if(j == 2 && bcnt == clentsel) return i; - bcnt++; - } - } - else if(disto, worldpos, vec(e.x, e.y, e.z), maxangle, dist) && dist < bdist) { best = i; bdist = dist; } } - if(best < 0 || bcnt == 1) break; - if(bcnt) clentsel %= bcnt; + } + if(best >= 0) + { // if closest ent shares location with other ents, pick one with clentsel + vector bs; + loopv(ents) + { + entity &e = ents[i]; + if(!(enttypemask & (1 << e.type))) continue; + if(ents[best].x == e.x && ents[best].y == e.y && ents[best].z == e.z) bs.add(i); + } + best = bs[(clentsel %= bs.length())]; } return best; }