From fc5435340e1a4a9fc54edaf29bc60aed1409582e Mon Sep 17 00:00:00 2001 From: cilix42 Date: Tue, 7 Aug 2007 14:20:02 +0000 Subject: [PATCH] Fix behaviour of toggle buttons (for VP states) in 3D box toolbar; reshape boxes when state of a VP changes --- src/box3d.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/box3d.h | 1 + src/perspective3d.cpp | 10 ++++++++++ src/perspective3d.h | 1 + src/vanishing-point.cpp | 2 +- src/widgets/toolbox.cpp | 29 +++++++---------------------- 6 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/box3d.cpp b/src/box3d.cpp index 0f71a99a8..966d762a1 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -581,12 +581,51 @@ sp_3dbox_move_corner_in_Z_direction (SP3DBox *box, guint id, NR::Point pt, bool box->corners[id ^ Box3D::Y] = pl_one.meet(pl_two); } +static void +sp_3dbox_reshape_edge_after_VP_toggling (SP3DBox *box, const guint corner, const Box3D::Axis axis, Box3D::Perspective3D *persp) +{ + /* Hmm, perhaps we should simply use one of the corners as the pivot point. + But this way we minimize the amount of reshaping. + On second thought, we need to find a way to ensure that all boxes sharing the same + perspective are updated consistently _as a group_. That is, they should also retain + their relative positions towards each other. */ + NR::Maybe pt = sp_3dbox_get_midpoint_between_corners (box, corner, corner ^ axis); + g_return_if_fail (pt); + + Box3D::Axis axis2 = ((axis == Box3D::Y) ? Box3D::X : Box3D::Y); + + Box3D::PerspectiveLine line1 (box->corners[corner], axis2, persp); + Box3D::PerspectiveLine line2 (box->corners[corner ^ axis], axis2, persp); + + Box3D::PerspectiveLine line3 (*pt, axis, persp); + + NR::Point new_corner1 = line1.meet (line3); + NR::Point new_corner2 = line2.meet (line3); + + box->corners[corner] = new_corner1; + box->corners[corner ^ axis] = new_corner2; +} + +void +sp_3dbox_reshape_after_VP_toggling (SP3DBox *box, Box3D::Axis axis) +{ + Box3D::Perspective3D *persp = Box3D::get_persp_of_box (box); + std::pair dirs = Box3D::get_remaining_axes (axis); + + sp_3dbox_reshape_edge_after_VP_toggling (box, 0, axis, persp); + sp_3dbox_reshape_edge_after_VP_toggling (box, 0 ^ dirs.first, axis, persp); + sp_3dbox_reshape_edge_after_VP_toggling (box, 0 ^ dirs.first ^ dirs.second, axis, persp); + sp_3dbox_reshape_edge_after_VP_toggling (box, 0 ^ dirs.second, axis, persp); +} + NR::Maybe sp_3dbox_get_center (SP3DBox *box) { return sp_3dbox_get_midpoint_between_corners (box, 0, 7); } +// TODO: The following function can probably be rewritten in a much more elegant and robust way +// by using projective coordinates for all points and using the cross ratio. NR::Maybe sp_3dbox_get_midpoint_between_corners (SP3DBox *box, guint id_corner1, guint id_corner2) { diff --git a/src/box3d.h b/src/box3d.h index aecc40462..ed563a42e 100644 --- a/src/box3d.h +++ b/src/box3d.h @@ -67,6 +67,7 @@ void sp_3dbox_set_ratios (SP3DBox *box, Box3D::Axis axes = Box3D::XYZ); void sp_3dbox_switch_front_face (SP3DBox *box, Box3D::Axis axis); void sp_3dbox_move_corner_in_XY_plane (SP3DBox *box, guint id, NR::Point pt, Box3D::Axis axes = Box3D::XY); void sp_3dbox_move_corner_in_Z_direction (SP3DBox *box, guint id, NR::Point pt, bool constrained = true); +void sp_3dbox_reshape_after_VP_toggling (SP3DBox *box, Box3D::Axis axis); NR::Maybe sp_3dbox_get_center (SP3DBox *box); NR::Maybe sp_3dbox_get_midpoint_between_corners (SP3DBox *box, guint id_corner1, guint id_corner2); diff --git a/src/perspective3d.cpp b/src/perspective3d.cpp index 421725bdb..c7592a06f 100644 --- a/src/perspective3d.cpp +++ b/src/perspective3d.cpp @@ -320,6 +320,16 @@ Perspective3D::reshape_boxes (Box3D::Axis axes) } } +void +Perspective3D::toggle_boxes (Box3D::Axis axis) +{ + get_vanishing_point (axis)->toggle_parallel(); + for (GSList *i = this->boxes; i != NULL; i = i->next) { + sp_3dbox_reshape_after_VP_toggling (SP_3DBOX (i->data), axis); + } + update_box_reprs(); +} + void Perspective3D::update_box_reprs () { diff --git a/src/perspective3d.h b/src/perspective3d.h index 6c7e77446..4dd309b1f 100644 --- a/src/perspective3d.h +++ b/src/perspective3d.h @@ -40,6 +40,7 @@ public: bool has_box (const SP3DBox *box) const; inline guint number_of_boxes () { return g_slist_length (boxes); } void reshape_boxes (Box3D::Axis axes); + void toggle_boxes (Box3D::Axis axes); // update the shape of boxes after a VP's state was toggled void update_box_reprs (); void update_z_orders (); diff --git a/src/vanishing-point.cpp b/src/vanishing-point.cpp index 0b4140a8b..9b2c45b56 100644 --- a/src/vanishing-point.cpp +++ b/src/vanishing-point.cpp @@ -749,7 +749,7 @@ VPDrag::drawLinesForFace (const SP3DBox *box, Box3D::Axis axis) //, guint corner } } else { // TODO: Draw infinite PLs - g_warning ("Perspective lines for infinite vanishing points are not supported yet.\n"); + //g_warning ("Perspective lines for infinite vanishing points are not supported yet.\n"); } } diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 25c5d2417..b0c8a9b7b 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -2117,26 +2117,8 @@ static void sp_3dbox_toggle_vp_changed( GtkToggleAction *act, gpointer data ) { Box3D::Axis axis = (Box3D::Axis) GPOINTER_TO_INT(data); - GString *pstring; - switch (axis) { - case Box3D::X: - pstring = g_string_new("togglevpx"); - break; - case Box3D::Y: - pstring = g_string_new("togglevpy"); - break; - case Box3D::Z: - pstring = g_string_new("togglevpz"); - break; - default: - g_warning ("Only single axis directions may be used to toggle VPs!\n"); - break; - } - if (Box3D::Perspective3D::current_perspective) { - Box3D::VanishingPoint *vp = Box3D::Perspective3D::current_perspective->get_vanishing_point(axis); - vp->toggle_parallel(); - prefs_set_int_attribute( "tools.shapes.3dbox", pstring->str, vp->is_finite() ? 0 : 1); + Box3D::Perspective3D::current_perspective->toggle_boxes (axis); } } @@ -2206,11 +2188,12 @@ static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction "toggle_vp_x", Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::X)); if (Box3D::Perspective3D::current_perspective) { toggled = !Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::X)->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::X)); } /* toggle VP in Y direction */ @@ -2221,11 +2204,12 @@ static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction "toggle_vp_y", Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::Y)); if (Box3D::Perspective3D::current_perspective) { toggled = !Box3D::Perspective3D::current_perspective->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)); } /* toggle VP in Z direction */ @@ -2236,11 +2220,12 @@ static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction "toggle_vp_z", Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); - g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::Z)); if (Box3D::Perspective3D::current_perspective) { toggled = !Box3D::Perspective3D::current_perspective->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)); } -- 2.30.2