diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp
index 0bcf9ffa46ccbbaaca3558fa189985b057778674..0ef2277ea0a638e50c8729aa588112dfc69ba405 100644 (file)
--- a/src/box3d-context.cpp
+++ b/src/box3d-context.cpp
static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEvent *event);
static gint sp_3dbox_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEvent *event);
-static void sp_3dbox_drag(SP3DBoxContext &rc, guint state);
-static void sp_3dbox_finish(SP3DBoxContext *rc);
+static void sp_3dbox_drag(SP3DBoxContext &bc, guint state);
+static void sp_3dbox_finish(SP3DBoxContext *bc);
static SPEventContextClass *parent_class;
event_context_class->item_handler = sp_3dbox_context_item_handler;
}
-Box3D::Perspective3D * SP3DBoxContext::current_perspective = NULL;
guint SP3DBoxContext::number_of_handles = 3;
static void sp_3dbox_context_init(SP3DBoxContext *box3d_context)
box3d_context->item = NULL;
- box3d_context->rx = 0.0;
- box3d_context->ry = 0.0;
-
box3d_context->ctrl_dragged = false;
box3d_context->extruded = false;
-
- /* create an initial perspective */
- if (!SP3DBoxContext::current_perspective) {
- SP3DBoxContext::current_perspective = new Box3D::Perspective3D (
- // VP in x-direction
- Box3D::VanishingPoint( NR::Point( 50.0, 600.0),
- NR::Point( -1.0, 0.0), Box3D::VP_INFINITE),
- // VP in y-direction
- Box3D::VanishingPoint( NR::Point(500.0,1000.0),
- NR::Point( 0.0, 1.0), Box3D::VP_INFINITE),
- // VP in z-direction
- Box3D::VanishingPoint( NR::Point(700.0, 500.0),
- NR::Point(sqrt(3.0),1.0), Box3D::VP_INFINITE));
- }
+ box3d_context->_vpdrag = NULL;
+
new (&box3d_context->sel_changed_connection) sigc::connection();
}
static void sp_3dbox_context_dispose(GObject *object)
{
- SP3DBoxContext *rc = SP_3DBOX_CONTEXT(object);
+ SP3DBoxContext *bc = SP_3DBOX_CONTEXT(object);
SPEventContext *ec = SP_EVENT_CONTEXT(object);
ec->enableGrDrag(false);
- rc->sel_changed_connection.disconnect();
- rc->sel_changed_connection.~connection();
+ delete (bc->_vpdrag);
+ bc->_vpdrag = NULL;
+
+ bc->sel_changed_connection.disconnect();
+ bc->sel_changed_connection.~connection();
/* fixme: This is necessary because we do not grab */
- if (rc->item) {
- sp_3dbox_finish(rc);
+ if (bc->item) {
+ sp_3dbox_finish(bc);
}
if (ec->shape_knot_holder) {
ec->shape_repr = 0;
}
- if (rc->_message_context) {
- delete rc->_message_context;
+ if (bc->_message_context) {
+ delete bc->_message_context;
}
G_OBJECT_CLASS(parent_class)->dispose(object);
*/
void sp_3dbox_context_selection_changed(Inkscape::Selection *selection, gpointer data)
{
- SP3DBoxContext *rc = SP_3DBOX_CONTEXT(data);
- SPEventContext *ec = SP_EVENT_CONTEXT(rc);
+ SP3DBoxContext *bc = SP_3DBOX_CONTEXT(data);
+ SPEventContext *ec = SP_EVENT_CONTEXT(bc);
if (ec->shape_knot_holder) { // destroy knotholder
sp_knot_holder_destroy(ec->shape_knot_holder);
@@ -203,21 +190,29 @@ void sp_3dbox_context_selection_changed(Inkscape::Selection *selection, gpointer
ec->shape_repr = shape_repr;
Inkscape::GC::anchor(shape_repr);
sp_repr_add_listener(shape_repr, &ec_shape_repr_events, ec);
-
- // FIXME: The following really belongs in sp_3dbox_build. But when undoing & redoing the
- // creation of a 3D box, we have no means of accessing the recreated paths, which
- // seem to be built after the box itself. Thus we need to check for untracked paths
- // here and hook them to the box if the latter was created by a redo operation.
- if (SP_IS_3DBOX(item)) {
- sp_3dbox_link_to_existing_paths (SP_3DBOX(item), shape_repr);
+ }
+ if (SP_IS_3DBOX (item)) {
+ Box3D::Perspective3D::current_perspective = Box3D::get_persp_of_box (SP_3DBOX (item));
+ }
+ } else {
+ /* If several boxes sharing the same perspective are selected,
+ we can still set the current selection accordingly */
+ std::set<Box3D::Perspective3D *> perspectives;
+ for (GSList *i = (GSList *) selection->itemList(); i != NULL; i = i->next) {
+ if (SP_IS_3DBOX (i->data)) {
+ perspectives.insert (Box3D::get_persp_of_box (SP_3DBOX (i->data)));
}
}
+ if (perspectives.size() == 1) {
+ Box3D::Perspective3D::current_perspective = *(perspectives.begin());
+ }
+ // TODO: What to do if several boxes with different perspectives are selected?
}
}
static void sp_3dbox_context_setup(SPEventContext *ec)
{
- SP3DBoxContext *rc = SP_3DBOX_CONTEXT(ec);
+ SP3DBoxContext *bc = SP_3DBOX_CONTEXT(ec);
if (((SPEventContextClass *) parent_class)->setup) {
((SPEventContextClass *) parent_class)->setup(ec);
}
}
- rc->sel_changed_connection.disconnect();
- rc->sel_changed_connection = sp_desktop_selection(ec->desktop)->connectChanged(
- sigc::bind(sigc::ptr_fun(&sp_3dbox_context_selection_changed), (gpointer)rc)
+ bc->sel_changed_connection.disconnect();
+ bc->sel_changed_connection = sp_desktop_selection(ec->desktop)->connectChanged(
+ sigc::bind(sigc::ptr_fun(&sp_3dbox_context_selection_changed), (gpointer)bc)
);
- sp_event_context_read(ec, "rx");
- sp_event_context_read(ec, "ry");
+ bc->_vpdrag = new Box3D::VPDrag(ec->desktop);
if (prefs_get_int_attribute("tools.shapes", "selcue", 0) != 0) {
ec->enableSelectionCue();
ec->enableGrDrag();
}
- rc->_message_context = new Inkscape::MessageContext((ec->desktop)->messageStack());
+ bc->_message_context = new Inkscape::MessageContext((ec->desktop)->messageStack());
}
static void sp_3dbox_context_set(SPEventContext *ec, gchar const *key, gchar const *val)
{
- SP3DBoxContext *rc = SP_3DBOX_CONTEXT(ec);
+ //SP3DBoxContext *bc = SP_3DBOX_CONTEXT(ec);
/* fixme: Proper error handling for non-numeric data. Use a locale-independent function like
* g_ascii_strtod (or a thin wrapper that does the right thing for invalid values inf/nan). */
+ /**
if ( strcmp(key, "rx") == 0 ) {
- rc->rx = ( val
+ bc->rx = ( val
? g_ascii_strtod (val, NULL)
: 0.0 );
} else if ( strcmp(key, "ry") == 0 ) {
- rc->ry = ( val
+ bc->ry = ( val
? g_ascii_strtod (val, NULL)
: 0.0 );
}
+ **/
}
static gint sp_3dbox_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEvent *event)
switch (event->type) {
case GDK_BUTTON_PRESS:
- if ( event->button.button == 1 ) {
+ if ( event->button.button == 1 && !event_context->space_panning) {
Inkscape::setup_for_drag_start(desktop, event_context, event);
ret = TRUE;
}
@@ -302,14 +298,14 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven
SPDesktop *desktop = event_context->desktop;
Inkscape::Selection *selection = sp_desktop_selection (desktop);
- SP3DBoxContext *rc = SP_3DBOX_CONTEXT(event_context);
+ SP3DBoxContext *bc = SP_3DBOX_CONTEXT(event_context);
event_context->tolerance = prefs_get_int_attribute_limited("options.dragtolerance", "value", 0, 0, 100);
gint ret = FALSE;
switch (event->type) {
case GDK_BUTTON_PRESS:
- if ( event->button.button == 1 ) {
+ if ( event->button.button == 1 && !event_context->space_panning) {
NR::Point const button_w(event->button.x,
event->button.y);
@@ -325,14 +321,14 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven
/* Position center */
NR::Point const button_dt(desktop->w2d(button_w));
- rc->drag_origin = button_dt;
- rc->drag_ptB = button_dt;
- rc->drag_ptC = button_dt;
+ bc->drag_origin = button_dt;
+ bc->drag_ptB = button_dt;
+ bc->drag_ptC = button_dt;
/* Snap center */
SnapManager const &m = desktop->namedview->snap_manager;
- rc->center = m.freeSnap(Inkscape::Snapper::SNAP_POINT | Inkscape::Snapper::BBOX_POINT,
- button_dt, rc->item).getPoint();
+ bc->center = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE,
+ button_dt, bc->item).getPoint();
sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
( GDK_KEY_PRESS_MASK |
@@ -345,7 +341,7 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven
break;
case GDK_MOTION_NOTIFY:
if ( dragging
- && ( event->motion.state & GDK_BUTTON1_MASK ) )
+ && ( event->motion.state & GDK_BUTTON1_MASK ) && !event_context->space_panning)
{
if ( event_context->within_tolerance
&& ( abs( (gint) event->motion.x - event_context->xp ) < event_context->tolerance )
@@ -362,53 +358,53 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven
NR::Point motion_dt(desktop->w2d(motion_w));
SnapManager const &m = desktop->namedview->snap_manager;
- motion_dt = m.freeSnap(Inkscape::Snapper::BBOX_POINT | Inkscape::Snapper::SNAP_POINT, motion_dt, rc->item).getPoint();
+ motion_dt = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, motion_dt, bc->item).getPoint();
- rc->ctrl_dragged = event->motion.state & GDK_CONTROL_MASK;
+ bc->ctrl_dragged = event->motion.state & GDK_CONTROL_MASK;
- if (event->motion.state & GDK_SHIFT_MASK && !rc->extruded) {
- /* once shift is pressed, set rc->extruded (no need to create further faces;
+ if (event->motion.state & GDK_SHIFT_MASK && !bc->extruded) {
+ /* once shift is pressed, set bc->extruded (no need to create further faces;
all of them are already created in sp_3dbox_init) */
- rc->extruded = true;
+ bc->extruded = true;
}
- if (!rc->extruded) {
- rc->drag_ptB = motion_dt;
- rc->drag_ptC = motion_dt;
+ if (!bc->extruded) {
+ bc->drag_ptB = motion_dt;
+ bc->drag_ptC = motion_dt;
} else {
// Without Ctrl, motion of the extruded corner is constrained to the
// perspective line from drag_ptB to vanishing point Y.
- if (!rc->ctrl_dragged) {
- rc->drag_ptC = Box3D::perspective_line_snap (rc->drag_ptB, Box3D::Z, motion_dt);
+ if (!bc->ctrl_dragged) {
+ bc->drag_ptC = Box3D::perspective_line_snap (bc->drag_ptB, Box3D::Z, motion_dt, Box3D::Perspective3D::current_perspective);
} else {
- rc->drag_ptC = motion_dt;
+ bc->drag_ptC = motion_dt;
}
- rc->drag_ptC = m.freeSnap(Inkscape::Snapper::BBOX_POINT | Inkscape::Snapper::SNAP_POINT, rc->drag_ptC, rc->item).getPoint();
- if (rc->ctrl_dragged) {
- Box3D::PerspectiveLine pl1 (NR::Point (event_context->xp, event_context->yp), Box3D::Y);
- Box3D::PerspectiveLine pl2 (rc->drag_ptB, Box3D::X);
+ bc->drag_ptC = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, bc->drag_ptC, bc->item).getPoint();
+ if (bc->ctrl_dragged) {
+ Box3D::PerspectiveLine pl1 (NR::Point (event_context->xp, event_context->yp), Box3D::Y, Box3D::Perspective3D::current_perspective);
+ Box3D::PerspectiveLine pl2 (bc->drag_ptB, Box3D::X, Box3D::Perspective3D::current_perspective);
NR::Point corner1 = pl1.meet(pl2);
- Box3D::PerspectiveLine pl3 (corner1, Box3D::X);
- Box3D::PerspectiveLine pl4 (rc->drag_ptC, Box3D::Z);
- rc->drag_ptB = pl3.meet(pl4);
+ Box3D::PerspectiveLine pl3 (corner1, Box3D::X, Box3D::Perspective3D::current_perspective);
+ Box3D::PerspectiveLine pl4 (bc->drag_ptC, Box3D::Z, Box3D::Perspective3D::current_perspective);
+ bc->drag_ptB = pl3.meet(pl4);
}
}
- sp_3dbox_drag(*rc, event->motion.state);
+ sp_3dbox_drag(*bc, event->motion.state);
ret = TRUE;
}
break;
case GDK_BUTTON_RELEASE:
event_context->xp = event_context->yp = 0;
- if ( event->button.button == 1 ) {
+ if ( event->button.button == 1 && !event_context->space_panning) {
dragging = false;
if (!event_context->within_tolerance) {
// we've been dragging, finish the box
- sp_3dbox_finish(rc);
+ sp_3dbox_finish(bc);
} else if (event_context->item_to_select) {
// no dragging, select clicked item if any
if (event->button.state & GDK_SHIFT_MASK) {
@@ -455,13 +451,72 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven
ret = TRUE;
break;
+ case GDK_I:
+ Box3D::Perspective3D::print_debugging_info();
+ ret = true;
+ break;
+
+ case GDK_L:
+ case GDK_l:
+ bc->_vpdrag->show_lines = !bc->_vpdrag->show_lines;
+ bc->_vpdrag->updateLines();
+ ret = true;
+ break;
+
+ case GDK_A:
+ case GDK_a:
+ if (MOD__CTRL) break; // Don't catch Ctrl+A ("select all")
+ if (bc->_vpdrag->show_lines) {
+ bc->_vpdrag->front_or_rear_lines = bc->_vpdrag->front_or_rear_lines ^ 0x2; // toggle rear PLs
+ }
+ bc->_vpdrag->updateLines();
+ ret = true;
+ break;
+
case GDK_x:
case GDK_X:
- if (MOD__ALT_ONLY) {
- // desktop->setToolboxFocusTo ("altx-rect");
- ret = TRUE;
+ {
+ if (MOD__CTRL) break; // Don't catch Ctrl+X ('cut') and Ctrl+Shift+X ('open XML editor')
+ // FIXME: Shouldn't we access _vpdrag->selection instead?
+ Inkscape::Selection *selection = sp_desktop_selection (bc->_vpdrag->desktop);
+ for (GSList const *i = selection->itemList(); i != NULL; i = i->next) {
+ if (!SP_IS_3DBOX (i->data)) continue;
+ sp_3dbox_switch_front_face (SP_3DBOX (i->data), Box3D::X);
+ }
+ bc->_vpdrag->updateLines();
+ ret = true;
+ break;
+ }
+
+ case GDK_y:
+ case GDK_Y:
+ {
+ if (MOD__CTRL) break; // Don't catch Ctrl+Y ("redo")
+ // FIXME: Shouldn't we access _vpdrag->selection instead?
+ Inkscape::Selection *selection = sp_desktop_selection (bc->_vpdrag->desktop);
+ for (GSList const *i = selection->itemList(); i != NULL; i = i->next) {
+ if (!SP_IS_3DBOX (i->data)) continue;
+ sp_3dbox_switch_front_face (SP_3DBOX (i->data), Box3D::Y);
}
+ bc->_vpdrag->updateLines();
+ ret = true;
break;
+ }
+
+ case GDK_z:
+ case GDK_Z:
+ {
+ if (MOD__CTRL) break; // Don't catch Ctrl+Z ("undo")
+ // FIXME: Shouldn't we access _vpdrag->selection instead?
+ Inkscape::Selection *selection = sp_desktop_selection (bc->_vpdrag->desktop);
+ for (GSList const *i = selection->itemList(); i != NULL; i = i->next) {
+ if (!SP_IS_3DBOX (i->data)) continue;
+ sp_3dbox_switch_front_face (SP_3DBOX (i->data), Box3D::Z);
+ }
+ bc->_vpdrag->updateLines();
+ ret = true;
+ break;
+ }
case GDK_Escape:
sp_desktop_selection(desktop)->clear();
@@ -475,7 +530,7 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven
dragging = false;
if (!event_context->within_tolerance) {
// we've been dragging, finish the box
- sp_3dbox_finish(rc);
+ sp_3dbox_finish(bc);
}
// do not return true, so that space would work switching to selector
}
}
bc.item->updateRepr();
+ sp_3dbox_set_z_orders (SP_3DBOX (bc.item));
+
+ // 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);
}
NR::Point origin_w(ec->xp, ec->yp);
NR::Point origin(desktop->w2d(origin_w));
sp_3dbox_position_set(bc);
+ sp_3dbox_set_z_orders (SP_3DBOX (bc.item));
// status text
//GString *Ax = SP_PX_TO_METRIC_STRING(origin[NR::X], desktop->namedview->getDefaultMetric());
//g_string_free(Ay, FALSE);
}
-static void sp_3dbox_finish(SP3DBoxContext *rc)
+static void sp_3dbox_finish(SP3DBoxContext *bc)
{
- rc->_message_context->clear();
+ bc->_message_context->clear();
- if ( rc->item != NULL ) {
+ if ( bc->item != NULL ) {
SPDesktop * desktop;
- desktop = SP_EVENT_CONTEXT_DESKTOP(rc);
+ desktop = SP_EVENT_CONTEXT_DESKTOP(bc);
- SP_OBJECT(rc->item)->updateRepr();
+ SP_OBJECT(bc->item)->updateRepr();
+ sp_3dbox_set_ratios(SP_3DBOX(bc->item));
sp_canvas_end_forced_full_redraws(desktop->canvas);
- sp_desktop_selection(desktop)->set(rc->item);
+ sp_desktop_selection(desktop)->set(bc->item);
sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX,
_("Create 3D box"));
- rc->item = NULL;
+ bc->item = NULL;
}
- rc->ctrl_dragged = false;
- rc->extruded = false;
+ bc->ctrl_dragged = false;
+ bc->extruded = false;
}
/*