From d3a9dec77cece2f44602083f87f4ec794b5a62cc Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sun, 29 May 2011 23:10:51 +0000 Subject: [PATCH] -- TROR: * Mapster32 now makes sandwiches, too: select all floors of a bunch and 'extend them below'. This will put a new sector between the highlighted ones and the their lower neighbors and displace the z's accordingly. Make sure you have enough headroom. * To facilitate the above, RAlt now has two more modifier keys (checked at release time, as usual): for every sector that would be selected, END will select all sectors whose floor bunchnum equals the first (this is useful for sandwiching), and HOME will select all sectors whose ceiling bunchnum equals it (not very useful, but provided for completeness). * Sloping extended sectors is now checked more rigorously -- misc: * When deleting highlighted sectors with DEL, pressing LShift will now always delete them irrespective whether the mouse pointer is over one of them. This is useful for the cleanup of corrupted maps. * 2D drawing is slightly tweaked so that active walls always display over inactive ones git-svn-id: https://svn.eduke32.com/eduke32@1900 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/build/include/editor.h | 2 + polymer/eduke32/build/src/build.c | 388 ++++++++++++++++++------- polymer/eduke32/build/src/engine.c | 35 ++- polymer/eduke32/source/astub.c | 62 +++- 4 files changed, 366 insertions(+), 121 deletions(-) diff --git a/polymer/eduke32/build/include/editor.h b/polymer/eduke32/build/include/editor.h index 5da856916..c28fb07f3 100644 --- a/polymer/eduke32/build/include/editor.h +++ b/polymer/eduke32/build/include/editor.h @@ -145,6 +145,8 @@ extern void fixxrepeat(int16_t wallnum, uint32_t lenrepquot); extern void AlignWallPoint2(int32_t w0); extern int32_t AutoAlignWalls(int32_t w0, uint32_t flags, int32_t nrecurs); +extern void SetFirstWall(int32_t sectnum, int32_t wallnum); + extern int32_t ExtInit(void); extern int32_t ExtPreInit(int32_t argc,const char **argv); extern void ExtUnInit(void); diff --git a/polymer/eduke32/build/src/build.c b/polymer/eduke32/build/src/build.c index f9ad3abd0..0eb3fa07c 100644 --- a/polymer/eduke32/build/src/build.c +++ b/polymer/eduke32/build/src/build.c @@ -335,6 +335,19 @@ int32_t yax_is121(int16_t bunchnum, int16_t getfloor) return headsectbunch[getfloor][bunchnum]; } +static int32_t yax_numsectsinbunch(int16_t bunchnum, int16_t cf) +{ + int32_t i, n=0; + + if (bunchnum<0 || bunchnum>=numyaxbunches) + return -1; + + for (SECTORS_OF_BUNCH(bunchnum, cf, i)) + n++; + + return n; +} + static void yax_fixreverselinks(int16_t oldwall, int16_t newwall) { int32_t cf, ynw; @@ -393,7 +406,7 @@ static int32_t yax_islockedwall(int16_t sec, int16_t line) } #endif -# define DEFAULT_YAX_HEIGHT 32768 +# define DEFAULT_YAX_HEIGHT (2048<<4) #endif static void reset_default_mapstate(void) @@ -2349,6 +2362,74 @@ static void sort_walls_geometrically(int16_t *wallist, int32_t nwalls) } #endif +void SetFirstWall(int32_t sectnum, int32_t wallnum) +{ +#ifdef YAX_ENABLE + int32_t i, j, k, startwall, endwall; + int16_t cf, bunchnum, tempsect, tempwall; + + for (i=0; i= 0 && + (tempsect=yax_is121(bunchnum, cf)) >= 0) + { + tempwall = yax_getnextwall(tempwall, cf); + if (tempwall < 0) + break; // corrupt! + wall[tempwall].cstat |= (1<<14); + } + } + + k = 0; + for (i=0; i 0) + message("Set first walls (sector[].wallptr) for %d sectors", k+1); + else +#endif + message("This wall now sector %d's first wall (sector[].wallptr)", sectnum); + + setfirstwall(sectnum, wallnum); + mkonwinvalid(); + asksave = 1; +} + +static void handlesecthighlight1(int32_t i, int32_t sub, int32_t nograycheck) +{ + int32_t j; + + if (sub) + { + hlsectorbitmap[i>>3] &= ~(1<<(i&7)); + for (j=sector[i].wallptr; j= 0) + checksectorpointer(wall[j].nextwall,wall[j].nextsector); + checksectorpointer(j, i); + } + } + else + { + if (nograycheck || (graysectbitmap[i>>3]&(1<<(i&7)))==0) + hlsectorbitmap[i>>3] |= (1<<(i&7)); + } +} + void overheadeditor(void) { char buffer[80], ch; @@ -2913,50 +2994,7 @@ void overheadeditor(void) { linehighlight = getlinehighlight(mousxplc, mousyplc, linehighlight); if (linehighlight >= 0) - { - int32_t secti = sectorofwall(linehighlight); -#ifdef YAX_ENABLE - int16_t cf, bunchnum, tempsect, tempwall; - - for (i=0; i= 0 && - (tempsect=yax_is121(bunchnum, cf)) >= 0) - { - tempwall = yax_getnextwall(tempwall, cf); - if (tempwall < 0) - break; // corrupt! - wall[tempwall].cstat |= (1<<14); - } - } - - k = 0; - for (i=0; i 0) - message("Set first walls (sector[].wallptr) for %d sectors", k+1); - else -#endif - printmessage16("This wall now sector %d's first wall (sector[].wallptr)", secti); - setfirstwall(secti, linehighlight); - mkonwinvalid(); - asksave = 1; - } + SetFirstWall(sectorofwall(linehighlight), linehighlight); } } @@ -3185,7 +3223,8 @@ void overheadeditor(void) ////////// YAX ////////// static const char *cfs[2] = {"ceiling", "floor"}; - int32_t cf, thez; + int32_t cf, thez, ulz[2]={0,0}; + int16_t bn, sandwichbunch=-1; if (numyaxbunches==YAX_MAXBUNCHES) { @@ -3206,10 +3245,30 @@ void overheadeditor(void) thez = SECTORFLD(highlightsector[0],z, cf); for (i=0; i= 0) + bn = yax_getbunch(highlightsector[i], cf); + + if (sandwichbunch >= 0 && bn!=sandwichbunch) { - message("Sector %d's %s is already extended", highlightsector[i], cfs[cf]); - goto end_yax; + message("When sandwiching extension, must select only sectors of one bunch"); + goto end_yax; + } + + if (bn >= 0) + { + if (cf==YAX_FLOOR) + { + if (sandwichbunch < 0 && i!=0) + { + message("When sandwiching extension, must select only sectors of the bunch"); + goto end_yax; + } + sandwichbunch = bn; + } + else + { + message("Sector %d's %s is already extended", highlightsector[i], cfs[cf]); + goto end_yax; + } } if (SECTORFLD(highlightsector[i],z, cf) != thez) @@ -3218,9 +3277,77 @@ void overheadeditor(void) goto end_yax; } - if (highlightsectorcnt>1 && SECTORFLD(highlightsector[i],stat, cf)&2) + if ((sandwichbunch>=0 || highlightsectorcnt>1) && SECTORFLD(highlightsector[i],stat, cf)&2) { - message("Sector %ss must not be sloped if extending more than one", cfs[cf]); + message("Sector %ss must not be sloped%s", cfs[cf], + sandwichbunch>=0 ? "" : "if extending more than one"); + goto end_yax; + } + } + + if (sandwichbunch >= 0) + { + // cf==YAX_FLOOR here + + int32_t tempz, oldfz, swsecheight = DEFAULT_YAX_HEIGHT/4; + // highest floor z of lower sectors, lowest ceiling z of these sectors + int32_t minfloorz = INT32_MAX, maxceilz = INT32_MIN; + + // some preparation for making the sandwich + if (highlightsectorcnt != yax_numsectsinbunch(sandwichbunch, YAX_FLOOR)) + { + message("When sandwiching extension, must select all sectors of the bunch"); + goto end_yax; + } + + // "for i in sectors of sandwichbunch(floor)" is now the same as + // "for i in highlighted sectors" + + oldfz = sector[highlightsector[0]].floorz; + + // check if enough room in z + for (SECTORS_OF_BUNCH(sandwichbunch, YAX_CEILING, i)) + for (WALLS_OF_SECTOR(i, j)) + { + tempz = getflorzofslope(i, wall[j].x, wall[j].y); + minfloorz = min(minfloorz, tempz); + } + for (SECTORS_OF_BUNCH(sandwichbunch, YAX_FLOOR, i)) + for (WALLS_OF_SECTOR(i, j)) + { + tempz = getceilzofslope(i, wall[j].x, wall[j].y); + maxceilz = max(maxceilz, tempz); + } + + if (minfloorz - maxceilz < 2*swsecheight) + { + message("Too little z headroom for sandwiching, need at least %d", + 2*swsecheight); + goto end_yax; + } + + if (maxceilz >= oldfz || oldfz >= minfloorz) + { + message("Internal error while sandwiching: oldfz out of bounds"); + goto end_yax; + } + + // maxceilz ---| + // ^ | + // ulz[0] ^ + // ^ oldfz + // ulz[1] ^ + // ^ | + // minfloorz ---| + + ulz[0] = oldfz - swsecheight*((double)(oldfz-maxceilz)/(minfloorz-maxceilz)); + ulz[0] &= ~255; + ulz[1] = ulz[0] + swsecheight; + + if (maxceilz >= ulz[0] || ulz[0] >= ulz[1] || ulz[1] >= minfloorz) + { + message("Too little z headroom for sandwiching"); +// message("Internal error while sandwiching: z values wrong"); goto end_yax; } } @@ -3254,11 +3381,32 @@ void overheadeditor(void) numwalls = m; goto end_yax; } + if (sandwichbunch >= 0) + { + if (YAX_NEXTWALL(j, cf) < 0) + { + message("Internal error while sandwiching (2): " + "YAX_NEXTWALL(%d, %d)<0!", j, cf); + numwalls = m; + goto end_yax; + } + } } for (i=m; i= 0) + { + int16_t oynw = YAX_NEXTWALL(j, cf); + yax_setnextwall(j, cf, i); + yax_setnextwall(i, cf, oynw); + yax_setnextwall(oynw, !cf, i); + } + else + { + yax_setnextwall(j, cf, i); + } } // create new sector based on first highlighted one @@ -3267,20 +3415,32 @@ void overheadeditor(void) sector[numsectors].wallptr = m; sector[numsectors].wallnum = numwalls-m; - if (SECTORFLD(i,stat, cf)&2) - setslope(numsectors, !cf, SECTORFLD(i,heinum, cf)); + if (sandwichbunch < 0) + { + if (SECTORFLD(i,stat, cf)&2) + setslope(numsectors, !cf, SECTORFLD(i,heinum, cf)); + else + setslope(numsectors, !cf, 0); + setslope(numsectors, cf, 0); + + SECTORFLD(numsectors,z, !cf) = SECTORFLD(i,z, cf); + SECTORFLD(numsectors,z, cf) = SECTORFLD(i,z, cf) - (1-2*cf)*DEFAULT_YAX_HEIGHT; + } else - setslope(numsectors, !cf, 0); - setslope(numsectors, cf, 0); - - SECTORFLD(numsectors,stat, !cf) &= ~1; // no plax - - SECTORFLD(numsectors,z, !cf) = SECTORFLD(i,z, cf); - SECTORFLD(numsectors,z, cf) = SECTORFLD(i,z, cf) - (1-2*cf)*DEFAULT_YAX_HEIGHT; + { + for (SECTORS_OF_BUNCH(sandwichbunch, cf, i)) + sector[i].floorz = ulz[0]; + sector[numsectors].ceilingz = ulz[0]; + sector[numsectors].floorz = ulz[1]; + for (SECTORS_OF_BUNCH(sandwichbunch, !cf, i)) + sector[i].ceilingz = ulz[1]; + } newnumwalls = numwalls; numwalls = m; + SECTORFLD(numsectors,stat, !cf) &= ~1; // no plax + // restore red walls of the selected sectors for (i=0; i>3]; + Bmemset(bunchbitmap, 0, sizeof(bunchbitmap)); +#endif if (!m32_sideview) { getpoint(highlightx1,highlighty1, &highlightx1,&highlighty1); @@ -3757,21 +3937,20 @@ end_yax: ; if (bad == 0) { - if (sub) +#ifdef YAX_ENABLE + if (bunchsel!=-1 && (fb = yax_getbunch(i, YAX_FLOOR))>=0) { - hlsectorbitmap[i>>3] &= ~(1<<(i&7)); - for (j=sector[i].wallptr; j>3]&(1<<(i&7)))==0) && + (bunchbitmap[fb>>3]&(1<<(fb&7)))==0) { - if (wall[j].nextwall >= 0) - checksectorpointer(wall[j].nextwall,wall[j].nextsector); - checksectorpointer(j, i); + bunchbitmap[fb>>3] |= (1<<(fb&7)); + for (SECTORS_OF_BUNCH(fb, bunchsel, j)) + handlesecthighlight1(j, sub, 1); } } else - { - if ((graysectbitmap[i>>3]&(1<<(i&7)))==0) - hlsectorbitmap[i>>3] |= (1<<(i&7)); - } +#endif + handlesecthighlight1(i, sub, 0); } } @@ -4475,12 +4654,14 @@ end_point_dragging: if (needsdisp) { - // a component can be displaced if it's not extended on the non-joining side + // a component is more likely to be displaced if it's not + // extended on the non-joining side movestat = (!(compstat[0][!joinstat]&1)) | ((!(compstat[1][joinstat]&1))<<1); if (!movestat) { - message("Internal error while TROR-joining: movestat inconsistent!"); - goto end_join_sectors; + movestat = 3; +// message("Internal error while TROR-joining: movestat inconsistent!"); +// goto end_join_sectors; } if (movestat==3) @@ -5669,35 +5850,37 @@ end_space_handling: for (i=0; i= 0) + if (highlightsectorcnt > 0) { - for (j=0; j>3]&(1<<(i&7)))) + { + for (j=highlightsectorcnt-1; j>=0; j--) { - for (j=highlightsectorcnt-1; j>=0; j--) - { #ifdef YAX_ENABLE - yax_getbunches(highlightsector[j], &cb, &fb); - if (cb>=0) hlsectorbitmap[cb>>3] |= (1<<(cb&7)); - if (fb>=0) hlsectorbitmap[fb>>3] |= (1<<(fb&7)); + yax_getbunches(highlightsector[j], &cb, &fb); + if (cb>=0) hlsectorbitmap[cb>>3] |= (1<<(cb&7)); + if (fb>=0) hlsectorbitmap[fb>>3] |= (1<<(fb&7)); #endif - deletesector(highlightsector[j]); - for (k=j-1; k>=0; k--) - if (highlightsector[k] >= highlightsector[j]) - highlightsector[k]--; - } - - printmessage16("Highlighted sectors deleted."); - mkonwinvalid(); - k = 1; - break; + deletesector(highlightsector[j]); + for (k=j-1; k>=0; k--) + if (highlightsector[k] >= highlightsector[j]) + highlightsector[k]--; } + + printmessage16("Highlighted sectors deleted."); + mkonwinvalid(); + k = 1; + } } if (k == 0) @@ -6187,8 +6370,11 @@ CANCEL: bad = 0; if (CheckMapCorruption(4, 0)>=4) + { + fade_editor_screen(-1); if (!ask_if_sure("Map is corrupt. Are you sure you want to save? (Y/N)", 0)) break; + } _printmessage16("Saving board..."); showframe(1); diff --git a/polymer/eduke32/build/src/engine.c b/polymer/eduke32/build/src/engine.c index 845aa43f1..764157a0e 100644 --- a/polymer/eduke32/build/src/engine.c +++ b/polymer/eduke32/build/src/engine.c @@ -14113,7 +14113,7 @@ void draw2dgrid(int32_t posxe, int32_t posye, int32_t posze, int16_t cursectnum, } -static void drawscreen_drawwall(int32_t i, int32_t posxe, int32_t posye, int32_t posze, int32_t zoome) +static void drawscreen_drawwall(int32_t i, int32_t posxe, int32_t posye, int32_t posze, int32_t zoome, int32_t grayp) { const walltype *wal = &wall[i]; int32_t sect=0, j, x1, y1, x2, y2, dz = 0, dz2 = 0; @@ -14123,20 +14123,21 @@ static void drawscreen_drawwall(int32_t i, int32_t posxe, int32_t posye, int32_t int64_t dist,dx,dy; + j = wal->nextwall; +#if 0 if (editstatus == 0) { if ((show2dwall[i>>3]&pow2char[i&7]) == 0) return; - j = wal->nextwall; if ((j >= 0) && (i > j)) if ((show2dwall[j>>3]&pow2char[j&7]) > 0) return; } else +#endif { - j = wal->nextwall; if (!m32_sideview && (j >= 0) && (i > j)) return; } - if ((graywallbitmap[i>>3] & (1<<(i&7))) || (j>=0 && (graywallbitmap[j>>3] & (1<<(j&7))))) + if (grayp) { col = 8; } @@ -14476,6 +14477,7 @@ void draw2dscreen(const vec3_t *pos, int16_t cursectnum, int16_t ange, int32_t z int16_t angofs = m32_sideview ? m32_sideang : 0; int32_t posxe=pos->x, posye=pos->y, posze=pos->z; + uint8_t *graybitmap = (uint8_t *)tempbuf; if (qsetmode == 200) return; @@ -14497,16 +14499,31 @@ void draw2dscreen(const vec3_t *pos, int16_t cursectnum, int16_t ange, int32_t z m32_swcnt = 0; + if (numgraysects==0) + Bmemset(graybitmap, 0, (numwalls+7)>>3); + else + { + for (i=0; i>3]&(1<<(i&7))) || + ((j=wall[i].nextwall)>=0 && (graywallbitmap[j>>3]&(1<<(j&7))))) + graybitmap[i>>3] |= (1<<(i&7)); + else + graybitmap[i>>3] &= ~(1<<(i&7)); + } + } + if (!m32_sideview) { + for (i=numwalls-1; i>=0; i--) #ifdef YAX_ENABLE - if (graywallbitmap[i>>3]&(1<<(i&7))) - drawscreen_drawwall(i,posxe,posye,posze,zoome); + if (graybitmap[i>>3]&(1<<(i&7))) + drawscreen_drawwall(i,posxe,posye,posze,zoome, 1); for (i=numwalls-1; i>=0; i--) - if ((graywallbitmap[i>>3]&(1<<(i&7)))==0) + if ((graybitmap[i>>3]&(1<<(i&7)))==0) #endif - drawscreen_drawwall(i,posxe,posye,posze,zoome); + drawscreen_drawwall(i,posxe,posye,posze,zoome, 0); } else { @@ -14557,7 +14574,7 @@ void draw2dscreen(const vec3_t *pos, int16_t cursectnum, int16_t ange, int32_t z { j = m32_wallsprite[i]; if (j>3]&(1<<(j&7)))); else drawscreen_drawsprite(j-MAXWALLS,posxe,posye,posze,zoome); } diff --git a/polymer/eduke32/source/astub.c b/polymer/eduke32/source/astub.c index 00f8f2cbc..8cc0bc4a9 100644 --- a/polymer/eduke32/source/astub.c +++ b/polymer/eduke32/source/astub.c @@ -199,6 +199,30 @@ static int32_t yax_invalidop() return 0; } +static int32_t yax_invalidslope() +{ + silentmessage("Firstwalls must coincide for changing slope."); + return 0; +} + +// 1: ok +static int32_t yax_checkslope(int16_t sectnum, int32_t othersectnum) +{ + int16_t w1 = sector[sectnum].wallptr, w2 = wall[w1].point2; + int16_t nw1 = sector[othersectnum].wallptr, nw2 = wall[nw1].point2; + + if (nw1 < 0) + return 0; // error + + nw2 = wall[nw1].point2; + if (wall[w1].x != wall[nw1].x || wall[w1].y != wall[nw1].y || + wall[w2].x != wall[nw2].x || wall[w2].y != wall[nw2].y) + return 0; + + return 1; +} + +# define YAXSLOPECHK(s,os) (yax_checkslope(s,os) || yax_invalidslope()) # define YAXCHK(p) ((p) || yax_invalidop()) #endif @@ -5650,11 +5674,7 @@ static void Keys3d(void) if (eitherALT) //ALT-F (relative alignmment flip) { if (!AIMING_AT_SPRITE && ASSERT_AIMING) - { - setfirstwall(searchsector, searchwall); - message("Sector %d first wall", searchsector); - asksave = 1; - } + SetFirstWall(searchsector, searchwall); } else { @@ -6426,7 +6446,8 @@ static void Keys3d(void) if (AIMING_AT_CEILING || (tsign < 0 && AIMING_AT_WALL_OR_MASK)) #ifdef YAX_ENABLE if (YAXCHK((bunchnum=yax_getbunch(searchsector, YAX_CEILING)) < 0 || - (othersidesect=yax_is121(bunchnum, 1))>=0)) + (othersidesect=yax_is121(bunchnum, 1))>=0) && + (bunchnum < 0 || YAXSLOPECHK(searchsector, othersidesect))) #endif { alignceilslope(searchsector, sx, sy, getceilzofslope(ns, sx, sy)); @@ -6440,7 +6461,8 @@ static void Keys3d(void) if (AIMING_AT_FLOOR || (tsign > 0 && AIMING_AT_WALL_OR_MASK)) #ifdef YAX_ENABLE if (YAXCHK((bunchnum=yax_getbunch(searchsector, YAX_FLOOR)) < 0 || - (othersidesect=yax_is121(bunchnum, 0))>=0)) + (othersidesect=yax_is121(bunchnum, 0))>=0) && + (bunchnum < 0 || YAXSLOPECHK(searchsector, othersidesect))) #endif { alignflorslope(searchsector, sx, sy, getflorzofslope(ns, sx, sy)); @@ -6457,7 +6479,8 @@ static void Keys3d(void) if (AIMING_AT_CEILING_OR_FLOOR) #ifdef YAX_ENABLE if (YAXCHK((bunchnum=yax_getbunch(searchsector, AIMING_AT_FLOOR)) < 0 || - (othersidesect=yax_is121(bunchnum, AIMING_AT_CEILING))>=0)) + (othersidesect=yax_is121(bunchnum, AIMING_AT_CEILING))>=0) && + (bunchnum < 0 || YAXSLOPECHK(searchsector, othersidesect))) #endif { int32_t newslope = clamp(AIMED_CEILINGFLOOR(heinum) + tsign*i, -BHEINUM_MAX, BHEINUM_MAX); @@ -10999,7 +11022,7 @@ void ExtCheckKeys(void) bad = max(bad, errlev); \ if (numcorruptthings>=MAXCORRUPTTHINGS) \ goto too_many_errors; \ - corruptthings[numcorruptthings++] = what; \ + corruptthings[numcorruptthings++] = (what); \ if (errlev >= printfromlev) \ OSD_Printf("#%d: " fmt "\n", numcorruptthings, ## __VA_ARGS__); \ } while (0) @@ -11119,6 +11142,7 @@ int32_t CheckMapCorruption(int32_t printfromlev, uint64_t tryfixing) if (nw>=w0 && nw<=endwall) CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTWALL is its own sector's wall", j); + #ifdef YAX_ENABLE { int32_t cf, ynw, jp2, ynwp2; @@ -11180,13 +11204,29 @@ int32_t CheckMapCorruption(int32_t printfromlev, uint64_t tryfixing) if (!bad) { int32_t onumct = numcorruptthings; + int32_t safetoclear = (nw==j || (wall[nw].nextwall==-1 && wall[nw].nextsector==-1)); + CORRUPTCHK_PRINT(4, CORRUPT_WALL|j, "WALL[%d].NEXTSECTOR is its own sector", j); if (onumct < MAXCORRUPTTHINGS) { if (tryfixing & (1ull<=printfromlev) - suggest_nextsector_correction(nw, j); + { + if (safetoclear) + OSD_Printf(" will clear wall %d's nextwall and nextsector on tryfix\n", j); + else + suggest_nextsector_correction(nw, j); + } } } }