/**************************************************************************** * Copyright (c) 2017 Zheng Lei (realthunder) * * * * 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 #include #include #include #include "LinkViewPy.h" #include "LinkViewPy.cpp" #include "ViewProviderDocumentObjectPy.h" using namespace Gui; PyObject* LinkViewPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { return new LinkViewPy(new LinkView); } int LinkViewPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) { return 0; } // returns a string which represent the object e.g. when printed in python std::string LinkViewPy::representation() const { return ""; } PyObject* LinkViewPy::reset(PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; } PY_TRY { auto lv = getLinkViewPtr(); lv->setSize(0); lv->setLink(nullptr); Py_Return; } PY_CATCH; } PyObject* LinkViewPy::setMaterial(PyObject* args) { PyObject* pyObj; if (!PyArg_ParseTuple(args, "O", &pyObj)) { return nullptr; } PY_TRY { auto lv = getLinkViewPtr(); if (pyObj == Py_None) { lv->setMaterial(-1, nullptr); Py_Return; } if (PyObject_TypeCheck(pyObj, &App::MaterialPy::Type)) { lv->setMaterial(-1, static_cast(pyObj)->getMaterialPtr()); Py_Return; } if (PyDict_Check(pyObj)) { PyObject *key, *value; Py_ssize_t pos = 0; std::map materials; while (PyDict_Next(pyObj, &pos, &key, &value)) { Py::Long idx(key); if (value == Py_None) { materials[(int)idx] = nullptr; } else if (!PyObject_TypeCheck(value, &App::MaterialPy::Type)) { PyErr_SetString(PyExc_TypeError, "exepcting a type of material"); return nullptr; } else { materials[(int)idx] = static_cast(value)->getMaterialPtr(); } } for (auto& v : materials) { lv->setMaterial(v.first, v.second); } Py_Return; } if (PySequence_Check(pyObj)) { Py::Sequence seq(pyObj); std::vector materials; materials.resize(seq.size(), nullptr); for (Py_ssize_t i = 0; i < seq.size(); ++i) { PyObject* item = seq[i].ptr(); if (item == Py_None) { continue; } if (!PyObject_TypeCheck(item, &App::MaterialPy::Type)) { PyErr_SetString(PyExc_TypeError, "exepcting a type of material"); return nullptr; } materials[i] = static_cast(item)->getMaterialPtr(); } for (size_t i = 0; i < materials.size(); ++i) { lv->setMaterial(i, materials[i]); } Py_Return; } PyErr_SetString( PyExc_TypeError, "exepcting a type of Material, [Material,...] or {Int:Material,}" ); return nullptr; } PY_CATCH; } PyObject* LinkViewPy::setTransform(PyObject* args) { PyObject* pyObj; if (!PyArg_ParseTuple(args, "O", &pyObj)) { return nullptr; } PY_TRY { auto lv = getLinkViewPtr(); if (PyObject_TypeCheck(pyObj, &Base::MatrixPy::Type)) { lv->setTransform(-1, *static_cast(pyObj)->getMatrixPtr()); Py_Return; } if (PyDict_Check(pyObj)) { PyObject *key, *value; Py_ssize_t pos = 0; std::map mat; while (PyDict_Next(pyObj, &pos, &key, &value)) { Py::Long idx(key); if (!PyObject_TypeCheck(value, &Base::MatrixPy::Type)) { PyErr_SetString(PyExc_TypeError, "exepcting a type of Matrix"); return nullptr; } else { mat[(int)idx] = static_cast(value)->getMatrixPtr(); } } for (auto& v : mat) { lv->setTransform(v.first, *v.second); } Py_Return; } if (PySequence_Check(pyObj)) { Py::Sequence seq(pyObj); std::vector mat; mat.resize(seq.size(), nullptr); for (Py_ssize_t i = 0; i < seq.size(); ++i) { PyObject* item = seq[i].ptr(); if (!PyObject_TypeCheck(item, &Base::MatrixPy::Type)) { PyErr_SetString(PyExc_TypeError, "exepcting a type of Matrix"); return nullptr; } mat[i] = static_cast(item)->getMatrixPtr(); } for (size_t i = 0; i < mat.size(); ++i) { lv->setTransform(i, *mat[i]); } Py_Return; } PyErr_SetString(PyExc_TypeError, "exepcting a type of Matrix, [Matrix,...] or {Int:Matrix,...}"); return nullptr; } PY_CATCH; } PyObject* LinkViewPy::setType(PyObject* args) { short type; PyObject* sublink = Py_True; if (!PyArg_ParseTuple(args, "h|O!", &type, &PyBool_Type, &sublink)) { return nullptr; } PY_TRY { getLinkViewPtr()->setNodeType((LinkView::SnapshotType)type, Base::asBoolean(sublink)); Py_Return; } PY_CATCH; } PyObject* LinkViewPy::setChildren(PyObject* args) { PyObject* pyObj; PyObject* pyVis = Py_None; short type = 0; if (!PyArg_ParseTuple(args, "O|Os", &pyObj, &pyVis, &type)) { return nullptr; } PY_TRY { App::PropertyBoolList vis; App::PropertyLinkList links; if (pyObj != Py_None) { links.setPyObject(pyObj); } if (pyVis != Py_None) { vis.setPyObject(pyVis); } getLinkViewPtr()->setChildren( links.getValue(), vis.getValue(), static_cast(type) ); Py_Return; } PY_CATCH; } PyObject* LinkViewPy::setLink(PyObject* args) { PyObject* pyObj; PyObject* pySubName = Py_None; if (!PyArg_ParseTuple(args, "O|O", &pyObj, &pySubName)) { return nullptr; } PY_TRY { ViewProviderDocumentObject* vpd = nullptr; App::DocumentObject* obj = nullptr; if (pyObj != Py_None) { if (PyObject_TypeCheck(pyObj, &App::DocumentObjectPy::Type)) { obj = static_cast(pyObj)->getDocumentObjectPtr(); } else if (PyObject_TypeCheck(pyObj, &ViewProviderDocumentObjectPy::Type)) { vpd = static_cast(pyObj) ->getViewProviderDocumentObjectPtr(); } else { PyErr_SetString( PyExc_TypeError, "exepcting a type of DocumentObject or ViewProviderDocumentObject" ); return nullptr; } } // Too lazy to parse the argument... App::PropertyStringList prop; if (pySubName != Py_None) { prop.setPyObject(pySubName); } if (obj) { getLinkViewPtr()->setLink(obj, prop.getValue()); } else { getLinkViewPtr()->setLinkViewObject(vpd, prop.getValue()); } Py_Return; } PY_CATCH; } Py::Object LinkViewPy::getOwner() const { auto owner = getLinkViewPtr()->getOwner(); if (!owner) { return Py::Object(); } return Py::Object(owner->getPyObject(), true); } void LinkViewPy::setOwner(Py::Object owner) { ViewProviderDocumentObject* vp = nullptr; if (!owner.isNone()) { if (!PyObject_TypeCheck(owner.ptr(), &ViewProviderDocumentObjectPy::Type)) { throw Py::TypeError("exepcting the owner to be of ViewProviderDocumentObject"); } vp = static_cast(owner.ptr())->getViewProviderDocumentObjectPtr(); } getLinkViewPtr()->setOwner(vp); } Py::Object LinkViewPy::getLinkedView() const { auto linked = getLinkViewPtr()->getLinkedView(); if (!linked) { return Py::Object(); } return Py::Object(linked->getPyObject(), true); } Py::Object LinkViewPy::getSubNames() const { const auto& subs = getLinkViewPtr()->getSubNames(); if (subs.empty()) { return Py::Object(); } Py::Tuple ret(subs.size()); int i = 0; for (auto& s : subs) { ret.setItem(i++, Py::String(s.c_str())); } return ret; } PyObject* LinkViewPy::getElementPicked(PyObject* args) { PyObject* obj; if (!PyArg_ParseTuple(args, "O", &obj)) { return nullptr; } void* ptr = nullptr; Base::Interpreter().convertSWIGPointerObj("pivy.coin", "SoPickedPoint *", obj, &ptr, 0); auto pp = static_cast(ptr); if (!pp) { throw Py::TypeError("type must be of coin.SoPickedPoint"); } PY_TRY { std::string name; if (!getLinkViewPtr()->linkGetElementPicked(pp, name)) { Py_Return; } return Py::new_reference_to(Py::String(name)); } PY_CATCH } PyObject* LinkViewPy::getDetailPath(PyObject* args) { const char* sub; PyObject* path; if (!PyArg_ParseTuple(args, "sO", &sub, &path)) { return nullptr; } void* ptr = nullptr; Base::Interpreter().convertSWIGPointerObj("pivy.coin", "SoPath *", path, &ptr, 0); auto pPath = static_cast(ptr); if (!pPath) { throw Py::TypeError("type must be of coin.SoPath"); } PY_TRY { SoDetail* det = nullptr; getLinkViewPtr()->linkGetDetailPath(sub, static_cast(pPath), det); if (!det) { Py_Return; } return Base::Interpreter() .createSWIGPointerObj("pivy.coin", "SoDetail *", static_cast(det), 0); } PY_CATCH } PyObject* LinkViewPy::getBoundBox(PyObject* args) { PyObject* vobj = Py_None; if (!PyArg_ParseTuple(args, "O", &vobj)) { return nullptr; } PY_TRY { Base::PyTypeCheck(&vobj, &ViewProviderDocumentObjectPy::Type); ViewProviderDocumentObject* vpd = nullptr; if (vobj) { vpd = static_cast(vobj)->getViewProviderDocumentObjectPtr(); } auto bbox = getLinkViewPtr()->getBoundBox(vpd); Py::Object ret(new Base::BoundBoxPy(new Base::BoundBox3d(bbox))); return Py::new_reference_to(ret); } PY_CATCH } PyObject* LinkViewPy::getCustomAttributes(const char*) const { return nullptr; } int LinkViewPy::setCustomAttributes(const char*, PyObject*) { return 0; } Py::Object LinkViewPy::getRootNode() const { try { SoNode* node = getLinkViewPtr()->getLinkRoot(); PyObject* Ptr = Base::Interpreter().createSWIGPointerObj("pivy.coin", "SoSeparator *", node, 1); node->ref(); return Py::Object(Ptr, true); } catch (const Base::Exception& e) { throw Py::RuntimeError(e.what()); } } Py::Object LinkViewPy::getVisibilities() const { auto linked = getLinkViewPtr(); if (!linked->getSize()) { return Py::Object(); } Py::Tuple ret(linked->getSize()); for (int i = 0; i < linked->getSize(); ++i) { ret.setItem(i, Py::Boolean(linked->isElementVisible(i))); } return ret; } void LinkViewPy::setVisibilities(Py::Object value) { App::PropertyBoolList v; if (!value.isNone()) { v.setPyObject(value.ptr()); } auto linked = getLinkViewPtr(); const auto& vis = v.getValue(); for (int i = 0; i < linked->getSize(); ++i) { linked->setElementVisible(i, i >= (int)vis.size() || vis[i]); } } PyObject* LinkViewPy::getChildren(PyObject* args) const { if (!PyArg_ParseTuple(args, "")) { return nullptr; } auto children = getLinkViewPtr()->getChildren(); if (children.empty()) { Py_Return; } Py::Tuple ret(children.size()); int i = 0; for (auto vp : children) { ret.setItem(i++, Py::Object(vp->getPyObject(), true)); } return Py::new_reference_to(ret); } Py::Long LinkViewPy::getCount() const { return Py::Long(getLinkViewPtr()->getSize()); } void LinkViewPy::setCount(Py::Long count) { try { getLinkViewPtr()->setSize((int)count); } catch (const Base::Exception& e) { throw Py::RuntimeError(e.what()); } }