summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMaximilian Albert <maximilian.albert@gmail.com>2007-09-01 23:36:14 +0000
committercilix42 <cilix42@users.sourceforge.net>2007-09-01 23:36:14 +0000
commit731a203a18d1028cefeea2bb19aa727149e0a4c4 (patch)
tree1d5dce4db226b7c905c99fe684e30c2f5842ce67 /src
parentrelabel widgets for (hopefully) clarity (diff)
downloadinkscape-731a203a18d1028cefeea2bb19aa727149e0a4c4.tar.gz
inkscape-731a203a18d1028cefeea2bb19aa727149e0a4c4.zip
Decent support for setting the direction of infinite VPs via the toolbar and partial fix for wrong undo behaviour (?)
(bzr r3659)
Diffstat (limited to 'src')
-rw-r--r--src/box3d.cpp8
-rw-r--r--src/perspective3d.cpp10
-rw-r--r--src/vanishing-point.cpp11
-rw-r--r--src/vanishing-point.h2
-rw-r--r--src/widgets/toolbox.cpp285
5 files changed, 276 insertions, 40 deletions
diff --git a/src/box3d.cpp b/src/box3d.cpp
index 1942ea3d6..e47aa73b3 100644
--- a/src/box3d.cpp
+++ b/src/box3d.cpp
@@ -234,7 +234,13 @@ sp_3dbox_update(SPObject *object, SPCtx *ctx, guint flags)
{
if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
SP3DBox *box = SP_3DBOX(object);
- sp_3dbox_link_to_existing_paths (box, SP_OBJECT_REPR(object));
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(object);
+ sp_3dbox_link_to_existing_paths (box, repr);
+ SP3DBoxContext *bc = SP_3DBOX_CONTEXT (inkscape_active_event_context());
+ bc->_vpdrag->updateDraggers();
+ // FIXME: Should we update the corners here, too? Maybe this is the reason why the handles
+ // are off after an undo/redo! On the other hand, if we do so we get warnings about
+ // updates occuring while other updats are in progress ...
}
/* Invoke parent method */
diff --git a/src/perspective3d.cpp b/src/perspective3d.cpp
index 9321af356..db4f564c7 100644
--- a/src/perspective3d.cpp
+++ b/src/perspective3d.cpp
@@ -196,6 +196,11 @@ Perspective3D::set_infinite_direction (Box3D::Axis axis, NR::Point const dir)
}
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
@@ -207,11 +212,6 @@ Perspective3D::rotate (Box3D::Axis const axis, double const angle)
a += angle;
a *= M_PI/180;
this->set_infinite_direction (axis, NR::Point (cos (a), sin (a)));
- 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();
}
}
diff --git a/src/vanishing-point.cpp b/src/vanishing-point.cpp
index 2426c9954..f5e98face 100644
--- a/src/vanishing-point.cpp
+++ b/src/vanishing-point.cpp
@@ -270,6 +270,8 @@ vp_knot_grabbed_handler (SPKnot *knot, unsigned int state, gpointer data)
VPDragger *dragger = (VPDragger *) data;
VPDrag *drag = dragger->parent;
+ drag->dragging = true;
+
//sp_canvas_force_full_redraw_after_interruptions(dragger->parent->desktop->canvas, 5);
if ((state & GDK_SHIFT_MASK) && !drag->hasEmptySelection()) { // FIXME: Is the second check necessary?
@@ -369,7 +371,13 @@ vp_knot_ungrabbed_handler (SPKnot *knot, guint state, gpointer data)
// TODO: Update box's paths and svg representation
+ dragger->parent->dragging = false;
+
// TODO: Undo machinery!!
+ g_return_if_fail (dragger->parent);
+ g_return_if_fail (dragger->parent->document);
+ sp_document_done(dragger->parent->document, SP_VERB_CONTEXT_3DBOX,
+ _("3D box: Move vanishing point"));
}
VPDragger::VPDragger(VPDrag *parent, NR::Point p, VanishingPoint *vp)
@@ -613,6 +621,7 @@ VPDrag::VPDrag (SPDocument *document)
//this->selected = NULL;
this->local_change = false;
+ this->dragging = false;
this->sel_changed_connection = this->selection->connectChanged(
sigc::bind (
@@ -676,6 +685,8 @@ VPDrag::getDraggerFor (VanishingPoint const &vp)
void
VPDrag::updateDraggers ()
{
+ if (this->dragging)
+ return;
/***
while (selected) {
selected = g_list_remove(selected, selected->data);
diff --git a/src/vanishing-point.h b/src/vanishing-point.h
index 428bb49ad..3dde39385 100644
--- a/src/vanishing-point.h
+++ b/src/vanishing-point.h
@@ -55,6 +55,7 @@ public:
bool operator== (VanishingPoint const &other);
inline NR::Point get_pos() const { return NR::Point ((*this)[NR::X], (*this)[NR::Y]); }
+ inline double get_angle() const { return NR::atan2 (this->v_dir) * 180/M_PI; } // return angle of infinite direction is in degrees
inline void set_pos(NR::Point const &pt) { (*this)[NR::X] = pt[NR::X];
(*this)[NR::Y] = pt[NR::Y]; }
inline void set_pos(const double pt_x, const double pt_y) { (*this)[NR::X] = pt_x;
@@ -120,6 +121,7 @@ public:
//void grabKnot (VanishingPoint const &vp, gint x, gint y, guint32 etime);
bool local_change;
+ bool dragging;
SPDocument *document;
GList *draggers;
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index 7e5de6b51..81bdc6607 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -303,8 +303,13 @@ static gchar const * ui_descr =
" </toolbar>"
" <toolbar name='3DBoxToolbar'>"
+ " <toolitem action='3DBoxPosAngleXAction' />"
" <toolitem action='3DBoxVPXAction' />"
+ " <separator />"
+ " <toolitem action='3DBoxPosAngleYAction' />"
" <toolitem action='3DBoxVPYAction' />"
+ " <separator />"
+ " <toolitem action='3DBoxPosAngleZAction' />"
" <toolitem action='3DBoxVPZAction' />"
" <separator />"
" </toolbar>"
@@ -2146,68 +2151,280 @@ static void sp_rect_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
//## 3D Box ##
//########################
-static void sp_3dbox_toggle_vp_changed( GtkToggleAction *act, gpointer data )
+static void sp_3dbox_toggle_vp_changed (GtkToggleAction *act, GObject *dataKludge, Box3D::Axis axis)
{
- SPDocument *document = sp_desktop_document (inkscape_active_desktop ());
- Box3D::Axis axis = (Box3D::Axis) GPOINTER_TO_INT(data);
+ SPDesktop *desktop = (SPDesktop *) g_object_get_data (dataKludge, "desktop");
+ SPDocument *document = sp_desktop_document (desktop);
+ Box3D::Perspective3D *persp = document->current_perspective;
- if (document->current_perspective) {
- document->current_perspective->toggle_boxes (axis);
+ g_return_if_fail (is_single_axis_direction (axis));
+ g_return_if_fail (persp);
+
+ persp->toggle_boxes (axis);
+
+ gchar *str;
+ switch (axis) {
+ case Box3D::X:
+ str = g_strdup ("box3d_angle_x_action");
+ break;
+ case Box3D::Y:
+ str = g_strdup ("box3d_angle_y_action");
+ break;
+ case Box3D::Z:
+ str = g_strdup ("box3d_angle_z_action");
+ break;
+ default:
+ return;
+ }
+ GtkAction* angle_action = GTK_ACTION (g_object_get_data (dataKludge, str));
+ if (angle_action) {
+ gtk_action_set_sensitive (angle_action, !persp->get_vanishing_point (axis)->is_finite() );
+ }
+
+ // FIXME: Given how it is realized in the other tools, this is probably not the right way to do it,
+ // but without the if construct, we get continuous segfaults. Needs further investigation.
+ if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
+ sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX,
+ _("3D Box: Change perspective"));
+ }
+}
+
+static void sp_3dbox_toggle_vp_x_changed(GtkToggleAction *act, GObject *dataKludge)
+{
+ sp_3dbox_toggle_vp_changed (act, dataKludge, Box3D::X);
+}
+
+static void sp_3dbox_toggle_vp_y_changed(GtkToggleAction *act, GObject *dataKludge)
+{
+ sp_3dbox_toggle_vp_changed (act, dataKludge, Box3D::Y);
+}
+
+static void sp_3dbox_toggle_vp_z_changed(GtkToggleAction *act, GObject *dataKludge)
+{
+ sp_3dbox_toggle_vp_changed (act, dataKludge, Box3D::Z);
+}
+
+static void sp_3dbox_vp_angle_changed(GtkAdjustment *adj, GObject *dataKludge, Box3D::Axis axis )
+{
+ SPDesktop *desktop = (SPDesktop *) g_object_get_data(dataKludge, "desktop");
+ Box3D::Perspective3D *persp = sp_desktop_document (desktop)->current_perspective;
+
+ if (persp) {
+ double angle = adj->value * M_PI/180;
+ persp->set_infinite_direction (axis, NR::Point (cos (angle), sin (angle)));
+
+ // FIXME: See comment above; without the if construct we get segfaults during undo.
+ if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
+ sp_document_maybe_done(sp_desktop_document(desktop), "perspectiveangle", SP_VERB_CONTEXT_3DBOX,
+ _("3D Box: Change perspective"));
+ }
+ }
+ //g_object_set_data(G_OBJECT(dataKludge), "freeze", GINT_TO_POINTER(FALSE));
+}
+
+static void sp_3dbox_vpx_angle_changed(GtkAdjustment *adj, GObject *dataKludge )
+{
+ sp_3dbox_vp_angle_changed (adj, dataKludge, Box3D::X);
+}
+
+static void sp_3dbox_vpy_angle_changed(GtkAdjustment *adj, GObject *dataKludge )
+{
+ sp_3dbox_vp_angle_changed (adj, dataKludge, Box3D::Y);
+}
+
+static void sp_3dbox_vpz_angle_changed(GtkAdjustment *adj, GObject *dataKludge )
+{
+ sp_3dbox_vp_angle_changed (adj, dataKludge, Box3D::Z);
+}
+
+// normalize angle so that it lies in the interval [0,360]
+static double sp_3dbox_normalize_angle (double a) {
+ double angle = a + ((int) (a/360.0))*360;
+ if (angle < 0) {
+ angle += 360.0;
+ }
+ return angle;
+}
+
+static void sp_3dbox_tb_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name,
+ gchar const *old_value, gchar const *new_value,
+ bool is_interactive, gpointer data)
+{
+ GtkWidget *tbl = GTK_WIDGET(data);
+
+ // FIXME: if we check for "freeze" as in other tools, no action is performed at all ...
+ /***
+ // quit if run by the _changed callbacks
+ if (g_object_get_data(G_OBJECT(tbl), "freeze")) {
+ return;
+ }
+
+ // in turn, prevent callbacks from responding
+ g_object_set_data(G_OBJECT(tbl), "freeze", GINT_TO_POINTER(TRUE));
+ ***/
+
+ if (!strcmp(name, "inkscape:perspective")) {
+ GtkAdjustment *adj = 0;
+ double angle;
+ SPDesktop *desktop = (SPDesktop *) g_object_get_data(G_OBJECT(tbl), "desktop");
+ Box3D::Perspective3D *persp = sp_desktop_document (desktop)->current_perspective;
+
+ adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_x"));
+ angle = sp_3dbox_normalize_angle (persp->get_vanishing_point (Box3D::X)->get_angle());
+ gtk_adjustment_set_value(adj, angle);
+
+ adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_y"));
+ angle = sp_3dbox_normalize_angle (persp->get_vanishing_point (Box3D::Y)->get_angle());
+ gtk_adjustment_set_value(adj, angle);
+
+ adj = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(tbl), "dir_vp_z"));
+ angle = sp_3dbox_normalize_angle (persp->get_vanishing_point (Box3D::Z)->get_angle());
+ gtk_adjustment_set_value(adj, angle);
+ }
+}
+
+static Inkscape::XML::NodeEventVector sp_3dbox_tb_repr_events =
+{
+ NULL, /* child_added */
+ NULL, /* child_removed */
+ sp_3dbox_tb_event_attr_changed,
+ NULL, /* content_changed */
+ NULL /* order_changed */
+};
+
+/**
+ * \param selection Should not be NULL.
+ */
+static void
+sp_3dbox_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl)
+{
+ Inkscape::XML::Node *repr = NULL;
+ purge_repr_listener(tbl, tbl);
+
+ SPItem *item = selection->singleItem();
+ if (item) {
+ repr = SP_OBJECT_REPR(item);
+ if (repr) {
+ g_object_set_data(tbl, "repr", repr);
+ Inkscape::GC::anchor(repr);
+ sp_repr_add_listener(repr, &sp_3dbox_tb_repr_events, tbl);
+ sp_repr_synthesize_events(repr, &sp_3dbox_tb_repr_events, tbl);
+ }
}
-
}
static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
{
+ EgeAdjustmentAction* eact = 0;
SPDocument *document = sp_desktop_document (desktop);
+ Box3D::Perspective3D *persp = document->current_perspective;
bool toggled = false;
+
+ /* angle of VP in X direction */
+ eact = create_adjustment_action("3DBoxPosAngleXAction",
+ _("Angle X:"), _("Angle of infinite vanishing point in X direction"),
+ "tools.shapes.3dbox", "dir_vp_x", persp->get_vanishing_point (Box3D::X)->get_angle(),
+ GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
+ 0.0, 360.0, 1.0, 10.0,
+ 0, 0, 0, // labels, values, G_N_ELEMENTS(labels),
+ sp_3dbox_vpx_angle_changed,
+ 0.1, 1);
+ gtk_action_group_add_action(mainActions, GTK_ACTION(eact));
+ g_object_set_data(holder, "box3d_angle_x_action", eact);
+ if (!persp->get_vanishing_point (Box3D::X)->is_finite()) {
+ gtk_action_set_sensitive(GTK_ACTION(eact), TRUE);
+ } else {
+ gtk_action_set_sensitive(GTK_ACTION(eact), FALSE);
+ }
+
/* toggle VP in X direction */
{
- InkToggleAction* act = ink_toggle_action_new( "3DBoxVPXAction",
+ InkToggleAction* act = ink_toggle_action_new("3DBoxVPXAction",
_("Toggle VP in X direction"),
_("Toggle VP in X direction between 'finite' and 'infinite' (=parallel)"),
"toggle_vp_x",
- Inkscape::ICON_SIZE_DECORATION );
- gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- if (document->current_perspective) {
- toggled = !document->current_perspective->get_vanishing_point(Box3D::X)->is_finite();
+ Inkscape::ICON_SIZE_DECORATION);
+ gtk_action_group_add_action(mainActions, GTK_ACTION(act));
+ if (persp) {
+ toggled = !persp->get_vanishing_point(Box3D::X)->is_finite();
}
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled );
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), toggled);
/* we connect the signal after setting the state to avoid switching the state again */
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::X));
+ g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_x_changed), holder);
+ }
+
+ /* angle of VP in Y direction */
+ eact = create_adjustment_action("3DBoxPosAngleYAction",
+ _("Angle Y:"), _("Angle of infinite vanishing point in Y direction"),
+ "tools.shapes.3dbox", "dir_vp_y", persp->get_vanishing_point (Box3D::Y)->get_angle(),
+ GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
+ 0.0, 360.0, 1.0, 10.0,
+ 0, 0, 0, // labels, values, G_N_ELEMENTS(labels),
+ sp_3dbox_vpy_angle_changed,
+ 0.1, 1);
+ gtk_action_group_add_action(mainActions, GTK_ACTION(eact));
+ g_object_set_data(holder, "box3d_angle_y_action", eact);
+ if (!persp->get_vanishing_point (Box3D::Y)->is_finite()) {
+ gtk_action_set_sensitive(GTK_ACTION(eact), TRUE);
+ } else {
+ gtk_action_set_sensitive(GTK_ACTION(eact), FALSE);
}
/* toggle VP in Y direction */
{
- InkToggleAction* act = ink_toggle_action_new( "3DBoxVPYAction",
- _("Toggle VP in Y direction"),
- _("Toggle VP in Y direction between 'finite' and 'infinite' (=parallel)"),
- "toggle_vp_y",
- Inkscape::ICON_SIZE_DECORATION );
- gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- if (document->current_perspective) {
- toggled = !document->current_perspective->get_vanishing_point(Box3D::Y)->is_finite();
- }
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled );
+ InkToggleAction* act = ink_toggle_action_new("3DBoxVPYAction",
+ _("Toggle VP in Y direction"),
+ _("Toggle VP in Y direction between 'finite' and 'infinite' (=parallel)"),
+ "toggle_vp_y",
+ Inkscape::ICON_SIZE_DECORATION);
+ gtk_action_group_add_action(mainActions, GTK_ACTION(act));
+ if (persp) {
+ toggled = !persp->get_vanishing_point(Box3D::Y)->is_finite();
+ }
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), toggled);
/* we connect the signal after setting the state to avoid switching the state again */
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::Y));
+ g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_y_changed), holder);
+ }
+
+ /* angle of VP in Z direction */
+ eact = create_adjustment_action("3DBoxPosAngleZAction",
+ _("Angle Z:"), _("Angle of infinite vanishing point in Z direction"),
+ "tools.shapes.3dbox", "dir_vp_z", persp->get_vanishing_point (Box3D::Z)->get_angle(),
+ GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
+ 0.0, 360.0, 1.0, 10.0,
+ 0, 0, 0, // labels, values, G_N_ELEMENTS(labels),
+ sp_3dbox_vpz_angle_changed,
+ 0.1, 1);
+
+ gtk_action_group_add_action(mainActions, GTK_ACTION(eact));
+ g_object_set_data(holder, "box3d_angle_z_action", eact);
+ if (!persp->get_vanishing_point (Box3D::Z)->is_finite()) {
+ gtk_action_set_sensitive(GTK_ACTION(eact), TRUE);
+ } else {
+ gtk_action_set_sensitive(GTK_ACTION(eact), FALSE);
}
/* toggle VP in Z direction */
{
- InkToggleAction* act = ink_toggle_action_new( "3DBoxVPZAction",
- _("Toggle VP in Z direction"),
- _("Toggle VP in Z direction between 'finite' and 'infinite' (=parallel)"),
- "toggle_vp_z",
- Inkscape::ICON_SIZE_DECORATION );
- gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
- if (document->current_perspective) {
- toggled = !document->current_perspective->get_vanishing_point(Box3D::Z)->is_finite();
+ InkToggleAction* act = ink_toggle_action_new("3DBoxVPZAction",
+ _("Toggle VP in Z direction"),
+ _("Toggle VP in Z direction between 'finite' and 'infinite' (=parallel)"),
+ "toggle_vp_z",
+ Inkscape::ICON_SIZE_DECORATION);
+ gtk_action_group_add_action(mainActions, GTK_ACTION(act));
+ if (persp) {
+ toggled = !persp->get_vanishing_point(Box3D::Z)->is_finite();
}
/* we connect the signal after setting the state to avoid switching the state again */
- gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled );
- g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::Z));
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), toggled);
+ g_signal_connect_after(G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_z_changed), holder);
}
+
+ sigc::connection *connection = new sigc::connection(
+ sp_desktop_selection(desktop)->connectChanged(sigc::bind(sigc::ptr_fun(sp_3dbox_toolbox_selection_changed), (GObject *)holder))
+ );
+ g_signal_connect(holder, "destroy", G_CALLBACK(delete_connection), connection);
+ g_signal_connect(holder, "destroy", G_CALLBACK(purge_repr_listener), holder);
}
//########################