Code

Refactoring of 3D box tool, mainly to avoid unnecessary creation of perspectives.
authorMaximilian Albert <maximilian.albert@gmail.com>
Sat, 26 Dec 2009 00:31:51 +0000 (01:31 +0100)
committerMaximilian Albert <maximilian.albert@gmail.com>
Sat, 26 Dec 2009 00:31:51 +0000 (01:31 +0100)
src/box3d-context.cpp
src/box3d.cpp
src/document.cpp
src/document.h
src/live_effects/lpe-perspective_path.cpp
src/persp3d-reference.h
src/persp3d.cpp
src/persp3d.h
src/selection.cpp
src/vanishing-point.cpp
src/widgets/toolbox.cpp

index e3476deb3a00aec82ab547d3c56a08e73a504fd0..c8fbfa8779ff27500679337568fa9df97b53de25 100644 (file)
@@ -123,16 +123,17 @@ static void sp_box3d_context_init(Box3DContext *box3d_context)
 
 static void sp_box3d_context_finish(SPEventContext *ec)
 {
-       Box3DContext *bc = SP_BOX3D_CONTEXT(ec);
-       SPDesktop *desktop = ec->desktop;
+    Box3DContext *bc = SP_BOX3D_CONTEXT(ec);
+    SPDesktop *desktop = ec->desktop;
 
-       sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), GDK_CURRENT_TIME);
-       sp_box3d_finish(bc);
+    sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), GDK_CURRENT_TIME);
+    sp_box3d_finish(bc);
     bc->sel_changed_connection.disconnect();
+//    sp_repr_remove_listener_by_data(cc->active_shape_repr, cc);
 
     if (((SPEventContextClass *) parent_class)->finish) {
-               ((SPEventContextClass *) parent_class)->finish(ec);
-       }
+        ((SPEventContextClass *) parent_class)->finish(ec);
+    }
 }
 
 
@@ -179,13 +180,14 @@ static void sp_box3d_context_selection_changed(Inkscape::Selection *selection, g
 
     if (selection->perspList().size() == 1) {
         // selecting a single box changes the current perspective
-        ec->desktop->doc()->current_persp3d = selection->perspList().front();
+        ec->desktop->doc()->setCurrentPersp3D(selection->perspList().front());
     }
 }
 
-/* create a default perspective in document defs if none is present
-   (can happen after 'vacuum defs' or when a pre-0.46 file is opened) */
-static void sp_box3d_context_check_for_persp_in_defs(SPDocument *document) {
+/* Create a default perspective in document defs if none is present (which can happen, among other
+ * circumstances, after 'vacuum defs' or when a pre-0.46 file is opened).
+ */
+static void sp_box3d_context_ensure_persp_in_defs(SPDocument *document) {
     SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document);
 
     bool has_persp = false;
@@ -197,7 +199,7 @@ static void sp_box3d_context_check_for_persp_in_defs(SPDocument *document) {
     }
 
     if (!has_persp) {
-        document->current_persp3d = persp3d_create_xml_element (document);
+        document->setCurrentPersp3D(persp3d_create_xml_element (document));
     }
 }
 
@@ -209,8 +211,6 @@ static void sp_box3d_context_setup(SPEventContext *ec)
         ((SPEventContextClass *) parent_class)->setup(ec);
     }
 
-    sp_box3d_context_check_for_persp_in_defs(sp_desktop_document (ec->desktop));
-
     ec->shape_editor = new ShapeEditor(ec->desktop);
 
     SPItem *item = sp_desktop_selection(ec->desktop)->singleItem();
@@ -267,13 +267,13 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
     static bool dragging;
 
     SPDesktop *desktop = event_context->desktop;
+    SPDocument *document = sp_desktop_document (desktop);
     Inkscape::Selection *selection = sp_desktop_selection (desktop);
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
     int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
 
     Box3DContext *bc = SP_BOX3D_CONTEXT(event_context);
-    g_assert (SP_ACTIVE_DOCUMENT->current_persp3d);
-    Persp3D *cur_persp = SP_ACTIVE_DOCUMENT->current_persp3d;
+    Persp3D *cur_persp = document->getCurrentPersp3D();
 
     event_context->tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
 
@@ -300,8 +300,14 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
             bc->drag_ptB = from_2geom(button_dt);
             bc->drag_ptC = from_2geom(button_dt);
 
+            // This can happen after saving when the last remaining perspective was purged and must be recreated.
+            if (!cur_persp) {
+                sp_box3d_context_ensure_persp_in_defs(document);
+                cur_persp = document->getCurrentPersp3D();
+            }
+
             /* Projective preimages of clicked point under current perspective */
-            bc->drag_origin_proj = cur_persp->tmat.preimage (from_2geom(button_dt), 0, Proj::Z);
+            bc->drag_origin_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(button_dt), 0, Proj::Z);
             bc->drag_ptB_proj = bc->drag_origin_proj;
             bc->drag_ptC_proj = bc->drag_origin_proj;
             bc->drag_ptC_proj.normalize();
@@ -355,7 +361,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
                bc->drag_ptB = from_2geom(motion_dt);
                bc->drag_ptC = from_2geom(motion_dt);
 
-                bc->drag_ptB_proj = cur_persp->tmat.preimage (from_2geom(motion_dt), 0, Proj::Z);
+                bc->drag_ptB_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(motion_dt), 0, Proj::Z);
                 bc->drag_ptC_proj = bc->drag_ptB_proj;
                 bc->drag_ptC_proj.normalize();
                 bc->drag_ptC_proj[Proj::Z] = 0.25;
@@ -364,16 +370,16 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
                 // perspective line from drag_ptB to vanishing point Y.
                 if (!bc->ctrl_dragged) {
                     /* snapping */
-                    Box3D::PerspectiveLine pline (bc->drag_ptB, Proj::Z, SP_ACTIVE_DOCUMENT->current_persp3d);
+                    Box3D::PerspectiveLine pline (bc->drag_ptB, Proj::Z, document->getCurrentPersp3D());
                     bc->drag_ptC = pline.closest_to (from_2geom(motion_dt));
 
                     bc->drag_ptB_proj.normalize();
-                    bc->drag_ptC_proj = cur_persp->tmat.preimage (bc->drag_ptC, bc->drag_ptB_proj[Proj::X], Proj::X);
+                    bc->drag_ptC_proj = cur_persp->perspective_impl->tmat.preimage (bc->drag_ptC, bc->drag_ptB_proj[Proj::X], Proj::X);
                 } else {
                     bc->drag_ptC = from_2geom(motion_dt);
 
                     bc->drag_ptB_proj.normalize();
-                    bc->drag_ptC_proj = cur_persp->tmat.preimage (from_2geom(motion_dt), bc->drag_ptB_proj[Proj::X], Proj::X);
+                    bc->drag_ptC_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(motion_dt), bc->drag_ptB_proj[Proj::X], Proj::X);
                 }
                 Geom::Point pt2g = to_2geom(bc->drag_ptC);
                 m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE);
@@ -424,43 +430,43 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
             break;
 
         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,
+            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::X, -180/snaps, MOD__ALT);
+            sp_document_done(document, 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,
+            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::X, 180/snaps, MOD__ALT);
+            sp_document_done(document, 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,
+            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Y, -180/snaps, MOD__ALT);
+            sp_document_done(document, 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,
+            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Y, 180/snaps, MOD__ALT);
+            sp_document_done(document, 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,
+            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Z, -180/snaps, MOD__ALT);
+            sp_document_done(document, 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,
+            persp3d_rotate_VP (document->getCurrentPersp3D(), Proj::Z, 180/snaps, MOD__ALT);
+            sp_document_done(document, SP_VERB_CONTEXT_3DBOX,
                              _("Change perspective (angle of PLs)"));
             ret = true;
             break;
@@ -468,7 +474,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
         /* TODO: what is this???
         case GDK_O:
             if (MOD__CTRL && MOD__SHIFT) {
-                Box3D::create_canvas_point(persp3d_get_VP(inkscape_active_document()->current_persp3d, Proj::W).affine(),
+                Box3D::create_canvas_point(persp3d_get_VP(document()->getCurrentPersp3D(), Proj::W).affine(),
                                            6, 0xff00ff00);
             }
             ret = true;
@@ -483,6 +489,16 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
             }
             break;
 
+        case GDK_p:
+        case GDK_P:
+            if (MOD__SHIFT_ONLY) {
+                if (document->getCurrentPersp3D()) {
+                    persp3d_print_debugging_info (document->getCurrentPersp3D());
+                }
+                ret = true;
+            }
+            break;
+
         case GDK_x:
         case GDK_X:
             if (MOD__ALT_ONLY) {
@@ -598,7 +614,7 @@ static void sp_box3d_drag(Box3DContext &bc, guint /*state*/)
 
         // TODO: It would be nice to show the VPs during dragging, but since there is no selection
         //       at this point (only after finishing the box), we must do this "manually"
