Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
UVMapView.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: UVMapView.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Implementation of the UVMapView class
13 */
14 
15 #include "stdafx.h"
16 #include "Magic.h"
17 
18 #include "MagicDoc.h"
19 #include "UVMapView.h"
20 #include "Selector.h"
21 #include "Selection.h"
22 
23 #include "ActiveWindow.h"
24 #include "Color.h"
25 #include "Screen.h"
26 #include "Video.h"
27 
28 DWORD GetRealTime();
29 
30 #ifdef _DEBUG
31 #define new DEBUG_NEW
32 #undef THIS_FILE
33 static char THIS_FILE[] = __FILE__;
34 #endif
35 
36 // +--------------------------------------------------------------------+
37 
39  : View(c), material(0), zoom(1), x_offset(0), y_offset(0),
40  nmarks(0), select_mode(SELECT_REPLACE), active(false)
41 {
42 }
43 
45 {
46 }
47 
48 // +--------------------------------------------------------------------+
49 
50 const int BATCH_SIZE = 64;
51 
52 void
54 {
56  if (!video)
57  return;
58 
60 
61  if (material && material->tex_diffuse) {
62  Bitmap* bmp = material->tex_diffuse;
63  int w = bmp->Width();
64  int h = bmp->Height();
65 
66  double cx = window->Width() / 2 + x_offset;
67  double cy = window->Height() / 2 + y_offset;
68 
69  int x1 = (int) (cx - (zoom * w/2));
70  int x2 = (int) (cx + (zoom * w/2));
71  int y1 = (int) (cy - (zoom * h/2));
72  int y2 = (int) (cy + (zoom * h/2));
73 
74  window->DrawBitmap(x1, y1, x2, y2, bmp);
75 
76  ListIter<Poly> iter = polys;
77  while (++iter) {
78  Poly* p = iter.value();
79  VertexSet* vset = p->vertex_set;
80 
81  if (p->material != material)
82  continue;
83 
84  for (int i = 0; i < p->nverts; i++) {
85  int n1 = p->verts[i];
86  int n2 = p->verts[0];
87  if (i < p->nverts-1)
88  n2 = p->verts[i+1];
89 
90  double tu1 = vset->tu[n1];
91  double tv1 = vset->tv[n1];
92  double tu2 = vset->tu[n2];
93  double tv2 = vset->tv[n2];
94 
95  x1 = (int) (cx + zoom * w * (tu1-0.5));
96  x2 = (int) (cx + zoom * w * (tu2-0.5));
97  y1 = (int) (cy + zoom * h * (tv1-0.5));
98  y2 = (int) (cy + zoom * h * (tv2-0.5));
99 
100  window->DrawLine(x1, y1, x2, y2, Color::Yellow);
101 
102  if (IsSelected(p, i))
103  window->FillRect(x1-3, y1-3, x1+3, y1+3, Color::Yellow);
104  else
105  window->DrawRect(x1-2, y1-2, x1+2, y1+2, Color::Yellow);
106  }
107  }
108  }
109 
110  if (active && nmarks > 1) {
111  float points[4*BATCH_SIZE + 4];
112 
113  for (int batch = 0; batch < nmarks; batch += BATCH_SIZE) {
114  int end = batch + BATCH_SIZE;
115  if (end > nmarks-1)
116  end = nmarks-1;
117  int nlines = end-batch;
118 
119  for (int i = 0; i < nlines; i++) {
120  points[4*i+0] = (float) marks[batch + i].x;
121  points[4*i+1] = (float) marks[batch + i].y;
122  points[4*i+2] = (float) marks[batch + i + 1].x;
123  points[4*i+3] = (float) marks[batch + i + 1].y;
124  }
125 
126  video->DrawScreenLines(nlines, points, Color::Cyan);
127  }
128  }
129 
130  const char* title = "UV Editor";
131 
132  int len = strlen(title);
133  Rect r(6,4,200,20);
134 
135  r.x += window->GetRect().x;
136  r.y += window->GetRect().y;
137 
138  video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::Black);
139 
140  r.x--;
141  r.y--;
142 
143  video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::White);
144 }
145 
146 // +--------------------------------------------------------------------+
147 
148 void
150 {
151  if (material != m) {
152  material = m;
153  zoom = 1;
154  x_offset = 0;
155  y_offset = 0;
156  }
157 }
158 
159 void
161 {
162  polys.clear();
163  polys.append(p);
164 }
165 
166 void
167 UVMapView::MoveBy(double dx, double dy)
168 {
169  x_offset += dx;
170  y_offset += dy;
171 }
172 
173 void
174 UVMapView::DragBy(double dx, double dy)
175 {
176  if (!material || !material->tex_diffuse || selverts.size() < 1)
177  return;
178 
179  Bitmap* bmp = material->tex_diffuse;
180  double w = zoom * bmp->Width();
181  double h = zoom * bmp->Height();
182  float du = (float) (dx/w);
183  float dv = (float) (dy/h);
184 
185  for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) {
186  DWORD value = *svi;
187  DWORD p = value >> 16;
188  DWORD n = value & 0xffff;
189 
190  Poly* poly = polys[p];
191  if (poly && n < poly->nverts) {
192  VertexSet* vset = poly->vertex_set;
193  int v = poly->verts[n];
194 
195  vset->tu[v] += du;
196  vset->tv[v] += dv;
197  }
198  }
199 }
200 
201 // +----------------------------------------------------------------------+
202 
203 void
205 {
206  selverts.clear();
207 }
208 
209 void
210 UVMapView::Begin(int seln_mode)
211 {
212  nmarks = 0;
213  select_mode = seln_mode;
214  active = true;
215 }
216 
217 void
219 {
220  if (nmarks < MAX_MARK)
221  marks[nmarks++] = p;
222 }
223 
224 void
226 {
227  active = false;
228 
229  // get the model:
230  if (!nmarks || !material || !material->tex_diffuse) return;
231 
232  // if not adding to selection:
233  if (select_mode == SELECT_REPLACE) {
234  Clear();
235  }
236 
237  Bitmap* bmp = material->tex_diffuse;
238  int w = bmp->Width();
239  int h = bmp->Height();
240 
241  double cx = window->Width() / 2 + x_offset;
242  double cy = window->Height() / 2 + y_offset;
243 
244 
245  // if only one mark:
246  if (nmarks < 2) {
247  // find all selected verts:
248  ListIter<Poly> iter = polys;
249  while (++iter) {
250  Poly* p = iter.value();
251  VertexSet* vset = p->vertex_set;
252 
253  for (int i = 0; i < p->nverts; i++) {
254  int n1 = p->verts[i];
255  double tu1 = vset->tu[n1];
256  double tv1 = vset->tv[n1];
257 
258  int x1 = (int) (cx + zoom * w * (tu1-0.5));
259  int y1 = (int) (cy + zoom * h * (tv1-0.5));
260 
261  int dx = abs(marks[0].x - x1);
262  int dy = abs(marks[0].y - y1);
263 
264  if (dx < 4 && dy < 4) {
265  WORD p_index = iter.index();
266  DWORD value = (p_index << 16) | i;
267 
268  if (select_mode == SELECT_REMOVE) {
269  for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) {
270  if (*svi == value) {
271  selverts.erase(svi);
272  }
273  }
274  }
275  else {
276  bool contains = false;
277  for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) {
278  if (*svi == value) {
279  contains = true;
280  }
281  }
282  if (!contains)
283  selverts.push_back(value);
284  }
285  }
286  }
287  }
288  }
289 
290  // otherwise, build a region:
291  else {
292  CRgn rgn;
293  rgn.CreatePolygonRgn(marks, nmarks, WINDING);
294 
295  // find all selected verts:
296  ListIter<Poly> iter = polys;
297  while (++iter) {
298  Poly* p = iter.value();
299  VertexSet* vset = p->vertex_set;
300 
301  for (int i = 0; i < p->nverts; i++) {
302  int n1 = p->verts[i];
303  double tu1 = vset->tu[n1];
304  double tv1 = vset->tv[n1];
305 
306  int x1 = (int) (cx + zoom * w * (tu1-0.5));
307  int y1 = (int) (cy + zoom * h * (tv1-0.5));
308 
309  CPoint p(x1,y1);
310 
311  if (rgn.PtInRegion(p)) {
312  WORD p_index = iter.index();
313  DWORD value = (p_index << 16) | i;
314 
315  if (select_mode == SELECT_REMOVE) {
316  for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) {
317  if (*svi == value)
318  selverts.erase(svi);
319  }
320  }
321  else {
322  bool contains = false;
323  for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) {
324  if (*svi == value)
325  contains = true;
326  }
327  if (!contains)
328  selverts.push_back(value);
329  }
330  }
331  }
332  }
333  }
334 
335  nmarks = 0;
336 }
337 
338 // +----------------------------------------------------------------------+
339 
340 void
342 {
343  selverts.clear();
344 
345  ListIter<Poly> iter = polys;
346  while (++iter) {
347  Poly* p = iter.value();
348 
349  if (p->material != material)
350  continue;
351 
352  for (int i = 0; i < p->nverts; i++) {
353  WORD p_index = iter.index();
354  DWORD value = (p_index << 16) | i;
355  selverts.push_back(value);
356  }
357  }
358 }
359 
360 void
362 {
363  selverts.clear();
364 }
365 
366 void
368 {
369  ListIter<Poly> iter = polys;
370  while (++iter) {
371  Poly* p = iter.value();
372 
373  if (p->material != material)
374  continue;
375 
376  for (int i = 0; i < p->nverts; i++) {
377  WORD p_index = iter.index();
378  DWORD value = (p_index << 16) | i;
379 
380  bool contains = false;
381  auto svi = selverts.begin();
382  for (; svi != selverts.end(); ++svi) {
383  if (*svi == value) contains = true;
384  break;
385  }
386 
387  if (contains)
388  selverts.erase(svi);
389  else
390  selverts.push_back(value);
391  }
392  }
393 }
394 
395 bool
397 {
398  WORD p = polys.index(poly);
399  DWORD value = (p << 16) | v;
400 
401  bool contains = false;
402 
403  for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) {
404  return true;
405  }
406 
407  return false;
408 }
409 
410 bool
412 {
413  if (!material || !material->tex_diffuse)
414  return false;
415 
416  Bitmap* bmp = material->tex_diffuse;
417  int w = bmp->Width();
418  int h = bmp->Height();
419 
420  double cx = window->Width() / 2 + x_offset;
421  double cy = window->Height() / 2 + y_offset;
422 
423  // find first selected vert:
424  ListIter<Poly> iter = polys;
425  while (++iter) {
426  Poly* poly = iter.value();
427  VertexSet* vset = poly->vertex_set;
428 
429  for (int i = 0; i < poly->nverts; i++) {
430  int n1 = poly->verts[i];
431  double tu1 = vset->tu[n1];
432  double tv1 = vset->tv[n1];
433 
434  int x1 = (int) (cx + zoom * w * (tu1-0.5));
435  int y1 = (int) (cy + zoom * h * (tv1-0.5));
436 
437  int dx = abs(p.x - x1);
438  int dy = abs(p.y - y1);
439 
440  if (dx < 4 && dy < 4) {
441  return true;
442  }
443  }
444  }
445 
446  return false;
447 }