Cube  Diff

Differences From Artifact [ed7b27bed9]:

To Artifact [df7a7d4fb4]:


1


2
3
4
5

6
7
8


9
10

11
12
13


14
15
16
17
18
19
20
21










22
23
24
25

26
27
28
29
30
31
32
33

34

35

36

37
38
39





40
41
42


43
44

45
46
47
48
49
50
51
52
53











54
55
56
57

58

59
60
61
62
63
64








65
66

67

68
69
70
71




72
73

74

75

76
77


78
79

80
81
82








83

84

85
86
87
88
89




90
91

92

93
94
95
96
97
98







99
100
101

102


103

104
105
106
107





108
109

110

111
112

113

114
115
116
117
118
119






120
121
122
123
124
125
126
127








128
129
130


131
132
133
134
135






136
137
138
139
140
141
142
143







144
145

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164




























165
166

167
168
169
170
171
172
173
174
175










176
177

178
179
180
181



182
183
184
185


186

187

188
189
190
191
192
193
194







195
196

197

198
199
200


201
202

203

204
205
206
207
208
209








210
211
212
213

214

215
216
217
218




219
220

221

222
223
224
225
226
227
228
229
230
231
232
















233
234

235


236
237
238
239
240




241
242
243
244
245
246
247
248








249
250

251

252
253

254
255
256
257
258
259
260
261







262
263
264
265
266


267

268

269
270

271
272
273




274
275

276
277
278
279




280
281

282

283
284
285
286
287




288
289
290
291

292

293
294

295
296
297
298
299
300













301
302

303

304
305
306
307
308
309
310
311
312
313
314














315
316

317

318
319
320
321
322
323





324
325
326
327
328
329
330
331
332




















333



334

335
336
337

338
339

340

341
342
343
344
345
346
347









348
349

350
351
352














353
354
355
356
357

358

359
360
361


362
363
364
365
366






367
368
369
370







371
372

373

374
375
376
377
378




379
380
381
382

383

384
385
386


387
388

389

390
391
392
393



394
395
396
397
398
399

400

401
402

403
404
405
406
407
408






409
410

411

412
413
414
415
416
417
418
419
420
421
422














423
424

425

426
427
428
429
430
431
432
433
434










435
436

437

438
439
440
441
442
443
444
445
446
447
448
449
450












451
452
453
454


455
456
457
458




459
460

461

462
463
464


465
466

467

468
469
470



471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487

1
2
3
4
5

6
7
8

9
10
11

12



13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42

43
44
45

46
47
48



49
50
51
52
53



54
55


56









57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

73
74





75
76
77
78
79
80
81
82
83
84
85

86
87



88
89
90
91
92
93
94

95
96
97


98
99
100
101
102



103
104
105
106
107
108
109
110
111
112

113
114




115
116
117
118
119
120
121

122
123





124
125
126
127
128
129
130
131
132

133
134
135
136

137
138



139
140
141
142
143
144
145
146

147
148

149
150
151






152
153
154
155
156
157
158







159
160
161
162
163
164
165
166
167


168
169
170




171
172
173
174
175
176
177







178
179
180
181
182
183
184
185

186



















187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

216









217
218
219
220
221
222
223
224
225
226
227

228




229
230
231
232
233


234
235
236
237

238
239






240
241
242
243
244
245
246
247
248
249

250
251


252
253
254
255
256

257
258





259
260
261
262
263
264
265
266
267
268
269
270
271

272
273



274
275
276
277
278
279
280

281
282










283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

302
303
304




305
306
307
308








309
310
311
312
313
314
315
316
317
318
319

320
321

322








323
324
325
326
327
328
329
330
331
332


333
334
335
336

337
338

339



340
341
342
343


344




345
346
347
348
349
350
351

352
353




354
355
356
357
358
359
360
361
362

363
364

365






366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

382
383










384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400

401
402





403
404
405
406
407









408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431

432



433
434
435
436

437
438






439
440
441
442
443
444
445
446
447
448
449
450



451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470

471
472


473
474





475
476
477
478
479
480




481
482
483
484
485
486
487
488
489
490

491
492




493
494
495
496
497
498
499
500
501

502
503


504
505
506
507
508

509
510



511
512
513
514
515
516
517
518
519
520

521
522

523






524
525
526
527
528
529
530
531
532

533
534










535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551

552
553








554
555
556
557
558
559
560
561
562
563
564
565
566

567
568












569
570
571
572
573
574
575
576
577
578
579
580
581
582


583
584




585
586
587
588

589
590

591
592


593
594
595
596
597

598
599


600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617


-
+
+



-
+


-
+
+

-
+
-
-
-
+
+