-        /**** bc._vpdrag->updateDraggers(); ****/
+        /* bc._vpdrag->updateDraggers(); */
 
         sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 5);
     }
@@ -631,7 +647,7 @@ static void sp_box3d_finish(Box3DContext *bc)
     if ( bc->item != NULL ) {
         SPDesktop * desktop = SP_EVENT_CONTEXT_DESKTOP(bc);
         SPDocument *doc = sp_desktop_document(desktop);
-        if (!doc || !doc->current_persp3d)
+        if (!doc || !doc->getCurrentPersp3D())
             return;
 
         SPBox3D *box = SP_BOX3D(bc->item);
index 93efa5c35183589ea7e604066d7afb9d93e8b52d..460465637de0d0e1f1290f40733cf3fb8f74105a 100644 (file)
@@ -127,10 +127,8 @@ box3d_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
     // TODO: Create/link to the correct perspective
 
     SPDocument *doc = SP_OBJECT_DOCUMENT(box);
-    if (!doc) {
-        g_print ("No document for the box!!!!\n");
+    if (!doc)
         return;
-    }
 
     box->persp_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(box3d_ref_changed), box));
 
@@ -150,13 +148,33 @@ box3d_release(SPObject *object)
     if (box->persp_href) {
         g_free(box->persp_href);
     }
+
+    // We have to store this here because the Persp3DReference gets destroyed below, but we need to
+    // access it to call persp3d_remove_box(), which cannot be called earlier because the reference
+    // needs to be destroyed first.
+    Persp3D *persp = box3d_get_perspective(box);
+
     if (box->persp_ref) {
         box->persp_ref->detach();
         delete box->persp_ref;
         box->persp_ref = NULL;
     }
 
-    //persp3d_remove_box (box3d_get_perspective(box), box);
+    if (persp) {
+        persp3d_remove_box (persp, box);
+        /*
+        // TODO: This deletes a perspective when the last box referring to it is gone. Eventually,
+        // it would be nice to have this but currently it crashes when undoing/redoing box deletion
+        // Reason: When redoing a box deletion, the associated perspective is deleted twice, first
+        // by the following code and then again by the redo mechanism! Perhaps we should perform
+        // deletion of the perspective from another location "outside" the undo/redo mechanism?
+        if (persp->perspective_impl->boxes.empty()) {
+            SPDocument *doc = SP_OBJECT_DOCUMENT(box);
+            persp->deleteObject();
+            doc->setCurrentPersp3D(persp3d_document_first_persp(doc));
+        }
+        */
+    }
 
     if (((SPObjectClass *) parent_class)->release)
         ((SPObjectClass *) parent_class)->release(object);
