static void rotate_items (Sheet *sheet, GList *items, gint angle) { GList *list, *item_data_list; Coords center, b1, b2; item_data_list = NULL; for (list = items; list; list = list->next) { item_data_list = g_list_prepend (item_data_list, sheet_item_get_data (list->data)); } item_data_list_get_absolute_bbox (item_data_list, &b1, &b2); center = coords_average(&b1, &b2); snap_to_grid (sheet->grid, ¢er.x, ¢er.y); for (list = item_data_list; list; list = list->next) { ItemData *item_data = list->data; if (item_data==NULL) continue; if (sheet->state == SHEET_STATE_NONE) item_data_unregister (item_data); item_data_rotate (item_data, angle, ¢er); if (sheet->state == SHEET_STATE_NONE) item_data_register (item_data); } g_list_free (item_data_list); }
static void rotate_items (Sheet *sheet, GList *items) { GList *list, *item_data_list; Coords center, b1, b2; item_data_list = NULL; for (list = items; list; list = list->next) { item_data_list = g_list_prepend (item_data_list, sheet_item_get_data (list->data)); } item_data_list_get_absolute_bbox (item_data_list, &b1, &b2); center.x = (b2.x + b1.x) / 2.; center.y = (b2.y + b1.y) / 2.; snap_to_grid (sheet->grid, ¢er.x, ¢er.y); for (list = item_data_list; list; list = list->next) { ItemData *item_data = list->data; if (sheet->state == SHEET_STATE_NONE) item_data_unregister (item_data); item_data_rotate (item_data, 90, ¢er); if (sheet->state == SHEET_STATE_NONE) item_data_register (item_data); } g_list_free (item_data_list); }
/** * \brief snaps to the grid, updates the model if snapping was necessary * * \attention this will cause a loop cycle of "changed" signals * until no more snapping is necessary * * @param item_data * @param grid */ void item_data_snap (ItemData *item_data, Grid *grid) { gboolean handler_connected; g_return_if_fail (item_data); g_return_if_fail (IS_ITEM_DATA (item_data)); g_return_if_fail (grid); g_return_if_fail (IS_GRID (grid)); if (snap_to_grid (grid, &(item_data->priv->translate.x0), &(item_data->priv->translate.y0))) { #if 1 // TODO FIXME XXX rename this to "snapped" instead of moved handler_connected = g_signal_handler_is_connected (G_OBJECT (item_data), item_data->moved_handler_id); if (handler_connected) { g_signal_emit_by_name (G_OBJECT (item_data), "moved"); // FIXME replace this by a "snapped" signal } #endif handler_connected = g_signal_handler_is_connected (G_OBJECT (item_data), item_data->changed_handler_id); if (handler_connected) { g_signal_emit_by_name (G_OBJECT (item_data), "changed"); } } }
gboolean sheet_get_pointer_snapped (Sheet *sheet, gdouble *x, gdouble *y) { if (!sheet_get_pointer_pixel (sheet, x, y)) return FALSE; goo_canvas_convert_from_pixels (GOO_CANVAS (sheet), x, y); snap_to_grid (sheet->grid, x, y); return TRUE; }
void sheet_get_pointer (Sheet *sheet, gdouble *x, gdouble *y) { GtkWidget *widget; GtkAdjustment *hadjustment; GtkAdjustment *vadjustment; gdouble value, x1, y1; gint _x, _y; GdkDeviceManager *device_manager; GdkDevice *device_pointer; GdkRectangle allocation; // gtk_widget_get_pointer (GTK_WIDGET (sheet), &_x, &_y); // replaced by a code copied from evince if (!gtk_widget_get_realized (GTK_WIDGET (sheet))) return; device_manager = gdk_display_get_device_manager ( gtk_widget_get_display (GTK_WIDGET (sheet))); device_pointer = gdk_device_manager_get_client_pointer (device_manager); gdk_window_get_device_position (gtk_widget_get_window (GTK_WIDGET (sheet)), device_pointer, &_x, &_y, NULL); if (!gtk_widget_get_has_window (GTK_WIDGET (sheet))) return; gtk_widget_get_allocation (GTK_WIDGET (sheet), &allocation); _x -= allocation.x; _y -= allocation.y; x1 = (gdouble) _x; y1 = (gdouble) _y; widget = gtk_widget_get_parent (GTK_WIDGET (sheet)); hadjustment = gtk_scrolled_window_get_hadjustment ( GTK_SCROLLED_WINDOW (widget)); value = gtk_adjustment_get_value (hadjustment); x1 += value; vadjustment = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW (widget)); value = gtk_adjustment_get_value (vadjustment); y1 += value; *x = x1; *y = y1; goo_canvas_convert_from_pixels (GOO_CANVAS (sheet), x, y); snap_to_grid (sheet->grid, x, y); }
static void flip_items (Sheet *sheet, GList *items, IDFlip direction) { GList *iter, *item_data_list; Coords center, b1, b2; Coords after; item_data_list = NULL; for (iter = items; iter; iter = iter->next) { item_data_list = g_list_prepend (item_data_list, sheet_item_get_data (iter->data)); } item_data_list_get_absolute_bbox (item_data_list, &b1, &b2); // FIXME center is currently not used by item_data_flip (part.c implentation) center.x = (b2.x + b1.x) / 2; center.y = (b2.y + b1.y) / 2; // FIXME - registering an item after flipping it still creates an offset as the position is still 0 for (iter = item_data_list; iter; iter = iter->next) { ItemData *item_data = iter->data; if (sheet->state == SHEET_STATE_NONE) item_data_unregister (item_data); item_data_flip (item_data, direction, ¢er); // Make sure we snap to grid. item_data_get_pos (item_data, &after); snap_to_grid (sheet->grid, &after.x, &after.y); item_data_set_pos (item_data, &after); if (sheet->state == SHEET_STATE_NONE) item_data_register (item_data); } g_list_free (item_data_list); }
static void flip_items (Sheet *sheet, GList *items, gboolean horizontal) { GList *list, *item_data_list; SheetPos center, b1, b2; SheetPos after; item_data_list = NULL; for (list = items; list; list = list->next) { item_data_list = g_list_prepend (item_data_list, sheet_item_get_data (list->data)); } item_data_list_get_absolute_bbox (item_data_list, &b1, &b2); center.x = (b2.x + b1.x) / 2; center.y = (b2.y + b1.y) / 2; for (list = item_data_list; list; list = list->next) { ItemData *item_data = list->data; if (sheet->state == SHEET_STATE_NONE) item_data_unregister (item_data); item_data_flip (item_data, horizontal, ¢er); // Make sure we snap to grid. item_data_get_pos (item_data, &after); snap_to_grid (sheet->grid, &after.x, &after.y); item_data_move (item_data, &after); if (sheet->state == SHEET_STATE_NONE) item_data_register (item_data); } g_list_free (item_data_list); g_list_free_full (list, g_object_unref); }
void part_browser_dnd (GtkSelectionData *selection_data, int x, int y) { LibraryPart *library_part; Coords pos; DndData *data; Sheet *sheet; Part *part; data = (DndData *) (gtk_selection_data_get_data (selection_data)); g_return_if_fail (data != NULL); pos.x = x; pos.y = y; sheet = schematic_view_get_sheet (data->schematic_view); snap_to_grid (sheet->grid, &pos.x, &pos.y); library_part = library_get_part (data->br->library, data->part_name); part = part_new_from_library_part (library_part); if (!part) { oregano_error (_("Unable to load required part")); return; } item_data_set_pos (ITEM_DATA (part), &pos); sheet_connect_part_item_to_floating_group (sheet, (gpointer) data->schematic_view); sheet_select_all (sheet, FALSE); sheet_clear_ghosts (schematic_view_get_sheet (data->schematic_view)); sheet_add_ghost_item (sheet, ITEM_DATA (part)); }
void bordwalk(const struct Cell_head *from_hd, struct Cell_head *to_hd, const struct pj_info *from_pj, const struct pj_info *to_pj) { struct Cell_head cur_hd; /* Set some (un)reasonable defaults before we walk the borders */ invert(&cur_hd, to_hd, 1.0e-6); /* Start walking */ bordwalk1(from_pj, to_pj, from_hd, &cur_hd); intersect(&cur_hd, to_hd); /* check some special cases by reversing the projection */ reverse_check(from_pj, to_pj, from_hd, to_hd, &cur_hd); debug("Extra check", &cur_hd); /* if we still have some unresonable default minmax left, then abort */ if (outside(&cur_hd, to_hd)) G_fatal_error(_("Input raster map is outside current region")); intersect(&cur_hd, to_hd); /* adjust to edges */ snap_to_grid(&cur_hd, to_hd); intersect(to_hd, &cur_hd); debug("Final check", to_hd); }
static void modify_motion (ModifyTool *tool, GdkEventMotion *event, DDisplay *ddisp) { Point to; Point now, delta, full_delta; gboolean auto_scroll, vertical = FALSE; ConnectionPoint *connectionpoint = NULL; ObjectChange *objchange = NULL; ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y); if (tool->state==STATE_NONE) { DiaObject *obj = NULL; Handle *handle = NULL; diagram_find_closest_handle (ddisp->diagram, &handle, &obj, &to); if (handle && handle->type != HANDLE_NON_MOVABLE && handle->id >= HANDLE_RESIZE_NW && handle->id <= HANDLE_RESIZE_SE && handle_is_clicked(ddisp, handle, &to) && g_list_length (ddisp->diagram->data->selected) == 1) ddisplay_set_all_cursor (get_direction_cursor (CURSOR_DIRECTION_0 + handle->id)); else ddisplay_set_all_cursor_name (NULL, "default"); return; /* Fast path... */ } auto_scroll = ddisplay_autoscroll(ddisp, event->x, event->y); if (!modify_move_already(tool, ddisp, &to)) return; switch (tool->state) { case STATE_MOVE_OBJECT: if (tool->orig_pos == NULL) { GList *list, *pla; int i; DiaObject *obj; /* consider non-selected children affected */ pla = list = parent_list_affected(ddisp->diagram->data->selected); tool->orig_pos = g_new(Point, g_list_length(list)); i=0; while (list != NULL) { obj = (DiaObject *) list->data; tool->orig_pos[i] = obj->position; list = g_list_next(list); i++; } g_list_free (pla); } if (tool->break_connections) diagram_unconnect_selected(ddisp->diagram); /* Pushes UNDO info */ if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) { full_delta = to; point_sub(&full_delta, &tool->start_at); vertical = (fabs(full_delta.x) < fabs(full_delta.y)); } point_add(&to, &tool->move_compensate); snap_to_grid(ddisp, &to.x, &to.y); now = tool->object->position; delta = to; point_sub(&delta, &now); if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) { /* Up-down or left-right */ if (vertical) { delta.x = tool->start_at.x + tool->move_compensate.x - now.x; } else { delta.y = tool->start_at.y + tool->move_compensate.y - now.y; } } object_add_updates_list(ddisp->diagram->data->selected, ddisp->diagram); objchange = object_list_move_delta(ddisp->diagram->data->selected, &delta); if (objchange != NULL) { undo_object_change(ddisp->diagram, tool->object, objchange); } object_add_updates_list(ddisp->diagram->data->selected, ddisp->diagram); object_add_updates(tool->object, ddisp->diagram); /* Put current mouse position in status bar */ { gchar *postext; GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status); guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos"); gtk_statusbar_pop (statusbar, context_id); postext = g_strdup_printf("%.3f, %.3f - %.3f, %.3f", tool->object->bounding_box.left, tool->object->bounding_box.top, tool->object->bounding_box.right, tool->object->bounding_box.bottom); gtk_statusbar_pop (statusbar, context_id); gtk_statusbar_push (statusbar, context_id, postext); g_free(postext); } diagram_update_connections_selection(ddisp->diagram); diagram_flush(ddisp->diagram); break; case STATE_MOVE_HANDLE: full_delta = to; point_sub(&full_delta, &tool->start_at); /* make sure resizing is restricted to its parent */ /* if resize was blocked by parent, that means the resizing was outward, thus it won't bother the children so we don't have to check the children */ if (!parent_handle_move_out_check(tool->object, &to)) parent_handle_move_in_check(tool->object, &to, &tool->start_at); if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) vertical = (fabs(full_delta.x) < fabs(full_delta.y)); highlight_reset_all(ddisp->diagram); if ((tool->handle->connect_type != HANDLE_NONCONNECTABLE)) { /* Move to ConnectionPoint if near: */ connectionpoint = object_find_connectpoint_display (ddisp, &to, tool->object, TRUE); if (connectionpoint != NULL) { DiaHighlightType type; to = connectionpoint->pos; if (connectionpoint->flags & CP_FLAGS_MAIN) { type = DIA_HIGHLIGHT_CONNECTIONPOINT_MAIN; } else { type = DIA_HIGHLIGHT_CONNECTIONPOINT; } highlight_object(connectionpoint->object, type, ddisp->diagram); ddisplay_set_all_cursor_name (NULL, "crosshair"); } } if (connectionpoint == NULL) { /* No connectionopoint near, then snap to grid (if enabled) */ snap_to_grid(ddisp, &to.x, &to.y); ddisplay_set_all_cursor_name (NULL, "move"); } if (tool->break_connections) { /* break connections to the handle currently selected. */ if (tool->handle->connected_to!=NULL) { Change *change = undo_unconnect (ddisp->diagram, tool->object, tool->handle); (change->apply)(change, ddisp->diagram); } } if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) { /* Up-down or left-right */ if (vertical) { to.x = tool->start_at.x; } else { to.y = tool->start_at.y; } } if (tool->orig_pos == NULL) { tool->orig_pos = g_new(Point, 1); *tool->orig_pos = tool->handle->pos; } /* Put current mouse position in status bar */ { gchar *postext; GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status); guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos"); if (tool->object) { /* play safe */ real w = tool->object->bounding_box.right - tool->object->bounding_box.left; real h = tool->object->bounding_box.bottom - tool->object->bounding_box.top; postext = g_strdup_printf("%.3f, %.3f (%.3fx%.3f)", to.x, to.y, w, h); } else { postext = g_strdup_printf("%.3f, %.3f", to.x, to.y); } gtk_statusbar_pop (statusbar, context_id); gtk_statusbar_push (statusbar, context_id, postext); g_free(postext); } object_add_updates(tool->object, ddisp->diagram); /* Handle undo */ if (tool->object) objchange = tool->object->ops->move_handle(tool->object, tool->handle, &to, connectionpoint, HANDLE_MOVE_USER, gdk_event_to_dia_ModifierKeys(event->state)); if (objchange != NULL) { undo_object_change(ddisp->diagram, tool->object, objchange); } object_add_updates(tool->object, ddisp->diagram); diagram_update_connections_selection(ddisp->diagram); diagram_flush(ddisp->diagram); break; case STATE_BOX_SELECT: tool->end_box = to; ddisplay_transform_coords (ddisp, MIN (tool->start_box.x, tool->end_box.x), MIN (tool->start_box.y, tool->end_box.y), &tool->x1, &tool->y1); ddisplay_transform_coords (ddisp, MAX (tool->start_box.x, tool->end_box.x), MAX (tool->start_box.y, tool->end_box.y), &tool->x2, &tool->y2); dia_interactive_renderer_set_selection (ddisp->renderer, TRUE, tool->x1, tool->y1, tool->x2 - tool->x1, tool->y2 - tool->y1); ddisplay_flush (ddisp); break; case STATE_NONE: break; default: message_error("Internal error: Strange state in modify_tool\n"); } tool->last_to = to; tool->auto_scrolled = auto_scroll; }
gboolean wire_item_event (WireItem *wire_item, GooCanvasItem *sheet_target_item, GdkEvent *event, Sheet *sheet) { SheetPos start_pos, length; Wire *wire; GooCanvas *canvas; static double last_x, last_y; double dx, dy, zoom; // The selected group's bounding box in window resp. canvas coordinates. double snapped_x, snapped_y; SheetPos pos; canvas = GOO_CANVAS (sheet); g_object_get (G_OBJECT (wire_item), "data", &wire, NULL); wire_get_pos_and_length (WIRE (wire), &start_pos, &length); sheet_get_zoom (sheet, &zoom); switch (event->type) { case GDK_BUTTON_PRESS: switch (event->button.button) { case 1: { double x, y; g_signal_stop_emission_by_name (wire_item, "button_press_event"); sheet_get_pointer (sheet, &x, &y); x = x - start_pos.x; y = y - start_pos.y; if ((x > -RESIZER_SIZE) && (x < RESIZER_SIZE) && (y > -RESIZER_SIZE) && (y < RESIZER_SIZE)) { gtk_widget_grab_focus (GTK_WIDGET (sheet)); sheet->state = SHEET_STATE_DRAG_START; wire_item->priv->resize_state = WIRE_RESIZER_1; sheet_get_pointer (sheet, &x, &y); last_x = x; last_y = y; item_data_unregister (ITEM_DATA (wire)); return TRUE; } if ((x > (length.x-RESIZER_SIZE)) && (x < (length.x+RESIZER_SIZE)) && (y > (length.y-RESIZER_SIZE)) && (y < (length.y+RESIZER_SIZE))) { gtk_widget_grab_focus (GTK_WIDGET (sheet)); sheet->state = SHEET_STATE_DRAG_START; wire_item->priv->resize_state = WIRE_RESIZER_2; sheet_get_pointer (sheet, &x, &y); last_x = x; last_y = y; item_data_unregister (ITEM_DATA (wire)); return TRUE; } } break; } break; case GDK_MOTION_NOTIFY: if (sheet->state != SHEET_STATE_DRAG && sheet->state != SHEET_STATE_DRAG_START) break; if (wire_item->priv->resize_state == WIRE_RESIZER_NONE) break; if (sheet->state == SHEET_STATE_DRAG_START || sheet->state == SHEET_STATE_DRAG) { g_signal_stop_emission_by_name (wire_item, "motion-notify-event"); sheet->state = SHEET_STATE_DRAG; sheet_get_pointer (sheet, &snapped_x, &snapped_y); dx = snapped_x - last_x; dy = snapped_y - last_y; last_x = snapped_x; last_y = snapped_y; wire_get_pos_and_length (wire, &pos, &length); if (wire_item->priv->resize_state == WIRE_RESIZER_1) { switch (wire->priv->direction) { case WIRE_DIR_VERT: /* Vertical Wire */ pos.y = last_y; length.y -= dy; break; case WIRE_DIR_HORIZ: /* Horizontal Wire */ pos.x = last_x; length.x -= dx; break; default: pos.y = last_y; length.y -= dy; pos.x = last_x; length.x -= dx; } } else { switch (wire->priv->direction) { case WIRE_DIR_VERT: /* Vertical Wire */ length.y += dy; break; case WIRE_DIR_HORIZ: /* Horizontal Wire */ length.x += dx; break; default: length.y += dy; length.x += dx; } } snap_to_grid (sheet->grid, &length.x, &length.y); item_data_set_pos (sheet_item_get_data (SHEET_ITEM (wire_item)), &pos); wire_set_length (wire, &length); return TRUE; } break; case GDK_BUTTON_RELEASE: switch (event->button.button) { case 1: if (sheet->state != SHEET_STATE_DRAG && sheet->state != SHEET_STATE_DRAG_START) { break; } if (wire_item->priv->resize_state == WIRE_RESIZER_NONE) { break; } g_signal_stop_emission_by_name (wire_item, "button-release-event"); goo_canvas_pointer_ungrab (canvas, GOO_CANVAS_ITEM (wire_item), event->button.time); wire_item->priv->resize_state = WIRE_RESIZER_NONE; sheet->state = SHEET_STATE_NONE; item_data_register (ITEM_DATA (wire)); return TRUE; } break; default: return sheet_item_event (GOO_CANVAS_ITEM (wire_item), GOO_CANVAS_ITEM (wire_item), event, sheet); } return sheet_item_event (GOO_CANVAS_ITEM (wire_item), GOO_CANVAS_ITEM (wire_item), event, sheet); }
int common_dm(int argc, const char *argv[]) { int status; struct bu_vls vls = BU_VLS_INIT_ZERO; if (dbip == DBI_NULL) return TCL_OK; if (BU_STR_EQUAL(argv[0], "idle")) { /* redraw after scaling */ if (gedp && gedp->ged_gvp && gedp->ged_gvp->gv_adaptive_plot && gedp->ged_gvp->gv_redraw_on_zoom && (am_mode == AMM_SCALE || am_mode == AMM_CON_SCALE_X || am_mode == AMM_CON_SCALE_Y || am_mode == AMM_CON_SCALE_Z)) { if (redraw_visible_objects() == TCL_ERROR) { return TCL_ERROR; } } am_mode = AMM_IDLE; scroll_active = 0; if (rubber_band->rb_active) { rubber_band->rb_active = 0; if (mged_variables->mv_mouse_behavior == 'p') rb_set_dirty_flag(); else if (mged_variables->mv_mouse_behavior == 'r') rt_rect_area(); else if (mged_variables->mv_mouse_behavior == 'z') zoom_rect_area(); } return TCL_OK; } if (BU_STR_EQUAL(argv[0], "m")) { int x; int y; int old_orig_gui; int stolen = 0; fastf_t fx, fy; if (argc < 3) { Tcl_AppendResult(INTERP, "dm m: need more parameters\n", "dm m xpos ypos\n", (char *)NULL); return TCL_ERROR; } old_orig_gui = mged_variables->mv_orig_gui; fx = dm_Xx2Normal(dmp, atoi(argv[1])); fy = dm_Xy2Normal(dmp, atoi(argv[2]), 0); x = fx * GED_MAX; y = fy * GED_MAX; if (mged_variables->mv_faceplate && mged_variables->mv_orig_gui) { #define MENUXLIM (-1250) if (x >= MENUXLIM && scroll_select(x, y, 0)) { stolen = 1; goto end; } if (x < MENUXLIM && mmenu_select(y, 0)) { stolen = 1; goto end; } } mged_variables->mv_orig_gui = 0; fy = dm_Xy2Normal(dmp, atoi(argv[2]), 1); y = fy * GED_MAX; end: if (mged_variables->mv_mouse_behavior == 'q' && !stolen) { point_t view_pt; point_t model_pt; if (grid_state->gr_snap) snap_to_grid(&fx, &fy); if (mged_variables->mv_perspective_mode) VSET(view_pt, fx, fy, 0.0); else VSET(view_pt, fx, fy, 1.0); MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt); VSCALE(model_pt, model_pt, base2local); if (dmp->dm_zclip) bu_vls_printf(&vls, "qray_nirt %lf %lf %lf", model_pt[X], model_pt[Y], model_pt[Z]); else bu_vls_printf(&vls, "qray_nirt -b %lf %lf %lf", model_pt[X], model_pt[Y], model_pt[Z]); } else if ((mged_variables->mv_mouse_behavior == 'p' || mged_variables->mv_mouse_behavior == 'r' || mged_variables->mv_mouse_behavior == 'z') && !stolen) { if (grid_state->gr_snap) snap_to_grid(&fx, &fy); rubber_band->rb_active = 1; rubber_band->rb_x = fx; rubber_band->rb_y = fy; rubber_band->rb_width = 0.0; rubber_band->rb_height = 0.0; rect_view2image(); rb_set_dirty_flag(); } else if (mged_variables->mv_mouse_behavior == 's' && !stolen) { #if 0 if (grid_state->gr_snap) { snap_to_grid(&fx, &fy); x = fx * GED_MAX; y = fy * GED_MAX; } #endif bu_vls_printf(&vls, "mouse_solid_edit_select %d %d", x, y); } else if (mged_variables->mv_mouse_behavior == 'm' && !stolen) { #if 0 if (grid_state->gr_snap) { snap_to_grid(&fx, &fy); x = fx * GED_MAX; y = fy * GED_MAX; } #endif bu_vls_printf(&vls, "mouse_matrix_edit_select %d %d", x, y); } else if (mged_variables->mv_mouse_behavior == 'c' && !stolen) { #if 0 if (grid_state->gr_snap) { snap_to_grid(&fx, &fy); x = fx * GED_MAX; y = fy * GED_MAX; } #endif bu_vls_printf(&vls, "mouse_comb_edit_select %d %d", x, y); } else if (mged_variables->mv_mouse_behavior == 'o' && !stolen) { #if 0 if (grid_state->gr_snap) { snap_to_grid(&fx, &fy); x = fx * GED_MAX; y = fy * GED_MAX; } #endif bu_vls_printf(&vls, "mouse_rt_obj_select %d %d", x, y); } else if (adc_state->adc_draw && mged_variables->mv_transform == 'a' && !stolen) { point_t model_pt; point_t view_pt; if (grid_state->gr_snap) snap_to_grid(&fx, &fy); VSET(view_pt, fx, fy, 1.0); MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt); VSCALE(model_pt, model_pt, base2local); bu_vls_printf(&vls, "adc xyz %lf %lf %lf\n", model_pt[X], model_pt[Y], model_pt[Z]); } else if (grid_state->gr_snap && !stolen && SEDIT_TRAN && mged_variables->mv_transform == 'e') { point_t view_pt; point_t model_pt; snap_to_grid(&fx, &fy); MAT4X3PNT(view_pt, view_state->vs_gvp->gv_model2view, curr_e_axes_pos); view_pt[X] = fx; view_pt[Y] = fy; MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt); VSCALE(model_pt, model_pt, base2local); bu_vls_printf(&vls, "p %lf %lf %lf", model_pt[X], model_pt[Y], model_pt[Z]); } else if (grid_state->gr_snap && !stolen && OEDIT_TRAN && mged_variables->mv_transform == 'e') { point_t view_pt; point_t model_pt; snap_to_grid(&fx, &fy); MAT4X3PNT(view_pt, view_state->vs_gvp->gv_model2view, curr_e_axes_pos); view_pt[X] = fx; view_pt[Y] = fy; MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt); VSCALE(model_pt, model_pt, base2local); bu_vls_printf(&vls, "translate %lf %lf %lf", model_pt[X], model_pt[Y], model_pt[Z]); } else if (grid_state->gr_snap && !stolen && STATE != ST_S_PICK && STATE != ST_O_PICK && STATE != ST_O_PATH && !SEDIT_PICK && !EDIT_SCALE) { point_t view_pt; point_t model_pt; point_t vcenter; snap_to_grid(&fx, &fy); MAT_DELTAS_GET_NEG(vcenter, view_state->vs_gvp->gv_center); MAT4X3PNT(view_pt, view_state->vs_gvp->gv_model2view, vcenter); view_pt[X] = fx; view_pt[Y] = fy; MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt); VSCALE(model_pt, model_pt, base2local); bu_vls_printf(&vls, "center %lf %lf %lf", model_pt[X], model_pt[Y], model_pt[Z]); } else bu_vls_printf(&vls, "M 1 %d %d\n", x, y); status = Tcl_Eval(INTERP, bu_vls_addr(&vls)); mged_variables->mv_orig_gui = old_orig_gui; bu_vls_free(&vls); return status; } if (BU_STR_EQUAL(argv[0], "am")) { if (argc < 4) { Tcl_AppendResult(INTERP, "dm am: need more parameters\n", "dm am <r|t|s> xpos ypos\n", (char *)NULL); return TCL_ERROR; } dml_omx = atoi(argv[2]); dml_omy = atoi(argv[3]); switch (*argv[1]) { case 'r': am_mode = AMM_ROT; break; case 't': am_mode = AMM_TRAN; if (grid_state->gr_snap) { int save_edflag; if ((STATE == ST_S_EDIT || STATE == ST_O_EDIT) && mged_variables->mv_transform == 'e') { if (STATE == ST_S_EDIT) { save_edflag = es_edflag; if (!SEDIT_TRAN) es_edflag = STRANS; } else { save_edflag = edobj; edobj = BE_O_XY; } snap_keypoint_to_grid(); if (STATE == ST_S_EDIT) es_edflag = save_edflag; else edobj = save_edflag; } else snap_view_center_to_grid(); } break; case 's': if (STATE == ST_S_EDIT && mged_variables->mv_transform == 'e' && ZERO(acc_sc_sol)) acc_sc_sol = 1.0; else if (STATE == ST_O_EDIT && mged_variables->mv_transform == 'e') { edit_absolute_scale = acc_sc_obj - 1.0; if (edit_absolute_scale > 0.0) edit_absolute_scale /= 3.0; } am_mode = AMM_SCALE; break; default: Tcl_AppendResult(INTERP, "dm am: need more parameters\n", "dm am <r|t|s> xpos ypos\n", (char *)NULL); return TCL_ERROR; } return TCL_OK; } if (BU_STR_EQUAL(argv[0], "adc")) { fastf_t fx, fy; fastf_t td; /* tick distance */ if (argc < 4) { Tcl_AppendResult(INTERP, "dm adc: need more parameters\n", "dm adc 1|2|t|d xpos ypos\n", (char *)NULL); return TCL_ERROR; } dml_omx = atoi(argv[2]); dml_omy = atoi(argv[3]); switch (*argv[1]) { case '1': fx = dm_Xx2Normal(dmp, dml_omx) * GED_MAX - adc_state->adc_dv_x; fy = dm_Xy2Normal(dmp, dml_omy, 1) * GED_MAX - adc_state->adc_dv_y; bu_vls_printf(&vls, "adc a1 %lf\n", RAD2DEG*atan2(fy, fx)); Tcl_Eval(INTERP, bu_vls_addr(&vls)); bu_vls_free(&vls); am_mode = AMM_ADC_ANG1; break; case '2': fx = dm_Xx2Normal(dmp, dml_omx) * GED_MAX - adc_state->adc_dv_x; fy = dm_Xy2Normal(dmp, dml_omy, 1) * GED_MAX - adc_state->adc_dv_y; bu_vls_printf(&vls, "adc a2 %lf\n", RAD2DEG*atan2(fy, fx)); Tcl_Eval(INTERP, bu_vls_addr(&vls)); bu_vls_free(&vls); am_mode = AMM_ADC_ANG2; break; case 't': { point_t model_pt; point_t view_pt; VSET(view_pt, dm_Xx2Normal(dmp, dml_omx), dm_Xy2Normal(dmp, dml_omy, 1), 0.0); if (grid_state->gr_snap) snap_to_grid(&view_pt[X], &view_pt[Y]); MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt); VSCALE(model_pt, model_pt, base2local); bu_vls_printf(&vls, "adc xyz %lf %lf %lf\n", model_pt[X], model_pt[Y], model_pt[Z]); Tcl_Eval(INTERP, bu_vls_addr(&vls)); bu_vls_free(&vls); am_mode = AMM_ADC_TRAN; } break; case 'd': fx = (dm_Xx2Normal(dmp, dml_omx) * GED_MAX - adc_state->adc_dv_x) * view_state->vs_gvp->gv_scale * base2local * INV_GED; fy = (dm_Xy2Normal(dmp, dml_omy, 1) * GED_MAX - adc_state->adc_dv_y) * view_state->vs_gvp->gv_scale * base2local * INV_GED; td = sqrt(fx * fx + fy * fy); bu_vls_printf(&vls, "adc dst %lf\n", td); Tcl_Eval(INTERP, bu_vls_addr(&vls)); bu_vls_free(&vls); am_mode = AMM_ADC_DIST; break; default: Tcl_AppendResult(INTERP, "dm adc: unrecognized parameter - ", argv[1], "\ndm adc 1|2|t|d xpos ypos\n", (char *)NULL); return TCL_ERROR; } return TCL_OK; } if (BU_STR_EQUAL(argv[0], "con")) { if (argc < 5) { Tcl_AppendResult(INTERP, "dm con: need more parameters\n", "dm con r|t|s x|y|z xpos ypos\n", "dm con a x|y|1|2|d xpos ypos\n", (char *)NULL); return TCL_ERROR; } dml_omx = atoi(argv[3]); dml_omy = atoi(argv[4]); switch (*argv[1]) { case 'a': switch (*argv[2]) { case 'x': am_mode = AMM_CON_XADC; break; case 'y': am_mode = AMM_CON_YADC; break; case '1': am_mode = AMM_CON_ANG1; break; case '2': am_mode = AMM_CON_ANG2; break; case 'd': am_mode = AMM_CON_DIST; break; default: Tcl_AppendResult(INTERP, "dm con: unrecognized parameter - ", argv[2], "\ndm con a x|y|1|2|d xpos ypos\n", (char *)NULL); } break; case 'r': switch (*argv[2]) { case 'x': am_mode = AMM_CON_ROT_X; break; case 'y': am_mode = AMM_CON_ROT_Y; break; case 'z': am_mode = AMM_CON_ROT_Z; break; default: Tcl_AppendResult(INTERP, "dm con: unrecognized parameter - ", argv[2], "\ndm con r|t|s x|y|z xpos ypos\n", (char *)NULL); return TCL_ERROR; } break; case 't': switch (*argv[2]) { case 'x': am_mode = AMM_CON_TRAN_X; break; case 'y': am_mode = AMM_CON_TRAN_Y; break; case 'z': am_mode = AMM_CON_TRAN_Z; break; default: Tcl_AppendResult(INTERP, "dm con: unrecognized parameter - ", argv[2], "\ndm con r|t|s x|y|z xpos ypos\n", (char *)NULL); return TCL_ERROR; } break; case 's': switch (*argv[2]) { case 'x': if (STATE == ST_S_EDIT && mged_variables->mv_transform == 'e' && ZERO(acc_sc_sol)) acc_sc_sol = 1.0; else if (STATE == ST_O_EDIT && mged_variables->mv_transform == 'e') { edit_absolute_scale = acc_sc[0] - 1.0; if (edit_absolute_scale > 0.0) edit_absolute_scale /= 3.0; } am_mode = AMM_CON_SCALE_X; break; case 'y': if (STATE == ST_S_EDIT && mged_variables->mv_transform == 'e' && ZERO(acc_sc_sol)) acc_sc_sol = 1.0; else if (STATE == ST_O_EDIT && mged_variables->mv_transform == 'e') { edit_absolute_scale = acc_sc[1] - 1.0; if (edit_absolute_scale > 0.0) edit_absolute_scale /= 3.0; } am_mode = AMM_CON_SCALE_Y; break; case 'z': if (STATE == ST_S_EDIT && mged_variables->mv_transform == 'e' && ZERO(acc_sc_sol)) acc_sc_sol = 1.0; else if (STATE == ST_O_EDIT && mged_variables->mv_transform == 'e') { edit_absolute_scale = acc_sc[2] - 1.0; if (edit_absolute_scale > 0.0) edit_absolute_scale /= 3.0; } am_mode = AMM_CON_SCALE_Z; break; default: Tcl_AppendResult(INTERP, "dm con: unrecognized parameter - ", argv[2], "\ndm con r|t|s x|y|z xpos ypos\n", (char *)NULL); return TCL_ERROR; } break; default: Tcl_AppendResult(INTERP, "dm con: unrecognized parameter - ", argv[1], "\ndm con r|t|s x|y|z xpos ypos\n", (char *)NULL); return TCL_ERROR; } return TCL_OK; } if (BU_STR_EQUAL(argv[0], "size")) { int width, height; /* get the window size */ if (argc == 1) { bu_vls_printf(&vls, "%d %d", dmp->dm_width, dmp->dm_height); Tcl_AppendResult(INTERP, bu_vls_addr(&vls), (char *)NULL); bu_vls_free(&vls); return TCL_OK; } /* set the window size */ if (argc == 3) { width = atoi(argv[1]); height = atoi(argv[2]); dmp->dm_width = width; dmp->dm_height = height; #if defined(DM_X) || defined(DM_TK) || defined(DM_OGL) || defined(DM_WGL) # if 0 Tk_ResizeWindow(((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin, width, height); # else #if defined(HAVE_TK) Tk_GeometryRequest(((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin, width, height); #endif # endif #endif return TCL_OK; } Tcl_AppendResult(INTERP, "Usage: dm size [width height]\n", (char *)NULL); return TCL_ERROR; } #if defined(DM_X) || defined(DM_TK) || defined(DM_OGL) || defined(DM_WGL) if (BU_STR_EQUAL(argv[0], "getx")) { if (argc == 1) { struct bu_vls tmp_vls = BU_VLS_INIT_ZERO; /* Bare set command, print out current settings */ bu_vls_struct_print2(&tmp_vls, "dm internal X variables", dm_xvars_vparse, (const char *)dmp->dm_vars.pub_vars); Tcl_AppendResult(INTERP, bu_vls_addr(&tmp_vls), (char *)NULL); bu_vls_free(&tmp_vls); } else if (argc == 2) { bu_vls_struct_item_named(&vls, dm_xvars_vparse, argv[1], (const char *)dmp->dm_vars.pub_vars, COMMA); Tcl_AppendResult(INTERP, bu_vls_addr(&vls), (char *)NULL); bu_vls_free(&vls); } return TCL_OK; } #endif if (BU_STR_EQUAL(argv[0], "bg")) { int r, g, b; if (argc != 1 && argc != 4) { bu_vls_printf(&vls, "Usage: dm bg [r g b]"); Tcl_AppendResult(INTERP, bu_vls_addr(&vls), (char *)NULL); bu_vls_free(&vls); return TCL_ERROR; } /* return background color of current display manager */ if (argc == 1) { bu_vls_printf(&vls, "%d %d %d", dmp->dm_bg[0], dmp->dm_bg[1], dmp->dm_bg[2]); Tcl_AppendResult(INTERP, bu_vls_addr(&vls), (char *)NULL); bu_vls_free(&vls); return TCL_OK; } if (sscanf(argv[1], "%d", &r) != 1 || sscanf(argv[2], "%d", &g) != 1 || sscanf(argv[3], "%d", &b) != 1) { bu_vls_printf(&vls, "Usage: dm bg r g b"); Tcl_AppendResult(INTERP, bu_vls_addr(&vls), (char *)NULL); bu_vls_free(&vls); return TCL_ERROR; } dirty = 1; return DM_SET_BGCOLOR(dmp, r, g, b); } Tcl_AppendResult(INTERP, "dm: bad command - ", argv[0], "\n", (char *)NULL); return TCL_ERROR; }
static void create_object_button_press(CreateObjectTool *tool, GdkEventButton *event, DDisplay *ddisp) { Point clickedpoint, origpoint; Handle *handle1; Handle *handle2; DiaObject *obj; real click_distance; ddisplay_untransform_coords(ddisp, (int)event->x, (int)event->y, &clickedpoint.x, &clickedpoint.y); origpoint = clickedpoint; snap_to_grid(ddisp, &clickedpoint.x, &clickedpoint.y); click_distance = ddisplay_untransform_length(ddisp, 3.0); obj = dia_object_default_create (tool->objtype, &clickedpoint, tool->user_data, &handle1, &handle2); tool->obj = obj; /* ensure that tool->obj is initialised in case we return early. */ if (!obj) { tool->moving = FALSE; tool->handle = NULL; message_error(_("'%s' creation failed"), tool->objtype ? tool->objtype->name : "NULL"); return; } diagram_add_object(ddisp->diagram, obj); /* Try a connect */ if (handle1 != NULL && handle1->connect_type != HANDLE_NONCONNECTABLE) { ConnectionPoint *connectionpoint; connectionpoint = object_find_connectpoint_display(ddisp, &origpoint, obj, TRUE); if (connectionpoint != NULL) { (obj->ops->move)(obj, &origpoint); } } if (!(event->state & GDK_SHIFT_MASK)) { /* Not Multi-select => remove current selection */ diagram_remove_all_selected(ddisp->diagram, TRUE); } diagram_select(ddisp->diagram, obj); /* Connect first handle if possible: */ if ((handle1!= NULL) && (handle1->connect_type != HANDLE_NONCONNECTABLE)) { object_connect_display(ddisp, obj, handle1, TRUE); } object_add_updates(obj, ddisp->diagram); ddisplay_do_update_menu_sensitivity(ddisp); diagram_flush(ddisp->diagram); if (handle2 != NULL) { tool->handle = handle2; tool->moving = TRUE; tool->last_to = handle2->pos; gdk_pointer_grab (gtk_widget_get_window(ddisp->canvas), FALSE, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, NULL, event->time); ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL)); } else { diagram_update_extents(ddisp->diagram); tool->moving = FALSE; } }
void snap_button(struct dlg *dlg, struct button *bp, bool sizing, int *content) { struct edges h; struct edges v; void *parent = NULL; int snapdist = g_snap_dist; int grid = g_snap_usegrid ? g_snap_gridsize : 0; int padding = g_snap_padding; if (snapdist < 1) return; h.dmin = v.dmin = h.def = v.def = snapdist; h.from2 = (h.from1 = bp->x0) + bp->w0; v.from2 = (v.from1 = bp->y0) + bp->h0; // ------------------------------------------------------ // snap to grid if (grid > 1)// && (parent || sizing)) { snap_to_grid(&h, &v, sizing, grid, padding); } else { struct snap_info si; si.h = &h; si.v = &v; si.sizing = sizing; si.same_level = true; si.pad = padding; si.self = bp; si.parent = parent; enum_buttons(dlg, snap_enum_proc, &si); h.to1 = 0; h.to2 = dlg->w; v.to1 = 0; v.to2 = dlg->h; snap_to_edge(&h, &v, sizing, false, padding); // ----------------------------------------- if (sizing) { // snap to button icons if (content) { // images have to be double padded, since they are centered h.to2 = (h.to1 = h.from1) + content[0]; v.to2 = (v.to1 = v.from1) + content[1]; snap_to_edge(&h, &v, sizing, false, -2*padding); } /* // snap frame to childs si.same_level = false; si.pad = -padding; si.self = NULL; si.parent = self; enum_buttons(dlg, snap_enum_proc, &si); */ } } // ----------------------------------------- // adjust the window-pos if (h.dmin < snapdist) { if (sizing) bp->w0 += h.omin; else bp->x0 += h.omin; } if (v.dmin < snapdist) { if (sizing) bp->h0 += v.omin; else bp->y0 += v.omin; } }
static void create_object_motion(CreateObjectTool *tool, GdkEventMotion *event, DDisplay *ddisp) { Point to; ConnectionPoint *connectionpoint = NULL; gchar *postext; GtkStatusbar *statusbar; guint context_id; if (!tool->moving) return; ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y); /* make sure the new object is restricted to its parent */ parent_handle_move_out_check(tool->obj, &to); /* Move to ConnectionPoint if near: */ if (tool->handle != NULL && tool->handle->connect_type != HANDLE_NONCONNECTABLE) { connectionpoint = object_find_connectpoint_display(ddisp, &to, tool->obj, TRUE); if (connectionpoint != NULL) { to = connectionpoint->pos; highlight_object(connectionpoint->object, DIA_HIGHLIGHT_CONNECTIONPOINT, ddisp->diagram); ddisplay_set_all_cursor(get_cursor(CURSOR_CONNECT)); } } if (connectionpoint == NULL) { /* No connectionopoint near, then snap to grid (if enabled) */ snap_to_grid(ddisp, &to.x, &to.y); highlight_reset_all(ddisp->diagram); ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL)); } object_add_updates(tool->obj, ddisp->diagram); tool->obj->ops->move_handle(tool->obj, tool->handle, &to, connectionpoint, HANDLE_MOVE_CREATE, 0); object_add_updates(tool->obj, ddisp->diagram); /* Put current mouse position in status bar */ statusbar = GTK_STATUSBAR (ddisp->modified_status); context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos"); postext = g_strdup_printf("%.3f, %.3f - %.3f, %.3f", tool->obj->bounding_box.left, tool->obj->bounding_box.top, tool->obj->bounding_box.right, tool->obj->bounding_box.bottom); gtk_statusbar_pop (statusbar, context_id); gtk_statusbar_push (statusbar, context_id, postext); g_free(postext); diagram_flush(ddisp->diagram); tool->last_to = to; return; }
/* ---------------------------------------------------------------------------- * Handles the events for the area editor. */ void area_editor::handle_controls(const ALLEGRO_EVENT &ev) { if(fade_mgr.is_fading()) return; gui->handle_event(ev); //Update mouse cursor in world coordinates. if( ev.type == ALLEGRO_EVENT_MOUSE_AXES || ev.type == ALLEGRO_EVENT_MOUSE_WARPED || ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN || ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP ) { mouse_cursor_x = ev.mouse.x / cam_zoom - cam_x - (gui_x / 2 / cam_zoom); mouse_cursor_y = ev.mouse.y / cam_zoom - cam_y - (scr_h / 2 / cam_zoom); lafi::widget* wum; if(!is_mouse_in_gui(ev.mouse.x, ev.mouse.y)) { wum = NULL; } else { wum = gui->get_widget_under_mouse(ev.mouse.x, ev.mouse.y); } ((lafi::label*) gui->widgets["lbl_status_bar"])->text = ( wum ? wum->description : "(" + i2s(mouse_cursor_x) + "," + i2s(mouse_cursor_y) + ")" ); } //Moving vertexes, camera, etc. if(ev.type == ALLEGRO_EVENT_MOUSE_AXES) { if( !is_mouse_in_gui(ev.mouse.x, ev.mouse.y) && moving_thing == INVALID && sec_mode != ESM_TEXTURE_VIEW && mode != EDITOR_MODE_OBJECTS ) { on_sector = get_sector(mouse_cursor_x, mouse_cursor_y, NULL, false); } else { on_sector = NULL; } //Move guide. if(sec_mode == ESM_GUIDE_MOUSE) { if(holding_m1) { guide_x += ev.mouse.dx / cam_zoom; guide_y += ev.mouse.dy / cam_zoom; } else if(holding_m2) { float new_w = guide_w + ev.mouse.dx / cam_zoom; float new_h = guide_h + ev.mouse.dy / cam_zoom; if(guide_aspect_ratio) { //Find the most significant change. if(ev.mouse.dx != 0 || ev.mouse.dy != 0) { bool most_is_width = fabs((double) ev.mouse.dx) > fabs((double) ev.mouse.dy); if(most_is_width) { float ratio = guide_h / guide_w; guide_w = new_w; guide_h = new_w * ratio; } else { float ratio = guide_w / guide_h; guide_h = new_h; guide_w = new_h * ratio; } } } else { guide_w = new_w; guide_h = new_h; } } guide_to_gui(); } else if(holding_m2) { //Move camera. cam_x += ev.mouse.dx / cam_zoom; cam_y += ev.mouse.dy / cam_zoom; } //Move thing. if(moving_thing != INVALID) { if(mode == EDITOR_MODE_SECTORS) { vertex* v_ptr = cur_area_data.vertexes[moving_thing]; v_ptr->x = snap_to_grid(mouse_cursor_x); v_ptr->y = snap_to_grid(mouse_cursor_y); } else if(mode == EDITOR_MODE_OBJECTS) { mob_gen* m_ptr = cur_area_data.mob_generators[moving_thing]; m_ptr->x = snap_to_grid(mouse_cursor_x); m_ptr->y = snap_to_grid(mouse_cursor_y); } else if(mode == EDITOR_MODE_PATHS) { path_stop* s_ptr = cur_area_data.path_stops[moving_thing]; s_ptr->x = snap_to_grid(mouse_cursor_x); s_ptr->y = snap_to_grid(mouse_cursor_y); s_ptr->calculate_dists(); path_preview_timeout.start(false); } else if(mode == EDITOR_MODE_SHADOWS) { tree_shadow* s_ptr = cur_area_data.tree_shadows[moving_thing]; s_ptr->x = snap_to_grid(mouse_cursor_x - moving_thing_x); s_ptr->y = snap_to_grid(mouse_cursor_y - moving_thing_y); shadow_to_gui(); } made_changes = true; } //Move path checkpoints. if(moving_path_preview_checkpoint != -1) { path_preview_checkpoints_x[moving_path_preview_checkpoint] = snap_to_grid(mouse_cursor_x); path_preview_checkpoints_y[moving_path_preview_checkpoint] = snap_to_grid(mouse_cursor_y); path_preview_timeout.start(false); } if(ev.mouse.dz != 0 && !is_mouse_in_gui(ev.mouse.x, ev.mouse.y)) { //Zoom. float new_zoom = cam_zoom + (cam_zoom * ev.mouse.dz * 0.1); new_zoom = max(ZOOM_MIN_LEVEL_EDITOR, new_zoom); new_zoom = min(ZOOM_MAX_LEVEL_EDITOR, new_zoom); float new_mc_x = ev.mouse.x / new_zoom - cam_x - (gui_x / 2 / new_zoom); float new_mc_y = ev.mouse.y / new_zoom - cam_y - (scr_h / 2 / new_zoom); cam_x -= (mouse_cursor_x - new_mc_x); cam_y -= (mouse_cursor_y - new_mc_y); mouse_cursor_x = new_mc_x; mouse_cursor_y = new_mc_y; cam_zoom = new_zoom; } if(sec_mode == ESM_NEW_SECTOR) { new_sector_valid_line = is_new_sector_line_valid( snap_to_grid(mouse_cursor_x), snap_to_grid(mouse_cursor_y) ); } } else if( ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN && !is_mouse_in_gui(ev.mouse.x, ev.mouse.y) ) { //Clicking. if(ev.mouse.button == 1) holding_m1 = true; else if(ev.mouse.button == 2) holding_m2 = true; else if(ev.mouse.button == 3) cam_zoom = 1.0; if(ev.mouse.button != 1) return; //If the user was editing, save it. if(mode == EDITOR_MODE_SECTORS) { gui_to_sector(); } else if(mode == EDITOR_MODE_OBJECTS) { gui_to_mob(); } else if(mode == EDITOR_MODE_SHADOWS) { gui_to_shadow(); } //Sector-related clicking. if(sec_mode == ESM_NONE && mode == EDITOR_MODE_SECTORS) { moving_thing = INVALID; edge* clicked_edge_ptr = NULL; size_t clicked_edge_nr = INVALID; bool created_vertex = false; for(size_t e = 0; e < cur_area_data.edges.size(); ++e) { edge* e_ptr = cur_area_data.edges[e]; if(!is_edge_valid(e_ptr)) continue; if( circle_intersects_line( mouse_cursor_x, mouse_cursor_y, 8 / cam_zoom, e_ptr->vertexes[0]->x, e_ptr->vertexes[0]->y, e_ptr->vertexes[1]->x, e_ptr->vertexes[1]->y ) ) { clicked_edge_ptr = e_ptr; clicked_edge_nr = e; break; } } if(double_click_time == 0) double_click_time = 0.5; else if(clicked_edge_ptr) { //Create a new vertex. double_click_time = 0; //New vertex, on the split point. //TODO create it on the edge, not on the cursor. vertex* new_v_ptr = new vertex(mouse_cursor_x, mouse_cursor_y); cur_area_data.vertexes.push_back(new_v_ptr); //New edge, copied from the original one. edge* new_e_ptr = new edge(*clicked_edge_ptr); cur_area_data.edges.push_back(new_e_ptr); //Save the original end vertex for later. vertex* end_v_ptr = clicked_edge_ptr->vertexes[1]; //Set vertexes on the new and original edges. new_e_ptr->vertex_nrs[0] = cur_area_data.vertexes.size() - 1; new_e_ptr->vertexes[0] = new_v_ptr; clicked_edge_ptr->vertex_nrs[1] = new_e_ptr->vertex_nrs[0]; clicked_edge_ptr->vertexes[1] = new_v_ptr; //Set sectors on the new edge. if(new_e_ptr->sectors[0]) { new_e_ptr->sectors[0]->edge_nrs.push_back( cur_area_data.edges.size() - 1 ); new_e_ptr->sectors[0]->edges.push_back(new_e_ptr); } if(new_e_ptr->sectors[1]) { new_e_ptr->sectors[1]->edge_nrs.push_back( cur_area_data.edges.size() - 1 ); new_e_ptr->sectors[1]->edges.push_back(new_e_ptr); } //Set edges of the new vertex. new_v_ptr->edge_nrs.push_back(cur_area_data.edges.size() - 1); new_v_ptr->edge_nrs.push_back(clicked_edge_nr); new_v_ptr->edges.push_back(new_e_ptr); new_v_ptr->edges.push_back(clicked_edge_ptr); //Update edge data on the end vertex of the original edge //(it now links to the new edge, not the old). for(size_t ve = 0; ve < end_v_ptr->edges.size(); ++ve) { if(end_v_ptr->edges[ve] == clicked_edge_ptr) { end_v_ptr->edges[ve] = new_e_ptr; end_v_ptr->edge_nrs[ve] = cur_area_data.edges.size() - 1; break; } } //Start dragging the new vertex. moving_thing = cur_area_data.vertexes.size() - 1; created_vertex = true; made_changes = true; } //Find a vertex to drag. if(!created_vertex) { for(size_t v = 0; v < cur_area_data.vertexes.size(); ++v) { if( dist( mouse_cursor_x, mouse_cursor_y, cur_area_data.vertexes[v]->x, cur_area_data.vertexes[v]->y ) <= 6.0 / cam_zoom ) { moving_thing = v; break; } } } //Find a sector to select. if(moving_thing == INVALID) { cur_sector = get_sector(mouse_cursor_x, mouse_cursor_y, NULL, false); sector_to_gui(); } } else if(sec_mode == ESM_NONE && mode == EDITOR_MODE_OBJECTS) { //Object-related clicking. cur_mob = NULL; moving_thing = INVALID; for(size_t m = 0; m < cur_area_data.mob_generators.size(); ++m) { mob_gen* m_ptr = cur_area_data.mob_generators[m]; float radius = m_ptr->type ? m_ptr->type->radius == 0 ? 16 : m_ptr->type->radius : 16; if( dist(m_ptr->x, m_ptr->y, mouse_cursor_x, mouse_cursor_y) <= radius ) { cur_mob = m_ptr; moving_thing = m; break; } } mob_to_gui(); } else if(sec_mode == ESM_NONE && mode == EDITOR_MODE_PATHS) { //Path-related clicking. cur_stop = NULL; moving_thing = INVALID; for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { path_stop* s_ptr = cur_area_data.path_stops[s]; if( dist(s_ptr->x, s_ptr->y, mouse_cursor_x, mouse_cursor_y) <= STOP_RADIUS ) { cur_stop = s_ptr; moving_thing = s; break; } } moving_path_preview_checkpoint = -1; if(show_path_preview) { for(unsigned char c = 0; c < 2; ++c) { if( bbox_check( path_preview_checkpoints_x[c], path_preview_checkpoints_y[c], mouse_cursor_x, mouse_cursor_y, PATH_PREVIEW_CHECKPOINT_RADIUS / cam_zoom ) ) { moving_path_preview_checkpoint = c; break; } } } } else if(sec_mode == ESM_NONE && mode == EDITOR_MODE_SHADOWS) { //Shadow-related clicking. cur_shadow = NULL; moving_thing = INVALID; for(size_t s = 0; s < cur_area_data.tree_shadows.size(); ++s) { tree_shadow* s_ptr = cur_area_data.tree_shadows[s]; float min_x, min_y, max_x, max_y; get_shadow_bounding_box(s_ptr, &min_x, &min_y, &max_x, &max_y); if( mouse_cursor_x >= min_x && mouse_cursor_x <= max_x && mouse_cursor_y >= min_y && mouse_cursor_y <= max_y ) { cur_shadow = s_ptr; moving_thing = s; moving_thing_x = mouse_cursor_x - s_ptr->x; moving_thing_y = mouse_cursor_y - s_ptr->y; break; } } shadow_to_gui(); } if(sec_mode == ESM_NEW_SECTOR) { //Next vertex in a new sector. float hotspot_x = snap_to_grid(mouse_cursor_x); float hotspot_y = snap_to_grid(mouse_cursor_y); new_sector_valid_line = is_new_sector_line_valid( snap_to_grid(mouse_cursor_x), snap_to_grid(mouse_cursor_y) ); if(new_sector_valid_line) { if( !new_sector_vertexes.empty() && dist( hotspot_x, hotspot_y, new_sector_vertexes[0]->x, new_sector_vertexes[0]->y ) <= VERTEX_MERGE_RADIUS ) { //Back to the first vertex. sec_mode = ESM_NONE; create_sector(); sector_to_gui(); made_changes = true; } else { //Add a new vertex. vertex* merge = get_merge_vertex( hotspot_x, hotspot_y, cur_area_data.vertexes, VERTEX_MERGE_RADIUS / cam_zoom ); if(merge) { new_sector_vertexes.push_back( new vertex(merge->x, merge->y) ); } else { new_sector_vertexes.push_back( new vertex(hotspot_x, hotspot_y) ); } } } } else if(sec_mode == ESM_NEW_OBJECT) { //Create a mob where the cursor is. sec_mode = ESM_NONE; float hotspot_x = snap_to_grid(mouse_cursor_x); float hotspot_y = snap_to_grid(mouse_cursor_y); cur_area_data.mob_generators.push_back( new mob_gen(hotspot_x, hotspot_y) ); cur_mob = cur_area_data.mob_generators.back(); mob_to_gui(); made_changes = true; } else if(sec_mode == ESM_DUPLICATE_OBJECT) { //Duplicate the current mob to where the cursor is. sec_mode = ESM_NONE; if(cur_mob) { float hotspot_x = snap_to_grid(mouse_cursor_x); float hotspot_y = snap_to_grid(mouse_cursor_y); mob_gen* new_mg = new mob_gen(*cur_mob); new_mg->x = hotspot_x; new_mg->y = hotspot_y; cur_area_data.mob_generators.push_back( new_mg ); cur_mob = new_mg; mob_to_gui(); made_changes = true; } } else if(sec_mode == ESM_NEW_STOP) { //Create a new stop where the cursor is. float hotspot_x = snap_to_grid(mouse_cursor_x); float hotspot_y = snap_to_grid(mouse_cursor_y); cur_area_data.path_stops.push_back( new path_stop(hotspot_x, hotspot_y, vector<path_link>()) ); cur_stop = cur_area_data.path_stops.back(); made_changes = true; } else if (sec_mode == ESM_NEW_LINK1 || sec_mode == ESM_NEW_1WLINK1) { //Pick a stop to start the link on. for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { path_stop* s_ptr = cur_area_data.path_stops[s]; if( dist(mouse_cursor_x, mouse_cursor_y, s_ptr->x, s_ptr->y) <= STOP_RADIUS ) { new_link_first_stop = s_ptr; sec_mode = sec_mode == ESM_NEW_LINK1 ? ESM_NEW_LINK2 : ESM_NEW_1WLINK2; break; } } path_preview_timeout.start(false); made_changes = true; } else if (sec_mode == ESM_NEW_LINK2 || sec_mode == ESM_NEW_1WLINK2) { //Pick a stop to end the link on. for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { path_stop* s_ptr = cur_area_data.path_stops[s]; if( dist(mouse_cursor_x, mouse_cursor_y, s_ptr->x, s_ptr->y) <= STOP_RADIUS ) { if(new_link_first_stop == s_ptr) continue; //Check if these two stops already have a link. //Delete it if so. for( size_t l = 0; l < new_link_first_stop->links.size(); ++l ) { if(new_link_first_stop->links[l].end_ptr == s_ptr) { new_link_first_stop->links.erase( new_link_first_stop->links.begin() + l ); break; } } for(size_t l = 0; l < s_ptr->links.size(); ++l) { if(s_ptr->links[l].end_ptr == new_link_first_stop) { s_ptr->links.erase(s_ptr->links.begin() + l); break; } } new_link_first_stop->links.push_back( path_link(s_ptr, s) ); if(sec_mode == ESM_NEW_LINK2) { s_ptr->links.push_back( path_link(new_link_first_stop, INVALID) ); s_ptr->fix_nrs(cur_area_data); } new_link_first_stop->calculate_dists(); sec_mode = sec_mode == ESM_NEW_LINK2 ? ESM_NEW_LINK1 : ESM_NEW_1WLINK1; break; } } path_preview_timeout.start(false); made_changes = true; } else if(sec_mode == ESM_DEL_STOP) { //Pick a stop to delete. for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { path_stop* s_ptr = cur_area_data.path_stops[s]; if( dist(mouse_cursor_x, mouse_cursor_y, s_ptr->x, s_ptr->y) <= STOP_RADIUS ) { //Check all links to this stop. for( size_t s2 = 0; s2 < cur_area_data.path_stops.size(); ++s2 ) { path_stop* s2_ptr = cur_area_data.path_stops[s2]; for(size_t l = 0; l < s2_ptr->links.size(); ++l) { if(s2_ptr->links[l].end_ptr == s_ptr) { s2_ptr->links.erase(s2_ptr->links.begin() + l); break; } } } //Finally, delete the stop. delete s_ptr; cur_area_data.path_stops.erase( cur_area_data.path_stops.begin() + s ); break; } } for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { cur_area_data.path_stops[s]->fix_nrs(cur_area_data); } path_preview.clear(); path_preview_timeout.start(false); made_changes = true; } else if(sec_mode == ESM_DEL_LINK) { //Pick a link to delete. bool deleted = false; for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) { path_stop* s_ptr = cur_area_data.path_stops[s]; for(size_t s2 = 0; s2 < s_ptr->links.size(); ++s2) { path_stop* s2_ptr = s_ptr->links[s2].end_ptr; if( circle_intersects_line( mouse_cursor_x, mouse_cursor_y, 8 / cam_zoom, s_ptr->x, s_ptr->y, s2_ptr->x, s2_ptr->y ) ) { s_ptr->links.erase(s_ptr->links.begin() + s2); for(size_t s3 = 0; s3 < s2_ptr->links.size(); ++s3) { if(s2_ptr->links[s3].end_ptr == s_ptr) { s2_ptr->links.erase( s2_ptr->links.begin() + s3 ); break; } } deleted = true; break; } } if(deleted) break; } path_preview.clear(); path_preview_timeout.start(false); made_changes = true; } else if(sec_mode == ESM_NEW_SHADOW) { //Create a new shadow where the cursor is. sec_mode = ESM_NONE; float hotspot_x = snap_to_grid(mouse_cursor_x); float hotspot_y = snap_to_grid(mouse_cursor_y); tree_shadow* new_shadow = new tree_shadow(hotspot_x, hotspot_y); new_shadow->bitmap = bmp_error; cur_area_data.tree_shadows.push_back(new_shadow); cur_shadow = new_shadow; shadow_to_gui(); made_changes = true; } } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { //Mouse button release. if(ev.mouse.button == 1) holding_m1 = false; else if(ev.mouse.button == 2) holding_m2 = false; if( ev.mouse.button == 1 && mode == EDITOR_MODE_SECTORS && sec_mode == ESM_NONE && moving_thing != INVALID ) { //Release the vertex. vertex* moved_v_ptr = cur_area_data.vertexes[moving_thing]; vertex* final_vertex = moved_v_ptr; unordered_set<sector*> affected_sectors; //Check if we should merge. for(size_t v = 0; v < cur_area_data.vertexes.size(); ++v) { vertex* dest_v_ptr = cur_area_data.vertexes[v]; if(dest_v_ptr == moved_v_ptr) continue; if( dist( moved_v_ptr->x, moved_v_ptr->y, dest_v_ptr->x, dest_v_ptr->y ) <= (VERTEX_MERGE_RADIUS / cam_zoom) ) { merge_vertex( moved_v_ptr, dest_v_ptr, &affected_sectors ); final_vertex = dest_v_ptr; break; } } //Finally, re-triangulate the affected sectors. for(size_t e = 0; e < final_vertex->edges.size(); ++e) { edge* e_ptr = final_vertex->edges[e]; for(size_t s = 0; s < 2; ++s) { if(e_ptr->sectors[s]) { affected_sectors.insert(e_ptr->sectors[s]); } } } for( auto s = affected_sectors.begin(); s != affected_sectors.end(); ++s ) { if(!(*s)) continue; triangulate(*s); } //If somewhere along the line, the current sector //got marked for deletion, unselect it. if(cur_sector) { if(cur_sector->edges.empty()) { cur_sector = NULL; sector_to_gui(); } } //Check if the edge's vertexes intersect with any other edges. //If so, they're marked with red. check_edge_intersections(moved_v_ptr); moving_thing = INVALID; } else if( ev.mouse.button == 1 && sec_mode == ESM_NONE && moving_thing != INVALID ) { //Release thing. moving_thing = INVALID; } moving_path_preview_checkpoint = -1; } else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) { //Key press. if( ev.keyboard.keycode == ALLEGRO_KEY_LSHIFT || ev.keyboard.keycode == ALLEGRO_KEY_RSHIFT ) { shift_pressed = true; } else if(ev.keyboard.keycode == ALLEGRO_KEY_F1) { debug_edge_nrs = !debug_edge_nrs; } else if(ev.keyboard.keycode == ALLEGRO_KEY_F2) { debug_sector_nrs = !debug_sector_nrs; } else if(ev.keyboard.keycode == ALLEGRO_KEY_F3) { debug_vertex_nrs = !debug_vertex_nrs; } else if(ev.keyboard.keycode == ALLEGRO_KEY_F4) { debug_triangulation = !debug_triangulation; } } else if(ev.type == ALLEGRO_EVENT_KEY_UP) { //Key release. if( ev.keyboard.keycode == ALLEGRO_KEY_LSHIFT || ev.keyboard.keycode == ALLEGRO_KEY_RSHIFT ) { shift_pressed = false; } } }
void PixelsMovement::moveImage(const gfx::Point& pos, MoveModifier moveModifier) { gfx::Transformation::Corners oldCorners; m_currentData.transformBox(oldCorners); ContextWriter writer(m_reader, 1000); gfx::RectF bounds = m_initialData.bounds(); bool updateBounds = false; double dx, dy; dx = ((pos.x - m_catchPos.x) * cos(m_currentData.angle()) + (pos.y - m_catchPos.y) * -sin(m_currentData.angle())); dy = ((pos.x - m_catchPos.x) * sin(m_currentData.angle()) + (pos.y - m_catchPos.y) * cos(m_currentData.angle())); switch (m_handle) { case MoveHandle: if ((moveModifier & LockAxisMovement) == LockAxisMovement) { if (ABS(dx) < ABS(dy)) dx = 0.0; else dy = 0.0; } bounds.offset(dx, dy); updateBounds = true; if ((moveModifier & SnapToGridMovement) == SnapToGridMovement) { // Snap the x1,y1 point to the grid. gfx::Rect gridBounds = App::instance() ->preferences().document(m_document).grid.bounds(); gfx::PointF gridOffset( snap_to_grid( gridBounds, gfx::Point(bounds.origin()), PreferSnapTo::ClosestGridVertex)); // Now we calculate the difference from x1,y1 point and we can // use it to adjust all coordinates (x1, y1, x2, y2). gridOffset -= bounds.origin(); bounds.offset(gridOffset); } break; case ScaleNWHandle: case ScaleNHandle: case ScaleNEHandle: case ScaleWHandle: case ScaleEHandle: case ScaleSWHandle: case ScaleSHandle: case ScaleSEHandle: { static double handles[][2] = { { 0.0, 0.0 }, { 0.5, 0.0 }, { 1.0, 0.0 }, { 0.0, 0.5 }, { 1.0, 0.5 }, { 0.0, 1.0 }, { 0.5, 1.0 }, { 1.0, 1.0 } }; gfx::PointF pivot; gfx::PointF handle( handles[m_handle-ScaleNWHandle][0], handles[m_handle-ScaleNWHandle][1]); if ((moveModifier & ScaleFromPivot) == ScaleFromPivot) { pivot.x = m_currentData.pivot().x; pivot.y = m_currentData.pivot().y; } else { pivot.x = 1.0 - handle.x; pivot.y = 1.0 - handle.y; pivot.x = bounds.x + bounds.w*pivot.x; pivot.y = bounds.y + bounds.h*pivot.y; } gfx::PointF a = bounds.origin(); gfx::PointF b = bounds.point2(); if ((moveModifier & MaintainAspectRatioMovement) == MaintainAspectRatioMovement) { auto u = point2Vector(gfx::PointF(m_catchPos) - pivot); auto v = point2Vector(gfx::PointF(pos) - pivot); auto w = v.projectOn(u); double scale = u.magnitude(); if (scale != 0.0) scale = (std::fabs(w.angle()-u.angle()) < PI/2.0 ? 1.0: -1.0) * w.magnitude() / scale; else scale = 1.0; a.x = int((a.x-pivot.x)*scale + pivot.x); a.y = int((a.y-pivot.y)*scale + pivot.y); b.x = int((b.x-pivot.x)*scale + pivot.x); b.y = int((b.y-pivot.y)*scale + pivot.y); } else { handle.x = bounds.x + bounds.w*handle.x; handle.y = bounds.y + bounds.h*handle.y; double w = (handle.x-pivot.x); double h = (handle.y-pivot.y); if (m_handle == ScaleNHandle || m_handle == ScaleSHandle) { dx = 0.0; w = 1.0; // Any value != 0.0 to avoid div by zero } else if (m_handle == ScaleWHandle || m_handle == ScaleEHandle) { dy = 0.0; h = 1.0; } a.x = int((a.x-pivot.x)*(1.0+dx/w) + pivot.x); a.y = int((a.y-pivot.y)*(1.0+dy/h) + pivot.y); b.x = int((b.x-pivot.x)*(1.0+dx/w) + pivot.x); b.y = int((b.y-pivot.y)*(1.0+dy/h) + pivot.y); } // Do not use "gfx::Rect(a, b)" here because if a > b we want to // keep a rectangle with negative width or height (to know that // it was flipped). bounds.x = a.x; bounds.y = a.y; bounds.w = b.x - a.x; bounds.h = b.y - a.y; updateBounds = true; break; } case RotateNWHandle: case RotateNHandle: case RotateNEHandle: case RotateWHandle: case RotateEHandle: case RotateSWHandle: case RotateSHandle: case RotateSEHandle: { gfx::PointF abs_initial_pivot = m_initialData.pivot(); gfx::PointF abs_pivot = m_currentData.pivot(); double newAngle = m_initialData.angle() + atan2((double)(-pos.y + abs_pivot.y), (double)(+pos.x - abs_pivot.x)) - atan2((double)(-m_catchPos.y + abs_initial_pivot.y), (double)(+m_catchPos.x - abs_initial_pivot.x)); // Put the angle in -180 to 180 range. while (newAngle < -PI) newAngle += 2*PI; while (newAngle > PI) newAngle -= 2*PI; // Is the "angle snap" is activated, we've to snap the angle // to common (pixel art) angles. if ((moveModifier & AngleSnapMovement) == AngleSnapMovement) { // TODO make this configurable static const double keyAngles[] = { 0.0, 26.565, 45.0, 63.435, 90.0, 116.565, 135.0, 153.435, 180.0, 180.0, -153.435, -135.0, -116, -90.0, -63.435, -45.0, -26.565 }; double newAngleDegrees = 180.0 * newAngle / PI; int closest = 0; int last = sizeof(keyAngles) / sizeof(keyAngles[0]) - 1; for (int i=0; i<=last; ++i) { if (std::fabs(newAngleDegrees-keyAngles[closest]) > std::fabs(newAngleDegrees-keyAngles[i])) closest = i; } newAngle = PI * keyAngles[closest] / 180.0; } m_currentData.angle(newAngle); } break; case PivotHandle: { // Calculate the new position of the pivot gfx::PointF newPivot(m_initialData.pivot().x + (pos.x - m_catchPos.x), m_initialData.pivot().y + (pos.y - m_catchPos.y)); m_currentData = m_initialData; m_currentData.displacePivotTo(newPivot); } break; } if (updateBounds) { m_currentData.bounds(bounds); m_adjustPivot = true; } redrawExtraImage(); m_document->setTransformation(m_currentData); // Get the new transformed corners gfx::Transformation::Corners newCorners; m_currentData.transformBox(newCorners); // Create a union of all corners, and that will be the bounds to // redraw of the sprite. gfx::Rect fullBounds; for (int i=0; i<gfx::Transformation::Corners::NUM_OF_CORNERS; ++i) { fullBounds = fullBounds.createUnion(gfx::Rect((int)oldCorners[i].x, (int)oldCorners[i].y, 1, 1)); fullBounds = fullBounds.createUnion(gfx::Rect((int)newCorners[i].x, (int)newCorners[i].y, 1, 1)); } // If "fullBounds" is empty is because the cel was not moved if (!fullBounds.isEmpty()) { // Notify the modified region. m_document->notifySpritePixelsModified(m_sprite, gfx::Region(fullBounds), m_site.frame()); } }
int common_dm(int argc, char **argv) { int status; struct bu_vls vls; if (dbip == DBI_NULL) return TCL_OK; if (!strcmp(argv[0], "idle")) { am_mode = AMM_IDLE; scroll_active = 0; if (rubber_band->rb_active) { rubber_band->rb_active = 0; if (mged_variables->mv_mouse_behavior == 'p') rb_set_dirty_flag(); else if (mged_variables->mv_mouse_behavior == 'r') rt_rect_area(); else if (mged_variables->mv_mouse_behavior == 'z') zoom_rect_area(); } return TCL_OK; } if (!strcmp(argv[0], "m")) { int x; int y; int old_orig_gui; int stolen = 0; fastf_t fx, fy; if (argc < 3) { Tcl_AppendResult(interp, "dm m: need more parameters\n", "dm m xpos ypos\n", (char *)NULL); return TCL_ERROR; } old_orig_gui = mged_variables->mv_orig_gui; fx = dm_Xx2Normal(dmp, atoi(argv[1])); fy = dm_Xy2Normal(dmp, atoi(argv[2]), 0); x = fx * GED_MAX; y = fy * GED_MAX; if (mged_variables->mv_faceplate && mged_variables->mv_orig_gui) { #define MENUXLIM (-1250) if (x >= MENUXLIM && scroll_select(x, y, 0)) { stolen = 1; goto end; } if (x < MENUXLIM && mmenu_select(y, 0)) { stolen = 1; goto end; } } mged_variables->mv_orig_gui = 0; fy = dm_Xy2Normal(dmp, atoi(argv[2]), 1); y = fy * GED_MAX; end: bu_vls_init(&vls); if (mged_variables->mv_mouse_behavior == 'q' && !stolen) { point_t view_pt; point_t model_pt; if (grid_state->gr_snap) snap_to_grid(&fx, &fy); if ( mged_variables->mv_perspective_mode ) VSET(view_pt, fx, fy, 0.0) else VSET(view_pt, fx, fy, 1.0) MAT4X3PNT(model_pt, view_state->vs_vop->vo_view2model, view_pt); VSCALE(model_pt, model_pt, base2local); if (dmp->dm_zclip) bu_vls_printf(&vls, "qray_nirt %lf %lf %lf", model_pt[X], model_pt[Y], model_pt[Z]); else bu_vls_printf(&vls, "qray_nirt -b %lf %lf %lf", model_pt[X], model_pt[Y], model_pt[Z]); } else if ((mged_variables->mv_mouse_behavior == 'p' ||
// Event handler for a "floating" group of objects. int sheet_item_floating_event (Sheet *sheet, const GdkEvent *event) { SheetPriv *priv; GList *list; static gboolean keep = FALSE; // Remember the start position of the mouse cursor. static Coords last = {0., 0.}; // Mouse cursor position in window coordinates, snapped to the grid spacing. static Coords snapped = {0., 0.}; // Move the selected item(s) by this movement. Coords delta = {0., 0.}; g_return_val_if_fail (sheet != NULL, FALSE); g_return_val_if_fail (IS_SHEET (sheet), FALSE); g_return_val_if_fail (sheet->priv->floating_objects != NULL, FALSE); priv = sheet->priv; switch (event->type) { case GDK_BUTTON_RELEASE: g_signal_stop_emission_by_name (sheet, "event"); break; case GDK_BUTTON_PRESS: if (sheet->state != SHEET_STATE_FLOAT) return TRUE; switch (event->button.button) { case 2: case 4: case 5: return FALSE; case 1: // do not free the floating items, but use them like a stamp keep = event->button.state & GDK_CONTROL_MASK; // Continue adding if CTRL is pressed if (!keep) { sheet->state = SHEET_STATE_NONE; g_signal_stop_emission_by_name (sheet, "event"); if (g_signal_handler_is_connected (sheet, sheet->priv->float_handler_id)) g_signal_handler_disconnect (sheet, sheet->priv->float_handler_id); sheet->priv->float_handler_id = 0; } // FIXME assert that `Coords current` has been set by now! for (list = priv->floating_objects; list; list = list->next) { SheetItem *floating_item; ItemData *floating_data; // Create a real item. floating_item = list->data; if (!keep) { floating_data = sheet_item_get_data (floating_item); g_object_set (floating_item, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); } else { // FIXME the bounding box of the clone is wrong floating_data = item_data_clone (sheet_item_get_data (floating_item)); } g_object_ref (G_OBJECT (floating_data)); NG_DEBUG ("Item Data Pos will be %lf %lf", snapped.x, snapped.y) item_data_set_pos (floating_data, &snapped); item_data_snap (floating_data, sheet->grid); schematic_add_item (schematic_view_get_schematic_from_sheet (sheet), floating_data); if (!keep) g_object_unref (G_OBJECT (floating_item)); } if (keep) { g_object_set (G_OBJECT (priv->floating_group), "x", snapped.x, "y", snapped.y, NULL); } else { g_list_free (priv->floating_objects); priv->floating_objects = NULL; } break; case 3: // Cancel the "float-placement" for button-3 clicks. g_signal_stop_emission_by_name (sheet, "event"); sheet_item_cancel_floating (sheet); break; } break; case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: g_signal_stop_emission_by_name (sheet, "event"); return TRUE; case GDK_MOTION_NOTIFY: // keep track of the position, as `sheet_get_pointer*()` does not work // in other events than MOTION_NOTIFY #if 0 { Coords tmp; last = current; if (sheet_get_pointer (sheet, &tmp.x, &tmp.y)) { snapped_current = current = tmp; snap_to_grid (sheet->grid, &snapped_current.x, &snapped_current.y); } } #endif if (sheet->state != SHEET_STATE_FLOAT && sheet->state != SHEET_STATE_FLOAT_START) return FALSE; g_signal_stop_emission_by_name (sheet, "event"); // Get pointer position independantly of the zoom if (sheet->state == SHEET_STATE_FLOAT_START) { sheet->state = SHEET_STATE_FLOAT; last.x = last.y = 0.; // Reparent the selected objects so that we can move them // efficiently. for (list = priv->floating_objects; list; list = list->next) { sheet_item_reparent (SHEET_ITEM (list->data), priv->floating_group); // Set the floating item visible g_object_set (G_OBJECT (list->data), "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); } #if 0 GooCanvasBounds box; goo_canvas_item_get_bounds (priv->floating_group, &box); #endif NG_DEBUG ("\n\n\nFLOAT ### START\n\n\n\n"); } sheet_get_pointer_snapped (sheet, &snapped.x, &snapped.y); delta = coords_sub (&snapped, &last); NG_DEBUG ("drag floating current sx=%lf sy=%lf \n", snapped.x, snapped.y); NG_DEBUG ("drag floating last lx=%lf ly=%lf \n", last.x, last.y); NG_DEBUG ("drag floating delta -> dx=%lf dy=%lf \n", delta.x, delta.y); #if !FIXME_INCREMENTAL_MOVMENT_DOES_NOT_WORK last = snapped; #else goo_canvas_item_set_transform (GOO_CANVAS_ITEM (priv->floating_group), NULL); #endif goo_canvas_item_translate (GOO_CANVAS_ITEM (priv->floating_group), delta.x, delta.y); break; case GDK_KEY_PRESS: switch (event->key.keyval) { case GDK_KEY_r: case GDK_KEY_R: { Coords bbdelta; GooCanvasBounds bounds; // Center the objects around the mouse pointer. goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (priv->floating_group), &bounds); bbdelta.x = (bounds.x2 - bounds.x1) / 2.; bbdelta.y = (bounds.y2 - bounds.y1) / 2.; sheet_rotate_ghosts (sheet); // Center the objects around the mouse pointer. goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (priv->floating_group), &bounds); bbdelta.x -= (bounds.x2 - bounds.x1) / 2.; bbdelta.y -= (bounds.y2 - bounds.y1) / 2.; snap_to_grid (sheet->grid, &bbdelta.x, &bbdelta.y); goo_canvas_item_translate (GOO_CANVAS_ITEM (priv->floating_group), bbdelta.x, bbdelta.y); } break; default: return FALSE; } default: return FALSE; } return TRUE; }
// Event handler for a SheetItem gboolean sheet_item_event (GooCanvasItem *sheet_item, GooCanvasItem *sheet_target_item, GdkEvent *event, Sheet *sheet) { // Remember the last position of the mouse cursor. static double last_x, last_y; GooCanvas *canvas; SheetPriv *priv; GList *list; // Mouse cursor position in window coordinates, snapped to the grid spacing. double snapped_x, snapped_y; // Move the selected item(s) by this movement. double dx, dy; g_return_val_if_fail (sheet_item != NULL, FALSE); g_return_val_if_fail (sheet != NULL, FALSE); priv = sheet->priv; canvas = GOO_CANVAS (sheet); switch (event->type) { case GDK_BUTTON_PRESS: // Grab focus to sheet for correct use of events gtk_widget_grab_focus (GTK_WIDGET (sheet)); switch (event->button.button) { case 1: g_signal_stop_emission_by_name (sheet_item, "button_press_event"); sheet->state = SHEET_STATE_DRAG_START; sheet_get_pointer (sheet, &last_x, &last_y); break; case 3: g_signal_stop_emission_by_name (sheet_item, "button_press_event"); if (sheet->state != SHEET_STATE_NONE) return TRUE; // Bring up a context menu for right button clicks. if (!SHEET_ITEM (sheet_item)->priv->selected && !((event->button.state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)) sheet_select_all (sheet, FALSE); sheet_item_select (SHEET_ITEM (sheet_item), TRUE); sheet_item_run_menu (SHEET_ITEM (sheet_item), sheet, (GdkEventButton *) event); break; default: return FALSE; } break; case GDK_2BUTTON_PRESS: // Do not interfere with object dragging. if (sheet->state == SHEET_STATE_DRAG) return FALSE; switch (event->button.button) { case 1: if (sheet->state == SHEET_STATE_DRAG_START) sheet->state = SHEET_STATE_NONE; g_signal_stop_emission_by_name (sheet_item, "button_press_event"); g_signal_emit_by_name (sheet_item, "double_clicked"); break; default: return FALSE; } break; case GDK_3BUTTON_PRESS: g_signal_stop_emission_by_name (sheet_item, "button_press_event"); return TRUE; case GDK_BUTTON_RELEASE: switch (event->button.button) { case 1: if (sheet->state != SHEET_STATE_DRAG && sheet->state != SHEET_STATE_DRAG_START) return TRUE; g_signal_stop_emission_by_name (sheet_item, "button-release-event"); if (sheet->state == SHEET_STATE_DRAG_START) { sheet->state = SHEET_STATE_NONE; if (!(event->button.state & GDK_SHIFT_MASK)) sheet_select_all (sheet, FALSE); if (IS_SHEET_ITEM (sheet_item)) sheet_item_select (SHEET_ITEM (sheet_item), TRUE); return TRUE; } // Get the mouse motion sheet_get_pointer (sheet, &snapped_x, &snapped_y); snapped_x -= last_x; snapped_y -= last_y; sheet->state = SHEET_STATE_NONE; goo_canvas_pointer_ungrab (canvas, GOO_CANVAS_ITEM (sheet_item), event->button.time); // Reparent the selected objects to the normal group // to have correct behaviour for (list = priv->selected_objects; list; list = list->next) { sheet_item_reparent (SHEET_ITEM (list->data), sheet->object_group); } for (list = priv->selected_objects; list; list = list->next) { ItemData *item_data; Coords pos; item_data = SHEET_ITEM (list->data)->priv->data; pos.x = snapped_x; pos.y = snapped_y; item_data_move (item_data, &pos); item_data_register (item_data); } g_list_free_full (list, g_object_unref); break; } case GDK_KEY_PRESS: switch (event->key.keyval) { case GDK_KEY_r: sheet_rotate_selection (sheet); { gdouble x, y; GooCanvasBounds bounds; sheet_get_pointer (sheet, &x, &y); // Center the objects around the mouse pointer. goo_canvas_item_get_bounds ( GOO_CANVAS_ITEM (priv->floating_group), &bounds); dx = x - (bounds.x1 + bounds.x2) / 2; dy = y - (bounds.y1 + bounds.y2) / 2; snap_to_grid (sheet->grid, &dx, &dy); goo_canvas_item_translate ( GOO_CANVAS_ITEM (priv->floating_group), dx, dy); last_x = snapped_x; last_y = snapped_y; } break; default: return FALSE; } return TRUE; case GDK_MOTION_NOTIFY: if (sheet->state != SHEET_STATE_DRAG && sheet->state != SHEET_STATE_DRAG_START) return FALSE; if (sheet->state == SHEET_STATE_DRAG_START) { sheet->state = SHEET_STATE_DRAG; // Update the selection if needed. if (IS_SHEET_ITEM (sheet_item) && (!SHEET_ITEM (sheet_item)->priv->selected)) { if (!(event->button.state & GDK_SHIFT_MASK)) { sheet_select_all (sheet, FALSE); } sheet_item_select (SHEET_ITEM (sheet_item), TRUE); } // Reparent the selected objects so that we can move them // efficiently. for (list = priv->selected_objects; list; list = list->next) { ItemData *item_data; item_data = SHEET_ITEM (list->data)->priv->data; item_data_unregister (item_data); sheet_item_reparent (SHEET_ITEM (list->data), priv->selected_group); } goo_canvas_pointer_grab (canvas, GOO_CANVAS_ITEM (sheet_item), GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, event->button.time); } // Set last_x & last_y to the pointer position sheet_get_pointer (sheet, &snapped_x, &snapped_y); dx = snapped_x - last_x; dy = snapped_y - last_y; // Check that we don't move outside the sheet... // Horizontally: /* if (cx1 <= 0) { // leftmost edge dx = dx - x1; snap_to_grid (sheet->grid, &dx, NULL); snapped_x = last_x + dx; } else if (cx2 >= sheet_width) { // rightmost edge dx = dx - (x2 - sheet_width / priv->zoom); snap_to_grid (sheet->grid, &dx, NULL); snapped_x = last_x + dx; } // And vertically: if (cy1 <= 0) { // upper edge dy = dy - y1; snap_to_grid (sheet->grid, NULL, &dy); snapped_y = last_y + dy; } else if (cy2 >= sheet_height) { // lower edge dy = dy - (y2 - sheet_height / priv->zoom); snap_to_grid (sheet->grid, NULL, &dy); snapped_y = last_y + dy; } //last_x = snapped_x; //last_y = snapped_y; */ goo_canvas_item_set_transform (GOO_CANVAS_ITEM (priv->selected_group), NULL); goo_canvas_item_translate (GOO_CANVAS_ITEM (priv->selected_group), dx, dy); return TRUE; default: return FALSE; } return TRUE; }
static int wire_item_event (WireItem *wire_item, const GdkEvent *event, SchematicView *sv) { SheetPos start_pos, length; Wire *wire; Sheet *sheet; GnomeCanvas *canvas; static double last_x, last_y; double dx, dy, zoom; /* The selected group's bounding box in window resp. canvas coordinates. */ double x1, y1, x2, y2; static double bb_x1, bb_y1, bb_x2, bb_y2; int cx1, cy1, cx2, cy2; double snapped_x, snapped_y; int sheet_width, sheet_height; SheetPos pos; sheet = schematic_view_get_sheet (sv); canvas = GNOME_CANVAS (sheet); g_object_get (G_OBJECT (wire_item), "data", &wire, NULL); wire_get_pos_and_length (WIRE (wire), &start_pos, &length); sheet_get_zoom (sheet, &zoom); switch (event->type) { case GDK_BUTTON_PRESS: switch (event->button.button) { case 1: { g_signal_stop_emission_by_name (G_OBJECT (sheet), "event"); double x, y; x = event->button.x - start_pos.x; y = event->button.y - start_pos.y; if ((x > -RESIZER_SIZE) && (x < RESIZER_SIZE) && (y > -RESIZER_SIZE) && (y < RESIZER_SIZE)) { gtk_widget_grab_focus (GTK_WIDGET (sheet)); sheet->state = SHEET_STATE_DRAG_START; wire_item->priv->resize_state = WIRE_RESIZER_1; last_x = event->button.x; last_y = event->button.y; item_data_unregister (ITEM_DATA (wire)); return TRUE; } if ((x > (length.x-RESIZER_SIZE)) && (x < (length.x+RESIZER_SIZE)) && (y > (length.y-RESIZER_SIZE)) && (y < (length.y+RESIZER_SIZE))) { gtk_widget_grab_focus (GTK_WIDGET (sheet)); sheet->state = SHEET_STATE_DRAG_START; wire_item->priv->resize_state = WIRE_RESIZER_2; last_x = event->button.x; last_y = event->button.y; item_data_unregister (ITEM_DATA (wire)); return TRUE; } } break; } break; case GDK_MOTION_NOTIFY: if (sheet->state != SHEET_STATE_DRAG && sheet->state != SHEET_STATE_DRAG_START) break; if (wire_item->priv->resize_state == WIRE_RESIZER_NONE) break; if (sheet->state == SHEET_STATE_DRAG_START || sheet->state == SHEET_STATE_DRAG) { sheet->state = SHEET_STATE_DRAG; snapped_x = event->motion.x; snapped_y = event->motion.y; snap_to_grid (sheet->grid, &snapped_x, &snapped_y); dx = snapped_x - last_x; dy = snapped_y - last_y; last_x = snapped_x; last_y = snapped_y; wire_get_pos_and_length (wire, &pos, &length); if (wire_item->priv->resize_state == WIRE_RESIZER_1) { switch (wire->priv->direction) { case WIRE_DIR_VERT: /* Vertical Wire */ pos.y = last_y; length.y -= dy; break; case WIRE_DIR_HORIZ: /* Horizontal Wire */ pos.x = last_x; length.x -= dx; break; default: pos.y = last_y; length.y -= dy; pos.x = last_x; length.x -= dx; } } else { switch (wire->priv->direction) { case WIRE_DIR_VERT: /* Vertical Wire */ length.y += dy; break; case WIRE_DIR_HORIZ: /* Horizontal Wire */ length.x += dx; break; default: length.y += dy; length.x += dx; } } snap_to_grid (sheet->grid, &length.x, &length.y); item_data_set_pos (sheet_item_get_data (SHEET_ITEM (wire_item)), &pos); wire_set_length (wire, &length); return TRUE; } break; case GDK_BUTTON_RELEASE: switch (event->button.button) { case 1: if (sheet->state != SHEET_STATE_DRAG && sheet->state != SHEET_STATE_DRAG_START) break; if (wire_item->priv->resize_state == WIRE_RESIZER_NONE) break; g_signal_stop_emission_by_name (G_OBJECT (wire_item), "event"); //gtk_timeout_remove (priv->scroll_timeout_id); // Esto no esta bien. sheet->state = SHEET_STATE_NONE; gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM (wire_item), event->button.time); wire_item->priv->resize_state = WIRE_RESIZER_NONE; sheet->state = SHEET_STATE_NONE; item_data_register (ITEM_DATA (wire)); return TRUE; } break; default: return sheet_item_event (SHEET_ITEM (wire_item), event, sv); } return sheet_item_event (SHEET_ITEM (wire_item), event, sv); }
// Event handler for a "floating" group of objects. int sheet_item_floating_event (Sheet *sheet, const GdkEvent *event) { SheetPriv *priv; GList *list; static Coords pos; static int keep = 0; // Remember the last position of the mouse cursor. static double last_x, last_y; // Mouse cursor position in window coordinates, snapped to the grid spacing. double snapped_x, snapped_y; // Move the selected item(s) by this movement. double dx, dy; g_return_val_if_fail (sheet != NULL, FALSE); g_return_val_if_fail (IS_SHEET (sheet), FALSE); g_return_val_if_fail (sheet->priv->floating_objects != NULL, FALSE); priv = sheet->priv; switch (event->type) { case GDK_BUTTON_RELEASE: g_signal_stop_emission_by_name (sheet, "event"); break; case GDK_BUTTON_PRESS: if (sheet->state != SHEET_STATE_FLOAT) return TRUE; switch (event->button.button) { case 2: case 4: case 5: return FALSE; case 1: // do not free the floating items, but use them like a stamp keep = event->button.state & GDK_CONTROL_MASK; // Continue adding if CTRL is pressed if (!keep) { sheet->state = SHEET_STATE_NONE; g_signal_stop_emission_by_name (sheet, "event"); if (g_signal_handler_is_connected (sheet, sheet->priv->float_handler_id)) g_signal_handler_disconnect (sheet, sheet->priv->float_handler_id); sheet->priv->float_handler_id = 0; } // Get pointer position in canvas coordinates sheet_get_pointer (sheet, &pos.x, &pos.y); for (list = priv->floating_objects; list; list = list->next) { SheetItem *floating_item; ItemData *floating_data; // Create a real item. floating_item = list->data; if (!keep) { floating_data = sheet_item_get_data (floating_item); g_object_set (floating_item, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); } else { floating_data = item_data_clone (sheet_item_get_data (floating_item)); } g_object_ref (G_OBJECT (floating_data)); item_data_set_pos (floating_data, &pos); schematic_add_item (schematic_view_get_schematic_from_sheet (sheet), floating_data); if (!keep) g_object_unref (G_OBJECT (floating_item)); } if (keep) { g_object_set (G_OBJECT (sheet->priv->floating_group), "x", pos.x, "y", pos.y, NULL); } else { g_list_free (sheet->priv->floating_objects); sheet->priv->floating_objects = NULL; } pos.x = 0.0; pos.y = 0.0; break; case 3: // Cancel the "float-placement" for button-3 clicks. g_signal_stop_emission_by_name (sheet, "event"); sheet_item_cancel_floating (sheet); break; } break; case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: g_signal_stop_emission_by_name (sheet, "event"); return TRUE; case GDK_MOTION_NOTIFY: if (sheet->state != SHEET_STATE_FLOAT && sheet->state != SHEET_STATE_FLOAT_START) return FALSE; g_signal_stop_emission_by_name (sheet, "event"); if (sheet->state == SHEET_STATE_FLOAT_START) { sheet->state = SHEET_STATE_FLOAT; // Reparent the selected objects so that we can move them // efficiently. for (list = priv->floating_objects; list; list = list->next) { sheet_item_reparent (SHEET_ITEM (list->data), priv->floating_group); // Set the floating item visible g_object_set (G_OBJECT (list->data), "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); } last_x = 0.0; last_y = 0.0; } // Get pointer position independantly of the zoom sheet_get_pointer (sheet, &snapped_x, &snapped_y); // Calculate which amount to move the selected objects by. dx = snapped_x - last_x; dy = snapped_y - last_y; last_x = snapped_x; last_y = snapped_y; for (list = priv->floating_objects; list; list = list->next) { goo_canvas_item_translate (GOO_CANVAS_ITEM (list->data), dx, dy); } g_list_free_full (list, g_object_unref); break; case GDK_KEY_PRESS: switch (event->key.keyval) { case GDK_KEY_r: case GDK_KEY_R: sheet_rotate_ghosts (sheet); { gdouble x, y; GooCanvasBounds bounds; sheet_get_pointer (sheet, &x, &y); // Center the objects around the mouse pointer. goo_canvas_item_get_bounds ( GOO_CANVAS_ITEM (priv->floating_group), &bounds); snapped_x = x - (bounds.x1 + bounds.x2) / 2; snapped_y = y - (bounds.y1 + bounds.y2) / 2; snap_to_grid (sheet->grid, &snapped_x, &snapped_y); goo_canvas_item_translate ( GOO_CANVAS_ITEM (priv->floating_group), snapped_x, snapped_y); last_x = snapped_x; last_y = snapped_y; } break; default: return FALSE; } default: return FALSE; } return TRUE; }