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