@@ -278,7 +296,7 @@ static Inkscape::XML::Node *box3d_write(SPObject *object, Inkscape::XML::Documen
                 repr->setAttribute("inkscape:perspectiveID", uri_string);
                 g_free(uri_string);
             } else {
-                Inkscape::XML::Node *persp_repr = SP_OBJECT_REPR(doc->current_persp3d);
+                Inkscape::XML::Node *persp_repr = SP_OBJECT_REPR(doc->getCurrentPersp3D());
                 const gchar *persp_id = persp_repr->attribute("id");
                 gchar *href = g_strdup_printf("#%s", persp_id);
                 repr->setAttribute("inkscape:perspectiveID", href);
@@ -340,7 +358,7 @@ box3d_set_transform(SPItem *item, Geom::Matrix const &xform)
         std::list<SPBox3D *> selboxes = sp_desktop_selection(inkscape_active_desktop())->box3DList();
 
         /* create a new perspective as a copy of the current one and link the selected boxes to it */
-        transf_persp = persp3d_create_xml_element (SP_OBJECT_DOCUMENT(persp), persp);
+        transf_persp = persp3d_create_xml_element (SP_OBJECT_DOCUMENT(persp), persp->perspective_impl);
 
         for (std::list<SPBox3D *>::iterator b = selboxes.begin(); b != selboxes.end(); ++b) {
             box3d_switch_perspectives(*b, persp, transf_persp);
@@ -412,9 +430,9 @@ box3d_get_corner_screen (SPBox3D const *box, guint id, bool item_coords) {
     }
     Geom::Matrix const i2d (sp_item_i2d_affine (SP_ITEM(box)));
     if (item_coords) {
-        return box3d_get_perspective(box)->tmat.image(proj_corner).affine() * i2d.inverse();
+        return box3d_get_perspective(box)->perspective_impl->tmat.image(proj_corner).affine() * i2d.inverse();
     } else {
-        return box3d_get_perspective(box)->tmat.image(proj_corner).affine();
+        return box3d_get_perspective(box)->perspective_impl->tmat.image(proj_corner).affine();
     }
 }
 
@@ -435,7 +453,7 @@ box3d_get_center_screen (SPBox3D *box) {
         return Geom::Point (NR_HUGE, NR_HUGE);
     }
     Geom::Matrix const i2d (sp_item_i2d_affine (SP_ITEM(box)));
-    return box3d_get_perspective(box)->tmat.image(proj_center).affine() * i2d.inverse();
+    return box3d_get_perspective(box)->perspective_impl->tmat.image(proj_center).affine() * i2d.inverse();
 }
 
 /*
@@ -461,13 +479,13 @@ box3d_snap (SPBox3D *box, int id, Proj::Pt3 const &pt_proj, Proj::Pt3 const &sta
     Proj::Pt3 D_proj (x_coord,          y_coord + diff_y, z_coord, 1.0);
     Proj::Pt3 E_proj (x_coord - diff_x, y_coord + diff_y, z_coord, 1.0);
 
-    Persp3D *persp = box3d_get_perspective(box);
-    Geom::Point A = persp->tmat.image(A_proj).affine();
-    Geom::Point B = persp->tmat.image(B_proj).affine();
-    Geom::Point C = persp->tmat.image(C_proj).affine();
-    Geom::Point D = persp->tmat.image(D_proj).affine();
-    Geom::Point E = persp->tmat.image(E_proj).affine();
-    Geom::Point pt = persp->tmat.image(pt_proj).affine();
+    Persp3DImpl *persp_impl = box3d_get_perspective(box)->perspective_impl;
+    Geom::Point A = persp_impl->tmat.image(A_proj).affine();
+    Geom::Point B = persp_impl->tmat.image(B_proj).affine();
+    Geom::Point C = persp_impl->tmat.image(C_proj).affine();
+    Geom::Point D = persp_impl->tmat.image(D_proj).affine();
+    Geom::Point E = persp_impl->tmat.image(E_proj).affine();
+    Geom::Point pt = persp_impl->tmat.image(pt_proj).affine();
 
     // TODO: Replace these lines between corners with lines from a corner to a vanishing point
     //       (this might help to prevent rounding errors if the box is small)
@@ -523,7 +541,7 @@ box3d_snap (SPBox3D *box, int id, Proj::Pt3 const &pt_proj, Proj::Pt3 const &sta
         remember_snap_index = snap_index;
         result = snap_pts[snap_index];
     }
-    return box3d_get_perspective(box)->tmat.preimage (result, z_coord, Proj::Z);
+    return box3d_get_perspective(box)->perspective_impl->tmat.preimage (result, z_coord, Proj::Z);
 }
 
 void
@@ -535,8 +553,9 @@ box3d_set_corner (SPBox3D *box, const guint id, Geom::Point const &new_pos, cons
 
     /* update corners 0 and 7 according to which handle was moved and to the axes of movement */
     if (!(movement & Box3D::Z)) {
-        Proj::Pt3 pt_proj (box3d_get_perspective(box)->tmat.preimage (new_pos, (id < 4) ? box->orig_corner0[Proj::Z] :
-                                                                      box->orig_corner7[Proj::Z], Proj::Z));
+        Persp3DImpl *persp_impl = box3d_get_perspective(box)->perspective_impl;
+        Proj::Pt3 pt_proj (persp_impl->tmat.preimage (new_pos, (id < 4) ? box->orig_corner0[Proj::Z] :
+                                                      box->orig_corner7[Proj::Z], Proj::Z));
         if (constrained) {
             pt_proj = box3d_snap (box, id, pt_proj, box3d_get_proj_corner (id, box->save_corner0, box->save_corner7));
         }
@@ -553,13 +572,14 @@ box3d_set_corner (SPBox3D *box, const guint id, Geom::Point const &new_pos, cons
                                        1.0);
     } else {
         Persp3D *persp = box3d_get_perspective(box);
-        Box3D::PerspectiveLine pl(persp->tmat.image(
+        Persp3DImpl *persp_impl = box3d_get_perspective(box)->perspective_impl;
+        Box3D::PerspectiveLine pl(persp_impl->tmat.image(
                                       box3d_get_proj_corner (id, box->save_corner0, box->save_corner7)).affine(),
                                   Proj::Z, persp);
         Geom::Point new_pos_snapped(pl.closest_to(new_pos));
-        Proj::Pt3 pt_proj (persp->tmat.preimage (new_pos_snapped,
-                                          box3d_get_proj_corner (box, id)[(movement & Box3D::Y) ? Proj::X : Proj::Y],
-                                          (movement & Box3D::Y) ? Proj::X : Proj::Y));
+        Proj::Pt3 pt_proj (persp_impl->tmat.preimage (new_pos_snapped,
+                                      box3d_get_proj_corner (box, id)[(movement & Box3D::Y) ? Proj::X : Proj::Y],
+                                                      (movement & Box3D::Y) ? Proj::X : Proj::Y));
         bool corner0_move_x = !(id & Box3D::X) && (movement & Box3D::X);
         bool corner0_move_y = !(id & Box3D::Y) && (movement & Box3D::Y);
         bool corner7_move_x =  (id & Box3D::X) && (movement & Box3D::X);
@@ -590,9 +610,9 @@ void box3d_set_center (SPBox3D *box, Geom::Point const &new_pos, Geom::Point con
         double radx = (box->orig_corner7[Proj::X] - box->orig_corner0[Proj::X]) / 2;
         double rady = (box->orig_corner7[Proj::Y] - box->orig_corner0[Proj::Y]) / 2;
 
-        Proj::Pt3 pt_proj (persp->tmat.preimage (new_pos, coord, Proj::Z));
+        Proj::Pt3 pt_proj (persp->perspective_impl->tmat.preimage (new_pos, coord, Proj::Z));
         if (constrained) {
-            Proj::Pt3 old_pos_proj (persp->tmat.preimage (old_pos, coord, Proj::Z));
+            Proj::Pt3 old_pos_proj (persp->perspective_impl->tmat.preimage (old_pos, coord, Proj::Z));
             old_pos_proj.normalize();
             pt_proj = box3d_snap (box, -1, pt_proj, old_pos_proj);
         }
@@ -612,7 +632,7 @@ void box3d_set_center (SPBox3D *box, Geom::Point const &new_pos, Geom::Point con
 
         Box3D::PerspectiveLine pl(old_pos, Proj::Z, persp);
         Geom::Point new_pos_snapped(pl.closest_to(new_pos));
-        Proj::Pt3 pt_proj (persp->tmat.preimage (new_pos_snapped, coord, Proj::X));
+        Proj::Pt3 pt_proj (persp->perspective_impl->tmat.preimage (new_pos_snapped, coord, Proj::X));
 
         /* normalizing pt_proj is essential because we want to mingle affine coordinates */
         pt_proj.normalize();
@@ -636,6 +656,7 @@ void box3d_corners_for_PLs (const SPBox3D * box, Proj::Axis axis,
 {
     Persp3D *persp = box3d_get_perspective(box);
     g_return_if_fail (persp);
+    Persp3DImpl *persp_impl = persp->perspective_impl;
     //box->orig_corner0.normalize();
     //box->orig_corner7.normalize();
     double coord = (box->orig_corner0[axis] > box->orig_corner7[axis]) ?
@@ -666,10 +687,10 @@ void box3d_corners_for_PLs (const SPBox3D * box, Proj::Axis axis,
         default:
             return;
     }
-    corner1 = persp->tmat.image(c1).affine();
-    corner2 = persp->tmat.image(c2).affine();
-    corner3 = persp->tmat.image(c3).affine();
-    corner4 = persp->tmat.image(c4).affine();
+    corner1 = persp_impl->tmat.image(c1).affine();
+    corner2 = persp_impl->tmat.image(c2).affine();
+    corner3 = persp_impl->tmat.image(c3).affine();
+    corner4 = persp_impl->tmat.image(c4).affine();
 }
 
 /* Auxiliary function: Checks whether the half-line from A to B crosses the line segment joining C and D */
@@ -1027,7 +1048,7 @@ box3d_recompute_z_orders (SPBox3D *box) {
     Geom::Point dirs[3];
     for (int i = 0; i < 3; ++i) {
         dirs[i] = persp3d_get_PL_dir_from_pt(persp, c3, Box3D::toProj(Box3D::axes[i]));
-        if (persp3d_VP_is_finite(persp, Proj::axes[i])) {
+        if (persp3d_VP_is_finite(persp->perspective_impl, Proj::axes[i])) {
             num_finite++;
             axis_finite = Box3D::axes[i];
         } else {
@@ -1212,7 +1233,7 @@ box3d_pt_lies_in_PL_sector (SPBox3D const *box, Geom::Point const &pt, int id1,
     Geom::Point c2(box3d_get_corner_screen(box, id2, false));
 
     int ret = 0;
-    if (persp3d_VP_is_finite(persp, Box3D::toProj(axis))) {
+    if (persp3d_VP_is_finite(persp->perspective_impl, Box3D::toProj(axis))) {
         Geom::Point vp(persp3d_get_VP(persp, Box3D::toProj(axis)).affine());
         Geom::Point v1(c1 - vp);
         Geom::Point v2(c2 - vp);
@@ -1239,7 +1260,7 @@ int
 box3d_VP_lies_in_PL_sector (SPBox3D const *box, Proj::Axis vpdir, int id1, int id2, Box3D::Axis axis) {
     Persp3D *persp = box3d_get_perspective(box);
 
-    if (!persp3d_VP_is_finite(persp, vpdir)) {
+    if (!persp3d_VP_is_finite(persp->perspective_impl, vpdir)) {
         return 0;
     } else {
         return box3d_pt_lies_in_PL_sector(box, persp3d_get_VP(persp, vpdir).affine(), id1, id2, axis);
@@ -1360,8 +1381,8 @@ box3d_switch_perspectives(SPBox3D *box, Persp3D *old_persp, Persp3D *new_persp,
         Geom::Point corner0_screen = box3d_get_corner_screen(box, 0, false);
         Geom::Point corner7_screen = box3d_get_corner_screen(box, 7, false);
 
-        box->orig_corner0 = new_persp->tmat.preimage(corner0_screen, z0, Proj::Z);
-        box->orig_corner7 = new_persp->tmat.preimage(corner7_screen, z7, Proj::Z);
+        box->orig_corner0 = new_persp->perspective_impl->tmat.preimage(corner0_screen, z0, Proj::Z);
+        box->orig_corner7 = new_persp->perspective_impl->tmat.preimage(corner7_screen, z7, Proj::Z);
     }
 
     persp3d_remove_box (old_persp, box);
index a3ad6f7beb1486a4bc236e6d0ff44213b2d89ef5..df77dde6413477512d601a226f70256d5d4590cf 100644 (file)
@@ -97,7 +97,6 @@ SPDocument::SPDocument() :
     rerouting_handler_id(0),
     profileManager(0), // deferred until after other initialization
     router(new Avoid::Router(Avoid::PolyLineRouting|Avoid::OrthogonalRouting)),
-    perspectives(0),
     current_persp3d(0),
     _collection_queue(0),
     oldSignalsConnected(false)
@@ -216,26 +215,43 @@ SPDocument::~SPDocument() {
     //delete this->_whiteboard_session_manager;
 }
 
-void SPDocument::add_persp3d (Persp3D * const /*persp*/)
-{
-    SPDefs *defs = SP_ROOT(this->root)->defs;
-    for (SPObject *i = sp_object_first_child(SP_OBJECT(defs)); i != NULL; i = SP_OBJECT_NEXT(i) ) {
-        if (SP_IS_PERSP3D(i)) {
-            g_print ("Encountered a Persp3D in defs\n");
-        }
+Persp3D *
+SPDocument::getCurrentPersp3D() {
+    // Check if current_persp3d is still valid
+    std::vector<Persp3D*> plist;
+    getPerspectivesInDefs(plist);
+    for (unsigned int i = 0; i < plist.size(); ++i) {
+        if (current_persp3d == plist[i])
+            return current_persp3d;
     }
 
-    g_print ("Adding Persp3D to defs\n");
-    persp3d_create_xml_element (this);
+    // If not, return the first perspective in defs (which may be NULL of none exists)
+    current_persp3d = persp3d_document_first_persp (this);
+
+    return current_persp3d;
 }
 
-void SPDocument::remove_persp3d (Persp3D * const /*persp*/)
-{
-    // TODO: Delete the repr, maybe perform a check if any boxes are still linked to the perspective.
-    //       Anything else?
-    g_print ("Please implement deletion of perspectives here.\n");
+Persp3DImpl *
+SPDocument::getCurrentPersp3DImpl() {
+    return current_persp3d_impl;
 }
 
+void
+SPDocument::setCurrentPersp3D(Persp3D * const persp) {
+    current_persp3d = persp;
+    //current_persp3d_impl = persp->perspective_impl;
+}
+
+void
+SPDocument::getPerspectivesInDefs(std::vector<Persp3D*> &list) {
+    SPDefs *defs = SP_ROOT(this->root)->defs;
+    for (SPObject *i = sp_object_first_child(SP_OBJECT(defs)); i != NULL; i = SP_OBJECT_NEXT(i) ) {
+        if (SP_IS_PERSP3D(i))
+            list.push_back(SP_PERSP3D(i));
+    }
+}
+
+/**
 void SPDocument::initialize_current_persp3d()
 {
     this->current_persp3d = persp3d_document_first_persp(this);
@@ -243,6 +259,7 @@ void SPDocument::initialize_current_persp3d()
         this->current_persp3d = persp3d_create_xml_element(this);
     }
 }
+**/
 
 unsigned long SPDocument::serial() const {
     return priv->serial;
@@ -390,10 +407,14 @@ sp_document_create(Inkscape::XML::Document *rdoc,
         inkscape_ref();
     }
 
-    // Remark: Here, we used to create a "currentpersp3d" element in the document defs.
-    // But this is probably a bad idea since we need to adapt it for every change of selection, which will
-    // completely clutter the undo history. Maybe rather save it to prefs on exit and re-read it on startup?
-    document->initialize_current_persp3d();
+    // Check if the document already has a perspective (e.g., when opening an existing
+    // document). If not, create a new one and set it as the current perspective.
+    document->setCurrentPersp3D(persp3d_document_first_persp(document));
+    if (!document->getCurrentPersp3D()) {
+        //document->setCurrentPersp3D(persp3d_create_xml_element (document));
+        Persp3DImpl *persp_impl = new Persp3DImpl();
+        document->setCurrentPersp3DImpl(persp_impl);
+    }
 
     sp_document_set_undo_sensitive(document, true);
 
@@ -746,11 +767,13 @@ SPDocument::emitReconstructionFinish(void)
 {
     // printf("Finishing Reconstruction\n");
     priv->_reconstruction_finish_signal.emit();
-    
+
+/**    
     // Reference to the old persp3d object is invalid after reconstruction.
     initialize_current_persp3d();
     
     return;
+**/
 }
 
 sigc::connection SPDocument::connectCommit(SPDocument::CommitSignal::slot_type slot)
index 06174c265f593b402151200b2fcb2e6a221f6c26..e83c37a968a2d4584cd020ed5173d70752aa7207 100644 (file)
@@ -55,6 +55,7 @@ namespace Inkscape {
 
 class SP3DBox;
 class Persp3D;
+class Persp3DImpl;
 
 namespace Proj {
     class TransfMat3x4;
@@ -107,17 +108,26 @@ struct SPDocument : public Inkscape::GC::Managed<>,
     // Instance of the connector router
     Avoid::Router *router;
 
-    GSList *perspectives;
-
-    Persp3D *current_persp3d; // "currently active" perspective (e.g., newly created boxes are attached to this one)
-
     GSList *_collection_queue;
 
     bool oldSignalsConnected;
 
-    void add_persp3d(Persp3D * const persp);
-    void remove_persp3d(Persp3D * const persp);
-    void initialize_current_persp3d();
+    void setCurrentPersp3D(Persp3D * const persp);
+    inline void setCurrentPersp3DImpl(Persp3DImpl * const persp_impl) { current_persp3d_impl = persp_impl; }
+    /*
+     * getCurrentPersp3D returns current_persp3d (if non-NULL) or the first
+     * perspective in the defs. If no perspective exists, returns NULL.
+     */
+    Persp3D * getCurrentPersp3D();
+    Persp3DImpl * getCurrentPersp3DImpl();
+    void getPerspectivesInDefs(std::vector<Persp3D*> &list);
+    unsigned int numPerspectivesInDefs() {
+        std::vector<Persp3D*> list;
+        getPerspectivesInDefs(list);
+        return list.size();
+    }
+
+    //void initialize_current_persp3d();
 
     sigc::connection connectModified(ModifiedSignal::slot_type slot);
     sigc::connection connectURISet(URISetSignal::slot_type slot);
@@ -155,6 +165,9 @@ private:
     SPDocument(SPDocument const &); // no copy
     void operator=(SPDocument const &); // no assign
 
+    Persp3D *current_persp3d; /**< Currently 'active' perspective (to which, e.g., newly created boxes are attached) */
+    Persp3DImpl *current_persp3d_impl;
+
 public:
     sigc::connection connectReconstructionStart(ReconstructionStart::slot_type slot);
     sigc::connection connectReconstructionFinish(ReconstructionFinish::slot_type slot);
index 091a4d9ae2b90deee7799e0d840862ce45f42660..3d18318c5c53ff0bbe899e2a5cd3e40e0e312ec1 100644 (file)
@@ -58,7 +58,7 @@ LPEPerspectivePath::LPEPerspectivePath(LivePathEffectObject *lpeobject) :
 
     Persp3D *persp = persp3d_document_first_persp(inkscape_active_document());
 
-    Proj::TransfMat3x4 pmat = persp->tmat;
+    Proj::TransfMat3x4 pmat = persp->perspective_impl->tmat;
 
     pmat.copy_tmat(tmat);
 }
index 43b0e82b1f5431899b2c55b6f8b6f5190f6e2c62..7c2ce31bf6136bf5996d2603239e41eaa3d31e2e 100644 (file)
@@ -12,9 +12,9 @@
 
 #include "uri-references.h"
 #include <sigc++/sigc++.h>
+#include "persp3d.h"
 
 class SPObject;
-class Persp3D;
 
 namespace Inkscape {
 namespace XML {
@@ -28,7 +28,7 @@ public:
     ~Persp3DReference();
 
     Persp3D *getObject() const {
-        return (Persp3D *)URIReference::getObject();
+        return SP_PERSP3D(URIReference::getObject());
     }
 
     SPObject *owner;
index 916e9f25f421fe071452b070e4088abfb2cf9bdf..3f1e8851fe7075185e9f3b4e3a8c7781cb5ac8cf 100644 (file)
@@ -24,7 +24,7 @@
 #include <glibmm/i18n.h>
 
 static void persp3d_class_init(Persp3DClass *klass);
-static void persp3d_init(Persp3D *stop);
+static void persp3d_init(Persp3D *persp);
 
 static void persp3d_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
 static void persp3d_release(SPObject *object);
@@ -38,6 +38,22 @@ static SPObjectClass *persp3d_parent_class;
 
 static int global_counter = 0;
 
+/* Constructor/destructor for the internal class */
+
+Persp3DImpl::Persp3DImpl() {
+    tmat = Proj::TransfMat3x4 ();
+
+    boxes_transformed = new std::map<SPBox3D *, bool>;
+    boxes_transformed->clear();
+    document = NULL;
+
+    my_counter = global_counter++;
+}
+
+Persp3DImpl::~Persp3DImpl() {
+    delete boxes_transformed;
+}
+
 /**
  * Registers Persp3d class and returns its type.
  */
@@ -91,13 +107,7 @@ static void persp3d_class_init(Persp3DClass *klass)
 static void
 persp3d_init(Persp3D *persp)
 {
-    persp->tmat = Proj::TransfMat3x4 ();
-
-    persp->boxes_transformed = new std::map<SPBox3D *, bool>;
-    persp->boxes_transformed->clear();
-    persp->document = NULL;
-
-    persp->my_counter = global_counter++;
+    persp->perspective_impl = new Persp3DImpl();
 }
 
 /**
@@ -124,8 +134,8 @@ static void persp3d_build(SPObject *object, SPDocument *document, Inkscape::XML:
  * Virtual release of Persp3D members before destruction.
  */
 static void persp3d_release(SPObject *object) {
-    Persp3D *persp = SP_PERSP3D (object);
-    delete persp->boxes_transformed;
+    Persp3D *persp = SP_PERSP3D(object);
+    delete persp->perspective_impl;
     SP_OBJECT_REPR(object)->removeListenerByData(object);
 }
 
@@ -138,34 +148,34 @@ static void persp3d_release(SPObject *object) {
 static void
 persp3d_set(SPObject *object, unsigned key, gchar const *value)
 {
-    Persp3D *persp = SP_PERSP3D (object);
+    Persp3DImpl *persp_impl = SP_PERSP3D(object)->perspective_impl;
 
     switch (key) {
         case SP_ATTR_INKSCAPE_PERSP3D_VP_X: {
             if (value) {
                 Proj::Pt2 new_image (value);
-                persp3d_update_with_point (persp, Proj::X, new_image);
+                persp3d_update_with_point (persp_impl, Proj::X, new_image);
             }
             break;
         }
         case SP_ATTR_INKSCAPE_PERSP3D_VP_Y: {
             if (value) {
                 Proj::Pt2 new_image (value);
-                persp3d_update_with_point (persp, Proj::Y, new_image);
+                persp3d_update_with_point (persp_impl, Proj::Y, new_image);
                 break;
             }
         }
         case SP_ATTR_INKSCAPE_PERSP3D_VP_Z: {
             if (value) {
                 Proj::Pt2 new_image (value);
-                persp3d_update_with_point (persp, Proj::Z, new_image);
+                persp3d_update_with_point (persp_impl, Proj::Z, new_image);
                 break;
             }
         }
         case SP_ATTR_INKSCAPE_PERSP3D_ORIGIN: {
             if (value) {
                 Proj::Pt2 new_image (value);
-                persp3d_update_with_point (persp, Proj::W, new_image);
+                persp3d_update_with_point (persp_impl, Proj::W, new_image);
                 break;
             }
         }
@@ -201,36 +211,40 @@ persp3d_update(SPObject *object, SPCtx *ctx, guint flags)
 }
 
 Persp3D *
-persp3d_create_xml_element (SPDocument *document, Persp3D *dup) {// if dup is given, copy the attributes over
+persp3d_create_xml_element (SPDocument *document, Persp3DImpl *dup) {// if dup is given, copy the attributes over
     SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document);
     Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
     Inkscape::XML::Node *repr;
-    if (dup) {
-        repr = SP_OBJECT_REPR(dup)->duplicate (xml_doc);
-    } else {
-        /* if no perspective is given, create a default one */
-        repr = xml_doc->createElement("inkscape:perspective");
-        repr->setAttribute("sodipodi:type", "inkscape:persp3d");
 
-        Proj::Pt2 proj_vp_x = Proj::Pt2 (0.0, sp_document_height(document)/2, 1.0);
-        Proj::Pt2 proj_vp_y = Proj::Pt2 (  0.0,1000.0, 0.0);
-        Proj::Pt2 proj_vp_z = Proj::Pt2 (sp_document_width(document), sp_document_height(document)/2, 1.0);
-        Proj::Pt2 proj_origin = Proj::Pt2 (sp_document_width(document)/2, sp_document_height(document)/3, 1.0);
+    /* if no perspective is given, create a default one */
+    repr = xml_doc->createElement("inkscape:perspective");
+    repr->setAttribute("sodipodi:type", "inkscape:persp3d");
 
-        gchar *str = NULL;
-        str = proj_vp_x.coord_string();
-        repr->setAttribute("inkscape:vp_x", str);
-        g_free (str);
-        str = proj_vp_y.coord_string();
-        repr->setAttribute("inkscape:vp_y", str);
-        g_free (str);
-        str = proj_vp_z.coord_string();
-        repr->setAttribute("inkscape:vp_z", str);
-        g_free (str);
-        str = proj_origin.coord_string();
-        repr->setAttribute("inkscape:persp3d-origin", str);
-        g_free (str);
-    }
+    Proj::Pt2 proj_vp_x = Proj::Pt2 (0.0, sp_document_height(document)/2, 1.0);
+    Proj::Pt2 proj_vp_y = Proj::Pt2 (0.0, 1000.0, 0.0);
+    Proj::Pt2 proj_vp_z = Proj::Pt2 (sp_document_width(document), sp_document_height(document)/2, 1.0);
+    Proj::Pt2 proj_origin = Proj::Pt2 (sp_document_width(document)/2, sp_document_height(document)/3, 1.0);
+
+    if (dup) {
+        proj_vp_x = dup->tmat.column (Proj::X);
+        proj_vp_y = dup->tmat.column (Proj::Y);
+        proj_vp_z = dup->tmat.column (Proj::Z);
+        proj_origin = dup->tmat.column (Proj::W);
+    }
+
+    gchar *str = NULL;
+    str = proj_vp_x.coord_string();
+    repr->setAttribute("inkscape:vp_x", str);
+    g_free (str);
+    str = proj_vp_y.coord_string();
+    repr->setAttribute("inkscape:vp_y", str);
+    g_free (str);
+    str = proj_vp_z.coord_string();
+    repr->setAttribute("inkscape:vp_z", str);
+    g_free (str);
+    str = proj_origin.coord_string();
+    repr->setAttribute("inkscape:persp3d-origin", str);
+    g_free (str);
 
     /* Append the new persp3d to defs */
     SP_OBJECT_REPR(defs)->addChild(repr, NULL);
@@ -258,7 +272,7 @@ persp3d_document_first_persp (SPDocument *document) {
 static Inkscape::XML::Node *
 persp3d_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
 {
-    Persp3D *persp = SP_PERSP3D(object);
+    Persp3DImpl *persp_impl = SP_PERSP3D(object)->perspective_impl;
 
     if ((flags & SP_OBJECT_WRITE_BUILD & SP_OBJECT_WRITE_EXT) && !repr) {
         // this is where we end up when saving as plain SVG (also in other circumstances?);
@@ -268,16 +282,16 @@ persp3d_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML:
 
     if (flags & SP_OBJECT_WRITE_EXT) {
         gchar *str = NULL; // FIXME: Should this be freed each time we set an attribute or only in the end or at all?
-        str = persp3d_pt_to_str (persp, Proj::X);
+        str = persp3d_pt_to_str (persp_impl, Proj::X);
         repr->setAttribute("inkscape:vp_x", str);
 
-        str = persp3d_pt_to_str (persp, Proj::Y);
+        str = persp3d_pt_to_str (persp_impl, Proj::Y);
         repr->setAttribute("inkscape:vp_y", str);
 
-        str = persp3d_pt_to_str (persp, Proj::Z);
+        str = persp3d_pt_to_str (persp_impl, Proj::Z);
         repr->setAttribute("inkscape:vp_z", str);
 
-        str = persp3d_pt_to_str (persp, Proj::W);
+        str = persp3d_pt_to_str (persp_impl, Proj::W);
         repr->setAttribute("inkscape:persp3d-origin", str);
     }
 
@@ -289,7 +303,7 @@ persp3d_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML:
 
 /* convenience wrapper around persp3d_get_finite_dir() and persp3d_get_infinite_dir() */
 Geom::Point persp3d_get_PL_dir_from_pt (Persp3D *persp, Geom::Point const &pt, Proj::Axis axis) {
-    if (persp3d_VP_is_finite(persp, axis)) {
+    if (persp3d_VP_is_finite(persp->perspective_impl, axis)) {
         return persp3d_get_finite_dir(persp, pt, axis);
     } else {
         return persp3d_get_infinite_dir(persp, axis);
@@ -314,17 +328,17 @@ persp3d_get_infinite_dir (Persp3D *persp, Proj::Axis axis) {
 
 double
 persp3d_get_infinite_angle (Persp3D *persp, Proj::Axis axis) {
-    return persp->tmat.get_infinite_angle(axis);
+    return persp->perspective_impl->tmat.get_infinite_angle(axis);
 }
 
 bool
-persp3d_VP_is_finite (Persp3D *persp, Proj::Axis axis) {
-    return persp->tmat.has_finite_image(axis);
+persp3d_VP_is_finite (Persp3DImpl *persp_impl, Proj::Axis axis) {
+    return persp_impl->tmat.has_finite_image(axis);
 }
 
 void
 persp3d_toggle_VP (Persp3D *persp, Proj::Axis axis, bool set_undo) {
-    persp->tmat.toggle_finite(axis);
+    persp->perspective_impl->tmat.toggle_finite(axis);
     // FIXME: Remove this repr update and rely on vp_drag_sel_modified() to do this for us
     //        On the other hand, vp_drag_sel_modified() would update all boxes;
     //        here we can confine ourselves to the boxes of this particular perspective.
@@ -348,7 +362,7 @@ persp3d_toggle_VPs (std::list<Persp3D *> 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->perspective_impl, axis) != (state == Proj::VP_FINITE)) {
         persp3d_toggle_VP(persp, axis);
     }
 }
@@ -356,62 +370,67 @@ persp3d_set_VP_state (Persp3D *persp, Proj::Axis axis, Proj::VPState state) {
 void
 persp3d_rotate_VP (Persp3D *persp, Proj::Axis axis, double angle, bool alt_pressed) { // angle is in degrees
     // FIXME: Most of this functionality should be moved to trans_mat_3x4.(h|cpp)
-    if (persp->tmat.has_finite_image(axis)) {
+    if (persp->perspective_impl->tmat.has_finite_image(axis)) {
         // don't rotate anything for finite VPs
         return;
     }
-    Proj::Pt2 v_dir_proj (persp->tmat.column(axis));
+    Proj::Pt2 v_dir_proj (persp->perspective_impl->tmat.column(axis));
     Geom::Point v_dir (v_dir_proj[0], v_dir_proj[1]);
     double a = Geom::atan2 (v_dir) * 180/M_PI;
     a += alt_pressed ? 0.5 * ((angle > 0 ) - (angle < 0)) : angle; // the r.h.s. yields +/-0.5 or angle
-    persp->tmat.set_infinite_direction (axis, a);
+    persp->perspective_impl->tmat.set_infinite_direction (axis, a);
 
     persp3d_update_box_reprs (persp);
     SP_OBJECT(persp)->updateRepr(SP_OBJECT_WRITE_EXT);
 }
 
 void
-persp3d_update_with_point (Persp3D *persp, Proj::Axis const axis, Proj::Pt2 const &new_image) {
-    persp->tmat.set_image_pt (axis, new_image);
+persp3d_update_with_point (Persp3DImpl *persp_impl, Proj::Axis const axis, Proj::Pt2 const &new_image) {
+    persp_impl->tmat.set_image_pt (axis, new_image);
 }
 
 void
 persp3d_apply_affine_transformation (Persp3D *persp, Geom::Matrix const &xform) {
-    persp->tmat *= xform;
+    persp->perspective_impl->tmat *= xform;
     persp3d_update_box_reprs(persp);
     SP_OBJECT(persp)->updateRepr(SP_OBJECT_WRITE_EXT);
 }
 
 gchar *
-persp3d_pt_to_str (Persp3D *persp, Proj::Axis const axis)
+persp3d_pt_to_str (Persp3DImpl *persp_impl, Proj::Axis const axis)
 {
-    return persp->tmat.pt_to_str(axis);
+    return persp_impl->tmat.pt_to_str(axis);
 }
 
 void
 persp3d_add_box (Persp3D *persp, SPBox3D *box) {
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
     if (!box) {
         return;
     }
-    if (std::find (persp->boxes.begin(), persp->boxes.end(), box) != persp->boxes.end()) {
+    if (std::find (persp_impl->boxes.begin(), persp_impl->boxes.end(), box) != persp_impl->boxes.end()) {
         return;
     }
-    persp->boxes.push_back(box);
+    persp_impl->boxes.push_back(box);
 }
 
 void
 persp3d_remove_box (Persp3D *persp, SPBox3D *box) {
-    std::vector<SPBox3D *>::iterator i = std::find (persp->boxes.begin(), persp->boxes.end(), box);
-    if (i != persp->boxes.end()) {
-        persp->boxes.erase(i);
-    }
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
+    std::vector<SPBox3D *>::iterator i = std::find (persp_impl->boxes.begin(), persp_impl->boxes.end(), box);
+    if (i != persp_impl->boxes.end())
+        persp_impl->boxes.erase(i);
 }
 
 bool
 persp3d_has_box (Persp3D *persp, SPBox3D *box) {
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
     // FIXME: For some reason, std::find() does not seem to compare pointers "correctly" (or do we need to
     //        provide a proper comparison function?), so we manually traverse the list.
-    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
+    for (std::vector<SPBox3D *>::iterator i = persp_impl->boxes.begin(); i != persp_impl->boxes.end(); ++i) {
         if ((*i) == box) {
             return true;
         }
@@ -421,44 +440,50 @@ persp3d_has_box (Persp3D *persp, SPBox3D *box) {
 
 void
 persp3d_add_box_transform (Persp3D *persp, SPBox3D *box) {
-    std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed->find(box);
-    if (i != persp->boxes_transformed->end() && (*i).second == true) {
-        g_print ("Warning! In %s (%d): trying to add transform status for box %d twice when it's already listed as true.\n", SP_OBJECT_REPR(persp)->attribute("id"), persp->my_counter, box->my_counter);
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
+    std::map<SPBox3D *, bool>::iterator i = persp_impl->boxes_transformed->find(box);
+    if (i != persp_impl->boxes_transformed->end() && (*i).second == true) {
+        g_print ("Warning! In %s (%d): trying to add transform status for box %d twice when it's already listed as true.\n", SP_OBJECT_REPR(persp_impl)->attribute("id"), persp_impl->my_counter, box->my_counter);
         return;
     }
  
-    (*persp->boxes_transformed)[box] = false;
+    (*persp_impl->boxes_transformed)[box] = false;
 }
 
 void
 persp3d_remove_box_transform (Persp3D *persp, SPBox3D *box) {
-    persp->boxes_transformed->erase(box);
+    persp->perspective_impl->boxes_transformed->erase(box);
 }
 
 void
 persp3d_set_box_transformed (Persp3D *persp, SPBox3D *box, bool transformed) {
-    if (persp->boxes_transformed->find(box) == persp->boxes_transformed->end()) {
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
+    if (persp_impl->boxes_transformed->find(box) == persp_impl->boxes_transformed->end()) {
         g_print ("Warning! In %s (%d): trying to set transform status for box %d, but it is not listed in the perspective!! Aborting.\n",
-                 SP_OBJECT_REPR(persp)->attribute("id"), persp->my_counter,
+                 SP_OBJECT_REPR(persp)->attribute("id"), persp_impl->my_counter,
                  box->my_counter);
         return;
     }
 
-    (*persp->boxes_transformed)[box] = transformed;
+    (*persp_impl->boxes_transformed)[box] = transformed;
 }
 
 bool
 persp3d_was_transformed (Persp3D *persp) {
-    if (persp->boxes_transformed->size() == 1) {
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
+    if (persp_impl->boxes_transformed->size() == 1) {
         /* either the transform has not been applied to the single box associated to this perspective yet
            or the transform was already reset; in both cases we need to return false because upcoming
            transforms need to be applied */
-        (*persp->boxes_transformed->begin()).second = false; // make sure the box is marked as untransformed (in case more boxes are added later)
+        (*persp_impl->boxes_transformed->begin()).second = false; // make sure the box is marked as untransformed (in case more boxes are added later)
         return false;
     }
 
-    for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed->begin();
-         i != persp->boxes_transformed->end(); ++i) {
+    for (std::map<SPBox3D *, bool>::iterator i = persp_impl->boxes_transformed->begin();
+         i != persp_impl->boxes_transformed->end(); ++i) {
         if ((*i).second == true) {
             // at least one of the boxes in the perspective has already been transformed;
             return true;
@@ -469,8 +494,10 @@ persp3d_was_transformed (Persp3D *persp) {
 
 bool
 persp3d_all_transformed(Persp3D *persp) {
-    for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed->begin();
-         i != persp->boxes_transformed->end(); ++i) {
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
+    for (std::map<SPBox3D *, bool>::iterator i = persp_impl->boxes_transformed->begin();
+         i != persp_impl->boxes_transformed->end(); ++i) {
         if ((*i).second == false) {
             return false;
         }
@@ -480,26 +507,36 @@ persp3d_all_transformed(Persp3D *persp) {
 
 void
 persp3d_unset_transforms(Persp3D *persp) {
-    for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed->begin();
-         i != persp->boxes_transformed->end(); ++i) {
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
+    for (std::map<SPBox3D *, bool>::iterator i = persp_impl->boxes_transformed->begin();
+         i != persp_impl->boxes_transformed->end(); ++i) {
         (*i).second = false;
     }
 }
 
 void
 persp3d_update_box_displays (Persp3D *persp) {
-    if (persp->boxes.empty())
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
+    if (persp_impl->boxes.empty())
         return;
-    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
+    for (std::vector<SPBox3D *>::iterator i = persp_impl->boxes.begin(); i != persp_impl->boxes.end(); ++i) {
         box3d_position_set(*i);
     }
 }
 
 void
 persp3d_update_box_reprs (Persp3D *persp) {
-    if (persp->boxes.empty())
+    if (!persp) {
+        // Hmm, is it an error if this happens?
         return;
-    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
+    }
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
+    if (persp_impl->boxes.empty())
+        return;
+    for (std::vector<SPBox3D *>::iterator i = persp_impl->boxes.begin(); i != persp_impl->boxes.end(); ++i) {
         SP_OBJECT(*i)->updateRepr(SP_OBJECT_WRITE_EXT);
         box3d_set_z_orders(*i);
     }
@@ -507,9 +544,11 @@ persp3d_update_box_reprs (Persp3D *persp) {
 
 void
 persp3d_update_z_orders (Persp3D *persp) {
-    if (persp->boxes.empty())
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
+    if (persp_impl->boxes.empty())
         return;
-    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
+    for (std::vector<SPBox3D *>::iterator i = persp_impl->boxes.begin(); i != persp_impl->boxes.end(); ++i) {
         box3d_set_z_orders(*i);
     }
 }
@@ -519,8 +558,10 @@ persp3d_update_z_orders (Persp3D *persp) {
 //        obsolete. We should do this.
 std::list<SPBox3D *>
 persp3d_list_of_boxes(Persp3D *persp) {
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
     std::list<SPBox3D *> bx_lst;
-    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
+    for (std::vector<SPBox3D *>::iterator i = persp_impl->boxes.begin(); i != persp_impl->boxes.end(); ++i) {
         bx_lst.push_back(*i);
     }
     return bx_lst;
@@ -529,7 +570,7 @@ persp3d_list_of_boxes(Persp3D *persp) {
 bool
 persp3d_perspectives_coincide(const Persp3D *lhs, const Persp3D *rhs)
 {
-    return lhs->tmat == rhs->tmat;
+    return lhs->perspective_impl->tmat == rhs->perspective_impl->tmat;
 }
 
 void
@@ -567,9 +608,11 @@ persp3d_on_repr_attr_changed ( Inkscape::XML::Node * /*repr*/,
 /* checks whether all boxes linked to this perspective are currently selected */
 bool
 persp3d_has_all_boxes_in_selection (Persp3D *persp) {
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+
     std::list<SPBox3D *> selboxes = sp_desktop_selection(inkscape_active_desktop())->box3DList();
 
-    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
+    for (std::vector<SPBox3D *>::iterator i = persp_impl->boxes.begin(); i != persp_impl->boxes.end(); ++i) {
         if (std::find(selboxes.begin(), selboxes.end(), *i) == selboxes.end()) {
             // we have an unselected box in the perspective
             return false;
@@ -592,11 +635,12 @@ persp3d_unselected_boxes(Inkscape::Selection *selection) {
     // for all perspectives in the list ...
     for (i = plist.begin(); i != plist.end(); ++i) {
         Persp3D *persp = *i;
+        Persp3DImpl *persp_impl = persp->perspective_impl;
         // ... and each box associated to it ...
-        for (j = persp->boxes.begin(); j != persp->boxes.end(); ++j) {
+        for (j = persp_impl->boxes.begin(); j != persp_impl->boxes.end(); ++j) {
             SPBox3D *box = *j;
             // ... check whether it is unselected, and if so add it to the list
-            if (persp->boxes_transformed->find(box) == persp->boxes_transformed->end()) {
+            if (persp_impl->boxes_transformed->find(box) == persp_impl->boxes_transformed->end()) {
                 punsel[persp].push_back(box);
             }
         }
@@ -620,7 +664,8 @@ persp3d_split_perspectives_according_to_selection(Inkscape::Selection *selection
         // ... if the perspective has unselected boxes ...
         if (!(*i).second.empty()) {
             // create a new perspective and move these boxes over
-            Persp3D * new_persp = persp3d_create_xml_element (SP_OBJECT_DOCUMENT(persp), persp);
+            SPDocument *document = SP_OBJECT_DOCUMENT(persp);
+            Persp3D * new_persp = persp3d_create_xml_element (document, persp->perspective_impl);
             for (j = (*i).second.begin(); j != (*i).second.end(); ++j) {
                 SPBox3D *box = *j;
                 box3d_switch_perspectives(box, persp, new_persp);
@@ -633,7 +678,8 @@ persp3d_split_perspectives_according_to_selection(Inkscape::Selection *selection
 
 void
 persp3d_print_debugging_info (Persp3D *persp) {
-    g_print ("=== Info for Persp3D %d ===\n", persp->my_counter);
+    Persp3DImpl *persp_impl = persp->perspective_impl;
+    g_print ("=== Info for Persp3D %d ===\n", persp_impl->my_counter);
     gchar * cstr;
     for (int i = 0; i < 4; ++i) {
         cstr = persp3d_get_VP(persp, Proj::axes[i]).coord_string();
@@ -645,8 +691,8 @@ persp3d_print_debugging_info (Persp3D *persp) {
     g_free(cstr);
 
     g_print ("  Boxes: ");
-    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
-        g_print ("%d (%d)  ", (*i)->my_counter, box3d_get_perspective(*i)->my_counter);
+    for (std::vector<SPBox3D *>::iterator i = persp_impl->boxes.begin(); i != persp_impl->boxes.end(); ++i) {
+        g_print ("%d (%d)  ", (*i)->my_counter, box3d_get_perspective(*i)->perspective_impl->my_counter);
     }
     g_print ("\n");
     g_print ("========================\n");
@@ -674,9 +720,10 @@ persp3d_print_all_selected() {
 
     for (std::list<Persp3D *>::iterator j = sel_persps.begin(); j != sel_persps.end(); ++j) {
         Persp3D *persp = SP_PERSP3D(*j);
-        g_print ("  %s (%d):  ", SP_OBJECT_REPR(persp)->attribute("id"), persp->my_counter);
-        for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed->begin();
-             i != persp->boxes_transformed->end(); ++i) {
+        Persp3DImpl *persp_impl = persp->perspective_impl;
+        g_print ("  %s (%d):  ", SP_OBJECT_REPR(persp)->attribute("id"), persp->perspective_impl->my_counter);
+        for (std::map<SPBox3D *, bool>::iterator i = persp_impl->boxes_transformed->begin();
+             i != persp_impl->boxes_transformed->end(); ++i) {
             g_print ("<%d,%d> ", (*i).first->my_counter, (*i).second);
         }
         g_print ("\n");
@@ -684,6 +731,12 @@ persp3d_print_all_selected() {
     g_print ("======================================\n\n");
  }
 
+void print_current_persp3d(gchar *func_name, Persp3D *persp) {
+    g_print ("%s: current_persp3d is now %s\n",
+             func_name,
+             persp ? SP_OBJECT_REPR(persp)->attribute("id") : "NULL");
+}
+
 /*
   Local Variables:
   mode:c++
index 79bec0232c5372465266a04e90924ade2e8e1481..31a6212c7a9a9b2e5bb4805992a464408dc3e580 100644 (file)
 class SPBox3D;
 class Box3DContext;
 
-struct Persp3D : public SPObject {
+class Persp3DImpl {
+public:
+    Persp3DImpl();
+    ~Persp3DImpl();
+
+//private:
     Proj::TransfMat3x4 tmat;
 
     // Also write the list of boxes into the xml repr and vice versa link boxes to their persp3d?
@@ -39,6 +44,12 @@ struct Persp3D : public SPObject {
 
     // for debugging only
     int my_counter;
+
+//    friend class Persp3D;
+};
+
+struct Persp3D : public SPObject {
+    Persp3DImpl *perspective_impl;
 };
 
 struct Persp3DClass {
@@ -54,20 +65,18 @@ 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);
+    return persp->perspective_impl->tmat.column(axis);
 }
 Geom::Point persp3d_get_PL_dir_from_pt (Persp3D *persp, Geom::Point const &pt, Proj::Axis axis); // convenience wrapper around the following two
 Geom::Point persp3d_get_finite_dir (Persp3D *persp, Geom::Point const &pt, Proj::Axis axis);
 Geom::Point persp3d_get_infinite_dir (Persp3D *persp, Proj::Axis axis);
 double persp3d_get_infinite_angle (Persp3D *persp, Proj::Axis axis);
-bool persp3d_VP_is_finite (Persp3D *persp, Proj::Axis axis);
+bool persp3d_VP_is_finite (Persp3DImpl *persp_impl, Proj::Axis axis);
 void persp3d_toggle_VP (Persp3D *persp, Proj::Axis axis, bool set_undo = true);
 void persp3d_toggle_VPs (std::list<Persp3D *>, Proj::Axis axis);
 void persp3d_set_VP_state (Persp3D *persp, Proj::Axis axis, Proj::VPState state);
 void persp3d_rotate_VP (Persp3D *persp, Proj::Axis axis, double angle, bool alt_pressed); // angle is in degrees
-void persp3d_update_with_point (Persp3D *persp, Proj::Axis const axis, Proj::Pt2 const &new_image);
 void persp3d_apply_affine_transformation (Persp3D *persp, Geom::Matrix const &xform);
-gchar * persp3d_pt_to_str (Persp3D *persp, Proj::Axis const axis);
 
 void persp3d_add_box (Persp3D *persp, SPBox3D *box);
 void persp3d_remove_box (Persp3D *persp, SPBox3D *box);
@@ -83,13 +92,13 @@ void persp3d_unset_transforms(Persp3D *persp);
 void persp3d_update_box_displays (Persp3D *persp);
 void persp3d_update_box_reprs (Persp3D *persp);
 void persp3d_update_z_orders (Persp3D *persp);
-inline unsigned int persp3d_num_boxes (Persp3D *persp) { return persp->boxes.size(); }
+inline unsigned int persp3d_num_boxes (Persp3D *persp) { return persp->perspective_impl->boxes.size(); }
 std::list<SPBox3D *> persp3d_list_of_boxes(Persp3D *persp);
 
 bool persp3d_perspectives_coincide(const Persp3D *lhs, const Persp3D *rhs);
 void persp3d_absorb(Persp3D *persp1, Persp3D *persp2);
 
-Persp3D * persp3d_create_xml_element (SPDocument *document, Persp3D *dup = NULL);
+Persp3D * persp3d_create_xml_element (SPDocument *document, Persp3DImpl *dup = NULL);
 Persp3D * persp3d_document_first_persp (SPDocument *document);
 
 bool persp3d_has_all_boxes_in_selection (Persp3D *persp);
@@ -100,6 +109,12 @@ void persp3d_print_debugging_info (Persp3D *persp);
 void persp3d_print_debugging_info_all(SPDocument *doc);
 void persp3d_print_all_selected();
 
+/* Internally used functions; maybe these should be made more private? */
+void persp3d_update_with_point (Persp3DImpl *persp_impl, Proj::Axis const axis, Proj::Pt2 const &new_image);
+gchar * persp3d_pt_to_str (Persp3DImpl *persp_impl, Proj::Axis const axis);
+
+void print_current_persp3d(gchar *func_name, Persp3D *persp);
+
 #endif /* __PERSP3D_H__ */
 
 /*
index 4d92a18df77948f7de0620a8609566eb9e33075e..ed8a9d57b86034dfcaf4c36915bace17a5ff3671 100644 (file)
@@ -224,7 +224,7 @@ void Selection::remove_box_perspective(SPBox3D *box) {
     Persp3D *persp = box3d_get_perspective(box);
     std::map<Persp3D *, unsigned int>::iterator p = _persps.find(persp);
     if (p == _persps.end()) {
-        g_print ("Warning! Trying to remove unselected perspective from selection!\n");
+        //g_print ("Warning! Trying to remove unselected perspective from selection!\n");
         return;
     }
     if ((*p).second > 1) {
index ab46b21a6c955ee8c69fead5af637fa15cad043d..78ceec4671178a2bf4fb33535d7f0137eeab7af4 100644 (file)
@@ -103,7 +103,7 @@ vp_knot_moved_handler (SPKnot */*knot*/, Geom::Point const *ppointer, guint stat
                 sel_boxes = (*vp)->selectedBoxes(sp_desktop_selection(inkscape_active_desktop()));
 
                 // we create a new perspective ...
-                Persp3D *new_persp = persp3d_create_xml_element (dragger->parent->document, old_persp);
+                Persp3D *new_persp = persp3d_create_xml_element (dragger->parent->document, old_persp->perspective_impl);
 
                 /* ... unlink the boxes from the old one and
                    FIXME: We need to unlink the _un_selected boxes of each VP so that
@@ -230,7 +230,7 @@ unsigned int VanishingPoint::global_counter = 0;
 void
 VanishingPoint::set_pos(Proj::Pt2 const &pt) {
     g_return_if_fail (_persp);
-    _persp->tmat.set_image_pt (_axis, pt);
+    _persp->perspective_impl->tmat.set_image_pt (_axis, pt);
 }
 
 std::list<SPBox3D *>
index 4362139464d0921768721fc4a5aef0d730ba076c..48e22d53f2895d742f6807836f8de9ba11eddfe1 100644 (file)
@@ -3226,7 +3226,7 @@ box3d_set_button_and_adjustment(Persp3D *persp, Proj::Axis axis,
     // 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);
+    bool is_infinite = !persp3d_VP_is_finite(persp->perspective_impl, axis);
 
     if (is_infinite) {
         gtk_toggle_action_set_active(tact, TRUE);
@@ -3254,6 +3254,10 @@ box3d_resync_toolbar(Inkscape::XML::Node *persp_repr, GObject *data) {
     GtkAction *act = 0;
     GtkToggleAction *tact = 0;
     Persp3D *persp = persp3d_get_from_repr(persp_repr);
+    if (!persp) {
+        // Hmm, is it an error if this happens?
+        return;
+    }
     {
         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"));
@@ -3340,7 +3344,7 @@ box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
             sp_repr_synthesize_events(persp_repr, &box3d_persp_tb_repr_events, tbl);
         }
 
-        inkscape_active_document()->current_persp3d = persp3d_get_from_repr(persp_repr);
+        inkscape_active_document()->setCurrentPersp3D(persp3d_get_from_repr(persp_repr));
         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
         prefs->setString("/tools/shapes/3dbox/persp", persp_repr->attribute("id"));
 
@@ -3364,7 +3368,6 @@ box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis ax
     // in turn, prevent listener from responding
     g_object_set_data(dataKludge, "freeze", GINT_TO_POINTER(TRUE));
 
-    //Persp3D *persp = document->current_persp3d;
     std::list<Persp3D *> sel_persps = sp_desktop_selection(desktop)->perspList();
     if (sel_persps.empty()) {
         // this can happen when the document is created; we silently ignore it
@@ -3372,7 +3375,7 @@ box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, Proj::Axis ax
     }
     Persp3D *persp = sel_persps.front();
 
-    persp->tmat.set_infinite_direction (axis, adj->value);
+    persp->perspective_impl->tmat.set_infinite_direction (axis, adj->value);
     SP_OBJECT(persp)->updateRepr();
 
     // TODO: use the correct axis here, too
@@ -3435,7 +3438,7 @@ static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions,
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
     EgeAdjustmentAction* eact = 0;
     SPDocument *document = sp_desktop_document (desktop);
-    Persp3D *persp = document->current_persp3d;
+    Persp3DImpl *persp_impl = document->getCurrentPersp3DImpl();
 
     EgeAdjustmentAction* box3d_angle_x = 0;
     EgeAdjustmentAction* box3d_angle_y = 0;
@@ -3459,7 +3462,7 @@ static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions,
         box3d_angle_x = eact;
     }
 
-    if (!persp3d_VP_is_finite(persp, Proj::X)) {
+    if (!persp3d_VP_is_finite(persp_impl, Proj::X)) {
         gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
     } else {
         gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
@@ -3499,7 +3502,7 @@ static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions,
         box3d_angle_y = eact;
     }
 
-    if (!persp3d_VP_is_finite(persp, Proj::Y)) {
+    if (!persp3d_VP_is_finite(persp_impl, Proj::Y)) {
         gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
     } else {
         gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
@@ -3538,7 +3541,7 @@ static void box3d_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions,
         box3d_angle_z = eact;
     }
 
-    if (!persp3d_VP_is_finite(persp, Proj::Z)) {
+    if (!persp3d_VP_is_finite(persp_impl, Proj::Z)) {
         gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
     } else {
         gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
@@ -3988,6 +3991,7 @@ sp_pencil_tb_tolerance_value_changed(GtkAdjustment *adj, GObject *tbl)
     g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
 }
 
+/*
 class PencilToleranceObserver : public Inkscape::Preferences::Observer {
 public:
     PencilToleranceObserver(Glib::ustring const &path, GObject *x) : Observer(path), _obj(x)
@@ -4015,7 +4019,7 @@ public:
 private:
     GObject *_obj;
 };
-
+*/
 
 static void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
 {
@@ -4040,9 +4044,6 @@ static void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActio
                                          1, 2);
         ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
         gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
-
-        PencilToleranceObserver *obs =
-            new PencilToleranceObserver("/tools/freehand/pencil/tolerance", G_OBJECT(holder));
     }
 
     /* advanced shape options */
@@ -6218,7 +6219,7 @@ sp_text_toolbox_selection_modified (Inkscape::Selection *selection, guint /*flag
 }
 
 void
-sp_text_toolbox_subselection_changed (gpointer /*dragger*/, GObject *tbl)
+sp_text_toolbox_subselection_changed (gpointer /*tc*/, GObject *tbl)
 {
     sp_text_toolbox_selection_changed (NULL, tbl);
 }