source: golgotha/src/maxtool/st_edit.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 11.9 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "st_edit.hh"
10#include "m1_info.hh"
11#include "window/window.hh"
12#include "gtext_load.hh"
13#include "image/image.hh"
14#include "max_object.hh"
15#include "window/win_evt.hh"
16#include "device/kernel.hh"
17#include "render.hh"
18#include "app/app.hh"
19#include "window/wmanager.hh"
20#include "gui/text_input.hh"
21#include "tmanage.hh"
22
23#define HANDLE_SIZE   3
24#define SNAP_DISTANCE 5
25
26i4_float m1_st_edit_window_class::twidth() const
27{
28  return (texture)? texture->width()-0.0001 : 255.9999;
29}
30
31i4_float m1_st_edit_window_class::theight() const
32{
33  return (texture)? texture->height()-0.0001 : 255.9999;
34}
35
36void m1_st_edit_window_class::get_point(int poly, int num, int &x, int &y)
37{
38  if (m1_info.obj)
39  {
40    g1_quad_class *q=m1_info.obj->quad+poly;
41    float tw=twidth(), th=theight();
42
43    x=(int)(q->u[num] * tw);
44    y=(int)(q->v[num] * th);
45  }
46}
47
48void m1_st_edit_window_class::draw(i4_draw_context_class &context)
49{
50  local_image->clear(0, context);
51
52  if (texture)
53    texture->put_image(local_image, 0,0, context);
54 
55  if (m1_info.obj)
56  {
57    w32 c=0x0000ff;   //(254<<16)|(2<<8)|166; 
58    int x1,y1,x2,y2;
59
60    for (int j=0; j<m1_info.obj->num_quad; j++)
61    {
62      if (m1_info.obj->quad[j].get_flags(g1_quad_class::SELECTED))
63      {
64        int i;
65       
66        g1_quad_class *q=&m1_info.obj->quad[j];
67
68        get_point(j,0,x2,y2);       
69        for (i=q->num_verts()-1; i>=0; i--)
70        {
71          get_point(j,i,x1,y1);
72          local_image->line(x1,y1,x2,y2,  c, context);
73          x2 = x1; y2 = y1;
74        }
75
76        for (i=0; i<q->num_verts(); i++)
77        {
78          int x,y;   
79          get_point(j,i,x,y);
80          if (m1_info.obj->get_poly_vert_flag(j,1<<i))
81            local_image->bar(x-2,y-2,x+2,y+2, 0xffff00, context);
82          else
83            local_image->bar(x-2,y-2,x+2,y+2, 0x808080, context);
84        }
85      }
86    }
87    if (preselect_x>=0)
88      local_image->bar(preselect_x-2,preselect_y-2,preselect_x+2,preselect_y+2, 0xff00ff, context);
89  }
90}
91
92void m1_st_edit_window_class::drag_points(int xc, int yc)
93{
94  m1_poly_object_class *obj=m1_info.obj;
95  if (!obj) return;
96 
97  float tw=twidth(), th=theight();
98  float u_change=xc/tw, v_change=yc/th;
99  i4_bool change=i4_F;
100       
101  for (int i=0; i<m1_info.obj->num_quad; i++)
102  {
103    if (obj->quad[i].get_flags(g1_quad_class::SELECTED))
104    {   
105      for (int j=0; j<obj->quad[i].num_verts(); j++)
106      {
107        if (obj->get_poly_vert_flag(i, 1<<j))
108        {
109          obj->quad[i].u[j]+=u_change;
110          if (obj->quad[i].u[j]<0) obj->quad[i].u[j]=0;
111          if (obj->quad[i].u[j]>1) obj->quad[i].u[j]=1;
112
113          obj->quad[i].v[j]+=v_change;
114          if (obj->quad[i].v[j]<0) obj->quad[i].v[j]=0;
115          if (obj->quad[i].v[j]>1) obj->quad[i].v[j]=1;
116          change=i4_T;
117        }
118      }
119    }
120  }
121
122  if (change)
123  {
124    obj->calc_texture_scales();
125    request_redraw(i4_F);
126    if (m1_render_window.get())
127      m1_render_window->request_redraw(i4_F);
128  }
129}
130
131i4_bool m1_st_edit_window_class::verts_are_selected()
132{
133  if (!m1_info.obj)
134    return 0;
135
136  for (int j=0; j<m1_info.obj->num_quad; j++)
137    if (m1_info.obj->quad[j].get_flags(g1_quad_class::SELECTED))
138    {
139      for (int i=0; i<m1_info.obj->quad[j].num_verts(); i++)
140        if (m1_info.obj->get_poly_vert_flag(j,1<<i))
141          return i4_T;
142    }
143
144  return i4_F;
145}
146
147void m1_st_edit_window_class::select_point(int point)
148{
149  if (!m1_info.obj)
150    return;
151
152  if (point<0)
153    return;
154
155  m1_poly_object_class *obj=m1_info.obj;
156 
157  if (!i4_current_app->get_window_manager()->shift_pressed())
158  {
159    for (int j=0; j<obj->num_quad; j++)
160      for (int i=0; i<4; i++)
161        obj->set_poly_vert_flag(j, 1<<i, 0);   
162  }
163
164  for (int j=0; j<obj->num_quad; j++)
165  {
166    g1_quad_class *q=obj->quad+j;
167    if (q->get_flags(g1_quad_class::SELECTED))
168      for (int i=0; i<q->num_verts(); i++)
169        if (q->vertex_ref[i] == point)
170          obj->set_poly_vert_flag(j, 1<<i, 1);
171  }
172
173  request_redraw();
174}
175
176void m1_st_edit_window_class::change_current_verts()
177{
178  if (!m1_info.obj)
179    return;
180
181  int old_px = preselect_x;
182  int old_py = preselect_y;
183
184  preselect_x = -1;
185
186  if (m1_info.preselect_point>=0)
187    for (int j=0; j<m1_info.obj->num_quad; j++)
188      if (m1_info.obj->quad[j].get_flags(g1_quad_class::SELECTED))
189      {
190        for (int i=0; i<m1_info.obj->quad[j].num_verts(); i++)
191          if (m1_info.obj->quad[j].vertex_ref[i] == m1_info.preselect_point)
192            get_point(j,i,preselect_x,preselect_y);
193      }
194 
195  if (preselect_x!=old_px || preselect_y!=old_py)
196    request_redraw();
197}
198
199void m1_st_edit_window_class::change_current_texture(i4_const_str new_name)
200{
201  if (m1_info.obj)
202  {
203    i4_file_class *fp=i4_open(new_name);
204    if (!fp) return;
205    delete fp;
206    int i;
207
208    for (i=0; i<m1_info.obj->num_quad; i++)
209      if (m1_info.obj->quad[i].get_flags(g1_quad_class::SELECTED))
210      {
211        delete m1_info.obj->texture_names[i];
212        m1_info.obj->texture_names[i]=new i4_str(new_name);
213      }
214
215    m1_info.texture_list_changed();
216  }
217}
218
219
220void m1_st_edit_window_class::receive_event(i4_event *ev)
221{
222  int pre_grab = grab;
223
224  m1_poly_object_class *obj=m1_info.obj;
225  if (!obj)
226    return ;
227
228  switch (ev->type())
229  {
230    case i4_event::WINDOW_MESSAGE:
231    {
232      CAST_PTR(wev, i4_window_message_class, ev);
233      if (wev->sub_type==i4_window_message_class::GOT_DROP)
234        i4_kernel.send_event(tname_edit, ev);
235    } break;
236
237    case i4_event::OBJECT_MESSAGE :
238    {
239      CAST_PTR(tc, i4_text_change_notify_event, ev);
240      if (tc->object==tname_edit && tc->new_text && m1_info.obj)
241      {
242        i4_file_class *fp=i4_open(*tc->new_text);
243        if (!fp) return;
244        delete fp;
245        int i;
246
247        for (i=0; i<m1_info.obj->num_quad; i++)
248          if (m1_info.obj->quad[i].get_flags(g1_quad_class::SELECTED))
249            m1_info.obj->texture_names[i]=new i4_str(*tc->new_text);
250
251        m1_info.texture_list_changed();
252      }
253
254
255    } break;
256
257    case i4_event::MOUSE_BUTTON_DOWN :
258    {     
259      CAST_PTR(bev, i4_mouse_button_down_event_class, ev);
260
261      if (bev->left())   grab |= LEFT;
262      if (bev->right())  grab |= RIGHT;
263      if (bev->center()) grab |= MIDDLE;
264
265      i4_window_request_key_grab_class kgrab(this);
266      i4_kernel.send_event(parent, &kgrab);
267
268      i4_bool clear_old=i4_T;
269      int sel_poly=-1, sel_vert=-1;
270
271      if (bev->left() && obj)
272      {
273        for (int j=0; j<obj->num_quad; j++)
274        {
275          g1_quad_class *q=obj->quad+j;
276          if (q->get_flags(g1_quad_class::SELECTED))
277          {
278            for (int i=0; i<q->num_verts(); i++)
279            {
280              int x,y;
281              get_point(j,i,x,y);
282              if (abs(bev->x-x)<HANDLE_SIZE && abs(bev->y-y)<HANDLE_SIZE)
283              {
284                if (obj->get_poly_vert_flag(j, 1<<i))
285                  clear_old=i4_F;
286                else
287                  obj->set_poly_vert_flag(j, 1<<i, 1);
288
289                sel_poly=j;
290                sel_vert=i;
291              }
292            }
293          }
294        }
295      }
296
297      if (clear_old && !i4_current_app->get_window_manager()->shift_pressed())
298      {
299        for (int j=0; j<obj->num_quad; j++)
300          for (int i=0; i<4; i++)
301            obj->set_poly_vert_flag(j, 1<<i, 0);   
302
303        if (sel_poly!=-1)
304          obj->set_poly_vert_flag(sel_poly, 1<<sel_vert, 1);
305      }
306
307      request_redraw(i4_T);
308    } break;
309
310    case i4_event::MOUSE_BUTTON_UP :
311    {
312      CAST_PTR(bev, i4_mouse_button_up_event_class, ev);
313
314      if (bev->left())   grab &= ~LEFT;
315      if (bev->right())  grab &= ~RIGHT;
316      if (bev->center()) grab &= ~MIDDLE;
317    } break;
318   
319    case i4_event::MOUSE_MOVE :
320    {
321      CAST_PTR(mev, i4_mouse_move_event_class, ev);
322
323      int old_px = preselect_x, old_py = preselect_y;
324
325      preselect_x = -1;
326
327      if (m1_info.obj)
328      {
329        if (grab && verts_are_selected())
330        {
331          int snap_x = mev->x, snap_y = mev->y;
332
333          for (int j=0; j<m1_info.obj->num_quad; j++)
334          {
335            g1_quad_class *q=m1_info.obj->quad+j;
336            if (q->get_flags(g1_quad_class::SELECTED))
337            {
338              for (int i=0; i<q->num_verts(); i++)
339              {
340                if (!m1_info.obj->get_poly_vert_flag(j,1<<i))
341                {
342                  int x,y;
343                  get_point(j,i,x,y);
344                  if (abs(mev->x-x)<SNAP_DISTANCE && abs(mev->y-y)<SNAP_DISTANCE)
345                  {
346                    snap_x = x;
347                    snap_y = y;
348                  }
349                }
350              }
351            }
352          }
353
354          drag_points(snap_x+snap_off_x-mev->lx, snap_y+snap_off_y-mev->ly);
355
356          snap_off_x = mev->x - snap_x;
357          snap_off_y = mev->y - snap_y;
358        }
359        else
360        {
361          for (int j=0; j<m1_info.obj->num_quad; j++)
362          {
363            g1_quad_class *q=m1_info.obj->quad+j;
364            if (q->get_flags(g1_quad_class::SELECTED))
365            {
366              for (int i=0; i<q->num_verts(); i++)
367              {
368                int x,y;
369                get_point(j,i,x,y);
370                if (abs(mev->x-x)<HANDLE_SIZE && abs(mev->y-y)<HANDLE_SIZE)
371                {
372                  preselect_x = x;
373                  preselect_y = y;
374                  snap_off_x = mev->x - preselect_x;
375                  snap_off_y = mev->y - preselect_y;
376                }
377              }
378            }
379          }
380        }
381
382        if (old_px!=preselect_x || old_py!=preselect_y)
383          request_redraw();
384      }
385
386    } break;
387
388  }
389  if (!pre_grab && grab)
390  {
391    i4_window_request_mouse_grab_class grab_ev(this);
392    i4_kernel.send_event(parent,&grab_ev);
393  }
394  if (pre_grab && !grab)
395  {
396    i4_window_request_mouse_ungrab_class grab_ev(this);
397    i4_kernel.send_event(parent,&grab_ev);
398  }
399}
400
401
402
403void m1_st_edit_window_class::edit_poly_changed()
404{
405  if (texture)   
406    delete texture;
407  texture=0;
408
409  if (m1_info.obj)
410  {
411    m1_poly_object_class *obj=m1_info.obj;
412
413    int sel_poly=-1;
414    for (int j=0; j<obj->num_quad; j++)
415      if (obj->quad[j].get_flags(g1_quad_class::SELECTED))
416      {
417        if (sel_poly==-1)
418          sel_poly=j;
419        else if (sel_poly>=0)
420          if (!(*obj->texture_names[sel_poly] == *obj->texture_names[j]))
421            sel_poly=-2;
422      }
423
424    if (sel_poly==-1)
425      tname_edit->change_text("<None Selected>");
426    else if (sel_poly==-2)
427      tname_edit->change_text("<Multiple Selected>");
428    else
429    {
430      i4_image_class *im[10];
431      int t=r1_load_gtext(r1_get_texture_id(*obj->texture_names[sel_poly]), im);
432     
433      for (int i=1; i<t; i++)
434        delete im[i];
435     
436      if (t)
437        texture=im[0];
438
439      if (texture)
440        tname_edit->change_text(*obj->texture_names[sel_poly]);
441      else
442        tname_edit->change_text("<Untextured>");
443    }
444  }
445
446  request_redraw(i4_F);
447}
448
449
450m1_st_edit_window_class::m1_st_edit_window_class(w16 w, w16 h,
451                                                 i4_text_input_class *tname_edit)
452  : i4_window_class(w,h),
453    tname_edit(tname_edit)
454{
455  texture=0;
456  dragging=i4_F;
457  preselect_x = -1;
458  grab=0;
459}
460
461i4_event_handler_reference_class<m1_st_edit_window_class> m1_st_edit;
462
463
464
Note: See TracBrowser for help on using the repository browser.