Code

Store a global list of existing perspectives; for each perspective hold a list of...
authorcilix42 <cilix42@users.sourceforge.net>
Mon, 6 Aug 2007 00:07:25 +0000 (00:07 +0000)
committercilix42 <cilix42@users.sourceforge.net>
Mon, 6 Aug 2007 00:07:25 +0000 (00:07 +0000)
src/box3d-context.cpp
src/box3d-context.h
src/box3d-face.cpp
src/box3d.cpp
src/desktop.cpp
src/desktop.h
src/perspective-line.h
src/perspective3d.cpp
src/perspective3d.h
src/widgets/toolbox.cpp

index d5d367d818b1e75473a8105d49ed182741e938e1..25f6f78f11768e85c5cc20982278452d46bea4f5 100644 (file)
@@ -90,7 +90,7 @@ static void sp_3dbox_context_class_init(SP3DBoxContextClass *klass)
     event_context_class->item_handler  = sp_3dbox_context_item_handler;
 }
 
-Box3D::Perspective3D * SP3DBoxContext::current_perspective = NULL;
+Box3D::Perspective3D * Box3D::Perspective3D::current_perspective = NULL;
 guint SP3DBoxContext::number_of_handles = 3;
 
 static void sp_3dbox_context_init(SP3DBoxContext *box3d_context)
@@ -116,20 +116,6 @@ static void sp_3dbox_context_init(SP3DBoxContext *box3d_context)
 
     box3d_context->ctrl_dragged = false;
     box3d_context->extruded = false;
-
-    /* create an initial perspective */
-    if (!SP3DBoxContext::current_perspective) {
-        SP3DBoxContext::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_INFINITE),
-                                              // 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, 500.0),
-                                                                     NR::Point(sqrt(3.0),1.0), Box3D::VP_INFINITE));
-    }
     
     new (&box3d_context->sel_changed_connection) sigc::connection();
 }
@@ -371,18 +357,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 (!rc->ctrl_dragged) {
-                       rc->drag_ptC = Box3D::perspective_line_snap (rc->drag_ptB, Box3D::Z, motion_dt);
+                       rc->drag_ptC = Box3D::perspective_line_snap (rc->drag_ptB, Box3D::Z, motion_dt, Box3D::Perspective3D::current_perspective);
                 } else {
                     rc->drag_ptC = motion_dt;
                 }
                 rc->drag_ptC = m.freeSnap(Inkscape::Snapper::SNAPPOINT_BBOX | Inkscape::Snapper::SNAPPOINT_NODE, rc->drag_ptC, rc->item).getPoint();
                 if (rc->ctrl_dragged) {
-                       Box3D::PerspectiveLine pl1 (NR::Point (event_context->xp, event_context->yp), Box3D::Y);
-                       Box3D::PerspectiveLine pl2 (rc->drag_ptB, Box3D::X);
+                       Box3D::PerspectiveLine pl1 (NR::Point (event_context->xp, event_context->yp), Box3D::Y, Box3D::Perspective3D::current_perspective);
+                       Box3D::PerspectiveLine pl2 (rc->drag_ptB, Box3D::X, Box3D::Perspective3D::current_perspective);
                        NR::Point corner1 = pl1.meet(pl2);
                        
-                       Box3D::PerspectiveLine pl3 (corner1, Box3D::X);
-                       Box3D::PerspectiveLine pl4 (rc->drag_ptC, Box3D::Z);
+                       Box3D::PerspectiveLine pl3 (corner1, Box3D::X, Box3D::Perspective3D::current_perspective);
+                       Box3D::PerspectiveLine pl4 (rc->drag_ptC, Box3D::Z, Box3D::Perspective3D::current_perspective);
                        rc->drag_ptB = pl3.meet(pl4);
                 }
             }
