Subversion Repositories Games.Descent

Rev

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