Code

If necessary, split up perspectives when applying transformations to boxes; moreover...
authorcilix42 <cilix42@users.sourceforge.net>
Thu, 13 Dec 2007 20:08:06 +0000 (20:08 +0000)
committercilix42 <cilix42@users.sourceforge.net>
Thu, 13 Dec 2007 20:08:06 +0000 (20:08 +0000)
src/box3d-context.cpp
src/box3d.cpp
src/box3d.h
src/desktop-style.cpp
src/persp3d.cpp
src/persp3d.h
src/vanishing-point.cpp

index d74b0e7d1c8c88d29d52f89eaccc6427c03a6f27..858e7fc57be29c9cfbaa59b068a1bed976f72843 100644 (file)
@@ -187,7 +187,7 @@ static void sp_box3d_context_selection_changed(Inkscape::Selection *selection, g
 
     SPDocument *doc = sp_desktop_document(bc->desktop);
     doc->persps_sel.clear();
-    doc->persps_sel = persp3d_currently_selected(bc);
+    doc->persps_sel = persp3d_currently_selected_persps(ec);
 
     SPItem *item = selection->singleItem();
     if (item) {
@@ -538,7 +538,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
             break;
         case GDK_X:
             if (MOD__CTRL) break; // Don't catch Ctrl+X ('cut') and Ctrl+Shift+X ('open XML editor')
-            persp3d_toggle_VPs(persp3d_currently_selected(bc), Proj::X);
+            persp3d_toggle_VPs(persp3d_currently_selected_persps(event_context), Proj::X);
             bc->_vpdrag->updateLines(); // FIXME: Shouldn't this be done automatically?
             ret = true;
             break;
@@ -546,7 +546,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
         case GDK_Y:
         {
             if (MOD__CTRL) break; // Don't catch Ctrl+Y ("redo")
-            persp3d_toggle_VPs(persp3d_currently_selected(bc), Proj::Y);
+            persp3d_toggle_VPs(persp3d_currently_selected_persps(event_context), Proj::Y);
             bc->_vpdrag->updateLines(); // FIXME: Shouldn't this be done automatically?
             ret = true;
             break;
@@ -555,7 +555,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
         case GDK_Z:
         {
             if (MOD__CTRL) break; // Don't catch Ctrl+Z ("undo")
-            persp3d_toggle_VPs(persp3d_currently_selected(bc), Proj::Z);
+            persp3d_toggle_VPs(persp3d_currently_selected_persps(event_context), Proj::Z);
             bc->_vpdrag->updateLines(); // FIXME: Shouldn't this be done automatically?
             ret = true;
             break;
index c9f3bb7d296b63b2533f1cdad606838d2caf921e..038a6b06b768e45b6edfbe849a03883fdfd65896 100644 (file)
@@ -345,11 +345,29 @@ box3d_position_set (SPBox3D *box)
 static NR::Matrix
 box3d_set_transform(SPItem *item, NR::Matrix const &xform)
 {
-    SPBox3D *box = SP_BOX3D(item);
-
-    Persp3D *persp = box->persp_ref->getObject();
+    /* check whether we need to unlink any boxes from their perspectives */
+    std::set<Persp3D *> p_sel = persp3d_currently_selected_persps(inkscape_active_event_context());
+    Persp3D *persp;
+    Persp3D *transf_persp;
+    for (std::set<Persp3D *>::iterator p = p_sel.begin(); p != p_sel.end(); ++p) {
+        persp = (*p);
+        if (!persp3d_has_all_boxes_in_selection (persp)) {
+            std::list<SPBox3D *> sel = persp3d_selected_boxes (persp);
+
+            /* 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);
+
+            for (std::list<SPBox3D *>::iterator b = sel.begin(); b != sel.end(); ++b) {
+                box3d_switch_perspectives(*b, persp, transf_persp);
+            }
+        } else {
+            transf_persp = persp;
+        }
 
-    persp3d_apply_affine_transformation(persp, xform); // also triggers repr updates
+        /* concatenate the affine transformation with the perspective mapping; this
+           function also triggers repr updates of boxes and the perspective itself */
+        persp3d_apply_affine_transformation(transf_persp, xform);
+    }
 
     /***
     // FIXME: We somehow have to apply the transformation to strokes, patterns, and gradients. How?
@@ -1324,6 +1342,16 @@ box3d_relabel_corners(SPBox3D *box) {
     box3d_swap_coords(box, Proj::Z, true);
 }
 
+void
+box3d_switch_perspectives(SPBox3D *box, Persp3D *old_persp, Persp3D *new_persp) {
+    persp3d_remove_box (old_persp, box);
+    persp3d_add_box (new_persp, box);
+    gchar *href = g_strdup_printf("#%s", SP_OBJECT_REPR(new_persp)->attribute("id"));
+    SP_OBJECT_REPR(box)->setAttribute("inkscape:perspectiveID", href);
+    g_free(href);
+}
+
+
 /*
   Local Variables:
   mode:c++
index c676696e99e978b32caba2f7b58f45a55fab1837..78ee450779bcf9eddd6d60b18af7a469c83651a2 100644 (file)
@@ -70,6 +70,7 @@ int box3d_VP_lies_in_PL_sector (SPBox3D const *box, Proj::Axis vpdir, int id1, i
 /* ensures that the coordinates of corner0 and corner7 are in the correct order (to prevent everted boxes) */
 void box3d_relabel_corners(SPBox3D *box);
 
+void box3d_switch_perspectives(SPBox3D *box, Persp3D *old_persp, Persp3D *new_persp);
 
 #endif /* __SP_BOX3D_H__ */
 
index eaa4ee6a7a5be8473f13d636a40e9e6867e3d59d..d0cecda03673b8b4cc306b47e1c78bd4e260fe97 100644 (file)
@@ -167,10 +167,8 @@ sp_desktop_set_style(SPDesktop *desktop, SPCSSAttr *css, bool change, bool write
         for (const GSList *i = desktop->selection->itemList(); i != NULL; i = i->next) {
             /* last used styles for 3D box faces are stored separately */
             if (SP_IS_BOX3D_SIDE (i->data)) {
-                //const char * descr  = SP_OBJECT_REPR (G_OBJECT (i->data))->attribute ("inkscape:box3dside");
                 const char * descr  = box3d_side_axes_string(SP_BOX3D_SIDE(i->data));
                 if (descr != NULL) {
-                    g_print ("################ Box3DSide description found.\n");
                     gchar *style_grp = g_strconcat ("desktop.", descr, NULL);
                     sp_repr_css_change(inkscape_get_repr(INKSCAPE, style_grp), css_write, "style");
                     g_free (style_grp);
index 3dafba30de3559afa8ce45624be96c55a26ae65f..818afe053ffacd106536a41410d5a24e75caf2e5 100644 (file)
@@ -129,6 +129,8 @@ static void persp3d_build(SPObject *object, SPDocument *document, Inkscape::XML:
 static void persp3d_release(SPObject *object) {
     //Persp3D *persp = (Persp3D *) object;
 
+    SP_OBJECT_REPR(object)->removeListenerByData(object);
+
     // FIXME: What precisely does this do and is it necessary for perspectives?
     /**
     if (SP_OBJECT_DOCUMENT(object)) {
@@ -356,6 +358,7 @@ void
 persp3d_apply_affine_transformation (Persp3D *persp, NR::Matrix const &xform) {
     persp->tmat *= xform;
     persp3d_update_box_reprs(persp);
+    SP_OBJECT(persp)->updateRepr(SP_OBJECT_WRITE_EXT);
 }
 
 gchar *
@@ -489,8 +492,8 @@ persp3d_on_repr_attr_changed ( Inkscape::XML::Node * repr,
 
 /* returns a std::set() of all perspectives of the currently selected boxes */
 std::set<Persp3D *>
-persp3d_currently_selected (Box3DContext *bc) {
-    Inkscape::Selection *selection = sp_desktop_selection (bc->desktop);
+persp3d_currently_selected_persps (SPEventContext *ec) {
+    Inkscape::Selection *selection = sp_desktop_selection (ec->desktop);
 
     std::set<Persp3D *> p;
     for (GSList *i = (GSList *) selection->itemList(); i != NULL; i = i->next) {
@@ -501,6 +504,33 @@ persp3d_currently_selected (Box3DContext *bc) {
     return p;
 }
 
+/* checks whether all boxes linked to this perspective are currently selected */
+bool
+persp3d_has_all_boxes_in_selection (Persp3D *persp) {
+    const GSList *selection = sp_desktop_selection (inkscape_active_desktop())->itemList();
+
+    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
+        if (g_slist_find((GSList *) selection, *i) == NULL) {
+            // we have an unselected box in the perspective
+            return false;
+        }
+    }
+    return true;
+}
+
+std::list<SPBox3D *>
+persp3d_selected_boxes (Persp3D *persp) {
+    const GSList *selection = sp_desktop_selection (inkscape_active_desktop())->itemList();
+    std::list<SPBox3D *> sel;
+
+    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
+        if (g_slist_find((GSList *) selection, *i) != NULL) {
+            sel.push_back(SP_BOX3D(*i));
+        }
+    }
+    return sel;
+}
+
 void
 persp3d_print_debugging_info (Persp3D *persp) {
     g_print ("=== Info for Persp3D %d ===\n", persp->my_counter);
index 934136ba2ea9a273163783e99b93929fe58b1719..696c0cdad9795bae96c67399d98c9489e32a7467 100644 (file)
@@ -75,7 +75,9 @@ void persp3d_absorb(Persp3D *persp1, Persp3D *persp2);
 
 Persp3D * persp3d_create_xml_element (SPDocument *document, Persp3D *dup = NULL);
 
-std::set<Persp3D *> persp3d_currently_selected (Box3DContext *bc);
+std::set<Persp3D *> persp3d_currently_selected_persps (SPEventContext *ec);
+bool persp3d_has_all_boxes_in_selection (Persp3D *persp);
+std::list<SPBox3D *> persp3d_selected_boxes (Persp3D *persp);
 
 void persp3d_print_debugging_info (Persp3D *persp);
 void persp3d_print_debugging_info_all(SPDocument *doc);
index 0a8336102c290feaa5ac46f0c42e32c4563684ad..0b68ff54141f279879d41090b8ed71c9359acbc5 100644 (file)
@@ -125,11 +125,7 @@ vp_knot_moved_handler (SPKnot *knot, NR::Point const *ppointer, guint state, gpo
                         /* if a box in the VP is unselected, move it to the
                            newly created perspective so that it doesn't get dragged **/
                         //g_print ("   switching box #%d to new perspective.\n", (*i)->my_counter);
-                        persp3d_remove_box (old_persp, *i);
-                        persp3d_add_box (new_persp, *i);
-                        gchar *href = g_strdup_printf("#%s", SP_OBJECT_REPR(new_persp)->attribute("id"));
-                        SP_OBJECT_REPR(*i)->setAttribute("inkscape:perspectiveID", href);
-                        g_free(href);
+                        box3d_switch_perspectives(*i, old_persp, new_persp);
                     }
                 }
             }