index c244699b440ce283a214b4cc1b955c3274767927..763c152ae0aab3041cc1dffcd1ee27f69578a6b7 100644 (file)
@@ -54,8 +54,6 @@ struct SP3DBoxContext : public SPEventContext {
     /* temporary member until the precise behaviour is sorted out */
     static guint number_of_handles;
 
-    static Box3D::Perspective3D *current_perspective;
-
        sigc::connection sel_changed_connection;
 
        Inkscape::MessageContext *_message_context;
index 287e5e2053e6182ad9117bd38157382d9553c267..55dc9b60aed28345ec127f919863f2069ade39f4 100644 (file)
@@ -64,11 +64,11 @@ void Box3DFace::set_shape(NR::Point const ul, NR::Point const lr,
     } else {
         if (align_along_PL) {
             Box3D::Axis dir3 = Box3D::third_axis_direction (dir1, dir2);
-            Box3D::Line line1(*SP3DBoxContext::current_perspective->get_vanishing_point(dir1), lr);
-            Box3D::Line line2(*pt_align, *SP3DBoxContext::current_perspective->get_vanishing_point(dir3));
+            Box3D::Line line1(*Box3D::Perspective3D::current_perspective->get_vanishing_point(dir1), lr);
+            Box3D::Line line2(*pt_align, *Box3D::Perspective3D::current_perspective->get_vanishing_point(dir3));
             corners[2] = *line1.intersect(line2);
         } else {
-            corners[2] = Box3D::Line(*pt_align, *SP3DBoxContext::current_perspective->get_vanishing_point(dir1)).closest_to(lr);
+            corners[2] = Box3D::Line(*pt_align, *Box3D::Perspective3D::current_perspective->get_vanishing_point(dir1)).closest_to(lr);
         }
     }
 
@@ -130,12 +130,12 @@ Box3DFace::set_face (NR::Point const A, NR::Point const C, Box3D::Axis const axi
         return;
     SP3DBoxContext *bc = SP_3DBOX_CONTEXT(inkscape_active_event_context());
     
-    Box3D::PerspectiveLine line1 (A, axis1);
-    Box3D::PerspectiveLine line2 (C, axis2);
+    Box3D::PerspectiveLine line1 (A, axis1, Box3D::Perspective3D::current_perspective);
+    Box3D::PerspectiveLine line2 (C, axis2, Box3D::Perspective3D::current_perspective);
     NR::Maybe<NR::Point> B = line1.intersect(line2);
 
-    Box3D::PerspectiveLine line3 (*corners[0], axis2);
-    Box3D::PerspectiveLine line4 (*corners[2], axis1);
+    Box3D::PerspectiveLine line3 (*corners[0], axis2, Box3D::Perspective3D::current_perspective);
+    Box3D::PerspectiveLine line4 (*corners[2], axis1, Box3D::Perspective3D::current_perspective);
     NR::Maybe<NR::Point> D = line3.intersect(line4);
 
     // FIXME: How to handle the case if one of the intersections doesn't exist?
index dec5e9d17ef823cfd69798340a1aa4ef34087069..76dad605b9f5fa60f5284d45493cec954aa92305 100644 (file)
@@ -24,7 +24,7 @@ static void sp_3dbox_class_init(SP3DBoxClass *klass);
 static void sp_3dbox_init(SP3DBox *box3d);
 
 static void sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
-//static void sp_3dbox_release (SPObject *object);
+static void sp_3dbox_release (SPObject *object);
 static void sp_3dbox_set(SPObject *object, unsigned int key, const gchar *value);
 static void sp_3dbox_update(SPObject *object, SPCtx *ctx, guint flags);
 static Inkscape::XML::Node *sp_3dbox_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
@@ -76,7 +76,7 @@ sp_3dbox_class_init(SP3DBoxClass *klass)
     sp_object_class->set = sp_3dbox_set;
     sp_object_class->write = sp_3dbox_write;
     sp_object_class->update = sp_3dbox_update;
-    //sp_object_class->release = sp_3dbox_release;
+    sp_object_class->release = sp_3dbox_release;
 
     item_class->description = sp_3dbox_description;
 }
@@ -97,6 +97,8 @@ sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr
 
     SP3DBox *box = SP_3DBOX (object);
 
+    Box3D::Perspective3D::current_perspective->add_box (box);
+
     sp_object_read_attr(object, "inkscape:box3dcornerA");
     sp_object_read_attr(object, "inkscape:box3dcornerB");
     sp_object_read_attr(object, "inkscape:box3dcornerC");
@@ -127,22 +129,24 @@ sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr
     sp_3dbox_link_to_existing_paths (box, repr);
 }
 
