X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fvanishing-point.h;h=7d53fa89d431a7cb06d581f276531eadd089e72a;hb=17b1b900f2bef1869ad4462e2c848315bfd45192;hp=b7f3d12a1f8ec322d35f8e5481bdb36c11f0a54d;hpb=5ab319377e453e88687f4d1e450b23633a6534c6;p=inkscape.git diff --git a/src/vanishing-point.h b/src/vanishing-point.h index b7f3d12a1..7d53fa89d 100644 --- a/src/vanishing-point.h +++ b/src/vanishing-point.h @@ -13,7 +13,13 @@ #define SEEN_VANISHING_POINT_H #include "libnr/nr-point.h" -#include "line-geometry.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. + +class SP3DBox; namespace Box3D { @@ -22,102 +28,6 @@ enum VPState { VP_INFINITE // perspective lines are parallel }; -// The X-/Y-/Z-axis corresponds to the first/second/third digit -// in binary representation, respectively. -enum Axis { - X = 1, - Y = 2, - Z = 4, - XY = 3, - XZ = 5, - YZ = 6, - XYZ = 7, - NONE = 0 -}; - -// We use the fourth bit in binary representation -// to indicate whether a face is front or rear. -enum FrontOrRear { // find a better name - FRONT = 0, - REAR = 8 -}; - -extern Axis axes[3]; -extern Axis planes[3]; -extern FrontOrRear face_positions [2]; - -// Given a bit sequence that unambiguously specifies the face of a 3D box, -// return a number between 0 and 5 corresponding to that particular face -// (which is normally used to index an array). Return -1 if the bit sequence -// does not specify a face. A face can either be given by its plane (e.g, XY) -// or by the axis that is orthogonal to it (e.g., Z). -inline gint face_to_int (guint face_id) { - switch (face_id) { - case 1: return 0; - case 2: return 2; - case 4: return 4; - case 3: return 4; - case 5: return 2; - case 6: return 0; - - case 9: return 1; - case 10: return 3; - case 12: return 5; - case 11: return 5; - case 13: return 3; - case 14: return 1; - - default: return -1; - } -} - -inline bool is_single_axis_direction (Box3D::Axis dir) { - // tests whether dir is nonzero and a power of 2 - return (!(dir & (dir - 1)) && dir); -} - -/** - * Given two axis directions out of {X, Y, Z} or the corresponding plane, return the remaining one - * We don't check if 'plane' really specifies a plane (i.e., if it consists of precisely two directions). - */ -inline Box3D::Axis third_axis_direction (Box3D::Axis dir1, Box3D::Axis dir2) { - return (Box3D::Axis) ((dir1 + dir2) ^ 0x7); -} -inline Box3D::Axis third_axis_direction (Box3D::Axis plane) { - return (Box3D::Axis) (plane ^ 0x7); -} - -/* returns the first/second axis direction occuring in the (possibly compound) expression 'dirs' */ -inline Box3D::Axis extract_first_axis_direction (Box3D::Axis dirs) { - if (dirs & Box3D::X) return Box3D::X; - if (dirs & Box3D::Y) return Box3D::Y; - if (dirs & Box3D::Z) return Box3D::Z; - return Box3D::NONE; -} -inline Box3D::Axis extract_second_axis_direction (Box3D::Axis dirs) { - return extract_first_axis_direction ((Box3D::Axis) (dirs ^ extract_first_axis_direction(dirs))); -} - -inline Box3D::Axis orth_plane (Box3D::Axis axis) { - return (Box3D::Axis) (Box3D::XYZ ^ axis); -} - -/* returns an axis direction perpendicular to the ones occuring in the (possibly compound) expression 'dirs' */ -inline Box3D::Axis get_perpendicular_axis_direction (Box3D::Axis dirs) { - if (!(dirs & Box3D::X)) return Box3D::X; - if (!(dirs & Box3D::Y)) return Box3D::Y; - if (!(dirs & Box3D::Z)) return Box3D::Z; - return Box3D::NONE; -} - -inline gchar * string_from_axes (Box3D::Axis axes) { - GString *pstring = g_string_new(""); - if (axes & Box3D::X) g_string_append_printf (pstring, "X"); - if (axes & Box3D::Y) g_string_append_printf (pstring, "Y"); - if (axes & Box3D::Z) g_string_append_printf (pstring, "Z"); - return pstring->str; -} - // FIXME: Store the Axis of the VP inside the class class VanishingPoint : public NR::Point { public: @@ -140,8 +50,17 @@ public: 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 is_finite(); + bool operator== (VanishingPoint const &other); + + inline NR::Point get_pos() const { return NR::Point ((*this)[NR::X], (*this)[NR::Y]); } + 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; + (*this)[NR::Y] = pt_y; } + + bool is_finite() const; VPState toggle_parallel(); void draw(Box3D::Axis const axis); // Draws a point on the canvas if state == VP_FINITE //inline VPState state() { return state; } @@ -153,6 +72,83 @@ public: private: }; +class Perspective3D; +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); + /* returns the VP of the dragger that belongs to the given perspective */ + VanishingPoint *getVPofPerspective (Perspective3D *persp); + + void updateTip(); + + bool hasBox (const SP3DBox *box); + guint numberOfBoxes(); // the number of boxes linked to all VPs of the dragger + + bool hasPerspective (const Perspective3D *perps); + void mergePerspectives (); // remove duplicate perspectives + + void reshapeBoxes(NR::Point const &p, Box3D::Axis axes); + void updateBoxReprs(); + void updateZOrders(); +}; + +struct VPDrag { +public: + VPDrag(SPDocument *document); + ~VPDrag(); + + VPDragger *getDraggerFor (VanishingPoint const &vp); + + //void grabKnot (VanishingPoint const &vp, gint x, gint y, guint32 etime); + + bool local_change; + + SPDocument *document; + GList *draggers; + GSList *lines; + + void updateDraggers (); + void updateLines (); + void updateBoxHandles (); + void drawLinesForFace (const SP3DBox *box, Box3D::Axis axis); //, guint corner1, guint corner2, guint corner3, guint corner4); + bool show_lines; /* whether perspective lines are drawn at all */ + guint front_or_rear_lines; /* whether we draw perspective lines from all corners or only the + front/rear corners (indicated by the first/second bit, respectively */ + + + inline bool hasEmptySelection() { return this->selection->isEmpty(); } + bool allBoxesAreSelected (VPDragger *dragger); + GSList * selectedBoxesWithVPinDragger (VPDragger *dragger); + + // FIXME: Should this be private? (It's the case with the corresponding function in gradient-drag.h) + // But vp_knot_grabbed_handler + void addDragger (VanishingPoint *vp); + +private: + //void deselect_all(); + + void addLine (NR::Point p1, NR::Point p2, guint32 rgba); + + Inkscape::Selection *selection; + sigc::connection sel_changed_connection; + sigc::connection sel_modified_connection; +}; } // namespace Box3D