-
+
+
+
+
+
+
+
+
+
+



-
+







-
+

+
-
+

+
-
-
-
+
+
+
+
+
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+




+
-
+

-
-
-
-
-
+
+
+
+
+
+
+
+


+
-
+

-
-
-
+
+
+
+


+
-
+

+
-
-
+
+


+
-
-
-
+
+
+
+
+
+
+
+

+
-
+

-
-
-
-
+
+
+
+


+
-
+

-
-
-
-
-
+
+
+
+
+
+
+


-
+

+
+
-
+

-
-
-
+
+
+
+
+


+
-
+

-
+

+
-
-
-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
+
+

-
-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
-
+
+
+


-
-
+
+

+
-
+

-
-
-
-
-
-
+
+
+
+
+
+
+


+
-
+

-
-
+
+


+
-
+

-
-
-
-
-
+
+
+
+
+
+
+
+




+
-
+

-
-
-
+
+
+
+


+
-
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
-
+
+

-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+


+
-
+

-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+



-
-
+
+

+
-
+

-
+
-
-
-
+
+
+
+
-
-
+
-
-
-
-
+
+
+
+


+
-
+

-
-
-
-
+
+
+
+




+
-
+

-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+


+
-
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
-
+

-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
-
+
-
-
-
+


+
-
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+


+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+





+
-
+

-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+


+
-
+

-
-
-
-
+
+
+
+




+
-
+

-
-
+
+


+
-
+

-
-
-
+
+
+






+
-
+

-
+
-
-
-
-
-
-
+
+
+
+
+
+


+
-
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
-
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+


+
-
+

-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+
-
-
-
-
+
+
+
+
-

+
-
+

-
-
+
+


+
-
+

-
-
+
+
+















-
-
// editing.cpp: most map editing commands go here, entity editing commands are in world.cpp
// editing.cpp: most map editing commands go here, entity editing commands are
// in world.cpp

#include "cube.h"

bool editmode = false; 
bool editmode = false;

// the current selection, used by almost all editing commands
// invariant: all code assumes that these are kept inside MINBORD distance of the edge of the map
// invariant: all code assumes that these are kept inside MINBORD distance of
// the edge of the map