-/*
 static void
 sp_3dbox_release (SPObject *object)
 {
-       SP3DBox *box3d = SP_3DBOX(object);
+       SP3DBox *box = SP_3DBOX(object);
         for (int i = 0; i < 6; ++i) {
-            if (box3d->faces[i]) {
-                delete box3d->faces[i]; // FIXME: Anything else to do? Do we need to clean up the face first?
+            if (box->faces[i]) {
+                delete box->faces[i]; // FIXME: Anything else to do? Do we need to clean up the face first?
             }
         }
 
+        // 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);
+
        if (((SPObjectClass *) parent_class)->release) {
          ((SPObjectClass *) parent_class)->release (object);
        }
 }
-*/
 
 static void sp_3dbox_set(SPObject *object, unsigned int key, const gchar *value)
 {
@@ -334,35 +338,37 @@ 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);
+
     NR::Point A (box->corners[id ^ Box3D::XY]);
     if (Box3D::is_single_axis_direction (axes)) {
-        pt = Box3D::PerspectiveLine (box->corners[id], axes).closest_to(pt);
+        pt = Box3D::PerspectiveLine (box->corners[id], axes, persp).closest_to(pt);
     }
 
     /* set the 'front' corners */
     box->corners[id] = pt;
 
-    Box3D::PerspectiveLine pl_one (A, Box3D::Y);
-    Box3D::PerspectiveLine pl_two (pt, Box3D::X);
+    Box3D::PerspectiveLine pl_one (A, Box3D::Y, persp);
+    Box3D::PerspectiveLine pl_two (pt, Box3D::X, persp);
     box->corners[id ^ Box3D::X] = pl_one.meet(pl_two);
 
-    pl_one = Box3D::PerspectiveLine (A, Box3D::X);
-    pl_two = Box3D::PerspectiveLine (pt, Box3D::Y);
+    pl_one = Box3D::PerspectiveLine (A, Box3D::X, persp);
+    pl_two = Box3D::PerspectiveLine (pt, Box3D::Y, persp);
     box->corners[id ^ Box3D::Y] = pl_one.meet(pl_two);
 
     /* set the 'rear' corners */
     NR::Point B (box->corners[id ^ Box3D::XYZ]);
 
-    pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::X], Box3D::Z);
-    pl_two = Box3D::PerspectiveLine (B, Box3D::Y);
+    pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::X], Box3D::Z, persp);
+    pl_two = Box3D::PerspectiveLine (B, Box3D::Y, persp);
     box->corners[id ^ Box3D::XZ] = pl_one.meet(pl_two);
 
-    pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::XZ], Box3D::X);
-    pl_two = Box3D::PerspectiveLine (pt, Box3D::Z);
+    pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::XZ], Box3D::X, persp);
+    pl_two = Box3D::PerspectiveLine (pt, Box3D::Z, persp);
     box->corners[id ^ Box3D::Z] = pl_one.meet(pl_two);
 
-    pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::Z], Box3D::Y);
-    pl_two = Box3D::PerspectiveLine (B, Box3D::X);
+    pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::Z], Box3D::Y, persp);
+    pl_two = Box3D::PerspectiveLine (B, Box3D::X, persp);
     box->corners[id ^ Box3D::YZ] = pl_one.meet(pl_two);
     
 }
@@ -372,19 +378,21 @@ 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);
+
     /* set the four corners of the face containing corners[id] */
-    box->corners[id] = Box3D::PerspectiveLine (box->corners[id], Box3D::Z).closest_to(pt);
+    box->corners[id] = Box3D::PerspectiveLine (box->corners[id], Box3D::Z, persp).closest_to(pt);
 
-    Box3D::PerspectiveLine pl_one (box->corners[id], Box3D::X);
-    Box3D::PerspectiveLine pl_two (box->corners[id ^ Box3D::XZ], Box3D::Z);
+    Box3D::PerspectiveLine pl_one (box->corners[id], Box3D::X, persp);
+    Box3D::PerspectiveLine pl_two (box->corners[id ^ Box3D::XZ], Box3D::Z, persp);
     box->corners[id ^ Box3D::X] = pl_one.meet(pl_two);
 
-    pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::X], Box3D::Y);
-    pl_two = Box3D::PerspectiveLine (box->corners[id ^ Box3D::XYZ], Box3D::Z);
+    pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::X], Box3D::Y, persp);
+    pl_two = Box3D::PerspectiveLine (box->corners[id ^ Box3D::XYZ], Box3D::Z, persp);
     box->corners[id ^ Box3D::XY] = pl_one.meet(pl_two);
 
-    pl_one = Box3D::PerspectiveLine (box->corners[id], Box3D::Y);
-    pl_two = Box3D::PerspectiveLine (box->corners[id ^ Box3D::YZ], Box3D::Z);
+    pl_one = Box3D::PerspectiveLine (box->corners[id], Box3D::Y, persp);
+    pl_two = Box3D::PerspectiveLine (box->corners[id ^ Box3D::YZ], Box3D::Z, persp);
     box->corners[id ^ Box3D::Y] = pl_one.meet(pl_two);
 }
 
