Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Selector.cpp
Go to the documentation of this file.
1 /* Project Magic 2.0
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: Magic.exe
6  FILE: Selector.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Source file for implementation of Selector
13 */
14 
15 
16 #include "stdafx.h"
17 #include "Selector.h"
18 #include "MagicDoc.h"
19 #include "ModelView.h"
20 #include "Selection.h"
21 
22 #include "Solid.h"
23 
24 // +----------------------------------------------------------------------+
25 
27  : nmarks(0), view_mode(0), select_mode(SELECT_REPLACE), model(0)
28 {
29  if (s) {
30  selection = s;
31  own_selection = false;
32  }
33  else {
34  selection = new Selection;
35  own_selection = true;
36  }
37 
38  strcpy_s(name, "Selector");
39 }
40 
42 {
43  if (selection && own_selection)
44  delete selection;
45 }
46 
47 // +----------------------------------------------------------------------+
48 
49 const int BATCH_SIZE = 64;
50 
51 void
52 Selector::Render(Video* video, DWORD flags)
53 {
54  if (nmarks < 2 || flags == Graphic::RENDER_SOLID)
55  return;
56 
57  float points[4*BATCH_SIZE + 4];
58 
59  for (int batch = 0; batch < nmarks; batch += BATCH_SIZE) {
60  int end = batch + BATCH_SIZE;
61  if (end > nmarks-1)
62  end = nmarks-1;
63  int nlines = end-batch;
64 
65  for (int i = 0; i < nlines; i++) {
66  points[4*i+0] = (float) marks[batch + i].x;
67  points[4*i+1] = (float) marks[batch + i].y;
68  points[4*i+2] = (float) marks[batch + i + 1].x;
69  points[4*i+3] = (float) marks[batch + i + 1].y;
70  }
71 
72  video->DrawScreenLines(nlines, points, Color::Cyan);
73  }
74 }
75 
76 // +----------------------------------------------------------------------+
77 
78 void
80 {
81  if (selection)
82  selection->Clear();
83 }
84 
85 void
86 Selector::Begin(Model* m, int mode, int seln_mode)
87 {
88  nmarks = 0;
89  model = m;
90  view_mode = mode;
91  select_mode = seln_mode;
92 }
93 
94 void
96 {
97  if (nmarks < MAX_MARK)
98  marks[nmarks++] = p;
99 }
100 
101 void
103 {
105  view_mode = 0;
106 
107  // get the model:
108  if (!model || !nmarks || !view) return;
109 
110  // if not adding to selection:
111  if (select_mode == SELECT_REPLACE) {
112  Clear();
113  }
114 
115  // if only one mark:
116  if (nmarks < 2) {
117  CPoint pts[Poly::MAX_VERTS];
118 
119  // find all selected polys:
120  ListIter<Surface> s_iter = model->GetSurfaces();
121  while (++s_iter) {
122  Surface* s = s_iter.value();
123 
124  if (s->IsHidden() || s->IsLocked() || s->IsSimplified())
125  continue;
126 
127  for (int i = 0; i < s->NumPolys(); i++) {
128  Poly* poly = s->GetPolys() + i;
129 
130  if (poly->nverts < 3)
131  continue;
132 
133  for (int v = 0; v < poly->nverts; v++)
134  pts[v] = view->ProjectPoint(s->GetVertexSet()->loc[poly->verts[v]]);
135 
136  CRgn rgn;
137  rgn.CreatePolygonRgn(pts, poly->nverts, ALTERNATE);
138 
139  if (rgn.PtInRegion(marks[0])) {
140  if (select_mode == SELECT_REMOVE) {
141  selection->RemovePoly(poly);
142  }
143  else {
144  selection->AddPoly(poly);
145  }
146 
147  for (int v = 0; v < poly->nverts; v++) {
148  WORD vert = poly->verts[v];
149  if (select_mode == SELECT_REMOVE) {
150  selection->RemoveVert((WORD) s_iter.index(), vert);
151  }
152  else {
153  selection->AddVert((WORD) s_iter.index(), vert);
154  }
155  }
156  }
157  }
158  }
159  }
160 
161  // otherwise, build a region:
162  else {
163  CRgn rgn;
164  rgn.CreatePolygonRgn(marks, nmarks, WINDING);
165 
166  // find all selected verts:
167  ListIter<Surface> s_iter = model->GetSurfaces();
168  while (++s_iter) {
169  Surface* s = s_iter.value();
170  VertexSet* vset = s->GetVertexSet();
171 
172  if (s->IsHidden() || s->IsLocked() || s->IsSimplified())
173  continue;
174 
175  for (WORD i = 0; i < vset->nverts; i++) {
176  CPoint p = view->ProjectPoint(s->GetVertexSet()->loc[i]);
177  if (rgn.PtInRegion(p)) {
178  if (select_mode == SELECT_REMOVE) {
179  selection->RemoveVert((WORD) s_iter.index(), i);
180  }
181  else {
182  selection->AddVert((WORD) s_iter.index(), i);
183  }
184  }
185  }
186 
187  // find all selected polys:
188  for (int i = 0; i < s->NumPolys(); i++) {
189  Poly* poly = s->GetPolys() + i;
190 
191  bool will_select = true;
192  for (int v = 0; v < poly->nverts && will_select; v++)
193  will_select = will_select &&
194  selection->Contains((WORD) s_iter.index(), poly->verts[v]);
195 
196  if (will_select)
197  selection->AddPoly(poly);
198  else
199  selection->RemovePoly(poly);
200  }
201  }
202  }
203 }
204 
205 // +----------------------------------------------------------------------+
206 
207 void
209 {
210  model = m;
211 
212  if (selection)
214 }
215 
216 // +----------------------------------------------------------------------+
217 
218 void
219 Selector::SelectAll(int select_mode)
220 {
221  Clear();
222 
223  if (model && select_mode != SELECT_REMOVE) {
225 
226  while (++iter) {
227  Surface* s = iter.value();
228 
229  for (int i = 0; i < s->NumPolys(); i++) {
230  selection->GetPolys().append(s->GetPolys() + i);
231  }
232 
233  for (int i = 0; i < s->NumVerts(); i++) {
234  DWORD value = (iter.index() << 16) | i;
235  selection->GetVerts().push_back(value);
236  }
237  }
238  }
239 }
240 
241 // +----------------------------------------------------------------------+
242 
243 void
245 {
246  if (model && selection) {
248 
249  while (++iter) {
250  Surface* s = iter.value();
251  WORD s_index = iter.index();
252 
253  for (int i = 0; i < s->NumPolys(); i++) {
254  Poly* p = s->GetPolys() + i;
255 
256  if (selection->Contains(p))
257  selection->RemovePoly(p);
258  else
259  selection->AddPoly(p);
260  }
261 
262  for (int i = 0; i < s->NumVerts(); i++) {
263  if (selection->Contains(s_index, i))
264  selection->RemoveVert(s_index, i);
265  else
266  selection->AddVert(s_index, i);
267  }
268  }
269  }
270 }
271 
272 // +----------------------------------------------------------------------+
273 
274 void
275 Selector::SelectSurface(Surface* s, int select_mode)
276 {
277  if (!s || !model)
278  return;
279 
280  WORD index = (WORD) model->GetSurfaces().index(s);
281 
282  if (select_mode == SELECT_REMOVE) {
283  for (int i = 0; i < s->NumPolys(); i++) {
284  selection->RemovePoly(s->GetPolys() + i);
285  }
286 
287  for (int i = 0; i < s->NumVerts(); i++) {
288  selection->RemoveVert(index, i);
289  }
290  }
291  else {
292  for (WORD i = 0; i < s->NumPolys(); i++) {
293  selection->AddPoly(s->GetPolys() + i);
294  }
295 
296  for (int i = 0; i < s->NumVerts(); i++) {
297  selection->AddVert(index, i);
298  }
299  }
300 }
301 
302 void
303 Selector::SelectVert(Surface* s, int v, int select_mode)
304 {
305  if (!s || !model)
306  return;
307 
308  WORD index = (WORD) model->GetSurfaces().index(s);
309 
310  if (select_mode == SELECT_REMOVE) {
311  selection->RemoveVert(index, (WORD) v);
312  }
313  else {
314  selection->AddVert(index, (WORD) v);
315  }
316 }
317 
318 void
319 Selector::SelectPoly(Poly* poly, int select_mode)
320 {
321  if (!poly || !model)
322  return;
323 
324  if (select_mode == SELECT_REMOVE) {
325  selection->RemovePoly(poly);
326  }
327  else {
328  selection->AddPoly(poly);
329  }
330 }
331 
332 // +----------------------------------------------------------------------+
333 
334 void
335 Selector::SelectMaterial(Material* m, int select_mode)
336 {
337  if (select_mode == SELECT_REPLACE)
338  Clear();
339 
340  if (model && select_mode != SELECT_REMOVE) {
342 
343  while (++iter) {
344  Surface* s = iter.value();
345  WORD s_index = iter.index();
346 
347  for (int i = 0; i < s->NumPolys(); i++) {
348  Poly* p = s->GetPolys() + i;
349 
350  if (p->material == m) {
351  selection->AddPoly(p);
352 
353  for (int v = 0; v < p->nverts; v++) {
354  selection->AddVert(s_index, p->verts[v]);
355  }
356  }
357  }
358  }
359  }
360 }
361 
362 // +----------------------------------------------------------------------+
363 
364 void
366 {
367  selection->GetPolys().clear();
368 
369  if (model) {
371 
372  while (++iter) {
373  Surface* s = iter.value();
374  WORD s_index = iter.index();
375 
376  // find all selected polys:
377  for (int i = 0; i < s->NumPolys(); i++) {
378  Poly* poly = s->GetPolys() + i;
379 
380  bool will_select = true;
381  for (int v = 0; v < poly->nverts && will_select; v++)
382  will_select = will_select &&
383  selection->Contains(s_index, poly->verts[v]);
384 
385  if (will_select)
386  selection->AddPoly(poly);
387  }
388  }
389  }
390 }