Code

Display CMS adjustment per-desktop view
[inkscape.git] / src / perspective3d.cpp
index c7592a06f0702e4749cdcbe981473bf6414cafcb..489e88dfc859d46786ec28cb4872b229b2f90fca 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
@@ -78,16 +49,21 @@ NR::Point
 perspective_line_snap (NR::Point line_pt, Box3D::Axis dir, NR::Point ext_pt, Perspective3D *persp)
 {
     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();
@@ -192,12 +174,48 @@ Perspective3D::set_vanishing_point (Box3D::Axis const dir, VanishingPoint const
         case Z:
             (*vp_z) = pt;
             break;
-        case NONE:
+        default:
             // no vanishing point to set
             break;
     }
 }
 
+void
+Perspective3D::set_infinite_direction (Box3D::Axis axis, NR::Point const dir)
+{
+    Box3D::Axis axis1 = Box3D::get_remaining_axes (axis).first;
+    Box3D::Axis axis2 = Box3D::get_remaining_axes (axis).second;
+    Box3D::VanishingPoint *vp1 = get_vanishing_point (axis1);
+    Box3D::VanishingPoint *vp2 = get_vanishing_point (axis2);
+    if (fabs (Box3D::determinant (vp1->v_dir, dir)) < Box3D::epsilon ||
+        fabs (Box3D::determinant (vp2->v_dir, dir)) < Box3D::epsilon) {
+        // This is an ad-hoc correction; we should fix this more thoroughly
+        double a = NR::atan2 (dir) + 0.01;
+        this->set_infinite_direction (axis, NR::Point (cos (a), sin (a))); // we call this function again in case there is another conflict (which is unlikely, but possible)
+        return;
+    }
+
+    get_vanishing_point (axis)->set_infinite_direction (dir);
+    for (GSList *i = this->boxes; i != NULL; i = i->next) {
+        sp_3dbox_reshape_after_VP_rotation (SP_3DBOX (i->data), axis);
+        sp_3dbox_set_z_orders_later_on (SP_3DBOX (i->data));
+    }
+    update_box_reprs();
+}
+
+void
+Perspective3D::rotate (Box3D::Axis const axis, double const angle, bool const alt_pressed)
+{
+    Box3D::VanishingPoint *vp = get_vanishing_point (axis);
+    if (!vp->is_finite()) {
+        //double add_value = angle;
+        double a = NR::atan2 (vp->v_dir) * 180/M_PI;
+        a += alt_pressed ? 0.5 * ((angle > 0 ) - (angle < 0)) : angle; // the r.h.s. yields +/-0.5 or angle
+        a *= M_PI/180;
+        this->set_infinite_direction (axis, NR::Point (cos (a), sin (a)));
+    }
+}
+
 Axis
 Perspective3D::get_axis_of_VP (VanishingPoint *vp)
 {
@@ -223,7 +241,7 @@ Perspective3D::set_vanishing_point (Box3D::Axis const dir, gdouble pt_x, gdouble
         case Z:
             vp = vp_z;
             break;
-        case NONE:
+        default:
             // no vanishing point to set
             return;
     }
@@ -314,7 +332,7 @@ Perspective3D::reshape_boxes (Box3D::Axis axes)
                 new_pt = vp->get_pos() + box->ratio_z * (box->corners[0] - vp->get_pos());
                 sp_3dbox_move_corner_in_Z_direction (box, 4, new_pt);
             }
-        }                
+        }
 
         sp_3dbox_set_shape (box, true);
     }
@@ -328,6 +346,9 @@ Perspective3D::toggle_boxes (Box3D::Axis axis)
         sp_3dbox_reshape_after_VP_toggling (SP_3DBOX (i->data), axis);
     }
     update_box_reprs();
+
+    SP3DBoxContext *bc = SP_3DBOX_CONTEXT (inkscape_active_event_context());
+    bc->_vpdrag->updateDraggers ();
 }
 
 void
@@ -342,10 +363,21 @@ void
 Perspective3D::update_z_orders ()
 {
     for (GSList *i = this->boxes; i != NULL; i = i->next) {
-        sp_3dbox_set_z_orders (SP_3DBOX (i->data));
+        sp_3dbox_set_z_orders_later_on (SP_3DBOX (i->data));
     }
 }
 
+/* the direction from a point pt towards the specified vanishing point of the perspective */
+NR::Point
+Perspective3D::direction (NR::Point pt, Box3D::Axis axis)
+{
+    Box3D::VanishingPoint *vp = this->get_vanishing_point (axis);
+    if (!vp->is_finite()) {
+        return vp->v_dir;
+    }
+    return (vp->get_pos() - pt);
+}
+
 // swallow the list of boxes from the other perspective and delete it
 void
 Perspective3D::absorb (Perspective3D *other)
@@ -368,39 +400,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);
 
@@ -428,13 +432,15 @@ Perspective3D::print_debugging_info ()
             if (j != NULL) {
                 g_print ("%d", SP_3DBOX (j->data)->my_counter);
             }
+            g_print ("\n");
         }
+        g_print ("\n");
     }
-    g_print ("\n====================================================\n");
+    g_print ("====================================================\n");
 }
 
-} // namespace Box3D 
+} // namespace Box3D
+
 /*
   Local Variables:
   mode:c++