From: cilix42 Date: Sat, 1 Sep 2007 23:36:14 +0000 (+0000) Subject: Decent support for setting the direction of infinite VPs via the toolbar and partial... X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=bedbeec8a0241f2d83052b4c9e3f40510b1edb73;p=inkscape.git Decent support for setting the direction of infinite VPs via the toolbar and partial fix for wrong undo behaviour (?) --- diff --git a/src/box3d.cpp b/src/box3d.cpp index 1942ea3d6..e47aa73b3 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -234,7 +234,13 @@ sp_3dbox_update(SPObject *object, SPCtx *ctx, guint flags) { if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { SP3DBox *box = SP_3DBOX(object); - sp_3dbox_link_to_existing_paths (box, SP_OBJECT_REPR(object)); + Inkscape::XML::Node *repr = SP_OBJECT_REPR(object); + sp_3dbox_link_to_existing_paths (box, repr); + SP3DBoxContext *bc = SP_3DBOX_CONTEXT (inkscape_active_event_context()); + bc->_vpdrag->updateDraggers(); + // FIXME: Should we update the corners here, too? Maybe this is the reason why the handles + // are off after an undo/redo! On the other hand, if we do so we get warnings about + // updates occuring while other updats are in progress ... } /* Invoke parent method */ diff --git a/src/perspective3d.cpp b/src/perspective3d.cpp index 9321af356..db4f564c7 100644 --- a/src/perspective3d.cpp +++ b/src/perspective3d.cpp @@ -196,6 +196,11 @@ Perspective3D::set_infinite_direction (Box3D::Axis axis, NR::Point const dir) } get_vanishing_point (axis)->set_infinite_direction (dir); + for (GSList *i = this->boxes; i != NULL; i = i->next) { + sp_3dbox_reshape_after_VP_rotation (SP_3DBOX (i->data), axis); + sp_3dbox_set_z_orders_later_on (SP_3DBOX (i->data)); + } + update_box_reprs(); } void @@ -207,11 +212,6 @@ Perspective3D::rotate (Box3D::Axis const axis, double const angle) a += angle; a *= M_PI/180; this->set_infinite_direction (axis, NR::Point (cos (a), sin (a))); - for (GSList *i = this->boxes; i != NULL; i = i->next) { - sp_3dbox_reshape_after_VP_rotation (SP_3DBOX (i->data), axis); - sp_3dbox_set_z_orders_later_on (SP_3DBOX (i->data)); - } - update_box_reprs(); } } diff --git a/src/vanishing-point.cpp b/src/vanishing-point.cpp index 2426c9954..f5e98face 100644 --- a/src/vanishing-point.cpp +++ b/src/vanishing-point.cpp @@ -270,6 +270,8 @@ vp_knot_grabbed_handler (SPKnot *knot, unsigned int state, gpointer data) VPDragger *dragger = (VPDragger *) data; VPDrag *drag = dragger->parent; + drag->dragging = true; + //sp_canvas_force_full_redraw_after_interruptions(dragger->parent->desktop->canvas, 5); if ((state & GDK_SHIFT_MASK) && !drag->hasEmptySelection()) { // FIXME: Is the second check necessary? @@ -369,7 +371,13 @@ vp_knot_ungrabbed_handler (SPKnot *knot, guint state, gpointer data) // TODO: Update box's paths and svg representation + dragger->parent->dragging = false; + // TODO: Undo machinery!! + g_return_if_fail (dragger->parent); + g_return_if_fail (dragger->parent->document); + sp_document_done(dragger->parent->document, SP_VERB_CONTEXT_3DBOX, + _("3D box: Move vanishing point")); } VPDragger::VPDragger(VPDrag *parent, NR::Point p, VanishingPoint *vp) @@ -613,6 +621,7 @@ VPDrag::VPDrag (SPDocument *document) //this->selected = NULL; this->local_change = false; + this->dragging = false; this->sel_changed_connection = this->selection->connectChanged( sigc::bind ( @@ -676,6 +685,8 @@ VPDrag::getDraggerFor (VanishingPoint const &vp) void VPDrag::updateDraggers () { + if (this->dragging) + return; /*** while (selected) { selected = g_list_remove(selected, selected->data); diff --git a/src/vanishing-point.h b/src/vanishing-point.h index 428bb49ad..3dde39385 100644 --- a/src/vanishing-point.h +++ b/src/vanishing-point.h @@ -55,6 +55,7 @@ public: bool operator== (VanishingPoint const &other); inline NR::Point get_pos() const { return NR::Point ((*this)[NR::X], (*this)[NR::Y]); } + inline double get_angle() const { return NR::atan2 (this->v_dir) * 180/M_PI; } // return angle of infinite direction is in degrees inline void set_pos(NR::Point const &pt) { (*this)[NR::X] = pt[NR::X]; (*this)[NR::Y] = pt[NR::Y]; } inline void set_pos(const double pt_x, const double pt_y) { (*this)[NR::X] = pt_x; @@ -120,6 +121,7 @@ public: //void grabKnot (VanishingPoint const &vp, gint x, gint y, guint32 etime); bool local_change; + bool dragging; SPDocument *document; GList *draggers; diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 7e5de6b51..81bdc6607 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -303,8 +303,13 @@ static gchar const * ui_descr = " " " " + " " " " + " " + " " " " + " " + " " " " " " " " @@ -2146,68 +2151,280 @@ static void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions //## 3D Box ## //######################## -static void sp_3dbox_toggle_vp_changed( GtkToggleAction *act, gpointer data ) +static void sp_3dbox_toggle_vp_changed (GtkToggleAction *act, GObject *dataKludge, Box3D::Axis axis) { - SPDocument *document = sp_desktop_document (inkscape_active_desktop ()); - Box3D::Axis axis = (Box3D::Axis) GPOINTER_TO_INT(data); + SPDesktop *desktop = (SPDesktop *) g_object_get_data (dataKludge, "desktop"); + SPDocument *document = sp_desktop_document (desktop); + Box3D::Perspective3D *persp = document->current_perspective; - if (document->current_perspective) { - document->current_perspective->toggle_boxes (axis); + g_return_if_fail (is_single_axis_direction (axis)); + g_return_if_fail (persp); + + persp->toggle_boxes (axis); + + gchar *str; + switch (axis) { + case Box3D::X: + str = g_strdup ("box3d_angle_x_action"); + break; + case Box3D::Y: + str = g_strdup ("box3d_angle_y_action"); + break; + case Box3D::Z: + str = g_strdup ("box3d_angle_z_action"); + break; + default: + return; + } + GtkAction* angle_action = GTK_ACTION (g_object_get_data (dataKludge, str)); + if (angle_action) { + gtk_action_set_sensitive (angle_action, !persp->get_vanishing_point (axis)->is_finite() ); + } + + // FIXME: Given how it is realized in the other tools, this is probably not the right way to do it, + // but without the if construct, we get continuous segfaults. Needs further investigation. + if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) { + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX, + _("3D Box: Change perspective")); + } +} + +static void sp_3dbox_toggle_vp_x_changed(GtkToggleAction *act, GObject *dataKludge) +{ + sp_3dbox_toggle_vp_changed (act, dataKludge, Box3D::X); +} + +static void sp_3dbox_toggle_vp_y_changed(GtkToggleAction *act, GObject *dataKludge) +{ + sp_3dbox_toggle_vp_changed (act, dataKludge, Box3D::Y); +} + +static void sp_3dbox_toggle_vp_z_changed(GtkToggleAction *act, GObject *dataKludge) +{ + sp_3dbox_toggle_vp_changed (act, dataKludge, Box3D::Z); +} + +static void sp_3dbox_vp_angle_changed(GtkAdjustment *adj, GObject *dataKludge, Box3D::Axis axis ) +{ + SPDesktop *desktop = (SPDesktop *) g_object_get_data(dataKludge, "desktop"); + Box3D::Perspective3D *persp = sp_desktop_document (desktop)->current_perspective; + + if (persp) { + double angle = adj->value * M_PI/180; + persp->set_infinite_direction (axis, NR::Point (cos (angle), sin (angle))); + + // FIXME: See comment above; without the if construct we get segfaults during undo. + if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) { + sp_document_maybe_done(sp_desktop_document(desktop), "perspectiveangle", SP_VERB_CONTEXT_3DBOX, + _("3D Box: Change perspective")); + } + } + //g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(FALSE)); +} + +static void sp_3dbox_vpx_angle_changed(GtkAdjustment *adj, GObject *dataKludge ) +{ + sp_3dbox_vp_angle_changed (adj, dataKludge, Box3D::X); +} + +static void sp_3dbox_vpy_angle_changed(GtkAdjustment *adj, GObject *dataKludge ) +{ + sp_3dbox_vp_angle_changed (adj, dataKludge, Box3D::Y); +} + +static void sp_3dbox_vpz_angle_changed(GtkAdjustment *adj, GObject *dataKludge ) +{ + sp_3dbox_vp_angle_changed (adj, dataKludge, Box3D::Z); +} + +// normalize angle so that it lies in the interval [0,360] +static double sp_3dbox_normalize_angle (double a) { + double angle = a + ((int) (a/360.0))*360; + if (angle < 0) { + angle += 360.0; + } + return angle; +} + +static void sp_3dbox_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name, + gchar const *old_value, gchar const *new_value, + bool is_interactive, gpointer data) +{ + GtkWidget *tbl = GTK_WIDGET(data); + + // FIXME: if we check for "freeze" as in other tools, no action is performed at all ... + /*** + // quit if run by the _changed callbacks + if (g_object_get_data(G_OBJECT(tbl), "freeze")) { + return; + } + + // in turn, prevent callbacks from responding + g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE)); + ***/ + + if (!strcmp(name, "inkscape:perspective")) { + GtkAdjustment *adj = 0; + double angle; + SPDesktop *desktop = (SPDesktop *) g_object_get_data(G_OBJECT(tbl), "desktop"); + Box3D::Perspective3D *persp = sp_desktop_document (desktop)->current_perspective; + + adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_x")); + angle = sp_3dbox_normalize_angle (persp->get_vanishing_point (Box3D::X)->get_angle()); + gtk_adjustment_set_value(adj, angle); + + adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_y")); + angle = sp_3dbox_normalize_angle (persp->get_vanishing_point (Box3D::Y)->get_angle()); + gtk_adjustment_set_value(adj, angle); + + adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_z")); + angle = sp_3dbox_normalize_angle (persp->get_vanishing_point (Box3D::Z)->get_angle()); + gtk_adjustment_set_value(adj, angle); + } +} + +static Inkscape::XML::NodeEventVector sp_3dbox_tb_repr_events = +{ + NULL, /* child_added */ + NULL, /* child_removed */ + sp_3dbox_tb_event_attr_changed, + NULL, /* content_changed */ + NULL /* order_changed */ +}; + +/** + * \param selection Should not be NULL. + */ +static void +sp_3dbox_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) +{ + Inkscape::XML::Node *repr = NULL; + purge_repr_listener(tbl, tbl); + + SPItem *item = selection->singleItem(); + if (item) { + repr = SP_OBJECT_REPR(item); + if (repr) { + g_object_set_data(tbl, "repr", repr); + Inkscape::GC::anchor(repr); + sp_repr_add_listener(repr, &sp_3dbox_tb_repr_events, tbl); + sp_repr_synthesize_events(repr, &sp_3dbox_tb_repr_events, tbl); + } } - } static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) { + EgeAdjustmentAction* eact = 0; SPDocument *document = sp_desktop_document (desktop); + Box3D::Perspective3D *persp = document->current_perspective; bool toggled = false; + + /* angle of VP in X direction */ + eact = create_adjustment_action("3DBoxPosAngleXAction", + _("Angle X:"), _("Angle of infinite vanishing point in X direction"), + "tools.shapes.3dbox", "dir_vp_x", persp->get_vanishing_point (Box3D::X)->get_angle(), + GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL, + 0.0, 360.0, 1.0, 10.0, + 0, 0, 0, // labels, values, G_N_ELEMENTS(labels), + sp_3dbox_vpx_angle_changed, + 0.1, 1); + gtk_action_group_add_action(mainActions, GTK_ACTION(eact)); + g_object_set_data(holder, "box3d_angle_x_action", eact); + if (!persp->get_vanishing_point (Box3D::X)->is_finite()) { + gtk_action_set_sensitive(GTK_ACTION(eact), TRUE); + } else { + gtk_action_set_sensitive(GTK_ACTION(eact), FALSE); + } + /* toggle VP in X direction */ { - InkToggleAction* act = ink_toggle_action_new( "3DBoxVPXAction", + InkToggleAction* act = ink_toggle_action_new("3DBoxVPXAction", _("Toggle VP in X direction"), _("Toggle VP in X direction between 'finite' and 'infinite' (=parallel)"), "toggle_vp_x", - Inkscape::ICON_SIZE_DECORATION ); - gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - if (document->current_perspective) { - toggled = !document->current_perspective->get_vanishing_point(Box3D::X)->is_finite(); + Inkscape::ICON_SIZE_DECORATION); + gtk_action_group_add_action(mainActions, GTK_ACTION(act)); + if (persp) { + toggled = !persp->get_vanishing_point(Box3D::X)->is_finite(); } - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled ); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), toggled); /* we connect the signal after setting the state to avoid switching the state again */ - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::X)); + g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_x_changed), holder); + } + + /* angle of VP in Y direction */ + eact = create_adjustment_action("3DBoxPosAngleYAction", + _("Angle Y:"), _("Angle of infinite vanishing point in Y direction"), + "tools.shapes.3dbox", "dir_vp_y", persp->get_vanishing_point (Box3D::Y)->get_angle(), + GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL, + 0.0, 360.0, 1.0, 10.0, + 0, 0, 0, // labels, values, G_N_ELEMENTS(labels), + sp_3dbox_vpy_angle_changed, + 0.1, 1); + gtk_action_group_add_action(mainActions, GTK_ACTION(eact)); + g_object_set_data(holder, "box3d_angle_y_action", eact); + if (!persp->get_vanishing_point (Box3D::Y)->is_finite()) { + gtk_action_set_sensitive(GTK_ACTION(eact), TRUE); + } else { + gtk_action_set_sensitive(GTK_ACTION(eact), FALSE); } /* toggle VP in Y direction */ { - InkToggleAction* act = ink_toggle_action_new( "3DBoxVPYAction", - _("Toggle VP in Y direction"), - _("Toggle VP in Y direction between 'finite' and 'infinite' (=parallel)"), - "toggle_vp_y", - Inkscape::ICON_SIZE_DECORATION ); - gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - if (document->current_perspective) { - toggled = !document->current_perspective->get_vanishing_point(Box3D::Y)->is_finite(); - } - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled ); + InkToggleAction* act = ink_toggle_action_new("3DBoxVPYAction", + _("Toggle VP in Y direction"), + _("Toggle VP in Y direction between 'finite' and 'infinite' (=parallel)"), + "toggle_vp_y", + Inkscape::ICON_SIZE_DECORATION); + gtk_action_group_add_action(mainActions, GTK_ACTION(act)); + if (persp) { + toggled = !persp->get_vanishing_point(Box3D::Y)->is_finite(); + } + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), toggled); /* we connect the signal after setting the state to avoid switching the state again */ - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::Y)); + g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_y_changed), holder); + } + + /* angle of VP in Z direction */ + eact = create_adjustment_action("3DBoxPosAngleZAction", + _("Angle Z:"), _("Angle of infinite vanishing point in Z direction"), + "tools.shapes.3dbox", "dir_vp_z", persp->get_vanishing_point (Box3D::Z)->get_angle(), + GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL, + 0.0, 360.0, 1.0, 10.0, + 0, 0, 0, // labels, values, G_N_ELEMENTS(labels), + sp_3dbox_vpz_angle_changed, + 0.1, 1); + + gtk_action_group_add_action(mainActions, GTK_ACTION(eact)); + g_object_set_data(holder, "box3d_angle_z_action", eact); + if (!persp->get_vanishing_point (Box3D::Z)->is_finite()) { + gtk_action_set_sensitive(GTK_ACTION(eact), TRUE); + } else { + gtk_action_set_sensitive(GTK_ACTION(eact), FALSE); } /* toggle VP in Z direction */ { - InkToggleAction* act = ink_toggle_action_new( "3DBoxVPZAction", - _("Toggle VP in Z direction"), - _("Toggle VP in Z direction between 'finite' and 'infinite' (=parallel)"), - "toggle_vp_z", - Inkscape::ICON_SIZE_DECORATION ); - gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - if (document->current_perspective) { - toggled = !document->current_perspective->get_vanishing_point(Box3D::Z)->is_finite(); + InkToggleAction* act = ink_toggle_action_new("3DBoxVPZAction", + _("Toggle VP in Z direction"), + _("Toggle VP in Z direction between 'finite' and 'infinite' (=parallel)"), + "toggle_vp_z", + Inkscape::ICON_SIZE_DECORATION); + gtk_action_group_add_action(mainActions, GTK_ACTION(act)); + if (persp) { + toggled = !persp->get_vanishing_point(Box3D::Z)->is_finite(); } /* we connect the signal after setting the state to avoid switching the state again */ - gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled ); - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::Z)); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), toggled); + g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_z_changed), holder); } + + sigc::connection *connection = new sigc::connection( + sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_3dbox_toolbox_selection_changed), (GObject *)holder)) + ); + g_signal_connect(holder, "destroy", G_CALLBACK(delete_connection), connection); + g_signal_connect(holder, "destroy", G_CALLBACK(purge_repr_listener), holder); } //########################