Code

Fix behaviour of toggle buttons (for VP states) in 3D box toolbar; reshape boxes...
authorcilix42 <cilix42@users.sourceforge.net>
Tue, 7 Aug 2007 14:20:02 +0000 (14:20 +0000)
committercilix42 <cilix42@users.sourceforge.net>
Tue, 7 Aug 2007 14:20:02 +0000 (14:20 +0000)
src/box3d.cpp
src/box3d.h
src/perspective3d.cpp
src/perspective3d.h
src/vanishing-point.cpp
src/widgets/toolbox.cpp

index 0f71a99a84f8a059c46709e1f7220d126f6e2190..966d762a1f4bef81361b59b2afa99972ec3b151f 100644 (file)
@@ -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<NR::Point> 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<Box3D::Axis, Box3D::Axis> 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<NR::Point>
 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<NR::Point>
 sp_3dbox_get_midpoint_between_corners (SP3DBox *box, guint id_corner1, guint id_corner2)
 {
index aecc40462c19d495a2d3229584b5cbfd3f2946be..ed563a42e4444fe1e861435d50dc22a4c68579ae 100644 (file)
@@ -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<NR::Point> sp_3dbox_get_center (SP3DBox *box);
 NR::Maybe<NR::Point> sp_3dbox_get_midpoint_between_corners (SP3DBox *box, guint id_corner1, guint id_corner2);
 
index 421725bdbd40018f6fd25506f773c9ee1ea5b6d7..c7592a06f0702e4749cdcbe981473bf6414cafcb 100644 (file)
@@ -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 ()
 {
index 6c7e774469fa0bc8cac0819017d2112ee587166e..4dd309b1f6513a6fc64d41b44e4041b256330002 100644 (file)
@@ -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 ();
 
index 0b4140a8bc95a37dab705832202209a3a5d12aec..9b2c45b56db494a793eb9ab0e65d97ffc8aec76b 100644 (file)
@@ -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");
     }
 
 }
index 25c5d2417f5b0bec9358721882531856a85b223f..b0c8a9b7b8bda5245ba0db7a1e5048bea8e65fbc 100644 (file)
@@ -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));
     }