@@ -409,8 +417,10 @@ sp_3dbox_get_midpoint_between_corners (SP3DBox *box, guint id_corner1, guint id_
 
         if (!adjacent_face_center) return NR::Nothing();
 
-        Box3D::PerspectiveLine pl (*adjacent_face_center, orth_dir);
-        return pl.intersect(Box3D::PerspectiveLine(box->corners[id_corner1], corner_axes));
+        Box3D::Perspective3D * persp = Box3D::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));
     } else {
         Box3D::Axis dir = Box3D::extract_first_axis_direction (corner_axes);
         Box3D::Line diag1 (box->corners[id_corner1], box->corners[id_corner2]);
index e785aab6dcd7a4b0e48cf1bfbc3e6f03cf5961fa..6314621c14e146805075c28fae13c2d916a893df 100644 (file)
@@ -132,6 +132,7 @@ SPDesktop::SPDesktop() :
     window_state(0),
     interaction_disabled_counter( 0 ),
     waiting_cursor( false ),
+    perspectives (NULL),
     guides_active( false ),
     gr_item( 0 ),
     gr_point_type( 0 ),
@@ -309,6 +310,21 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas)
     layer_manager = new Inkscape::LayerManager( this );
 
     grids_visible = true;
+
+    /* Create initial perspective, append it to the list of existing perspectives
+       and make it the current perspective */
+    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));
+    this->add_perspective (initial_persp);
+    Box3D::Perspective3D::current_perspective = (Box3D::Perspective3D *) perspectives->data;
 }
 
 
@@ -352,6 +368,11 @@ void SPDesktop::destroy()
 
     g_list_free (zooms_past);
     g_list_free (zooms_future);
+
+    for (GSList *p = this->perspectives; p != NULL; p = p->next) {
+        delete ((Box3D::Perspective3D *) p->data);
+    }
+    g_slist_free (perspectives);
 }
 
 SPDesktop::~SPDesktop() {}
@@ -693,6 +714,30 @@ void SPDesktop::set_display_area(NR::Rect const &a, NR::Coord b, bool log)
     set_display_area(a.min()[NR::X], a.min()[NR::Y], a.max()[NR::X], a.max()[NR::Y], b, log);
 }
 
+/**
+ * Add a perspective to the desktop if it doesn't exist yet
+ */
+void
+SPDesktop::add_perspective (Box3D::Perspective3D * const persp)
+{
+    // FIXME: Should we handle the case that the perspectives have equal VPs but are not identical?
+    if (persp == NULL || g_slist_find (this->perspectives, persp)) return;
+    this->perspectives = g_slist_prepend (this->perspectives, persp);
+    persp->desktop = this;
+}
+
+void SPDesktop::remove_perspective (Box3D::Perspective3D * const persp)
+{
+    if (persp == NULL) return;
+
+    if (!g_slist_find (this->perspectives, persp)) {
+        g_warning ("Could not find perspective in current desktop. Not removed.\n");
+        return;
+    }
+
+    this->perspectives = g_slist_remove (this->perspectives, persp);
+}
+
 /**
  * Return viewbox dimensions.
  */
index ca2d2420465f919ac7ab474cc5c637b96eb76adc..fa6602651bc1b8c8dd2b8fc4ade2a99146e7fe22 100644 (file)
@@ -34,6 +34,7 @@
 #include "libnr/nr-rect.h"
 #include "ui/view/view.h"
 #include "ui/view/edit-widget-interface.h"
+#include "perspective3d.h"
 
 class NRRect;
 class SPCSSAttr;
@@ -112,6 +113,9 @@ struct SPDesktop : public Inkscape::UI::View::View
     unsigned int interaction_disabled_counter;
     bool waiting_cursor;
 
+    // All 3D perspectives that are present in the current desktop
+    GSList *perspectives;
+
     /// \todo fixme: This has to be implemented in different way */
     guint guides_active : 1;
 
@@ -202,6 +206,10 @@ struct SPDesktop : public Inkscape::UI::View::View
     SPItem *group_at_point (NR::Point const p) const;
     NR::Point point() const;
 
