Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 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 selecting segments |
||
23 | * |
||
24 | */ |
||
25 | |||
26 | #include <utility> |
||
27 | #include <string.h> |
||
28 | |||
29 | #include "inferno.h" |
||
30 | #include "editor/editor.h" |
||
31 | #include "editor/esegment.h" |
||
32 | #include "editor/medmisc.h" |
||
33 | #include "gameseg.h" |
||
34 | #include "kdefs.h" |
||
35 | #include "compiler-range_for.h" |
||
36 | #include "d_range.h" |
||
37 | |||
38 | __attribute_warn_unused_result |
||
39 | static vmsegptridx_t get_any_attached_segment(const vmsegptridx_t curseg_num, const uint_fast32_t skipside) |
||
40 | { |
||
41 | range_for (const uint_fast32_t s, xrange(MAX_SIDES_PER_SEGMENT)) |
||
42 | { |
||
43 | if (unlikely(s == skipside)) |
||
44 | continue; |
||
45 | const auto child = curseg_num->children[s]; |
||
46 | if (IS_CHILD(child)) |
||
47 | return curseg_num.absolute_sibling(child); |
||
48 | } |
||
49 | return curseg_num; |
||
50 | } |
||
51 | |||
52 | __attribute_warn_unused_result |
||
53 | static vmsegptridx_t get_previous_segment(const vmsegptridx_t curseg_num, const uint_fast32_t curside) |
||
54 | { |
||
55 | const auto side_child = curseg_num->children[Side_opposite[curside]]; |
||
56 | if (IS_CHILD(side_child)) |
||
57 | return curseg_num.absolute_sibling(side_child); |
||
58 | // no segment on opposite face, connect to anything |
||
59 | return get_any_attached_segment(curseg_num, curside); |
||
60 | } |
||
61 | |||
62 | // --------------------------------------------------------------------------------------- |
||
63 | // Select previous segment. |
||
64 | // If there is a connection on the side opposite to the current side, then choose that segment. |
||
65 | // If there is no connecting segment on the opposite face, try any segment. |
||
66 | __attribute_warn_unused_result |
||
67 | static std::pair<vmsegptridx_t, uint_fast32_t> get_previous_segment_side(const vmsegptridx_t curseg_num, const uint_fast32_t curside) |
||
68 | { |
||
69 | const auto &newseg_num = get_previous_segment(curseg_num, curside); |
||
70 | // Now make Curside point at the segment we just left (unless we couldn't leave it). |
||
71 | return {newseg_num, newseg_num == curseg_num ? curside : find_connect_side(curseg_num, newseg_num)}; |
||
72 | } |
||
73 | |||
74 | // -------------------------------------------------------------------------------------- |
||
75 | // Select next segment. |
||
76 | // If there is a connection on the current side, then choose that segment. |
||
77 | // If there is no connecting segment on the current side, try any segment. |
||
78 | __attribute_warn_unused_result |
||
79 | static std::pair<vmsegptridx_t, uint_fast32_t> get_next_segment_side(const vmsegptridx_t curseg_num, uint_fast32_t curside) |
||
80 | { |
||
81 | const auto side_child = curseg_num->children[curside]; |
||
82 | if (IS_CHILD(side_child)) |
||
83 | { |
||
84 | const auto &&newseg_num = curseg_num.absolute_sibling(side_child); |
||
85 | // Find out what side we came in through and favor side opposite that |
||
86 | const auto newside = Side_opposite[find_connect_side(curseg_num, newseg_num)]; |
||
87 | // If there is nothing attached on the side opposite to what we came in (*newside), pick any other side |
||
88 | if (!IS_CHILD(newseg_num->children[newside])) |
||
89 | range_for (const uint_fast32_t s, xrange(MAX_SIDES_PER_SEGMENT)) |
||
90 | { |
||
91 | const auto cseg = newseg_num->children[s]; |
||
92 | if (cseg != curseg_num && IS_CHILD(cseg)) |
||
93 | return {newseg_num, s}; |
||
94 | } |
||
95 | return {newseg_num, newside}; |
||
96 | } |
||
97 | else |
||
98 | { |
||
99 | return {curseg_num, curside}; |
||
100 | } |
||
101 | |||
102 | } |
||
103 | |||
104 | // ---------- select current segment ---------- |
||
105 | int SelectCurrentSegForward() |
||
106 | { |
||
107 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
108 | auto &Vertices = LevelSharedVertexState.get_vertices(); |
||
109 | const auto p = get_next_segment_side(Cursegp,Curside); |
||
110 | const auto &newseg_num = p.first; |
||
111 | |||
112 | if (newseg_num != Cursegp) |
||
113 | { |
||
114 | Cursegp = newseg_num; |
||
115 | const auto &newside = p.second; |
||
116 | Curside = newside; |
||
117 | Update_flags |= UF_ED_STATE_CHANGED; |
||
118 | if (Lock_view_to_cursegp) |
||
119 | { |
||
120 | auto &vcvertptr = Vertices.vcptr; |
||
121 | set_view_target_from_segment(vcvertptr, Cursegp); |
||
122 | } |
||
123 | |||
124 | med_create_new_segment_from_cursegp(); |
||
125 | mine_changed = 1; |
||
126 | } |
||
127 | |||
128 | return 1; |
||
129 | } |
||
130 | |||
131 | // ------------------------------------------------------------------------------------- |
||
132 | int SelectCurrentSegBackward() |
||
133 | { |
||
134 | auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state(); |
||
135 | auto &Vertices = LevelSharedVertexState.get_vertices(); |
||
136 | const auto &p = get_previous_segment_side(Cursegp,Curside); |
||
137 | Cursegp = p.first; |
||
138 | Curside = p.second; |
||
139 | |||
140 | if (Lock_view_to_cursegp) |
||
141 | { |
||
142 | auto &vcvertptr = Vertices.vcptr; |
||
143 | set_view_target_from_segment(vcvertptr, Cursegp); |
||
144 | } |
||
145 | Update_flags |= UF_ED_STATE_CHANGED; |
||
146 | mine_changed = 1; |
||
147 | med_create_new_segment_from_cursegp(); |
||
148 | |||
149 | return 1; |
||
150 | } |
||
151 | |||
152 | |||
153 | // ---------- select next/previous side on current segment ---------- |
||
154 | int SelectNextSide() |
||
155 | { |
||
156 | if (++Curside >= MAX_SIDES_PER_SEGMENT) |
||
157 | Curside = 0; |
||
158 | Update_flags |= UF_ED_STATE_CHANGED; |
||
159 | mine_changed = 1; |
||
160 | return 1; |
||
161 | } |
||
162 | |||
163 | int SelectPrevSide() |
||
164 | { |
||
165 | if (--Curside < 0) |
||
166 | Curside = MAX_SIDES_PER_SEGMENT-1; |
||
167 | Update_flags |= UF_ED_STATE_CHANGED; |
||
168 | mine_changed = 1; |
||
169 | return 1; |
||
170 | } |
||
171 | |||
172 | // ---------- Copy current segment and side to marked segment and side ---------- |
||
173 | |||
174 | int CopySegToMarked() |
||
175 | { |
||
176 | autosave_mine(mine_filename); |
||
177 | undo_status[Autosave_count] = "Mark Segment UNDONE."; |
||
178 | Markedsegp = Cursegp; |
||
179 | Markedside = Curside; |
||
180 | Update_flags |= UF_ED_STATE_CHANGED; |
||
181 | mine_changed = 1; |
||
182 | return 1; |
||
183 | } |
||
184 | |||
185 | // ---------- select absolute face on segment ---------- |
||
186 | |||
187 | int SelectBottom() |
||
188 | { |
||
189 | Curside = WBOTTOM; |
||
190 | Update_flags |= UF_ED_STATE_CHANGED; |
||
191 | mine_changed = 1; |
||
192 | return 1; |
||
193 | } |
||
194 | |||
195 | int SelectFront() |
||
196 | { |
||
197 | Curside = WFRONT; |
||
198 | Update_flags |= UF_ED_STATE_CHANGED; |
||
199 | mine_changed = 1; |
||
200 | return 1; |
||
201 | } |
||
202 | |||
203 | int SelectTop() |
||
204 | { |
||
205 | Curside = WTOP; |
||
206 | Update_flags |= UF_ED_STATE_CHANGED; |
||
207 | mine_changed = 1; |
||
208 | return 1; |
||
209 | } |
||
210 | |||
211 | int SelectBack() |
||
212 | { |
||
213 | Curside = WBACK; |
||
214 | Update_flags |= UF_ED_STATE_CHANGED; |
||
215 | mine_changed = 1; |
||
216 | return 1; |
||
217 | } |
||
218 | |||
219 | int SelectLeft() |
||
220 | { |
||
221 | Curside = WLEFT; |
||
222 | Update_flags |= UF_ED_STATE_CHANGED; |
||
223 | mine_changed = 1; |
||
224 | return 1; |
||
225 | } |
||
226 | |||
227 | int SelectRight() |
||
228 | { |
||
229 | Curside = WRIGHT; |
||
230 | Update_flags |= UF_ED_STATE_CHANGED; |
||
231 | mine_changed = 1; |
||
232 | return 1; |
||
233 | } |
||
234 |