diff --git a/src/Gui/Application.h b/src/Gui/Application.h index 3dec079a5..031cf4dd7 100644 --- a/src/Gui/Application.h +++ b/src/Gui/Application.h @@ -245,6 +245,9 @@ public: PYFUNCDEF_S(sShowDownloads); PYFUNCDEF_S(sShowPreferences); + + PYFUNCDEF_S(sCreateViewer); + static PyMethodDef Methods[]; private: diff --git a/src/Gui/ApplicationPy.cpp b/src/Gui/ApplicationPy.cpp index be69ecdf7..f37875fdd 100644 --- a/src/Gui/ApplicationPy.cpp +++ b/src/Gui/ApplicationPy.cpp @@ -48,6 +48,7 @@ #include "PythonEditor.h" #include "SoFCDB.h" #include "View3DInventor.h" +#include "SplitView3DInventor.h" #include "ViewProvider.h" #include "WidgetFactory.h" #include "Workbench.h" @@ -169,6 +170,9 @@ PyMethodDef Application::Methods[] = { {"showPreferences", (PyCFunction) Application::sShowPreferences,1, "showPreferences([string,int]) -> None\n\n" "Shows the preferences window. If string and int are provided, the given page index in the given group is shown."}, + {"createViewer", (PyCFunction) Application::sCreateViewer,1, + "createViewer([int]) -> View3DInventor/SplitView3DInventor\n\n" + "shows and returns a viewer. If the integer argument is given and > 1: -> splitViewer"}, {NULL, NULL} /* Sentinel */ }; @@ -1109,3 +1113,29 @@ PyObject* Application::sShowPreferences(PyObject * /*self*/, PyObject *args,PyOb Py_INCREF(Py_None); return Py_None; } + + +PyObject* Application::sCreateViewer(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/) +{ + + int num_of_views = 1; + // if one argument (int) is given + if (PyArg_ParseTuple(args, "|i", &num_of_views)) + { + if (num_of_views < 0) + return NULL; + else if (num_of_views==1) + { + View3DInventor* viewer = new View3DInventor(0, 0); + Gui::getMainWindow()->addWindow(viewer); + return viewer->getPyObject(); + } + else + { + SplitView3DInventor* viewer = new SplitView3DInventor(num_of_views, 0, 0); + Gui::getMainWindow()->addWindow(viewer); + return viewer->getPyObject(); + } + } + return Py_None; +} \ No newline at end of file diff --git a/src/Gui/SplitView3DInventor.cpp b/src/Gui/SplitView3DInventor.cpp index 01b00c7a6..a1e7ff560 100644 --- a/src/Gui/SplitView3DInventor.cpp +++ b/src/Gui/SplitView3DInventor.cpp @@ -46,6 +46,7 @@ TYPESYSTEM_SOURCE_ABSTRACT(Gui::AbstractSplitView,Gui::MDIView); AbstractSplitView::AbstractSplitView(Gui::Document* pcDocument, QWidget* parent, Qt::WindowFlags wflags) : MDIView(pcDocument,parent, wflags) { + _viewerPy = 0; // important for highlighting setMouseTracking(true); } @@ -56,6 +57,10 @@ AbstractSplitView::~AbstractSplitView() for (std::vector::iterator it = _viewer.begin(); it != _viewer.end(); ++it) { delete *it; } + if (_viewerPy) { + static_cast(_viewerPy)->_view = 0; + Py_DECREF(_viewerPy); + } } void AbstractSplitView::deleteSelf() @@ -374,8 +379,10 @@ PyObject *AbstractSplitView::getPyObject(void) init = true; AbstractSplitViewPy::init_type(); } - - return new AbstractSplitViewPy(this); + if (!_viewerPy) + _viewerPy = new AbstractSplitViewPy(this); + Py_INCREF(_viewerPy); + return _viewerPy; } void AbstractSplitView::setPyObject(PyObject *) @@ -383,6 +390,11 @@ void AbstractSplitView::setPyObject(PyObject *) throw Base::AttributeError("Attribute is read-only"); } +int AbstractSplitView::getSize() +{ + return _viewer.size(); +} + // ------------------------------------------------------ void AbstractSplitViewPy::init_type() @@ -391,6 +403,7 @@ void AbstractSplitViewPy::init_type() behaviors().doc("Python binding class for the Inventor viewer class"); // you must have overwritten the virtual functions behaviors().supportRepr(); + behaviors().supportSequenceType(); add_varargs_method("fitAll",&AbstractSplitViewPy::fitAll,"fitAll()"); add_varargs_method("viewBottom",&AbstractSplitViewPy::viewBottom,"viewBottom()"); @@ -400,6 +413,8 @@ void AbstractSplitViewPy::init_type() add_varargs_method("viewRight",&AbstractSplitViewPy::viewRight,"viewRight()"); add_varargs_method("viewTop",&AbstractSplitViewPy::viewTop,"viewTop()"); add_varargs_method("viewAxometric",&AbstractSplitViewPy::viewAxometric,"viewAxometric()"); + add_varargs_method("getViewer",&AbstractSplitViewPy::getViewer,"getViewer(index)"); + add_varargs_method("close",&AbstractSplitViewPy::close,"close()"); } AbstractSplitViewPy::AbstractSplitViewPy(AbstractSplitView *vi) @@ -411,6 +426,12 @@ AbstractSplitViewPy::~AbstractSplitViewPy() { } +void AbstractSplitViewPy::testExistence() +{ + if (!(_view and _view->getViewer(0))) + throw Py::Exception("Object already deleted"); +} + Py::Object AbstractSplitViewPy::repr() { std::string s; @@ -425,7 +446,7 @@ Py::Object AbstractSplitViewPy::fitAll(const Py::Tuple& args) { if (!PyArg_ParseTuple(args.ptr(), "")) throw Py::Exception(); - + testExistence(); try { _view->onMsg("ViewFit", 0); } @@ -445,7 +466,7 @@ Py::Object AbstractSplitViewPy::viewBottom(const Py::Tuple& args) { if (!PyArg_ParseTuple(args.ptr(), "")) throw Py::Exception(); - + testExistence(); try { _view->onMsg("ViewBottom", 0); } @@ -466,7 +487,7 @@ Py::Object AbstractSplitViewPy::viewFront(const Py::Tuple& args) { if (!PyArg_ParseTuple(args.ptr(), "")) throw Py::Exception(); - + testExistence(); try { _view->onMsg("ViewFront", 0); } @@ -487,7 +508,7 @@ Py::Object AbstractSplitViewPy::viewLeft(const Py::Tuple& args) { if (!PyArg_ParseTuple(args.ptr(), "")) throw Py::Exception(); - + testExistence(); try { _view->onMsg("ViewLeft", 0); } @@ -508,7 +529,7 @@ Py::Object AbstractSplitViewPy::viewRear(const Py::Tuple& args) { if (!PyArg_ParseTuple(args.ptr(), "")) throw Py::Exception(); - + testExistence(); try { _view->onMsg("ViewRear", 0); } @@ -529,7 +550,7 @@ Py::Object AbstractSplitViewPy::viewRight(const Py::Tuple& args) { if (!PyArg_ParseTuple(args.ptr(), "")) throw Py::Exception(); - + testExistence(); try { _view->onMsg("ViewRight", 0); } @@ -550,7 +571,7 @@ Py::Object AbstractSplitViewPy::viewTop(const Py::Tuple& args) { if (!PyArg_ParseTuple(args.ptr(), "")) throw Py::Exception(); - + testExistence(); try { _view->onMsg("ViewTop", 0); } @@ -571,7 +592,7 @@ Py::Object AbstractSplitViewPy::viewAxometric(const Py::Tuple& args) { if (!PyArg_ParseTuple(args.ptr(), "")) throw Py::Exception(); - + testExistence(); try { _view->onMsg("ViewAxo", 0); } @@ -588,6 +609,55 @@ Py::Object AbstractSplitViewPy::viewAxometric(const Py::Tuple& args) return Py::None(); } +Py::Object AbstractSplitViewPy::getViewer(const Py::Tuple& args) +{ + int viewIndex; + if (!PyArg_ParseTuple(args.ptr(), "i", &viewIndex)) + throw Py::Exception(); + testExistence(); + try { + return Py::Object(_view->getViewer(viewIndex)->getPyObject()); + } + catch (const Base::Exception& e) { + throw Py::Exception(e.what()); + } + catch (const std::exception& e) { + throw Py::Exception(e.what()); + } + catch(...) { + throw Py::Exception("Unknown C++ exception"); + } + + return Py::None(); +} + +Py::Object AbstractSplitViewPy::sequence_item(ssize_t viewIndex) +{ + testExistence(); + if (viewIndex >= _view->getSize() or viewIndex < 0) + throw Py::Exception("Index out of range"); + PyObject* viewer = _view->getViewer(viewIndex)->getPyObject(); + return Py::Object(viewer); +} + +int AbstractSplitViewPy::sequence_length() +{ + return _view->getSize(); +} + +Py::Object AbstractSplitViewPy::close(const Py::Tuple& args) +{ + if (!PyArg_ParseTuple(args.ptr(), "")) + throw Py::Exception(); + testExistence(); + + _view->close(); + if (_view->parentWidget()) + _view->parentWidget()->deleteLater(); + _view = 0; + + return Py::None(); +} // ------------------------------------------------------ TYPESYSTEM_SOURCE_ABSTRACT(Gui::SplitView3DInventor, Gui::AbstractSplitView); @@ -595,26 +665,86 @@ TYPESYSTEM_SOURCE_ABSTRACT(Gui::SplitView3DInventor, Gui::AbstractSplitView); SplitView3DInventor::SplitView3DInventor(int views, Gui::Document* pcDocument, QWidget* parent, Qt::WindowFlags wflags) : AbstractSplitView(pcDocument,parent, wflags) { - QSplitter* mainSplitter=0; + // attach parameter Observer + hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View"); + hGrp->Attach(this); - if (views <= 3) { + //anti-aliasing settings + QGLFormat f; + bool smoothing = false; + bool glformat = false; + switch( hGrp->GetInt("AntiAliasing",0) ) { + case View3DInventorViewer::MSAA2x: + glformat = true; + f.setSampleBuffers(true); + f.setSamples(2); + break; + case View3DInventorViewer::MSAA4x: + glformat = true; + f.setSampleBuffers(true); + f.setSamples(4); + break; + case View3DInventorViewer::MSAA8x: + glformat = true; + f.setSampleBuffers(true); + f.setSamples(8); + break; + case View3DInventorViewer::Smoothing: + smoothing = true; + break; + case View3DInventorViewer::None: + default: + break; + } + + + QSplitter* mainSplitter=0; + // minimal 2 views + while (views < 2) + views ++; + // if views < 3 show them as a row + if (views <= 3) + { mainSplitter = new QSplitter(Qt::Horizontal, this); - _viewer.push_back(new View3DInventorViewer(mainSplitter)); - _viewer.push_back(new View3DInventorViewer(mainSplitter)); - if (views==3) - _viewer.push_back(new View3DInventorViewer(mainSplitter)); + for (int i=0; i < views; i++) + { + if (glformat) + _viewer.push_back(new View3DInventorViewer(f, mainSplitter)); + else + _viewer.push_back(new View3DInventorViewer(mainSplitter)); + } } else { mainSplitter = new QSplitter(Qt::Vertical, this); QSplitter *topSplitter = new QSplitter(Qt::Horizontal, mainSplitter); QSplitter *botSplitter = new QSplitter(Qt::Horizontal, mainSplitter); - _viewer.push_back(new View3DInventorViewer(topSplitter)); - _viewer.push_back(new View3DInventorViewer(topSplitter)); + if (glformat) + { + _viewer.push_back(new View3DInventorViewer(f, mainSplitter)); + _viewer.push_back(new View3DInventorViewer(f, topSplitter)); + _viewer.push_back(new View3DInventorViewer(f, topSplitter)); + } + else + { + _viewer.push_back(new View3DInventorViewer(mainSplitter)); + _viewer.push_back(new View3DInventorViewer(topSplitter)); + _viewer.push_back(new View3DInventorViewer(topSplitter)); + } for (int i=2;isetOpaqueResize( true ); botSplitter->setOpaqueResize( true ); } + if (smoothing) + { + for (std::vector::size_type i = 0; i != _viewer.size(); i++) + _viewer[i]->getSoRenderManager()->getGLRenderAction()->setSmoothing(true); + } mainSplitter->show(); setCentralWidget(mainSplitter); diff --git a/src/Gui/SplitView3DInventor.h b/src/Gui/SplitView3DInventor.h index d32afd000..ec717b934 100644 --- a/src/Gui/SplitView3DInventor.h +++ b/src/Gui/SplitView3DInventor.h @@ -32,7 +32,7 @@ namespace Gui { class View3DInventorViewer; - +class AbstractSplitViewPy; /** The SplitView3DInventor class allows to create a window with two or more Inventor views. * \author Werner Mayer @@ -59,6 +59,7 @@ public: PyObject *getPyObject(void); void setPyObject(PyObject *); + int getSize(); protected: void setupSettings(); @@ -67,6 +68,7 @@ protected: /// handle to the viewer parameter group ParameterGrp::handle hGrp; std::vector _viewer; + PyObject *_viewerPy; }; class AbstractSplitViewPy : public Py::PythonExtension @@ -87,9 +89,15 @@ public: Py::Object viewRight(const Py::Tuple&); Py::Object viewTop(const Py::Tuple&); Py::Object viewAxometric(const Py::Tuple&); + Py::Object getViewer(const Py::Tuple&); + Py::Object sequence_item(ssize_t); + Py::Object close(const Py::Tuple&); + int sequence_length(); private: AbstractSplitView* _view; + friend class AbstractSplitView; + void testExistence(); }; /** The SplitView3DInventor class allows to create a window with two or more Inventor views. diff --git a/src/Gui/View3DViewerPy.cpp b/src/Gui/View3DViewerPy.cpp index fa239ca83..d5fc8e515 100644 --- a/src/Gui/View3DViewerPy.cpp +++ b/src/Gui/View3DViewerPy.cpp @@ -31,6 +31,8 @@ #include "View3DViewerPy.h" #include #include +#include +#include #include using namespace Gui; @@ -66,7 +68,7 @@ void View3DInventorViewerPy::init_type() ); add_varargs_method("setFocalDistance",&View3DInventorViewerPy::setFocalDistance,"setFocalDistance(float) -> None\n"); add_varargs_method("getFocalDistance",&View3DInventorViewerPy::getFocalDistance,"getFocalDistance() -> float\n"); - + add_varargs_method("getPoint", &View3DInventorViewerPy::getPoint, "getPoint(x, y) -> Base::Vector(x,y,z)"); } View3DInventorViewerPy::View3DInventorViewerPy(View3DInventorViewer *vi) @@ -258,3 +260,24 @@ Py::Object View3DInventorViewerPy::getFocalDistance(const Py::Tuple& args) throw Py::Exception("Unknown C++ exception"); } } + +Py::Object View3DInventorViewerPy::getPoint(const Py::Tuple& args) +{ + short x,y; + if (!PyArg_ParseTuple(args.ptr(), "hh", &x, &y)) { + PyErr_Clear(); + Py::Tuple t(args[0]); + x = (int)Py::Int(t[0]); + y = (int)Py::Int(t[1]); + } + try { + SbVec3f pt = _viewer->getPointOnScreen(SbVec2s(x,y)); + return Py::Vector(Base::Vector3f(pt[0], pt[1], pt[2])); + } + catch (const Base::Exception& e) { + throw Py::Exception(e.what()); + } + catch (const Py::Exception&) { + throw; + } +} diff --git a/src/Gui/View3DViewerPy.h b/src/Gui/View3DViewerPy.h index 3f9f0f3c7..1432cdac6 100644 --- a/src/Gui/View3DViewerPy.h +++ b/src/Gui/View3DViewerPy.h @@ -59,6 +59,8 @@ public: Py::Object seekToPoint(const Py::Tuple&); Py::Object setFocalDistance(const Py::Tuple& args); Py::Object getFocalDistance(const Py::Tuple& args); + Py::Object getPoint(const Py::Tuple& args); + private: