source: golgotha/src/golg/controller.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: 23.2 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 "controller.hh"
10#include "objs/stank.hh"
11#include "map.hh"
12#include "window/win_evt.hh"
13#include "time/profile.hh"
14#include "menu/menu.hh"
15#include "menu/textitem.hh"
16#include "window/style.hh"
17#include "time/time.hh"
18#include "math/pi.hh"
19#include "resources.hh"
20#include "input.hh"
21#include "math/angle.hh"
22#include "mess_id.hh"
23#include "sound_man.hh"
24#include "math/random.hh"
25#include "g1_speed.hh"
26#include "remove_man.hh"
27#include "image/color.hh"
28#include "light.hh"
29#include "statistics.hh"
30#include "g1_render.hh"
31#include "r1_api.hh"
32#include "player.hh"
33#include "m_flow.hh"
34#include "math/trig.hh"
35#include "time/profile.hh"
36#include "app/app.hh"
37#include "loaders/load.hh"
38#include "g1_texture_id.hh"
39#include "tmanage.hh"
40#include "saver.hh"
41#include "human.hh"
42#include "objs/explode_model.hh"
43#include "objs/def_object.hh"
44#include "objs/miscobjs.hh"
45#include "tick_count.hh"
46#include "r1_clip.hh"
47#include "status/status.hh"
48#include "lisp/lisp.hh"
49#include "device/key_man.hh"
50#include <stdlib.h>
51
52enum {
53  G1_CONTROLLER_WIREFRAME,
54  G1_CONTROLLER_TEXTUREMAP,
55  G1_CONTROLLER_WHITE_LIGHT,
56  G1_CONTROLLER_320X200,
57  G1_CONTROLLER_400X400,
58  G1_CONTROLLER_640X480,
59  G1_CONTROLLER_SCROLL
60};
61
62static li_symbol_ref li_mouse_left_button("mouse_left_button"),
63                     li_mouse_right_button("mouse_right_button");
64 
65i4_event_handler_reference_class<g1_object_controller_class> g1_current_controller;
66
67i4_profile_class pf_draw_overhead("controller::draw_overhead"),
68  pf_test_clip("controller::test_clip");
69
70extern sw32 g1_cur_num_map_objects;
71
72//  View Frustrum Points
73enum { NUM_VIEW_POINTS=5 };
74static i4_3d_vector view_point[NUM_VIEW_POINTS];
75
76class view_point_init_class : i4_init_class
77{
78public:
79  void init()
80  {
81    view_point[0].set(   0,   0,   0 );
82    view_point[1].set( 200, 200, 200 );
83    view_point[2].set(-200, 200, 200 );
84    view_point[3].set(-200,-200, 200 );
85    view_point[4].set( 200,-200, 200 );
86  }
87};
88static view_point_init_class view_point_init;
89
90
91void g1_controller_global_id_reset_notifier::reset()
92{
93  for_who->reset_global_ids();
94}
95
96void g1_object_controller_class::reset_global_ids()
97{
98  selectable_list.t_recent=0;
99}
100
101i4_bool g1_object_controller_class::add_spin_event(char *model_name, w8 lost)
102{
103  spin_event e(g1_model_list_man.find_handle(model_name), lost);
104  return spin_events.que(e);
105}
106
107g1_player_piece_class *g1_object_controller_class::get_track()
108{
109  return g1_player_man.get(team_on())->get_commander();
110}
111
112
113g1_player_type g1_object_controller_class::team_on() const
114{
115  return (g1_human)? g1_human->team() : g1_default_player;
116}
117
118
119void g1_object_controller_class::get_pos(i4_3d_vector& pos)
120{
121  view.get_camera_pos(pos);
122}
123
124g1_object_controller_class::g1_object_controller_class(w16 w, w16 h,
125                                                       i4_graphical_style_class *style)
126  : i4_parent_window_class(w,h),
127    style(style),
128    notifier(0)
129{
130  scroll_active=i4_F;
131  for (int i=0; i<MAX_MESSAGES; i++)
132    messages[i].text[0]=0;
133
134  notifier.for_who=this;
135  first_frame=i4_T;
136
137  cursor_state=255;
138  flags=NEED_CLEAR;
139
140  context_menu=0;
141
142  last_frame_draw_time.get();
143
144  frames_to_count=8;
145  frame_rate=0;
146
147  mouse_mask=0;
148}
149
150g1_object_controller_class::~g1_object_controller_class()
151{
152  stop_scroll();
153}
154
155
156void g1_object_controller_class::setup_context(i4_draw_context_class &i4_context)
157{
158  g1_context.window_setup(0,0,width(), height(),
159                          g1_render.center_x, g1_render.center_y,
160                          g1_render.scale_x, g1_render.scale_y,
161                          g1_render.ooscale_x, g1_render.ooscale_y);
162
163  g1_context.transform=&transform;
164  g1_context.context=&i4_context;
165  g1_context.screen=local_image;
166  g1_context.style=style;
167
168  g1_render.calculate_frame_ratio();
169
170  selectable_list.t_recent=0;
171  g1_render.current_selectable_list=&selectable_list;
172
173}
174
175#define MAX(x,y) (x)>(y)?(x):(y)
176
177extern i4_bool g1_disable_all_drawing;
178
179extern i4_3d_point_class listentemp;
180
181i4_profile_class pf_controller_draw("controller::parent_draw");
182
183void g1_object_controller_class::draw_counts()
184{
185#if 0      // not working anymore - fixme:jc
186  i4_float z=g1_near_z_range();
187  int xoff,yoff,x=0;
188  int icon_sx = g1_resources.stat_pad_size_x/2;
189  int icon_sy = g1_resources.stat_pad_size_x/2;
190 
191  xoff = g1_resources.stat_pad_start_x;
192  yoff = g1_resources.stat_pad_start_y;
193
194  if (yoff>0) yoff += g1_resources.radar_window.y2;
195
196  if (g1_resources.render_window_expand_mode==R1_COPY_2x2)
197  {
198    xoff = xoff*3/4;
199    yoff = yoff/2;
200  }
201  if (xoff<0) xoff+= width();
202  if (yoff<0) yoff+= height();
203
204  g1_render.r_api->set_shading_mode(R1_COLORED_SHADING);
205  g1_render.r_api->set_write_mode(R1_WRITE_COLOR);
206
207
208
209  if (current_spin.model==0)
210    if (spin_events.deque(current_spin))
211    {
212      last_stat_time.get();
213      stat_x = (i4_float(x) - g1_render.center_x)/(g1_render.center_x*g1_render.scale_x);
214      stat_y = (i4_float(yoff) - g1_render.center_y)/(g1_render.center_y*g1_render.scale_y);
215      if (current_spin.type==spin_event::GAINED)
216        stat_time = 3000;
217      else
218        stat_time = 500;
219    }
220
221
222  if (current_spin.model)
223  {
224    i4_time_class now;
225    stat_time -= now.milli_diff(last_stat_time);
226    last_stat_time.get();
227
228    if (stat_time<=0)    // we are done with this spin
229      current_spin.model=0;
230    else
231    {
232      g1_quad_object_class *model = g1_model_list_man.get_model(current_spin.model);
233
234      if (model)
235      {
236        i4_3d_vector pos(0,0,0);
237        i4_float w=1.0;
238
239        if (current_spin.type==spin_event::GAINED)
240        {
241          if      (stat_time>2000) { w = 1/(1.0 + i4_float(stat_time-2000)*0.02); }
242          else if (stat_time>500)  { }  // sit for a while
243          else                   
244          {
245            i4_float frac = 1.0-i4_float(stat_time)/500.0;
246            pos.x = i4_interpolate(pos.x,stat_x,frac);
247            pos.y = i4_interpolate(pos.y,stat_y,frac);
248            w = (0.2 - 1.0)*frac + 1.0;
249          }
250        }
251        else
252        {
253          i4_float frac = 1.0-i4_float(stat_time)/500.0;
254          pos.x = i4_interpolate(stat_x,-1.0,frac);
255          pos.y = stat_y;
256          w = i4_interpolate(0.2, 1.0, frac);
257        }
258        pos.z = 1.0;
259
260        i4_transform_class scale, rot, transform;
261
262        transform.translate(pos);
263        transform.mult_rotate_y(stat_time*i4_2pi()/1000.0);
264        transform.mult_rotate_x(i4_pi()/2.0);
265        transform.mult_uniscale(w);
266
267        i4_float save_ambient = g1_lights.ambient_intensity;
268
269        g1_lights.ambient_intensity = 1.0;
270        g1_render.render_object(model, &transform, 0, w);
271        g1_lights.ambient_intensity = save_ambient;
272      }
273    }
274
275  }
276#endif
277}
278
279int last_draw_tick=0;
280int frame_locked_mode=0;
281
282void g1_object_controller_class::parent_draw(i4_draw_context_class &context)
283{
284  if (frame_locked_mode)
285  {
286    if (last_draw_tick!=g1_tick_counter)
287      last_draw_tick=g1_tick_counter;
288    else
289      return ;
290  }
291 
292  if (!g1_render.main_draw)
293  {
294    if (clear_if_cannot_draw())
295    {
296      g1_render.r_api->default_state();
297      g1_render.r_api->clear_area(0,0, width()-1, height()-1, 0, g1_far_z_range());
298    }
299
300    request_redraw(i4_F);
301    return ;
302  }
303
304  if (!g1_map_is_loaded())
305  {
306    local_image->clear(0,context);
307    return ;
308  }
309
310  i4_parent_window_class::parent_draw(context);
311
312  update_cursor();
313
314  if (g1_disable_all_drawing) return; 
315
316  pf_controller_draw.start();
317
318  setup_context(context);
319
320
321  frames_to_count--;
322  if (frames_to_count==0)
323  {
324    frames_to_count=FRAME_MEASURE_INTERVAL;
325    i4_time_class now;
326    frame_rate=1.0/(float)(now.milli_diff(last_frame_draw_time)/(1000.0*FRAME_MEASURE_INTERVAL));
327    last_frame_draw_time.get();
328  } 
329 
330
331  i4_bool repeat;
332  do
333  {
334    repeat=i4_F;
335
336    g1_render.r_api->default_state();
337
338
339    g1_render.r_api->set_z_range(g1_near_z_range(), g1_far_z_range()+0.01);
340
341    if (g1_render.draw_mode==g1_render_class::WIREFRAME)
342      g1_render.r_api->clear_area(0,0, width()-1, height()-1, 0, g1_far_z_range());
343
344
345    g1_player_piece_class *track=get_track();
346
347    editor_pre_draw(context);
348
349
350    g1_render.r_api->set_write_mode(R1_WRITE_COLOR | R1_WRITE_W | R1_COMPARE_W);
351    g1_render.r_api->set_shading_mode(R1_COLORED_SHADING);
352    g1_render.r_api->set_alpha_mode(R1_ALPHA_DISABLED);
353    g1_render.r_api->set_color_tint(0);
354 
355    view.calc_transform(transform);
356    setup_clip();
357 
358    //   //are we using a software rasterizer?
359    //   if (view_mode==STRATEGY_MODE && !camera_is_zooming())
360    //   {
361    //     g1_render.r_api->modify_features(R1_PERSPECTIVE_CORRECT, 0);
362    //     g1_render.r_api->modify_features(R1_SPANS, 1);
363    //   }
364
365    g1_render.r_api->modify_features(R1_PERSPECTIVE_CORRECT, 1);
366    g1_render.r_api->modify_features(R1_SPANS, 1);
367
368    draw_overhead(&g1_context);
369
370 
371    editor_post_draw(context);
372
373    g1_render.post_draw_quads();
374
375
376    sw32 cx1=context.xoff,
377      cy1=context.yoff;
378    sw32 cx2=cx1+width()-1,
379      cy2=cy1+height()-1;
380
381    if (view.get_view_mode()==G1_ACTION_MODE ||
382        view.get_view_mode()==G1_STRATEGY_MODE ||
383        view.get_view_mode()==G1_FOLLOW_MODE)     
384      draw_counts();
385
386    g1_render.r_api->get_tmanager()->next_frame();
387    g1_stat_counter.t_frames++;
388
389    g1_render.current_selectable_list=0;
390
391
392    if (first_frame &&
393        g1_render.r_api->get_tmanager()->texture_resolution_change())
394    {
395      g1_render.r_api->clear_area(0,0, width()-1, height()-1, 0, r1_far_clip_z);
396      repeat=i4_T;
397     
398      for (i4_idle_class *p=i4_idle_class::first; p;p=p->next)
399        p->idle();
400    }
401
402    // keep drawing till everything is rez-ed in
403  } while (repeat);
404  first_frame=i4_F;
405
406
407  int tx=0, ty=0;
408  for (int i=0; i<MAX_MESSAGES; i++)
409  {   
410    if (messages[i].text[0])
411    {
412      g1_render.rendered_font->set_color(messages[i].color);
413      g1_render.rendered_font->put_string(local_image, tx,ty, messages[i].text, context);
414      ty+=g1_render.rendered_font->height(messages[i].text);
415    }
416  }
417
418  pf_controller_draw.stop();
419}
420
421void g1_object_controller_class::start_scroll()
422{
423  if (!scroll_active)
424  {
425    scroll_active=i4_T;
426    i4_event *ev=new i4_user_message_event_class(G1_CONTROLLER_SCROLL);
427    message_scroll_id=i4_time_dev.request_event(this,  ev, 8000);
428  }
429}
430
431void g1_object_controller_class::stop_scroll()
432{
433  if (scroll_active)
434  {
435    i4_time_dev.cancel_event(message_scroll_id);
436    scroll_active=i4_F;
437  }
438}
439
440
441void g1_object_controller_class::scroll_message(const i4_const_str &m, w32 color)
442{
443  start_scroll();
444
445  int i;
446  for (i=0; i<MAX_MESSAGES; i++)
447  {
448    w32 c=messages[i].color;
449    c=((((c>>16)&0xff)>>1)<<16)|
450      ((((c>>8)&0xff)>>1)<<8)|
451      ((((c>>0)&0xff)>>1)<<0);
452    messages[i].color=c; 
453   
454
455    if (messages[i].text[0]==0)
456    {
457      i4_os_string(m, messages[i].text, sizeof(messages[i].text));
458      messages[i].color=color;
459      return ;
460    }
461  }
462
463  for (i=0; i>MAX_MESSAGES-1; i++)
464    memcpy(&messages[i], &messages[i+1], sizeof(message));
465
466  i4_os_string(m, messages[MAX_MESSAGES-1].text, sizeof(messages[0]));
467  messages[MAX_MESSAGES-1].color=color;
468
469  request_redraw();
470}
471
472void g1_object_controller_class::window_event(i4_window_message_class *wev)
473{
474  switch (wev->sub_type)
475  {
476    case i4_window_message_class::LOST_KEYBOARD_FOCUS :
477      set_flag(KEY_FOCUS, i4_F);
478      request_redraw();
479      break;
480  }
481}
482
483void g1_object_controller_class::do_command_event(i4_do_command_event_class *ev)
484{
485  if (!strcmp(ev->command, "Toggle Stats"))
486    g1_stat_counter.show(); 
487  else if (!strcmp(ev->command, "Toggle Texture Loading"))
488    g1_render.r_api->get_tmanager()->toggle_texture_loading();
489  else if (!strcmp(ev->command, "Show Help"))
490  {
491    i4_user_message_event_class u(G1_HELP_SCREEN);
492    i4_kernel.send_event(i4_current_app, &u);
493  } 
494  else
495    g1_input.receive_event(ev);
496}
497
498void g1_object_controller_class::end_command_event(i4_end_command_event_class *ev)
499{
500  g1_input.receive_event(ev);
501}
502
503g1_object_class *dummy_obj = NULL;
504
505void g1_object_controller_class::change_mouse_mask(int new_mask)
506{
507 
508  i4_bool lock=i4_F;
509  if (new_mask & MOUSE_RIGHT)
510  {
511    if (mouse_mask & MOUSE_LEFT) // don't ack right if left is already down
512      return ;
513
514    lock=i4_T;
515  }
516
517//   if (new_mask && !mouse_mask)
518//   {
519//     i4_window_request_mouse_grab_class grab(this, lock);
520//     i4_kernel.send_event(parent, &grab);
521//   }
522//   else if (!new_mask && mouse_mask)
523//   {
524//     i4_window_request_mouse_ungrab_class ungrab(this);
525//     i4_kernel.send_event(parent, &ungrab);
526//   }
527
528  mouse_mask=new_mask;
529}
530
531
532void g1_object_controller_class::reparent(i4_image_class *draw_area, i4_parent_window_class *parent)
533{
534  change_mouse_mask(0);
535  i4_parent_window_class::reparent(draw_area, parent);
536}
537
538void g1_object_controller_class::update_cursor()
539{
540  g1_object_class *o=find_object_under_mouse(last_mouse_x, last_mouse_y);
541  w8 new_cursor=g1_human->determine_cursor(o);
542
543  if (new_cursor!=cursor_state)
544  {
545    set_cursor(g1_resources.big_cursors[new_cursor]);
546    cursor_state=new_cursor;
547  }
548}
549
550
551void g1_object_controller_class::receive_event(i4_event *ev)
552{
553  i4_parent_window_class::receive_event(ev);
554
555  switch (ev->type())
556  {
557    case i4_event::USER_MESSAGE :
558    {
559      CAST_PTR(uev, i4_user_message_event_class, ev);
560      if (uev->sub_type==G1_CONTROLLER_SCROLL)
561      {
562        for (int i=0; i<MAX_MESSAGES-1; i++)
563        {   
564          memcpy(&messages[i], &messages[i+1], sizeof(message));
565          w32 c=messages[i].color;
566          c=((((c>>16)&0xff)>>1)<<16)|
567            ((((c>>8)&0xff)>>1)<<8)|
568            ((((c>>0)&0xff)>>1)<<0);
569          messages[i].color=c; 
570
571        }
572
573        messages[MAX_MESSAGES-1].text[0]=0;
574
575        request_redraw();
576
577        scroll_active=i4_F;
578        if (messages[0].text[0])
579          start_scroll();
580      }
581
582    } break;
583
584    case i4_event::WINDOW_MESSAGE :
585    {
586      CAST_PTR(wev,i4_window_message_class,ev);
587      window_event(wev);
588
589    } break;
590
591    case i4_event::MOUSE_BUTTON_UP :
592    {
593      CAST_PTR(mev,i4_mouse_button_up_event_class,ev);
594
595      if (view.get_view_mode()==G1_ACTION_MODE)
596      {
597        if (mev->left())
598        {
599          char *s=li_string::get(li_get_value(li_mouse_left_button.get()),0)->value();
600          i4_end_command_event_class cmd(s, i4_key_man.get_command_id(s), mev->time);
601          g1_input.receive_event(&cmd);
602        }
603        else if (mev->right())
604        {
605          char *s=li_string::get(li_get_value(li_mouse_right_button.get()),0)->value();
606          i4_end_command_event_class cmd(s, i4_key_man.get_command_id(s), mev->time);
607          g1_input.receive_event(&cmd);
608        }
609      }
610
611
612    } break;
613
614    case i4_event::MOUSE_BUTTON_DOWN :
615    {
616      CAST_PTR(mev,i4_mouse_button_down_event_class,ev);
617
618      if (view.get_view_mode()==G1_ACTION_MODE)
619      {
620        if (mev->left())
621        {
622          char *s=li_string::get(li_get_value(li_mouse_left_button.get()),0)->value();
623          i4_do_command_event_class cmd(s, i4_key_man.get_command_id(s), mev->time);
624          g1_input.receive_event(&cmd);
625        }
626        else if (mev->right())
627        {
628          char *s=li_string::get(li_get_value(li_mouse_right_button.get()),0)->value();
629          i4_do_command_event_class cmd(s, i4_key_man.get_command_id(s), mev->time);
630          g1_input.receive_event(&cmd);
631        }
632      }
633    } break;
634
635
636    case i4_event::DO_COMMAND :
637    {
638      CAST_PTR(kev, i4_do_command_event_class, ev);
639      do_command_event(kev);
640    } break;
641
642    case i4_event::END_COMMAND :
643    {
644      CAST_PTR(kev, i4_end_command_event_class, ev);
645      end_command_event(kev);
646    } break;
647
648  }
649  i4_window_class::receive_event(ev);
650}
651
652void g1_object_controller_class::delete_context_menu()
653{
654  if (context_menu)
655  {
656    delete context_menu;
657    context_menu=0;
658    note_undrawn(0,0,width()-1,height()-1);
659    request_redraw();
660  }
661}
662
663
664
665void g1_object_controller_class::resize(w16 new_width, w16 new_height)
666{
667  set_flag(NEED_CLEAR,i4_T);
668  i4_parent_window_class::resize(new_width,new_height);
669}
670
671 
672
673
674
675void g1_object_controller_class::update_camera()
676{
677  if (view.get_view_mode()!=G1_EDIT_MODE)
678  {
679    view.update();
680    request_redraw(i4_F);
681  }
682  else    // see if the camera moved
683  {
684    g1_camera_info_struct old_camera=*view.get_camera();
685    view.update();
686
687    if (memcmp(view.get_camera(), &old_camera, sizeof(g1_camera_info_struct))!=0)
688      request_redraw(i4_F);
689  }
690}
691
692
693
694i4_bool g1_object_controller_class::view_to_game(sw32 mouse_x, sw32 mouse_y,
695                                                 i4_float &game_x, i4_float &game_y,
696                                                 i4_float &dir_x, i4_float &dir_y)
697{
698  i4_3d_vector c_pos, c_dir, c_plane;
699
700
701  i4_transform_class tran=transform;
702 
703  i4_float max_dim = width() > height() ? (i4_float)width() : (i4_float)height();
704  max_dim/=2;
705
706  i4_float mx=(mouse_x - width()/2);
707  i4_float my=(mouse_y - height()/2); 
708
709  tran.inverse_transform(i4_3d_vector(0,0,0),c_pos);
710  tran.inverse_transform(i4_3d_vector(mx,my, max_dim),c_dir); 
711
712  c_dir -= c_pos;       
713
714  i4_float t = -(c_pos.z/c_dir.z);
715
716  dir_x = c_dir.x;
717  dir_y = c_dir.y;
718
719  i4_float dist = sqrt(dir_x*dir_x + dir_y*dir_y);
720  dir_x /= dist;
721  dir_y /= dist;
722
723  if (t<0)
724    return i4_F;
725
726  //where the camera/mouse ray intersects the ground
727  i4_float g_intersect_x, g_intersect_y;
728
729  g_intersect_x = c_pos.x + c_dir.x * t;
730  g_intersect_y = c_pos.y + c_dir.y * t;
731  i4_float z    = c_pos.z + c_dir.z * t;
732  if (z>0.1 || z<-0.1)
733  {
734    i4_float a=0;
735    //    i4_warning("bad view_to_game calculation");
736  }
737
738  i4_float d_x = g_intersect_x - c_pos.x;
739  i4_float d_y = g_intersect_y - c_pos.y;
740  i4_float d_z = -c_pos.z;
741  i4_float biggest = fabs(d_x);
742  if (fabs(d_y)>biggest) biggest = fabs(d_y);
743 
744  //dont check for big z step. height only changes on
745  //x and y steps
746
747  biggest *= 4;
748 
749  d_x /= biggest;
750  d_y /= biggest;
751  d_z /= biggest;
752
753  i4_float px=c_pos.x, py=c_pos.y, pz=c_pos.z;
754
755  if (px>=get_map()->width() || py>=get_map()->height() || px<0 || py<0 ||
756      get_map()->terrain_height(px,py)>pz)
757  {
758    game_x = px;
759    game_y = py;
760    return i4_T;
761  }
762  for (t=0;t<biggest;t+=1)
763  {
764    px += d_x;
765    py += d_y;
766    pz += d_z;
767    if (px<get_map()->width() && py<get_map()->height() && px>=0 && py>=0)
768    {
769      if (get_map()->terrain_height(px,py)>pz)
770      {
771        d_x /= 4;
772        d_y /= 4;
773        d_z /= 4;
774        while (get_map()->terrain_height(px,py)>pz)
775        {
776          px -= d_x;
777          py -= d_y;
778          pz -= d_z;       
779        }
780        game_x = px;
781        game_y = py;
782        return i4_T;
783      }
784    }
785    else
786    {
787      game_x = px - d_x;
788      game_y = py - d_y;
789      return i4_T;
790    }
791  }
792  game_x = px;
793  game_y = py;
794
795  return i4_T;
796}
797
798
799g1_object_class *g1_object_controller_class::find_object_under_mouse(sw32 mx, sw32 my)
800{
801  g1_screen_box *b=selectable_list.recent, *closest=0;
802
803  for (int i=0; i<selectable_list.t_recent; i++, b++)
804  {
805    if (mx>=b->x1 && mx<=b->x2 &&
806        my>=b->y1 && my<=b->y2)
807    {
808      if (!closest || closest->z1>b->z1)
809        closest=b;
810    }
811  }
812
813  if (closest && g1_global_id.check_id(closest->object_id))
814    return g1_global_id.get(closest->object_id);
815
816  return 0;
817}
818
819
820void g1_object_controller_class::set_exclusive_mode(i4_bool yes_no)
821{
822  if (!parent)
823    i4_error("call set exclusive when window is parented");
824
825  i4_window_request_key_grab_class kgrab(this);
826  i4_kernel.send_event(parent, &kgrab);
827
828  if (!kgrab.return_result)
829    i4_error("key grab failed");
830
831  request_redraw();
832}
833
834
835
836void g1_object_controller_class::zoom(i4_float dist)
837{
838  view.zoom(dist);
839  request_redraw(i4_F);
840}
841
842void g1_object_controller_class::pan(i4_float x, i4_float y, i4_float z)
843{
844  view.pan(x,y,z);
845  request_redraw(i4_F);
846}
847
848
849void g1_object_controller_class::rotate(i4_float about_game_z, i4_float up_down)
850{
851  view.rotate(about_game_z, up_down);
852  request_redraw(i4_F);
853}
854
855inline float fmin(float a, float b) { return (a<b)?a:b; }
856inline float fmax(float a, float b) { return (a>b)?a:b; }
857
858void g1_object_controller_class::setup_clip()
859//  precalculate constants used to clip orthogonal bounding boxes from the view frustrum
860{
861  i4_3d_vector a,b;
862  int i;
863  // transform
864  for (i=0; i<NUM_VIEW_POINTS; i++)
865    transform.inverse_transform(view_point[i], camera_point[i]);
866
867  // Calculate bbox of view
868  bbox.min = camera_point[0];
869  bbox.max = camera_point[0];
870  for (i=1; i<NUM_VIEW_POINTS; i++)
871  {
872    bbox.min.x = fmin(bbox.min.x, camera_point[i].x);
873    bbox.min.y = fmin(bbox.min.y, camera_point[i].y);
874    bbox.min.z = fmin(bbox.min.z, camera_point[i].z);
875    bbox.max.x = fmax(bbox.max.x, camera_point[i].x);
876    bbox.max.y = fmax(bbox.max.y, camera_point[i].y);
877    bbox.max.z = fmax(bbox.max.z, camera_point[i].z);
878  }
879
880  // Calculate plane equations and determine N & P points for planes
881  int j=4;
882  for (i=0; i<4; i++)
883  {
884    a = camera_point[j];
885    a -= camera_point[0];
886     
887    j = i+1;
888    b = camera_point[j];
889    b -= camera_point[0];
890     
891    plane[i].normal.cross(a,b);
892    plane[i].D = -plane[i].normal.dot(camera_point[0]);
893    plane[i].calc_np();
894  }
895}
896
897int g1_object_controller_class::test_clip(const i4_3d_vector& min, const i4_3d_vector& max)
898// test bounding region of lod_node against the view frustrum
899{
900  pf_test_clip.start();
901
902  int i;
903  int ret=-1;
904 
905  if (max.x<bbox.min.x || min.x>bbox.max.x ||
906      max.y<bbox.min.y || min.y>bbox.max.y ||
907      max.z<bbox.min.z || min.z>bbox.max.z)
908    // bounding box check
909    ret = -1;
910  else
911  {
912    ret = 1;
913    i4_3d_vector corner[8];
914   
915    // create indexed array for bounding box corners
916    corner[0].set(min.x,min.y,min.z);
917    corner[1].set(max.x,min.y,min.z);
918    corner[2].set(min.x,max.y,min.z);
919    corner[3].set(max.x,max.y,min.z);
920    corner[4].set(min.x,min.y,max.z);
921    corner[5].set(max.x,min.y,max.z);
922    corner[6].set(min.x,max.y,max.z);
923    corner[7].set(max.x,max.y,max.z);
924   
925    // check the bounding box against the 4 view frustrum planes
926    for (i=0; i<4; i++)
927    {
928      if (plane[i].evaluate(corner[plane[i].p]) < 0)
929      {
930        // completely outside this plane
931        ret = -1;
932        break;
933      }
934
935      if (plane[i].evaluate(corner[plane[i].n]) < 0)
936        // not completely inside this plane
937        ret = 0;
938    }
939  }
940
941  pf_test_clip.stop();
942  return ret;
943}
944
Note: See TracBrowser for help on using the repository browser.