From 725274d44aa54f0543dbd2397cdd68b8afd5d20a Mon Sep 17 00:00:00 2001 From: cilix42 Date: Tue, 3 Jul 2007 18:55:50 +0000 Subject: [PATCH] Only create the faces of a 3D box when needed (use pointers to refer to them). --- src/box3d-context.cpp | 24 +++++++++-------- src/box3d-face.cpp | 45 ++++++++++++++++++++++++++++++++ src/box3d-face.h | 1 + src/box3d.cpp | 60 +++++++++++++++++++++++++++++++------------ src/box3d.h | 2 +- 5 files changed, 105 insertions(+), 27 deletions(-) diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp index 35bdb6af2..1ec86b827 100644 --- a/src/box3d-context.cpp +++ b/src/box3d-context.cpp @@ -357,8 +357,18 @@ static gint sp_3dbox_context_root_handler(SPEventContext *event_context, GdkEven rc->ctrl_dragged = event->motion.state & GDK_CONTROL_MASK; - if (event->motion.state & GDK_SHIFT_MASK) - rc->extruded = true; // set rc->extruded once shift is pressed + if (event->motion.state & GDK_SHIFT_MASK && !rc->extruded) { + /* once shift is pressed, set rc->extruded and create the remaining faces */ + rc->extruded = true; + + /* The separate faces */ + SP3DBox *box3d = SP_3DBOX(rc->item); + for (int i = 0; i < 6; ++i) { + if (i == 4 || box3d->faces[i]) continue; + box3d->faces[i] = new Box3DFace (box3d); + box3d->faces[i]->hook_path_to_3dbox(); + } + } if (!rc->extruded) { rc->drag_ptB = motion_dt; @@ -522,14 +532,8 @@ static void sp_3dbox_drag(SP3DBoxContext &rc, guint state) Inkscape::GC::release(repr); rc.item->transform = SP_ITEM(desktop->currentRoot())->getRelativeTransform(desktop->currentLayer()); - /* The separate faces (created from rear to front) */ - SP3DBox *box3d = SP_3DBOX(rc.item); - box3d->faces[2].hook_path_to_3dbox(); - box3d->faces[3].hook_path_to_3dbox(); - box3d->faces[4].hook_path_to_3dbox(); - box3d->faces[5].hook_path_to_3dbox(); - box3d->faces[0].hook_path_to_3dbox(); - box3d->faces[1].hook_path_to_3dbox(); + /* Hook path to the only currenctly existing face */ + SP_3DBOX(rc.item)->faces[4]->hook_path_to_3dbox(); rc.item->updateRepr(); diff --git a/src/box3d-face.cpp b/src/box3d-face.cpp index d038de84f..e499fe4d0 100644 --- a/src/box3d-face.cpp +++ b/src/box3d-face.cpp @@ -78,6 +78,45 @@ Box3DFace::Box3DFace(Box3DFace const &box3dface) this->dir2 = box3dface.dir2; } +/** + * Construct a 3D box face with opposite corners A and C whose sides are directed + * along axis1 and axis2. The corners have the following order: + * + * A = corners[0] --> along axis1 --> B = corners[1] --> along axis2 --> C = corners[2] + * --> along axis1 --> D = corners[3] --> along axis2 --> D = corners[0]. + * + * Note that several other functions rely on this precise order. + */ +void +Box3DFace::set_face (NR::Point const A, NR::Point const C, Box3D::Axis const axis1, Box3D::Axis const axis2) +{ + corners[0] = A; + corners[2] = C; + if (!SP_IS_3DBOX_CONTEXT(inkscape_active_event_context())) + return; + SP3DBoxContext *bc = SP_3DBOX_CONTEXT(inkscape_active_event_context()); + + Box3D::PerspectiveLine line1 (A, axis1); + Box3D::PerspectiveLine line2 (C, axis2); + NR::Maybe B = line1.intersect(line2); + + Box3D::PerspectiveLine line3 (corners[0], axis2); + Box3D::PerspectiveLine line4 (corners[2], axis1); + NR::Maybe D = line3.intersect(line4); + + // FIXME: How to handle the case if one of the intersections doesn't exist? + // Maybe set them equal to the corresponding VPs? + if (!D) D = NR::Point(0.0, 0.0); + if (!B) B = NR::Point(0.0, 0.0); + + corners[1] = *B; + corners[3] = *D; + + this->dir1 = axis1; + this->dir2 = axis2; +} + + NR::Point Box3DFace::operator[](unsigned int i) { return corners[i % 4]; @@ -89,6 +128,8 @@ NR::Point Box3DFace::operator[](unsigned int i) */ void Box3DFace::hook_path_to_3dbox() { + if (this->path) return; // This test can probably be removed. + SPDesktop *desktop = inkscape_active_desktop(); Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_EVENT_CONTEXT_DOCUMENT(inkscape_active_event_context())); Inkscape::XML::Node *repr_face = xml_doc->createElement("svg:path"); @@ -110,6 +151,10 @@ void Box3DFace::set_curve() SPDocument *doc = SP_OBJECT_DOCUMENT(this->parent_box3d); gdouble height = sp_document_height(doc); + if (this->path == NULL) { + g_warning("this->path is NULL! \n"); + return; + } SPCurve *curve = sp_curve_new(); sp_curve_moveto(curve, corners[0][NR::X], height - corners[0][NR::Y]); sp_curve_lineto(curve, corners[1][NR::X], height - corners[1][NR::Y]); diff --git a/src/box3d-face.h b/src/box3d-face.h index 1b1eb451e..e557aebf2 100644 --- a/src/box3d-face.h +++ b/src/box3d-face.h @@ -37,6 +37,7 @@ public: Box3D::Axis const dir1, Box3D::Axis const dir2, unsigned int shift_count = 0, NR::Maybe pt_align = NR::Nothing(), bool align_along_PL = false); + void set_face (NR::Point const A, NR::Point const C, Box3D::Axis const dir1, Box3D::Axis const dir2); void hook_path_to_3dbox(); void set_path_repr(); diff --git a/src/box3d.cpp b/src/box3d.cpp index 94dfaf996..290b5111e 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -21,6 +21,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_shape_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); @@ -75,8 +76,12 @@ sp_3dbox_class_init(SP3DBoxClass *klass) static void sp_3dbox_init(SP3DBox *box3d) { + if (box3d == NULL) { g_warning ("box3d is NULL!\n"); } + box3d->faces[4] = new Box3DFace (box3d); + //box3d->faces[4]->hook_path_to_3dbox(); for (int i = 0; i < 6; ++i) { - box3d->faces[i] = Box3DFace (box3d); + if (i == 4) continue; + box3d->faces[i] = NULL; } } @@ -90,6 +95,22 @@ sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr //sp_object_read_attr(object, "width"); } +static void +sp_3dbox_release (SPObject *object) +{ + SP3DBox *box3d = 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 (((SPObjectClass *) parent_class)->release) { + ((SPObjectClass *) parent_class)->release (object); + } +} + + static void sp_3dbox_set(SPObject *object, unsigned int key, const gchar *value) { //SP3DBox *box3d = SP_3DBOX(object); @@ -140,12 +161,13 @@ static Inkscape::XML::Node *sp_3dbox_write(SPObject *object, Inkscape::XML::Node } - box3d->faces[0].set_path_repr(); + box3d->faces[4]->set_path_repr(); if (bc->extruded) { NR::Point corner1, corner2, corner3, corner4; sp_3dbox_compute_specific_corners (bc, corner1, corner2, corner3, corner4); for (int i = 0; i < 6; ++i) { - box3d->faces[i].set_path_repr(); + if (i == 4) continue; + box3d->faces[i]->set_path_repr(); } } if (((SPObjectClass *) (parent_class))->write) { @@ -199,20 +221,26 @@ sp_3dbox_set_shape(SP3DBox *box3d) if (bc->extruded) { sp_3dbox_compute_specific_corners (bc, corner1, corner2, corner3, corner4); - box3d->faces[2].set_shape(bc->drag_origin, corner4, Box3D::Z, Box3D::Y); - box3d->faces[2].set_curve(); - box3d->faces[3].set_shape(corner2, corner4, Box3D::X, Box3D::Y); - box3d->faces[3].set_curve(); - box3d->faces[4].set_shape(bc->drag_origin, corner2, Box3D::X, Box3D::Z); - box3d->faces[4].set_curve(); - box3d->faces[5].set_shape(bc->drag_ptB, corner4, Box3D::X, Box3D::Z); - box3d->faces[5].set_curve(); - - box3d->faces[1].set_shape(corner1, bc->drag_ptC, Box3D::Z, Box3D::Y); - box3d->faces[1].set_curve(); + for (int i=0; i < 6; ++i) { + if (!box3d->faces[i]) { + g_warning ("Face no. %d does not exist!\n", i); + return; + } + } + box3d->faces[0]->set_face (bc->drag_origin, corner4, Box3D::Z, Box3D::Y); + box3d->faces[0]->set_curve(); + box3d->faces[5]->set_face (corner3, bc->drag_ptC, Box3D::Y, Box3D::X); + box3d->faces[5]->set_curve(); + box3d->faces[3]->set_face (bc->drag_origin, corner2, Box3D::X, Box3D::Z); + box3d->faces[3]->set_curve(); + box3d->faces[2]->set_face (bc->drag_ptB, corner4, Box3D::X, Box3D::Z); + box3d->faces[2]->set_curve(); + + box3d->faces[1]->set_face (corner1, bc->drag_ptC, Box3D::Z, Box3D::Y); + box3d->faces[1]->set_curve(); } - box3d->faces[0].set_shape(bc->drag_origin, bc->drag_ptB, Box3D::X, Box3D::Y); - box3d->faces[0].set_curve(); + box3d->faces[4]->set_face(bc->drag_origin, bc->drag_ptB, Box3D::Y, Box3D::X); + box3d->faces[4]->set_curve(); } diff --git a/src/box3d.h b/src/box3d.h index 332848103..982596d8f 100644 --- a/src/box3d.h +++ b/src/box3d.h @@ -34,7 +34,7 @@ struct SP3DBox : public SPGroup { - Box3DFace faces[6]; + Box3DFace *faces[6]; }; struct SP3DBoxClass { -- 2.30.2