1 /*
2 * s_slice.cc
3 * Cut a slice out of a sector
4 * AYM 2001-09-11
5 */
6
7
8 /*
9 This file is part of Yadex.
10
11 Yadex incorporates code from DEU 5.21 that was put in the public domain in
12 1994 by Rapha�l Quinet and Brendon Wyber.
13
14 The rest of Yadex is Copyright � 1997-2003 Andr� Majorel and others.
15
16 This program is free software; you can redistribute it and/or modify it under
17 the terms of the GNU General Public License as published by the Free Software
18 Foundation; either version 2 of the License, or (at your option) any later
19 version.
20
21 This program is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
23 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License along with
26 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
27 Place, Suite 330, Boston, MA 02111-1307, USA.
28 */
29
30
31 #include "yadex.h"
32 #include <map>
33 #include "dialog.h"
34 #include "levels.h"
35 #include "objects.h"
36 #include "objid.h"
37 #include "s_slice.h"
38
39
40 class Secref // Reference to a sector
41 {
42 public :
Secref()43 Secref () : linedef1 ('\0'), linedef2 ('\0') { }
44 char linedef1;
45 char linedef2;
46 };
47
48
49 /*
50 * sector_slice - cut a slice out of a sector
51 */
sector_slice(obj_no_t linedef1,obj_no_t linedef2)52 void sector_slice (obj_no_t linedef1, obj_no_t linedef2)
53 {
54 /* We have between 0 and 4 sidedefs. We need to make sure that
55 there are exactly 2 that face the same sector and that they
56 belong to different linedefs.
57
58 If a linedef has more than one sidedef that faces the same
59 sector, we can't decide which one faces the other linedef.
60 Well, we can but it's hard for a dummy like me.
61
62 The problem is the same if the linedefs have two sectors in
63 common. Consider the following setup :
64 ____________________________________
65 | |
66 | sector 0 |
67 | ________________________ |
68 | | | |
69 | | sector 1 | |
70 | | ____________ | |
71 | | | | | |
72 | | | sector 0 |-L1 |-L2 |
73 | | |____________| | |
74 | | | |
75 | | | |
76 | |________________________| |
77 | |
78 | |
79 |____________________________________|
80
81 How do you decide to which vertex of L2 should the start
82 vertex of L1 be linked ? */
83
84 if (! is_linedef (linedef1)) // Paranoia
85 {
86 char buf[100];
87 y_snprintf (buf, sizeof buf,
88 "First argument is not a valid linedef number");
89 Notify (-1, -1, buf, 0);
90 return;
91 }
92
93 if (! is_linedef (linedef2)) // Paranoia
94 {
95 char buf[100];
96 y_snprintf (buf, sizeof buf,
97 "Second argument is not a valid linedef number");
98 Notify (-1, -1, buf, 0);
99 return;
100 }
101
102 if (linedef1 == linedef2)
103 {
104 char buf[100];
105 y_snprintf (buf, sizeof buf, "Both arguments are the same linedef");
106 Notify (-1, -1, buf, 0);
107 return;
108 }
109
110 obj_no_t l1start = LineDefs[linedef1].start;
111 obj_no_t l1end = LineDefs[linedef1].end;
112 obj_no_t l2start = LineDefs[linedef2].start;
113 obj_no_t l2end = LineDefs[linedef2].end;
114
115 if (l1start == l2start && l1end == l2end
116 || l1start == l2end && l1end == l2start)
117 {
118 char buf[100];
119 y_snprintf (buf, sizeof buf, "Linedefs %d and %d are superimposed",
120 int (linedef1), int (linedef2));
121 Notify (-1, -1, buf, 0);
122 return;
123 }
124
125 obj_no_t l1sdr = LineDefs[linedef1].sidedef1;
126 obj_no_t l1sdl = LineDefs[linedef1].sidedef2;
127 obj_no_t l2sdr = LineDefs[linedef2].sidedef1;
128 obj_no_t l2sdl = LineDefs[linedef2].sidedef2;
129
130 obj_no_t l1sr = is_sidedef (l1sdr) ? SideDefs[l1sdr].sector : OBJ_NO_NONE;
131 obj_no_t l1sl = is_sidedef (l1sdl) ? SideDefs[l1sdl].sector : OBJ_NO_NONE;
132 obj_no_t l2sr = is_sidedef (l2sdr) ? SideDefs[l2sdr].sector : OBJ_NO_NONE;
133 obj_no_t l2sl = is_sidedef (l2sdl) ? SideDefs[l2sdl].sector : OBJ_NO_NONE;
134
135 if (is_sector (l1sr) && is_sector (l1sl) && l1sr == l1sl)
136 {
137 char buf[100];
138 y_snprintf (buf, sizeof buf, "Linedef %d has both sides in the same sector",
139 int (linedef1));
140 Notify (-1, -1, buf, 0);
141 return;
142 }
143
144 if (is_sector (l2sr) && is_sector (l2sl) && l2sr == l2sl)
145 {
146 char buf[100];
147 y_snprintf (buf, sizeof buf, "Linedef %d has both sides in the same sector",
148 int (linedef2));
149 Notify (-1, -1, buf, 0);
150 return;
151 }
152
153 // Verify that the linedefs have exactly one sector in common
154 typedef std::map<obj_no_t, Secref> secref_list_t;
155 secref_list_t secref;
156 if (is_sector (l1sr))
157 secref[l1sr].linedef1 = 'r';
158 if (is_sector (l1sl))
159 secref[l1sl].linedef1 = 'l';
160 if (is_sector (l2sr))
161 secref[l2sr].linedef2 = 'r';
162 if (is_sector (l2sl))
163 secref[l2sl].linedef2 = 'l';
164 obj_no_t sector;
165 int count = 0;
166 for (secref_list_t::iterator i = secref.begin (); i != secref.end (); i++)
167 {
168 if (i->second.linedef1 != '\0' && i->second.linedef2 != '\0')
169 {
170 sector = i->first;
171 count++;
172 }
173 }
174 if (count < 1)
175 {
176 char buf[100];
177 y_snprintf (buf, sizeof buf,
178 "Linedefs %d and %d don't face the same sector",
179 int (linedef1), int (linedef2));
180 Notify (-1, -1, buf, 0);
181 return;
182 }
183 if (count > 1)
184 {
185 char buf[100];
186 y_snprintf (buf, sizeof buf,
187 "Linedefs %d and %d have more than one sector in common",
188 int (linedef1), int (linedef2));
189 Notify (-1, -1, buf, 0);
190 return;
191 }
192
193 // Insert new sector between linedefs
194 obj_no_t la0, la1; // Start and end of the first linedef (the
195 // one that goes from linedef1 to linedef2)
196 obj_no_t lb0, lb1; // Start and end of the second linedef (the
197 // one that goes from linedef2 to linedef1)
198 char side = secref[sector].linedef1;
199 if (side == 'r')
200 {
201 la0 = l1end;
202 lb1 = l1start;
203 }
204 else if (side == 'l')
205 {
206 la0 = l1start;
207 lb1 = l1end;
208 }
209 else // Can't happen
210 {
211 nf_bug ("sector %d: linedef1 = %02Xh", int (sector), side);
212 return;
213 }
214
215 side = secref[sector].linedef2;
216 if (side == 'r')
217 {
218 la1 = l2start;
219 lb0 = l2end;
220 }
221 else if (side == 'l')
222 {
223 la1 = l2end;
224 lb0 = l2start;
225 }
226 else // Can't happen
227 {
228 nf_bug ("sector %d: linedef2 = %02Xh", int (sector), side);
229 return;
230 }
231
232 // Verify that there's no linedef already between linedef1 and linedef2
233 {
234 for (int n = 0; n < NumLineDefs; n++)
235 {
236 if (n == linedef1 || n == linedef2)
237 continue;
238 if (LineDefs[n].start == la0 && LineDefs[n].end == la1
239 || LineDefs[n].start == la1 && LineDefs[n].end == la0
240 || LineDefs[n].start == lb0 && LineDefs[n].end == lb1
241 || LineDefs[n].start == lb1 && LineDefs[n].end == lb0)
242 {
243 char buf[100];
244 y_snprintf (buf, sizeof buf,
245 "A linedef already exists between linedefs %d and %d (linedef %d)",
246 int (linedef1), int (linedef2), int (n));
247 Notify (-1, -1, buf, 0);
248 return;
249 }
250 }
251 }
252
253 // Create new sector
254 InsertObject (OBJ_SECTORS, sector, 0, 0);
255
256 // Create new linedef from linedef1 to linedef2
257 if (la0 != la1)
258 {
259 InsertObject (OBJ_LINEDEFS, -1, 0, 0);
260 LineDefs[NumLineDefs - 1].start = la0;
261 LineDefs[NumLineDefs - 1].end = la1;
262 LineDefs[NumLineDefs - 1].flags = 4;
263 InsertObject (OBJ_SIDEDEFS, -1, 0, 0); // Right sidedef
264 SideDefs[NumSideDefs - 1].sector = NumSectors - 1; // Redundant
265 strncpy (SideDefs[NumSideDefs - 1].tex3, "-", 8);
266 LineDefs[NumLineDefs - 1].sidedef1 = NumSideDefs - 1;
267 InsertObject (OBJ_SIDEDEFS, -1, 0, 0); // Left sidedef
268 SideDefs[NumSideDefs - 1].sector = sector;
269 strncpy (SideDefs[NumSideDefs - 1].tex3, "-", 8);
270 LineDefs[NumLineDefs - 1].sidedef2 = NumSideDefs - 1;
271 }
272
273 // Create new linedef from linedef2 to linedef1
274 if (lb0 != lb1)
275 {
276 InsertObject (OBJ_LINEDEFS, -1, 0, 0);
277 LineDefs[NumLineDefs - 1].start = lb0;
278 LineDefs[NumLineDefs - 1].end = lb1;
279 LineDefs[NumLineDefs - 1].flags = 4;
280 InsertObject (OBJ_SIDEDEFS, -1, 0, 0); // Right sidedef
281 SideDefs[NumSideDefs - 1].sector = NumSectors - 1; // Redundant
282 strncpy (SideDefs[NumSideDefs - 1].tex3, "-", 8);
283 LineDefs[NumLineDefs - 1].sidedef1 = NumSideDefs - 1;
284 InsertObject (OBJ_SIDEDEFS, -1, 0, 0); // Left sidedef
285 SideDefs[NumSideDefs - 1].sector = sector;
286 strncpy (SideDefs[NumSideDefs - 1].tex3, "-", 8);
287 LineDefs[NumLineDefs - 1].sidedef2 = NumSideDefs - 1;
288 }
289
290 // Adjust sector references for linedef1
291 side = secref[sector].linedef1;
292 if (side == 'r')
293 SideDefs[LineDefs[linedef1].sidedef1].sector = NumSectors - 1;
294 else if (side == 'l')
295 SideDefs[LineDefs[linedef1].sidedef2].sector = NumSectors - 1;
296
297 // Adjust sector references for linedef2
298 side = secref[sector].linedef2;
299 if (side == 'r')
300 SideDefs[LineDefs[linedef2].sidedef1].sector = NumSectors - 1;
301 else if (side == 'l')
302 SideDefs[LineDefs[linedef2].sidedef2].sector = NumSectors - 1;
303
304 MadeChanges = 1;
305 MadeMapChanges = 1;
306 }
307
308