From 41fa9e1b34a839ba0265bc95c47d932a3b311b77 Mon Sep 17 00:00:00 2001 From: ac-stef Date: Sat, 27 Aug 2016 21:57:29 +0200 Subject: [PATCH] add command for raw scripted editing selectionwalk action beginsel endsel The command iterates over all cubes in all selections and executes "action" for each cube. The cubes of every selection are framed by executions of "beginsel" and "endsel". The action script is allowed to make changes to cube attributes, and if it does, an undo point is automatically added. "beginsel" and "endsel" are optional. While the scripts are executed, several aliases provide further info: sw_cursel Position and size of the current selection. Valid in all three scripts. Holds four integer values for x, y, xs, ys. See command "selection" for details. (all following aliases are only valid during the execution of the action script and provide the attributes of one cube of the map) sw_abs_x sw_abs_y sw_rel_x sw_rel_y Absolute and relative (within the current selection) coordinates of the current cube. Read-only values. sw_type Type of the current cube. Can be 0..4 for SOLID, CORNER, FHF, CHF and SPACE. May be changed to other numerical value or keyword. sw_floor sw_ceil Floor and ceiling heights of the current cube. Range -128..127 sw_wtex sw_ftex sw_ctex sw_utex Texture slot indices for wall, floor, ceiling and upper wall of the current cube. sw_vdelta sw_tag Vdelta and tag values of current cube. sw_r sw_g sw_b Current light values of current cube. Can be edited, but only with temporary effect. Will be reset with the next light recalc. The command is mostly useful for statistics scripts (like counting cubes with certain attributes), but is can also be used for scripted editing, as the following (useless) example shows: selectionwalk [ += sw_floor (rnd 2) ] Further changes: The command listoptions now also can return the names of cube types: echo (listoptions cubetypes) The command countwalls is now implemented as a script instead of a builtin command. The script works better, because it doesn't create unnecessary undo points. DOCREF selectionwalk listoptions countwalls --- config/scripts.cfg | 7 +++++ source/src/command.cpp | 4 +-- source/src/editing.cpp | 61 ++++++++++++++++++++++++++++---------- source/src/protos.h | 1 + source/src/rendercubes.cpp | 4 +-- 5 files changed, 58 insertions(+), 19 deletions(-) diff --git a/config/scripts.cfg b/config/scripts.cfg index 90b318d6..e5e95be2 100644 --- a/config/scripts.cfg +++ b/config/scripts.cfg @@ -317,6 +317,13 @@ const pasteent [ ] ] +// countwalls - Counts cubes of a specific type in all selections +const countwalls [ + push __cnt 0 + selectionwalk [ if (= $sw_type $arg1) [ += __cnt 1 ] ] + pop __cnt +] + // genhex - Randomly generates a valid hexadecimal color value (e.g. 0x2FCAF1) - useful for finding fogcolours. const genhex [ push genhex [at [0 1 2 3 4 5 6 7 8 9 A B C D E F] (rnd 16)] diff --git a/source/src/command.cpp b/source/src/command.cpp index 2f71bc93..3c8f17cc 100644 --- a/source/src/command.cpp +++ b/source/src/command.cpp @@ -1789,8 +1789,8 @@ COMMAND(getscrext, ""); void listoptions(char *s) { extern const char *menufilesortorders[], *texturestacktypes[]; - const char *optionnames[] = { "entities", "ents", "weapons", "teamnames", "teamnames-abbrv", "punctuations", "crosshairnames", "menufilesortorders", "texturestacktypes", "" }; - const char **optionlists[] = { optionnames, entnames + 1, entnames + 1, gunnames, teamnames, teamnames_s, punctnames, crosshairnames, menufilesortorders, texturestacktypes }; + const char *optionnames[] = { "entities", "ents", "weapons", "teamnames", "teamnames-abbrv", "punctuations", "crosshairnames", "menufilesortorders", "texturestacktypes", "cubetypes", "" }; + const char **optionlists[] = { optionnames, entnames + 1, entnames + 1, gunnames, teamnames, teamnames_s, punctnames, crosshairnames, menufilesortorders, texturestacktypes, cubetypenames }; const char **listp = optionlists[getlistindex(s, optionnames, true, -1) + 1]; commandret = conc(listp, -1, true); } diff --git a/source/src/editing.cpp b/source/src/editing.cpp index 591ef8e9..36939e27 100644 --- a/source/src/editing.cpp +++ b/source/src/editing.cpp @@ -593,21 +593,6 @@ void paste() } COMMAND(paste, ""); -// Count the walls of type "type" contained in the current selection -void countwalls(int *type) -{ - int counter = 0; - EDITSELMP; - if(*type < 0 || *type >= MAXTYPE) - { - conoutf("invalid type"); - intret(0); - } - loopselsxy(if(s->type==*type) counter++) - intret(counter); -} -COMMAND(countwalls, "i"); - void tofronttex() // maintain most recently used of the texture lists when applying texture { loopi(3) @@ -1086,6 +1071,52 @@ void selectionflip(char *axis) } COMMAND(selectionflip, "s"); +void selectionwalk(char *action, char *beginsel, char *endsel) +{ + EDITSELMP; + if(*action) + { + const char *localvars[] = { "sw_cursel", "sw_abs_x", "sw_abs_y", "sw_rel_x", "sw_rel_y", "sw_type", "sw_floor", "sw_ceil", "sw_wtex", "sw_ftex", "sw_ctex", "sw_utex", "sw_vdelta", "sw_tag", "sw_r", "sw_g", "sw_b", "" }; + for(int i = 0; *localvars[i]; i++) push(localvars[i], ""); + int maxsels = sels.length(); + loopv(sels) + { + if(i >= maxsels) break; // don't allow the script to add selections + block sel = sels[i]; // (copy, not reference) + defformatstring(tmp)("%d %d %d %d", sel.x, sel.y, sel.xs, sel.ys); + alias("sw_cursel", tmp); + if(*beginsel) execute(beginsel); + bool haveundo = false; + loop(x, sel.xs) loop(y, sel.ys) + { + sqr *s = S(sel.x + x, sel.y + y), so = *s; + formatstring(tmp)("%d", sel.x + x); alias("sw_abs_x", tmp); + formatstring(tmp)("%d", sel.y + y); alias("sw_abs_y", tmp); + formatstring(tmp)("%d", x); alias("sw_rel_x", tmp); + formatstring(tmp)("%d", y); alias("sw_rel_y", tmp); + #define AATTR(x) formatstring(tmp)("%d", s->x); alias("sw_"#x, tmp) + AATTR(type); AATTR(floor); AATTR(ceil); AATTR(wtex); AATTR(ftex); AATTR(ctex); AATTR(utex); AATTR(vdelta); AATTR(tag); AATTR(r); AATTR(g); AATTR(b); + #undef AATTR + execute(action); + so.type = getlistindex(getalias("sw_type"), cubetypenames, true, int(SPACE)); + #define GETA(x) so.x = ATOI(getalias("sw_"#x)) + GETA(floor); GETA(ceil); GETA(wtex); GETA(ftex); GETA(ctex); GETA(utex); GETA(vdelta); GETA(tag); GETA(r); GETA(g); GETA(b); + #undef GETA + if(memcmp(s, &so, sizeof(sqr))) + { + if(!haveundo) makeundo(sel); + haveundo = true; + *s = so; + } + } + if(haveundo) remip(sel); + if(*endsel) execute(endsel); + } + for(int i = 0; *localvars[i]; i++) pop(localvars[i]); + } +} +COMMAND(selectionwalk, "sss"); + void transformclipentities() // transforms all clip entities to tag clips, if they are big enough (so, that no player could be above or below them) { // (hardcoded factor ENTSCALE10 for attr1 and ENTSCALE5 for attr2-4) EDITMP; diff --git a/source/src/protos.h b/source/src/protos.h index 4aa1818a..364940af 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -475,6 +475,7 @@ struct zone { int x1, x2, y1, y2, color; }; // zones (drawn on the minimap) // rendercubes extern void mipstats(const int a[]); +extern const char *cubetypenames[]; extern bool editfocusdetails(sqr *s); extern void render_flat(int tex, int x, int y, int size, int h, sqr *l1, sqr *l2, sqr *l3, sqr *l4, bool isceil); extern void render_flatdelta(int wtex, int x, int y, int size, float h1, float h2, float h3, float h4, sqr *l1, sqr *l2, sqr *l3, sqr *l4, bool isceil); diff --git a/source/src/rendercubes.cpp b/source/src/rendercubes.cpp index ef786c88..70804809 100644 --- a/source/src/rendercubes.cpp +++ b/source/src/rendercubes.cpp @@ -138,8 +138,8 @@ bool showm = false, showef = false; COMMANDF(showmip, "",() { showm = !showm; }); COMMANDF(showfocuscubedetails, "",() { showef = !showef; }); -const char *cubetypes[] = {"SOLID", "CORNER", "FHF", "CHF", "SPACE"}; -const char *cubetypename(int t) { return t >= 0 && t < SEMISOLID ? cubetypes[t] : "unknown"; } +const char *cubetypenames[] = {"SOLID", "CORNER", "FHF", "CHF", "SPACE", ""}; +const char *cubetypename(int t) { return t >= 0 && t < SEMISOLID ? cubetypenames[t] : "unknown"; } void mipstats(const int a[]) { if(showm && !showef) hudeditf(HUDMSG_MIPSTATS, "1x1/2x2/4x4/8x8: %d / %d / %d / %d", a[0], a[1], a[2], a[3]); }