From: cilix42 Date: Tue, 8 Jan 2008 22:39:39 +0000 (+0000) Subject: Enable 3D box toolbar X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=3f9c2aaadaf4dd5bb8f29d92098dcb6805ca9d97;p=inkscape.git Enable 3D box toolbar --- diff --git a/src/axis-manip.h b/src/axis-manip.h index 8fb8fdc8e..e5cc963ba 100644 --- a/src/axis-manip.h +++ b/src/axis-manip.h @@ -12,15 +12,14 @@ #ifndef SEEN_AXIS_MANIP_H #define SEEN_AXIS_MANIP_H -#include // g_assert() #include #include "libnr/nr-point.h" namespace Proj { enum VPState { - VP_FINITE = 0, - VP_INFINITE + FINITE = 0, + INFINITE }; // The X-/Y-/Z-axis corresponds to the first/second/third digit diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp index 83952d5ef..78e80be45 100644 --- a/src/box3d-context.cpp +++ b/src/box3d-context.cpp @@ -455,37 +455,51 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven case GDK_bracketright: persp3d_rotate_VP (inkscape_active_document()->current_persp3d, Proj::X, -180/snaps, MOD__ALT); + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX, + _("Change perspective (angle of PLs)")); ret = true; break; case GDK_bracketleft: persp3d_rotate_VP (inkscape_active_document()->current_persp3d, Proj::X, 180/snaps, MOD__ALT); + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX, + _("Change perspective (angle of PLs)")); ret = true; break; case GDK_parenright: persp3d_rotate_VP (inkscape_active_document()->current_persp3d, Proj::Y, -180/snaps, MOD__ALT); + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX, + _("Change perspective (angle of PLs)")); ret = true; break; case GDK_parenleft: persp3d_rotate_VP (inkscape_active_document()->current_persp3d, Proj::Y, 180/snaps, MOD__ALT); + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX, + _("Change perspective (angle of PLs)")); ret = true; break; case GDK_braceright: persp3d_rotate_VP (inkscape_active_document()->current_persp3d, Proj::Z, -180/snaps, MOD__ALT); + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX, + _("Change perspective (angle of PLs)")); ret = true; break; case GDK_braceleft: persp3d_rotate_VP (inkscape_active_document()->current_persp3d, Proj::Z, 180/snaps, MOD__ALT); + sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX, + _("Change perspective (angle of PLs)")); ret = true; break; case GDK_O: - Box3D::create_canvas_point(persp3d_get_VP(inkscape_active_document()->current_persp3d, Proj::W).affine(), - 6, 0xff00ff00); + if (MOD__CTRL && MOD__SHIFT) { + Box3D::create_canvas_point(persp3d_get_VP(inkscape_active_document()->current_persp3d, Proj::W).affine(), + 6, 0xff00ff00); + } ret = true; break; diff --git a/src/persp3d.cpp b/src/persp3d.cpp index 27701c80d..c2bbb5b46 100644 --- a/src/persp3d.cpp +++ b/src/persp3d.cpp @@ -309,7 +309,7 @@ persp3d_toggle_VP (Persp3D *persp, Proj::Axis axis, bool set_undo) { // On the other hand, vp_drag_sel_modified() would update all boxes; // here we can confine ourselves to the boxes of this particular perspective. persp3d_update_box_reprs (persp); - persp3d_update_z_orders (persp); + //persp3d_update_z_orders (persp); SP_OBJECT(persp)->updateRepr(SP_OBJECT_WRITE_EXT); if (set_undo) { sp_document_done(sp_desktop_document(inkscape_active_desktop()), SP_VERB_CONTEXT_3DBOX, @@ -329,7 +329,7 @@ persp3d_toggle_VPs (std::set p, Proj::Axis axis) { void persp3d_set_VP_state (Persp3D *persp, Proj::Axis axis, Proj::VPState state) { - if (persp3d_VP_is_finite(persp, axis) != (state == Proj::VP_FINITE)) { + if (persp3d_VP_is_finite(persp, axis) != (state == Proj::FINITE)) { persp3d_toggle_VP(persp, axis); } } @@ -348,7 +348,7 @@ persp3d_rotate_VP (Persp3D *persp, Proj::Axis axis, double angle, bool alt_press persp->tmat.set_infinite_direction (axis, a); persp3d_update_box_reprs (persp); - persp3d_update_z_orders (persp); + //persp3d_update_z_orders (persp); SP_OBJECT(persp)->updateRepr(SP_OBJECT_WRITE_EXT); } @@ -488,6 +488,7 @@ persp3d_update_box_reprs (Persp3D *persp) { //g_print ("Requesting repr update for %d boxes in the perspective.\n", persp->boxes.size()); for (std::vector::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) { SP_OBJECT(*i)->updateRepr(SP_OBJECT_WRITE_EXT); + box3d_set_z_orders(*i); } } diff --git a/src/persp3d.h b/src/persp3d.h index c74af2e29..ce4587f62 100644 --- a/src/persp3d.h +++ b/src/persp3d.h @@ -23,8 +23,9 @@ #include #include "sp-item.h" #include "transf_mat_3x4.h" +#include "document.h" +#include "inkscape.h" -class SPDocument; class SPBox3D; class Box3DContext; @@ -49,7 +50,12 @@ struct Persp3DClass { GType persp3d_get_type (void); // FIXME: Make more of these inline! -inline Proj::Pt2 persp3d_get_VP (Persp3D *persp, Proj::Axis axis) { return persp->tmat.column(axis); } +inline Persp3D * persp3d_get_from_repr (Inkscape::XML::Node *repr) { + return SP_PERSP3D(SP_ACTIVE_DOCUMENT->getObjectByRepr(repr)); +} +inline Proj::Pt2 persp3d_get_VP (Persp3D *persp, Proj::Axis axis) { + return persp->tmat.column(axis); +} NR::Point persp3d_get_PL_dir_from_pt (Persp3D *persp, NR::Point const &pt, Proj::Axis axis); // convenience wrapper around the following two NR::Point persp3d_get_finite_dir (Persp3D *persp, NR::Point const &pt, Proj::Axis axis); NR::Point persp3d_get_infinite_dir (Persp3D *persp, Proj::Axis axis); diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 3c35d0cfe..37f122ca7 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -312,15 +312,14 @@ static gchar const * ui_descr = " " " " - " " - " " + " " + " " " " - " " - " " - " " - " " - " " + " " + " " " " + " " + " " " " " " @@ -2343,228 +2342,224 @@ static void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions //## 3D Box ## //######################## -static void box3d_toggle_vp_changed (GtkToggleAction *act, GObject *dataKludge, Proj::Axis axis) -{ - SPDesktop *desktop = (SPDesktop *) g_object_get_data (dataKludge, "desktop"); - SPDocument *document = sp_desktop_document (desktop); - // FIXME: Make sure document->current_persp3d is set correctly! - Persp3D *persp = document->current_persp3d; +// normalize angle so that it lies in the interval [0,360] +static double box3d_normalize_angle (double a) { + double angle = a + ((int) (a/360.0))*360; + if (angle < 0) { + angle += 360.0; + } + return angle; +} - g_return_if_fail (persp); +static void +box3d_set_button_and_adjustment(Persp3D *persp, Proj::Axis axis, + GtkAdjustment *adj, GtkAction *act, GtkToggleAction *tact) { + // TODO: Take all selected perspectives into account but don't touch the state button if not all of them + // have the same state (otherwise a call to box3d_vp_z_state_changed() is triggered and the states + // are reset). + bool is_infinite = !persp3d_VP_is_finite(persp, axis); + + if (is_infinite) { + gtk_toggle_action_set_active(tact, TRUE); + gtk_action_set_sensitive(act, TRUE); + + double angle = persp3d_get_infinite_angle(persp, axis); + if (angle != NR_HUGE) { // FIXME: We should catch this error earlier (don't show the spinbutton at all) + gtk_adjustment_set_value(adj, box3d_normalize_angle(angle)); + } + } else { + gtk_toggle_action_set_active(tact, FALSE); + gtk_action_set_sensitive(act, FALSE); + } +} - // quit if run by the attr_changed listener - if (g_object_get_data(dataKludge, "freeze")) { +static void +box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data) { + if (!persp_repr) { + g_print ("No perspective given to box3d_resync_toolbar().\n"); return; } - // in turn, prevent listener from responding - g_object_set_data(dataKludge, "freeze", GINT_TO_POINTER(TRUE)); - - persp3d_set_VP_state(persp, axis, (gtk_toggle_action_get_active(act) ? Proj::VP_INFINITE : Proj::VP_FINITE)); + GtkWidget *tbl = GTK_WIDGET(data); + GtkAdjustment *adj = 0; + GtkAction *act = 0; + GtkToggleAction *tact = 0; + Persp3D *persp = persp3d_get_from_repr(persp_repr); + { + adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "box3d_angle_x")); + act = GTK_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_angle_x_action")); + tact = &INK_TOGGLE_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_vp_x_state_action"))->action; - // FIXME: Can we merge this functionality with the one in box3d_persp_tb_event_attr_changed()? - gchar *str; - switch (axis) { - case Proj::X: - str = g_strdup ("box3d_angle_x_action"); - break; - case Proj::Y: - str = g_strdup ("box3d_angle_y_action"); - break; - case Proj::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, !persp3d_VP_is_finite(persp, axis)); + box3d_set_button_and_adjustment(persp, Proj::X, adj, act, tact); } + { + adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "box3d_angle_y")); + act = GTK_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_angle_y_action")); + tact = &INK_TOGGLE_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_vp_y_state_action"))->action; - sp_document_maybe_done(sp_desktop_document(desktop), "toggle_vp", SP_VERB_CONTEXT_3DBOX, - _("3D Box: Toggle VP")); - //sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX,_("3D Box: Toggle VP")); + box3d_set_button_and_adjustment(persp, Proj::Y, adj, act, tact); + } + { + adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "box3d_angle_z")); + act = GTK_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_angle_z_action")); + tact = &INK_TOGGLE_ACTION(g_object_get_data(G_OBJECT(tbl), "box3d_vp_z_state_action"))->action; - g_object_set_data(dataKludge, "freeze", GINT_TO_POINTER(FALSE)); + box3d_set_button_and_adjustment(persp, Proj::Z, adj, act, tact); + } } -static void box3d_toggle_vp_x_changed(GtkToggleAction *act, GObject *dataKludge) +static void box3d_persp_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name, + gchar const */*old_value*/, gchar const */*new_value*/, + bool /*is_interactive*/, gpointer data) { - box3d_toggle_vp_changed (act, dataKludge, Proj::X); + GtkWidget *tbl = GTK_WIDGET(data); + + // quit if run by the attr_changed listener + // note: it used to work without the differently called freeze_ attributes (here and in + // box3d_angle_value_changed()) but I now it doesn't so I'm leaving them in for now + if (g_object_get_data(G_OBJECT(tbl), "freeze_angle")) { + return; + } + + // set freeze so that it can be caught in box3d_angle_z_value_changed() (to avoid calling + // sp_document_maybe_done() when the document is undo insensitive) + g_object_set_data(G_OBJECT(tbl), "freeze_attr", GINT_TO_POINTER(TRUE)); + + // TODO: Only update the appropriate part of the toolbar +// if (!strcmp(name, "inkscape:vp_z")) { + box3d_resync_toolbar(repr, G_OBJECT(tbl)); +// } + + Persp3D *persp = persp3d_get_from_repr(repr); + persp3d_update_box_reprs(persp); + + g_object_set_data(G_OBJECT(tbl), "freeze_attr", GINT_TO_POINTER(FALSE)); } -static void box3d_toggle_vp_y_changed(GtkToggleAction *act, GObject *dataKludge) +static Inkscape::XML::NodeEventVector box3d_persp_tb_repr_events = { - box3d_toggle_vp_changed (act, dataKludge, Proj::Y); -} + NULL, /* child_added */ + NULL, /* child_removed */ + box3d_persp_tb_event_attr_changed, + NULL, /* content_changed */ + NULL /* order_changed */ +}; -static void box3d_toggle_vp_z_changed(GtkToggleAction *act, GObject *dataKludge) +/** + * \param selection Should not be NULL. + */ +// FIXME: This should rather be put into persp3d-reference.cpp or something similar so that it reacts upon each +// Change of the perspective, and not of the current selection (but how to refer to the toolbar then?) +static void +box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) { - box3d_toggle_vp_changed (act, dataKludge, Proj::Z); + // Here the following should be done: If all selected boxes have finite VPs in a certain direction, + // disable the angle entry fields for this direction (otherwise entering a value in them should only + // update the perspectives with infinite VPs and leave the other ones untouched). + + Inkscape::XML::Node *persp_repr = NULL; + purge_repr_listener(tbl, tbl); + + SPItem *item = selection->singleItem(); + if (item && SP_IS_BOX3D(item)) { + // FIXME: Also deal with multiple selected boxes + SPBox3D *box = SP_BOX3D(item); + Persp3D *persp = box3d_get_perspective(box); + persp_repr = SP_OBJECT_REPR(persp); + if (persp_repr) { + g_object_set_data(tbl, "repr", persp_repr); + Inkscape::GC::anchor(persp_repr); + sp_repr_add_listener(persp_repr, &box3d_persp_tb_repr_events, tbl); + sp_repr_synthesize_events(persp_repr, &box3d_persp_tb_repr_events, tbl); + } + + inkscape_active_document()->current_persp3d = persp3d_get_from_repr(persp_repr); + prefs_set_string_attribute("tools.shapes.3dbox", "persp", persp_repr->attribute("id")); + + box3d_resync_toolbar(persp_repr, tbl); + } } -static void box3d_vp_angle_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis axis ) +static void +box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis axis) { - SPDesktop *desktop = (SPDesktop *) g_object_get_data(dataKludge, "desktop"); - Persp3D *persp = sp_desktop_document (desktop)->current_persp3d; + SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" ); + SPDocument *document = sp_desktop_document(desktop); // quit if run by the attr_changed listener - if (g_object_get_data(dataKludge, "freeze")) { + // note: it used to work without the differently called freeze_ attributes (here and in + // box3d_persp_tb_event_attr_changed()) but I now it doesn't so I'm leaving them in for now + if (g_object_get_data( dataKludge, "freeze_attr" )) { return; } // in turn, prevent listener from responding - g_object_set_data(dataKludge, "freeze", GINT_TO_POINTER(TRUE)); + g_object_set_data(dataKludge, "freeze_angle", GINT_TO_POINTER(TRUE)); - if (persp) { - double angle = adj->value; - // FIXME: Shouldn't we set the angle via the SVG attributes of the perspective instead of directly? - if (persp3d_VP_is_finite(persp, axis)) { - return; - } - persp->tmat.set_infinite_direction (axis, angle); - persp3d_update_box_reprs (persp); - - sp_document_maybe_done(sp_desktop_document(desktop), "perspectiveangle", SP_VERB_CONTEXT_3DBOX, - _("3D Box: Change perspective")); + //Persp3D *persp = document->current_persp3d; + std::set sel_persps = persp3d_currently_selected_persps (inkscape_active_event_context()); + if (sel_persps.empty()) { + // this can happen when the document is created; we silently ignore it + return; } + Persp3D *persp = *(sel_persps.begin()); - g_object_set_data(dataKludge, "freeze", GINT_TO_POINTER(FALSE)); + persp->tmat.set_infinite_direction (axis, adj->value); + SP_OBJECT(persp)->updateRepr(); + + // TODO: use the correct axis here, too + sp_document_maybe_done(document, "perspangle", SP_VERB_CONTEXT_3DBOX, _("3D Box: Change perspective (angle of infinite axis)")); + + g_object_set_data( dataKludge, "freeze_angle", GINT_TO_POINTER(FALSE) ); } -static void box3d_vpx_angle_changed(GtkAdjustment *adj, GObject *dataKludge ) + +static void +box3d_angle_x_value_changed(GtkAdjustment *adj, GObject *dataKludge) { - box3d_vp_angle_changed (adj, dataKludge, Proj::X); + box3d_angle_value_changed(adj, dataKludge, Proj::X); } -static void box3d_vpy_angle_changed(GtkAdjustment *adj, GObject *dataKludge ) +static void +box3d_angle_y_value_changed(GtkAdjustment *adj, GObject *dataKludge) { - box3d_vp_angle_changed (adj, dataKludge, Proj::Y); + box3d_angle_value_changed(adj, dataKludge, Proj::Y); } -static void box3d_vpz_angle_changed(GtkAdjustment *adj, GObject *dataKludge ) +static void +box3d_angle_z_value_changed(GtkAdjustment *adj, GObject *dataKludge) { - box3d_vp_angle_changed (adj, dataKludge, Proj::Z); + box3d_angle_value_changed(adj, dataKludge, Proj::Z); } -// normalize angle so that it lies in the interval [0,360] -static double box3d_normalize_angle (double a) { - double angle = a + ((int) (a/360.0))*360; - if (angle < 0) { - angle += 360.0; - } - return angle; -} -static void box3d_persp_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name, - gchar const *old_value, gchar const *new_value, - bool is_interactive, gpointer data) +static void box3d_vp_state_changed( GtkToggleAction *act, GtkAction *box3d_angle, Proj::Axis axis ) { - 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)); - - GtkAdjustment *adj = 0; - double angle; - SPDesktop *desktop = (SPDesktop *) g_object_get_data(G_OBJECT(tbl), "desktop"); - // FIXME: Get the persp from the box (should be the same, but ...) - Persp3D *persp = sp_desktop_document (desktop)->current_persp3d; - if (!strcmp(name, "inkscape:vp_x")) { - GtkAction* act = GTK_ACTION (gtk_object_get_data (GTK_OBJECT(tbl), "box3d_angle_x_action")); - GtkToggleAction* tact = GTK_TOGGLE_ACTION (gtk_object_get_data (GTK_OBJECT(tbl), "toggle_vp_x_action")); - if (!persp3d_VP_is_finite(persp, Proj::X)) { - gtk_action_set_sensitive(GTK_ACTION(act), TRUE); - gtk_toggle_action_set_active(tact, TRUE); - } else { - gtk_action_set_sensitive(GTK_ACTION(act), FALSE); - gtk_toggle_action_set_active(tact, FALSE); - } - - adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_x")); - angle = persp3d_get_infinite_angle(persp, Proj::X); - if (angle != NR_HUGE) { // FIXME: We should catch this error earlier (don't show the spinbutton at all) - gtk_adjustment_set_value(adj, box3d_normalize_angle(angle)); - } - } - - if (!strcmp(name, "inkscape:vp_y")) { - GtkAction* act = GTK_ACTION (gtk_object_get_data (GTK_OBJECT(tbl), "box3d_angle_y_action")); - GtkToggleAction* tact = GTK_TOGGLE_ACTION (gtk_object_get_data (GTK_OBJECT(tbl), "toggle_vp_y_action")); - if (!persp3d_VP_is_finite(persp, Proj::Y)) { - gtk_action_set_sensitive(GTK_ACTION(act), TRUE); - gtk_toggle_action_set_active(tact, TRUE); - } else { - gtk_action_set_sensitive(GTK_ACTION(act), FALSE); - gtk_toggle_action_set_active(tact, FALSE); - } - - adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_y")); - angle = persp3d_get_infinite_angle(persp, Proj::Y); - if (angle != NR_HUGE) { // FIXME: We should catch this error earlier (don't show the spinbutton at all) - gtk_adjustment_set_value(adj, box3d_normalize_angle(angle)); - } + // TODO: Take all selected perspectives into account + std::set sel_persps = persp3d_currently_selected_persps (inkscape_active_event_context()); + if (sel_persps.empty()) { + // this can happen when the document is created; we silently ignore it + return; } + Persp3D *persp = *(sel_persps.begin()); - if (!strcmp(name, "inkscape:vp_z")) { - GtkAction* act = GTK_ACTION (gtk_object_get_data (GTK_OBJECT(tbl), "box3d_angle_z_action")); - GtkToggleAction* tact = GTK_TOGGLE_ACTION (gtk_object_get_data (GTK_OBJECT(tbl), "toggle_vp_z_action")); - if (!persp3d_VP_is_finite(persp, Proj::Z)) { - gtk_action_set_sensitive(GTK_ACTION(act), TRUE); - gtk_toggle_action_set_active(tact, TRUE); - } else { - gtk_action_set_sensitive(GTK_ACTION(act), FALSE); - gtk_toggle_action_set_active(tact, FALSE); - } - - adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_z")); - angle = persp3d_get_infinite_angle(persp, Proj::Z); - if (angle != NR_HUGE) { // FIXME: We should catch this error earlier (don't show the spinbutton at all) - gtk_adjustment_set_value(adj, box3d_normalize_angle(angle)); - } - } - - //g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(FALSE)); + bool set_infinite = gtk_toggle_action_get_active(act); + persp3d_set_VP_state (persp, axis, set_infinite ? Proj::INFINITE : Proj::FINITE); } -static Inkscape::XML::NodeEventVector box3d_persp_tb_repr_events = +static void box3d_vp_x_state_changed( GtkToggleAction *act, GtkAction *box3d_angle ) { - NULL, /* child_added */ - NULL, /* child_removed */ - box3d_persp_tb_event_attr_changed, - NULL, /* content_changed */ - NULL /* order_changed */ -}; + box3d_vp_state_changed(act, box3d_angle, Proj::X); +} -/** - * \param selection Should not be NULL. - */ -// FIXME: This should rather be put into persp3d-reference.cpp or something similar so that it reacts upon each -// Change of the perspective, and not of the current selection (but how to refer to the toolbar then?) -static void -box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) +static void box3d_vp_y_state_changed( GtkToggleAction *act, GtkAction *box3d_angle ) { - Inkscape::XML::Node *repr = NULL; - purge_repr_listener(tbl, tbl); + box3d_vp_state_changed(act, box3d_angle, Proj::Y); +} - SPItem *item = selection->singleItem(); - if (item && SP_IS_BOX3D(item)) { - //repr = SP_OBJECT_REPR(item); - repr = SP_OBJECT_REPR(SP_BOX3D(item)->persp_ref->getObject()); - if (repr) { - g_object_set_data(tbl, "repr", repr); - Inkscape::GC::anchor(repr); - sp_repr_add_listener(repr, &box3d_persp_tb_repr_events, tbl); - sp_repr_synthesize_events(repr, &box3d_persp_tb_repr_events, tbl); - } - } +static void box3d_vp_z_state_changed( GtkToggleAction *act, GtkAction *box3d_angle ) +{ + box3d_vp_state_changed(act, box3d_angle, Proj::Z); } static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder) @@ -2572,101 +2567,127 @@ static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, EgeAdjustmentAction* eact = 0; SPDocument *document = sp_desktop_document (desktop); Persp3D *persp = document->current_persp3d; - bool toggled = false; - - /* angle of VP in X direction */ - eact = create_adjustment_action("3DBoxPosAngleXAction", - _("Angle X"), _("Angle X:"), _("Angle of infinite vanishing point in X direction"), - "tools.shapes.3dbox", "dir_vp_x", persp3d_get_infinite_angle(persp, Proj::X), - GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-box3d", - -360.0, 360.0, 1.0, 10.0, - 0, 0, 0, // labels, values, G_N_ELEMENTS(labels), - box3d_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); + + EgeAdjustmentAction* box3d_angle_x = 0; + EgeAdjustmentAction* box3d_angle_y = 0; + EgeAdjustmentAction* box3d_angle_z = 0; + + /* Angle X */ + { + gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 }; + gdouble values[] = {-90, -60, -30, 0, 30, 60, 90}; + eact = create_adjustment_action( "3DBoxAngleXAction", + _("Angle in X direction"), _("Angle X:"), + // Translators: PL is short for 'perspective line' + _("Angle of PLs in X direction"), + "tools.shapes.3dbox", "box3d_angle_x", 30, + GTK_WIDGET(desktop->canvas), NULL, holder, TRUE, "altx-box3d", + -360.0, 360.0, 1.0, 10.0, + labels, values, G_N_ELEMENTS(labels), + box3d_angle_x_value_changed ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + g_object_set_data( holder, "box3d_angle_x_action", eact ); + box3d_angle_x = eact; + } + if (!persp3d_VP_is_finite(persp, Proj::X)) { - gtk_action_set_sensitive(GTK_ACTION(eact), TRUE); + gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } else { - gtk_action_set_sensitive(GTK_ACTION(eact), FALSE); + gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); + } + + + /* VP X state */ + { + InkToggleAction* act = ink_toggle_action_new( "3DBoxVPXStateAction", + // Translators: VP is short for 'vanishing point' + _("State of 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 ) ); + g_object_set_data( holder, "box3d_vp_x_state_action", act ); + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_x_state_changed), box3d_angle_x ); + gtk_action_set_sensitive( GTK_ACTION(box3d_angle_x), !prefs_get_int_attribute( "tools.shapes.3dbox", "vp_x_state", 1 ) ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.shapes.3dbox", "vp_x_state", 1 ) ); } - /* toggle VP in X direction */ + /* Angle Y */ { - 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)); - g_object_set_data(holder, "toggle_vp_x_action", act); - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), !persp3d_VP_is_finite(persp, Proj::X)); - /* we connect the signal after setting the state to avoid switching the state again */ - g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(box3d_toggle_vp_x_changed), holder); - } - - /* angle of VP in Y direction */ - eact = create_adjustment_action("3DBoxPosAngleYAction", - _("Angle Y"), _("Angle Y:"), _("Angle of infinite vanishing point in Y direction"), - "tools.shapes.3dbox", "dir_vp_y", persp3d_get_infinite_angle(persp, Proj::Y), - GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL, - -360.0, 360.0, 1.0, 10.0, - 0, 0, 0, // labels, values, G_N_ELEMENTS(labels), - box3d_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); + gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 }; + gdouble values[] = {-90, -60, -30, 0, 30, 60, 90}; + eact = create_adjustment_action( "3DBoxAngleYAction", + _("Angle in Y direction"), _("Angle Y:"), + // Translators: PL is short for 'perspective line' + _("Angle of PLs in Y direction"), + "tools.shapes.3dbox", "box3d_angle_y", 30, + GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL, + -360.0, 360.0, 1.0, 10.0, + labels, values, G_N_ELEMENTS(labels), + box3d_angle_y_value_changed ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + g_object_set_data( holder, "box3d_angle_y_action", eact ); + box3d_angle_y = eact; + } + if (!persp3d_VP_is_finite(persp, Proj::Y)) { - gtk_action_set_sensitive(GTK_ACTION(eact), TRUE); + gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } else { - gtk_action_set_sensitive(GTK_ACTION(eact), FALSE); + gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); + } + + /* VP Y state */ + { + InkToggleAction* act = ink_toggle_action_new( "3DBoxVPYStateAction", + // Translators: VP is short for 'vanishing point' + _("State of 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 ) ); + g_object_set_data( holder, "box3d_vp_y_state_action", act ); + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_y_state_changed), box3d_angle_y ); + gtk_action_set_sensitive( GTK_ACTION(box3d_angle_y), !prefs_get_int_attribute( "tools.shapes.3dbox", "vp_y_state", 1 ) ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.shapes.3dbox", "vp_y_state", 1 ) ); } - /* toggle VP in Y direction */ + /* Angle Z */ { - 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)); - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), !persp3d_VP_is_finite(persp, Proj::Y)); - g_object_set_data(holder, "toggle_vp_y_action", act); - /* we connect the signal after setting the state to avoid switching the state again */ - g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(box3d_toggle_vp_y_changed), holder); - } - - /* angle of VP in Z direction */ - eact = create_adjustment_action("3DBoxPosAngleZAction", - _("Angle Z"), _("Angle Z:"), _("Angle of infinite vanishing point in Z direction"), - "tools.shapes.3dbox", "dir_vp_z", persp3d_get_infinite_angle(persp, Proj::Z), - GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL, - -360.0, 360.0, 1.0, 10.0, - 0, 0, 0, // labels, values, G_N_ELEMENTS(labels), - box3d_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); + gchar const* labels[] = { 0, 0, 0, 0, 0, 0, 0 }; + gdouble values[] = {-90, -60, -30, 0, 30, 60, 90}; + eact = create_adjustment_action( "3DBoxAngleZAction", + _("Angle in Z direction"), _("Angle Z:"), + // Translators: PL is short for 'perspective line' + _("Angle of PLs in Z direction"), + "tools.shapes.3dbox", "box3d_angle_z", 30, + GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL, + -360.0, 360.0, 1.0, 10.0, + labels, values, G_N_ELEMENTS(labels), + box3d_angle_z_value_changed ); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + g_object_set_data( holder, "box3d_angle_z_action", eact ); + box3d_angle_z = eact; + } + if (!persp3d_VP_is_finite(persp, Proj::Z)) { - gtk_action_set_sensitive(GTK_ACTION(eact), TRUE); + gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); } else { - gtk_action_set_sensitive(GTK_ACTION(eact), FALSE); + gtk_action_set_sensitive( GTK_ACTION(eact), FALSE ); } - /* toggle VP in Z direction */ + /* VP Z state */ { - 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)); - - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), !persp3d_VP_is_finite(persp, Proj::Z)); - g_object_set_data(holder, "toggle_vp_z_action", act); - /* we connect the signal after setting the state to avoid switching the state again */ - g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(box3d_toggle_vp_z_changed), holder); + InkToggleAction* act = ink_toggle_action_new( "3DBoxVPZStateAction", + // Translators: VP is short for 'vanishing point' + _("State of 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 ) ); + g_object_set_data( holder, "box3d_vp_z_state_action", act ); + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(box3d_vp_z_state_changed), box3d_angle_z ); + gtk_action_set_sensitive( GTK_ACTION(box3d_angle_z), !prefs_get_int_attribute( "tools.shapes.3dbox", "vp_z_state", 1 ) ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.shapes.3dbox", "vp_z_state", 1 ) ); } sigc::connection *connection = new sigc::connection(