Code

* INTL - fixed: "Crop to" dropdown strings not translated for PDF Import
[inkscape.git] / src / box3d.cpp
index 0add188e7cbd1a163b640a5d39f6c146072f798d..72aff25985fcb49d54a502074f6fa6b0225137d1 100644 (file)
@@ -32,6 +32,9 @@
 #include "persp3d-reference.h"
 #include "uri.h"
 #include "2geom/geom.h"
+#include "sp-guide.h"
+#include "sp-namedview.h"
+#include "prefs-utils.h"
 
 #include "desktop.h"
 #include "macros.h"
@@ -47,11 +50,10 @@ static Inkscape::XML::Node *box3d_write(SPObject *object, Inkscape::XML::Node *r
 
 static gchar *box3d_description(SPItem *item);
 static NR::Matrix box3d_set_transform(SPItem *item, NR::Matrix const &xform);
+static void box3d_convert_to_guides(SPItem *item);
 
 static void box3d_ref_changed(SPObject *old_ref, SPObject *ref, SPBox3D *box);
 static void box3d_ref_modified(SPObject *href, guint flags, SPBox3D *box);
-//static void box3d_ref_changed(SPObject *old_ref, SPObject *ref, Persp3D *persp);
-//static void box3d_ref_modified(SPObject *href, guint flags, Persp3D *persp);
 
 static SPGroupClass *parent_class;
 
@@ -97,6 +99,7 @@ box3d_class_init(SPBox3DClass *klass)
 
     item_class->description = box3d_description;
     item_class->set_transform = box3d_set_transform;
+    item_class->convert_to_guides = box3d_convert_to_guides;
 }
 
 static void
@@ -370,7 +373,7 @@ box3d_set_transform(SPItem *item, NR::Matrix const &xform)
         transf_persp = persp;
     }
 
-    /* only transform the perspective once, even it it has several selected boxes */
+    /* only transform the perspective once, even if it has several selected boxes */
     if(!persp3d_was_transformed (transf_persp)) {
         /* concatenate the affine transformation with the perspective mapping; this
            function also triggers repr updates of boxes and the perspective itself */
@@ -384,8 +387,6 @@ box3d_set_transform(SPItem *item, NR::Matrix const &xform)
         persp3d_unset_transforms(transf_persp);
     }
 
-    /***
-    // FIXME: We somehow have to apply the transformation to strokes, patterns, and gradients. How?
     NR::Matrix ret(NR::transform(xform));
     gdouble const sw = hypot(ret[0], ret[1]);
     gdouble const sh = hypot(ret[2], ret[3]);
@@ -406,7 +407,6 @@ box3d_set_transform(SPItem *item, NR::Matrix const &xform)
         // Adjust LPE
         sp_item_adjust_livepatheffect(item, xform);
     }
-    ***/
 
     return NR::identity();
 }
@@ -616,6 +616,9 @@ box3d_set_corner (SPBox3D *box, const guint id, NR::Point const &new_pos, const
 void box3d_set_center (SPBox3D *box, NR::Point const &new_pos, NR::Point const &old_pos, const Box3D::Axis movement, bool constrained) {
     g_return_if_fail ((movement != Box3D::NONE) && (movement != Box3D::XYZ));
 
+    box->orig_corner0.normalize();
+    box->orig_corner7.normalize();
+
     Persp3D *persp = box3d_get_perspective(box);
     if (!(movement & Box3D::Z)) {
         double coord = (box->orig_corner0[Proj::Z] + box->orig_corner7[Proj::Z]) / 2;
@@ -625,6 +628,7 @@ void box3d_set_center (SPBox3D *box, NR::Point const &new_pos, NR::Point const &
         Proj::Pt3 pt_proj (persp->tmat.preimage (new_pos, coord, Proj::Z));
         if (constrained) {
             Proj::Pt3 old_pos_proj (persp->tmat.preimage (old_pos, coord, Proj::Z));
+            old_pos_proj.normalize();
             pt_proj = box3d_snap (box, -1, pt_proj, old_pos_proj);
         }
         // normalizing pt_proj is essential because we want to mingle affine coordinates
@@ -769,13 +773,13 @@ box3d_swap_z_orders (int z_orders[6]) {
 }
 
 /*
- * In der Standard-Perspektive:
- * 2 = vorne
- * 1 = oben
- * 0 = links
- * 3 = rechts
- * 4 = unten
- * 5 = hinten
+ * In standard perspective we have:
+ * 2 = front face
+ * 1 = top face
+ * 0 = left face
+ * 3 = right face
+ * 4 = bottom face
+ * 5 = rear face
  */
 
 /* All VPs infinite */
@@ -992,7 +996,11 @@ box3d_set_new_z_orders_case2 (SPBox3D *box, int z_orders[6], Box3D::Axis central
                         box3d_aux_set_z_orders (z_orders, 3, 1, 5, 2, 4, 0);
                     } else {
                         //g_print ("central axis X (case b3)");
-                        box3d_aux_set_z_orders (z_orders, 1, 3, 5, 0, 2, 4);
+                        if (insidexy == 0) {
+                            box3d_aux_set_z_orders (z_orders, 3, 5, 1, 0, 2, 4);
+                        } else {
+                            box3d_aux_set_z_orders (z_orders, 3, 1, 5, 0, 2, 4);
+                        }
                     }
                 }
             }
@@ -1008,7 +1016,11 @@ box3d_set_new_z_orders_case2 (SPBox3D *box, int z_orders[6], Box3D::Axis central
                 }
             } else {
                 //g_print ("central axis Y (case b)");
-                box3d_aux_set_z_orders (z_orders, 5, 0, 4, 1, 3, 2);
+                if (insideyx == 1) {
+                    box3d_aux_set_z_orders (z_orders, 4, 0, 5, 1, 3, 2);
+                } else {
+                    box3d_aux_set_z_orders (z_orders, 5, 0, 4, 1, 3, 2);
+                }
             }
             break;
         case Box3D::Z:
@@ -1025,7 +1037,7 @@ box3d_set_new_z_orders_case2 (SPBox3D *box, int z_orders[6], Box3D::Axis central
                 }
             } else {
                 //g_print ("central axis Z (case b)");
-                box3d_aux_set_z_orders (z_orders, 5, 3, 4, 1, 0, 2);
+                box3d_aux_set_z_orders (z_orders, 3, 4, 5, 1, 0, 2);
             }
             break;
         case Box3D::NONE:
