Subversion Repositories eduke32

Rev

Rev 8490 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
2
// Ken Silverman's official web site: "http://www.advsys.net/ken"
3
// See the included license file "BUILDLIC.TXT" for license info.
4
//
5
// This file has been modified from Ken Silverman's original release
2456 hendricks2 6
// by Jonathon Fowler (jf@jonof.id.au)
7139 hendricks2 7
// by the EDuke32 team (development@voidpoint.com)
5 Plagman 8
 
9
#include "build.h"
7818 terminx 10
 
11
#include "baselayer.h"
12
#include "cache1d.h"
13
#include "colmatch.h"
14
#include "common.h"
5 Plagman 15
#include "compat.h"
7818 terminx 16
#include "editor.h"
17
#include "m32script.h"
5 Plagman 18
#include "osd.h"
5789 terminx 19
#include "palette.h"
7818 terminx 20
#include "pragmas.h"
21
#include "renderlayer.h"
6860 terminx 22
#include "scancodes.h"
7359 hendricks2 23
#include "vfs.h"
24
 
3221 hendricks2 25
#ifdef _WIN32
7818 terminx 26
#include "winbits.h"
5 Plagman 27
#endif
28
 
4557 hendricks2 29
char levelname[BMAX_PATH] = {0};
30
 
1205 terminx 31
#define updatecrc16(crc,dat) (crc = (((crc<<8)&65535)^crctable[((((uint16_t)crc)>>8)&65535)^dat]))
32
static int32_t crctable[256];
1101 terminx 33
static char kensig[64];
5 Plagman 34
 
4555 hendricks2 35
static const char *CallExtGetVer(void);
36
static int32_t CallExtInit(void);
5552 hendricks2 37
static int32_t CallExtPreInit(int32_t argc,char const * const * argv);
4557 hendricks2 38
static int32_t CallExtPostStartupWindow(void);
5345 hendricks2 39
static void CallExtPostInit(void);
4555 hendricks2 40
static void CallExtUnInit(void);
41
static void CallExtPreCheckKeys(void);
8428 hendricks2 42
static void CallExtAnalyzeSprites(int32_t, int32_t, int32_t, int32_t, int32_t);
4555 hendricks2 43
static void CallExtCheckKeys(void);
44
static void CallExtPreLoadMap(void);
45
static void CallExtSetupMapFilename(const char *mapname);
46
static void CallExtLoadMap(const char *mapname);
47
static int32_t CallExtPreSaveMap(void);
48
static void CallExtSaveMap(const char *mapname);
5290 terminx 49
static inline const char *CallExtGetSectorCaption(int16_t sectnum) { return ExtGetSectorCaption(sectnum); }
50
static inline const char *CallExtGetWallCaption(int16_t wallnum) { return ExtGetWallCaption(wallnum); }
51
static inline const char *CallExtGetSpriteCaption(int16_t spritenum) { return ExtGetSpriteCaption(spritenum); }
4555 hendricks2 52
static void CallExtShowSectorData(int16_t sectnum);
53
static void CallExtShowWallData(int16_t wallnum);
54
static void CallExtShowSpriteData(int16_t spritenum);
55
static void CallExtEditSectorData(int16_t sectnum);
56
static void CallExtEditWallData(int16_t wallnum);
57
static void CallExtEditSpriteData(int16_t spritenum);
58
// static const char *CallExtGetSectorType(int32_t lotag);
5 Plagman 59
 
2028 helixhorne 60
int8_t m32_clipping=2;
2942 helixhorne 61
static int32_t m32_rotateang = 0;
5 Plagman 62
 
726 terminx 63
// 0   1     2     3      4       5      6      7
64
// up, down, left, right, lshift, rctrl, lctrl, space
65
// 8  9  10    11    12   13
66
// a, z, pgdn, pgup, [,], [.]
67
// 14       15     16 17 18   19
68
// kpenter, enter, =, -, tab, `
1205 terminx 69
uint8_t buildkeys[NUMBUILDKEYS] =
584 terminx 70
{
71
    0xc8,0xd0,0xcb,0xcd,0x2a,0x9d,0x1d,0x39,
72
    0x1e,0x2c,0xd1,0xc9,0x33,0x34,
73
    0x9c,0x1c,0xd,0xc,0xf,0x29
74
};
5 Plagman 75
 
3697 helixhorne 76
// Start position
77
vec3_t startpos;
78
int16_t startang, startsectnum;
79
 
80
// Current position
1208 terminx 81
vec3_t pos;
82
int32_t horiz = 100;
1205 terminx 83
int16_t ang, cursectnum;
3509 helixhorne 84
static int32_t hvel, vel, svel, angvel;
3532 helixhorne 85
int32_t g_doHardcodedMovement = 1;
5 Plagman 86
 
1886 helixhorne 87
static int32_t mousexsurp = 0, mouseysurp = 0;
4890 terminx 88
double msens = 1.0;
1886 helixhorne 89
 
1205 terminx 90
int32_t grponlymode = 0;
91
int32_t graphicsmode = 0;
5 Plagman 92
 
1205 terminx 93
int32_t synctics = 0, lockclock = 0;
5 Plagman 94
 
1679 helixhorne 95
// those ones save the respective 3d video vars while in 2d mode
96
// so that exiting from mapster32 in 2d mode saves the correct ones
4606 terminx 97
float vid_gamma_3d=-1, vid_contrast_3d=-1, vid_brightness_3d=-1;
1679 helixhorne 98
 
1205 terminx 99
int32_t xdim2d = 640, ydim2d = 480, xdimgame = 640, ydimgame = 480, bppgame = 8;
100
int32_t forcesetup = 1;
5 Plagman 101
 
3582 hendricks2 102
#ifndef GEKKO
8205 terminx 103
int32_t g_maxCacheSize = 128<<20;
3582 hendricks2 104
#else
105
int32_t g_maxCacheSize = 8<<20;
106
#endif
5 Plagman 107
 
1205 terminx 108
static int16_t oldmousebstatus = 0;
4558 hendricks2 109
 
110
char game_executable[BMAX_PATH] = {0};
111
 
2260 helixhorne 112
int32_t zlock = 0x7fffffff, zmode = 0, kensplayerheight = 32;
8440 hendricks2 113
int16_t defaultspritecstat = 0;
5 Plagman 114
 
1205 terminx 115
int16_t localartfreq[MAXTILES];
116
int16_t localartlookup[MAXTILES], localartlookupnum;
5 Plagman 117
 
118
char tempbuf[4096];
119
 
120
char names[MAXTILES][25];
1832 helixhorne 121
const char *g_namesFileName = "NAMES.H";
5 Plagman 122
 
1205 terminx 123
int16_t asksave = 0;
124
int32_t osearchx, osearchy;                               //old search input
5 Plagman 125
 
5281 terminx 126
int32_t grid = 0, autogrid = 1, gridlock = 1, showtags = 2;
127
int32_t zoom = 768, gettilezoom = 1, ztarget = 768;
1359 terminx 128
int32_t lastpm16time = 0;
5 Plagman 129
 
1205 terminx 130
extern int32_t mapversion;
5 Plagman 131
 
1733 helixhorne 132
int16_t highlight[MAXWALLS+MAXSPRITES];
1205 terminx 133
int16_t highlightsector[MAXSECTORS], highlightsectorcnt = -1;
5 Plagman 134
extern char textfont[128][8];
135
 
2715 helixhorne 136
int32_t tempsectornum = -1;  // for auto ceiling/floor alignment
137
int32_t temppicnum, tempcstat, templotag, temphitag, tempextra;
138
uint32_t temppal, tempvis, tempxrepeat, tempyrepeat, tempxpanning=0, tempypanning=0;
139
int32_t tempshade, tempxvel, tempyvel, tempzvel;
5925 terminx 140
int32_t tempstatnum=0, tempblend=0;
2715 helixhorne 141
char somethingintab = 255;
142
 
143
// Only valid when highlightsectorcnt>0 and no structural
1886 helixhorne 144
// modifications (deleting/inserting sectors or points, setting new firstwall)
2715 helixhorne 145
// have been made:
2119 helixhorne 146
static int16_t onextwall[MAXWALLS];  // onextwall[i]>=0 implies wall[i].nextwall < 0
1886 helixhorne 147
static void mkonwvalid(void) { chsecptr_onextwall = onextwall; }
2715 helixhorne 148
static void mkonwinvalid(void) { chsecptr_onextwall = NULL; tempsectornum=-1; }
2716 helixhorne 149
static void mkonwinvalid_keeptempsect(void) { chsecptr_onextwall = NULL; }
1886 helixhorne 150
static int32_t onwisvalid(void) { return chsecptr_onextwall != NULL; }
151
 
1843 helixhorne 152
int32_t mlook = 0, mskip=0;
1205 terminx 153
int32_t revertCTRL=0,scrollamount=3;
154
int32_t unrealedlook=1, quickmapcycling=1; //PK
5 Plagman 155
 
1361 terminx 156
char program_origcwd[BMAX_PATH];
1904 helixhorne 157
const char *mapster32_fullpath;
1361 terminx 158
char *testplay_addparam = 0;
159
 
5 Plagman 160
static char boardfilename[BMAX_PATH], selectedboardfilename[BMAX_PATH];
2096 helixhorne 161
//extern char levelname[BMAX_PATH];  // in astub.c   XXX: clean up this mess!!!
5 Plagman 162
 
4121 helixhorne 163
void B_SetBoardFileName(const char *fn)
164
{
165
    Bstrncpyz(boardfilename, fn, BMAX_PATH);
166
}
167
 
2556 helixhorne 168
static fnlist_t fnlist;
8199 terminx 169
static BUILDVFS_FIND_REC *finddirshigh=NULL, *findfileshigh=NULL;
1205 terminx 170
static int32_t currentlist=0;
5 Plagman 171
 
1205 terminx 172
//static int32_t repeatcountx, repeatcounty;
5 Plagman 173
 
1205 terminx 174
static int32_t fillist[640];
2132 helixhorne 175
// used for fillsector, batch point insertion, backup_highlighted_map
1930 helixhorne 176
static int32_t tempxyar[MAXWALLS][2];
5 Plagman 177
 