block sel =
block sel = {
{
    variable("selx",  0, 0, 4096, &sel.x,  NULL, false),
    variable("sely",  0, 0, 4096, &sel.y,  NULL, false),
    variable("selx", 0, 0, 4096, &sel.x, NULL, false),
    variable("sely", 0, 0, 4096, &sel.y, NULL, false),
    variable("selxs", 0, 0, 4096, &sel.xs, NULL, false),
    variable("selys", 0, 0, 4096, &sel.ys, NULL, false),
};

int selh = 0;
bool selset = false;

#define loopselxy(b) { makeundo(); loop(x,sel.xs) loop(y,sel.ys) { sqr *s = S(sel.x+x, sel.y+y); b; }; remip(sel); }
#define loopselxy(b)                                                           \
	{                                                                      \
		makeundo();                                                    \
		loop(x, sel.xs) loop(y, sel.ys)                                \
		{                                                              \
			sqr *s = S(sel.x + x, sel.y + y);                      \
			b;                                                     \
		};                                                             \
		remip(sel);                                                    \
	}

int cx, cy, ch;

int curedittex[] = { -1, -1, -1 };
int curedittex[] = {-1, -1, -1};

bool dragging = false;
int lastx, lasty, lasth;

int lasttype = 0, lasttex = 0;
sqr rtex;

VAR(editing,0,0,1);
VAR(editing, 0, 0, 1);

void
void toggleedit()
toggleedit()
{
	if (player1->state == CS_DEAD)
    if(player1->state==CS_DEAD) return;                 // do not allow dead players to edit to avoid state confusion
    if(!editmode && !allowedittoggle()) return;         // not in most multiplayer modes
    if(!(editmode = !editmode))
		return; // do not allow dead players to edit to avoid state
		        // confusion
	if (!editmode && !allowedittoggle())
		return; // not in most multiplayer modes
	if (!(editmode = !editmode)) {
    {
        settagareas();                                  // reset triggers to allow quick playtesting
        entinmap(player1);                              // find spawn closest to current floating pos
		settagareas();     // reset triggers to allow quick playtesting
		entinmap(player1); // find spawn closest to current floating pos
    }
    else
	} else {
    {
        resettagareas();                                // clear trigger areas to allow them to be edited
        player1->health = 100;
        if(m_classicsp) monsterclear();                 // all monsters back at their spawns for editing
        projreset();
    };
    keyrepeat(editmode);
    selset = false;
    editing = editmode;
		resettagareas(); // clear trigger areas to allow them to be
		                 // edited
		player1->health = 100;
		if (m_classicsp)
			monsterclear(); // all monsters back at their spawns for
			                // editing
		projreset();
	};
	keyrepeat(editmode);
	selset = false;
	editing = editmode;
};

COMMANDN(edittoggle, toggleedit, ARG_NONE);

void
void correctsel()                                       // ensures above invariant
correctsel() // ensures above invariant
{
    selset = !OUTBORD(sel.x, sel.y);
    int bsize = ssize-MINBORD;
    if(sel.xs+sel.x>bsize) sel.xs = bsize-sel.x;
    if(sel.ys+sel.y>bsize) sel.ys = bsize-sel.y;
    if(sel.xs<=0 || sel.ys<=0) selset = false;
	selset = !OUTBORD(sel.x, sel.y);
	int bsize = ssize - MINBORD;
	if (sel.xs + sel.x > bsize)
		sel.xs = bsize - sel.x;
	if (sel.ys + sel.y > bsize)
		sel.ys = bsize - sel.y;
	if (sel.xs <= 0 || sel.ys <= 0)
		selset = false;
};

bool
bool noteditmode()
noteditmode()
{
    correctsel();
    if(!editmode) conoutf("this function is only allowed in edit mode");
    return !editmode;
	correctsel();
	if (!editmode)
		conoutf("this function is only allowed in edit mode");
	return !editmode;
};

bool
bool noselection()
noselection()
{
	if (!selset)
    if(!selset) conoutf("no selection");
    return !selset;
		conoutf("no selection");
	return !selset;
};

#define EDITSEL                                                                \
#define EDITSEL   if(noteditmode() || noselection()) return;
#define EDITSELMP if(noteditmode() || noselection() || multiplayer()) return;
#define EDITMP    if(noteditmode() || multiplayer()) return;
	if (noteditmode() || noselection())                                    \
		return;
#define EDITSELMP                                                              \
	if (noteditmode() || noselection() || multiplayer())                   \
		return;
#define EDITMP                                                                 \
	if (noteditmode() || multiplayer())                                    \
		return;

void
void selectpos(int x, int y, int xs, int ys)
selectpos(int x, int y, int xs, int ys)
{
    block s = { x, y, xs, ys };
    sel = s;
    selh = 0;
    correctsel();
	block s = {x, y, xs, ys};
	sel = s;
	selh = 0;
	correctsel();
};

void
void makesel()
makesel()
{
    block s = { min(lastx,cx), min(lasty,cy), abs(lastx-cx)+1, abs(lasty-cy)+1 };
    sel = s;
    selh = max(lasth,ch);
    correctsel();
    if(selset) rtex = *S(sel.x, sel.y);
	block s = {min(lastx, cx), min(lasty, cy), abs(lastx - cx) + 1,
	    abs(lasty - cy) + 1};
	sel = s;
	selh = max(lasth, ch);
	correctsel();
	if (selset)
		rtex = *S(sel.x, sel.y);
};

VAR(flrceil,0,0,2);
VAR(flrceil, 0, 0, 2);

float
sheight(
float sheight(sqr *s, sqr *t, float z)                  // finds out z height when cursor points at wall
    sqr *s, sqr *t, float z) // finds out z height when cursor points at wall
{
    return !flrceil //z-s->floor<s->ceil-z
        ? (s->type==FHF ? s->floor-t->vdelta/4.0f : (float)s->floor)
        : (s->type==CHF ? s->ceil+t->vdelta/4.0f : (float)s->ceil);
	return !flrceil // z-s->floor<s->ceil-z
	           ? (s->type == FHF ? s->floor - t->vdelta / 4.0f
	                             : (float)s->floor)
	           : (s->type == CHF ? s->ceil + t->vdelta / 4.0f
	                             : (float)s->ceil);
};

void
void cursorupdate()                                     // called every frame from hud
cursorupdate() // called every frame from hud
{
    flrceil = ((int)(player1->pitch>=0))*2;
	flrceil = ((int)(player1->pitch >= 0)) * 2;

	volatile float x =
    volatile float x = worldpos.x;                      // volatile needed to prevent msvc7 optimizer bug?
    volatile float y = worldpos.y;
    volatile float z = worldpos.z;
    
    cx = (int)x;
    cy = (int)y;
	    worldpos.x; // volatile needed to prevent msvc7 optimizer bug?
	volatile float y = worldpos.y;
	volatile float z = worldpos.z;

	cx = (int)x;
	cy = (int)y;

    if(OUTBORD(cx, cy)) return;
    sqr *s = S(cx,cy);
    
    if(fabs(sheight(s,s,z)-z)>1)                        // selected wall
    {
        x += x>player1->o.x ? 0.5f : -0.5f;             // find right wall cube
        y += y>player1->o.y ? 0.5f : -0.5f;
	if (OUTBORD(cx, cy))
		return;
	sqr *s = S(cx, cy);

	if (fabs(sheight(s, s, z) - z) > 1) // selected wall
	{
		x += x > player1->o.x ? 0.5f : -0.5f; // find right wall cube
		y += y > player1->o.y ? 0.5f : -0.5f;

        cx = (int)x;
        cy = (int)y;
		cx = (int)x;
		cy = (int)y;

        if(OUTBORD(cx, cy)) return;
    };
        
    if(dragging) makesel();
		if (OUTBORD(cx, cy))
			return;
	};

	if (dragging)
		makesel();

    const int GRIDSIZE = 5;
    const float GRIDW = 0.5f;
    const float GRID8 = 2.0f;
    const float GRIDS = 2.0f;
    const int GRIDM = 0x7;
    
    // render editing grid
	const int GRIDSIZE = 5;
	const float GRIDW = 0.5f;
	const float GRID8 = 2.0f;
	const float GRIDS = 2.0f;
	const int GRIDM = 0x7;

	// render editing grid

    for(int ix = cx-GRIDSIZE; ix<=cx+GRIDSIZE; ix++) for(int iy = cy-GRIDSIZE; iy<=cy+GRIDSIZE; iy++)
	for (int ix = cx - GRIDSIZE; ix <= cx + GRIDSIZE; ix++)
    {
        if(OUTBORD(ix, iy)) continue;
        sqr *s = S(ix,iy);
        if(SOLID(s)) continue;
        float h1 = sheight(s, s, z);
        float h2 = sheight(s, SWS(s,1,0,ssize), z);
        float h3 = sheight(s, SWS(s,1,1,ssize), z);
        float h4 = sheight(s, SWS(s,0,1,ssize), z);
        if(s->tag) linestyle(GRIDW, 0xFF, 0x40, 0x40);
        else if(s->type==FHF || s->type==CHF) linestyle(GRIDW, 0x80, 0xFF, 0x80);
        else linestyle(GRIDW, 0x80, 0x80, 0x80);
        block b = { ix, iy, 1, 1 };
        box(b, h1, h2, h3, h4);
        linestyle(GRID8, 0x40, 0x40, 0xFF);
        if(!(ix&GRIDM))   line(ix,   iy,   h1, ix,   iy+1, h4);
        if(!(ix+1&GRIDM)) line(ix+1, iy,   h2, ix+1, iy+1, h3);
        if(!(iy&GRIDM))   line(ix,   iy,   h1, ix+1, iy,   h2);
        if(!(iy+1&GRIDM)) line(ix,   iy+1, h4, ix+1, iy+1, h3);
    };
		for (int iy = cy - GRIDSIZE; iy <= cy + GRIDSIZE; iy++) {
			if (OUTBORD(ix, iy))
				continue;
			sqr *s = S(ix, iy);
			if (SOLID(s))
				continue;
			float h1 = sheight(s, s, z);
			float h2 = sheight(s, SWS(s, 1, 0, ssize), z);
			float h3 = sheight(s, SWS(s, 1, 1, ssize), z);
			float h4 = sheight(s, SWS(s, 0, 1, ssize), z);
			if (s->tag)
				linestyle(GRIDW, 0xFF, 0x40, 0x40);
			else if (s->type == FHF || s->type == CHF)
				linestyle(GRIDW, 0x80, 0xFF, 0x80);
			else
				linestyle(GRIDW, 0x80, 0x80, 0x80);
			block b = {ix, iy, 1, 1};
			box(b, h1, h2, h3, h4);
			linestyle(GRID8, 0x40, 0x40, 0xFF);
			if (!(ix & GRIDM))
				line(ix, iy, h1, ix, iy + 1, h4);
			if (!(ix + 1 & GRIDM))
				line(ix + 1, iy, h2, ix + 1, iy + 1, h3);
			if (!(iy & GRIDM))
				line(ix, iy, h1, ix + 1, iy, h2);
			if (!(iy + 1 & GRIDM))
				line(ix, iy + 1, h4, ix + 1, iy + 1, h3);
		};

    if(!SOLID(s))
	if (!SOLID(s)) {
    {
        float ih = sheight(s, s, z);
        linestyle(GRIDS, 0xFF, 0xFF, 0xFF);
        block b = { cx, cy, 1, 1 };
        box(b, ih, sheight(s, SWS(s,1,0,ssize), z), sheight(s, SWS(s,1,1,ssize), z), sheight(s, SWS(s,0,1,ssize), z));
        linestyle(GRIDS, 0xFF, 0x00, 0x00);
        dot(cx, cy, ih);
        ch = (int)ih;
    };
		float ih = sheight(s, s, z);
		linestyle(GRIDS, 0xFF, 0xFF, 0xFF);
		block b = {cx, cy, 1, 1};
		box(b, ih, sheight(s, SWS(s, 1, 0, ssize), z),
		    sheight(s, SWS(s, 1, 1, ssize), z),
		    sheight(s, SWS(s, 0, 1, ssize), z));
		linestyle(GRIDS, 0xFF, 0x00, 0x00);
		dot(cx, cy, ih);
		ch = (int)ih;
	};

    if(selset)
	if (selset) {
    {
        linestyle(GRIDS, 0xFF, 0x40, 0x40);
        box(sel, (float)selh, (float)selh, (float)selh, (float)selh);
    };
		linestyle(GRIDS, 0xFF, 0x40, 0x40);
		box(sel, (float)selh, (float)selh, (float)selh, (float)selh);
	};
};

vector<block *> undos;                                  // unlimited undo
VARP(undomegs, 0, 1, 10);                                // bounded by n megs
vector<block *> undos;    // unlimited undo
VARP(undomegs, 0, 1, 10); // bounded by n megs

void
void pruneundos(int maxremain)                          // bound memory
pruneundos(int maxremain) // bound memory
{
    int t = 0;
    loopvrev(undos)
    {
        t += undos[i]->xs*undos[i]->ys*sizeof(sqr);
        if(t>maxremain) free(undos.remove(i));
    };
	int t = 0;
	loopvrev(undos)
	{
		t += undos[i]->xs * undos[i]->ys * sizeof(sqr);
		if (t > maxremain)
			free(undos.remove(i));
	};
};

void
void makeundo()
makeundo()
{
    undos.add(blockcopy(sel));
    pruneundos(undomegs<<20);
	undos.add(blockcopy(sel));
	pruneundos(undomegs << 20);
};

void
void editundo()
editundo()
{
    EDITMP;
    if(undos.empty()) { conoutf("nothing more to undo"); return; };
    block *p = undos.pop();
    blockpaste(*p);
    free(p);
	EDITMP;
	if (undos.empty()) {
		conoutf("nothing more to undo");
		return;
	};
	block *p = undos.pop();
	blockpaste(*p);
	free(p);
};

block *copybuf = NULL;

void
void copy()
copy()
{
    EDITSELMP;
    if(copybuf) free(copybuf);
    copybuf = blockcopy(sel);
	EDITSELMP;
	if (copybuf)
		free(copybuf);
	copybuf = blockcopy(sel);
};

void
void paste()
paste()
{
    EDITMP;
    if(!copybuf) { conoutf("nothing to paste"); return; };
    sel.xs = copybuf->xs;
    sel.ys = copybuf->ys;
    correctsel();
    if(!selset || sel.xs!=copybuf->xs || sel.ys!=copybuf->ys) { conoutf("incorrect selection"); return; };
    makeundo();
    copybuf->x = sel.x;
    copybuf->y = sel.y;
    blockpaste(*copybuf);
	EDITMP;
	if (!copybuf) {
		conoutf("nothing to paste");
		return;
	};
	sel.xs = copybuf->xs;
	sel.ys = copybuf->ys;
	correctsel();
	if (!selset || sel.xs != copybuf->xs || sel.ys != copybuf->ys) {
		conoutf("incorrect selection");
		return;
	};
	makeundo();
	copybuf->x = sel.x;
	copybuf->y = sel.y;
	blockpaste(*copybuf);
};

void
void tofronttex()                                       // maintain most recently used of the texture lists when applying texture
tofronttex() // maintain most recently used of the texture lists when applying
             // texture
{
    loopi(3)
    {
        int c = curedittex[i];
        if(c>=0)
	loopi(3)
	{
		int c = curedittex[i];
		if (c >= 0) {
        {
            uchar *p = hdr.texlists[i];
            int t = p[c];
            for(int a = c-1; a>=0; a--) p[a+1] = p[a];
            p[0] = t;
            curedittex[i] = -1;
        };
    };
			uchar *p = hdr.texlists[i];
			int t = p[c];
			for (int a = c - 1; a >= 0; a--)
				p[a + 1] = p[a];
			p[0] = t;
			curedittex[i] = -1;
		};
	};
};

void
void editdrag(bool isdown)
editdrag(bool isdown)
{
    if(dragging = isdown)
	if (dragging = isdown) {
    {
        lastx = cx;
        lasty = cy;
        lasth = ch;
        selset = false;
        tofronttex();
    };
    makesel();
		lastx = cx;
		lasty = cy;
		lasth = ch;
		selset = false;
		tofronttex();
	};
	makesel();
};

// the core editing function. all the *xy functions perform the core operations
// and are also called directly from the network, the function below it is strictly
// triggered locally. They all have very similar structure.
// and are also called directly from the network, the function below it is
// strictly triggered locally. They all have very similar structure.

void
void editheightxy(bool isfloor, int amount, block &sel)
editheightxy(bool isfloor, int amount, block &sel)
{
    loopselxy(if(isfloor)
	loopselxy(
    {
        s->floor += amount;
        if(s->floor>=s->ceil) s->floor = s->ceil-1;
	    if (isfloor) {
		    s->floor += amount;
		    if (s->floor >= s->ceil)
			    s->floor = s->ceil - 1;
    }
    else
	    } else {
    {
        s->ceil += amount;
        if(s->ceil<=s->floor) s->ceil = s->floor+1;
    });
		    s->ceil += amount;
		    if (s->ceil <= s->floor)
			    s->ceil = s->floor + 1;
	    });
};

void
void editheight(int flr, int amount)
editheight(int flr, int amount)
{
    EDITSEL;
    bool isfloor = flr==0;
    editheightxy(isfloor, amount, sel);
    addmsg(1, 7, SV_EDITH, sel.x, sel.y, sel.xs, sel.ys, isfloor, amount);
	EDITSEL;
	bool isfloor = flr == 0;
	editheightxy(isfloor, amount, sel);
	addmsg(1, 7, SV_EDITH, sel.x, sel.y, sel.xs, sel.ys, isfloor, amount);
};

COMMAND(editheight, ARG_2INT);

void
void edittexxy(int type, int t, block &sel)            
edittexxy(int type, int t, block &sel)
{
    loopselxy(switch(type)
	loopselxy(switch (type) {
    {
        case 0: s->ftex = t; break;
        case 1: s->wtex = t; break;
        case 2: s->ctex = t; break;
        case 3: s->utex = t; break;
    });
	        case 0:
		        s->ftex = t;
		        break;
	        case 1:
		        s->wtex = t;
		        break;
	        case 2:
		        s->ctex = t;
		        break;
	        case 3:
		        s->utex = t;
		        break;
	});
};

void
void edittex(int type, int dir)
edittex(int type, int dir)
{
    EDITSEL;
    if(type<0 || type>3) return;
    if(type!=lasttype) { tofronttex(); lasttype = type; };
    int atype = type==3 ? 1 : type;
    int i = curedittex[atype];
    i = i<0 ? 0 : i+dir;
    curedittex[atype] = i = min(max(i, 0), 255);
    int t = lasttex = hdr.texlists[atype][i];
    edittexxy(type, t, sel);
    addmsg(1, 7, SV_EDITT, sel.x, sel.y, sel.xs, sel.ys, type, t);
	EDITSEL;
	if (type < 0 || type > 3)
		return;
	if (type != lasttype) {
		tofronttex();
		lasttype = type;
	};
	int atype = type == 3 ? 1 : type;
	int i = curedittex[atype];
	i = i < 0 ? 0 : i + dir;
	curedittex[atype] = i = min(max(i, 0), 255);
	int t = lasttex = hdr.texlists[atype][i];
	edittexxy(type, t, sel);
	addmsg(1, 7, SV_EDITT, sel.x, sel.y, sel.xs, sel.ys, type, t);
};

void
void replace()
replace()
{
    EDITSELMP;
    loop(x,ssize) loop(y,ssize)
    {
        sqr *s = S(x, y);
        switch(lasttype)
	EDITSELMP;
	loop(x, ssize) loop(y, ssize)
	{
		sqr *s = S(x, y);
		switch (lasttype) {
        {
            case 0: if(s->ftex == rtex.ftex) s->ftex = lasttex; break;
            case 1: if(s->wtex == rtex.wtex) s->wtex = lasttex; break;
            case 2: if(s->ctex == rtex.ctex) s->ctex = lasttex; break;
            case 3: if(s->utex == rtex.utex) s->utex = lasttex; break;
        };
    };
    block b = { 0, 0, ssize, ssize }; 
    remip(b);
		case 0:
			if (s->ftex == rtex.ftex)
				s->ftex = lasttex;
			break;
		case 1:
			if (s->wtex == rtex.wtex)
				s->wtex = lasttex;
			break;
		case 2:
			if (s->ctex == rtex.ctex)
				s->ctex = lasttex;
			break;
		case 3:
			if (s->utex == rtex.utex)
				s->utex = lasttex;
			break;
		};
	};
	block b = {0, 0, ssize, ssize};
	remip(b);
};

void
edittypexy(int type, block &sel)

{
void edittypexy(int type, block &sel)
{
    loopselxy(s->type = type);
	loopselxy(s->type = type);
};

void
void edittype(int type)
edittype(int type)
{
    EDITSEL;
    if(type==CORNER && (sel.xs!=sel.ys || sel.xs==3 || sel.xs>4 && sel.xs!=8
                   || sel.x&~-sel.xs || sel.y&~-sel.ys))
                   { conoutf("corner selection must be power of 2 aligned"); return; };
    edittypexy(type, sel);
    addmsg(1, 6, SV_EDITS, sel.x, sel.y, sel.xs, sel.ys, type);
	EDITSEL;
	if (type == CORNER &&
	    (sel.xs != sel.ys || sel.xs == 3 || sel.xs > 4 && sel.xs != 8 ||
	        sel.x & ~-sel.xs || sel.y & ~-sel.ys)) {
		conoutf("corner selection must be power of 2 aligned");
		return;
	};
	edittypexy(type, sel);
	addmsg(1, 6, SV_EDITS, sel.x, sel.y, sel.xs, sel.ys, type);
};

void
void heightfield(int t) { edittype(t==0 ? FHF : CHF); };
void solid(int t)       { edittype(t==0 ? SPACE : SOLID); };
void corner()           { edittype(CORNER); };
heightfield(int t)
{
	edittype(t == 0 ? FHF : CHF);
};
void
solid(int t)
{
	edittype(t == 0 ? SPACE : SOLID);
};
void
corner()
{
	edittype(CORNER);
};

COMMAND(heightfield, ARG_1INT);
COMMAND(solid, ARG_1INT);
COMMAND(corner, ARG_NONE);

void
void editequalisexy(bool isfloor, block &sel)
editequalisexy(bool isfloor, block &sel)
{
    int low = 127, hi = -128;
    loopselxy(
	int low = 127, hi = -128;
	loopselxy({
    {
        if(s->floor<low) low = s->floor;
        if(s->ceil>hi) hi = s->ceil;
    });
    loopselxy(
		if (s->floor < low)
			low = s->floor;
		if (s->ceil > hi)
			hi = s->ceil;
	});
	loopselxy({
    {
        if(isfloor) s->floor = low; else s->ceil = hi;
        if(s->floor>=s->ceil) s->floor = s->ceil-1;
    });
		if (isfloor)
			s->floor = low;
		else
			s->ceil = hi;
		if (s->floor >= s->ceil)
			s->floor = s->ceil - 1;
	});
};

void
void equalize(int flr)
equalize(int flr)
{
    bool isfloor = flr==0;
    EDITSEL;
    editequalisexy(isfloor, sel);
    addmsg(1, 6, SV_EDITE, sel.x, sel.y, sel.xs, sel.ys, isfloor);
	bool isfloor = flr == 0;
	EDITSEL;
	editequalisexy(isfloor, sel);
	addmsg(1, 6, SV_EDITE, sel.x, sel.y, sel.xs, sel.ys, isfloor);
};

COMMAND(equalize, ARG_1INT);

void
void setvdeltaxy(int delta, block &sel)
setvdeltaxy(int delta, block &sel)
{
    loopselxy(s->vdelta = max(s->vdelta+delta, 0));
    remipmore(sel);    
	loopselxy(s->vdelta = max(s->vdelta + delta, 0));
	remipmore(sel);
};

void
void setvdelta(int delta)
setvdelta(int delta)
{
    EDITSEL;
    setvdeltaxy(delta, sel);
    addmsg(1, 6, SV_EDITD, sel.x, sel.y, sel.xs, sel.ys, delta);
	EDITSEL;
	setvdeltaxy(delta, sel);
	addmsg(1, 6, SV_EDITD, sel.x, sel.y, sel.xs, sel.ys, delta);
};

const int MAXARCHVERT = 50;
int archverts[MAXARCHVERT][MAXARCHVERT];
bool archvinit = false;

void
void archvertex(int span, int vert, int delta)
archvertex(int span, int vert, int delta)
{
    if(!archvinit)
	if (!archvinit) {
    {
        archvinit = true;
        loop(s,MAXARCHVERT) loop(v,MAXARCHVERT) archverts[s][v] = 0;
    };
    if(span>=MAXARCHVERT || vert>=MAXARCHVERT || span<0 || vert<0) return;
    archverts[span][vert] = delta;
		archvinit = true;
		loop(s, MAXARCHVERT) loop(v, MAXARCHVERT) archverts[s][v] = 0;
	};
	if (span >= MAXARCHVERT || vert >= MAXARCHVERT || span < 0 || vert < 0)
		return;
	archverts[span][vert] = delta;
};

void
void arch(int sidedelta, int _a)
arch(int sidedelta, int _a)
{
    EDITSELMP;
    sel.xs++;
    sel.ys++;
    if(sel.xs>MAXARCHVERT) sel.xs = MAXARCHVERT;
    if(sel.ys>MAXARCHVERT) sel.ys = MAXARCHVERT;
    loopselxy(s->vdelta =
        sel.xs>sel.ys
            ? (archverts[sel.xs-1][x] + (y==0 || y==sel.ys-1 ? sidedelta : 0))
            : (archverts[sel.ys-1][y] + (x==0 || x==sel.xs-1 ? sidedelta : 0)));
    remipmore(sel);
	EDITSELMP;
	sel.xs++;
	sel.ys++;
	if (sel.xs > MAXARCHVERT)
		sel.xs = MAXARCHVERT;
	if (sel.ys > MAXARCHVERT)
		sel.ys = MAXARCHVERT;
	loopselxy(
	    s->vdelta = sel.xs > sel.ys
	                    ? (archverts[sel.xs - 1][x] +
	                          (y == 0 || y == sel.ys - 1 ? sidedelta : 0))
	                    : (archverts[sel.ys - 1][y] +
	                          (x == 0 || x == sel.xs - 1 ? sidedelta : 0)));
	remipmore(sel);
};

void
void slope(int xd, int yd)
slope(int xd, int yd)
{
    EDITSELMP;
    int off = 0;
    if(xd<0) off -= xd*sel.xs;
    if(yd<0) off -= yd*sel.ys;
    sel.xs++;
    sel.ys++;
    loopselxy(s->vdelta = xd*x+yd*y+off);
    remipmore(sel);
	EDITSELMP;
	int off = 0;
	if (xd < 0)
		off -= xd * sel.xs;
	if (yd < 0)
		off -= yd * sel.ys;
	sel.xs++;
	sel.ys++;
	loopselxy(s->vdelta = xd * x + yd * y + off);
	remipmore(sel);
};

void
void perlin(int scale, int seed, int psize)
perlin(int scale, int seed, int psize)
{
    EDITSELMP;
    sel.xs++;
    sel.ys++;
    makeundo();
    sel.xs--;
    sel.ys--;
    perlinarea(sel, scale, seed, psize);
    sel.xs++;
    sel.ys++;
    remipmore(sel);
    sel.xs--;
    sel.ys--;
	EDITSELMP;
	sel.xs++;
	sel.ys++;
	makeundo();
	sel.xs--;
	sel.ys--;
	perlinarea(sel, scale, seed, psize);
	sel.xs++;
	sel.ys++;
	remipmore(sel);
	sel.xs--;
	sel.ys--;
};

VARF(fullbright, 0, 0, 1,
    if(fullbright)
VARF(
    fullbright, 0, 0, 1, if (fullbright) {
    {
        if(noteditmode()) return;
        loopi(mipsize) world[i].r = world[i].g = world[i].b = 176;
    };
	    if (noteditmode())
		    return;
	    loopi(mipsize) world[i].r = world[i].g = world[i].b = 176;
    };);
);

void
void edittag(int tag)
edittag(int tag)
{
    EDITSELMP;
    loopselxy(s->tag = tag);
	EDITSELMP;
	loopselxy(s->tag = tag);
};

void
void newent(char *what, char *a1, char *a2, char *a3, char *a4)
newent(char *what, char *a1, char *a2, char *a3, char *a4)
{
    EDITSEL;
    newentity(sel.x, sel.y, (int)player1->o.z, what, ATOI(a1), ATOI(a2), ATOI(a3), ATOI(a4));
	EDITSEL;
	newentity(sel.x, sel.y, (int)player1->o.z, what, ATOI(a1), ATOI(a2),
	    ATOI(a3), ATOI(a4));
};

COMMANDN(select, selectpos, ARG_4INT);
COMMAND(edittag, ARG_1INT);
COMMAND(replace, ARG_NONE);
COMMAND(archvertex, ARG_3INT);
COMMAND(arch, ARG_2INT);
COMMAND(slope, ARG_2INT);
COMMANDN(vdelta, setvdelta, ARG_1INT);
COMMANDN(undo, editundo, ARG_NONE);
COMMAND(copy, ARG_NONE);
COMMAND(paste, ARG_NONE);
COMMAND(edittex, ARG_2INT);
COMMAND(newent, ARG_5STR);
COMMAND(perlin, ARG_3INT);