mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-24 10:40:46 +00:00
Ability to duplicate an inner loop in a neighboring TROR sector.
Called 'loop punching'. In addition to duplicating the loop, the inner portions of the original and cloned loop are made into a new bunch, and the loop walls are made to be neighbors, linking their movement to each other. This gives a way to create island sectors with a differing bunchnum in the midst of an already extended area. Usage: For an extended sector containing a CCW inner loop, select its points using Ctrl+Shift. Press Ctrl-E to be queried whether to duplicate the points into the upper or lower extension (even if it's unambiguous). A number of conditions must be met for a successful 'punch', which should hopefully be more or less obvious. Among them: - loop walls should all be red - the starting wall is only considered among the non-grayed-out ones - the neighboring sector must not contain points inside or at the loop git-svn-id: https://svn.eduke32.com/eduke32@2130 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
f4d81d7975
commit
ee30112c38
1 changed files with 265 additions and 10 deletions
|
@ -177,6 +177,9 @@ static char scantoascwithshift[128] =
|
||||||
|
|
||||||
#define DOWN_BK(BuildKey) (keystatus[buildkeys[BK_##BuildKey]])
|
#define DOWN_BK(BuildKey) (keystatus[buildkeys[BK_##BuildKey]])
|
||||||
|
|
||||||
|
#define CLOCKDIR_CW 0
|
||||||
|
#define CLOCKDIR_CCW 1
|
||||||
|
|
||||||
int32_t pk_turnaccel=16;
|
int32_t pk_turnaccel=16;
|
||||||
int32_t pk_turndecel=12;
|
int32_t pk_turndecel=12;
|
||||||
int32_t pk_uedaccel=3;
|
int32_t pk_uedaccel=3;
|
||||||
|
@ -2643,10 +2646,13 @@ static int32_t vec2eq(const vec2_t *v1, const vec2_t *v2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// precondition: [numwalls, newnumwalls-1] form a new loop (may be of wrong orientation)
|
// precondition: [numwalls, newnumwalls-1] form a new loop (may be of wrong orientation)
|
||||||
|
// ret_ofirstwallofs: if != NULL, *ret_ofirstwallofs will contain the offset of the old
|
||||||
|
// first wall from the new first wall of the sector k, and the automatic
|
||||||
|
// restoring of the old first wll will not be carried out
|
||||||
// returns:
|
// returns:
|
||||||
// -1, -2: errors
|
// -1, -2: errors
|
||||||
// 0, 1: OK, 1 means it was an extended sector and an inner loop has been added automatically
|
// 0, 1: OK, 1 means it was an extended sector and an inner loop has been added automatically
|
||||||
static int32_t AddLoopToSector(int32_t k)
|
static int32_t AddLoopToSector(int32_t k, int32_t *ret_ofirstwallofs)
|
||||||
{
|
{
|
||||||
int32_t extendedSector=0, firstwall, i, j;
|
int32_t extendedSector=0, firstwall, i, j;
|
||||||
#ifdef YAX_ENABLE
|
#ifdef YAX_ENABLE
|
||||||
|
@ -2678,7 +2684,7 @@ static int32_t AddLoopToSector(int32_t k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (clockdir(numwalls) == 0)
|
if (clockdir(numwalls) == CLOCKDIR_CW)
|
||||||
flipwalls(numwalls,newnumwalls);
|
flipwalls(numwalls,newnumwalls);
|
||||||
|
|
||||||
sector[k].wallnum += j;
|
sector[k].wallnum += j;
|
||||||
|
@ -2730,11 +2736,17 @@ static int32_t AddLoopToSector(int32_t k)
|
||||||
numsectors++;
|
numsectors++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
setfirstwall(k, firstwall+j); // restore old first wall
|
if (ret_ofirstwallofs)
|
||||||
|
*ret_ofirstwallofs = j;
|
||||||
|
else
|
||||||
|
setfirstwall(k, firstwall+j); // restore old first wall
|
||||||
|
|
||||||
return extendedSector;
|
return extendedSector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define EDITING_MAP_P() (newnumwalls>=0 || joinsector[0]>=0 || circlewall>=0 || (bstatus&1))
|
||||||
|
|
||||||
|
|
||||||
void overheadeditor(void)
|
void overheadeditor(void)
|
||||||
{
|
{
|
||||||
char buffer[80];
|
char buffer[80];
|
||||||
|
@ -3837,8 +3849,248 @@ void overheadeditor(void)
|
||||||
message("Sandwiched bunch %d, creating bunch %d",
|
message("Sandwiched bunch %d, creating bunch %d",
|
||||||
sandwichbunch, numyaxbunches-1);
|
sandwichbunch, numyaxbunches-1);
|
||||||
asksave = 1;
|
asksave = 1;
|
||||||
end_yax: ;
|
|
||||||
}
|
}
|
||||||
|
else if (highlightcnt > 0)
|
||||||
|
{
|
||||||
|
/// 'punch' wall loop through extension
|
||||||
|
|
||||||
|
int32_t loopstartwall = -1, numloopwalls, cf;
|
||||||
|
int32_t srcsect, dstsect, ofirstwallofs;
|
||||||
|
int16_t cb, fb, bunchnum;
|
||||||
|
|
||||||
|
if (EDITING_MAP_P())
|
||||||
|
{
|
||||||
|
printmessage16("Must not be editing map to punch loop");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numyaxbunches >= YAX_MAXBUNCHES)
|
||||||
|
{
|
||||||
|
message("TROR bunch limit reached, cannot punch loop");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine start wall
|
||||||
|
for (i=0; i<highlightcnt; i++)
|
||||||
|
if ((highlight[i]&16384)==0 && clockdir(highlight[i])==CLOCKDIR_CCW)
|
||||||
|
{
|
||||||
|
YAX_SKIPWALL(highlight[i]);
|
||||||
|
|
||||||
|
if (loopstartwall >= 0)
|
||||||
|
{
|
||||||
|
message("Must have a unique highlighted CCW loop to punch");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
|
||||||
|
loopstartwall = highlight[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loopstartwall == -1)
|
||||||
|
{
|
||||||
|
message("Didn't find any non-grayed out loop start walls");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine sector
|
||||||
|
srcsect = sectorofwall(loopstartwall);
|
||||||
|
yax_getbunches(srcsect, &cb, &fb);
|
||||||
|
if (cb < 0 && fb < 0)
|
||||||
|
{
|
||||||
|
message("Ceiling or floor must be extended to punch loop");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// determine c/f
|
||||||
|
cf = -1;
|
||||||
|
if (fb < 0)
|
||||||
|
cf = YAX_CEILING;
|
||||||
|
else if (cb < 0)
|
||||||
|
cf = YAX_FLOOR;
|
||||||
|
|
||||||
|
// query top/bottom
|
||||||
|
if (cf == -1)
|
||||||
|
{
|
||||||
|
char dachars[2] = {'a', 'z'};
|
||||||
|
cf = editor_ask_function("Punch loop above (a) or below (z)?", dachars, 2);
|
||||||
|
if (cf == -1)
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ask even if only one choice -- I find it more
|
||||||
|
// consistent with 'extend sector' this way
|
||||||
|
if (-1 == editor_ask_function(cf==YAX_CEILING ? "Punch loop above (a)?" :
|
||||||
|
"Punch loop below (z)?", cf==YAX_CEILING?"a":"z", 1))
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
|
||||||
|
bunchnum = (cf==YAX_CEILING) ? cb : fb;
|
||||||
|
|
||||||
|
// check 1
|
||||||
|
j = loopstartwall; // will be real start wall of loop
|
||||||
|
numloopwalls = 1; // will be number of walls in loop
|
||||||
|
for (i=wall[loopstartwall].point2; i!=loopstartwall; i=wall[i].point2)
|
||||||
|
{
|
||||||
|
numloopwalls++;
|
||||||
|
if (i < j)
|
||||||
|
j = i;
|
||||||
|
|
||||||
|
if ((show2dwall[i>>3]&(1<<(i&7)))==0)
|
||||||
|
{
|
||||||
|
message("All loop points must be highlighted to punch");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yax_getnextwall(loopstartwall, cf) >= 0 || yax_getnextwall(i, cf) >= 0)
|
||||||
|
{
|
||||||
|
// somewhat redundant, since it would also be caught by check 2
|
||||||
|
message("Loop walls must not already have TROR neighbors");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wall[loopstartwall].nextwall < 0 || wall[i].nextwall < 0)
|
||||||
|
{
|
||||||
|
message("INTERNAL ERROR: All loop walls are expected to be red");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loopstartwall = j;
|
||||||
|
|
||||||
|
if (numwalls + 2*numloopwalls > MAXWALLS || numsectors+1 > MAXSECTORS)
|
||||||
|
{
|
||||||
|
message("Punching loop through extension would exceed limits");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get other-side sector, j==loopstartwall
|
||||||
|
dstsect = yax_getneighborsect(wall[j].x, wall[j].y, srcsect, cf, NULL);
|
||||||
|
if (dstsect < 0)
|
||||||
|
{
|
||||||
|
message("Punch loop INTERNAL ERROR: dstsect < 0. Map corrupt?");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check 2
|
||||||
|
i = loopstartwall;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
j = wall[i].point2;
|
||||||
|
|
||||||
|
for (WALLS_OF_SECTOR(dstsect, k))
|
||||||
|
{
|
||||||
|
vec2_t pint;
|
||||||
|
if (lineintersect2v((vec2_t *)&wall[i], (vec2_t *)&wall[j],
|
||||||
|
(vec2_t *)&wall[k], (vec2_t *)&POINT2(k), &pint))
|
||||||
|
{
|
||||||
|
message("Loop lines must not intersect any destination sector's walls");
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((i = j) != loopstartwall);
|
||||||
|
|
||||||
|
// construct new loop and (dummy yet) sector
|
||||||
|
Bmemcpy(&wall[numwalls], &wall[loopstartwall], numloopwalls*sizeof(walltype));
|
||||||
|
newnumwalls = numwalls+numloopwalls;
|
||||||
|
|
||||||
|
for (i=numwalls; i<newnumwalls; i++)
|
||||||
|
{
|
||||||
|
wall[i].point2 += (numwalls - loopstartwall);
|
||||||
|
wall[i].nextsector = wall[i].nextwall = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sector[numsectors].wallptr = numwalls;
|
||||||
|
sector[numsectors].wallnum = numloopwalls;
|
||||||
|
numsectors++; // temp
|
||||||
|
|
||||||
|
// check 3
|
||||||
|
for (SECTORS_OF_BUNCH(bunchnum, !cf, i))
|
||||||
|
for (WALLS_OF_SECTOR(i, j))
|
||||||
|
{
|
||||||
|
if (inside(wall[i].x, wall[i].y, numsectors-1)==1)
|
||||||
|
{
|
||||||
|
numsectors--;
|
||||||
|
newnumwalls = -1;
|
||||||
|
message("A point of bunch %d's sectors lies inside the loop to punch",
|
||||||
|
bunchnum);
|
||||||
|
goto end_yax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
numsectors--;
|
||||||
|
|
||||||
|
// clear wall & sprite highlights
|
||||||
|
// TODO: see about consistency with update_highlight() after other ops
|
||||||
|
Bmemset(show2dwall, 0, sizeof(show2dwall));
|
||||||
|
Bmemset(show2dsprite, 0, sizeof(show2dsprite));
|
||||||
|
update_highlight();
|
||||||
|
|
||||||
|
// construct the loop!
|
||||||
|
i = AddLoopToSector(dstsect, &ofirstwallofs);
|
||||||
|
|
||||||
|
if (i <= 0)
|
||||||
|
{
|
||||||
|
message("Punch loop INTERNAL ERROR with AddLoopToSector!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int32_t oneinnersect = -1, innerdstsect = numsectors-1;
|
||||||
|
|
||||||
|
if (dstsect < srcsect)
|
||||||
|
loopstartwall += numloopwalls;
|
||||||
|
|
||||||
|
/// handle bunchnums! (specifically, create a new one)
|
||||||
|
|
||||||
|
// collect sectors inside source loop; for that, first break the
|
||||||
|
// inner->outer nextwall links
|
||||||
|
for (i=loopstartwall; i<loopstartwall+numloopwalls; i++)
|
||||||
|
{
|
||||||
|
// all src loop walls are red!
|
||||||
|
NEXTWALL(i).nextwall = NEXTWALL(i).nextsector = -1;
|
||||||
|
oneinnersect = wall[i].nextsector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vvv
|
||||||
|
// expect oneinnersect >= 0 here! Assumption: we collect exactly
|
||||||
|
// one connected component of sectors
|
||||||
|
collect_sectors1(collsectlist[0], collsectbitmap[0],
|
||||||
|
&collnumsects[0], oneinnersect, 0, 0);
|
||||||
|
|
||||||
|
// set new bunchnums
|
||||||
|
for (i=0; i<collnumsects[0]; i++)
|
||||||
|
yax_setbunch(collsectlist[0][i], cf, numyaxbunches);
|
||||||
|
yax_setbunch(innerdstsect, !cf, numyaxbunches);
|
||||||
|
// ^^^
|
||||||
|
|
||||||
|
// restore inner->outer nextwall links
|
||||||
|
for (i=loopstartwall; i<loopstartwall+numloopwalls; i++)
|
||||||
|
{
|
||||||
|
NEXTWALL(i).nextwall = i;
|
||||||
|
NEXTWALL(i).nextsector = srcsect;
|
||||||
|
|
||||||
|
// set yax-nextwalls!
|
||||||
|
j = (i-loopstartwall) + sector[dstsect].wallptr;
|
||||||
|
yax_setnextwall(i, cf, j);
|
||||||
|
yax_setnextwall(j, !cf, i);
|
||||||
|
|
||||||
|
yax_setnextwall(wall[i].nextwall, cf, wall[j].nextwall);
|
||||||
|
yax_setnextwall(wall[j].nextwall, !cf, wall[i].nextwall);
|
||||||
|
}
|
||||||
|
|
||||||
|
setfirstwall(dstsect, sector[dstsect].wallptr+ofirstwallofs);
|
||||||
|
|
||||||
|
message("Punched loop starting w/ wall %d into %s sector %d%s",
|
||||||
|
loopstartwall, cf==YAX_CEILING?"upper":"lower", dstsect,
|
||||||
|
(oneinnersect>=0) ? "" : " (ERRORS)");
|
||||||
|
}
|
||||||
|
|
||||||
|
mkonwinvalid();
|
||||||
|
asksave = 1;
|
||||||
|
|
||||||
|
yax_update(0);
|
||||||
|
yax_updategrays(pos.z);
|
||||||
|
}
|
||||||
|
end_yax: ;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3903,6 +4155,9 @@ end_yax: ;
|
||||||
else
|
else
|
||||||
show2dwall[i>>3] &= ~(1<<(i&7));
|
show2dwall[i>>3] &= ~(1<<(i&7));
|
||||||
|
|
||||||
|
// XXX: this selects too many walls, need something more like
|
||||||
|
// those of dragpoint() -- could be still too many for
|
||||||
|
// loop punching though
|
||||||
for (j=0; j<numwalls; j++)
|
for (j=0; j<numwalls; j++)
|
||||||
if (j!=i && wall[j].x==wall[i].x && wall[j].y==wall[i].y)
|
if (j!=i && wall[j].x==wall[i].x && wall[j].y==wall[i].y)
|
||||||
{
|
{
|
||||||
|
@ -4179,7 +4434,7 @@ end_yax: ;
|
||||||
newnumwalls = k;
|
newnumwalls = k;
|
||||||
n = (newnumwalls-numwalls); // number of walls in just constructed loop
|
n = (newnumwalls-numwalls); // number of walls in just constructed loop
|
||||||
|
|
||||||
if (clockdir(numwalls)==0)
|
if (clockdir(numwalls)==CLOCKDIR_CW)
|
||||||
{
|
{
|
||||||
int16_t begwalltomove = sector[refsect].wallptr+sector[refsect].wallnum;
|
int16_t begwalltomove = sector[refsect].wallptr+sector[refsect].wallnum;
|
||||||
int32_t onwwasvalid = onwisvalid();
|
int32_t onwwasvalid = onwisvalid();
|
||||||
|
@ -4805,7 +5060,7 @@ end_point_dragging:
|
||||||
if (keystatus[0x3d]) // F3
|
if (keystatus[0x3d]) // F3
|
||||||
{
|
{
|
||||||
keystatus[0x3d]=0;
|
keystatus[0x3d]=0;
|
||||||
if (!m32_sideview && (newnumwalls>=0 || joinsector[0]>=0 || circlewall>=0 || (bstatus&1)))
|
if (!m32_sideview && EDITING_MAP_P())
|
||||||
message("Must not be editing map while switching to side view mode.");
|
message("Must not be editing map while switching to side view mode.");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -6010,7 +6265,7 @@ check_next_sector: ;
|
||||||
if (k == -1) //if not inside another sector either
|
if (k == -1) //if not inside another sector either
|
||||||
{
|
{
|
||||||
//add island sector
|
//add island sector
|
||||||
if (clockdir(numwalls) == 1)
|
if (clockdir(numwalls) == CLOCKDIR_CCW)
|
||||||
flipwalls(numwalls,newnumwalls);
|
flipwalls(numwalls,newnumwalls);
|
||||||
|
|
||||||
Bmemset(§or[numsectors], 0, sizeof(sectortype));
|
Bmemset(§or[numsectors], 0, sizeof(sectortype));
|
||||||
|
@ -6036,7 +6291,7 @@ check_next_sector: ;
|
||||||
}
|
}
|
||||||
else //else add loop to sector
|
else //else add loop to sector
|
||||||
{
|
{
|
||||||
int32_t ret = AddLoopToSector(k);
|
int32_t ret = AddLoopToSector(k, NULL);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto end_space_handling;
|
goto end_space_handling;
|
||||||
|
@ -6056,7 +6311,7 @@ check_next_sector: ;
|
||||||
|
|
||||||
//add new sector with connections
|
//add new sector with connections
|
||||||
|
|
||||||
if (clockdir(numwalls) == 1)
|
if (clockdir(numwalls) == CLOCKDIR_CCW)
|
||||||
flipwalls(numwalls,newnumwalls);
|
flipwalls(numwalls,newnumwalls);
|
||||||
|
|
||||||
for (i=numwalls; i<newnumwalls; i++)
|
for (i=numwalls; i<newnumwalls; i++)
|
||||||
|
@ -9003,7 +9258,7 @@ static int16_t whitelinescan(int16_t sucksect, int16_t dalinehighlight)
|
||||||
wall[i].point2 = i+1;
|
wall[i].point2 = i+1;
|
||||||
wall[tnewnumwalls-1].point2 = numwalls;
|
wall[tnewnumwalls-1].point2 = numwalls;
|
||||||
|
|
||||||
if (clockdir(numwalls) == 1)
|
if (clockdir(numwalls) == CLOCKDIR_CCW)
|
||||||
return(-1);
|
return(-1);
|
||||||
else
|
else
|
||||||
return(tnewnumwalls);
|
return(tnewnumwalls);
|
||||||
|
|
Loading…
Reference in a new issue