source: golgotha/src/golg/editor/contedit.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: 18.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 "editor/contedit.hh"
10#include "controller.hh"
11#include "map.hh"
12#include "tile.hh"
13#include "window/win_evt.hh"
14#include "string/string.hh"
15#include "draw_context.hh"
16#include "font/font.hh"
17#include "window/style.hh"
18#include "resources.hh"
19#include "editor/dialogs/obj_win.hh"
20#include "math/pi.hh"
21#include "mess_id.hh"
22#include "loaders/load.hh"
23#include "editor/edit_id.hh"
24#include "g1_object.hh"
25#include "editor/commands/fill.hh"
26#include "device/keys.hh"
27#include "editor/e_state.hh"
28#include "window/win_evt.hh"
29#include "m_flow.hh"
30#include "image/color.hh"
31#include "input.hh"
32
33#include "editor/mode/e_tile.hh"
34#include "editor/mode/e_camera.hh"
35#include "editor/mode/e_light.hh"
36#include "editor/mode/e_object.hh"
37// #include "editor/mode/e_ai.hh"
38
39#include "editor/editor.hh"
40#include "r1_clip.hh"
41#include "g1_render.hh"
42#include "r1_api.hh"
43#include "app/app.hh"
44#include "window/wmanager.hh"
45#include "f_tables.hh"
46#include "map_vert.hh"
47#include "lisp/lisp.hh"
48
49
50void g1_controller_edit_class::update_cursor()
51{
52  if (!active())
53  {
54    if (cursor_state!=G1_X_CURSOR)
55    {
56      cursor_state=G1_X_CURSOR;
57      set_cursor(g1_resources.big_cursors[cursor_state]);
58    }
59  }
60  else if (mode)
61    mode->update_cursor();
62}
63
64
65
66void g1_controller_edit_class::setup_context()
67
68  g1_context.window_setup(0,0,width(), height(),
69                          g1_render.center_x, g1_render.center_y,
70                          g1_render.scale_x, g1_render.scale_y,
71                          g1_render.ooscale_x, g1_render.ooscale_y);
72}
73
74void g1_controller_edit_class::setup_mode()
75{
76  if (mode && active())
77    mode->hide_focus();
78
79  if (mode)
80  {
81    delete mode;   
82  }
83
84  mode=0;
85
86
87  for (g1_mode_creator *mc=g1_mode_creator::first; mc; mc=mc->next)
88    if (strcmp(g1_edit_state.major_mode, mc->name())==0)
89      mode=mc->create_mode_handler(this);
90
91  if (mode && active())
92    mode->show_focus();
93
94  refresh();
95
96
97}
98
99void g1_controller_edit_class::show_focus()
100{
101  if (!focus_visible)
102  {
103    mode->show_focus();
104    focus_visible=i4_T;
105  }
106}
107
108void g1_controller_edit_class::hide_focus()
109{
110  if (focus_visible)
111  {
112    mode->hide_focus();
113    focus_visible=i4_F;
114  }
115}
116
117void g1_controller_edit_class::refresh()
118{
119  i4_user_message_event_class ch(G1_MAP_CHANGED);
120  i4_kernel.send_event(i4_current_app, &ch);
121}
122
123g1_controller_edit_class::~g1_controller_edit_class()
124
125  g1_edit_state.context_help.hide();
126
127  if (active())
128    unfocused();
129
130  if (mode)
131  {
132    delete mode;   
133    mode=0;
134  }
135}
136
137
138void g1_controller_edit_class::unfocused()
139{
140  hide_focus();
141
142  update_cursor();
143
144  if (g1_current_controller.get()==this)
145    g1_current_controller=0;
146 
147
148  request_redraw();
149}
150
151void g1_controller_edit_class::focused()
152{
153  setup_mode();
154
155  g1_current_controller=this;
156 
157  i4_window_request_key_grab_class kgrab(this);
158  i4_kernel.send_event(parent, &kgrab);
159
160  show_focus();
161  request_redraw();
162
163  cursor_state=G1_DEFAULT_CURSOR;
164  set_cursor(g1_resources.big_cursors[cursor_state]);
165}
166
167void g1_replace_cell(g1_map_class *map,
168                     g1_map_cell_class &original,
169                     g1_map_cell_class &new_cell)
170{
171  g1_map_cell_class old;
172
173  while (original.get_obj_list())
174  {
175    g1_object_class *o=original.object_list->object;
176    o->unoccupy_location();
177
178    old=original;
179    original=new_cell;
180    o->occupy_location();
181    new_cell=original;
182    original=old;       
183  }
184
185  old=original;
186  original=new_cell;
187  new_cell=old;
188 
189  I4_ASSERT(new_cell.object_list==0, "new cell list should be null");
190
191}
192
193void g1_controller_edit_class::replace_cell(g1_map_class *map,
194                                            g1_map_cell_class &original,
195                                            g1_map_cell_class &new_cell)
196{
197  g1_replace_cell(map, original, new_cell);
198}
199
200void g1_controller_edit_class::restore_cell()
201{
202  if (need_restore_cell)
203  {
204    if (g1_map_is_loaded())
205    {
206      replace_cell(get_map(),
207                   *get_map()->cell(cell_x, cell_y),
208                   saved_cell);
209
210      need_restore_cell=i4_F;
211
212      li_call("redraw");
213    }
214  }
215}
216
217void g1_controller_edit_class::save_and_put_cell()
218{
219  if (g1_map_is_loaded())
220  {
221    saved_cell=*get_map()->cell(cell_x, cell_y);
222    saved_cell.object_list=0;                    // don't keep the object list
223
224    g1_map_cell_class new_cell;
225    new_cell.init(g1_e_tile.get_cell_type(),
226                  g1_e_tile.get_cell_rotation(),
227                  g1_e_tile.get_mirrored());
228
229    replace_cell(get_map(), *get_map()->cell(cell_x, cell_y), new_cell);
230 
231    need_restore_cell=i4_T;
232
233    li_call("redraw");
234  }
235}
236
237class g1_map_fill_class : public g1_flood_fill_class
238{
239
240public:
241  g1_map_class *map;
242  g1_map_class *get_map() { return map; }
243  w16 type, block_type;
244  g1_rotation_type rotation;
245  g1_player_type owner;
246  i4_bool mirror;
247
248  virtual void get_clip(sw32 &x1, sw32 &y1, sw32 &x2, sw32 &y2)
249  {
250    x1=y1=0;
251    x2=get_map()->width()-1;
252    y2=get_map()->height()-1;
253  }
254
255  i4_bool blocking(sw32 x, sw32 y)
256  {
257    w16 on_type=get_map()->cell(x,y)->type;
258    if (on_type==block_type)
259      return i4_F;
260    else return i4_T;
261  }
262
263  void fill_block(sw32 x, sw32 y, sw32 startx, sw32 starty)
264  {
265    g1_map_cell_class c;
266    c.init(type, rotation, mirror);
267
268    g1_replace_cell(map, *get_map()->cell(x,y), c);
269  }
270
271  g1_map_fill_class(g1_map_class *map, w16 type,
272                    g1_rotation_type rotation,
273                    i4_bool mirror,
274                    g1_player_type owner,
275                    w16 block_type)
276    : map(map), type(type), rotation(rotation),
277      mirror(mirror),
278      block_type(block_type), owner(owner)
279  {}
280};
281
282void g1_controller_edit_class::fill_map()
283{
284  if (g1_map_is_loaded())
285  {
286    g1_editor_instance.add_undo(G1_MAP_CELLS);
287
288    if (active())
289      hide_focus();   
290
291
292    w32 type_on=get_map()->cell(cell_x, cell_y)->type;
293
294    if (type_on!=g1_e_tile.get_cell_type())
295    {
296      g1_map_fill_class f(get_map(),
297                          g1_e_tile.get_cell_type(),
298                          g1_e_tile.get_cell_rotation(),
299                          g1_e_tile.get_mirrored(),
300                          g1_edit_state.current_team,
301                          type_on);
302
303      f.fill(cell_x, cell_y);
304    }
305
306
307    if (active())
308      show_focus();
309
310    changed();
311  }
312}
313
314void g1_controller_edit_class::change_map_cell()
315{
316  g1_editor_instance.add_undo(G1_MAP_CELLS);
317
318  graph_changed=i4_T;
319  saved_cell.init(g1_e_tile.get_cell_type(),
320                  g1_e_tile.get_cell_rotation(),
321                  g1_e_tile.get_mirrored());
322  changed();
323}
324
325
326void g1_controller_edit_class::draw_3d_line(const i4_3d_point_class &p1,
327                                            const i4_3d_point_class &p2,
328                                            i4_color color1,
329                                            i4_color color2,
330                                            i4_image_class *local_image,
331                                            g1_draw_context_class *context)
332{
333  g1_render.render_3d_line(p1, p2, color1, color2, context->transform);
334}
335
336
337void g1_controller_edit_class::draw_3d_point(sw32 w,
338                                             i4_color color,
339                                             const i4_3d_point_class &p,
340                                             i4_image_class *local_image,
341                                             g1_draw_context_class *context)
342{
343  r1_vert v;
344  if (g1_render.project_point(p, v, context->transform))
345    r1_clip_clear_area((sw32)v.px-w, (sw32)v.py-w,
346                       (sw32)v.px+w, (sw32)v.py+w, color, v.v.z, *context->context,
347                       g1_render.r_api);
348}
349
350
351void g1_controller_edit_class::draw_spline(i4_image_class *local_image,
352                                           g1_draw_context_class *g1_context,
353                                           i4_color cpoint_color,
354                                           i4_color line_color,
355                                           i4_color spline_color,
356                                           i4_spline_class *s,
357                                           w32 cur_frame)
358{
359  sw32 i;
360  i4_float lx,ly,x,y,z;
361  if (!s->total()) return;
362
363  i4_spline_class::point *p;   
364  i4_3d_point_class cur_p, last_p;
365
366  for (i=0; i<s->total(); i++)
367  {
368    p=s->get_control_point(i);     
369
370    cur_p=i4_3d_point_class(p->x, p->y, p->z);
371
372    if (i!=0)
373      draw_3d_line(cur_p, last_p, line_color, line_color, local_image, g1_context);
374   
375    last_p=cur_p;
376  }
377
378
379  p=s->get_control_point(0);
380
381  w32 frame=0;
382
383  while (p->next)
384  {
385    while (frame<p->next->frame)
386    {
387      i4_float x1,y1,z1,x2,y2,z2;
388
389      i4_3d_point_class q1,q2;
390      s->get_point(frame, x1,y1,z1);
391         
392
393      if (g1_e_camera.should_show_frames()) 
394        draw_3d_point(1, 0x0000ff, i4_3d_point_class(x1,y1,z1), local_image, g1_context);
395
396      if (frame==cur_frame)
397        draw_3d_point(1, 0xff00ff, i4_3d_point_class(x1,y1,z1), local_image, g1_context);
398
399      frame++;
400
401      s->get_point(frame, x2,y2,z2);
402      draw_3d_line(i4_3d_point_class(x1,y1,z1),
403                   i4_3d_point_class(x2,y2,z2),
404                   spline_color, spline_color,
405                   local_image, g1_context);
406
407
408    }
409    p=p->next;
410  }
411
412  for (i=0; i<s->total(); i++)
413  {
414    i4_3d_point_class q;
415
416    i4_spline_class::point *p=s->get_control_point(i);
417
418    if (p->selected)
419      draw_3d_point(1, 0xffff00,
420                    i4_3d_point_class(p->x,p->y,p->z), local_image, g1_context);
421    else
422      draw_3d_point(1,
423                    cpoint_color,
424                    i4_3d_point_class(p->x,p->y,p->z), local_image, g1_context);
425  }
426
427
428}
429
430void g1_controller_edit_class_tile_post_cell_draw(sw32 x, sw32 y, void *context)
431{
432  ((g1_controller_edit_class *)context)->tile_cell_draw(x,y);
433}
434
435
436void g1_controller_edit_class_object_post_cell_draw(sw32 x, sw32 y, void *context)
437{
438  ((g1_controller_edit_class *)context)->object_cell_draw(x,y);
439}
440
441void g1_controller_edit_class::object_cell_draw(sw32 x, sw32 y)
442{
443  g1_map_class *map=get_map();
444
445   int bgrade=-1;
446//   for (int j=0; j<G1_GRADE_LEVELS; j++)
447//   {
448//     g1_block_map_class *bmap=map->get_block_map(j);
449//     if (bmap && bmap->is_blocked(x,y, G1_NORTH | G1_SOUTH | G1_WEST | G1_EAST))
450//       bgrade=j;
451//   }
452
453  if ((map->cell(x,y)->flags & g1_map_cell_class::IS_GROUND)==0)
454    bgrade=0;
455
456  if (map->cell(x,y)->get_solid_list())
457    bgrade=1;
458  else
459    bgrade=-1;
460
461  if (bgrade!=-1)
462  {
463    w32 c[5]={0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xff00ff };
464
465    float r=0.01;
466    draw_3d_line(i4_3d_point_class(x,y, map->terrain_height(x,y)+r),
467                 i4_3d_point_class(x+1,y+1, map->terrain_height(x+1,y+1)+r),
468                 c[bgrade], c[bgrade], local_image, &g1_context);
469
470    draw_3d_line(i4_3d_point_class(x+1,y, map->terrain_height(x+1,y)+r),
471                 i4_3d_point_class(x,y+1, map->terrain_height(x,y+1)+r),
472                 c[bgrade], c[bgrade], local_image, &g1_context);
473  }
474
475}
476
477void g1_controller_edit_class::tile_cell_draw(sw32 x, sw32 y)
478{
479  r1_vert rv;
480  g1_map_class *map=get_map();
481
482  g1_map_vertex_class *v[4];
483  v[0]=map->vertex(x,y);
484  v[1]=v[0]+1;
485  v[2]=v[0]+map->width()+1;
486  v[3]=v[0]+map->width()+1+1;
487
488  int vt[8]={x,y,x+1,y,x,y+1,x+1,y+1};
489
490  object_cell_draw(x,y);
491
492  for (w32 i=0; i<4; i++)
493  {
494    if (v[i]->is_selected())
495    {
496      i4_3d_point_class cp(vt[i*2],vt[i*2+1],v[i]->get_height());
497
498      if (g1_render.project_point(cp, rv, g1_context.transform))
499        r1_clip_clear_area((sw32)rv.px-1, (sw32)rv.py-1, (sw32)rv.px+1, (sw32)rv.py+1,
500                           0xffff00, rv.v.z, *g1_context.context,
501                           g1_render.r_api);
502    }
503
504    v[i]->set_flag(g1_map_vertex_class::WAS_DRAWN_LAST_FRAME,1);
505  }
506
507}
508
509void g1_controller_edit_class::editor_pre_draw(i4_draw_context_class &context)
510{
511  g1_render.frame_ratio=0;
512
513  if (g1_map_is_loaded() && active())
514  {
515    int w=(get_map()->width()+1) * (get_map()->height()+1);
516    g1_map_vertex_class *v=get_map()->vertex(0,0);
517
518    for (int i=0; i<w; i++, v++)
519      v->set_flag(g1_map_vertex_class::WAS_DRAWN_LAST_FRAME, 0);
520  }
521
522  if (strcmp(g1_edit_state.major_mode,"TILE")==0 && get_map())
523    get_map()->set_post_cell_draw_function(g1_controller_edit_class_tile_post_cell_draw, this);
524
525  if (strcmp(g1_edit_state.major_mode,"OBJECT")==0 && get_map())
526    get_map()->set_post_cell_draw_function(g1_controller_edit_class_object_post_cell_draw, this);
527
528
529  if (g1_resources.paused)
530    g1_context.draw_editor_stuff=i4_T;
531
532  if (view.get_view_mode()==G1_EDIT_MODE)
533  {
534    g1_render.r_api->set_write_mode(R1_WRITE_COLOR | R1_WRITE_W);
535    r1_clip_clear_area(0,0,width()-1, height()-1, 0, r1_far_clip_z, context, g1_render.r_api);
536    g1_render.r_api->set_write_mode(R1_WRITE_COLOR | R1_WRITE_W | R1_WRITE_COLOR);
537  }
538
539}
540
541void g1_controller_edit_class::editor_post_draw(i4_draw_context_class &context)
542{
543
544  g1_context.draw_editor_stuff=i4_F;
545
546  if (g1_map_is_loaded())
547    get_map()->set_post_cell_draw_function(0,0);
548
549  mode->post_draw(context);
550
551  if (active())
552    g1_render.draw_rectangle(0,0, width()-1, height()-1, 0xffff00, context);
553  else
554    g1_render.draw_rectangle(0,0, width()-1, height()-1, 0, context);
555}
556
557
558
559void g1_controller_edit_class::process_input(i4_time_class tick_time)
560{
561  /*  if (have_focus)
562  {
563    if (!get_map()) return;
564   
565    i4_angle a=camera.ground_rotate, move_speed=1.0, pan_speed=0.2;
566
567    if (camera.gx>=0 && camera.gy>=0 &&
568        camera.gx<get_map()->width() && camera.gy<get_map()->height())
569    {
570      i4_float th=get_map()->terrain_height(camera.gx, camera.gy);
571      i4_float camera_dist=camera.gz-th;
572
573      if (camera_dist<6)
574      {
575        pan_speed*=camera_dist/6.0;
576        move_speed*=camera_dist/6.0;
577      }
578    }
579
580
581
582    if (g1_editor_instance.movement.rotate_left)
583      rotate(0.08, 0);
584
585    if (g1_editor_instance.movement.rotate_right)
586      rotate(-0.08, 0);
587
588    if (g1_editor_instance.movement.rotate_up)
589      rotate(0, -0.08);
590
591    if (g1_editor_instance.movement.rotate_down)
592      rotate(0, 0.08);
593
594
595    if (g1_editor_instance.movement.pan_down)
596      pan(0,0,-pan_speed);
597
598    if (g1_editor_instance.movement.pan_up)
599      pan(0,0,pan_speed);
600
601    if (g1_editor_instance.movement.pan_left)
602      pan(-sin(a)*move_speed, cos(a)*move_speed,0);
603
604    if (g1_editor_instance.movement.pan_right)
605      pan(sin(a)*move_speed, -cos(a)*move_speed,0);
606
607    if (g1_editor_instance.movement.pan_forward)
608      pan(cos(a)*move_speed, sin(a)*move_speed,0);
609
610    if (g1_editor_instance.movement.pan_backward)
611      pan(-cos(a)*move_speed, -sin(a)*move_speed,0);
612
613
614      } */
615}
616
617g1_map_vertex_class *g1_controller_edit_class::find_map_vertex(sw32 x, sw32 y,
618                                                               sw32 &vx, sw32 &vy)
619{
620  sw32 sx,sy,ex,ey, tx,ty;
621  sx=(sw32)0;  sy=(sw32)0;
622  ex=(sw32)get_map()->width();  ey=(sw32)get_map()->height();
623
624  g1_map_vertex_class *mv=get_map()->vertex(0,0);
625
626  if (!g1_context.transform)
627    return 0;
628
629  // transform all the points in area and test proximity to mouse x,y
630  for (ty=sy; ty<=ey; ty++)
631    for (tx=sx; tx<=ex; tx++)
632    {
633      if (mv->get_flag(g1_map_vertex_class::WAS_DRAWN_LAST_FRAME))
634      {
635        r1_vert v;
636
637        if (g1_render.project_point(i4_3d_point_class(tx, ty, mv->get_height()),
638                                    v, g1_context.transform))
639        {
640          if (abs((sw32)v.px-x)<=3 && abs((sw32)v.py-y)<=3)
641          {
642            vx=tx; vy=ty;
643            return mv;
644          }
645        }     
646      }
647      mv++;
648    }
649
650  return 0;
651}
652
653
654
655
656void g1_controller_edit_class::clear_selected_verts()
657{
658  if (!i4_current_app->get_window_manager()->control_pressed())
659  {
660    i4_bool change=i4_F;
661
662    sw32 w=(get_map()->width()+1)*(get_map()->height()+1);
663    g1_map_vertex_class *v=get_map()->vertex(0,0);
664
665
666    for (w32 x=0; x<w; x++, v++)
667      if (v->is_selected())
668      {
669        change=i4_T;
670        v->set_is_selected(i4_F);
671      }
672
673    if (change)
674    {
675      changed();
676      refresh();
677    }
678  }
679}
680
681
682void g1_controller_edit_class::select_verts_in_area(sw32 x1, sw32 y1,
683                                                    sw32 x2, sw32 y2,
684                                                    g1_mode_handler::select_modifier mod)
685{
686  sw32 w=(get_map()->width()+1),h=(get_map()->height()+1),x,y;
687  g1_map_vertex_class *v=get_map()->vertex(0,0);
688 
689  i4_bool change=i4_F;
690
691  g1_editor_instance.add_undo(G1_MAP_VERTS);
692
693
694  for (y=0; y<h; y++)
695    for (x=0; x<w; x++, v++)
696    {
697      if (v->get_flag(g1_map_vertex_class::WAS_DRAWN_LAST_FRAME))
698      {
699        r1_vert vt;
700        if (g1_render.project_point(i4_3d_point_class(x, y, v->get_height()),
701                                    vt,
702                                    g1_context.transform))
703        {
704          if (vt.px>=x1 && vt.px<=x2 && vt.py>=y1 && vt.py<=y2)
705          {
706            change=i4_T;
707
708            if (mod==g1_mode_handler::SUB_FROM_OLD)
709              v->set_is_selected(i4_F);
710            else
711              v->set_is_selected(i4_T);
712
713
714          }
715          else if (mod==g1_mode_handler::CLEAR_OLD_IF_NO_SELECTION)
716          {
717            if (v->is_selected())
718            {
719              change=i4_T;
720              v->set_is_selected(i4_F);
721            }
722          }
723        } else if (mod==g1_mode_handler::CLEAR_OLD_IF_NO_SELECTION)
724        {
725          if (v->is_selected())
726          {
727            change=i4_T;
728            v->set_is_selected(i4_F);
729          }
730        }
731      }
732    }
733
734  if (change)
735  {
736    changed();
737    refresh();
738  }
739}
740
741
742g1_controller_edit_class::g1_controller_edit_class(w16 w, w16 h,
743                                                   i4_graphical_style_class *style)
744  : g1_object_controller_class(w,h, style)
745{   
746  focus_visible=i4_F;
747
748  move_vert_x=move_vert_y=0;
749  move_vert_z=0;
750  move_verts=i4_F;
751
752  edit_win=0;
753  drag_select=i4_F;
754  move_points=i4_F;
755
756  graph_changed=i4_F;
757  need_restore_cell=i4_F;     
758  place_object=0;
759  selected_object=0;
760
761  place_object_on_map=i4_F;
762  cell_x=cell_y=0;
763   
764  mode=0;
765  setup_mode();
766
767}
768
Note: See TracBrowser for help on using the repository browser.