00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028
00029 #include "studio.h"
00030 #include "servemsg.h"
00031 #include "exult_constants.h"
00032 #include "locator.h"
00033 #include "utils.h"
00034
00035 using std::cout;
00036 using std::endl;
00037
00038
00039
00040
00041
00042 C_EXPORT void on_locator1_activate
00043 (
00044 GtkMenuItem *menuitem,
00045 gpointer user_data
00046 )
00047 {
00048 ExultStudio *studio = ExultStudio::get_instance();
00049 studio->open_locator_window();
00050 }
00051 void ExultStudio::open_locator_window
00052 (
00053 )
00054 {
00055 if (!locwin)
00056 {
00057 locwin = new Locator();
00058 }
00059 locwin->show(true);
00060 }
00061
00062
00063
00064
00065 C_EXPORT void on_loc_close_clicked
00066 (
00067 GtkButton *btn,
00068 gpointer user_data
00069 )
00070 {
00071 Locator *loc = (Locator *) gtk_object_get_user_data(
00072 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(btn))));
00073 loc->show(false);
00074 }
00075
00076
00077
00078
00079 C_EXPORT gboolean on_loc_window_delete_event
00080 (
00081 GtkWidget *widget,
00082 GdkEvent *event,
00083 gpointer user_data
00084 )
00085 {
00086 Locator *loc = (Locator *)
00087 gtk_object_get_user_data(GTK_OBJECT(widget));
00088 loc->show(false);
00089 return TRUE;
00090 }
00091
00092
00093
00094
00095 C_EXPORT gint on_loc_draw_configure_event
00096 (
00097 GtkWidget *widget,
00098 GdkEventConfigure *event,
00099 gpointer data
00100 )
00101 {
00102 Locator *loc = (Locator *) gtk_object_get_user_data(
00103 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget))));
00104 loc->configure(widget);
00105 return TRUE;
00106 }
00107
00108
00109
00110 C_EXPORT gint on_loc_draw_expose_event
00111 (
00112 GtkWidget *widget,
00113 GdkEventExpose *event,
00114 gpointer data
00115 )
00116 {
00117 Locator *loc = (Locator *) gtk_object_get_user_data(
00118 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget))));
00119 loc->render(&event->area);
00120 return TRUE;
00121 }
00122
00123
00124
00125 C_EXPORT gint on_loc_draw_button_press_event
00126 (
00127 GtkWidget *widget,
00128 GdkEventButton *event,
00129 gpointer data
00130 )
00131 {
00132 Locator *loc = (Locator *) gtk_object_get_user_data(
00133 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget))));
00134 return loc->mouse_press(event);
00135 }
00136
00137 C_EXPORT gint on_loc_draw_button_release_event
00138 (
00139 GtkWidget *widget,
00140 GdkEventButton *event,
00141 gpointer data
00142 )
00143 {
00144 Locator *loc = (Locator *) gtk_object_get_user_data(
00145 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget))));
00146 return loc->mouse_release(event);
00147 }
00148
00149 C_EXPORT gint on_loc_draw_motion_notify_event
00150 (
00151 GtkWidget *widget,
00152 GdkEventMotion *event,
00153 gpointer data
00154 )
00155 {
00156 Locator *loc = (Locator *) gtk_object_get_user_data(
00157 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget))));
00158 return loc->mouse_motion(event);
00159 }
00160
00161
00162
00163
00164
00165 Locator::Locator
00166 (
00167 ) : drawgc(0), tx(0), ty(0), txs(40), tys(25), scale(1),
00168 dragging(false), send_location_timer(-1)
00169 {
00170 GladeXML *app_xml = ExultStudio::get_instance()->get_xml();
00171 win = glade_xml_get_widget(app_xml, "loc_window");
00172 gtk_object_set_user_data(GTK_OBJECT(win), this);
00173 draw = glade_xml_get_widget(app_xml, "loc_draw");
00174
00175 gtk_widget_set_events(draw, GDK_EXPOSURE_MASK |
00176 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
00177 GDK_BUTTON1_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
00178
00179 GtkWidget *scale = glade_xml_get_widget(app_xml, "loc_hscale");
00180 hadj = gtk_range_get_adjustment(GTK_RANGE(scale));
00181 scale = glade_xml_get_widget(app_xml, "loc_vscale");
00182 vadj = gtk_range_get_adjustment(GTK_RANGE(scale));
00183 hadj->upper = vadj->upper = c_num_chunks;
00184 hadj->page_increment = vadj->page_increment = c_chunks_per_schunk;
00185 hadj->page_size = vadj->page_size = 2;
00186 gtk_signal_emit_by_name(GTK_OBJECT(hadj), "changed");
00187 gtk_signal_emit_by_name(GTK_OBJECT(vadj), "changed");
00188
00189 gtk_signal_connect(GTK_OBJECT(hadj), "value_changed",
00190 GTK_SIGNAL_FUNC(hscrolled), this);
00191 gtk_signal_connect(GTK_OBJECT(vadj), "value_changed",
00192 GTK_SIGNAL_FUNC(vscrolled), this);
00193 }
00194
00195
00196
00197
00198
00199 Locator::~Locator
00200 (
00201 )
00202 {
00203 if (send_location_timer != -1)
00204 gtk_timeout_remove(send_location_timer);
00205 gtk_widget_destroy(win);
00206 }
00207
00208
00209
00210
00211
00212 void Locator::show
00213 (
00214 bool tf
00215 )
00216 {
00217 if (tf)
00218 {
00219 gtk_widget_show(win);
00220 query_location();
00221 }
00222 else
00223 gtk_widget_hide(win);
00224 }
00225
00226
00227
00228
00229
00230 void Locator::configure
00231 (
00232 GtkWidget *widget
00233 )
00234 {
00235 if (!widget->window)
00236 return;
00237 if (!drawgc)
00238 {
00239 drawgc = gdk_gc_new(widget->window);
00240 }
00241 }
00242
00243
00244
00245
00246
00247 void Locator::render
00248 (
00249 GdkRectangle *area
00250 )
00251 {
00252
00253 int draww = draw->allocation.width,
00254 drawh = draw->allocation.height;
00255 GdkRectangle all;
00256 if (!area)
00257 {
00258 all.x = all.y = 0;
00259 all.width = draww;
00260 all.height = drawh;
00261 area = &all;
00262 }
00263 gdk_gc_set_clip_rectangle(drawgc, area);
00264
00265 gdk_rgb_gc_set_foreground(drawgc, 64);
00266 gdk_draw_rectangle(draw->window, drawgc, TRUE, area->x, area->y,
00267 area->width, area->height);
00268
00269 #if 0
00270 gdk_gc_set_line_attributes(drawgc, 1, GDK_LINE_ON_OFF_DASH,
00271 GDK_CAP_BUTT, GDK_JOIN_BEVEL);
00272 #endif
00273
00274 gdk_rgb_gc_set_foreground(drawgc, 0xc0c0c0);
00275 int i;
00276 int cur = 0;
00277
00278 for (i = 0; i < c_num_schunks - 1; i++)
00279 {
00280 int rowht = (drawh - cur)/(c_num_schunks - i);
00281 cur += rowht;
00282 gdk_draw_line(draw->window, drawgc, 0, cur, draww, cur);
00283 if (i == c_num_schunks/2 - 1)
00284 {
00285 gdk_draw_line(draw->window, drawgc, 0, cur - 1,
00286 draww, cur - 1);
00287 gdk_draw_line(draw->window, drawgc, 0, cur + 1,
00288 draww, cur + 1);
00289 }
00290 }
00291 cur = 0;
00292 for (i = 0; i < c_num_schunks - 1; i++)
00293 {
00294 int colwd = (draww - cur)/(c_num_schunks - i);
00295 cur += colwd;
00296 gdk_draw_line(draw->window, drawgc, cur, 0, cur, drawh);
00297 if (i == c_num_schunks/2 - 1)
00298 {
00299 gdk_draw_line(draw->window, drawgc, cur - 1, 0,
00300 cur - 1, drawh);
00301 gdk_draw_line(draw->window, drawgc, cur + 1, 0,
00302 cur + 1, drawh);
00303 }
00304 }
00305 #if 0
00306
00307 gdk_gc_set_line_attributes(drawgc, 1, GDK_LINE_SOLID,
00308 GDK_CAP_BUTT, GDK_JOIN_BEVEL);
00309 #endif
00310
00311 int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk;
00312 int x = (cx*draww)/c_num_chunks,
00313 y = (cy*drawh)/c_num_chunks;
00314 int w = (txs*draww)/c_num_tiles,
00315 h = (tys*drawh)/c_num_tiles;
00316 if (w == 0)
00317 w = 1;
00318 if (h == 0)
00319 h = 1;
00320
00321 gdk_rgb_gc_set_foreground(drawgc, (255<<16) + (255<<8));
00322 gdk_draw_rectangle(draw->window, drawgc, FALSE, x, y, w, h);
00323 viewbox.x = x; viewbox.y = y;
00324 viewbox.width = w; viewbox.height = h;
00325
00326 gdk_rgb_gc_set_foreground(drawgc, (255<<16) + (128<<8) + 128);
00327 gdk_draw_rectangle(draw->window, drawgc, FALSE,
00328 x - 3, y - 3, w + 6, h + 6);
00329 }
00330
00331
00332
00333
00334
00335 void Locator::view_changed
00336 (
00337 unsigned char *data,
00338 int datalen
00339 )
00340 {
00341 if (datalen < 4*4)
00342 return;
00343 if (dragging)
00344 return;
00345 tx = Read4(data);
00346 ty = Read4(data);
00347 txs = Read4(data);
00348 tys = Read4(data);
00349
00350
00351 int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk;
00352 tx = cx*c_tiles_per_chunk;
00353 ty = cy*c_tiles_per_chunk;
00354
00355 gtk_adjustment_set_value(hadj, cx);
00356 gtk_adjustment_set_value(vadj, cy);
00357 render();
00358 }
00359
00360
00361
00362
00363
00364 void Locator::vscrolled
00365 (
00366 GtkAdjustment *adj,
00367 gpointer data
00368 )
00369 {
00370 Locator *loc = (Locator *) data;
00371 int oldty = loc->ty;
00372 loc->ty = ((gint) adj->value)*c_tiles_per_chunk;
00373 if (loc->ty != oldty)
00374
00375 {
00376 loc->render();
00377 loc->send_location();
00378 }
00379 }
00380 void Locator::hscrolled
00381 (
00382 GtkAdjustment *adj,
00383 gpointer data
00384 )
00385 {
00386 Locator *loc = (Locator *) data;
00387 int oldtx = loc->tx;
00388 loc->tx = ((gint) adj->value)*c_tiles_per_chunk;
00389 if (loc->tx != oldtx)
00390
00391 {
00392 loc->render();
00393 loc->send_location();
00394 }
00395 }
00396
00397
00398
00399
00400
00401 void Locator::send_location
00402 (
00403 )
00404 {
00405 unsigned char data[50];
00406 unsigned char *ptr = &data[0];
00407 Write4(ptr, tx);
00408 Write4(ptr, ty);
00409 Write4(ptr, txs);
00410 Write4(ptr, tys);
00411 Write4(ptr, static_cast<uint32>(-1));
00412 cout << "Locator::send_location" << endl;
00413 ExultStudio::get_instance()->send_to_server(Exult_server::view_pos,
00414 &data[0], ptr - data);
00415 }
00416
00417
00418
00419
00420
00421 void Locator::query_location
00422 (
00423 )
00424 {
00425 unsigned char data[50];
00426 unsigned char *ptr = &data[0];
00427 Write4(ptr, static_cast<uint32>(-1));
00428 Write4(ptr, static_cast<uint32>(-1));
00429 Write4(ptr, static_cast<uint32>(-1));
00430 Write4(ptr, static_cast<uint32>(-1));
00431 Write4(ptr, static_cast<uint32>(-1));
00432 ExultStudio::get_instance()->send_to_server(Exult_server::view_pos,
00433 &data[0], ptr - data);
00434 }
00435
00436
00437
00438
00439
00440
00441 gint Locator::delayed_send_location
00442 (
00443 gpointer data
00444 )
00445 {
00446 Locator *loc = (Locator *) data;
00447 loc->send_location();
00448 loc->send_location_timer = -1;
00449 return 0;
00450 }
00451
00452
00453
00454
00455
00456 void Locator::goto_mouse
00457 (
00458 int mx, int my,
00459 bool delay_send
00460 )
00461 {
00462 GdkRectangle oldbox = viewbox;
00463 int oldtx = tx, oldty = ty;
00464
00465
00466 tx = (mx*c_num_tiles)/draw->allocation.width;
00467 ty = (my*c_num_tiles)/draw->allocation.height;
00468 int cx = tx/c_tiles_per_chunk, cy = ty/c_tiles_per_chunk;
00469 if (cx > c_num_chunks - 2)
00470 cx = c_num_chunks - 2;
00471 if (cy > c_num_chunks - 2)
00472 cy = c_num_chunks - 2;
00473 tx = cx*c_tiles_per_chunk;
00474 ty = cy*c_tiles_per_chunk;
00475
00476 gtk_adjustment_set_value(hadj, cx);
00477 gtk_adjustment_set_value(vadj, cy);
00478
00479 if (tx != oldtx || ty != oldty)
00480 {
00481 if (send_location_timer != -1)
00482 gtk_timeout_remove(send_location_timer);
00483 if (delay_send)
00484 send_location_timer = gtk_timeout_add(333,
00485 delayed_send_location, this);
00486 else
00487 {
00488 send_location();
00489 send_location_timer = -1;
00490 }
00491 GdkRectangle newbox;
00492 GdkRectangle dirty;
00493 newbox.x = (cx*draw->allocation.width)/c_num_chunks,
00494 newbox.y = (cy*draw->allocation.height)/c_num_chunks;
00495 newbox.width = oldbox.width;
00496 newbox.height = oldbox.height;
00497 gdk_rectangle_union(&oldbox, &newbox, &dirty);
00498
00499 dirty.x -= 4; dirty.y -= 4;
00500 dirty.width += 8; dirty.height += 8;
00501 render(&dirty);
00502 }
00503 }
00504
00505
00506
00507
00508
00509 gint Locator::mouse_press
00510 (
00511 GdkEventButton *event
00512 )
00513 {
00514 dragging = false;
00515 if (event->button != 1)
00516 return FALSE;
00517
00518 int mx = (int) event->x, my = (int) event->y;
00519 int draww = draw->allocation.width,
00520 drawh = draw->allocation.height;
00521
00522 if (((GdkEvent *) event)->type == GDK_2BUTTON_PRESS)
00523 {
00524 goto_mouse(mx, my);
00525 return TRUE;
00526 }
00527
00528 if (mx < viewbox.x - 3 || my < viewbox.y - 3 ||
00529 mx > viewbox.x + viewbox.width + 6 ||
00530 my > viewbox.y + viewbox.height + 6)
00531 return FALSE;
00532 dragging = true;
00533 drag_relx = mx - viewbox.x;
00534 drag_rely = my - viewbox.y;
00535 return (TRUE);
00536 }
00537
00538
00539
00540
00541
00542 gint Locator::mouse_release
00543 (
00544 GdkEventButton *event
00545 )
00546 {
00547 dragging = false;
00548 return TRUE;
00549 }
00550
00551
00552
00553
00554
00555 gint Locator::mouse_motion
00556 (
00557 GdkEventMotion *event
00558 )
00559 {
00560 int mx, my;
00561 GdkModifierType state;
00562 if (event->is_hint)
00563 gdk_window_get_pointer(event->window, &mx, &my, &state);
00564 else
00565 {
00566 mx = (int) event->x;
00567 my = (int) event->y;
00568 state = (GdkModifierType) event->state;
00569 }
00570 if (!dragging || !(state & GDK_BUTTON1_MASK))
00571 return FALSE;
00572
00573 goto_mouse(mx + drag_relx, my + drag_rely, true);
00574 return TRUE;
00575 }