From d81a973b81c26fcef48f46fc665eef88d386af07 Mon Sep 17 00:00:00 2001 From: cilix42 Date: Mon, 6 Aug 2007 00:07:25 +0000 Subject: [PATCH] Store a global list of existing perspectives; for each perspective hold a list of associated boxes; explicitly pass perspectives as arguments when creating PLs --- src/box3d-context.cpp | 26 ++++---------- src/box3d-context.h | 2 -- src/box3d-face.cpp | 14 ++++---- src/box3d.cpp | 64 ++++++++++++++++++++--------------- src/desktop.cpp | 45 +++++++++++++++++++++++++ src/desktop.h | 8 +++++ src/perspective-line.h | 3 +- src/perspective3d.cpp | 75 ++++++++++++++++++++++++++++++++++------- src/perspective3d.h | 18 ++++++++-- src/widgets/toolbox.cpp | 16 ++++----- 10 files changed, 190 insertions(+), 81 deletions(-) diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp index d5d367d81..25f6f78f1 100644 --- a/src/box3d-context.cpp +++ b/src/box3d-context.cpp @@ -90,7 +90,7 @@ static void sp_3dbox_context_class_init(SP3DBoxContextClass *klass) event_context_class->item_handler = sp_3dbox_context_item_handler; } -Box3D::Perspective3D * SP3DBoxContext::current_perspective = NULL; +Box3D::Perspective3D * Box3D::Perspective3D::current_perspective = NULL; guint SP3DBoxContext::number_of_handles = 3; static void sp_3dbox_context_init(SP3DBoxContext *box3d_context) @@ -116,20 +116,6 @@ static void sp_3dbox_context_init(SP3DBoxContext *box3d_context) 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)); - } new (&box3d_context->sel_changed_connection) sigc::connection(); } @@ -371,18 +357,18 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven // 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); + rc->drag_ptC = Box3D::perspective_line_snap (rc->drag_ptB, Box3D::Z, motion_dt, Box3D::Perspective3D::current_perspective); } else { rc->drag_ptC = motion_dt; } rc->drag_ptC = m.freeSnap(Inkscape::Snapper::SNAPPOINT_BBOX | Inkscape::Snapper::SNAPPOINT_NODE, 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); + Box3D::PerspectiveLine pl1 (NR::Point (event_context->xp, event_context->yp), Box3D::Y, Box3D::Perspective3D::current_perspective); + Box3D::PerspectiveLine pl2 (rc->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); + Box3D::PerspectiveLine pl3 (corner1, Box3D::X, Box3D::Perspective3D::current_perspective); + Box3D::PerspectiveLine pl4 (rc->drag_ptC, Box3D::Z, Box3D::Perspective3D::current_perspective); rc->drag_ptB = pl3.meet(pl4); } } diff --git a/src/box3d-context.h b/src/box3d-context.h index c244699b4..763c152ae 100644 --- a/src/box3d-context.h +++ b/src/box3d-context.h @@ -54,8 +54,6 @@ struct SP3DBoxContext : public SPEventContext { /* temporary member until the precise behaviour is sorted out */ static guint number_of_handles; - static Box3D::Perspective3D *current_perspective; - sigc::connection sel_changed_connection; Inkscape::MessageContext *_message_context; diff --git a/src/box3d-face.cpp b/src/box3d-face.cpp index 287e5e205..55dc9b60a 100644 --- a/src/box3d-face.cpp +++ b/src/box3d-face.cpp @@ -64,11 +64,11 @@ void Box3DFace::set_shape(NR::Point const ul, NR::Point const lr, } else { if (align_along_PL) { Box3D::Axis dir3 = Box3D::third_axis_direction (dir1, dir2); - Box3D::Line line1(*SP3DBoxContext::current_perspective->get_vanishing_point(dir1), lr); - Box3D::Line line2(*pt_align, *SP3DBoxContext::current_perspective->get_vanishing_point(dir3)); + Box3D::Line line1(*Box3D::Perspective3D::current_perspective->get_vanishing_point(dir1), lr); + Box3D::Line line2(*pt_align, *Box3D::Perspective3D::current_perspective->get_vanishing_point(dir3)); corners[2] = *line1.intersect(line2); } else { - corners[2] = Box3D::Line(*pt_align, *SP3DBoxContext::current_perspective->get_vanishing_point(dir1)).closest_to(lr); + corners[2] = Box3D::Line(*pt_align, *Box3D::Perspective3D::current_perspective->get_vanishing_point(dir1)).closest_to(lr); } } @@ -130,12 +130,12 @@ Box3DFace::set_face (NR::Point const A, NR::Point const C, Box3D::Axis const axi return; SP3DBoxContext *bc = SP_3DBOX_CONTEXT(inkscape_active_event_context()); - Box3D::PerspectiveLine line1 (A, axis1); - Box3D::PerspectiveLine line2 (C, axis2); + Box3D::PerspectiveLine line1 (A, axis1, Box3D::Perspective3D::current_perspective); + Box3D::PerspectiveLine line2 (C, axis2, Box3D::Perspective3D::current_perspective); NR::Maybe B = line1.intersect(line2); - Box3D::PerspectiveLine line3 (*corners[0], axis2); - Box3D::PerspectiveLine line4 (*corners[2], axis1); + Box3D::PerspectiveLine line3 (*corners[0], axis2, Box3D::Perspective3D::current_perspective); + Box3D::PerspectiveLine line4 (*corners[2], axis1, Box3D::Perspective3D::current_perspective); NR::Maybe D = line3.intersect(line4); // FIXME: How to handle the case if one of the intersections doesn't exist? diff --git a/src/box3d.cpp b/src/box3d.cpp index dec5e9d17..76dad605b 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -24,7 +24,7 @@ static void sp_3dbox_class_init(SP3DBoxClass *klass); static void sp_3dbox_init(SP3DBox *box3d); static void sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); -//static void sp_3dbox_release (SPObject *object); +static void sp_3dbox_release (SPObject *object); static void sp_3dbox_set(SPObject *object, unsigned int key, const gchar *value); static void sp_3dbox_update(SPObject *object, SPCtx *ctx, guint flags); static Inkscape::XML::Node *sp_3dbox_write(SPObject *object, Inkscape::XML::Node *repr, guint flags); @@ -76,7 +76,7 @@ sp_3dbox_class_init(SP3DBoxClass *klass) sp_object_class->set = sp_3dbox_set; sp_object_class->write = sp_3dbox_write; sp_object_class->update = sp_3dbox_update; - //sp_object_class->release = sp_3dbox_release; + sp_object_class->release = sp_3dbox_release; item_class->description = sp_3dbox_description; } @@ -97,6 +97,8 @@ sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr SP3DBox *box = SP_3DBOX (object); + Box3D::Perspective3D::current_perspective->add_box (box); + sp_object_read_attr(object, "inkscape:box3dcornerA"); sp_object_read_attr(object, "inkscape:box3dcornerB"); sp_object_read_attr(object, "inkscape:box3dcornerC"); @@ -127,22 +129,24 @@ sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr sp_3dbox_link_to_existing_paths (box, repr); } -/* static void sp_3dbox_release (SPObject *object) { - SP3DBox *box3d = SP_3DBOX(object); + SP3DBox *box = SP_3DBOX(object); for (int i = 0; i < 6; ++i) { - if (box3d->faces[i]) { - delete box3d->faces[i]; // FIXME: Anything else to do? Do we need to clean up the face first? + if (box->faces[i]) { + delete box->faces[i]; // FIXME: Anything else to do? Do we need to clean up the face first? } } + // FIXME: We do not duplicate perspectives if they are the same for several boxes. + // Thus, don't delete the perspective when deleting a box but rather unlink the box from it. + Box3D::get_persp_of_box (box)->remove_box (box); + if (((SPObjectClass *) parent_class)->release) { ((SPObjectClass *) parent_class)->release (object); } } -*/ static void sp_3dbox_set(SPObject *object, unsigned int key, const gchar *value) { @@ -334,35 +338,37 @@ sp_3dbox_link_to_existing_paths (SP3DBox *box, Inkscape::XML::Node *repr) { void sp_3dbox_move_corner_in_XY_plane (SP3DBox *box, guint id, NR::Point pt, Box3D::Axis axes) { + Box3D::Perspective3D * persp = Box3D::get_persp_of_box (box); + NR::Point A (box->corners[id ^ Box3D::XY]); if (Box3D::is_single_axis_direction (axes)) { - pt = Box3D::PerspectiveLine (box->corners[id], axes).closest_to(pt); + pt = Box3D::PerspectiveLine (box->corners[id], axes, persp).closest_to(pt); } /* set the 'front' corners */ box->corners[id] = pt; - Box3D::PerspectiveLine pl_one (A, Box3D::Y); - Box3D::PerspectiveLine pl_two (pt, Box3D::X); + Box3D::PerspectiveLine pl_one (A, Box3D::Y, persp); + Box3D::PerspectiveLine pl_two (pt, Box3D::X, persp); box->corners[id ^ Box3D::X] = pl_one.meet(pl_two); - pl_one = Box3D::PerspectiveLine (A, Box3D::X); - pl_two = Box3D::PerspectiveLine (pt, Box3D::Y); + pl_one = Box3D::PerspectiveLine (A, Box3D::X, persp); + pl_two = Box3D::PerspectiveLine (pt, Box3D::Y, persp); box->corners[id ^ Box3D::Y] = pl_one.meet(pl_two); /* set the 'rear' corners */ NR::Point B (box->corners[id ^ Box3D::XYZ]); - pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::X], Box3D::Z); - pl_two = Box3D::PerspectiveLine (B, Box3D::Y); + pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::X], Box3D::Z, persp); + pl_two = Box3D::PerspectiveLine (B, Box3D::Y, persp); box->corners[id ^ Box3D::XZ] = pl_one.meet(pl_two); - pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::XZ], Box3D::X); - pl_two = Box3D::PerspectiveLine (pt, Box3D::Z); + pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::XZ], Box3D::X, persp); + pl_two = Box3D::PerspectiveLine (pt, Box3D::Z, persp); box->corners[id ^ Box3D::Z] = pl_one.meet(pl_two); - pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::Z], Box3D::Y); - pl_two = Box3D::PerspectiveLine (B, Box3D::X); + pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::Z], Box3D::Y, persp); + pl_two = Box3D::PerspectiveLine (B, Box3D::X, persp); box->corners[id ^ Box3D::YZ] = pl_one.meet(pl_two); } @@ -372,19 +378,21 @@ sp_3dbox_move_corner_in_Z_direction (SP3DBox *box, guint id, NR::Point pt, bool { if (!constrained) sp_3dbox_move_corner_in_XY_plane (box, id, pt, Box3D::XY); + Box3D::Perspective3D * persp = Box3D::get_persp_of_box (box); + /* set the four corners of the face containing corners[id] */ - box->corners[id] = Box3D::PerspectiveLine (box->corners[id], Box3D::Z).closest_to(pt); + box->corners[id] = Box3D::PerspectiveLine (box->corners[id], Box3D::Z, persp).closest_to(pt); - Box3D::PerspectiveLine pl_one (box->corners[id], Box3D::X); - Box3D::PerspectiveLine pl_two (box->corners[id ^ Box3D::XZ], Box3D::Z); + Box3D::PerspectiveLine pl_one (box->corners[id], Box3D::X, persp); + Box3D::PerspectiveLine pl_two (box->corners[id ^ Box3D::XZ], Box3D::Z, persp); box->corners[id ^ Box3D::X] = pl_one.meet(pl_two); - pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::X], Box3D::Y); - pl_two = Box3D::PerspectiveLine (box->corners[id ^ Box3D::XYZ], Box3D::Z); + pl_one = Box3D::PerspectiveLine (box->corners[id ^ Box3D::X], Box3D::Y, persp); + pl_two = Box3D::PerspectiveLine (box->corners[id ^ Box3D::XYZ], Box3D::Z, persp); box->corners[id ^ Box3D::XY] = pl_one.meet(pl_two); - pl_one = Box3D::PerspectiveLine (box->corners[id], Box3D::Y); - pl_two = Box3D::PerspectiveLine (box->corners[id ^ Box3D::YZ], Box3D::Z); + pl_one = Box3D::PerspectiveLine (box->corners[id], Box3D::Y, persp); + pl_two = Box3D::PerspectiveLine (box->corners[id ^ Box3D::YZ], Box3D::Z, persp); box->corners[id ^ Box3D::Y] = pl_one.meet(pl_two); } @@ -409,8 +417,10 @@ sp_3dbox_get_midpoint_between_corners (SP3DBox *box, guint id_corner1, guint id_ if (!adjacent_face_center) return NR::Nothing(); - Box3D::PerspectiveLine pl (*adjacent_face_center, orth_dir); - return pl.intersect(Box3D::PerspectiveLine(box->corners[id_corner1], corner_axes)); + Box3D::Perspective3D * persp = Box3D::get_persp_of_box (box); + + Box3D::PerspectiveLine pl (*adjacent_face_center, orth_dir, persp); + return pl.intersect(Box3D::PerspectiveLine(box->corners[id_corner1], corner_axes, persp)); } else { Box3D::Axis dir = Box3D::extract_first_axis_direction (corner_axes); Box3D::Line diag1 (box->corners[id_corner1], box->corners[id_corner2]); diff --git a/src/desktop.cpp b/src/desktop.cpp index e785aab6d..6314621c1 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -132,6 +132,7 @@ SPDesktop::SPDesktop() : window_state(0), interaction_disabled_counter( 0 ), waiting_cursor( false ), + perspectives (NULL), guides_active( false ), gr_item( 0 ), gr_point_type( 0 ), @@ -309,6 +310,21 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) layer_manager = new Inkscape::LayerManager( this ); grids_visible = true; + + /* Create initial perspective, append it to the list of existing perspectives + and make it the current perspective */ + Box3D::Perspective3D *initial_persp = new Box3D::Perspective3D ( + // VP in x-direction + Box3D::VanishingPoint( NR::Point(-50.0, 600.0), + NR::Point( -1.0, 0.0), Box3D::VP_FINITE), + // 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, 600.0), + NR::Point(sqrt(3.0),1.0), Box3D::VP_FINITE)); + this->add_perspective (initial_persp); + Box3D::Perspective3D::current_perspective = (Box3D::Perspective3D *) perspectives->data; } @@ -352,6 +368,11 @@ void SPDesktop::destroy() g_list_free (zooms_past); g_list_free (zooms_future); + + for (GSList *p = this->perspectives; p != NULL; p = p->next) { + delete ((Box3D::Perspective3D *) p->data); + } + g_slist_free (perspectives); } SPDesktop::~SPDesktop() {} @@ -693,6 +714,30 @@ void SPDesktop::set_display_area(NR::Rect const &a, NR::Coord b, bool log) set_display_area(a.min()[NR::X], a.min()[NR::Y], a.max()[NR::X], a.max()[NR::Y], b, log); } +/** + * Add a perspective to the desktop if it doesn't exist yet + */ +void +SPDesktop::add_perspective (Box3D::Perspective3D * const persp) +{ + // FIXME: Should we handle the case that the perspectives have equal VPs but are not identical? + if (persp == NULL || g_slist_find (this->perspectives, persp)) return; + this->perspectives = g_slist_prepend (this->perspectives, persp); + persp->desktop = this; +} + +void SPDesktop::remove_perspective (Box3D::Perspective3D * const persp) +{ + if (persp == NULL) return; + + if (!g_slist_find (this->perspectives, persp)) { + g_warning ("Could not find perspective in current desktop. Not removed.\n"); + return; + } + + this->perspectives = g_slist_remove (this->perspectives, persp); +} + /** * Return viewbox dimensions. */ diff --git a/src/desktop.h b/src/desktop.h index ca2d24204..fa6602651 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -34,6 +34,7 @@ #include "libnr/nr-rect.h" #include "ui/view/view.h" #include "ui/view/edit-widget-interface.h" +#include "perspective3d.h" class NRRect; class SPCSSAttr; @@ -112,6 +113,9 @@ struct SPDesktop : public Inkscape::UI::View::View unsigned int interaction_disabled_counter; bool waiting_cursor; + // All 3D perspectives that are present in the current desktop + GSList *perspectives; + /// \todo fixme: This has to be implemented in different way */ guint guides_active : 1; @@ -202,6 +206,10 @@ struct SPDesktop : public Inkscape::UI::View::View SPItem *group_at_point (NR::Point const p) const; NR::Point point() const; + // Methods to handle 3D perspective + void add_perspective (Box3D::Perspective3D * const persp); + void remove_perspective (Box3D::Perspective3D * const persp); + NR::Rect get_display_area() const; void set_display_area (double x0, double y0, double x1, double y1, double border, bool log = true); void set_display_area(NR::Rect const &a, NR::Coord border, bool log = true); diff --git a/src/perspective-line.h b/src/perspective-line.h index a02737692..8f218803b 100644 --- a/src/perspective-line.h +++ b/src/perspective-line.h @@ -27,8 +27,7 @@ public: * PL runs through it; otherwise it has the direction specified by the v_dir vector * of the VP. */ - PerspectiveLine (NR::Point const &pt, Box3D::Axis const axis, - Perspective3D *perspective = SP3DBoxContext::current_perspective); + PerspectiveLine (NR::Point const &pt, Box3D::Axis const axis, Perspective3D *perspective); NR::Maybe intersect (Line const &line); // FIXME: Can we make this return only a NR::Point to remove the extra method meet()? NR::Point meet (Line const &line); diff --git a/src/perspective3d.cpp b/src/perspective3d.cpp index 35558e832..2c9a5e61e 100644 --- a/src/perspective3d.cpp +++ b/src/perspective3d.cpp @@ -14,18 +14,35 @@ #include "box3d-context.h" #include "perspective-line.h" #include +#include "desktop.h" + +// can probably be removed later +#include "inkscape.h" namespace Box3D { +Perspective3D * +get_persp_of_box (const SP3DBox *box) +{ + SPDesktop *desktop = inkscape_active_desktop(); // Should we pass the desktop as an argument? + for (GSList *p = desktop->perspectives; p != NULL; p = p->next) { + if (((Perspective3D *) p->data)->has_box (box)) + return (Perspective3D *) p->data; + } + g_warning ("Stray 3D box!\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. */ // FIXME: This has been moved to a virtual method inside PerspectiveLine; can probably be purged -NR::Point perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point pt2, Box3D::Axis dir2) +NR::Point +perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point pt2, Box3D::Axis dir2, Perspective3D *persp) { - VanishingPoint const *vp1 = SP3DBoxContext::current_perspective->get_vanishing_point(dir1); - VanishingPoint const *vp2 = SP3DBoxContext::current_perspective->get_vanishing_point(dir2); + VanishingPoint const *vp1 = persp->get_vanishing_point(dir1); + VanishingPoint const *vp2 = persp->get_vanishing_point(dir2); NR::Maybe meet = Line(pt1, *vp1).intersect(Line(pt2, *vp2)); // FIXME: How to handle parallel lines (also depends on the type of the VPs)? if (!meet) { meet = NR::Point (0.0, 0.0); } @@ -36,22 +53,30 @@ NR::Point perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point p * Find the point on the perspective line from line_pt to the * vanishing point in direction dir that is closest to ext_pt. */ -NR::Point perspective_line_snap (NR::Point line_pt, Box3D::Axis dir, NR::Point ext_pt) +NR::Point +perspective_line_snap (NR::Point line_pt, Box3D::Axis dir, NR::Point ext_pt, Perspective3D *persp) { - return PerspectiveLine(line_pt, dir).closest_to(ext_pt); + return PerspectiveLine(line_pt, dir, persp).closest_to(ext_pt); } Perspective3D::Perspective3D (VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z) - : vp_x (pt_x), - vp_y (pt_y), - vp_z (pt_z) + : desktop (NULL), + vp_x (pt_x), + vp_y (pt_y), + vp_z (pt_z), + boxes (NULL) { - // Draw the three vanishing points - vp_x.draw(X); - vp_y.draw(Y); - vp_z.draw(Z); } +Perspective3D::~Perspective3D () +{ + g_assert (desktop != NULL); + desktop->remove_perspective (this); + + g_slist_free (boxes); +} + + VanishingPoint *Perspective3D::get_vanishing_point (Box3D::Axis const dir) { // FIXME: Also handle value 'NONE' in switch @@ -86,6 +111,32 @@ void Perspective3D::set_vanishing_point (Box3D::Axis const dir, VanishingPoint c } } +void +Perspective3D::add_box (SP3DBox *box) +{ + if (g_slist_find (this->boxes, box) != NULL) { + // Don't add the same box twice + g_warning ("Box already uses the current perspective. We don't add it again.\n"); + return; + } + this->boxes = g_slist_append (this->boxes, box); +} + +void +Perspective3D::remove_box (const SP3DBox *box) +{ + if (!g_slist_find (this->boxes, box)) { + g_warning ("Could not find box that is to be removed in the current perspective.\n"); + } + this->boxes = g_slist_remove (this->boxes, box); +} + +bool +Perspective3D::has_box (const SP3DBox *box) +{ + return (g_slist_find (this->boxes, box) != NULL); +} + } // namespace Box3D /* diff --git a/src/perspective3d.h b/src/perspective3d.h index 007b02df1..fa9eda65f 100644 --- a/src/perspective3d.h +++ b/src/perspective3d.h @@ -14,26 +14,38 @@ #include "vanishing-point.h" -namespace Box3D { +class SP3DBox; -NR::Point perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point pt2, Box3D::Axis dir2); -NR::Point perspective_line_snap (NR::Point pt, Box3D::Axis dir, NR::Point ext_pt); +namespace Box3D { class PerspectiveLine; class Perspective3D { public: Perspective3D(VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z); + ~Perspective3D(); VanishingPoint *get_vanishing_point (Box3D::Axis const dir); void set_vanishing_point (Box3D::Axis const dir, VanishingPoint const &pt); + void add_box (SP3DBox *box); + void remove_box (const SP3DBox *box); + bool has_box (const SP3DBox *box); + + static Perspective3D * current_perspective; // should current_perspective be moved to desktop.h? + + SPDesktop * desktop; // we need to store the perspective's desktop to be able to access it in the destructor private: VanishingPoint vp_x; VanishingPoint vp_y; VanishingPoint vp_z; + GSList * boxes; // holds a list of boxes sharing this specific perspective }; +Perspective3D * get_persp_of_box (const SP3DBox *box); + +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); } // namespace Box3D diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index aeab3b45b..8acb08a12 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -2133,8 +2133,8 @@ static void sp_3dbox_toggle_vp_changed( GtkToggleAction *act, gpointer data ) break; } - if (SP3DBoxContext::current_perspective) { - Box3D::VanishingPoint *vp = SP3DBoxContext::current_perspective->get_vanishing_point(axis); + if (Box3D::Perspective3D::current_perspective) { + Box3D::VanishingPoint *vp = Box3D::Perspective3D::current_perspective->get_vanishing_point(axis); vp->toggle_parallel(); vp->draw(axis); prefs_set_int_attribute( "tools.shapes.3dbox", pstring->str, vp->is_finite() ? 0 : 1); @@ -2208,8 +2208,8 @@ static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::X)); - if (SP3DBoxContext::current_perspective) { - toggled = SP3DBoxContext::current_perspective->get_vanishing_point(Box3D::X)->is_finite(); + if (Box3D::Perspective3D::current_perspective) { + toggled = !Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::X)->is_finite(); } gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled ); } @@ -2223,8 +2223,8 @@ static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::Y)); - if (SP3DBoxContext::current_perspective) { - toggled = SP3DBoxContext::current_perspective->get_vanishing_point(Box3D::Y)->is_finite(); + if (Box3D::Perspective3D::current_perspective) { + toggled = !Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::Y)->is_finite(); } gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled ); } @@ -2238,8 +2238,8 @@ static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction Inkscape::ICON_SIZE_DECORATION ); gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_3dbox_toggle_vp_changed), GINT_TO_POINTER(Box3D::Z)); - if (SP3DBoxContext::current_perspective) { - toggled = SP3DBoxContext::current_perspective->get_vanishing_point(Box3D::Z)->is_finite(); + if (Box3D::Perspective3D::current_perspective) { + toggled = !Box3D::Perspective3D::current_perspective->get_vanishing_point(Box3D::Z)->is_finite(); } gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled ); } -- 2.30.2