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 |