void Box3DKnotHolderEntityCenter::knot_set(Geom::Point const &new_pos, Geom::Point const &origin, guint state) { Geom::Point const s = snap_knot_position(new_pos, state); SPBox3D *box = SP_BOX3D(item); Geom::Affine const i2dt (item->i2dt_affine ()); box3d_set_center (SP_BOX3D(item), s * i2dt, origin * i2dt, !(state & GDK_SHIFT_MASK) ? Box3D::XY : Box3D::Z, state & GDK_CONTROL_MASK); box3d_set_z_orders(box); box3d_position_set(box); }
static void sp_box3d_finish(Box3DContext *bc) { bc->_message_context->clear(); bc->ctrl_dragged = false; bc->extruded = false; if ( bc->item != NULL ) { SPDesktop * desktop = SP_EVENT_CONTEXT_DESKTOP(bc); SPDocument *doc = sp_desktop_document(desktop); if (!doc || !doc->getCurrentPersp3D()) return; SPBox3D *box = SP_BOX3D(bc->item); box->orig_corner0 = bc->drag_origin_proj; box->orig_corner7 = bc->drag_ptC_proj; box->updateRepr(); box3d_relabel_corners(box); desktop->canvas->end_forced_full_redraws(); sp_desktop_selection(desktop)->set(bc->item); sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX, _("Create 3D box")); bc->item = NULL; } }
/** * Regenerates the draggers list from the current selection; is called when selection is changed or modified */ void VPDrag::updateDraggers () { if (this->dragging) return; // 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); if (!SP_IS_BOX3D (item)) continue; SPBox3D *box = SP_BOX3D (item); VanishingPoint vp; for (int i = 0; i < 3; ++i) { vp.set(box3d_get_perspective(box), Proj::axes[i]); addDragger (vp); } } }
std::list<SPBox3D *> VanishingPoint::selectedBoxes(Inkscape::Selection *sel) { std::list<SPBox3D *> sel_boxes; for (GSList const* i = sel->itemList(); i != NULL; i = i->next) { if (!SP_IS_BOX3D(i->data)) continue; SPBox3D *box = SP_BOX3D(i->data); if (this->hasBox(box)) { sel_boxes.push_back (box); } } return sel_boxes; }
std::set<VanishingPoint*, less_ptr> VPDragger::VPsOfSelectedBoxes() { std::set<VanishingPoint*, less_ptr> sel_vps; VanishingPoint *vp; // FIXME: Should we take the selection from the parent VPDrag? I guess it shouldn't make a difference. Inkscape::Selection *sel = sp_desktop_selection(inkscape_active_desktop()); for (GSList const* i = sel->itemList(); i != NULL; i = i->next) { if (!SP_IS_BOX3D(i->data)) continue; SPBox3D *box = SP_BOX3D(i->data); vp = this->findVPWithBox(box); if (vp) { sel_vps.insert (vp); } } return sel_vps; }
void Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom::Point const &new_pos, guint state) { Geom::Point const s = snap_knot_position(new_pos, state); g_assert(item != NULL); SPBox3D *box = SP_BOX3D(item); Geom::Affine const i2dt (item->i2dt_affine ()); Box3D::Axis movement; if ((knot_id < 4) != (state & GDK_SHIFT_MASK)) { movement = Box3D::XY; } else { movement = Box3D::Z; } box3d_set_corner (box, knot_id, s * i2dt, movement, (state & GDK_CONTROL_MASK)); box3d_set_z_orders(box); box3d_position_set(box); }
/** Regenerates the lines list from the current selection; is called on each move of a dragger, so that lines are always in sync with the actual perspective */ void VPDrag::updateLines () { // delete old lines for (GSList const *i = this->lines; i != NULL; i = i->next) { gtk_object_destroy( GTK_OBJECT (i->data)); } g_slist_free (this->lines); this->lines = NULL; // do nothing if perspective lines are currently disabled if (this->show_lines == 0) return; g_return_if_fail (this->selection != NULL); for (GSList const* i = this->selection->itemList(); i != NULL; i = i->next) { if (!SP_IS_BOX3D(i->data)) continue; SPBox3D *box = SP_BOX3D (i->data); this->drawLinesForFace (box, Proj::X); this->drawLinesForFace (box, Proj::Y); this->drawLinesForFace (box, Proj::Z); } }
static void sp_box3d_drag(Box3DContext &bc, guint /*state*/) { SPDesktop *desktop = SP_EVENT_CONTEXT(&bc)->desktop; if (!bc.item) { if (Inkscape::have_viable_layer(desktop, bc._message_context) == false) { return; } /* Create object */ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_EVENT_CONTEXT_DOCUMENT(&bc)); Inkscape::XML::Node *repr = xml_doc->createElement("svg:g"); repr->setAttribute("sodipodi:type", "inkscape:box3d"); /* Set style */ sp_desktop_apply_style_tool (desktop, repr, "/tools/shapes/3dbox", false); bc.item = (SPItem *) desktop->currentLayer()->appendChildRepr(repr); Inkscape::GC::release(repr); Inkscape::XML::Node *repr_side; // TODO: Incorporate this in box3d-side.cpp! for (int i = 0; i < 6; ++i) { repr_side = xml_doc->createElement("svg:path"); repr_side->setAttribute("sodipodi:type", "inkscape:box3dside"); repr->addChild(repr_side, NULL); Box3DSide *side = SP_BOX3D_SIDE(inkscape_active_document()->getObjectByRepr (repr_side)); guint desc = Box3D::int_to_face(i); Box3D::Axis plane = (Box3D::Axis) (desc & 0x7); plane = (Box3D::is_plane(plane) ? plane : Box3D::orth_plane_or_axis(plane)); side->dir1 = Box3D::extract_first_axis_direction(plane); side->dir2 = Box3D::extract_second_axis_direction(plane); side->front_or_rear = (Box3D::FrontOrRear) (desc & 0x8); /* Set style */ box3d_side_apply_style(side); SP_OBJECT(side)->updateRepr(); // calls box3d_side_write() and updates, e.g., the axes string description } box3d_set_z_orders(SP_BOX3D(bc.item)); 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(); */ desktop->canvas->force_full_redraw_after_interruptions(5); } g_assert(bc.item); SPBox3D *box = SP_BOX3D(bc.item); box->orig_corner0 = bc.drag_origin_proj; box->orig_corner7 = bc.drag_ptC_proj; box3d_check_for_swapped_coords(box); /* we need to call this from here (instead of from box3d_position_set(), for example) because z-order setting must not interfere with display updates during undo/redo */ box3d_set_z_orders (box); box3d_position_set(box); // status text bc._message_context->setF(Inkscape::NORMAL_MESSAGE, "%s", _("<b>3D Box</b>; with <b>Shift</b> to extrude along the Z axis")); }
Persp3D * box3d_side_perspective(Box3DSide *side) { return SP_BOX3D(side->parent)->persp_ref->getObject(); }
void Box3DSide::set_shape() { if (!this->document->getRoot()) { // avoid a warning caused by sp_document_height() (which is called from sp_item_i2d_affine() below) // when reading a file containing 3D boxes return; } SPObject *parent = this->parent; if (!SP_IS_BOX3D(parent)) { g_warning("Parent of 3D box side is not a 3D box.\n"); return; } SPBox3D *box = SP_BOX3D(parent); Persp3D *persp = box3d_side_perspective(this); if (!persp) { return; } // TODO: Draw the correct quadrangle here // To do this, determine the perspective of the box, the orientation of the side (e.g., XY-FRONT) // compute the coordinates of the corners in P^3, project them onto the canvas, and draw the // resulting path. unsigned int corners[4]; box3d_side_compute_corner_ids(this, corners); SPCurve *c = new SPCurve(); if (!box3d_get_corner_screen(box, corners[0]).isFinite() || !box3d_get_corner_screen(box, corners[1]).isFinite() || !box3d_get_corner_screen(box, corners[2]).isFinite() || !box3d_get_corner_screen(box, corners[3]).isFinite() ) { g_warning ("Trying to draw a 3D box side with invalid coordinates.\n"); return; } c->moveto(box3d_get_corner_screen(box, corners[0])); c->lineto(box3d_get_corner_screen(box, corners[1])); c->lineto(box3d_get_corner_screen(box, corners[2])); c->lineto(box3d_get_corner_screen(box, corners[3])); c->closepath(); /* Reset the this'scurve to the "original_curve" * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/ this->setCurveInsync( c, TRUE); if (hasPathEffect() && pathEffectsEnabled()) { SPCurve *c_lpe = c->copy(); bool success = this->performPathEffect(c_lpe); if (success) { this->setCurveInsync(c_lpe, TRUE); } c_lpe->unref(); } c->unref(); }
Geom::Point Box3DKnotHolderEntityCenter::knot_get() const { return box3d_get_center_screen(SP_BOX3D(item)); }
Geom::Point Box3DKnotHolderEntity::knot_get_generic(SPItem *item, unsigned int knot_id) const { return box3d_get_corner_screen(SP_BOX3D(item), knot_id); }
bool sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_select, bool skip_all_lpeitems) { bool did = false; for (; items != NULL; items = items->next) { SPItem *item = SP_ITEM(items->data); SPDocument *document = item->document; if ( skip_all_lpeitems && SP_IS_LPE_ITEM(item) && !SP_IS_GROUP(item) ) // also convert objects in an SPGroup when skip_all_lpeitems is set. { continue; } if (SP_IS_PATH(item) && !SP_PATH(item)->original_curve) { continue; // already a path, and no path effect } if (SP_IS_BOX3D(item)) { // convert 3D box to ordinary group of paths; replace the old element in 'selected' with the new group Inkscape::XML::Node *repr = SP_OBJECT_REPR(box3d_convert_to_group(SP_BOX3D(item))); if (repr) { *to_select = g_slist_prepend (*to_select, repr); did = true; *selected = g_slist_remove (*selected, item); } continue; } if (SP_IS_GROUP(item)) { sp_lpe_item_remove_all_path_effects(SP_LPE_ITEM(item), true); GSList *item_list = sp_item_group_item_list(SP_GROUP(item)); GSList *item_to_select = NULL; GSList *item_selected = NULL; if (sp_item_list_to_curves(item_list, &item_selected, &item_to_select)) did = true; g_slist_free(item_list); g_slist_free(item_to_select); g_slist_free(item_selected); continue; } Inkscape::XML::Node *repr = sp_selected_item_to_curved_repr(item, 0); if (!repr) continue; did = true; *selected = g_slist_remove (*selected, item); // remember the position of the item gint pos = SP_OBJECT_REPR(item)->position(); // remember parent Inkscape::XML::Node *parent = SP_OBJECT_REPR(item)->parent(); // remember id char const *id = SP_OBJECT_REPR(item)->attribute("id"); // remember title gchar *title = item->title(); // remember description gchar *desc = item->desc(); // It's going to resurrect, so we delete without notifying listeners. SP_OBJECT(item)->deleteObject(false); // restore id repr->setAttribute("id", id); // add the new repr to the parent parent->appendChild(repr); SPObject* newObj = document->getObjectByRepr(repr); if (title && newObj) { newObj->setTitle(title); g_free(title); } if (desc && newObj) { newObj->setDesc(desc); g_free(desc); } // move to the saved position repr->setPosition(pos > 0 ? pos : 0); /* Buglet: We don't re-add the (new version of the) object to the selection of any other * desktops where it was previously selected. */ *to_select = g_slist_prepend (*to_select, repr); Inkscape::GC::release(repr); } return did; }