summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMaximilian Albert <maximilian.albert@gmail.com>2007-12-13 20:08:06 +0000
committercilix42 <cilix42@users.sourceforge.net>2007-12-13 20:08:06 +0000
commit49308ff2f6ca0d4c640bc584b1b87a3ee6e31e97 (patch)
treeb02d64329cded4890fb01b7f9dd33a49f274eec7 /src
parentImproved tango icons by Michael Grossberg. (diff)
downloadinkscape-49308ff2f6ca0d4c640bc584b1b87a3ee6e31e97.tar.gz
inkscape-49308ff2f6ca0d4c640bc584b1b87a3ee6e31e97.zip
If necessary, split up perspectives when applying transformations to boxes; moreover, fix crash caused by listening to already destroyed perspectives
(bzr r4227)
Diffstat (limited to 'src')
-rw-r--r--src/box3d-context.cpp8
-rw-r--r--src/box3d.cpp36
-rw-r--r--src/box3d.h1
-rw-r--r--src/desktop-style.cpp2
-rw-r--r--src/persp3d.cpp34
-rw-r--r--src/persp3d.h4
-rw-r--r--src/vanishing-point.cpp6
7 files changed, 73 insertions, 18 deletions
diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp
index d74b0e7d1..858e7fc57 100644
--- a/src/box3d-context.cpp
+++ b/src/box3d-context.cpp
@@ -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;
diff --git a/src/box3d.cpp b/src/box3d.cpp
index c9f3bb7d2..038a6b06b 100644
--- a/src/box3d.cpp
+++ b/src/box3d.cpp
@@ -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++
diff --git a/src/box3d.h b/src/box3d.h
index c676696e9..78ee45077 100644
--- a/src/box3d.h
+++ b/src/box3d.h
@@ -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__ */
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp
index eaa4ee6a7..d0cecda03 100644
--- a/src/desktop-style.cpp
+++ b/src/desktop-style.cpp
@@ -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);
diff --git a/src/persp3d.cpp b/src/persp3d.cpp
index 3dafba30d..818afe053 100644
--- a/src/persp3d.cpp
+++ b/src/persp3d.cpp
@@ -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);
diff --git a/src/persp3d.h b/src/persp3d.h
index 934136ba2..696c0cdad 100644
--- a/src/persp3d.h
+++ b/src/persp3d.h
@@ -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);
diff --git a/src/vanishing-point.cpp b/src/vanishing-point.cpp
index 0a8336102..0b68ff541 100644
--- a/src/vanishing-point.cpp
+++ b/src/vanishing-point.cpp
@@ -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);
}
}
}