+    // Methods to handle 3D perspective
+    void add_perspective (Box3D::Perspective3D * const persp);
+    void remove_perspective (Box3D::Perspective3D * const persp);
+
     NR::Rect get_display_area() const;
     void set_display_area (double x0, double y0, double x1, double y1, double border, bool log = true);
     void set_display_area(NR::Rect const &a, NR::Coord border, bool log = true);
index a02737692d07cc63bfbce6da024f2288af55e436..8f218803b56f09c8377fca9e9b7ea77434d341eb 100644 (file)
@@ -27,8 +27,7 @@ public:
      * PL runs through it; otherwise it has the direction specified by the v_dir vector
      * of the VP.
      */
-    PerspectiveLine (NR::Point const &pt, Box3D::Axis const axis,
-                     Perspective3D *perspective = SP3DBoxContext::current_perspective);
+    PerspectiveLine (NR::Point const &pt, Box3D::Axis const axis, Perspective3D *perspective);
     NR::Maybe<NR::Point> intersect (Line const &line); // FIXME: Can we make this return only a NR::Point to remove the extra method meet()?
     NR::Point meet (Line const &line);
        
index 35558e832280a378ca809f55436f2a7636bcccb5..2c9a5e61e476f07f4d4350d784aaabd9e516cfee 100644 (file)
 #include "box3d-context.h"
 #include "perspective-line.h"
 #include <iostream>
