1 /*
2  * Portions of this file are copyright Rebirth contributors and licensed as
3  * described in COPYING.txt.
4  * Portions of this file are copyright Parallax Software and licensed
5  * according to the Parallax license below.
6  * See COPYING.txt for license details.
7 
8 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18 */
19 
20 /*
21  *
22  * Functions for building parts of mines.
23  *
24  */
25 
26 #include <string.h>
27 #include "editor/editor.h"
28 #include "editor/esegment.h"
29 #include "gamesave.h"
30 #include "kdefs.h"
31 #include "compiler-range_for.h"
32 
33 //  ---------- Create a bridge segment between current segment/side and marked segment/side ----------
CreateBridge()34 int CreateBridge()
35 {
36 	if (!Markedsegp) {
37 		editor_status("No marked side.");
38 		return 0;
39 	}
40 
41     if (!med_form_bridge_segment(Cursegp,Curside,Markedsegp,Markedside)) {
42 		Update_flags |= UF_WORLD_CHANGED;
43 		mine_changed = 1;
44     	autosave_mine(mine_filename);
45     	diagnostic_message("Bridge segment formed.");
46 		undo_status[Autosave_count] = "Bridge segment UNDONE.";
47     	warn_if_concave_segments();
48 	}
49     return 1;
50 }
51 
52 
53 
54 // ---------- Form a joint between current segment:side and marked segment:side, modifying marked segment ----------
FormJoint()55 int FormJoint()
56 {
57 	if (!Markedsegp)
58 		diagnostic_message("Marked segment not set -- unable to form joint.");
59 	else {
60         if (!med_form_joint(Cursegp,Curside,Markedsegp,Markedside)) {
61             Update_flags |= UF_WORLD_CHANGED;
62             mine_changed = 1;
63             autosave_mine(mine_filename);
64             diagnostic_message("Joint formed.");
65 			undo_status[Autosave_count] = "Joint undone.";
66     			warn_if_concave_segments();
67         }
68 	}
69 
70 	return 1;
71 
72 }
73 
74 //  ---------- Create a bridge segment between current segment:side adjacent segment:side ----------
CreateAdjacentJoint()75 int CreateAdjacentJoint()
76 {
77 	int		adj_side;
78 	imsegptridx_t adj_sp = segment_none;
79 
80 	if (med_find_adjacent_segment_side(Cursegp, Curside, adj_sp, &adj_side)) {
81 		if (Cursegp->children[Curside] != adj_sp) {
82 			med_form_joint(Cursegp,Curside,adj_sp,adj_side);
83 			Update_flags |= UF_WORLD_CHANGED;
84 			mine_changed = 1;
85          autosave_mine(mine_filename);
86          diagnostic_message("Joint segment formed.");
87 			undo_status[Autosave_count] = "Joint segment undone.";
88     		warn_if_concave_segments();
89 		} else
90 			editor_status("Attempted to form joint through connected side -- joint segment not formed (you bozo).");
91 	} else
92 		editor_status("Could not find adjacent segment -- joint segment not formed.");
93 
94 	return 1;
95 }
96 
97 //  ---------- Create a bridge segment between current segment:side adjacent segment:side ----------
CreateSloppyAdjacentJoint()98 int CreateSloppyAdjacentJoint()
99 {
100 	int		adj_side;
101 	imsegptridx_t adj_sp = segment_none;
102 
103 	save_level(
104 #if defined(DXX_BUILD_DESCENT_II)
105 		LevelSharedSegmentState.DestructibleLights,
106 #endif
107 		"SLOPPY.LVL");
108 
109 	if (med_find_closest_threshold_segment_side(Cursegp, Curside, adj_sp, &adj_side, 20*F1_0)) {
110 		if (Cursegp->children[Curside] != adj_sp) {
111 			if (!med_form_joint(Cursegp,Curside,adj_sp,adj_side))
112 				{
113 				Update_flags |= UF_WORLD_CHANGED;
114 				mine_changed = 1;
115 	         autosave_mine(mine_filename);
116 	         diagnostic_message("Sloppy Joint segment formed.");
117 				undo_status[Autosave_count] = "Sloppy Joint segment undone.";
118 	    		warn_if_concave_segments();
119 				}
120 			else editor_status("Could not form sloppy joint.\n");
121 		} else
122 			editor_status("Attempted to form sloppy joint through connected side -- joint segment not formed.");
123 	} else
124 		editor_status("Could not find close threshold segment -- joint segment not formed.");
125 
126 	return 1;
127 }
128 
129 
130 //  -------------- Create all sloppy joints within CurrentGroup ------------------
CreateSloppyAdjacentJointsGroup()131 int CreateSloppyAdjacentJointsGroup()
132 {
133 	int		adj_side;
134 	int		done_been_a_change = 0;
135 	range_for(const auto &gs, GroupList[current_group].segments)
136 	{
137 		auto segp = vmsegptridx(gs);
138 
139 		for (int sidenum=0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++)
140 			if (!IS_CHILD(segp->children[sidenum]))
141 			{
142 				imsegptridx_t adj_sp = segment_none;
143 				if (med_find_closest_threshold_segment_side(segp, sidenum, adj_sp, &adj_side, 5*F1_0)) {
144 					if (adj_sp->group == segp->group) {
145 						if (segp->children[sidenum] != adj_sp)
146 							if (!med_form_joint(segp, sidenum, adj_sp,adj_side))
147 								done_been_a_change = 1;
148 					}
149 				}
150 			}
151 	}
152 
153 	if (done_been_a_change) {
154 		Update_flags |= UF_WORLD_CHANGED;
155 		mine_changed = 1;
156 		autosave_mine(mine_filename);
157 		diagnostic_message("Sloppy Joint segment formed.");
158 		undo_status[Autosave_count] = "Sloppy Joint segment undone.";
159 		warn_if_concave_segments();
160 	}
161 
162 	return 1;
163 }
164 
165 
166 //  ---------- Create a bridge segment between current segment and all adjacent segment:side ----------
CreateAdjacentJointsSegment()167 int CreateAdjacentJointsSegment()
168 {
169 	auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
170 	int		adj_side;
171 
172 	auto &Vertex_active = LevelSharedVertexState.get_vertex_active();
173 	med_combine_duplicate_vertices(Vertex_active);
174 
175 	for (int s=0; s<MAX_SIDES_PER_SEGMENT; s++) {
176 		imsegptridx_t adj_sp = segment_none;
177 		if (med_find_adjacent_segment_side(Cursegp, s, adj_sp, &adj_side))
178 			if (Cursegp->children[s] != adj_sp)
179 					{
180 					med_form_joint(Cursegp,s,adj_sp,adj_side);
181 					Update_flags |= UF_WORLD_CHANGED;
182 					mine_changed = 1;
183 	            autosave_mine(mine_filename);
184 	            diagnostic_message("Adjacent Joint segment formed.");
185 				undo_status[Autosave_count] = "Adjacent Joint segment UNDONE.";
186 	    			warn_if_concave_segments();
187 					}
188 	}
189 
190 	return 1;
191 }
192 
193 //  ---------- Create a bridge segment between all segment:side and all adjacent segment:side ----------
CreateAdjacentJointsAll()194 int CreateAdjacentJointsAll()
195 {
196 	auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
197 	int		adj_side;
198 
199 	auto &Vertex_active = LevelSharedVertexState.get_vertex_active();
200 	med_combine_duplicate_vertices(Vertex_active);
201 
202 	range_for (const auto &&segp, vmsegptridx)
203 	{
204 		for (int s=0; s<MAX_SIDES_PER_SEGMENT; s++)
205 		{
206 			imsegptridx_t adj_sp = segment_none;
207 			if (med_find_adjacent_segment_side(segp, s, adj_sp, &adj_side))
208 				if (segp->children[s] != adj_sp)
209 						med_form_joint(segp,s,adj_sp,adj_side);
210 		}
211 	}
212 
213 	Update_flags |= UF_WORLD_CHANGED;
214 	mine_changed = 1;
215    autosave_mine(mine_filename);
216    diagnostic_message("All Adjacent Joint segments formed.");
217 	undo_status[Autosave_count] = "All Adjacent Joint segments UNDONE.";
218  	warn_if_concave_segments();
219    return 1;
220 }
221 
222 
223