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); + } } } }