+#include "desktop.h"
+
+// can probably be removed later
+#include "inkscape.h"
 
 namespace Box3D {
 
+Perspective3D *
+get_persp_of_box (const SP3DBox *box)
+{
+    SPDesktop *desktop = inkscape_active_desktop(); // Should we pass the desktop as an argument?
+    for (GSList *p = desktop->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();
+}
+
 /**
  * Computes the intersection of the two perspective lines from pt1 and pt2 to the respective
  * vanishing points in the given directions.
  */
 // FIXME: This has been moved to a virtual method inside PerspectiveLine; can probably be purged
-NR::Point perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point pt2, Box3D::Axis dir2)
+NR::Point
+perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point pt2, Box3D::Axis dir2, Perspective3D *persp)
 {
-    VanishingPoint const *vp1 = SP3DBoxContext::current_perspective->get_vanishing_point(dir1);
-    VanishingPoint const *vp2 = SP3DBoxContext::current_perspective->get_vanishing_point(dir2);
+    VanishingPoint const *vp1 = persp->get_vanishing_point(dir1);
+    VanishingPoint const *vp2 = persp->get_vanishing_point(dir2);
     NR::Maybe<NR::Point> meet = Line(pt1, *vp1).intersect(Line(pt2, *vp2));
     // FIXME: How to handle parallel lines (also depends on the type of the VPs)?
     if (!meet) { meet = NR::Point (0.0, 0.0); }
@@ -36,22 +53,30 @@ NR::Point perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point p
  * Find the point on the perspective line from line_pt to the
  * vanishing point in direction dir that is closest to ext_pt.
  */
-NR::Point perspective_line_snap (NR::Point line_pt, Box3D::Axis dir, NR::Point ext_pt)
+NR::Point
+perspective_line_snap (NR::Point line_pt, Box3D::Axis dir, NR::Point ext_pt, Perspective3D *persp)
 {
-    return PerspectiveLine(line_pt, dir).closest_to(ext_pt);
+    return PerspectiveLine(line_pt, dir, persp).closest_to(ext_pt);
 }  
 
 Perspective3D::Perspective3D (VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z)
-        : vp_x (pt_x),
-          vp_y (pt_y),
-          vp_z (pt_z)
+    : desktop (NULL),
+      vp_x (pt_x),
+      vp_y (pt_y),
+      vp_z (pt_z),
+      boxes (NULL)
 {
-       // Draw the three vanishing points
-    vp_x.draw(X);
-    vp_y.draw(Y);
-    vp_z.draw(Z);
 }
 
+Perspective3D::~Perspective3D ()
+{
+    g_assert (desktop != NULL);
+    desktop->remove_perspective (this);
+
+    g_slist_free (boxes);
+}
+
+
 VanishingPoint *Perspective3D::get_vanishing_point (Box3D::Axis const dir)
 {
     // FIXME: Also handle value 'NONE' in switch
@@ -86,6 +111,32 @@ void Perspective3D::set_vanishing_point (Box3D::Axis const dir, VanishingPoint c
     }
 }
 
+void
+Perspective3D::add_box (SP3DBox *box)
+{
+    if (g_slist_find (this->boxes, box) != NULL) {
+        // Don't add the same box twice
+        g_warning ("Box already uses the current perspective. We don't add it again.\n");
+        return;
+    }
+    this->boxes = g_slist_append (this->boxes, box);
+}
+
+void
+Perspective3D::remove_box (const SP3DBox *box)
+{
+    if (!g_slist_find (this->boxes, box)) {
+        g_warning ("Could not find box that is to be removed in the current perspective.\n");
+    }
+    this->boxes = g_slist_remove (this->boxes, box);
+}
+
+bool
+Perspective3D::has_box (const SP3DBox *box)
+{
+    return (g_slist_find (this->boxes, box) != NULL);
+}
+
 } // namespace Box3D 
  
 /*
index 007b02df19c4af82663b1d3a5c0eebc791d10448..fa9eda65f1974a3da54f22219b799311a103569a 100644 (file)
 
 #include "vanishing-point.h"
 
-namespace Box3D {
+class SP3DBox;
 
-NR::Point perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point pt2, Box3D::Axis dir2);
-NR::Point perspective_line_snap (NR::Point pt, Box3D::Axis dir, NR::Point ext_pt);
+namespace Box3D {
 
 class PerspectiveLine;
 
 class Perspective3D {
 public:
     Perspective3D(VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z);
+    ~Perspective3D();
 
     VanishingPoint *get_vanishing_point (Box3D::Axis const dir);
     void set_vanishing_point (Box3D::Axis const dir, VanishingPoint const &pt);
+    void add_box (SP3DBox *box);
+    void remove_box (const SP3DBox *box);
+    bool has_box (const SP3DBox *box);
+
+    static Perspective3D * current_perspective; // should current_perspective be moved to desktop.h?
+
+    SPDesktop * desktop; // we need to store the perspective's desktop to be able to access it in the destructor
 
 private:
     VanishingPoint vp_x;
     VanishingPoint vp_y;
     VanishingPoint vp_z;
+    GSList * boxes; // holds a list of boxes sharing this specific perspective
 };
 
+Perspective3D * get_persp_of_box (const SP3DBox *box);
+
+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);
 
 } // namespace Box3D
 
index aeab3b45bea54c78621a2c751ab7519f3b90123a..8acb08a12f6e8e34199d338869a3e26d1cdce6e3 100644 (file)
@@ -2133,8 +2133,8 @@ static void sp_3dbox_toggle_vp_changed( GtkToggleAction *act, gpointer data )
             break;
     }
     
-    if (SP3DBoxContext::current_perspective) {
-        Box3D::VanishingPoint *vp = SP3DBoxContext::current_perspective->get_vanishing_point(axis);
+    if (Box3D::Perspective3D::current_perspective) {
+        Box3D::VanishingPoint *vp = Box3D::Perspective3D::current_perspective->get_vanishing_point(axis);
         vp->toggle_parallel();
         vp->draw(axis);
         prefs_set_int_attribute( "tools.shapes.3dbox", pstring->str, vp->is_finite() ? 0 : 1);
@@ -2208,8 +2208,8 @@ static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
                                                   Inkscape::ICON_SIZE_DECORATION );
     gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
     g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::X));
-    if (SP3DBoxContext::current_perspective) {
-        toggled = SP3DBoxContext::current_perspective->get_vanishing_point(Box3D::X)->is_finite();
+    if (Box3D::Perspective3D::current_perspective) {
+        toggled = !Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::X)->is_finite();
     }
     gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled );
     }
@@ -2223,8 +2223,8 @@ static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
                                                   Inkscape::ICON_SIZE_DECORATION );
     gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
     g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::Y));
-    if (SP3DBoxContext::current_perspective) {
-        toggled = SP3DBoxContext::current_perspective->get_vanishing_point(Box3D::Y)->is_finite();
+    if (Box3D::Perspective3D::current_perspective) {
+        toggled = !Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::Y)->is_finite();
     }
     gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled );
     }
@@ -2238,8 +2238,8 @@ static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
                                                   Inkscape::ICON_SIZE_DECORATION );
     gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
     g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::Z));
-    if (SP3DBoxContext::current_perspective) {
-        toggled = SP3DBoxContext::current_perspective->get_vanishing_point(Box3D::Z)->is_finite();
+    if (Box3D::Perspective3D::current_perspective) {
+        toggled = !Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::Z)->is_finite();
     }
     gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled );
     }