summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 772ae09)
raw | patch | inline | side by side (parent: 772ae09)
author | cilix42 <cilix42@users.sourceforge.net> | |
Mon, 6 Aug 2007 07:37:24 +0000 (07:37 +0000) | ||
committer | cilix42 <cilix42@users.sourceforge.net> | |
Mon, 6 Aug 2007 07:37:24 +0000 (07:37 +0000) |
diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp
index 5f1029576a6420e68a545fb61aa691f424f3a47f..3096ad17985c268d9e3ed897a8d62cb037082be4 100644 (file)
--- a/src/box3d-context.cpp
+++ b/src/box3d-context.cpp
box3d_context->ctrl_dragged = false;
box3d_context->extruded = false;
+ box3d_context->_vpdrag = NULL;
+
new (&box3d_context->sel_changed_connection) sigc::connection();
}
ec->enableGrDrag(false);
+ delete (bc->_vpdrag);
+ bc->_vpdrag = NULL;
+
bc->sel_changed_connection.disconnect();
bc->sel_changed_connection.~connection();
sigc::bind(sigc::ptr_fun(&sp_3dbox_context_selection_changed), (gpointer)bc)
);
+ bc->_vpdrag = new Box3D::VPDrag(ec->desktop);
+
if (prefs_get_int_attribute("tools.shapes", "selcue", 0) != 0) {
ec->enableSelectionCue();
}
}
bc.item->updateRepr();
+ // TODO: It would be nice to show the VPs during dragging, but since there is no selection
+ // at this point (only after finishing the box), we must do this "manually"
+ bc._vpdrag->updateDraggers();
sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 5);
}
diff --git a/src/box3d-context.h b/src/box3d-context.h
index bf359ebe7ff58884e498a0ed041c1cd42aff7963..6d2e560d45f610ad4ca03ef06e50e571237c3480 100644 (file)
--- a/src/box3d-context.h
+++ b/src/box3d-context.h
bool ctrl_dragged; /* whether we are ctrl-dragging */
bool extruded; /* whether shift-dragging already occured (i.e. the box is already extruded) */
+ Box3D::VPDrag * _vpdrag;
+
/* temporary member until the precise behaviour is sorted out */
static guint number_of_handles;
diff --git a/src/object-edit.cpp b/src/object-edit.cpp
index 6eff465f8ab308b5bf19a3ce15c41f7be4fd7fd0..e8390da20b9fb1b9ae4315df559df827a1826033 100644 (file)
--- a/src/object-edit.cpp
+++ b/src/object-edit.cpp
@@ -546,6 +546,7 @@ static void sp_3dbox_knot_set(SPItem *item, guint knot_id, Box3D::Axis direction
sp_3dbox_move_corner_in_XY_plane (box, knot_id, new_pos * i2d, (state & GDK_SHIFT_MASK) ? direction : Box3D::XY);
}
sp_3dbox_update_curves (box);
+ sp_3dbox_set_ratios (box);
}
static NR::Point sp_3dbox_knot_get(SPItem *item, guint knot_id)
@@ -615,6 +616,7 @@ static void sp_3dbox_knot_set_uniformly(SPItem *item, guint knot_id, Box3D::Axis
sp_3dbox_move_corner_in_Z_direction (box, knot_id, new_pos * i2d, (state & GDK_SHIFT_MASK));
}
sp_3dbox_update_curves (box);
+ sp_3dbox_set_ratios (box);
}
static void sp_3dbox_knot0_set_uniformly(SPItem *item, NR::Point const &new_pos, NR::Point const &origin, guint state)
diff --git a/src/perspective3d.cpp b/src/perspective3d.cpp
index dd05ec7c7cef6ca7563e75782a2a78ce25200908..e5b1f62126f25983d026002cc3a8e5d3fefc3bbc 100644 (file)
--- a/src/perspective3d.cpp
+++ b/src/perspective3d.cpp
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
* vanishing points in the given directions.
{
Perspective3D::remove_perspective (this);
+ // Remove the VPs from their draggers
+ SPEventContext *ec = inkscape_active_event_context();
+ if (SP_IS_3DBOX_CONTEXT (ec)) {
+ SP3DBoxContext *bc = SP_3DBOX_CONTEXT (ec);
+ // we need to check if there are any draggers because the selection
+ // is temporarily empty during duplication of boxes, e.g.
+ if (bc->_vpdrag->draggers != NULL) {
+ /***
+ g_assert (bc->_vpdrag->getDraggerFor (*vp_x) != NULL);
+ g_assert (bc->_vpdrag->getDraggerFor (*vp_y) != NULL);
+ g_assert (bc->_vpdrag->getDraggerFor (*vp_z) != NULL);
+ bc->_vpdrag->getDraggerFor (*vp_x)->removeVP (vp_x);
+ bc->_vpdrag->getDraggerFor (*vp_y)->removeVP (vp_y);
+ bc->_vpdrag->getDraggerFor (*vp_z)->removeVP (vp_z);
+ ***/
+ // TODO: the temporary perspective created when building boxes is not linked to any dragger, hence
+ // we need to do the following checks. Maybe it would be better to not create a temporary
+ // perspective at all but simply compare the VPs manually in sp_3dbox_build.
+ VPDragger * dragger;
+ dragger = bc->_vpdrag->getDraggerFor (*vp_x);
+ if (dragger)
+ dragger->removeVP (vp_x);
+ dragger = bc->_vpdrag->getDraggerFor (*vp_y);
+ if (dragger)
+ dragger->removeVP (vp_y);
+ dragger = bc->_vpdrag->getDraggerFor (*vp_z);
+ if (dragger)
+ dragger->removeVP (vp_z);
+ }
+ }
+
delete vp_x;
delete vp_y;
delete vp_z;
@@ -145,6 +193,17 @@ Perspective3D::set_vanishing_point (Box3D::Axis const dir, VanishingPoint const
}
}
+Axis
+Perspective3D::get_axis_of_VP (VanishingPoint *vp)
+{
+ if (vp == vp_x) return X;
+ if (vp == vp_y) return Y;
+ if (vp == vp_z) return Z;
+
+ g_warning ("Vanishing point not present in the perspective.\n");
+ return NONE;
+}
+
void
Perspective3D::set_vanishing_point (Box3D::Axis const dir, gdouble pt_x, gdouble pt_y, gdouble dir_x, gdouble dir_y, VPState st)
{
diff --git a/src/perspective3d.h b/src/perspective3d.h
index 43b0ca3d3776fb56c0ad7eeb603292a6d1d69671..c3e07b23b3c0b357ee83d69de6e46c8b48444e35 100644 (file)
--- a/src/perspective3d.h
+++ b/src/perspective3d.h
bool operator== (Perspective3D const &other);
VanishingPoint *get_vanishing_point (Box3D::Axis const dir);
+ Axis get_axis_of_VP (VanishingPoint *vp);
void set_vanishing_point (Box3D::Axis const dir, VanishingPoint const &pt);
void set_vanishing_point (Box3D::Axis const dir, gdouble pt_x, gdouble pt_y, gdouble dir_x, gdouble dir_y, VPState st);
void add_box (SP3DBox *box);
};
Perspective3D * get_persp_of_box (const SP3DBox *box);
+Perspective3D * get_persp_of_VP (const VanishingPoint *vp);
NR::Point perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point pt2, Box3D::Axis dir2, Perspective3D *persp);
NR::Point perspective_line_snap (NR::Point pt, Box3D::Axis dir, NR::Point ext_pt, Perspective3D *persp);
index 5f40936cf5ca637da07e98c252eb15b223274a43..edf769c176388f9c6164836167639bc3fda1ad44 100644 (file)
--- a/src/vanishing-point.cpp
+++ b/src/vanishing-point.cpp
*/
#include "vanishing-point.h"
+#include "desktop-handles.h"
+#include "box3d.h"
namespace Box3D {
+#define VP_KNOT_COLOR_NORMAL 0xffffff00
+#define VP_KNOT_COLOR_SELECTED 0x0000ff00
+
+#define VP_LINE_COLOR_FILL 0x0000ff7f
+#define VP_LINE_COLOR_STROKE_X 0xff00007f
+#define VP_LINE_COLOR_STROKE_Y 0x0000ff7f
+#define VP_LINE_COLOR_STROKE_Z 0xffff007f
+
+// screen pixels between knots when they snap:
+#define SNAP_DIST 5
+
+// absolute distance between gradient points for them to become a single dragger when the drag is created:
+#define MERGE_DIST 0.1
+
+// knot shapes corresponding to GrPointType enum
+SPKnotShapeType vp_knot_shapes [] = {
+ SP_KNOT_SHAPE_SQUARE, // VP_FINITE
+ SP_KNOT_SHAPE_CIRCLE //VP_INFINITE
+};
+
// FIXME: We should always require to have both the point (for finite VPs)
// and the direction (for infinite VPs) set. Otherwise toggling
// shows very unexpected behaviour.
this->v_dir = rhs.v_dir;
}
+VanishingPoint::~VanishingPoint () {}
+
bool VanishingPoint::operator== (VanishingPoint const &other)
{
// Should we compare the parent perspectives, too? Probably not.
}
}
+static void
+vp_drag_sel_changed(Inkscape::Selection *selection, gpointer data)
+{
+ VPDrag *drag = (VPDrag *) data;
+ drag->updateDraggers ();
+ //drag->updateLines ();
+}
+
+static void
+vp_drag_sel_modified (Inkscape::Selection *selection, guint flags, gpointer data)
+{
+ VPDrag *drag = (VPDrag *) data;
+ /***
+ if (drag->local_change) {
+ drag->local_change = false;
+ } else {
+ drag->updateDraggers ();
+ }
+ ***/
+ //drag->updateLines ();
+}
+
+static void
+vp_knot_moved_handler (SPKnot *knot, NR::Point const *ppointer, guint state, gpointer data)
+{
+ g_warning ("Please implement vp_knot_moved_handler.\n");
+ VPDragger *dragger = (VPDragger *) data;
+ //VPDrag *drag = dragger->parent;
+
+ NR::Point p = *ppointer;
+
+ dragger->point = p;
+
+ dragger->reshapeBoxes (p, Box3D::XYZ);
+ //dragger->parent->updateLines ();
+
+ //drag->local_change = false;
+}
+
+static void
+vp_knot_grabbed_handler (SPKnot *knot, unsigned int state, gpointer data)
+{
+ VPDragger *dragger = (VPDragger *) data;
+
+ //sp_canvas_force_full_redraw_after_interruptions(dragger->parent->desktop->canvas, 5);
+}
+
+static void
+vp_knot_ungrabbed_handler (SPKnot *knot, guint state, gpointer data)
+{
+ g_warning ("Please fully implement vp_knot_ungrabbed_handler.\n");
+
+ VPDragger *dragger = (VPDragger *) data;
+ //VPDrag *drag = dragger->parent;
+
+ //sp_canvas_end_forced_full_redraws(dragger->parent->desktop->canvas);
+
+ dragger->point_original = dragger->point = knot->pos;
+
+ /***
+ VanishingPoint *vp;
+ for (GSList *i = dragger->vps; i != NULL; i = i->next) {
+ vp = (VanishingPoint *) i->data;
+ vp->set_pos (knot->pos);
+ }
+ ***/
+
+ dragger->parent->updateDraggers ();
+ dragger->updateBoxReprs ();
+
+ // TODO: Update box's paths and svg representation
+
+ // TODO: Undo machinery!!
+}
+
+VPDragger::VPDragger(VPDrag *parent, NR::Point p, VanishingPoint *vp)
+{
+ if (vp == NULL) {
+ g_print ("VP used to create the VPDragger is NULL. This can happen when shift-dragging knots.\n");
+ g_print ("How to correctly handle this? Should we just ignore it, as we currently do?\n");
+ //g_assert (vp != NULL);
+ }
+ this->vps = NULL;
+
+ this->parent = parent;
+
+ this->point = p;
+ this->point_original = p;
+
+ // create the knot
+ this->knot = sp_knot_new (parent->desktop, NULL);
+ this->knot->setMode(SP_KNOT_MODE_XOR);
+ this->knot->setFill(VP_KNOT_COLOR_NORMAL, VP_KNOT_COLOR_NORMAL, VP_KNOT_COLOR_NORMAL);
+ this->knot->setStroke(0x000000ff, 0x000000ff, 0x000000ff);
+ sp_knot_update_ctrl(this->knot);
+
+ // move knot to the given point
+ sp_knot_set_position (this->knot, &this->point, SP_KNOT_STATE_NORMAL);
+ sp_knot_show (this->knot);
+
+ // connect knot's signals
+ g_signal_connect (G_OBJECT (this->knot), "moved", G_CALLBACK (vp_knot_moved_handler), this);
+ /***
+ g_signal_connect (G_OBJECT (this->knot), "clicked", G_CALLBACK (vp_knot_clicked_handler), this);
+ ***/
+ g_signal_connect (G_OBJECT (this->knot), "grabbed", G_CALLBACK (vp_knot_grabbed_handler), this);
+ g_signal_connect (G_OBJECT (this->knot), "ungrabbed", G_CALLBACK (vp_knot_ungrabbed_handler), this);
+ /***
+ g_signal_connect (G_OBJECT (this->knot), "doubleclicked", G_CALLBACK (vp_knot_doubleclicked_handler), this);
+ ***/
+
+ // add the initial VP (which may be NULL!)
+ this->addVP (vp);
+ //updateKnotShape();
+}
+
+VPDragger::~VPDragger()
+{
+ // unselect if it was selected
+ //this->parent->setDeselected(this);
+
+ // disconnect signals
+ g_signal_handlers_disconnect_by_func(G_OBJECT(this->knot), (gpointer) G_CALLBACK (vp_knot_moved_handler), this);
+ /***
+ g_signal_handlers_disconnect_by_func(G_OBJECT(this->knot), (gpointer) G_CALLBACK (vp_knot_clicked_handler), this);
+ ***/
+ g_signal_handlers_disconnect_by_func(G_OBJECT(this->knot), (gpointer) G_CALLBACK (vp_knot_grabbed_handler), this);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(this->knot), (gpointer) G_CALLBACK (vp_knot_ungrabbed_handler), this);
+ /***
+ g_signal_handlers_disconnect_by_func(G_OBJECT(this->knot), (gpointer) G_CALLBACK (vp_knot_doubleclicked_handler), this);
+ ***/
+
+ /* unref should call destroy */
+ g_object_unref (G_OBJECT (this->knot));
+
+ g_slist_free (this->vps);
+ this->vps = NULL;
+}
+
+/**
+ * Adds a vanishing point to the dragger (also updates the position)
+ */
+void
+VPDragger::addVP (VanishingPoint *vp)
+{
+ if (vp == NULL) {
+ g_print ("No VP present in addVP. We return without adding a new VP to the list.\n");
+ return;
+ }
+ vp->set_pos (this->point);
+ this->vps = g_slist_prepend (this->vps, vp);
+
+ //this->updateTip();
+}
+
+void
+VPDragger::removeVP (VanishingPoint *vp)
+{
+ if (vp == NULL) {
+ g_print ("NULL vanishing point will not be removed.\n");
+ return;
+ }
+ g_assert (this->vps != NULL);
+ this->vps = g_slist_remove (this->vps, vp);
+
+ //this->updateTip();
+}
+
+void
+VPDragger::reshapeBoxes (NR::Point const &p, Box3D::Axis axes)
+{
+ Perspective3D *persp;
+ for (GSList const* i = this->vps; i != NULL; i = i->next) {
+ VanishingPoint *vp = (VanishingPoint *) i->data;
+ // TODO: We can extract the VP directly from the box's perspective. Is that vanishing point identical to 'vp'?
+ // Or is there duplicated information? If so, remove it and simplify the whole construction!
+ vp->set_pos(p);
+ persp = get_persp_of_VP (vp);
+ Box3D::Axis axis = persp->get_axis_of_VP (vp);
+ get_persp_of_VP (vp)->reshape_boxes (axis); // FIXME: we should only update the direction of the VP
+ }
+}
+
+void
+VPDragger::updateBoxReprs ()
+{
+ for (GSList *i = this->vps; i != NULL; i = i->next) {
+ Box3D::get_persp_of_VP ((VanishingPoint *) i->data)->update_box_reprs ();
+ }
+}
+
+VPDrag::VPDrag (SPDesktop *desktop)
+{
+ this->desktop = desktop;
+ this->draggers = NULL;
+ this->selection = sp_desktop_selection(desktop);
+
+ this->sel_changed_connection = this->selection->connectChanged(
+ sigc::bind (
+ sigc::ptr_fun(&vp_drag_sel_changed),
+ (gpointer)this )
+
+ );
+ this->sel_modified_connection = this->selection->connectModified(
+ sigc::bind(
+ sigc::ptr_fun(&vp_drag_sel_modified),
+ (gpointer)this )
+ );
+
+ this->updateDraggers ();
+ //this->updateLines ();
+}
+
+VPDrag::~VPDrag()
+{
+ this->sel_changed_connection.disconnect();
+ this->sel_modified_connection.disconnect();
+
+ for (GList *l = this->draggers; l != NULL; l = l->next) {
+ delete ((VPDragger *) l->data);
+ }
+ g_list_free (this->draggers);
+ this->draggers = NULL;
+}
+
+/**
+ * Select the dragger that has the given VP.
+ */
+VPDragger *
+VPDrag::getDraggerFor (VanishingPoint const &vp)
+{
+ for (GList const* i = this->draggers; i != NULL; i = i->next) {
+ VPDragger *dragger = (VPDragger *) i->data;
+ for (GSList const* j = dragger->vps; j != NULL; j = j->next) {
+ VanishingPoint *vp2 = (VanishingPoint *) j->data;
+ g_assert (vp2 != NULL);
+
+ // TODO: Should we compare the pointers or the VPs themselves!?!?!?!
+ //if ((*vp2) == vp) {
+ if (vp2 == &vp) {
+ return (dragger);
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Regenerates the draggers list from the current selection; is called when selection is changed or modified
+ */
+void
+VPDrag::updateDraggers ()
+{
+ /***
+ while (selected) {
+ selected = g_list_remove(selected, selected->data);
+ }
+ ***/
+ // delete old draggers
+ for (GList const* i = this->draggers; i != NULL; i = i->next) {
+ delete ((VPDragger *) i->data);
+ }
+ g_list_free (this->draggers);
+ this->draggers = NULL;
+
+ g_return_if_fail (this->selection != NULL);
+
+ for (GSList const* i = this->selection->itemList(); i != NULL; i = i->next) {
+ SPItem *item = SP_ITEM(i->data);
+ //SPStyle *style = SP_OBJECT_STYLE (item);
+
+ if (!SP_IS_3DBOX (item)) continue;
+ SP3DBox *box = SP_3DBOX (item);
+
+ // FIXME: Get the VPs from the selection!!!!
+ //addDragger (Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::X));
+ //addDragger (Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::Y));
+ //addDragger (Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::Z));
+
+ //Box3D::Perspective3D *persp = box->perspective;
+ Box3D::Perspective3D *persp = Box3D::get_persp_of_box (box);
+ addDragger (persp->get_vanishing_point(Box3D::X));
+ addDragger (persp->get_vanishing_point(Box3D::Y));
+ addDragger (persp->get_vanishing_point(Box3D::Z));
+ }
+}
+
+/**
+ * If there already exists a dragger within MERGE_DIST of p, add the VP to it;
+ * otherwise create new dragger and add it to draggers list
+ */
+void
+VPDrag::addDragger (VanishingPoint *vp)
+{
+ if (vp == NULL) {
+ g_print ("Warning: The VP in addDragger is already NULL. Aborting.\n)");
+ g_assert (vp != NULL);
+ }
+ NR::Point p = vp->get_pos();
+
+ for (GList *i = this->draggers; i != NULL; i = i->next) {
+ VPDragger *dragger = (VPDragger *) i->data;
+ if (NR::L2 (dragger->point - p) < MERGE_DIST) {
+ // distance is small, merge this draggable into dragger, no need to create new dragger
+ dragger->addVP (vp);
+ //dragger->updateKnotShape();
+ return;
+ }
+ }
+
+ VPDragger *new_dragger = new VPDragger(this, p, vp);
+ // fixme: draggers should be added AFTER the last one: this way tabbing through them will be from begin to end.
+ this->draggers = g_list_append (this->draggers, new_dragger);
+}
+
} // namespace Box3D
/*
diff --git a/src/vanishing-point.h b/src/vanishing-point.h
index 918b27fc76876c79bc20bec4507af2d2d18c0b92..58b3b142727c8fd93b8f1b8b28d8547e5879e818 100644 (file)
--- a/src/vanishing-point.h
+++ b/src/vanishing-point.h
#define SEEN_VANISHING_POINT_H
#include "libnr/nr-point.h"
+#include "knot.h"
+#include "selection.h"
#include "axis-manip.h"
#include "line-geometry.h" // TODO: Remove this include as soon as we don't need create_canvas_(point|line) any more.
VanishingPoint(NR::Coord x, NR::Coord y, VPState const state);
VanishingPoint(NR::Coord x, NR::Coord y, NR::Coord dir_x, NR::Coord dir_y);
VanishingPoint(VanishingPoint const &rhs);
+ ~VanishingPoint();
bool operator== (VanishingPoint const &other);
private:
};
+class VPDrag;
+
+struct VPDragger {
+public:
+ VPDragger(VPDrag *parent, NR::Point p, VanishingPoint *vp);
+ ~VPDragger();
+
+ VPDrag *parent;
+ SPKnot *knot;
+
+ // position of the knot, desktop coords
+ NR::Point point;
+ // position of the knot before it began to drag; updated when released
+ NR::Point point_original;
+
+ GSList *vps; // the list of vanishing points
+
+ void addVP(VanishingPoint *vp);
+ void removeVP(VanishingPoint *vp);
+
+ void reshapeBoxes(NR::Point const &p, Box3D::Axis axes);
+ void updateBoxReprs();
+};
+
+struct VPDrag {
+public:
+ VPDrag(SPDesktop *desktop);
+ ~VPDrag();
+
+ VPDragger *getDraggerFor (VanishingPoint const &vp);
+
+ //void grabKnot (VanishingPoint const &vp, gint x, gint y, guint32 etime);
+
+ bool local_change;
+
+ SPDesktop *desktop;
+ GList *draggers;
+ //GSList *lines;
+
+ void updateDraggers ();
+ //void updateLines ();
+
+private:
+ //void deselect_all();
+
+ //void addLine (NR::Point p1, NR::Point p2, guint32 rgba);
+ void addDragger (VanishingPoint *vp);
+
+ Inkscape::Selection *selection;
+ sigc::connection sel_changed_connection;
+ sigc::connection sel_modified_connection;
+};
} // namespace Box3D