Code

Hold perspectives on document level rather than globally; this corrects the changes...
authorcilix42 <cilix42@users.sourceforge.net>
Thu, 9 Aug 2007 23:49:05 +0000 (23:49 +0000)
committercilix42 <cilix42@users.sourceforge.net>
Thu, 9 Aug 2007 23:49:05 +0000 (23:49 +0000)
12 files changed:
src/box3d-context.cpp
src/box3d-face.cpp
src/box3d-face.h
src/box3d.cpp
src/document.cpp
src/document.h
src/inkscape.cpp
src/perspective3d.cpp
src/perspective3d.h
src/vanishing-point.cpp
src/vanishing-point.h
src/widgets/toolbox.cpp

index 0ef2277ea0a638e50c8729aa588112dfc69ba405..667bfca610b76d62bf4c100652d7c81de02164ec 100644 (file)
@@ -192,7 +192,7 @@ void sp_3dbox_context_selection_changed(Inkscape::Selection *selection, gpointer
             sp_repr_add_listener(shape_repr, &ec_shape_repr_events, ec);
         }
         if (SP_IS_3DBOX (item)) {
-            Box3D::Perspective3D::current_perspective = Box3D::get_persp_of_box (SP_3DBOX (item));
+            bc->_vpdrag->document->current_perspective = bc->_vpdrag->document->get_persp_of_box (SP_3DBOX (item));
         }
     } else {
         /* If several boxes sharing the same perspective are selected,
@@ -200,11 +200,11 @@ void sp_3dbox_context_selection_changed(Inkscape::Selection *selection, gpointer
         std::set<Box3D::Perspective3D *> perspectives;
         for (GSList *i = (GSList *) selection->itemList(); i != NULL; i = i->next) {
             if (SP_IS_3DBOX (i->data)) {
-                perspectives.insert (Box3D::get_persp_of_box (SP_3DBOX (i->data)));
+                perspectives.insert (bc->_vpdrag->document->get_persp_of_box (SP_3DBOX (i->data)));
             }
         }
         if (perspectives.size() == 1) {
-            Box3D::Perspective3D::current_perspective = *(perspectives.begin());
+            bc->_vpdrag->document->current_perspective = *(perspectives.begin());
         }
         // TODO: What to do if several boxes with different perspectives are selected?
     }
@@ -234,7 +234,7 @@ static void sp_3dbox_context_setup(SPEventContext *ec)
         sigc::bind(sigc::ptr_fun(&sp_3dbox_context_selection_changed), (gpointer)bc)
     );
 
-    bc->_vpdrag = new Box3D::VPDrag(ec->desktop);
+    bc->_vpdrag = new Box3D::VPDrag(sp_desktop_document (ec->desktop));
 
     if (prefs_get_int_attribute("tools.shapes", "selcue", 0) != 0) {
         ec->enableSelectionCue();
@@ -375,18 +375,18 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven
                 // Without Ctrl, motion of the extruded corner is constrained to the
                 // perspective line from drag_ptB to vanishing point Y.
                 if (!bc->ctrl_dragged) {
-                       bc->drag_ptC = Box3D::perspective_line_snap (bc->drag_ptB, Box3D::Z, motion_dt, Box3D::Perspective3D::current_perspective);
+                       bc->drag_ptC = Box3D::perspective_line_snap (bc->drag_ptB, Box3D::Z, motion_dt, bc->_vpdrag->document->current_perspective);
                 } else {
                     bc->drag_ptC = motion_dt;
                 }
                 bc->drag_ptC = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, bc->drag_ptC, bc->item).getPoint();
                 if (bc->ctrl_dragged) {
-                       Box3D::PerspectiveLine pl1 (NR::Point (event_context->xp, event_context->yp), Box3D::Y, Box3D::Perspective3D::current_perspective);
-                       Box3D::PerspectiveLine pl2 (bc->drag_ptB, Box3D::X, Box3D::Perspective3D::current_perspective);
+                       Box3D::PerspectiveLine pl1 (NR::Point (event_context->xp, event_context->yp), Box3D::Y, bc->_vpdrag->document->current_perspective);
+                       Box3D::PerspectiveLine pl2 (bc->drag_ptB, Box3D::X, bc->_vpdrag->document->current_perspective);
                        NR::Point corner1 = pl1.meet(pl2);
                        
-                       Box3D::PerspectiveLine pl3 (corner1, Box3D::X, Box3D::Perspective3D::current_perspective);
-                       Box3D::PerspectiveLine pl4 (bc->drag_ptC, Box3D::Z, Box3D::Perspective3D::current_perspective);
+                       Box3D::PerspectiveLine pl3 (corner1, Box3D::X, bc->_vpdrag->document->current_perspective);
+                       Box3D::PerspectiveLine pl4 (bc->drag_ptC, Box3D::Z, bc->_vpdrag->document->current_perspective);
                        bc->drag_ptB = pl3.meet(pl4);
                 }
             }
@@ -477,8 +477,7 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven
         case GDK_X:
         {
             if (MOD__CTRL) break; // Don't catch Ctrl+X ('cut') and Ctrl+Shift+X ('open XML editor')
-            // FIXME: Shouldn't we access _vpdrag->selection instead?
-            Inkscape::Selection *selection = sp_desktop_selection (bc->_vpdrag->desktop);
+            Inkscape::Selection *selection = sp_desktop_selection (inkscape_active_desktop());
             for (GSList const *i = selection->itemList(); i != NULL; i = i->next) {
                 if (!SP_IS_3DBOX (i->data)) continue;
                 sp_3dbox_switch_front_face (SP_3DBOX (i->data), Box3D::X);
@@ -492,8 +491,7 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven
         case GDK_Y:
         {
             if (MOD__CTRL) break; // Don't catch Ctrl+Y ("redo")
-            // FIXME: Shouldn't we access _vpdrag->selection instead?
-            Inkscape::Selection *selection = sp_desktop_selection (bc->_vpdrag->desktop);
+            Inkscape::Selection *selection = sp_desktop_selection (inkscape_active_desktop());
             for (GSList const *i = selection->itemList(); i != NULL; i = i->next) {
                 if (!SP_IS_3DBOX (i->data)) continue;
                 sp_3dbox_switch_front_face (SP_3DBOX (i->data), Box3D::Y);
@@ -507,8 +505,7 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven
         case GDK_Z:
         {
             if (MOD__CTRL) break; // Don't catch Ctrl+Z ("undo")
-            // FIXME: Shouldn't we access _vpdrag->selection instead?
-            Inkscape::Selection *selection = sp_desktop_selection (bc->_vpdrag->desktop);
+            Inkscape::Selection *selection = sp_desktop_selection (inkscape_active_desktop());
             for (GSList const *i = selection->itemList(); i != NULL; i = i->next) {
                 if (!SP_IS_3DBOX (i->data)) continue;
                 sp_3dbox_switch_front_face (SP_3DBOX (i->data), Box3D::Z);
index 55dc9b60aed28345ec127f919863f2069ade39f4..096e7d7a6bbbd9868bbef2e94c6699f95b1f3178 100644 (file)
@@ -121,6 +121,7 @@ Box3DFace::Box3DFace(Box3DFace const &box3dface)
  * 
  * Note that several other functions rely on this precise order.
  */
+/***
 void
 Box3DFace::set_face (NR::Point const A, NR::Point const C, Box3D::Axis const axis1, Box3D::Axis const axis2)
 {
@@ -149,7 +150,7 @@ Box3DFace::set_face (NR::Point const A, NR::Point const C, Box3D::Axis const axi
     this->dir1 = axis1;
     this->dir2 = axis2;
 }
-
+***/
 
 NR::Point Box3DFace::operator[](unsigned int i)
 {
index 0e911cccfdbe84a1d18878ac63586d47767441e7..e69c81e24c8e557295a575491f7bfbb713259dc8 100644 (file)
@@ -40,7 +40,7 @@ public:
                    bool align_along_PL = false);
     ***/
     void set_corners (NR::Point &A, NR::Point &B, NR::Point &C, NR::Point &D);
-    void set_face (NR::Point const A, NR::Point const C, Box3D::Axis const dir1, Box3D::Axis const dir2);
+    //void set_face (NR::Point const A, NR::Point const C, Box3D::Axis const dir1, Box3D::Axis const dir2);
     
     void hook_path_to_3dbox(SPPath * existing_path = NULL);
     void set_path_repr();
index 966d762a1f4bef81361b59b2afa99972ec3b151f..c9c03ea9cefc88e666fb0f6b5052ea033ff44a06 100644 (file)
@@ -110,19 +110,21 @@ sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr
 
     box->front_bits = 0x0;
 
+    
     if (repr->attribute ("inkscape:perspective") == NULL) {
         // we are creating a new box; link it to the current perspective
-        Box3D::Perspective3D::current_perspective->add_box (box);
+        document->current_perspective->add_box (box);
     } else {
         // create a new perspective that we can compare with existing ones
         Box3D::Perspective3D *persp = new Box3D::Perspective3D (Box3D::VanishingPoint (0,0),
                                                                 Box3D::VanishingPoint (0,0),
-                                                                Box3D::VanishingPoint (0,0));
+                                                                Box3D::VanishingPoint (0,0),
+                                                                document);
         sp_3dbox_update_perspective (persp, repr->attribute ("inkscape:perspective"));
-        Box3D::Perspective3D *comp =  Box3D::Perspective3D::find_perspective (persp);
+        Box3D::Perspective3D *comp =  document->find_perspective (persp);
         if (comp == NULL) {
             // perspective doesn't exist yet
-            Box3D::Perspective3D::add_perspective (persp);
+            document->add_perspective (persp);
             persp->add_box (box);
         } else {
             // link the box to the existing perspective and delete the temporary one
@@ -166,7 +168,7 @@ sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr
     // document (e.g., after a 'redo' operation or after opening a file) and do so if necessary.
     sp_3dbox_link_to_existing_paths (box, repr);
 
-    sp_3dbox_set_ratios (box);
+    sp_3dbox_set_ratios (box, Box3D::XYZ);
 }
 
 static void
@@ -181,7 +183,7 @@ sp_3dbox_release (SPObject *object)
 
         // FIXME: We do not duplicate perspectives if they are the same for several boxes.
         //        Thus, don't delete the perspective when deleting a box but rather unlink the box from it.
-        Box3D::get_persp_of_box (box)->remove_box (box);
+        SP_OBJECT_DOCUMENT (G_OBJECT (box))->get_persp_of_box (box)->remove_box (box);
 
        if (((SPObjectClass *) parent_class)->release) {
          ((SPObjectClass *) parent_class)->release (object);
@@ -201,8 +203,11 @@ static void sp_3dbox_set(SPObject *object, unsigned int key, const gchar *value)
             sp_3dbox_update_corner_with_value_from_svg (object, 5, value);
             break;
         case SP_ATTR_INKSCAPE_3DBOX_PERSPECTIVE:
-            sp_3dbox_update_perspective (Box3D::get_persp_of_box (SP_3DBOX (object)), value);
+        {
+            SP3DBox *box = SP_3DBOX (object);
+            sp_3dbox_update_perspective (SP_OBJECT_DOCUMENT (object)->get_persp_of_box (box), value);
             break;
+        }
        default:
             if (((SPObjectClass *) (parent_class))->set) {
                 ((SPObjectClass *) (parent_class))->set(object, key, value);
@@ -283,7 +288,7 @@ sp_3dbox_description(SPItem *item)
 
 void sp_3dbox_set_ratios (SP3DBox *box, Box3D::Axis axes)
 {
-    Box3D::Perspective3D *persp = Box3D::get_persp_of_box (box);
+    Box3D::Perspective3D *persp = SP_OBJECT_DOCUMENT (G_OBJECT (box))->get_persp_of_box (box);
     NR::Point pt;
 
     if (axes & Box3D::X) {
@@ -305,7 +310,7 @@ void sp_3dbox_set_ratios (SP3DBox *box, Box3D::Axis axes)
 void
 sp_3dbox_switch_front_face (SP3DBox *box, Box3D::Axis axis)
 {
-    if (Box3D::get_persp_of_box (box)->get_vanishing_point (axis)->is_finite()) {
+    if (SP_OBJECT_DOCUMENT (G_OBJECT (box))->get_persp_of_box (box)->get_vanishing_point (axis)->is_finite()) {
         box->front_bits = box->front_bits ^ axis;
     }
 }
@@ -386,7 +391,7 @@ normalized_angle (double angle) {
 static gdouble
 sp_3dbox_corner_angle_to_VP (SP3DBox *box, Box3D::Axis axis, guint extreme_corner)
 {
-    Box3D::VanishingPoint *vp = Box3D::get_persp_of_box (box)->get_vanishing_point (axis);
+    Box3D::VanishingPoint *vp = SP_OBJECT_DOCUMENT (G_OBJECT (box))->get_persp_of_box (box)->get_vanishing_point (axis);
     NR::Point dir;
 
     if (vp->is_finite()) {
@@ -403,7 +408,7 @@ bool sp_3dbox_recompute_z_orders (SP3DBox *box)
 {
     guint new_z_orders[6];
 
-    Box3D::Perspective3D *persp = Box3D::get_persp_of_box (box);
+    Box3D::Perspective3D *persp = SP_OBJECT_DOCUMENT (G_OBJECT (box))->get_persp_of_box (box);
 
     // TODO: Determine the front corner depending on the distance from VPs and/or the user presets
     guint front_corner = sp_3dbox_get_front_corner_id (box);
@@ -523,7 +528,7 @@ sp_3dbox_link_to_existing_paths (SP3DBox *box, Inkscape::XML::Node *repr) {
 void
 sp_3dbox_move_corner_in_XY_plane (SP3DBox *box, guint id, NR::Point pt, Box3D::Axis axes)
 {
-    Box3D::Perspective3D * persp = Box3D::get_persp_of_box (box);
+    Box3D::Perspective3D * persp = SP_OBJECT_DOCUMENT (G_OBJECT (box))->get_persp_of_box (box);
 
     NR::Point A (box->corners[id ^ Box3D::XY]);
     if (Box3D::is_single_axis_direction (axes)) {
@@ -563,7 +568,7 @@ sp_3dbox_move_corner_in_Z_direction (SP3DBox *box, guint id, NR::Point pt, bool
 {
     if (!constrained) sp_3dbox_move_corner_in_XY_plane (box, id, pt, Box3D::XY);
 
-    Box3D::Perspective3D * persp = Box3D::get_persp_of_box (box);
+    Box3D::Perspective3D * persp = SP_OBJECT_DOCUMENT (G_OBJECT (box))->get_persp_of_box (box);
 
     /* set the four corners of the face containing corners[id] */
     box->corners[id] = Box3D::PerspectiveLine (box->corners[id], Box3D::Z, persp).closest_to(pt);
@@ -609,7 +614,7 @@ sp_3dbox_reshape_edge_after_VP_toggling (SP3DBox *box, const guint corner, const
 void
 sp_3dbox_reshape_after_VP_toggling (SP3DBox *box, Box3D::Axis axis)
 {
-    Box3D::Perspective3D *persp = Box3D::get_persp_of_box (box);
+    Box3D::Perspective3D *persp = SP_OBJECT_DOCUMENT (G_OBJECT (box))->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);
@@ -641,7 +646,7 @@ sp_3dbox_get_midpoint_between_corners (SP3DBox *box, guint id_corner1, guint id_
 
         if (!adjacent_face_center) return NR::Nothing();
 
-        Box3D::Perspective3D * persp = Box3D::get_persp_of_box (box);
+        Box3D::Perspective3D * persp = SP_OBJECT_DOCUMENT (G_OBJECT (box))->get_persp_of_box (box);
 
         Box3D::PerspectiveLine pl (*adjacent_face_center, orth_dir, persp);
         return pl.intersect(Box3D::PerspectiveLine(box->corners[id_corner1], corner_axes, persp));
@@ -685,7 +690,7 @@ static gchar *
 sp_3dbox_get_perspective_string (SP3DBox *box)
 {
     
-    return sp_3dbox_get_svg_descr_of_persp (Box3D::get_persp_of_box (box));
+    return sp_3dbox_get_svg_descr_of_persp (SP_OBJECT_DOCUMENT (G_OBJECT (box))->get_persp_of_box (box));
 }
   
 gchar *
@@ -779,7 +784,7 @@ sp_3dbox_get_corner_id_along_edge (const SP3DBox *box, guint corner, Box3D::Axis
 {
     guint result;
     guint other_corner = corner ^ axis;
-    Box3D::VanishingPoint *vp = Box3D::get_persp_of_box (box)->get_vanishing_point(axis);
+    Box3D::VanishingPoint *vp = SP_OBJECT_DOCUMENT (G_OBJECT (box))->get_persp_of_box (box)->get_vanishing_point(axis);
     if (vp->is_finite()) {
         result = (  NR::L2 (vp->get_pos() - box->corners[corner])
                   < NR::L2 (vp->get_pos() - box->corners[other_corner]) ? other_corner : corner);
index 252c9b17379070e296bc2cc7b058400b42b841da..2a482648f1044ea6f22e61f5f5f9744e4facf78a 100644 (file)
@@ -53,6 +53,7 @@
 #include "libavoid/router.h"
 #include "libnr/nr-rect.h"
 #include "sp-item-group.h"
+#include "perspective3d.h"
 
 #include "display/nr-arena-item.h"
 
@@ -96,6 +97,23 @@ SPDocument::SPDocument() {
     // Don't use the Consolidate moves optimisation.
     router->ConsolidateMoves = false;
 
+    perspectives = NULL;
+
+    /* Create an initial perspective, make it current and append it to the list of existing perspectives */
+    current_perspective = new Box3D::Perspective3D (
+                              // VP in x-direction
+                              Box3D::VanishingPoint( NR::Point(-50.0, 600.0),
+                                                     NR::Point( -1.0,   0.0), Box3D::VP_FINITE),
+                              // VP in y-direction
+                              Box3D::VanishingPoint( NR::Point(500.0,1000.0),
+                                                     NR::Point(  0.0,   1.0), Box3D::VP_INFINITE),
+                              // VP in z-direction
+                              Box3D::VanishingPoint( NR::Point(700.0, 600.0),
+                                                     NR::Point(sqrt(3.0),1.0), Box3D::VP_FINITE),
+                              this);
+
+    add_perspective (current_perspective);    
+
     p = new SPDocumentPrivate();
 
     p->serial = next_serial++;
@@ -184,6 +202,66 @@ SPDocument::~SPDocument() {
     }
 
     //delete this->_whiteboard_session_manager;
+
+    current_perspective = NULL;
+    // TODO: Do we have to delete the perspectives?
+    /***
+    for (GSList *i = perspectives; i != NULL; ++i) {
+        delete ((Box3D::Perspective3D *) i->data);
+    }
+    g_slist_free (perspectives);
+    ***/
+}
+
+void SPDocument::add_perspective (Box3D::Perspective3D * const persp)
+{
+    // FIXME: Should we handle the case that the perspectives have equal VPs but are not identical?
+    //        If so, we need to take care of relinking the boxes, etc.
+    if (persp == NULL || g_slist_find (perspectives, persp)) return;
+    perspectives = g_slist_prepend (perspectives, persp);
+}
+
+void SPDocument::remove_perspective (Box3D::Perspective3D * const persp)
+{
+    if (persp == NULL || !g_slist_find (perspectives, persp)) return;
+    perspectives = g_slist_remove (perspectives, persp);
+}
+
+// find an existing perspective whose VPs are equal to those of persp
+Box3D::Perspective3D * SPDocument::find_perspective (const Box3D::Perspective3D * persp)
+{
+    for (GSList *p = perspectives; p != NULL; p = p->next) {
+        if (*((Box3D::Perspective3D *) p->data) == *persp) {
+            return ((Box3D::Perspective3D *) p->data);
+        }
+    }
+    return NULL; // perspective was not found
+}
+
+Box3D::Perspective3D * SPDocument::get_persp_of_box (const SP3DBox *box)
+{
+    for (GSList *p = perspectives; p != NULL; p = p->next) {
+        if (((Box3D::Perspective3D *) p->data)->has_box (box))
+            return (Box3D::Perspective3D *) p->data;
+    }
+    g_warning ("Stray 3D box!\n");
+    g_assert_not_reached();
+}
+
+Box3D::Perspective3D * SPDocument::get_persp_of_VP (const Box3D::VanishingPoint *vp)
+{
+    Box3D::Perspective3D *persp;
+    for (GSList *p = perspectives; p != NULL; p = p->next) {
+        persp = (Box3D::Perspective3D *) p->data;
+        // we compare the pointers, not the position/state of the VPs; is this correct?
+        if (persp->get_vanishing_point (Box3D::X) == vp ||
+            persp->get_vanishing_point (Box3D::Y) == vp ||
+            persp->get_vanishing_point (Box3D::Z) == vp)
+            return persp;
+    }
+
+    g_warning ("Stray vanishing point!\n");
+    g_assert_not_reached();
 }
 
 unsigned long SPDocument::serial() const {
index 16300d170e1fa2a749c4385bd79ab8fa9d208bd8..c04ed5441db175af559cb5b8a33b5f65e229ae05 100644 (file)
@@ -51,6 +51,13 @@ namespace Inkscape {
     }
 }
 
+class SP3DBox;
+
+namespace Box3D {
+  class Perspective3D;
+  class VanishingPoint;
+}
+
 class SPDocumentPrivate;
 
 /// Typed SVG document implementation.
@@ -92,6 +99,19 @@ struct SPDocument : public Inkscape::GC::Managed<>,
        // Instance of the connector router
        Avoid::Router *router;
 
+        GSList *perspectives;
+        Box3D::Perspective3D *current_perspective;
+
+        // FIXME: Perspectives should be linked to the list of existing ones automatically in the constructor
+        //        and removed in the destructor!
+        void add_perspective (Box3D::Perspective3D * const persp);
+        void remove_perspective (Box3D::Perspective3D * const persp);
+        /* find an existing perspective whose VPs are equal to those of persp */
+        Box3D::Perspective3D * find_perspective (const Box3D::Perspective3D * persp);
+
+        Box3D::Perspective3D * get_persp_of_box (const SP3DBox *box);
+        Box3D::Perspective3D * get_persp_of_VP (const Box3D::VanishingPoint *vp);
+
        sigc::connection connectModified(ModifiedSignal::slot_type slot);
        sigc::connection connectURISet(URISetSignal::slot_type slot);
        sigc::connection connectResized(ResizedSignal::slot_type slot);
index 8f76edddfa92916cbf7fa0585d1329a56c450ed4..c167be493c0900a05a12b9560472da180c80b6a8 100644 (file)
@@ -59,7 +59,6 @@ using Inkscape::Extension::Internal::PrintWin32;
 #include "prefs-utils.h"
 #include "xml/repr.h"
 #include "io/sys.h"
-#include "perspective3d.h"
 
 #include "extension/init.h"
 
@@ -598,21 +597,6 @@ inkscape_application_init (const gchar *argv0, gboolean use_gui)
     /* Initialize the extensions */
     Inkscape::Extension::init();
 
-    /* Create an initial perspective, append it to the list of existing perspectives and make it current */
-    Box3D::Perspective3D *initial_persp = new Box3D::Perspective3D (
-                                          // VP in x-direction
-                                          Box3D::VanishingPoint( NR::Point(-50.0, 600.0),
-                                                                 NR::Point( -1.0,   0.0), Box3D::VP_FINITE),
-                                          // VP in y-direction
-                                          Box3D::VanishingPoint( NR::Point(500.0,1000.0),
-                                                                 NR::Point(  0.0,   1.0), Box3D::VP_INFINITE),
-                                          // VP in z-direction
-                                          Box3D::VanishingPoint( NR::Point(700.0, 600.0),
-                                                                 NR::Point(sqrt(3.0),1.0), Box3D::VP_FINITE));
-
-    Box3D::Perspective3D::current_perspective = initial_persp;
-    Box3D::Perspective3D::add_perspective (initial_persp);
-
     return;
 }
 
index c7592a06f0702e4749cdcbe981473bf6414cafcb..0d4877f37ec83f406f8913e832b9df2093545b10 100644 (file)
@@ -16,6 +16,7 @@
 #include "perspective-line.h"
 #include <iostream>
 #include "perspective3d.h"
+#include "desktop-handles.h"
 
 // can probably be removed later
 #include "inkscape.h"
 namespace Box3D {
 
 gint Perspective3D::counter = 0;
-GSList * Perspective3D::perspectives = NULL;
-Perspective3D * Perspective3D::current_perspective = NULL;
-
-Perspective3D *
-get_persp_of_box (const SP3DBox *box)
-{
-    for (GSList *p = Perspective3D::perspectives; p != NULL; p = p->next) {
-        if (((Perspective3D *) p->data)->has_box (box))
-            return (Perspective3D *) p->data;
-    }
-    g_warning ("Stray 3D box!\n");
-    g_assert_not_reached();
-}
-
-Perspective3D *
-get_persp_of_VP (const VanishingPoint *vp)
-{
-    Perspective3D *persp;
-    for (GSList *p = Perspective3D::perspectives; p != NULL; p = p->next) {
-        persp = (Perspective3D *) p->data;
-        // we compare the pointers, not the position/state of the VPs; is this correct?
-        if (persp->get_vanishing_point (Box3D::X) == vp ||
-            persp->get_vanishing_point (Box3D::Y) == vp ||
-            persp->get_vanishing_point (Box3D::Z) == vp)
-            return persp;
-    }
-
-    g_warning ("Stray vanishing point!\n");
-    g_assert_not_reached();
-}
 
 /**
  * Computes the intersection of the two perspective lines from pt1 and pt2 to the respective
@@ -80,14 +51,19 @@ perspective_line_snap (NR::Point line_pt, Box3D::Axis dir, NR::Point ext_pt, Per
     return PerspectiveLine(line_pt, dir, persp).closest_to(ext_pt);
 }  
 
-Perspective3D::Perspective3D (VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z)
-    : boxes (NULL)
+Perspective3D::Perspective3D (VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z, SPDocument *doc)
+    : boxes (NULL),
+      document (doc)
 {
     vp_x = new VanishingPoint (pt_x);
     vp_y = new VanishingPoint (pt_y);
     vp_z = new VanishingPoint (pt_z);
 
     my_counter = Perspective3D::counter++;
+
+    if (document == NULL) {
+        g_warning ("What to do now?\n");
+    }
 }
 
 Perspective3D::Perspective3D (Perspective3D &other)
@@ -98,11 +74,17 @@ Perspective3D::Perspective3D (Perspective3D &other)
     vp_z = new VanishingPoint (*other.vp_z);
 
     my_counter = Perspective3D::counter++;
+
+    document = other.document;
 }
 
 Perspective3D::~Perspective3D ()
 {
-    Perspective3D::remove_perspective (this);
+    if (document) {
+        document->remove_perspective (this);
+    } else {
+        g_warning ("No document found!\n");
+    }
 
     // Remove the VPs from their draggers
     SPEventContext *ec = inkscape_active_event_context();
@@ -368,39 +350,11 @@ Perspective3D::svg_string ()
 }
 ***/
 
-void
-Perspective3D::add_perspective (Box3D::Perspective3D * const persp)
-{
-    // FIXME: Should we handle the case that the perspectives have equal VPs but are not identical?
-    //        If so, we need to take care of relinking the boxes, etc.
-    if (persp == NULL || g_slist_find (Perspective3D::perspectives, persp)) return;
-    Perspective3D::perspectives = g_slist_prepend (Perspective3D::perspectives, persp);
-}
-
-void
-Perspective3D::remove_perspective (Box3D::Perspective3D * const persp)
-{
-    if (persp == NULL || !g_slist_find (Perspective3D::perspectives, persp)) return;
-    Perspective3D::perspectives = g_slist_remove (Perspective3D::perspectives, persp);
-}
-
-// find an existing perspective whose VPs are equal to those of persp
-Box3D::Perspective3D *
-Perspective3D::find_perspective (Box3D::Perspective3D * const persp)
-{
-    for (GSList *p = Perspective3D::perspectives; p != NULL; p = p->next) {
-        if (*((Box3D::Perspective3D *) p->data) == *persp) {
-            return ((Box3D::Perspective3D *) p->data);
-        }
-    }
-    return NULL; // perspective was not found
-}
-
 void
 Perspective3D::print_debugging_info ()
 {
     g_print ("====================================================\n");
-    for (GSList *i = Perspective3D::perspectives; i != NULL; i = i->next) {
+    for (GSList *i = sp_desktop_document (inkscape_active_desktop())->perspectives; i != NULL; i = i->next) {
         Perspective3D *persp = (Perspective3D *) i->data;
         g_print ("Perspective %d:\n", persp->my_counter);
 
index 4dd309b1f6513a6fc64d41b44e4041b256330002..a56003393e026f16833a6cd8685d87766c419d9e 100644 (file)
@@ -24,7 +24,7 @@ class PerspectiveLine;
 
 class Perspective3D {
 public:
-    Perspective3D(VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z);
+    Perspective3D(VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z, SPDocument *document);
     Perspective3D(Perspective3D &other);
     ~Perspective3D();
 
@@ -53,15 +53,6 @@ public:
     static gint counter; // for testing only
     gint my_counter; // for testing only
 
-    static GSList * perspectives; // All existing 3D perspectives
-    // FIXME: Perspectives should be linked to the list of existing ones automatically in the constructor
-    //        and removed in the destructor!
-    static void add_perspective (Box3D::Perspective3D * const persp);
-    static void remove_perspective (Box3D::Perspective3D * const persp);
-
-    /* find an existing perspective whose VPs are equal to those of persp */
-    static Box3D::Perspective3D * find_perspective (Box3D::Perspective3D * const persp);
-
     static void print_debugging_info();
     static Perspective3D * current_perspective;
 
@@ -70,11 +61,9 @@ private:
     VanishingPoint *vp_y;
     VanishingPoint *vp_z;
     GSList * boxes; // holds a list of boxes sharing this specific perspective
+    SPDocument * document;
 };
 
-Perspective3D * get_persp_of_box (const SP3DBox *box);
-Perspective3D * get_persp_of_VP (const VanishingPoint *vp);
-
 NR::Point perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point pt2, Box3D::Axis dir2, Perspective3D *persp);
 NR::Point perspective_line_snap (NR::Point pt, Box3D::Axis dir, NR::Point ext_pt, Perspective3D *persp);
 
index 5cd8332a3fb470b6e28a28ceac7bc528f36a662a..ac7300b157810bc2624cddef6fe468e45f7b4ce7 100644 (file)
@@ -178,7 +178,7 @@ have_VPs_of_same_perspective (VPDragger *dr1, VPDragger *dr2)
 {
     Perspective3D *persp;
     for (GSList *i = dr1->vps; i != NULL; i = i->next) {
-        persp = get_persp_of_VP ((VanishingPoint *) i->data);
+        persp = dr1->parent->document->get_persp_of_VP ((VanishingPoint *) i->data);
         if (dr2->hasPerspective (persp)) {
             return true;
         }
@@ -195,7 +195,7 @@ vp_knot_moved_handler (SPKnot *knot, NR::Point const *ppointer, guint state, gpo
     NR::Point p = *ppointer;
 
     // FIXME: take from prefs
-    double snap_dist = SNAP_DIST / drag->desktop->current_zoom();
+    double snap_dist = SNAP_DIST / inkscape_active_desktop()->current_zoom();
 
     if (!(state & GDK_SHIFT_MASK)) {
         // without Shift; see if we need to snap to another dragger
@@ -302,7 +302,7 @@ vp_knot_grabbed_handler (SPKnot *knot, unsigned int state, gpointer data)
 
             for (GSList *i = boxes_to_do; i != NULL; i = i->next) {
                 SP3DBox *box = SP_3DBOX (i->data);
-                Perspective3D *persp = get_persp_of_box (box);
+                Perspective3D *persp = drag->document->get_persp_of_box (box);
                 VanishingPoint *vp = dr_new->getVPofPerspective (persp);
                 if (vp == NULL) {
                     g_warning ("VP is NULL. We should be okay, though.\n");
@@ -318,7 +318,7 @@ vp_knot_grabbed_handler (SPKnot *knot, unsigned int state, gpointer data)
                     /* otherwise the unselected boxes need to stay linked to dr_new; thus we
                        create a new perspective and link the VPs to the correct draggers */
                     Perspective3D *persp_new = new Perspective3D (*persp);
-                    Perspective3D::add_perspective (persp_new);
+                    drag->document->add_perspective (persp_new);
 
                     Axis vp_axis = persp->get_axis_of_VP (vp);
                     dragger->addVP (persp_new->get_vanishing_point (vp_axis));
@@ -382,7 +382,7 @@ VPDragger::VPDragger(VPDrag *parent, NR::Point p, VanishingPoint *vp)
     this->point_original = p;
 
     // create the knot
-    this->knot = sp_knot_new (parent->desktop, NULL);
+    this->knot = sp_knot_new (inkscape_active_desktop(), NULL);
     this->knot->setMode(SP_KNOT_MODE_XOR);
     this->knot->setFill(VP_KNOT_COLOR_NORMAL, VP_KNOT_COLOR_NORMAL, VP_KNOT_COLOR_NORMAL);
     this->knot->setStroke(0x000000ff, 0x000000ff, 0x000000ff);
@@ -523,7 +523,7 @@ bool
 VPDragger::hasBox(const SP3DBox *box)
 {
     for (GSList *i = this->vps; i != NULL; i = i->next) {
-        if (get_persp_of_VP ((VanishingPoint *) i->data)->has_box (box)) return true;
+        if (parent->document->get_persp_of_VP ((VanishingPoint *) i->data)->has_box (box)) return true;
     }
     return false;
 }
@@ -533,7 +533,7 @@ VPDragger::numberOfBoxes ()
 {
     guint num = 0;
     for (GSList *i = this->vps; i != NULL; i = i->next) {
-        num += get_persp_of_VP ((VanishingPoint *) i->data)->number_of_boxes ();
+        num += parent->document->get_persp_of_VP ((VanishingPoint *) i->data)->number_of_boxes ();
     }
     return num;
 }
@@ -542,7 +542,7 @@ bool
 VPDragger::hasPerspective (const Perspective3D *persp)
 {
     for (GSList *i = this->vps; i != NULL; i = i->next) {
-        if (*persp == *get_persp_of_VP ((VanishingPoint *) i->data)) {
+        if (*persp == *parent->document->get_persp_of_VP ((VanishingPoint *) i->data)) {
             return true;
         }        
     }
@@ -555,11 +555,11 @@ VPDragger::mergePerspectives ()
     Perspective3D *persp1, *persp2;
     GSList * successor = NULL;
     for (GSList *i = this->vps; i != NULL; i = i->next) {
-        persp1 = get_persp_of_VP ((VanishingPoint *) i->data);
+        persp1 = parent->document->get_persp_of_VP ((VanishingPoint *) i->data);
         for (GSList *j = i->next; j != NULL; j = successor) {
             // if the perspective is deleted, the VP is invalidated, too, so we must store its successor beforehand
             successor = j->next;
-            persp2 = get_persp_of_VP ((VanishingPoint *) j->data);
+            persp2 = parent->document->get_persp_of_VP ((VanishingPoint *) j->data);
             if (*persp1 == *persp2) {
                 persp1->absorb (persp2); // persp2 is deleted; hopefully this doesn't screw up the list of vanishing points and thus the loops
             }
@@ -576,9 +576,9 @@ VPDragger::reshapeBoxes (NR::Point const &p, Box3D::Axis axes)
         // TODO: We can extract the VP directly from the box's perspective. Is that vanishing point identical to 'vp'?
         //       Or is there duplicated information? If so, remove it and simplify the whole construction!
         vp->set_pos(p);
-        persp = get_persp_of_VP (vp);
+        persp = parent->document->get_persp_of_VP (vp);
         Box3D::Axis axis = persp->get_axis_of_VP (vp);
-        get_persp_of_VP (vp)->reshape_boxes (axis); // FIXME: we should only update the direction of the VP
+        parent->document->get_persp_of_VP (vp)->reshape_boxes (axis); // FIXME: we should only update the direction of the VP
     }
     parent->updateBoxHandles();
 }
@@ -587,7 +587,7 @@ void
 VPDragger::updateBoxReprs ()
 {
     for (GSList *i = this->vps; i != NULL; i = i->next) {
-        Box3D::get_persp_of_VP ((VanishingPoint *) i->data)->update_box_reprs ();
+        parent->document->get_persp_of_VP ((VanishingPoint *) i->data)->update_box_reprs ();
     }
 }
 
@@ -595,14 +595,14 @@ void
 VPDragger::updateZOrders ()
 {
     for (GSList *i = this->vps; i != NULL; i = i->next) {
-        Box3D::get_persp_of_VP ((VanishingPoint *) i->data)->update_z_orders ();
+        parent->document->get_persp_of_VP ((VanishingPoint *) i->data)->update_z_orders ();
     }
 }
 
-VPDrag::VPDrag (SPDesktop *desktop)
+VPDrag::VPDrag (SPDocument *document)
 {
-    this->desktop = desktop;
-    this->selection = sp_desktop_selection(desktop);
+    this->document = document;
+    this->selection = sp_desktop_selection(inkscape_active_desktop());
 
     this->draggers = NULL;
     this->lines = NULL;
@@ -695,13 +695,7 @@ VPDrag::updateDraggers ()
         if (!SP_IS_3DBOX (item)) continue;
         SP3DBox *box = SP_3DBOX (item);
 
-        // FIXME: Get the VPs from the selection!!!!
-        //addDragger (Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::X));
-        //addDragger (Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::Y));
-        //addDragger (Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::Z));
-
-        //Box3D::Perspective3D *persp = box->perspective;
-        Box3D::Perspective3D *persp = Box3D::get_persp_of_box (box);
+        Box3D::Perspective3D *persp = document->get_persp_of_box (box);
         addDragger (persp->get_vanishing_point(Box3D::X));
         addDragger (persp->get_vanishing_point(Box3D::Y));
         addDragger (persp->get_vanishing_point(Box3D::Z));
@@ -777,8 +771,7 @@ VPDrag::drawLinesForFace (const SP3DBox *box, Box3D::Axis axis) //, guint corner
     NR::Point corner1, corner2, corner3, corner4;
     sp_3dbox_corners_for_perspective_lines (box, axis, corner1, corner2, corner3, corner4);
 
-    //VanishingPoint *vp = box->perspective->get_vanishing_point (axis);
-    VanishingPoint *vp = Box3D::get_persp_of_box (box)->get_vanishing_point (axis);
+    VanishingPoint *vp = document->get_persp_of_box (box)->get_vanishing_point (axis);
     if (vp->is_finite()) {
         NR::Point pt = vp->get_pos();
         if (this->front_or_rear_lines & 0x1) {
@@ -805,7 +798,7 @@ bool
 VPDrag::allBoxesAreSelected (VPDragger *dragger) {
     GSList *selected_boxes = (GSList *) dragger->parent->selection->itemList();
     for (GSList *i = dragger->vps; i != NULL; i = i->next) {
-        if (!get_persp_of_VP ((VanishingPoint *) i->data)->all_boxes_occur_in_list (selected_boxes)) {
+        if (!document->get_persp_of_VP ((VanishingPoint *) i->data)->all_boxes_occur_in_list (selected_boxes)) {
             return false;
         }
     }
@@ -860,7 +853,7 @@ Create a line from p1 to p2 and add it to the lines list
 void
 VPDrag::addLine (NR::Point p1, NR::Point p2, guint32 rgba)
 {
-    SPCanvasItem *line = sp_canvas_item_new(sp_desktop_controls(this->desktop), SP_TYPE_CTRLLINE, NULL);
+    SPCanvasItem *line = sp_canvas_item_new(sp_desktop_controls(inkscape_active_desktop()), SP_TYPE_CTRLLINE, NULL);
     sp_ctrlline_set_coords(SP_CTRLLINE(line), p1, p2);
     if (rgba != VP_LINE_COLOR_FILL) // fill is the default, so don't set color for it to speed up redraw
         sp_ctrlline_set_rgba32 (SP_CTRLLINE(line), rgba);
index 70b473024f5b3f5a9cf575044aa0601a64da8ac6..7d53fa89d431a7cb06d581f276531eadd089e72a 100644 (file)
@@ -110,7 +110,7 @@ public:
 
 struct VPDrag {
 public:
-    VPDrag(SPDesktop *desktop);
+    VPDrag(SPDocument *document);
     ~VPDrag();
 
     VPDragger *getDraggerFor (VanishingPoint const &vp);
@@ -119,7 +119,7 @@ public:
 
     bool local_change;
 
-    SPDesktop *desktop;
+    SPDocument *document;
     GList *draggers;
     GSList *lines;
 
index 95decde952efaec05dae4bb1aa5b26a052bd979c..7f4f637b4cae187628fe5eceea810ed912453d75 100644 (file)
@@ -2129,10 +2129,11 @@ static void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
 
 static void sp_3dbox_toggle_vp_changed( GtkToggleAction *act, gpointer data )
 {
+    SPDocument *document = sp_desktop_document (inkscape_active_desktop ());
     Box3D::Axis axis = (Box3D::Axis) GPOINTER_TO_INT(data);
 
-    if (Box3D::Perspective3D::current_perspective) {
-        Box3D::Perspective3D::current_perspective->toggle_boxes (axis);
+    if (document->current_perspective) {
+        document->current_perspective->toggle_boxes (axis);
     }
     
 }
@@ -2193,6 +2194,7 @@ static void sp_3dboxtb_handles_state_changed( EgeSelectOneAction *act, GObject *
 
 static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
 {
+    SPDocument *document = sp_desktop_document (desktop);
     bool toggled = false;
     /* toggle VP in X direction */
     {
@@ -2202,8 +2204,8 @@ 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 ) );
-    if (Box3D::Perspective3D::current_perspective) {
-        toggled = !Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::X)->is_finite();
+    if (document->current_perspective) {
+        toggled = !document->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 */
@@ -2218,8 +2220,8 @@ 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 ) );
-    if (Box3D::Perspective3D::current_perspective) {
-        toggled = !Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::Y)->is_finite();
+    if (document->current_perspective) {
+        toggled = !document->current_perspective->get_vanishing_point(Box3D::Y)->is_finite();
     }
     gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled );
     /* we connect the signal after setting the state to avoid switching the state again */
@@ -2234,8 +2236,8 @@ 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 ) );
-    if (Box3D::Perspective3D::current_perspective) {
-        toggled = !Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::Z)->is_finite();
+    if (document->current_perspective) {
+        toggled = !document->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 );