1644 helixhorne 178
static int32_t mousx, mousy;
1892 helixhorne 179
int16_t prefixtiles[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
7594 terminx 180
uint8_t hlsectorbitmap[(MAXSECTORS+7)>>3];  // show2dsector is already taken...
2144 helixhorne 181
static int32_t minhlsectorfloorz, numhlsecwalls;
5289 terminx 182
int32_t searchlock = 0;
1644 helixhorne 183
 
2787 helixhorne 184
// used for:
185
//  - hl_all_bunch_sectors_p
186
//  - AlignWalls
187
//  - trace_loop
7594 terminx 188
static uint8_t visited[(MAXWALLS+7)>>3];
1830 helixhorne 189
 
5281 terminx 190
int32_t m32_2d3dmode = 0;
191
int32_t m32_2d3dsize = 4;
6061 hendricks2 192
vec2_t m32_2d3d = { 0xffff, 4 };
5281 terminx 193
 
7435 terminx 194
int32_t m32_3dundo = 1;
195
 
1730 helixhorne 196
typedef struct
197
{
198
    int16_t numsectors, numwalls, numsprites;
2136 helixhorne 199
#ifdef YAX_ENABLE
200
    int16_t numyaxbunches;
201
    int16_t *bunchnum;  // [numsectors][2]
202
    int16_t *ynextwall;  // [numwalls][2]
203
#endif
5796 terminx 204
    usectortype *sector;
205
    uwalltype *wall;
206
    uspritetype *sprite;
1730 helixhorne 207
} mapinfofull_t;
208
 
2818 helixhorne 209
int32_t g_doScreenShot;
210
 
6860 terminx 211
#define eitherALT   (keystatus[sc_LeftAlt]|keystatus[sc_RightAlt])
212
#define eitherCTRL  (keystatus[sc_LeftControl]|keystatus[sc_RightControl])
213
#define eitherSHIFT (keystatus[sc_LeftShift]|keystatus[sc_RightShift])
1644 helixhorne 214
 
215
#define DOWN_BK(BuildKey) (keystatus[buildkeys[BK_##BuildKey]])
216
 
1205 terminx 217
int32_t pk_turnaccel=16;
218
int32_t pk_turndecel=12;
219
int32_t pk_uedaccel=3;
5 Plagman 220
 
3398 helixhorne 221
int8_t keeptexturestretch = 1;
1730 helixhorne 222
int8_t sideview_reversehrot = 0;
223
 
6318 hendricks2 224
int16_t pointhighlightdist = 256;
5568 terminx 225
int16_t linehighlightdist = 1024;
226
 
1372 helixhorne 227
char lastpm16buf[156];
1359 terminx 228
 
1760 helixhorne 229
//static int32_t checksectorpointer_warn = 0;
2110 helixhorne 230
static int32_t saveboard_savedtags, saveboard_fixedsprites;
3911 helixhorne 231
static int32_t saveboard_canceled;
1730 helixhorne 232
 
3697 helixhorne 233
static int32_t backup_highlighted_map(mapinfofull_t *mapinfo);
234
static int32_t restore_highlighted_map(mapinfofull_t *mapinfo, int32_t forreal);
235
static void SaveBoardAndPrintMessage(const char *fn);
236
 
1644 helixhorne 237
static int32_t adjustmark(int32_t *xplc, int32_t *yplc, int16_t danumwalls);
238
static void locktogrid(int32_t *dax, int32_t *day);
239
static int32_t checkautoinsert(int32_t dax, int32_t day, int16_t danumwalls);
3061 helixhorne 240
static void keytimerstuff(void);
1644 helixhorne 241
static void flipwalls(int16_t numwalls, int16_t newnumwalls);
2125 helixhorne 242
static int32_t insertpoint(int16_t linehighlight, int32_t dax, int32_t day, int32_t *mapwallnum);
2599 helixhorne 243
static void deletepoint(int16_t point, int32_t runi);
1644 helixhorne 244
static int32_t deletesector(int16_t sucksect);
1843 helixhorne 245
static int16_t whitelinescan(int16_t sucksect, int16_t dalinehighlight);
3061 helixhorne 246
static void printcoords16(int32_t posxe, int32_t posye, int16_t ange);
247
static void overheadeditor(void);
4026 helixhorne 248
static int32_t getlinehighlight(int32_t xplc, int32_t yplc, int32_t line, int8_t ignore_pointhighlight);
1644 helixhorne 249
static int32_t movewalls(int32_t start, int32_t offs);
5414 hendricks2 250
static void loadnames(const char *namesfile);
1865 helixhorne 251
static void getclosestpointonwall(int32_t x, int32_t y, int32_t dawall, int32_t *nx, int32_t *ny,
252
                                  int32_t maybe_screen_coord_p);
1644 helixhorne 253
static void initcrc(void);
5 Plagman 254
 
1644 helixhorne 255
static int32_t menuselect(void);
5282 terminx 256
static int32_t menuselect_auto(int, int); //PK
726 terminx 257
 
7072 terminx 258
static int32_t insert_sprite_common(int32_t sectnum, int32_t dax, int32_t day);
1801 helixhorne 259
static void correct_ornamented_sprite(int32_t i, int32_t hitw);
260
 
1644 helixhorne 261
static int32_t getfilenames(const char *path, const char *kind);
5 Plagman 262
 
3750 helixhorne 263
// Get basename of BUILD file name (forward slashes as directory separators).
264
static const char *getbasefn(const char *fn)
265
{
266
    const char *slash = Bstrrchr(fn, '/');
267
    return slash ? slash+1 : fn;
268
}
3697 helixhorne 269
 
3061 helixhorne 270
void clearkeys(void)
271
{
272
    Bmemset(keystatus,0,sizeof(keystatus));
273
}
5 Plagman 274
 
1740 helixhorne 275
#ifdef USE_OPENGL
7154 terminx 276
int osdcmd_restartvid(osdcmdptr_t UNUSED(parm))
5 Plagman 277
{
6297 terminx 278
    UNREFERENCED_CONST_PARAMETER(parm);
655 terminx 279
 
3823 helixhorne 280
    if (!in3dmode()) return OSDCMD_OK;
5 Plagman 281
 
6828 terminx 282
    videoResetMode();
6939 pogokeen 283
    if (videoSetGameMode(fullscreen,xres,yres,bpp,upscalefactor))
109 terminx 284
        OSD_Printf("restartvid: Reset failed...\n");
285
 
286
    return OSDCMD_OK;
5 Plagman 287
}
2289 helixhorne 288
#endif
5 Plagman 289
 
7154 terminx 290
static int osdcmd_vidmode(osdcmdptr_t parm)
5 Plagman 291
{
6939 pogokeen 292
    int32_t newx = xres, newy = yres, newbpp = bpp, newfullscreen = fullscreen;
2685 hendricks2 293
#ifdef USE_OPENGL
294
    int32_t tmp;
295
#endif
5 Plagman 296
 
584 terminx 297
    switch (parm->numparms)
298
    {
2289 helixhorne 299
#ifdef USE_OPENGL
109 terminx 300
    case 1:     // bpp switch
1456 helixhorne 301
        tmp = Batol(parm->parms[0]);
2311 helixhorne 302
        if (!(tmp==8 || tmp==16 || tmp==32))
303
            return OSDCMD_SHOWHELP;
304
        newbpp = tmp;
2315 helixhorne 305
        break;
109 terminx 306
    case 4:     // fs, res, bpp switch
307
        newfullscreen = (Batol(parm->parms[3]) != 0);
6370 terminx 308
        fallthrough__;
109 terminx 309
    case 3:     // res & bpp switch
1456 helixhorne 310
        tmp = Batol(parm->parms[2]);
2311 helixhorne 311
        if (!(tmp==8 || tmp==16 || tmp==32))
312
            return OSDCMD_SHOWHELP;
313
        newbpp = tmp;
6370 terminx 314
        fallthrough__;
2289 helixhorne 315
#endif
109 terminx 316
    case 2: // res switch
317
        newx = Batol(parm->parms[0]);
318
        newy = Batol(parm->parms[1]);
319
        break;
331 terminx 320
    default:
321
        return OSDCMD_SHOWHELP;
109 terminx 322
    }
5 Plagman 323
 
3823 helixhorne 324
    if (!in3dmode())
626 terminx 325
    {
6828 terminx 326
        videoSet2dMode(newx,newy);
626 terminx 327
        xdim2d = xdim;
328
        ydim2d = ydim;
329
 
6828 terminx 330
        videoBeginDrawing();    //{{{
1665 terminx 331
        CLEARLINES2D(0, ydim16, 0);
6828 terminx 332
        videoEndDrawing();      //}}}
1648 helixhorne 333
 
1359 terminx 334
        ydim16 = ydim-STATUS2DSIZ2;
1843 helixhorne 335
 
626 terminx 336
        return OSDCMD_OK;
337
    }
338
 
6939 pogokeen 339
    if (videoSetGameMode(newfullscreen,newx,newy,newbpp,upscalefactor))
109 terminx 340
        OSD_Printf("vidmode: Mode change failed!\n");
1644 helixhorne 341
 
342
    xdimgame = newx;
343
    ydimgame = newy;
344
    bppgame = newbpp;
345
    fullscreen = newfullscreen;
346
 
109 terminx 347
    return OSDCMD_OK;
5 Plagman 348
}
349
 
350
 
1456 helixhorne 351
#ifdef M32_SHOWDEBUG
1706 helixhorne 352
char m32_debugstr[64][128];
353
int32_t m32_numdebuglines=0;
1456 helixhorne 354
 
1644 helixhorne 355
static void M32_drawdebug(void)
1456 helixhorne 356
{
2265 helixhorne 357
    int32_t i;
358
    int32_t x=4, y=8;
1456 helixhorne 359
 
1797 helixhorne 360
#if 0
361
    {
362
        static char tstr[128];
1848 helixhorne 363
        Bsprintf(tstr, "search... stat=%d, sector=%d, wall=%d (%d), isbottom=%d, asksave=%d",
364
                 searchstat, searchsector, searchwall, searchbottomwall, searchisbottom, asksave);
1797 helixhorne 365
        printext256(x,y,whitecol,0,tstr,xdimgame>640?0:1);
366
    }
367
#endif
1836 helixhorne 368
    if (m32_numdebuglines>0)
1456 helixhorne 369
    {
6828 terminx 370
        videoBeginDrawing();
1877 helixhorne 371
        for (i=0; i<m32_numdebuglines && y<ydim-8; i++, y+=8)
1836 helixhorne 372
            printext256(x,y,whitecol,0,m32_debugstr[i],xdimgame>640?0:1);
6828 terminx 373
        videoEndDrawing();
1456 helixhorne 374
    }
375
    m32_numdebuglines=0;
376
}
377
#endif
378
 
1843 helixhorne 379
#ifdef YAX_ENABLE
1882 helixhorne 380
// Check whether bunchnum has exactly one corresponding floor and ceiling
381
// and return it in this case. If not 1-to-1, return -1.
382
int32_t yax_is121(int16_t bunchnum, int16_t getfloor)
383
{
384
    int32_t i;
385
    i = headsectbunch[0][bunchnum];
386
    if (i<0 || nextsectbunch[0][i]>=0)
387
        return -1;
388
    i = headsectbunch[1][bunchnum];
389
    if (i<0 || nextsectbunch[1][i]>=0)
390
        return -1;
391
 
392
    return headsectbunch[getfloor][bunchnum];
393
}
394
 
1900 helixhorne 395
static int32_t yax_numsectsinbunch(int16_t bunchnum, int16_t cf)
396
{
397
    int32_t i, n=0;
398
 
399
    if (bunchnum<0 || bunchnum>=numyaxbunches)
400
        return -1;
401
 
402
    for (SECTORS_OF_BUNCH(bunchnum, cf, i))
403
        n++;
404
 
405
    return n;
406
}
407
 
1875 helixhorne 408
static void yax_fixreverselinks(int16_t oldwall, int16_t newwall)
1865 helixhorne 409
{
1875 helixhorne 410
    int32_t cf, ynw;
411
    for (cf=0; cf<2; cf++)
1865 helixhorne 412
    {
1875 helixhorne 413
        ynw = yax_getnextwall(oldwall, cf);
414
        if (ynw >= 0)
415
            yax_setnextwall(ynw, !cf, newwall);
1865 helixhorne 416
    }
417
}
418
 
1875 helixhorne 419
static void yax_tweakwalls(int16_t start, int16_t offs)
420
{
421
    int32_t i, nw, cf;
422
    for (i=0; i<numwalls; i++)
423
        for (cf=0; cf<2; cf++)
424
        {
425
            nw = yax_getnextwall(i, cf);
426
            if (nw >= start)
427
                yax_setnextwall(i, cf, nw+offs);
428
        }
429
}
430
 
1843 helixhorne 431
static void yax_resetbunchnums(void)
432
{
433
    int32_t i;
434
 
435
    for (i=0; i<MAXSECTORS; i++)
436
        yax_setbunches(i, -1, -1);
1856 helixhorne 437
    yax_update(1);
1869 helixhorne 438
    yax_updategrays(pos.z);
1843 helixhorne 439
}
1854 helixhorne 440
 
1856 helixhorne 441
// Whether a wall is constrained by sector extensions.
442
// If false, it's a wall that you can freely move around,
443
// attach points to, etc...
2091 helixhorne 444
static int32_t yax_islockedwall(int16_t line)
1854 helixhorne 445
{
3658 helixhorne 446
#ifdef NEW_MAP_FORMAT
447
    return (wall[line].upwall>=0 || wall[line].dnwall>=0);
448
#else
1865 helixhorne 449
    return !!(wall[line].cstat&YAX_NEXTWALLBITS);
3658 helixhorne 450
#endif
1865 helixhorne 451
}
1854 helixhorne 452
 
1900 helixhorne 453
# define DEFAULT_YAX_HEIGHT (2048<<4)
1843 helixhorne 454
#endif
455
 
456
static void reset_default_mapstate(void)
457
{
458
    pos.x = 32768;          //new board!
459
    pos.y = 32768;
460
    pos.z = 0;
461
    ang = 1536;
1854 helixhorne 462
    cursectnum = -1;
463
 
1843 helixhorne 464
    numsectors = 0;
465
    numwalls = 0;
1854 helixhorne 466
 
1886 helixhorne 467
    editorzrange[0] = INT32_MIN;
468
    editorzrange[1] = INT32_MAX;
1877 helixhorne 469
 
1843 helixhorne 470
    initspritelists();
1867 helixhorne 471
    taglab_init();
6830 terminx 472
    artClearMapArt();
1843 helixhorne 473
#ifdef YAX_ENABLE
474
    yax_resetbunchnums();
475
#endif
3911 helixhorne 476
    g_loadedMapVersion = -1;
1843 helixhorne 477
}
478
 
2122 helixhorne 479
static void m32_keypresscallback(int32_t code, int32_t downp)
480
{
2123 helixhorne 481
    UNREFERENCED_PARAMETER(downp);
482
 
2122 helixhorne 483
    g_iReturnVar = code;
484
    VM_OnEvent(EVENT_KEYPRESS, -1);
485
}
486
 
2350 helixhorne 487
void M32_ResetFakeRORTiles(void)
488
{
489
#ifdef POLYMER
490
# ifdef YAX_ENABLE
491
        // END_TWEAK ceiling/floor fake 'TROR' pics, see BEGIN_TWEAK in engine.c
6829 terminx 492
        if (videoGetRenderMode() == REND_POLYMER && showinvisibility)
2350 helixhorne 493
        {
494
            int32_t i;
495
 
496
            for (i=0; i<numyaxbunches; i++)
497
            {
498
                yax_tweakpicnums(i, YAX_CEILING, 1);
499
                yax_tweakpicnums(i, YAX_FLOOR, 1);
500
            }
501
        }
502
# endif
503
#endif
504
}
505
 
2314 helixhorne 506
void M32_DrawRoomsAndMasks(void)
507
{
4880 helixhorne 508
    static int srchwall = -1;
5182 helixhorne 509
    const int32_t tmpyx=yxaspect, tmpvr=viewingrange;
4880 helixhorne 510
 
5182 helixhorne 511
    if (r_usenewaspect)
512
    {
513
        newaspect_enable = 1;
6828 terminx 514
        videoSetCorrectedAspect();
5182 helixhorne 515
    }
516
 
3648 helixhorne 517
    VM_OnEvent(EVENT_PREDRAW3DSCREEN, -1);
518
 
2314 helixhorne 519
    yax_preparedrawrooms();
520
    drawrooms(pos.x,pos.y,pos.z,ang,horiz,cursectnum);
4555 hendricks2 521
    yax_drawrooms(CallExtAnalyzeSprites, cursectnum, 0, 0);
2314 helixhorne 522
 
4880 helixhorne 523
    const int osearchwall=searchwall, osearchstat=searchstat;
524
    if (srchwall >= 0)
525
    {
526
        // a.m32 states 'tduprot' and 'tduplin' need searchstat to check for
527
        // whether we've hit a sprite, but these would be only set after the
528
        // drawmasks(). Hence this hackish workaround.
529
        searchstat = 3;
530
        searchwall = srchwall;
531
    }
8428 hendricks2 532
    CallExtAnalyzeSprites(0,0,0,0,0);
4880 helixhorne 533
    searchwall = osearchwall, searchstat=osearchstat;
534
 
6831 terminx 535
    renderDrawMasks();
4880 helixhorne 536
    srchwall = (searchstat == 3) ? searchwall : -1;
2350 helixhorne 537
    M32_ResetFakeRORTiles();
2314 helixhorne 538
 
539
#ifdef POLYMER
6829 terminx 540
    if (videoGetRenderMode() == REND_POLYMER && searchit == 2)
2314 helixhorne 541
    {
542
        polymer_editorpick();
543
        drawrooms(pos.x,pos.y,pos.z,ang,horiz,cursectnum);
8428 hendricks2 544
        CallExtAnalyzeSprites(0,0,0,0,0);
6831 terminx 545
        renderDrawMasks();
2350 helixhorne 546
        M32_ResetFakeRORTiles();
2314 helixhorne 547
    }
548
#endif
2818 helixhorne 549
 
550
    VM_OnEvent(EVENT_DRAW3DSCREEN, -1);
551
 
552
    if (g_doScreenShot)
553
    {
6831 terminx 554
        videoCaptureScreen("mcapxxxx.tga", 0);
2818 helixhorne 555
        g_doScreenShot = 0;
556
    }
5182 helixhorne 557
 
558
    if (r_usenewaspect)
559
    {
560
        newaspect_enable = 0;
6831 terminx 561
        renderSetAspect(tmpvr, tmpyx);
5182 helixhorne 562
    }
2314 helixhorne 563
}
564
 
7156 terminx 565
void M32_OnShowOSD(int shown)
5321 helixhorne 566
{
6827 terminx 567
    mouseLockToWindow((!shown) + 2);
5321 helixhorne 568
}
569
 
5345 hendricks2 570
static void M32_FatalEngineError(void)
571
{
8191 terminx 572
#ifdef DEBUGGINGAIDS
573
    debug_break();
574
#endif
575
    Bsprintf(tempbuf, "There was a problem initializing the engine: %s\n", engineerrstr);
576
    ERRprintf("%s", tempbuf);
577
    fatal_exit(tempbuf);
5345 hendricks2 578
}
579
 
8478 hendricks2 580
static void InitCustomColors()
581
{
582
    /* blue */
583
    vgapal16[9*4+0] = 252;
584
    vgapal16[9*4+1] = 124;
585
    vgapal16[9*4+2] = 28;
586
 
587
    /* orange */
588
    vgapal16[31*4+0] = 80; // blue
589
    vgapal16[31*4+1] = 180; // green
590
    vgapal16[31*4+2] = 240; // red
591
 
592
    // UNUSED?
593
    vgapal16[39*4+0] = 144;
594
    vgapal16[39*4+1] = 212;
595
    vgapal16[39*4+2] = 252;
596
 
597
 
598
    /* light yellow */
599
    vgapal16[22*4+0] = 204;
600
    vgapal16[22*4+1] = 252;
601
    vgapal16[22*4+2] = 252;
602
 
603
    /* grey */
604
    vgapal16[23*4+0] = 180;
605
    vgapal16[23*4+1] = 180;
606
    vgapal16[23*4+2] = 180;
607
 
608
    /* blue */
609
    vgapal16[24*4+0] = 204;
610
    vgapal16[24*4+1] = 164;
611
    vgapal16[24*4+2] = 48;
612
 
613
    vgapal16[32*4+0] = 240;
614
    vgapal16[32*4+1] = 200;
615
    vgapal16[32*4+2] = 84;
616
 
617
    // grid color
618
    vgapal16[25*4+0] = 64;
619
    vgapal16[25*4+1] = 56;
620
    vgapal16[25*4+2] = 56;
621
 
622
    vgapal16[26*4+0] = 96;
623
    vgapal16[26*4+1] = 96;
624
    vgapal16[26*4+2] = 96;
625
 
626
    // UNUSED?
627
    vgapal16[33*4+0] = 0; //60; // blue
628
    vgapal16[33*4+1] = 0; //120; // green
629
    vgapal16[33*4+2] = 192; //180; // red
630
 
631
    // UNUSED?
632
    vgapal16[41*4+0] = 0; //96;
633
    vgapal16[41*4+1] = 0; //160;
634
    vgapal16[41*4+2] = 252; //192;
635
}
636
 
5828 terminx 637
int app_main(int argc, char const * const * argv)
5 Plagman 638
{
2079 helixhorne 639
#ifdef STARTUP_SETUP_WINDOW
640
    char cmdsetup = 0;
641
#endif
642
    char quitflag;
4973 helixhorne 643
    int32_t i;
5 Plagman 644
 
109 terminx 645
    pathsearchmode = 1;         // unrestrict findfrompath so that full access to the filesystem can be had
646
 
5 Plagman 647
#ifdef USE_OPENGL
627 terminx 648
    OSD_RegisterFunction("restartvid","restartvid: reinitialize the video mode",osdcmd_restartvid);
1112 hnt_ts 649
    OSD_RegisterFunction("vidmode","vidmode <xdim> <ydim> <bpp> <fullscreen>: immediately change the video mode",osdcmd_vidmode);
4015 helixhorne 650
    baselayer_osdcmd_vidmode_func = osdcmd_vidmode;
2289 helixhorne 651
#else
652
    OSD_RegisterFunction("vidmode","vidmode <xdim> <ydim>: immediately change the video mode",osdcmd_vidmode);
5 Plagman 653
#endif
4015 helixhorne 654
 
4558 hendricks2 655
    wm_setapptitle(AppProperName);
5 Plagman 656
 
1706 helixhorne 657
    editstatus = 1;
1717 helixhorne 658
 
4555 hendricks2 659
    if ((i = CallExtPreInit(argc,argv)) < 0) return -1;
5 Plagman 660
 
3221 hendricks2 661
#ifdef _WIN32
8174 terminx 662
    win_priorityclass = 1;
5 Plagman 663
#endif
664
 
584 terminx 665
    for (i=1; i<argc; i++)
666
    {
667
        if (argv[i][0] == '-')
668
        {
2079 helixhorne 669
#ifdef STARTUP_SETUP_WINDOW
1644 helixhorne 670
            if (!Bstrcmp(argv[i], "-setup")) cmdsetup = 1;
2079 helixhorne 671
            else
672
#endif
673
            if (!Bstrcmp(argv[i], "-help") || !Bstrcmp(argv[i], "--help") || !Bstrcmp(argv[i], "-?"))
584 terminx 674
            {
4558 hendricks2 675
#ifdef WM_MSGBOX_WINDOW
676
                wm_msgbox(AppProperName,
677
#else
678
                Bprintf(
679
#endif
680
                    "%s\n"
681
                    "Syntax: %s [options] mapname\n"
109 terminx 682
                    "Options:\n"
683
                    "\t-grp\tUse an extra GRP or ZIP file.\n"
684
                    "\t-g\tSame as above.\n"
2079 helixhorne 685
#ifdef STARTUP_SETUP_WINDOW
109 terminx 686
                    "\t-setup\tDisplays the configuration dialogue box before entering the editor.\n"
5 Plagman 687
#endif
4558 hendricks2 688
                    , AppProperName, AppTechnicalName);
109 terminx 689
                return 0;
690
            }
691
            continue;
692
        }
693
    }
3749 helixhorne 694
 
584 terminx 695
    if (boardfilename[0] == 0)
109 terminx 696
        Bstrcpy(boardfilename,"newboard.map");
584 terminx 697
    else if (Bstrchr(boardfilename,'.') == 0)
109 terminx 698
        Bstrcat(boardfilename, ".map");
699
    //Bcanonicalisefilename(boardfilename,0);
5 Plagman 700
 
4558 hendricks2 701
    OSD_SetFunctions(
702
        NULL, NULL, NULL, NULL, NULL,
703
        COMMON_clearbackground,
704
        BGetTime,
5321 helixhorne 705
        M32_OnShowOSD
4558 hendricks2 706
    );
707
 
7359 hendricks2 708
    if (!buildvfs_getcwd(program_origcwd,BMAX_PATH))
4557 hendricks2 709
        program_origcwd[0] = '\0';
710
 
4558 hendricks2 711
    Bstrncpy(game_executable, DefaultGameLocalExec, sizeof(game_executable));
712
 
6831 terminx 713
    if (enginePreInit())
5345 hendricks2 714
        M32_FatalEngineError();
4740 terminx 715
 
4555 hendricks2 716
    if ((i = CallExtInit()) < 0) return -1;
4557 hendricks2 717
 
2079 helixhorne 718
#ifdef STARTUP_SETUP_WINDOW
584 terminx 719
    if (i || forcesetup || cmdsetup)
720
    {
1762 terminx 721
        if (quitevent || !startwin_run())
1665 terminx 722
        {
6831 terminx 723
            engineUnInit();
8274 hendricks2 724
            exit(EXIT_SUCCESS);
1665 terminx 725
        }
194 terminx 726
    }
5 Plagman 727
#endif
728
 
4557 hendricks2 729
    if (CallExtPostStartupWindow() < 0) return -1;
730
 
5414 hendricks2 731
    loadnames(g_namesFileName);
1711 helixhorne 732
 
342 terminx 733
    if (initinput()) return -1;
1836 helixhorne 734
 
6827 terminx 735
    mouseInit();
342 terminx 736
 
8171 terminx 737
    timerInit(CLOCKTICKSPERSECOND);
6828 terminx 738
    timerSetCallback(keytimerstuff);
5 Plagman 739
 
6830 terminx 740
    artLoadFiles("tiles000.art", g_maxCacheSize);
109 terminx 741
 
5384 hendricks2 742
    Bstrcpy(kensig,"Uses BUILD technology by Ken Silverman");
743
    initcrc();
744
 
8490 hendricks2 745
    InitCustomColors();
746
 
5384 hendricks2 747
    const char *defsfile = G_DefFile();
748
 
7431 terminx 749
    if (testkopen("editor.def", 0))
750
        G_AddDefModule("editor.def");
751
 
5384 hendricks2 752
    if (!loaddefinitionsfile(defsfile))
753
        initprintf("Definitions file \"%s\" loaded.\n",defsfile);
754
 
6673 hendricks2 755
    for (char * m : g_defModules)
756
        free(m);
757
    g_defModules.clear();
5384 hendricks2 758
 
6831 terminx 759
    if (enginePostInit())
5384 hendricks2 760
        M32_FatalEngineError();
761
 
762
    CallExtPostInit();
763
 
1869 helixhorne 764
#ifdef YAX_ENABLE
765
    // init dummy texture for YAX
766
    // must be after loadpics(), which inits BUILD's cache
767
 
1895 helixhorne 768
    i = MAXTILES-1;
5842 hendricks2 769
    if (tilesiz[i].x==0 && tilesiz[i].y==0)
1895 helixhorne 770
    {
771
        static char R[8*16] = { //
772
            0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
773
            0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
774
            0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
775
            0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0,
776
            0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0,
777
            0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0,
778
            0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0,
779
        };
1869 helixhorne 780
 
1895 helixhorne 781
        char *newtile;
782
        int32_t sx=32, sy=32, col, j;
1869 helixhorne 783
 
8204 terminx 784
        walock[i] = CACHE1D_PERMANENT;
1895 helixhorne 785
        picsiz[i] = 5 + (5<<4);
4623 terminx 786
        tilesiz[i].x = sx; tilesiz[i].y = sy;
8204 terminx 787
        g_cache.allocateBlock(&waloff[i], sx*sy, &walock[i]);
1895 helixhorne 788
        newtile = (char *)waloff[i];
1869 helixhorne 789
 
6831 terminx 790
        col = paletteGetClosestColor(128, 128, 0);
1895 helixhorne 791
        for (j=0; j<(signed)sizeof(R); j++)
792
            R[j] *= col;
1869 helixhorne 793
 
1895 helixhorne 794
        Bmemset(newtile, 0, sx*sy);
795
        for (j=0; j<8; j++)
796
            Bmemcpy(&newtile[32*j], &R[16*j], 16);
797
    }
1869 helixhorne 798
#endif
799
 
2495 hendricks2 800
#ifdef HAVE_CLIPSHAPE_FEATURE
6831 terminx 801
    int k = engineLoadClipMaps();
1728 helixhorne 802
    if (k>0)
1722 helixhorne 803
        initprintf("There was an error loading the sprite clipping map (status %d).\n", k);
2495 hendricks2 804
 
6673 hendricks2 805
    for (char * f : g_clipMapFiles)
806
        free(f);
807
    g_clipMapFiles.clear();
2270 helixhorne 808
#endif
1719 helixhorne 809
 
1867 helixhorne 810
    taglab_init();
811
 
1886 helixhorne 812
    mkonwinvalid();
813
 
6223 terminx 814
    // executed once per init
815
    OSD_Exec("m32_autoexec.cfg");
816
 
1760 helixhorne 817
    if (LoadBoard(boardfilename, 1))
1843 helixhorne 818
        reset_default_mapstate();
5 Plagman 819
 
109 terminx 820
    totalclock = 0;
584 terminx 821
 
1208 terminx 822
    updatesector(pos.x,pos.y,&cursectnum);
584 terminx 823
 
6827 terminx 824
    keySetCallback(&m32_keypresscallback);
5321 helixhorne 825
    M32_OnShowOSD(0);  // make sure the desktop's mouse cursor is hidden
2122 helixhorne 826
 
456 terminx 827
    if (cursectnum == -1)
828
    {
6828 terminx 829
        vid_gamma_3d = g_videoGamma;
830
        vid_brightness_3d = g_videoBrightness;
831
        vid_contrast_3d = g_videoContrast;
1679 helixhorne 832
 
6828 terminx 833
        g_videoGamma = g_videoContrast = 1.0;
834
        g_videoBrightness = 0.0;
1665 terminx 835
 
6829 terminx 836
        videoSetPalette(0,0,0);
6939 pogokeen 837
        if (videoSetGameMode(fullscreen, xdim2d, ydim2d, 8, upscalefactor) < 0)
1364 terminx 838
        {
4555 hendricks2 839
            CallExtUnInit();
6831 terminx 840
            engineUnInit();
1364 terminx 841
            Bprintf("%d * %d not supported in this graphics mode\n",xdim2d,ydim2d);
8190 terminx 842
            Bexit(EXIT_SUCCESS);
1364 terminx 843
        }
1691 helixhorne 844
 
4090 hendricks2 845
        system_getcvars();
846
 
456 terminx 847
        overheadeditor();
727 terminx 848
        keystatus[buildkeys[BK_MODE2D_3D]] = 0;
1665 terminx 849
 
6828 terminx 850
        g_videoGamma = vid_gamma_3d;
851
        g_videoContrast = vid_contrast_3d;
852
        g_videoBrightness = vid_brightness_3d;
1679 helixhorne 853
 
854
        vid_gamma_3d = vid_contrast_3d = vid_brightness_3d = -1;
855
 
6829 terminx 856
        videoSetPalette(GAMMA_CALC,0,0);
456 terminx 857
    }
1360 terminx 858
    else
859
    {
6939 pogokeen 860
        if (videoSetGameMode(fullscreen, xdimgame, ydimgame, bppgame, upscalefactor) < 0)
1360 terminx 861
        {
4555 hendricks2 862
            CallExtUnInit();
6831 terminx 863
            engineUnInit();
1360 terminx 864
            Bprintf("%d * %d not supported in this graphics mode\n",xdim,ydim);
8190 terminx 865
            Bexit(EXIT_SUCCESS);
1360 terminx 866
        }
1691 helixhorne 867
 
4090 hendricks2 868
        system_getcvars();
869
 
6829 terminx 870
        videoSetPalette(GAMMA_CALC,0,0);
1360 terminx 871
    }
1760 helixhorne 872
 
5 Plagman 873
CANCEL:
109 terminx 874
    quitflag = 0;
875
    while (quitflag == 0)
876
    {
584 terminx 877
        if (handleevents())
878
        {
879
            if (quitevent)
880
            {
6860 terminx 881
                keystatus[sc_Escape] = 1;
109 terminx 882
                quitevent = 0;
883
            }
407 terminx 884
        }
584 terminx 885
 
109 terminx 886
        OSD_DispatchQueued();
5 Plagman 887
 
6828 terminx 888
        videoNextPage();
8050 pogokeen 889
        synctics = (int32_t) totalclock-lockclock;
1656 terminx 890
        lockclock += synctics;
891
 
4555 hendricks2 892
        CallExtPreCheckKeys();
1854 helixhorne 893
 
2314 helixhorne 894
        M32_DrawRoomsAndMasks();
1877 helixhorne 895
 
4200 hendricks2 896
        inputchecked = 1;
897
 
1456 helixhorne 898
#ifdef M32_SHOWDEBUG
1706 helixhorne 899
        if (searchstat>=0 && (searchwall<0 || searchsector<0))
900
        {
1866 helixhorne 901
            if (m32_numdebuglines<64)
902
                Bsprintf(m32_debugstr[m32_numdebuglines++], "inconsistent search variables!");
1706 helixhorne 903
            searchstat = -1;
904
        }
905
 
1456 helixhorne 906
        M32_drawdebug();
907
#endif
4555 hendricks2 908
        CallExtCheckKeys();
5 Plagman 909
 
910
 
6860 terminx 911
        if (keystatus[sc_Escape])
109 terminx 912
        {
6860 terminx 913
            keystatus[sc_Escape] = 0;
1776 helixhorne 914
 
5 Plagman 915
            printext256(0,0,whitecol,0,"Are you sure you want to quit?",0);
916
 
6828 terminx 917
            videoShowFrame(1);
8050 pogokeen 918
            synctics = (int32_t) totalclock-lockclock;
109 terminx 919
            lockclock += synctics;
5 Plagman 920
 
6860 terminx 921
            while ((keystatus[sc_Escape]|keystatus[sc_Enter]|keystatus[sc_Space]|keystatus[sc_N]) == 0)
109 terminx 922
            {
1486 helixhorne 923
                idle_waitevent();
584 terminx 924
                if (handleevents())
925
                {
926
                    if (quitevent)
927
                    {
109 terminx 928
                        quitflag = 1;
929
                        break;
930
                    }
451 terminx 931
                }
5 Plagman 932
 
6860 terminx 933
                if (keystatus[sc_Y]||keystatus[sc_Enter]) // Y or ENTER
584 terminx 934
                {
6860 terminx 935
                    keystatus[sc_Y] = 0;
936
                    keystatus[sc_Enter] = 0;
109 terminx 937
                    quitflag = 1; break;
938
                }
939
            }
6860 terminx 940
            while (keystatus[sc_Escape])
5 Plagman 941
            {
6860 terminx 942
                keystatus[sc_Escape] = 0;
5 Plagman 943
                quitevent = 0;
944
                goto CANCEL;
945
            }
109 terminx 946
        }
947
    }
5 Plagman 948
 
109 terminx 949
    if (asksave)
950
    {
1790 helixhorne 951
        i = CheckMapCorruption(4, 0);
1760 helixhorne 952
 
953
        printext256(0,8,whitecol,0,i<4?"Save changes?":"Map is heavily corrupt. Save changes?",0);
6828 terminx 954
        videoShowFrame(1);
5 Plagman 955
 
6860 terminx 956
        while ((keystatus[sc_Escape]|keystatus[sc_Enter]|keystatus[sc_Space]|keystatus[sc_N]|keystatus[sc_C]) == 0)
109 terminx 957
        {
1486 helixhorne 958
            idle_waitevent();
406 terminx 959
            if (handleevents()) { if (quitevent) break; } // like saying no
584 terminx 960
 
6860 terminx 961
            if (keystatus[sc_Y] || keystatus[sc_Enter]) // Y or ENTER
584 terminx 962
            {
6860 terminx 963
                keystatus[sc_Y] = keystatus[sc_Enter] = 0;
1760 helixhorne 964
 
3911 helixhorne 965
                SaveBoard(NULL, M32_SB_ASKOV);
1760 helixhorne 966
 
109 terminx 967
                break;
968
            }
969
        }
6860 terminx 970
        while (keystatus[sc_Escape]||keystatus[sc_C])
5 Plagman 971
        {
6860 terminx 972
            keystatus[sc_Escape] = keystatus[sc_C] = 0;
5 Plagman 973
            quitevent = 0;
974
            goto CANCEL;
109 terminx 975
        }
5 Plagman 976
    }
977
 
978
 
4555 hendricks2 979
    CallExtUnInit();
1843 helixhorne 980
//    clearfilenames();
6831 terminx 981
    engineUnInit();
5 Plagman 982
 
5803 terminx 983
    return 0;
5 Plagman 984
}
1644 helixhorne 985
 
986
static int32_t mhk=0;
2236 helixhorne 987
static void loadmhk(int32_t domessage)
606 terminx 988
{
3735 helixhorne 989
    char levname[BMAX_PATH];
606 terminx 990
 
1644 helixhorne 991
    if (!mhk)
992
        return;
1760 helixhorne 993
 
1644 helixhorne 994
    Bstrcpy(levname, boardfilename);
3735 helixhorne 995
    append_ext_UNSAFE(levname, ".mhk");
1760 helixhorne 996
 
6831 terminx 997
    if (!engineLoadMHK(levname))
1760 helixhorne 998
    {
999
        if (domessage)
2538 hendricks2 1000
            message("Loaded map hack file \"%s\"",levname);
1760 helixhorne 1001
        else
2538 hendricks2 1002
            initprintf("Loaded map hack file \"%s\"\n",levname);
1760 helixhorne 1003
    }
1004
    else
1005
    {
1006
        mhk=2;
1007
        if (domessage)
2538 hendricks2 1008
            message("No maphack found for map \"%s\"",boardfilename);
1760 helixhorne 1009
    }
606 terminx 1010
}
1011
 
1854 helixhorne 1012
// this is spriteon{ceiling,ground}z from astub.c packed into
1013
// one convenient function
1014
void spriteoncfz(int32_t i, int32_t *czptr, int32_t *fzptr)
1015
{
3205 helixhorne 1016
    int32_t height, zofs;
1836 helixhorne 1017
 
3205 helixhorne 1018
    getzsofslope(sprite[i].sectnum, sprite[i].x,sprite[i].y, czptr, fzptr);
1019
    if ((sprite[i].cstat&48)==32)
1020
        return;
1854 helixhorne 1021
 
3205 helixhorne 1022
    zofs = spriteheightofs(i, &height, 0);
1023
 
1024
    *czptr += height - zofs;
1025
    *fzptr -= zofs;
1854 helixhorne 1026
}
1027
 
1836 helixhorne 1028
static void move_and_update(int32_t xvect, int32_t yvect, int32_t addshr)
1029
{
2028 helixhorne 1030
    if (m32_clipping==0)
1836 helixhorne 1031
    {
1032
        pos.x += xvect>>(14+addshr);
1033
        pos.y += yvect>>(14+addshr);
1034
        updatesector(pos.x,pos.y, &cursectnum);
1035
    }
1036
    else
2028 helixhorne 1037
    {
1836 helixhorne 1038
        clipmove(&pos,&cursectnum, xvect>>addshr,yvect>>addshr,
2028 helixhorne 1039
                 128,4<<8,4<<8, (m32_clipping==1) ? 0 : CLIPMASK0);
1040
    }
5277 terminx 1041
 
1042
    if (in3dmode())
1043
    {
1044
        silentmessage("x:%d y:%d z:%d ang:%d horiz:%d", pos.x, pos.y, pos.z, ang, horiz);
8050 pogokeen 1045
        getmessagetimeoff = (int32_t) totalclock+30;
5277 terminx 1046
    }
1836 helixhorne 1047
}
1048
 
1854 helixhorne 1049
static void mainloop_move(void)
1836 helixhorne 1050
{
1051
    int32_t xvect, yvect, doubvel;
1052
 
1053
    if (angvel != 0)  //ang += angvel * constant
1054
    {
5281 terminx 1055
        if (eitherCTRL && m32_2d3dmode)
1056
        {
1057
            int x = m32_2d3d.x + (angvel / 32);
1058
            int xx = m32_2d3d.x + XSIZE_2D3D + (angvel / 32);
1836 helixhorne 1059
 
5281 terminx 1060
            if (x > 4 && xx < xdim2d - 4)
1061
            {
1062
                silentmessage("2d3d x:%d y:%d", m32_2d3d.x, m32_2d3d.y);
1063
                m32_2d3d.x += (angvel / 32);
1064
            }
1065
        }
1066
        else
1067
        {
1068
            //ENGINE calculates angvel for you
1836 helixhorne 1069
 
5281 terminx 1070
            //Lt. shift makes turn velocity 50% faster
1071
            doubvel = (synctics + DOWN_BK(RUN)*(synctics>>1));
5277 terminx 1072
 
5281 terminx 1073
            ang += ((angvel*doubvel)>>4);
1074
            ang &= 2047;
1075
 
1076
            if (in3dmode())
1077
            {
1078
                silentmessage("x:%d y:%d z:%d ang:%d horiz:%d", pos.x, pos.y, pos.z, ang, horiz);
8050 pogokeen 1079
                getmessagetimeoff = (int32_t) totalclock+30;
5281 terminx 1080
            }
5277 terminx 1081
        }
1836 helixhorne 1082
    }
1083
    if ((vel|svel) != 0)
1084
    {
5281 terminx 1085
        if (eitherCTRL && m32_2d3dmode)
1086
        {
1087
            int y = m32_2d3d.y - (vel / 64);
1088
            int yy = m32_2d3d.y + YSIZE_2D3D - (vel / 64);
1836 helixhorne 1089
 
5281 terminx 1090
            if (y > 4 && yy < ydim2d - STATUS2DSIZ2 - 4)
1091
            {
1092
                silentmessage("2d3d x:%d y:%d", m32_2d3d.x, m32_2d3d.y);
1093
                m32_2d3d.y -= (vel / 64);
1094
            }
1095
        }
1096
        else
1836 helixhorne 1097
 
1098
        {
5281 terminx 1099
            //Lt. shift doubles forward velocity
1100
            doubvel = (1+(DOWN_BK(RUN)))*synctics;
1101
 
1102
            xvect = 0;
1103
            yvect = 0;
1104
 
1105
            if (vel != 0)
1106
            {
5282 terminx 1107
                xvect += ((vel*doubvel)>>3)*(int32_t) sintable[(ang+2560)&2047];
1108
                yvect += ((vel*doubvel)>>3)*(int32_t) sintable[(ang+2048)&2047];
5281 terminx 1109
            }
1110
            if (svel != 0)
1111
            {
5282 terminx 1112
                xvect += ((svel*doubvel)>>3)*(int32_t) sintable[(ang+2048)&2047];
1113
                yvect += ((svel*doubvel)>>3)*(int32_t) sintable[(ang+1536)&2047];
5281 terminx 1114
            }
1115
 
1116
            move_and_update(xvect, yvect, 0);
1836 helixhorne 1117
        }
1118
    }
1119
}
1120
 
2699 helixhorne 1121
static void handle_sprite_in_clipboard(int32_t i)
1122
{
1123
    if (somethingintab == 3)
1124
    {
1125
        int32_t j, k;
1126
 
1127
        sprite[i].picnum = temppicnum;
4623 terminx 1128
        if (tilesiz[temppicnum].x <= 0 || tilesiz[temppicnum].y <= 0)
2699 helixhorne 1129
        {
1130
            j = 0;
1131
            for (k=0; k<MAXTILES; k++)
4623 terminx 1132
                if (tilesiz[k].x > 0 && tilesiz[k].y > 0)
2699 helixhorne 1133
                {
1134
                    j = k;
1135
                    break;
1136
                }
1137
            sprite[i].picnum = j;
1138
        }
1139
        sprite[i].shade = tempshade;
6175 terminx 1140
        sprite[i].blend = tempblend;
2699 helixhorne 1141
        sprite[i].pal = temppal;
7078 terminx 1142
        sprite[i].xrepeat = max(tempxrepeat, 1u);
1143
        sprite[i].yrepeat = max(tempyrepeat, 1u);
2699 helixhorne 1144
        sprite[i].cstat = tempcstat;
1145
    }
1146
}
1147
 
1148
 
5 Plagman 1149
void editinput(void)
1150
{
1205 terminx 1151
    int32_t mousz, bstatus;
2699 helixhorne 1152
    int32_t i, tempint=0;
1843 helixhorne 1153
    int32_t goalz, xvect, yvect, hiz, loz, oposz;
5239 terminx 1154
    int32_t hihit, lohit, omlook=mlook;
5 Plagman 1155
 
726 terminx 1156
// 3B  3C  3D  3E   3F  40  41  42   43  44  57  58          46
1157
// F1  F2  F3  F4   F5  F6  F7  F8   F9 F10 F11 F12        SCROLL
1158
 
109 terminx 1159
    mousz = 0;
6831 terminx 1160
    mouseGetValues(&mousx,&mousy,&bstatus);
1836 helixhorne 1161
    mousx = (mousx<<16) + mousexsurp;
1162
    mousy = (mousy<<16) + mouseysurp;
1055 terminx 1163
 
1836 helixhorne 1164
    if (unrealedlook && !mskip)
1165
    {
1166
        if (mlook==0 && (bstatus&(1|2|4))==2)
1167
            mlook = 3;
1168
        else if ((bstatus&(1|2|4))==1)
1169
            mlook = 3;
1170
    }
1055 terminx 1171
 
109 terminx 1172
    {
1173
        ldiv_t ld;
1055 terminx 1174
        if (mlook)
1175
        {
1836 helixhorne 1176
            ld = ldiv(mousx, (int32_t)((1<<16)/(msens*0.5f))); mousx = ld.quot; mousexsurp = ld.rem;
1177
            ld = ldiv(mousy, (int32_t)((1<<16)/(msens*0.25f))); mousy = ld.quot; mouseysurp = ld.rem;
1055 terminx 1178
        }
1179
        else
1180
        {
1836 helixhorne 1181
            ld = ldiv(mousx, (int32_t)((1<<16)/msens)); mousx = ld.quot; mousexsurp = ld.rem;
1182
            ld = ldiv(mousy, (int32_t)((1<<16)/msens)); mousy = ld.quot; mouseysurp = ld.rem;
1055 terminx 1183
        }
109 terminx 1184
    }
5 Plagman 1185
 
1055 terminx 1186
    if (mlook == 3)
1836 helixhorne 1187
        mlook = omlook;
1055 terminx 1188
 
726 terminx 1189
    // UnrealEd:
1190
    // rmb: mouselook
1191
    // lbm: x:turn y:fwd/back local x
1192
    // lmb&rmb: x:strafe y:up/dn (move in local yz plane)
1193
    // mmb: fwd/back in viewing vector
1194
 
728 terminx 1195
    if (unrealedlook && !mskip)    //PK
5 Plagman 1196
    {
1836 helixhorne 1197
        if ((bstatus&(1|2|4))==1)
726 terminx 1198
        {
1055 terminx 1199
            ang += mousx;
1205 terminx 1200
            xvect = -((mousy*(int32_t)sintable[(ang+2560)&2047])<<(3+pk_uedaccel));
1201
            yvect = -((mousy*(int32_t)sintable[(ang+2048)&2047])<<(3+pk_uedaccel));
726 terminx 1202
 
1836 helixhorne 1203
            move_and_update(xvect, yvect, 0);
726 terminx 1204
        }
1836 helixhorne 1205
        else if (!mlook && (bstatus&(1|2|4))==2)
726 terminx 1206
        {
1207
            mlook=2;
1208
        }
1836 helixhorne 1209
        else if ((bstatus&(1|2|4))==(1|2))
726 terminx 1210
        {
1211
            zmode = 2;
1205 terminx 1212
            xvect = -((mousx*(int32_t)sintable[(ang+2048)&2047])<<pk_uedaccel);
1213
            yvect = -((mousx*(int32_t)sintable[(ang+1536)&2047])<<pk_uedaccel);
1208 terminx 1214
            pos.z += mousy<<(4+pk_uedaccel);
1836 helixhorne 1215
 
1216
            move_and_update(xvect, yvect, 0);
726 terminx 1217
        }
1836 helixhorne 1218
        else if ((bstatus&(1|2|4))==4)
726 terminx 1219
        {
1220
            zmode = 2;
1221
 
1222
            // horiz-100 of 200 is viewing at 326.4 build angle units (=atan(200/128)) upward
1223
            tempint = getangle(128, horiz-100);
1224
 
1225
            xvect = -((mousy*
1205 terminx 1226
                       ((int32_t)sintable[(ang+2560)&2047]>>6)*
1227
                       ((int32_t)sintable[(tempint+512)&2047])>>6)
726 terminx 1228
                      <<pk_uedaccel);
1229
            yvect = -((mousy*
1205 terminx 1230
                       ((int32_t)sintable[(ang+2048)&2047]>>6)*
1231
                       ((int32_t)sintable[(tempint+512)&2047])>>6)
726 terminx 1232
                      <<pk_uedaccel);
1233
 
1836 helixhorne 1234
            pos.z += mousy*(((int32_t)sintable[(tempint+2048)&2047])>>(10-pk_uedaccel));
726 terminx 1235
 
1836 helixhorne 1236
            move_and_update(xvect, yvect, 2);
726 terminx 1237
        }
1238
    }
1239
 
1052 terminx 1240
    if (mskip)
1836 helixhorne 1241
    {
1242
        // mskip was set in astub.c to not trigger UEd mouse movements.
1243
        // Reset now.
1244
        mskip = 0;
1245
    }
1052 terminx 1246
    else
726 terminx 1247
    {
1836 helixhorne 1248
        if (mlook && (unrealedlook==0 || (bstatus&(1|4))==0))
1052 terminx 1249
        {
1055 terminx 1250
            ang += mousx;
1251
            horiz -= mousy;
164 terminx 1252
 
1836 helixhorne 1253
            /*
1254
            if (mousy && !(mousy/4))
1255
                horiz--;
1256
            if (mousx && !(mousx/2))
1257
                ang++;
1258
            */
1762 terminx 1259
 
1854 helixhorne 1260
            inpclamp(&horiz, -99, 299);
1644 helixhorne 1261
 
1052 terminx 1262
            if (mlook == 1)
1263
            {
1264
                searchx = xdim>>1;
1265
                searchy = ydim>>1;
1266
            }
1267
            osearchx = searchx-mousx;
1268
            osearchy = searchy-mousy;
5277 terminx 1269
 
5305 terminx 1270
            if (mousx || mousy)
1271
            {
1272
                silentmessage("x:%d y:%d z:%d ang:%d horiz:%d", pos.x, pos.y, pos.z, ang, horiz);
8050 pogokeen 1273
                getmessagetimeoff = (int32_t) totalclock+30;
5305 terminx 1274
            }
1052 terminx 1275
        }
1836 helixhorne 1276
        else if (unrealedlook==0 || (bstatus&(1|2|4))==0)
500 terminx 1277
        {
1052 terminx 1278
            osearchx = searchx;
1279
            osearchy = searchy;
1280
            searchx += mousx;
1281
            searchy += mousy;
1644 helixhorne 1282
 
1854 helixhorne 1283
            inpclamp(&searchx, 12, xdim-13);
1284
            inpclamp(&searchy, 12, ydim-13);
584 terminx 1285
        }
5 Plagman 1286
    }
1287
 
728 terminx 1288
//    showmouse();
5 Plagman 1289
 
6860 terminx 1290
    if (keystatus[sc_F9])  // F9
606 terminx 1291
    {
1656 terminx 1292
        if (mhk)
1293
        {
1294
            Bmemset(spriteext, 0, sizeof(spriteext_t) * MAXSPRITES);
1830 helixhorne 1295
            Bmemset(spritesmooth, 0, sizeof(spritesmooth_t) * (MAXSPRITES+MAXUNIQHUDID));
6831 terminx 1296
            engineClearLightsFromMHK();
1656 terminx 1297
            mhk = 0;
1760 helixhorne 1298
            message("Maphacks disabled");
1656 terminx 1299
        }
1300
        else
1301
        {
1302
            mhk = 1;
1760 helixhorne 1303
            loadmhk(1);
1656 terminx 1304
        }
1305
 
6860 terminx 1306
        keystatus[sc_F9] = 0;
606 terminx 1307
    }
1644 helixhorne 1308
 
1836 helixhorne 1309
    mainloop_move();
1644 helixhorne 1310
 
2028 helixhorne 1311
    getzrange(&pos,cursectnum, &hiz,&hihit, &loz,&lohit, 128, (m32_clipping==1)?0:CLIPMASK0);
1866 helixhorne 1312
/*
1313
{
1314
    int32_t his = !(hihit&32768), los = !(lohit&32768);
1315
    if (m32_numdebuglines<64)
1316
        Bsprintf(m32_debugstr[m32_numdebuglines++], "s%d: cf[%s%d, %s%d] z(%d, %d)", cursectnum,
1317
                 his?"s":"w",hihit&16383, los?"s":"w",lohit&16383, hiz,loz);
1318
}
1319
*/
1843 helixhorne 1320
    oposz = pos.z;
109 terminx 1321
    if (zmode == 0)
1322
    {
1644 helixhorne 1323
        goalz = loz-(kensplayerheight<<8);  //playerheight pixels above floor
1324
        if (goalz < hiz+(16<<8))  //ceiling&floor too close
1325
            goalz = (loz+hiz)>>1;
109 terminx 1326
        goalz += mousz;
1644 helixhorne 1327
 
1328
        if (DOWN_BK(MOVEUP))  //A (stand high)
109 terminx 1329
        {
1836 helixhorne 1330
            goalz -= (16<<8);
1331
            if (DOWN_BK(RUN))
2092 helixhorne 1332
                goalz -= (24<<8);
109 terminx 1333
        }
1644 helixhorne 1334
        if (DOWN_BK(MOVEDOWN))  //Z (stand low)
109 terminx 1335
        {
1836 helixhorne 1336
            goalz += (12<<8);
1337
            if (DOWN_BK(RUN))
109 terminx 1338
                goalz += (12<<8);
1339
        }
5 Plagman 1340
 
1208 terminx 1341
        if (goalz != pos.z)
109 terminx 1342
        {
1208 terminx 1343
            if (pos.z < goalz) hvel += 64;
1344
            if (pos.z > goalz) hvel = ((goalz-pos.z)>>3);
5 Plagman 1345
 
1208 terminx 1346
            pos.z += hvel;
1347
            if (pos.z > loz-(4<<8)) pos.z = loz-(4<<8), hvel = 0;
1348
            if (pos.z < hiz+(4<<8)) pos.z = hiz+(4<<8), hvel = 0;
109 terminx 1349
        }
1350
    }
1351
    else
1352
    {
1208 terminx 1353
        goalz = pos.z;
1644 helixhorne 1354
        if (DOWN_BK(MOVEUP))  //A
109 terminx 1355
        {
7303 terminx 1356
            if (eitherALT)
584 terminx 1357
            {
1644 helixhorne 1358
                horiz = max(-100,horiz-((DOWN_BK(RUN)+1)*synctics*2));
584 terminx 1359
            }
1360
            else
1361
            {
109 terminx 1362
                if (zmode != 1)
1363
                    goalz -= (8<<8);
1364
                else
1365
                {
1366
                    zlock += (4<<8);
1644 helixhorne 1367
                    DOWN_BK(MOVEUP) = 0;
109 terminx 1368
                }
1369
            }
1370
        }
1644 helixhorne 1371
        if (DOWN_BK(MOVEDOWN))  //Z (stand low)
109 terminx 1372
        {
7303 terminx 1373
            if (eitherALT)
584 terminx 1374
            {
1644 helixhorne 1375
                horiz = min(300,horiz+((DOWN_BK(RUN)+1)*synctics*2));
584 terminx 1376
            }
1377
            else
1378
            {
109 terminx 1379
                if (zmode != 1)
1380
                    goalz += (8<<8);
1381
                else if (zlock > 0)
1382
                {
1383
                    zlock -= (4<<8);
1644 helixhorne 1384
                    DOWN_BK(MOVEDOWN) = 0;
109 terminx 1385
                }
1386
            }
1387
        }
5 Plagman 1388
 
2028 helixhorne 1389
        if (m32_clipping)
1854 helixhorne 1390
            inpclamp(&goalz, hiz+(4<<8), loz-(4<<8));
1644 helixhorne 1391
 
109 terminx 1392
        if (zmode == 1) goalz = loz-zlock;
2028 helixhorne 1393
        if (m32_clipping && (goalz < hiz+(4<<8)))
1644 helixhorne 1394
            goalz = ((loz+hiz)>>1);  //ceiling&floor too close
1208 terminx 1395
        if (zmode == 1) pos.z = goalz;
5 Plagman 1396
 
1208 terminx 1397
        if (goalz != pos.z)
109 terminx 1398
        {
1644 helixhorne 1399
            //if (pos.z < goalz) hvel += (32<<DOWN_BK(RUN));
1400
            //if (pos.z > goalz) hvel -= (32<<DOWN_BK(RUN));
1836 helixhorne 1401
            if (pos.z < goalz)
1402
                hvel = ((192*synctics)<<DOWN_BK(RUN));
1403
            else
1404
                hvel = -((192*synctics)<<DOWN_BK(RUN));
5 Plagman 1405
 
1208 terminx 1406
            pos.z += hvel;
5 Plagman 1407
 
2028 helixhorne 1408
            if (m32_clipping)
717 plagman 1409
            {
1208 terminx 1410
                if (pos.z > loz-(4<<8)) pos.z = loz-(4<<8), hvel = 0;
1411
                if (pos.z < hiz+(4<<8)) pos.z = hiz+(4<<8), hvel = 0;
717 plagman 1412
            }
109 terminx 1413
        }
1414
        else
1415
            hvel = 0;
1416
    }
5 Plagman 1417
 
1843 helixhorne 1418
    {
1419
        int16_t ocursectnum = cursectnum;
1420
        updatesectorz(pos.x,pos.y,pos.z, &cursectnum);
1421
        if (cursectnum<0)
1422
        {
1423
            if (zmode != 2)
1424
                pos.z = oposz;  // don't allow to fall into infinity when in void space
1425
            cursectnum = ocursectnum;
1426
        }
1427
    }
1830 helixhorne 1428
 
5277 terminx 1429
    if (pos.z != oposz && in3dmode())
1430
    {
1431
        silentmessage("x:%d y:%d z:%d ang:%d horiz:%d", pos.x, pos.y, pos.z, ang, horiz);
8050 pogokeen 1432
        getmessagetimeoff = (int32_t) totalclock+30;
5277 terminx 1433
    }
1434
 
109 terminx 1435
    searchit = 2;
1436
    if (searchstat >= 0)
1437
    {
6860 terminx 1438
        if ((bstatus&(1|2|4)) || keystatus[sc_Space])  // SPACE
109 terminx 1439
            searchit = 0;
5 Plagman 1440
 
6860 terminx 1441
        if (keystatus[sc_S])  //S (insert sprite) (3D)
109 terminx 1442
        {
2877 helixhorne 1443
            hitdata_t hit;
7495 hendricks2 1444
            vec2_t osearch = {searchx, searchy};
1445
            vec2_t bdim = {xdim, ydim};
1446
            if (m32_is2d3dmode())
1447
            {
1448
                xdim = XSIZE_2D3D;
1449
                ydim = YSIZE_2D3D;
1450
                searchx -= m32_2d3d.x;
1451
                searchy -= m32_2d3d.y;
1452
            }
1801 helixhorne 1453
 
5239 terminx 1454
            vec2_t da = { 16384, divscale14(searchx-(xdim>>1), xdim>>1) };
5 Plagman 1455
 
5239 terminx 1456
            rotatepoint(zerovec, da, ang, &da);
1457
 
5277 terminx 1458
#ifdef USE_OPENGL
6829 terminx 1459
            if (videoGetRenderMode() == REND_POLYMOST)
5277 terminx 1460
                hit = polymost_hitdata;
1461
            else
1462
#endif
1463
                hitscan((const vec3_t *)&pos,cursectnum,              //Start position
5239 terminx 1464
                    da.x,da.y,(scale(searchy,200,ydim)-horiz)*2000, //vector of 3D ang
2877 helixhorne 1465
                    &hit,CLIPMASK1);
5 Plagman 1466
 
2877 helixhorne 1467
            if (hit.sect >= 0)
109 terminx 1468
            {
5239 terminx 1469
                da.x = hit.pos.x;
1470
                da.y = hit.pos.y;
1644 helixhorne 1471
                if (gridlock && grid > 0)
109 terminx 1472
                {
1854 helixhorne 1473
                    if (AIMING_AT_WALL || AIMING_AT_MASKWALL)
2877 helixhorne 1474
                        hit.pos.z &= 0xfffffc00;
109 terminx 1475
                    else
5239 terminx 1476
                        locktogrid(&da.x, &da.y);
109 terminx 1477
                }
5 Plagman 1478
 
5239 terminx 1479
                i = insert_sprite_common(hit.sect, da.x, da.y);
5 Plagman 1480
 
1801 helixhorne 1481
                if (i < 0)
1482
                    message("Couldn't insert sprite.");
109 terminx 1483
                else
1801 helixhorne 1484
                {
1485
                    int32_t cz, fz;
5 Plagman 1486
 
2699 helixhorne 1487
                    handle_sprite_in_clipboard(i);
1801 helixhorne 1488
 
1854 helixhorne 1489
                    spriteoncfz(i, &cz, &fz);
3780 helixhorne 1490
                    sprite[i].z = clamp2(hit.pos.z, cz, fz);
5 Plagman 1491
 
1854 helixhorne 1492
                    if (AIMING_AT_WALL || AIMING_AT_MASKWALL)
109 terminx 1493
                    {
1801 helixhorne 1494
                        sprite[i].cstat &= ~48;
1495
                        sprite[i].cstat |= (16+64);
1496
 
2877 helixhorne 1497
                        correct_ornamented_sprite(i, hit.wall);
109 terminx 1498
                    }
1801 helixhorne 1499
                    else
4623 terminx 1500
                        sprite[i].cstat |= (tilesiz[sprite[i].picnum].y>=32);
5 Plagman 1501
 
1832 helixhorne 1502
                    correct_sprite_yoffset(i);
1503
 
1801 helixhorne 1504
                    asksave = 1;
1493 helixhorne 1505
 
1801 helixhorne 1506
                    VM_OnEvent(EVENT_INSERTSPRITE3D, i);
1507
                }
109 terminx 1508
            }
5 Plagman 1509
 
7495 hendricks2 1510
            xdim = bdim.x;
1511
            ydim = bdim.y;
1512
            searchx = osearch.x;
1513
            searchy = osearch.y;
6860 terminx 1514
            keystatus[sc_S] = 0;
109 terminx 1515
        }
5 Plagman 1516
 
6860 terminx 1517
        if (keystatus[sc_F5]||keystatus[sc_F6])  //F5,F6
109 terminx 1518
        {
331 terminx 1519
            switch (searchstat)
109 terminx 1520
            {
1854 helixhorne 1521
            case SEARCH_CEILING:
1522
            case SEARCH_FLOOR:
4555 hendricks2 1523
                CallExtShowSectorData(searchsector); break;
1854 helixhorne 1524
            case SEARCH_WALL:
1525
            case SEARCH_MASKWALL:
4555 hendricks2 1526
                CallExtShowWallData(searchwall); break;
1854 helixhorne 1527
            case SEARCH_SPRITE:
4555 hendricks2 1528
                CallExtShowSpriteData(searchwall); break;
109 terminx 1529
            }
1836 helixhorne 1530
 
6860 terminx 1531
            keystatus[sc_F5] = keystatus[sc_F6] = 0;
109 terminx 1532
        }
6860 terminx 1533
        if (keystatus[sc_F7]||keystatus[sc_F8])  //F7,F8
109 terminx 1534
        {
331 terminx 1535
            switch (searchstat)
109 terminx 1536
            {
1854 helixhorne 1537
            case SEARCH_CEILING:
1538
            case SEARCH_FLOOR:
4555 hendricks2 1539
                CallExtEditSectorData(searchsector); break;
1854 helixhorne 1540
            case SEARCH_WALL:
1541
            case SEARCH_MASKWALL:
4555 hendricks2 1542
                CallExtEditWallData(searchwall); break;
1854 helixhorne 1543
            case SEARCH_SPRITE:
4555 hendricks2 1544
                CallExtEditSpriteData(searchwall); break;
109 terminx 1545
            }
1836 helixhorne 1546
 
6860 terminx 1547
            keystatus[sc_F7] = keystatus[sc_F8] = 0;
109 terminx 1548
        }
5 Plagman 1549
 
109 terminx 1550
    }
1665 terminx 1551
 
5281 terminx 1552
    if (keystatus[buildkeys[BK_MODE2D_3D]] && !m32_is2d3dmode())  // Enter
109 terminx 1553
    {
1665 terminx 1554
 
6828 terminx 1555
        vid_gamma_3d = g_videoGamma;
1556
        vid_contrast_3d = g_videoContrast;
1557
        vid_brightness_3d = g_videoBrightness;
1679 helixhorne 1558
 
6828 terminx 1559
        g_videoGamma = g_videoContrast = 1.0;
1560
        g_videoBrightness = 0.0;
1665 terminx 1561
 
6829 terminx 1562
        videoSetPalette(0,0,0);
1679 helixhorne 1563
 
1648 helixhorne 1564
        keystatus[buildkeys[BK_MODE2D_3D]] = 0;
109 terminx 1565
        overheadeditor();
1648 helixhorne 1566
        keystatus[buildkeys[BK_MODE2D_3D]] = 0;
1665 terminx 1567
 
6828 terminx 1568
        g_videoGamma = vid_gamma_3d;
1569
        g_videoContrast = vid_contrast_3d;
1570
        g_videoBrightness = vid_brightness_3d;
1679 helixhorne 1571
 
1572
        vid_gamma_3d = vid_contrast_3d = vid_brightness_3d = -1;
1573
 
6829 terminx 1574
        videoSetPalette(GAMMA_CALC,0,0);
109 terminx 1575
    }
5 Plagman 1576
}
1577
 
1205 terminx 1578
char changechar(char dachar, int32_t dadir, char smooshyalign, char boundcheck)
5 Plagman 1579
{
109 terminx 1580
    if (dadir < 0)
1581
    {
1582
        if ((dachar > 0) || (boundcheck == 0))
1583
        {
1584
            dachar--;
1585
            if (smooshyalign > 0)
1586
                dachar = (dachar&0xf8);
1587
        }
1588
    }
1589
    else if (dadir > 0)
1590
    {
1591
        if ((dachar < 255) || (boundcheck == 0))
1592
        {
1593
            dachar++;
1594
            if (smooshyalign > 0)
1595
            {
1596
                if (dachar >= 256-8) dachar = 255;
1597
                else dachar = ((dachar+7)&0xf8);
1598
            }
1599
        }
1600
    }
5803 terminx 1601
    return dachar;
5 Plagman 1602
}
1603
 
1644 helixhorne 1604
 
1605
////////////////////// OVERHEADEDITOR //////////////////////
1606
 
2089 helixhorne 1607
// some 2d mode state
1608
static struct overheadstate
1609
{
2090 helixhorne 1610
    // number of backed up drawn walls
1611
    int32_t bak_wallsdrawn;
1612
 
2089 helixhorne 1613
    // state related to line drawing
1614
    int16_t suckwall, split;
1615
    int16_t splitsect;
1616
    int16_t splitstartwall;
1617
} ovh;
1618
 
1869 helixhorne 1619
 
3038 helixhorne 1620
static int32_t inside_editor(const vec3_t *pos, int32_t searchx, int32_t searchy, int32_t zoom,
1621
                             int32_t x, int32_t y, int16_t sectnum)
1830 helixhorne 1622
{
1623
    if (!m32_sideview)
1624
        return inside(x, y, sectnum);
1625
 
1626
    // if in side-view mode, use the screen coords instead
1627
    {
1628
        int32_t dst = MAXSECTORS+M32_FIXME_SECTORS-1, i, oi;
1629
        int32_t srcw=sector[sectnum].wallptr, dstw=MAXWALLS;
1630
        int32_t ret;
1631
 
1632
        if (sector[sectnum].wallnum > M32_FIXME_WALLS)
1633
            return -1;
1634
 
1635
        Bmemcpy(&sector[dst], &sector[sectnum], sizeof(sectortype));
1636
        sector[dst].wallptr = dstw;
1637
 
1638
        Bmemcpy(&wall[dstw], &wall[srcw], sector[dst].wallnum*sizeof(walltype));
1639
        for (i=dstw, oi=srcw; i<dstw+sector[dst].wallnum; i++, oi++)
1640
        {
1641
            wall[i].point2 += dstw-srcw;
1642
 
6831 terminx 1643
            editorGet2dScreenCoordinates(&wall[i].x, &wall[i].y, wall[i].x-pos->x, wall[i].y-pos->y, zoom);
1830 helixhorne 1644
            wall[i].y += getscreenvdisp(getflorzofslope(sectnum,wall[oi].x,wall[oi].y)-pos->z, zoom);
1645
            wall[i].x += halfxdim16;
1646
            wall[i].y += midydim16;
1647
        }
1648
 
1649
        i = numsectors;
1650
        numsectors = dst+1;
1651
        ret = inside(searchx, searchy, dst);
1652
        numsectors = i;
1653
        return ret;
1654
    }
1655
}
1656
 
3038 helixhorne 1657
int32_t inside_editor_curpos(int16_t sectnum)
1658
{
1659
    // TODO: take care: mous[xy]plc global vs overheadeditor auto
1660
    return inside_editor(&pos, searchx,searchy, zoom, mousxplc,mousyplc, sectnum);
1661
}
1662
 
1663
 
1730 helixhorne 1664
static inline void drawline16base(int32_t bx, int32_t by, int32_t x1, int32_t y1, int32_t x2, int32_t y2, char col)
1665
{
6831 terminx 1666
    editorDraw2dLine(bx+x1, by+y1, bx+x2, by+y2, col);
1730 helixhorne 1667
}
1668
 
5289 terminx 1669
void drawsmallabel(const char *text, char col, char backcol, char border, int32_t dax, int32_t day, int32_t daz)
1790 helixhorne 1670
{
6831 terminx 1671
    editorGet2dScreenCoordinates(&dax,&day, dax-pos.x,day-pos.y, zoom);
1790 helixhorne 1672
 
1832 helixhorne 1673
    if (m32_sideview)
1674
        day += getscreenvdisp(daz-pos.z, zoom);
1675
 
5293 terminx 1676
    int32_t const x1 = halfxdim16+dax-(Bstrlen(text)<<1);
1677
    int32_t const y1 = midydim16+day-4;
1678
    int32_t const x2 = x1 + (Bstrlen(text)<<2)+2;
1679
    int32_t const y2 = y1 + 7;
1792 helixhorne 1680
 
5289 terminx 1681
    int f = mulscale8(x2-x1, zoom);
1682
 
5293 terminx 1683
    if ((x1 <= -f) || (x2 >= xdim + f) || (y1 <= -f) || (y2 >= ydim16 + f))
1684
        return;
5289 terminx 1685
 
5293 terminx 1686
    printext16(x1,y1, col,backcol, text,1);
5289 terminx 1687
 
6831 terminx 1688
    editorDraw2dLine(x1-2, y1-2, x2-2, y1-2, border);
1689
    editorDraw2dLine(x1-2, y2+1, x2-2, y2+1, border);
5289 terminx 1690
 
6831 terminx 1691
    editorDraw2dLine(x1-3, y1-1, x1-3, y2+0, border);
1692
    editorDraw2dLine(x2-1, y1-1, x2-1, y2+0, border);
5289 terminx 1693
 
6831 terminx 1694
    editorDraw2dLine(x1-1,y1-1, x2-3,y1-1, backcol);
1695
    editorDraw2dLine(x1-1,y2+0, x2-3,y2+0, backcol);
1792 helixhorne 1696
 
6831 terminx 1697
    editorDraw2dLine(x1-2,y1+0, x1-2,y2-1, backcol);
1698
    editorDraw2dLine(x2-2,y1+0, x2-2,y2-1, backcol);
1699
    editorDraw2dLine(x2-3,y1+0, x2-3,y2+0, backcol);
5293 terminx 1700
 
6828 terminx 1701
    videoBeginDrawing(); //{{{
5293 terminx 1702
 
1703
    if ((unsigned)y1-1 < ydim16+0u && (unsigned) (x1-2) < xdim2d+0u && (unsigned) (x2-2) < xdim2d+0u)
1704
    {
1705
        drawpixel((char *) (frameplace + ((y1-1) * bytesperline) + (x1-2)), border);
1706
        drawpixel((char *) (frameplace + ((y1-1) * bytesperline) + (x2-2)), border);
1792 helixhorne 1707
    }
5293 terminx 1708
 
1709
    if ((unsigned) y2 < ydim16+0u && (unsigned) (x1-2) < xdim2d+0u && (unsigned) (x2-2) < xdim2d+0u)
1710
    {
1711
        drawpixel((char *) (frameplace + ((y2) * bytesperline) + (x1-2)), border);
1712
        drawpixel((char *) (frameplace + ((y2) * bytesperline) + (x2-2)), border);
1713
    }
1714
 
6828 terminx 1715
    videoEndDrawing();
1790 helixhorne 1716
}
1717
 
1730 helixhorne 1718
// backup highlighted sectors with sprites as mapinfo for later restoration
1719
// return values:
1720
//  -1: highlightsectorcnt<=0
1721
//   0: ok
1722
static int32_t backup_highlighted_map(mapinfofull_t *mapinfo)
1723
{
1724
    int32_t i, j, k, m, tmpnumwalls=0, tmpnumsprites=0;
2276 helixhorne 1725
    int16_t *const otonsect = (int16_t *)tempxyar;  // STRICTALIASING
2136 helixhorne 1726
    int16_t *const otonwall = ((int16_t *)tempxyar) + MAXWALLS;
1727
#ifdef YAX_ENABLE
1728
    int16_t otonbunch[YAX_MAXBUNCHES];
1729
    int16_t numsectsofbunch[YAX_MAXBUNCHES];  // ceilings + floors
1730
#endif
1730 helixhorne 1731
 
1732
    if (highlightsectorcnt <= 0)
1733
        return -1;
1734
 
2136 helixhorne 1735
#ifdef YAX_ENABLE
1736
    for (i=0; i<numyaxbunches; i++)
1737
        numsectsofbunch[i] = 0;
1738
#endif
1739
 
2135 helixhorne 1740
    // set up old-->new mappings
2132 helixhorne 1741
    j = 0;
1742
    k = 0;
1743
    for (i=0; i<numsectors; i++)
1744
    {
1745
        int32_t startwall, endwall;
1746
 
7876 terminx 1747
        if (hlsectorbitmap[i>>3]&pow2char[i&7])
2132 helixhorne 1748
        {
2136 helixhorne 1749
#ifdef YAX_ENABLE
1750
            int16_t bn[2], cf;
1751
 
1752
            yax_getbunches(i, &bn[0], &bn[1]);
1753
            for (cf=0; cf<2; cf++)
1754
                if (bn[cf] >= 0)
1755
                    numsectsofbunch[bn[cf]]++;
1756
#endif
2132 helixhorne 1757
            otonsect[i] = j++;
1758
 
1759
            for (WALLS_OF_SECTOR(i, m))
1760
                otonwall[m] = k++;
1761
        }
1762
        else
1763
        {
1764
            otonsect[i] = -1;
1765
 
1766
            for (WALLS_OF_SECTOR(i, m))
1767
                otonwall[m] = -1;
1768
        }
1769
    }
1770
 
2136 helixhorne 1771
#ifdef YAX_ENABLE
1772
    j = 0;
1773
    for (i=0; i<numyaxbunches; i++)
1774
    {
1775
        // only back up complete bunches
1776
        if (numsectsofbunch[i] == yax_numsectsinbunch(i, 0)+yax_numsectsinbunch(i, 1))
2963 helixhorne 1777
            otonbunch[i] = j++;  // kept bunch
2136 helixhorne 1778
        else
2963 helixhorne 1779
            otonbunch[i] = -1;  // discarded bunch
2136 helixhorne 1780
    }
1781
    mapinfo->numyaxbunches = j;
1782
#endif
1783
 
1730 helixhorne 1784
    // count walls & sprites
1785
    for (i=0; i<highlightsectorcnt; i++)
1786
    {
1787
        tmpnumwalls += sector[highlightsector[i]].wallnum;
1788
 
1789
        m = headspritesect[highlightsector[i]];
1790
        while (m != -1)
1791
        {
1792
            tmpnumsprites++;
1793
            m = nextspritesect[m];
1794
        }
1795
    }
1796
 
1797
    // allocate temp storage
5796 terminx 1798
    mapinfo->sector = (usectortype *)Xmalloc(highlightsectorcnt * sizeof(sectortype));
1799
    mapinfo->wall = (uwalltype *)Xmalloc(tmpnumwalls * sizeof(walltype));
2135 helixhorne 1800
 
2136 helixhorne 1801
#ifdef YAX_ENABLE
1802
    if (mapinfo->numyaxbunches > 0)
1803
    {
4491 helixhorne 1804
        mapinfo->bunchnum = (int16_t *)Xmalloc(highlightsectorcnt*2*sizeof(int16_t));
1805
        mapinfo->ynextwall = (int16_t *)Xmalloc(tmpnumwalls*2*sizeof(int16_t));
2136 helixhorne 1806
    }
1807
    else
1808
    {
1809
        mapinfo->bunchnum = mapinfo->ynextwall = NULL;
1810
    }
1811
#endif
1812
 
1730 helixhorne 1813
    if (tmpnumsprites>0)
1814
    {
5796 terminx 1815
        mapinfo->sprite = (uspritetype *)Xmalloc(tmpnumsprites * sizeof(spritetype));
1730 helixhorne 1816
    }
2135 helixhorne 1817
    else
1818
    {
1819
        // would never be accessed because mapinfo->numsprites is 0, but cleaner
1820
        mapinfo->sprite = NULL;
1821
    }
1730 helixhorne 1822
 
1823
 
1824
    // copy everything over
1825
    tmpnumwalls = 0;
1826
    tmpnumsprites = 0;
1827
    for (i=0; i<highlightsectorcnt; i++)
1828
    {
1829
        k = highlightsector[i];
1830
        Bmemcpy(&mapinfo->sector[i], &sector[k], sizeof(sectortype));
1831
        mapinfo->sector[i].wallptr = tmpnumwalls;
1832
 
2136 helixhorne 1833
#ifdef YAX_ENABLE
2963 helixhorne 1834
        if (mapinfo->numyaxbunches > 0 || numyaxbunches > 0)
2136 helixhorne 1835
        {
1836
            int16_t bn[2];
1837
 
1838
            yax_getbunches(k, &bn[0], &bn[1]);
1839
            for (j=0; j<2; j++)
2963 helixhorne 1840
            {
1841
                // old bunchnum, new bunchnum
1842
                int32_t obn=bn[j], nbn=(obn>=0) ? otonbunch[obn] : -1;
1843
 
1844
                if (mapinfo->numyaxbunches > 0)
1845
                    mapinfo->bunchnum[2*i + j] = nbn;
4011 helixhorne 1846
 
2963 helixhorne 1847
                if (obn >= 0 && nbn < 0)
1848
                {
4011 helixhorne 1849
                    // A bunch was discarded.
7603 terminx 1850
                    auto const sec = &mapinfo->sector[i];
4011 helixhorne 1851
# if !defined NEW_MAP_FORMAT
3174 helixhorne 1852
                    uint16_t *const cs = j==YAX_CEILING ? &sec->ceilingstat : &sec->floorstat;
2963 helixhorne 1853
                    uint8_t *const xp = j==YAX_CEILING ? &sec->ceilingxpanning : &sec->floorxpanning;
1854
 
1855
                    *cs &= ~YAX_BIT;
1856
                    *xp = 0;
4011 helixhorne 1857
# else
1858
                    if (j == YAX_CEILING)
1859
                        sec->ceilingbunch = -1;
1860
                    else
1861
                        sec->floorbunch = -1;
1862
# endif
2963 helixhorne 1863
                }
1864
            }
2136 helixhorne 1865
        }
1866
#endif
1867
 
1730 helixhorne 1868
        for (j=0; j<sector[k].wallnum; j++)
1869
        {
2136 helixhorne 1870
            m = sector[k].wallptr;
1871
            Bmemcpy(&mapinfo->wall[tmpnumwalls+j], &wall[m+j], sizeof(walltype));
1872
            mapinfo->wall[tmpnumwalls+j].point2 += (tmpnumwalls-m);
2132 helixhorne 1873
 
2136 helixhorne 1874
#ifdef YAX_ENABLE
4012 helixhorne 1875
            if (mapinfo->numyaxbunches > 0 || numyaxbunches > 0)
2136 helixhorne 1876
            {
2965 helixhorne 1877
                int32_t cf;
2136 helixhorne 1878
 
1879
                for (cf=0; cf<2; cf++)
1880
                {
2965 helixhorne 1881
                    const int32_t ynw = yax_getnextwall(m+j, cf);
1882
                    const int32_t nynw = (ynw >= 0) ? otonwall[ynw] : -1;
1883
 
1884
                    if (mapinfo->numyaxbunches > 0)
1885
                        mapinfo->ynextwall[2*(tmpnumwalls+j) + cf] = nynw;
1886
 
1887
                    if (ynw >= 0 && nynw < 0)  // CLEAR_YNEXTWALLS
1888
                        YAX_PTRNEXTWALL(mapinfo->wall, tmpnumwalls+j, cf) = YAX_NEXTWALLDEFAULT(cf);
2136 helixhorne 1889
                }
1890
            }
1891
#endif
2132 helixhorne 1892
            m = mapinfo->wall[tmpnumwalls+j].nextsector;
1893
            if (m < 0 || otonsect[m] < 0)
1894
            {
1895
                mapinfo->wall[tmpnumwalls+j].nextsector = -1;
1896
                mapinfo->wall[tmpnumwalls+j].nextwall = -1;
1897
            }
1898
            else
1899
            {
1900
                mapinfo->wall[tmpnumwalls+j].nextsector = otonsect[m];
1901
                m = mapinfo->wall[tmpnumwalls+j].nextwall;
1902
                mapinfo->wall[tmpnumwalls+j].nextwall = otonwall[m];
1903
            }
1730 helixhorne 1904
        }
1905
        tmpnumwalls += j;
1906
 
1907
        m = headspritesect[highlightsector[i]];
1908
        while (m != -1)
1909
        {
1910
            Bmemcpy(&mapinfo->sprite[tmpnumsprites], &sprite[m], sizeof(spritetype));
2132 helixhorne 1911
            mapinfo->sprite[tmpnumsprites].sectnum = otonsect[highlightsector[i]];
1730 helixhorne 1912
            m = nextspritesect[m];
1913
            tmpnumsprites++;
1914
        }
1915
    }
1916
 
1917
 
1918
    mapinfo->numsectors = highlightsectorcnt;
1919
    mapinfo->numwalls = tmpnumwalls;
1920
    mapinfo->numsprites = tmpnumsprites;
1921
 
1922
    return 0;
1923
}
1924
 
1925
static void mapinfofull_free(mapinfofull_t *mapinfo)
1926
{
7705 terminx 1927
    Xfree(mapinfo->sector);
2136 helixhorne 1928
#ifdef YAX_ENABLE
1929
    if (mapinfo->numyaxbunches > 0)
1930
    {
7705 terminx 1931
        Xfree(mapinfo->bunchnum);
1932
        Xfree(mapinfo->ynextwall);
2136 helixhorne 1933
    }
1934
#endif
7705 terminx 1935
    Xfree(mapinfo->wall);
1730 helixhorne 1936
    if (mapinfo->numsprites>0)
7705 terminx 1937
        Xfree(mapinfo->sprite);
1730 helixhorne 1938
}
1939
 
1940
// restore map saved with backup_highlighted_map, also
1941
// frees mapinfo's sector, wall, (sprite) in any case.
1942
// return values:
1943
//  -1: limits exceeded
1944
//   0: ok
2138 helixhorne 1945
// forreal: if 0, only test if we have enough space (same return values)
1946
static int32_t restore_highlighted_map(mapinfofull_t *mapinfo, int32_t forreal)
1730 helixhorne 1947
{
2963 helixhorne 1948
    int32_t i, j, onumsectors=numsectors, newnumsectors, newnumwalls;
1730 helixhorne 1949
 
1950
    if (numsectors+mapinfo->numsectors>MAXSECTORS || numwalls+mapinfo->numwalls>MAXWALLS
2136 helixhorne 1951
#ifdef YAX_ENABLE
1952
            || numyaxbunches+mapinfo->numyaxbunches > YAX_MAXBUNCHES
1953
#endif
2478 helixhorne 1954
            || Numsprites+mapinfo->numsprites>MAXSPRITES)
1730 helixhorne 1955
    {
1956
        mapinfofull_free(mapinfo);
1957
        return -1;
1958
    }
1959
 
2138 helixhorne 1960
    if (!forreal)
1961
        return 0;
1962
 
1730 helixhorne 1963
    newnumsectors = numsectors + mapinfo->numsectors;
1964
    newnumwalls = numwalls + mapinfo->numwalls;
1965
 
1966
    // copy sectors & walls
1967
    Bmemcpy(&sector[numsectors], mapinfo->sector, mapinfo->numsectors*sizeof(sectortype));
1968
    Bmemcpy(&wall[numwalls], mapinfo->wall, mapinfo->numwalls*sizeof(walltype));
1969
 
1970
    // tweak index members
1971
    for (i=numwalls; i<newnumwalls; i++)
1972
    {
1973
        wall[i].point2 += numwalls;
2132 helixhorne 1974
 
1975
        if (wall[i].nextsector >= 0)
1976
        {
1977
            wall[i].nextsector += numsectors;
1978
            wall[i].nextwall += numwalls;
1979
        }
2136 helixhorne 1980
#ifdef YAX_ENABLE
1981
        for (j=0; j<2; j++)
1982
        {
1983
            if (mapinfo->numyaxbunches > 0)
4011 helixhorne 1984
            {
2136 helixhorne 1985
                yax_setnextwall(i, j, mapinfo->ynextwall[2*(i-numwalls) + j]>=0 ?
1986
                                numwalls+mapinfo->ynextwall[2*(i-numwalls) + j] : -1);
4011 helixhorne 1987
            }
1988
            else
1989
            {
3658 helixhorne 1990
# if !defined NEW_MAP_FORMAT
4011 helixhorne 1991
                // XXX: When copying a TROR portion into a non-TROR map (e.g. a
1992
                // new one), tags denoting ynextwalls are left in place.
2965 helixhorne 1993
                wall[i].cstat &= ~YAX_NEXTWALLBIT(j);  // CLEAR_YNEXTWALLS
4011 helixhorne 1994
# else
1995
                yax_setnextwall(i, j, -1);
3658 helixhorne 1996
# endif
4011 helixhorne 1997
            }
2136 helixhorne 1998
        }
1999
#endif
1730 helixhorne 2000
    }
2136 helixhorne 2001
    for (i=numsectors; i<newnumsectors; i++)
2002
        sector[i].wallptr += numwalls;
1730 helixhorne 2003
 
2132 helixhorne 2004
    // highlight copied sectors
2136 helixhorne 2005
 
2132 helixhorne 2006
    numsectors = newnumsectors;
2007
 
1730 helixhorne 2008
    Bmemset(hlsectorbitmap, 0, sizeof(hlsectorbitmap));
2009
    for (i=onumsectors; i<newnumsectors; i++)
2135 helixhorne 2010
    {
7876 terminx 2011
        hlsectorbitmap[i>>3] |= pow2char[i&7];
2136 helixhorne 2012
 
2135 helixhorne 2013
#ifdef YAX_ENABLE
2136 helixhorne 2014
        for (j=0; j<2; j++)
2963 helixhorne 2015
        {
2136 helixhorne 2016
            if (mapinfo->numyaxbunches > 0)
2963 helixhorne 2017
            {
2018
                int32_t bn = mapinfo->bunchnum[2*(i-onumsectors)+j];
2019
                yax_setbunch(i, j, bn>=0 ? numyaxbunches+bn : -2);
2020
                // -2 clears forward yax-nextwall links.
2021
                // XXX: still may wrongly reset xpanning.
2022
            }
2136 helixhorne 2023
            else
2963 helixhorne 2024
                Bassert(yax_getbunch(i, j) < 0);
2025
        }
2135 helixhorne 2026
#endif
2027
    }
1730 helixhorne 2028
 
2029
    // insert sprites
2030
    for (i=0; i<mapinfo->numsprites; i++)
2031
    {
7603 terminx 2032
        uspriteptr_t srcspr = &mapinfo->sprite[i];
3897 helixhorne 2033
        int32_t sect = onumsectors + srcspr->sectnum;
2034
 
2035
        j = insertsprite(sect, srcspr->statnum);
2036
        Bassert(j >= 0);
2037
        Bmemcpy(&sprite[j], srcspr, sizeof(spritetype));
1730 helixhorne 2038
        sprite[j].sectnum = sect;
2039
    }
2040
 
2136 helixhorne 2041
    mapinfofull_free(mapinfo);
2042
 
1730 helixhorne 2043
    numwalls = newnumwalls;
2044
 
2045
    update_highlightsector();
2046
 
2136 helixhorne 2047
#ifdef YAX_ENABLE
2048
    if (mapinfo->numyaxbunches > 0)
2049
        yax_update(0);
2050
#endif
2051
    yax_updategrays(pos.z);
2052
 
1730 helixhorne 2053
    return 0;
2054
}
2055
 
2056
 
7078 terminx 2057
static int16_t newnumwalls=-1;
1622 helixhorne 2058
 
1927 helixhorne 2059
void ovh_whiteoutgrab(int32_t restoreredwalls)
1644 helixhorne 2060
{
2061
    int32_t i, j, k, startwall, endwall;
1887 helixhorne 2062
#if 0
2063
//def YAX_ENABLE
1886 helixhorne 2064
    int16_t cb, fb;
2065
#endif
1644 helixhorne 2066
 
1927 helixhorne 2067
    if (restoreredwalls)
2068
    {
2069
        // restore onextwalls first
2070
        for (i=0; i<numsectors; i++)
2071
            for (WALLS_OF_SECTOR(i, j))
2072
                checksectorpointer(j, i);
2073
    }
2074
 
1886 helixhorne 2075
    for (i=0; i<MAXWALLS; i++)
2076
        onextwall[i] = -1;
2077
 
1644 helixhorne 2078
    //White out all bordering lines of grab that are
2079
    //not highlighted on both sides
2080
    for (i=highlightsectorcnt-1; i>=0; i--)
1866 helixhorne 2081
        for (WALLS_OF_SECTOR(highlightsector[i], j))
1644 helixhorne 2082
        {
1886 helixhorne 2083
            if (wall[j].nextwall < 0)
2084
                continue;
1866 helixhorne 2085
 
1886 helixhorne 2086
            k = wall[j].nextsector;
2087
 
7876 terminx 2088
            if (hlsectorbitmap[k>>3]&pow2char[k&7])
1886 helixhorne 2089
                continue;
2090
#if 0
2091
//def YAX_ENABLE
2092
            // internal red walls are kept red
2093
            yax_getbunches(highlightsector[i], &cb, &fb);
2094
            if (cb>=0 && yax_getbunch(k, YAX_CEILING)>=0)
2095
                continue;
2096
            if (fb>=0 && yax_getbunch(k, YAX_FLOOR)>=0)
2097
                continue;
2098
#endif
2099
            onextwall[j] = wall[j].nextwall;
2100
 
2101
            NEXTWALL(j).nextwall = -1;
2102
            NEXTWALL(j).nextsector = -1;
2103
            wall[j].nextwall = -1;
2104
            wall[j].nextsector = -1;
1644 helixhorne 2105
        }
1886 helixhorne 2106
 
2121 helixhorne 2107
    if (highlightsectorcnt > 0)
2108
        mkonwvalid();
2109
    else
2716 helixhorne 2110
        mkonwinvalid_keeptempsect();
1644 helixhorne 2111
}
2112
 
1854 helixhorne 2113
static void duplicate_selected_sectors(void)
1701 helixhorne 2114
{
2138 helixhorne 2115
    mapinfofull_t mapinfo;
2116
    int32_t i, j, onumsectors;
2117
#ifdef YAX_ENABLE
2118
    int32_t onumyaxbunches;
2119
#endif
2120
    int32_t minx=INT32_MAX, maxx=INT32_MIN, miny=INT32_MAX, maxy=INT32_MIN, dx, dy;
2121
 
2122
    i = backup_highlighted_map(&mapinfo);
2123
 
2124
    if (i < 0)
2125
    {
2126
        message("Out of memory!");
2127
        return;
2128
    }
2129
 
2130
    i = restore_highlighted_map(&mapinfo, 0);
2131
    if (i < 0)
2132
    {
2133
        // XXX: no, might be another limit too.  Better message needed.
2134
        printmessage16("Copying sectors would exceed sector or wall limit.");
2135
        return;
2136
    }
2137
 
2138
    // restoring would succeed, tweak things...
2139
    Bmemset(hlsectorbitmap, 0, sizeof(hlsectorbitmap));
2140
    for (i=0; i<highlightsectorcnt; i++)
2141
    {
2142
        int32_t startwall, endwall;
2143
 
2144
        // first, make red lines of old selected sectors, effectively
2145
        // restoring the original state
2146
        for (WALLS_OF_SECTOR(highlightsector[i], j))
2147
        {
2148
            if (wall[j].nextwall >= 0)
2149
                checksectorpointer(wall[j].nextwall,wall[j].nextsector);
2150
            checksectorpointer(j, highlightsector[i]);
2151
 
7078 terminx 2152
            minx = min(minx, TrackerCast(wall[j].x));
2153
            maxx = max(maxx, TrackerCast(wall[j].x));
2154
            miny = min(miny, TrackerCast(wall[j].y));
2155
            maxy = max(maxy, TrackerCast(wall[j].y));
2138 helixhorne 2156
        }
2157
    }
2158
 
2159
    // displace walls & sprites of new sectors by a small amount:
2160
    // calculate displacement
2161
    if (grid>0 && grid<9)
2162
        dx = max(2048>>grid, 128);
2163
    else
2164
        dx = 512;
2165
    dy = -dx;
2166
    if (maxx+dx >= editorgridextent) dx*=-1;
2167
    if (minx+dx <= -editorgridextent) dx*=-1;
2168
    if (maxy+dy >= editorgridextent) dy*=-1;
2169
    if (miny+dy <= -editorgridextent) dy*=-1;
2170
 
2171
    onumsectors = numsectors;
2204 helixhorne 2172
#ifdef YAX_ENABLE
2138 helixhorne 2173
    onumyaxbunches = numyaxbunches;
2204 helixhorne 2174
#endif
2138 helixhorne 2175
    // restore! this will not fail.
2176
    restore_highlighted_map(&mapinfo, 1);
2177
 
2178
    // displace
2179
    for (i=onumsectors; i<numsectors; i++)
2180
    {
2181
        for (j=sector[i].wallptr; j<sector[i].wallptr+sector[i].wallnum; j++)
2182
        {
2183
            wall[j].x += dx;
2184
            wall[j].y += dy;
2185
        }
2186
 
2187
        for (j=headspritesect[i]; j>=0; j=nextspritesect[j])
2188
        {
2189
            sprite[j].x += dx;
2190
            sprite[j].y += dy;
2191
        }
2192
    }
2193
 
2194
#ifdef YAX_ENABLE
2195
    if (numyaxbunches > onumyaxbunches)
2196
        printmessage16("Sectors duplicated, creating %d new bunches.", numyaxbunches-onumyaxbunches);
2197
    else
2198
#endif
5302 terminx 2199
        printmessage16("Sectors duplicated.");
2138 helixhorne 2200
    asksave = 1;
2201
 
2202
#ifdef YAX_ENABLE
2203
    if (numyaxbunches > onumyaxbunches)
2204
        yax_update(0);
2205
#endif
2206
    yax_updategrays(pos.z);
2207
}
2208
 
1886 helixhorne 2209
 
1854 helixhorne 2210
static void duplicate_selected_sprites(void)
1701 helixhorne 2211
{
1730 helixhorne 2212
    int32_t i, j, k=0;
1701 helixhorne 2213
 
1730 helixhorne 2214
    for (i=0; i<highlightcnt; i++)
2479 helixhorne 2215
        if ((highlight[i]&0xc000) == 16384)
2216
            k++;
1730 helixhorne 2217
 
2479 helixhorne 2218
    if (Numsprites + k <= MAXSPRITES)
1701 helixhorne 2219
    {
2220
        for (i=0; i<highlightcnt; i++)
2221
            if ((highlight[i]&0xc000) == 16384)
2222
            {
2223
                //duplicate sprite
2224
                k = (highlight[i]&16383);
2225
                j = insertsprite(sprite[k].sectnum,sprite[k].statnum);
2226
                Bmemcpy(&sprite[j],&sprite[k],sizeof(spritetype));
1730 helixhorne 2227
//                sprite[j].sectnum = sprite[k].sectnum;   //Don't let memcpy overwrite sector!
2228
//                setsprite(j,(vec3_t *)&sprite[j]);
1701 helixhorne 2229
            }
2478 helixhorne 2230
 
5302 terminx 2231
        printmessage16("Sprites duplicated.");
1701 helixhorne 2232
        asksave = 1;
2233
    }
2234
    else
2235
    {
2236
        printmessage16("Copying sprites would exceed sprite limit.");
2237
    }
2238
}
2239
 
1801 helixhorne 2240
static void correct_ornamented_sprite(int32_t i, int32_t hitw)
2241
{
2242
    int32_t j;
2243
 
2244
    if (hitw >= 0)
3038 helixhorne 2245
    {
1801 helixhorne 2246
        sprite[i].ang = (getangle(POINT2(hitw).x-wall[hitw].x,
2247
                                  POINT2(hitw).y-wall[hitw].y)+512)&2047;
2248
 
3038 helixhorne 2249
        //Make sure sprite's in right sector
2250
        if (inside(sprite[i].x, sprite[i].y, sprite[i].sectnum) != 1)
2251
        {
2252
            j = wall[hitw].point2;
2253
            sprite[i].x -= ksgn(wall[j].y-wall[hitw].y);
2254
            sprite[i].y += ksgn(wall[j].x-wall[hitw].x);
2255
        }
1801 helixhorne 2256
    }
2257
}
2258
 
2259
void DoSpriteOrnament(int32_t i)
2260
{
2877 helixhorne 2261
    hitdata_t hit;
1801 helixhorne 2262
 
2263
    hitscan((const vec3_t *)&sprite[i],sprite[i].sectnum,
2264
            sintable[(sprite[i].ang+1536)&2047],
2265
            sintable[(sprite[i].ang+1024)&2047],
2266
            0,
2877 helixhorne 2267
            &hit,CLIPMASK1);
1801 helixhorne 2268
 
4901 terminx 2269
    if (hit.sect == -1)
2270
        return;
2271
 
2877 helixhorne 2272
    sprite[i].x = hit.pos.x;
2273
    sprite[i].y = hit.pos.y;
2274
    sprite[i].z = hit.pos.z;
2275
    changespritesect(i, hit.sect);
1801 helixhorne 2276
 
2877 helixhorne 2277
    correct_ornamented_sprite(i, hit.wall);
1801 helixhorne 2278
}
2279
 
1854 helixhorne 2280
void update_highlight(void)
1701 helixhorne 2281
{
2282
    int32_t i;
2283
 
2284
    highlightcnt = 0;
2285
    for (i=0; i<numwalls; i++)
7876 terminx 2286
        if (show2dwall[i>>3]&pow2char[i&7])
1701 helixhorne 2287
            highlight[highlightcnt++] = i;
2288
    for (i=0; i<MAXSPRITES; i++)
2289
        if (sprite[i].statnum < MAXSTATUS)
2290
        {
7876 terminx 2291
            if (show2dsprite[i>>3]&pow2char[i&7])
1701 helixhorne 2292
                highlight[highlightcnt++] = i+16384;
2293
        }
2294
        else
7876 terminx 2295
            show2dsprite[i>>3] &= ~pow2char[i&7];
1701 helixhorne 2296
 
2297
    if (highlightcnt == 0)
2298
        highlightcnt = -1;
2299
}
2300
 
1854 helixhorne 2301
void update_highlightsector(void)
1728 helixhorne 2302
{
2303
    int32_t i;
2304
 
1901 helixhorne 2305
    minhlsectorfloorz = INT32_MAX;
2144 helixhorne 2306
    numhlsecwalls = 0;
1901 helixhorne 2307
 
1728 helixhorne 2308
    highlightsectorcnt = 0;
2309
    for (i=0; i<numsectors; i++)
7876 terminx 2310
        if (hlsectorbitmap[i>>3]&pow2char[i&7])
1901 helixhorne 2311
        {
1728 helixhorne 2312
            highlightsector[highlightsectorcnt++] = i;
7078 terminx 2313
            minhlsectorfloorz = min(minhlsectorfloorz, TrackerCast(sector[i].floorz));
2144 helixhorne 2314
            numhlsecwalls += sector[i].wallnum;
1901 helixhorne 2315
        }
1728 helixhorne 2316
 
2317
    if (highlightsectorcnt==0)
1901 helixhorne 2318
    {
2319
        minhlsectorfloorz = 0;
1728 helixhorne 2320
        highlightsectorcnt = -1;
1901 helixhorne 2321
    }
1728 helixhorne 2322
}
2323
 
1801 helixhorne 2324
// Get average point of sectors
2325
static void get_sectors_center(const int16_t *sectors, int32_t numsecs, int32_t *cx, int32_t *cy)
2326
{
2327
    int32_t i, j, k=0, dax = 0, day = 0;
2328
    int32_t startwall, endwall;
1760 helixhorne 2329
 
1801 helixhorne 2330
    for (i=0; i<numsecs; i++)
2331
    {
2332
        for (WALLS_OF_SECTOR(sectors[i], j))
2333
        {
2334
            dax += wall[j].x;
2335
            day += wall[j].y;
2336
            k++;
2337
        }
2338
    }
2339
 
2340
    if (k > 0)
2341
    {
2342
        dax /= k;
2343
        day /= k;
2344
    }
2345
 
2346
    *cx = dax;
2347
    *cy = day;
2348
}
2349
 
2088 helixhorne 2350
static int32_t insert_sprite_common(int32_t sectnum, int32_t dax, int32_t day)
1801 helixhorne 2351
{
2352
    int32_t i, j, k;
2353
 
2088 helixhorne 2354
    i = insertsprite(sectnum,0);
1801 helixhorne 2355
    if (i < 0)
2356
        return -1;
2357
 
2358
    sprite[i].x = dax, sprite[i].y = day;
8440 hendricks2 2359
    sprite[i].cstat = defaultspritecstat;
1801 helixhorne 2360
    sprite[i].shade = 0;
2361
    sprite[i].pal = 0;
2362
    sprite[i].xrepeat = 64, sprite[i].yrepeat = 64;
2363
    sprite[i].xoffset = 0, sprite[i].yoffset = 0;
2364
    sprite[i].ang = 1536;
2365
    sprite[i].xvel = 0; sprite[i].yvel = 0; sprite[i].zvel = 0;
2366
    sprite[i].owner = -1;
2367
    sprite[i].clipdist = 32;
2368
    sprite[i].lotag = 0;
2369
    sprite[i].hitag = 0;
2370
    sprite[i].extra = -1;
2371
 
2372
    Bmemset(localartfreq, 0, sizeof(localartfreq));
2373
    for (k=0; k<MAXSPRITES; k++)
2043 helixhorne 2374
        if (sprite[k].statnum < MAXSTATUS && k!=i)
2375
            localartfreq[sprite[k].picnum]++;
1801 helixhorne 2376
 
2377
    j = 0;
2378
    for (k=0; k<MAXTILES; k++)
2379
        if (localartfreq[k] > localartfreq[j