/*************************************************************************** * Copyright (c) 2004 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include #endif /// Here the FreeCAD includes sorted by Base,App,Gui...... #include #include #include #include #include "ViewProvider.h" #include "Application.h" #include "Document.h" #include "ViewProviderPy.h" #include "BitmapFactory.h" #include "View3DInventor.h" #include "View3DInventorViewer.h" #include "SoFCDB.h" using namespace std; using namespace Gui; //************************************************************************** //************************************************************************** // ViewProvider //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ PROPERTY_SOURCE_ABSTRACT(Gui::ViewProvider, App::PropertyContainer) ViewProvider::ViewProvider() : pcAnnotation(0) , pyViewObject(0) , overrideMode("As Is") , _iActualMode(-1) , _iEditMode(-1) , viewOverrideMode(-1) , _updateData(true) { pcRoot = new SoSeparator(); pcRoot->ref(); pcModeSwitch = new SoSwitch(); pcModeSwitch->ref(); pcTransform = new SoTransform(); pcTransform->ref(); pcRoot->addChild(pcTransform); pcRoot->addChild(pcModeSwitch); sPixmap = "px"; pcModeSwitch->whichChild = _iActualMode; } ViewProvider::~ViewProvider() { if (pyViewObject) { pyViewObject->setInvalid(); pyViewObject->DecRef(); } pcRoot->unref(); pcTransform->unref(); pcModeSwitch->unref(); if (pcAnnotation) pcAnnotation->unref(); } bool ViewProvider::startEditing(int ModNum) { bool ok = setEdit(ModNum); if (ok) _iEditMode = ModNum; return ok; } int ViewProvider::getEditingMode() const { return _iEditMode; } bool ViewProvider::isEditing() const { return getEditingMode() > -1; } void ViewProvider::finishEditing() { unsetEdit(_iEditMode); _iEditMode = -1; } bool ViewProvider::setEdit(int ModNum) { return true; } void ViewProvider::unsetEdit(int ModNum) { } void ViewProvider::setEditViewer(View3DInventorViewer*, int ModNum) { } void ViewProvider::unsetEditViewer(View3DInventorViewer*) { } bool ViewProvider::isUpdatesEnabled () const { return _updateData; } void ViewProvider::setUpdatesEnabled (bool enable) { _updateData = enable; } void highlight(const HighlightMode& high) { } void ViewProvider::eventCallback(void * ud, SoEventCallback * node) { const SoEvent * ev = node->getEvent(); Gui::View3DInventorViewer* viewer = reinterpret_cast(node->getUserData()); ViewProvider *self = reinterpret_cast(ud); assert(self); try { // Keyboard events if (ev->getTypeId().isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { SoKeyboardEvent * ke = (SoKeyboardEvent *)ev; const SbBool press = ke->getState() == SoButtonEvent::DOWN ? true : false; switch (ke->getKey()) { case SoKeyboardEvent::ESCAPE: if (self->keyPressed (press, ke->getKey())) node->setHandled(); else Gui::Application::Instance->activeDocument()->resetEdit(); break; default: // call the virtual method if (self->keyPressed (press, ke->getKey())) node->setHandled(); break; } } // switching the mouse buttons else if (ev->getTypeId().isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) { const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev; const int button = event->getButton(); const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false; // call the virtual method if (self->mouseButtonPressed(button,press,ev->getPosition(),viewer)) node->setHandled(); } // Mouse Movement handling else if (ev->getTypeId().isDerivedFrom(SoLocation2Event::getClassTypeId())) { if (self->mouseMove(ev->getPosition(),viewer)) node->setHandled(); } } catch (const Base::Exception& e) { Base::Console().Error("Unhandled exception in ViewProvider::eventCallback: %s\n", e.what()); } catch (const std::exception& e) { Base::Console().Error("Unhandled std exception in ViewProvider::eventCallback: %s\n", e.what()); } catch (...) { Base::Console().Error("Unhandled unknown C++ exception in ViewProvider::eventCallback"); } } SoSeparator* ViewProvider::getAnnotation(void) { if (!pcAnnotation) { pcAnnotation = new SoSeparator(); pcAnnotation->ref(); pcRoot->addChild(pcAnnotation); } return pcAnnotation; } void ViewProvider::update(const App::Property* prop) { // Hide the object temporarily to speed up the update if (!isUpdatesEnabled()) return; bool vis = ViewProvider::isShow(); if (vis) ViewProvider::hide(); updateData(prop); if (vis) ViewProvider::show(); } QIcon ViewProvider::getIcon(void) const { return Gui::BitmapFactory().pixmap(sPixmap); } void ViewProvider::setTransformation(const Base::Matrix4D &rcMatrix) { double dMtrx[16]; rcMatrix.getGLMatrix(dMtrx); pcTransform->setMatrix(SbMatrix(dMtrx[0], dMtrx[1], dMtrx[2], dMtrx[3], dMtrx[4], dMtrx[5], dMtrx[6], dMtrx[7], dMtrx[8], dMtrx[9], dMtrx[10], dMtrx[11], dMtrx[12],dMtrx[13],dMtrx[14], dMtrx[15])); } void ViewProvider::setTransformation(const SbMatrix &rcMatrix) { pcTransform->setMatrix(rcMatrix); } SbMatrix ViewProvider::convert(const Base::Matrix4D &rcMatrix) const { double dMtrx[16]; rcMatrix.getGLMatrix(dMtrx); return SbMatrix(dMtrx[0], dMtrx[1], dMtrx[2], dMtrx[3], dMtrx[4], dMtrx[5], dMtrx[6], dMtrx[7], dMtrx[8], dMtrx[9], dMtrx[10], dMtrx[11], dMtrx[12],dMtrx[13],dMtrx[14], dMtrx[15]); } void ViewProvider::addDisplayMaskMode( SoNode *node, const char* type ) { _sDisplayMaskModes[ type ] = pcModeSwitch->getNumChildren(); pcModeSwitch->addChild( node ); } void ViewProvider::setDisplayMaskMode( const char* type ) { std::map::const_iterator it = _sDisplayMaskModes.find( type ); if (it != _sDisplayMaskModes.end()) _iActualMode = it->second; else _iActualMode = -1; setModeSwitch(); } SoNode* ViewProvider::getDisplayMaskMode(const char* type) const { std::map::const_iterator it = _sDisplayMaskModes.find( type ); if (it != _sDisplayMaskModes.end()) { return pcModeSwitch->getChild(it->second); } return 0; } std::vector ViewProvider::getDisplayMaskModes() const { std::vector types; for (std::map::const_iterator it = _sDisplayMaskModes.begin(); it != _sDisplayMaskModes.end(); ++it) types.push_back( it->first ); return types; } /** * If you add new viewing modes in @ref getDisplayModes() then you need to reimplement * also seDisplaytMode() to handle these new modes by setting the appropriate display * mode. */ void ViewProvider::setDisplayMode(const char* ModeName) { _sCurrentMode = ModeName; } std::string ViewProvider::getActiveDisplayMode(void) const { return _sCurrentMode; } void ViewProvider::hide(void) { pcModeSwitch->whichChild = -1; } void ViewProvider::show(void) { setModeSwitch(); } bool ViewProvider::isShow(void) const { return pcModeSwitch->whichChild.getValue() != -1; } void ViewProvider::setVisible(bool s) { s ? show() : hide(); } bool ViewProvider::isVisible() const { return isShow(); } void ViewProvider::setOverrideMode(const std::string &mode) { if (mode == "As Is") { viewOverrideMode = -1; overrideMode = mode; } else { std::map::const_iterator it = _sDisplayMaskModes.find(mode); if (it == _sDisplayMaskModes.end()) return; //view style not supported viewOverrideMode = (*it).second; overrideMode = mode; } if (pcModeSwitch->whichChild.getValue() != -1) setModeSwitch(); } const string ViewProvider::getOverrideMode() { return overrideMode; } void ViewProvider::setModeSwitch() { if (viewOverrideMode == -1) pcModeSwitch->whichChild = _iActualMode; else if (viewOverrideMode < pcModeSwitch->getNumChildren()) pcModeSwitch->whichChild = viewOverrideMode; } void ViewProvider::setDefaultMode(int val) { _iActualMode = val; } void ViewProvider::onChanged(const App::Property* prop) { Application::Instance->signalChangedObject(*this, *prop); } std::string ViewProvider::toString() const { return SoFCDB::writeNodesToString(pcRoot); } PyObject* ViewProvider::getPyObject() { if (!pyViewObject) pyViewObject = new ViewProviderPy(this); pyViewObject->IncRef(); return pyViewObject; } SoPickedPoint* ViewProvider::getPointOnRay(const SbVec2s& pos, const View3DInventorViewer* viewer) const { //first get the path to this node and calculate the current transformation SoSearchAction sa; sa.setNode(pcRoot); sa.setSearchingAll(true); sa.apply(viewer->getSoRenderManager()->getSceneGraph()); SoGetMatrixAction gm(viewer->getSoRenderManager()->getViewportRegion()); gm.apply(sa.getPath()); SoTransform* trans = new SoTransform; trans->setMatrix(gm.getMatrix()); trans->ref(); // build a temporary scenegraph only keeping this viewproviders nodes and the accumulated // transformation SoSeparator* root = new SoSeparator; root->ref(); root->addChild(viewer->getSoRenderManager()->getCamera()); root->addChild(trans); root->addChild(pcRoot); //get the picked point SoRayPickAction rp(viewer->getSoRenderManager()->getViewportRegion()); rp.setPoint(pos); rp.apply(root); root->unref(); trans->unref(); SoPickedPoint* pick = rp.getPickedPoint(); return (pick ? new SoPickedPoint(*pick) : 0); } SoPickedPoint* ViewProvider::getPointOnRay(const SbVec3f& pos,const SbVec3f& dir, const View3DInventorViewer* viewer) const { // Note: There seems to be a bug with setRay() which causes SoRayPickAction // to fail to get intersections between the ray and a line //first get the path to this node and calculate the current setTransformation SoSearchAction sa; sa.setNode(pcRoot); sa.setSearchingAll(true); sa.apply(viewer->getSoRenderManager()->getSceneGraph()); SoGetMatrixAction gm(viewer->getSoRenderManager()->getViewportRegion()); gm.apply(sa.getPath()); // build a temporary scenegraph only keeping this viewproviders nodes and the accumulated // transformation SoTransform* trans = new SoTransform; trans->ref(); trans->setMatrix(gm.getMatrix()); SoSeparator* root = new SoSeparator; root->ref(); root->addChild(viewer->getSoRenderManager()->getCamera()); root->addChild(trans); root->addChild(pcRoot); //get the picked point SoRayPickAction rp(viewer->getSoRenderManager()->getViewportRegion()); rp.setRay(pos,dir); rp.apply(root); root->unref(); trans->unref(); // returns a copy of the point SoPickedPoint* pick = rp.getPickedPoint(); //return (pick ? pick->copy() : 0); // needs the same instance of CRT under MS Windows return (pick ? new SoPickedPoint(*pick) : 0); } std::vector ViewProvider::getModelPoints(const SoPickedPoint* pp) const { // the default implementation just returns the picked point from the visual representation std::vector pts; const SbVec3f& vec = pp->getPoint(); pts.push_back(Base::Vector3d(vec[0],vec[1],vec[2])); return pts; }