@@ -1455,6 +1467,79 @@ box3d_switch_perspectives(SPBox3D *box, Persp3D *old_persp, Persp3D *new_persp,
     g_free(href);
 }
 
+/* Converts the 3D box to an ordinary SPGroup, adds it to the XML tree at the same position as
+   the original box and deletes the latter */
+// TODO: Copy over all important attributes (see sp_selected_item_to_curved_repr() for an example)
+SPGroup *
+box3d_convert_to_group(SPBox3D *box) {
+    SPDocument *doc = SP_OBJECT_DOCUMENT(box);
+    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
+
+    // remember position of the box
+    int pos = SP_OBJECT_REPR(box)->position();
+
+    // create a new group and add the sides (converted to ordinary paths) as its children
+    Inkscape::XML::Node *grepr = xml_doc->createElement("svg:g");
+
+    Inkscape::XML::Node *repr;
+    for (SPObject *child = sp_object_first_child(SP_OBJECT(box)); child != NULL; child = SP_OBJECT_NEXT(child) ) {
+        if (SP_IS_BOX3D_SIDE(child)) {
+            repr = box3d_side_convert_to_path(SP_BOX3D_SIDE(child));
+            grepr->appendChild(repr);
+        } else {
+            g_warning("Non-side object encountered as child of a 3D box.\n");
+        }
+    }
+
+    // add the new group to the box's parent and set remembered position
+    SPObject *parent = SP_OBJECT_PARENT(box);
+    SP_OBJECT_REPR(parent)->appendChild(grepr);
+    grepr->setPosition(pos);
+
+    SP_OBJECT(box)->deleteObject(true);
+
+    return SP_GROUP(doc->getObjectByRepr(grepr));
+}
+
+static inline void
+box3d_push_back_corner_pair(SPBox3D *box, std::list<std::pair<Geom::Point, Geom::Point> > &pts, int c1, int c2) {
+    pts.push_back(std::make_pair(box3d_get_corner_screen(box, c1).to_2geom(),
+                                 box3d_get_corner_screen(box, c2).to_2geom()));
+}
+
+void
+box3d_convert_to_guides(SPItem *item) {
+    SPBox3D *box = SP_BOX3D(item);
+
+    if (prefs_get_int_attribute("tools.shapes.3dbox", "convertguides", 1) == 0) {
+        sp_item_convert_to_guides(SP_ITEM(box));
+        return;
+    }
+
+    SPDocument *doc = SP_OBJECT_DOCUMENT(box);
+
+    std::list<std::pair<Geom::Point, Geom::Point> > pts;
+
+    /* perspective lines in X direction */
+    box3d_push_back_corner_pair(box, pts, 0, 1);
+    box3d_push_back_corner_pair(box, pts, 2, 3);
+    box3d_push_back_corner_pair(box, pts, 4, 5);
+    box3d_push_back_corner_pair(box, pts, 6, 7);
+
+    /* perspective lines in Y direction */
+    box3d_push_back_corner_pair(box, pts, 0, 2);
+    box3d_push_back_corner_pair(box, pts, 1, 3);
+    box3d_push_back_corner_pair(box, pts, 4, 6);
+    box3d_push_back_corner_pair(box, pts, 5, 7);
+
+    /* perspective lines in Z direction */
+    box3d_push_back_corner_pair(box, pts, 0, 4);
+    box3d_push_back_corner_pair(box, pts, 1, 5);
+    box3d_push_back_corner_pair(box, pts, 2, 6);
+    box3d_push_back_corner_pair(box, pts, 3, 7);
+
+    sp_guide_pt_pairs_to_guides(doc, pts);
+}
 
 /*
   Local Variables: