From 44884ecaf70ffb347d81832d08553a8752e4ec19 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Sat, 19 Aug 2023 21:44:03 -0300 Subject: [PATCH] Gui: Change SoQtOffscreenRendererPy to new PyCXX extension type --- src/Gui/Application.cpp | 2 +- src/Gui/CMakeLists.txt | 2 + src/Gui/SoFCOffscreenRenderer.cpp | 177 ------------------------- src/Gui/SoFCOffscreenRenderer.h | 35 ----- src/Gui/SoQtOffscreenRendererPy.cpp | 199 ++++++++++++++++++++++++++++ src/Gui/SoQtOffscreenRendererPy.h | 66 +++++++++ 6 files changed, 268 insertions(+), 213 deletions(-) create mode 100644 src/Gui/SoQtOffscreenRendererPy.cpp create mode 100644 src/Gui/SoQtOffscreenRendererPy.h diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 971a2e4c83..2bdf781c7a 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -84,7 +84,7 @@ #include "SoFCDB.h" #include "Selection.h" #include "SelectionFilterPy.h" -#include "SoFCOffscreenRenderer.h" +#include "SoQtOffscreenRendererPy.h" #include "SplitView3DInventor.h" #include "TaskView/TaskView.h" #include "TaskView/TaskDialogPython.h" diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 0b62b44fdc..bd08153797 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -968,6 +968,7 @@ SET(Inventor_CPP_SRCS SoFCDB.cpp SoFCInteractiveElement.cpp SoFCOffscreenRenderer.cpp + SoQtOffscreenRendererPy.cpp SoFCSelection.cpp SoFCUnifiedSelection.cpp SoFCSelectionContext.cpp @@ -996,6 +997,7 @@ SET(Inventor_SRCS SoFCDB.h SoFCInteractiveElement.h SoFCOffscreenRenderer.h + SoQtOffscreenRendererPy.h SoFCSelection.h SoFCUnifiedSelection.h SoFCSelectionContext.h diff --git a/src/Gui/SoFCOffscreenRenderer.cpp b/src/Gui/SoFCOffscreenRenderer.cpp index 1771a4be29..eae9667c6f 100644 --- a/src/Gui/SoFCOffscreenRenderer.cpp +++ b/src/Gui/SoFCOffscreenRenderer.cpp @@ -749,180 +749,3 @@ QStringList SoQtOffscreenRenderer::getWriteImageFiletypeInfo() const #undef PRIVATE #undef PUBLIC - -// --------------------------------------------------------------- - -void SoQtOffscreenRendererPy::init_type() -{ - behaviors().name("SoQtOffscreenRenderer"); - behaviors().doc("Python interface for SoQtOffscreenRenderer"); - behaviors().set_tp_new(PyMake); - - // you must have overwritten the virtual functions - behaviors().supportRepr(); - behaviors().supportGetattr(); - behaviors().supportSetattr(); - behaviors().readyType(); - - add_varargs_method("setViewportRegion",&SoQtOffscreenRendererPy::setViewportRegion,"setViewportRegion(int, int)"); - add_varargs_method("getViewportRegion",&SoQtOffscreenRendererPy::getViewportRegion,"getViewportRegion() -> tuple"); - add_varargs_method("setBackgroundColor",&SoQtOffscreenRendererPy::setBackgroundColor,"setBackgroundColor(float, float, float, [float])"); - add_varargs_method("getBackgroundColor",&SoQtOffscreenRendererPy::getBackgroundColor,"getBackgroundColor() -> tuple"); - add_varargs_method("setNumPasses",&SoQtOffscreenRendererPy::setNumPasses,"setNumPasses(int)"); - add_varargs_method("getNumPasses",&SoQtOffscreenRendererPy::getNumPasses,"getNumPasses() -> int"); - add_varargs_method("setInternalTextureFormat",&SoQtOffscreenRendererPy::setInternalTextureFormat,"setInternalTextureFormat(int)"); - add_varargs_method("getInternalTextureFormat",&SoQtOffscreenRendererPy::getInternalTextureFormat,"getInternalTextureFormat() -> int"); - add_varargs_method("render",&SoQtOffscreenRendererPy::render,"render(node)"); - add_varargs_method("writeToImage",&SoQtOffscreenRendererPy::writeToImage,"writeToImage(string)"); - add_varargs_method("getWriteImageFiletypeInfo",&SoQtOffscreenRendererPy::getWriteImageFiletypeInfo,"getWriteImageFiletypeInfo() -> tuple"); -} - -PyObject *SoQtOffscreenRendererPy::PyMake(struct _typeobject * /*type*/, PyObject * args, PyObject * /*kwds*/) -{ - short w, h; - if (!PyArg_ParseTuple(args, "hh", &w, &h)) - return nullptr; - - return new SoQtOffscreenRendererPy(SbViewportRegion(w, h)); -} - -SoQtOffscreenRendererPy::SoQtOffscreenRendererPy(const SbViewportRegion& vpr) - : renderer(vpr) -{ -} - -SoQtOffscreenRendererPy::~SoQtOffscreenRendererPy() -{ -} - -Py::Object SoQtOffscreenRendererPy::repr() -{ - std::stringstream s; - s << ""; - return Py::String(s.str()); -} - -Py::Object SoQtOffscreenRendererPy::setViewportRegion(const Py::Tuple& args) -{ - short w, h; - if (!PyArg_ParseTuple(args.ptr(), "hh", &w, &h)) - throw Py::Exception(); - - renderer.setViewportRegion(SbViewportRegion(w, h)); - return Py::None(); -} - -Py::Object SoQtOffscreenRendererPy::getViewportRegion(const Py::Tuple& args) -{ - if (!PyArg_ParseTuple(args.ptr(), "")) - throw Py::Exception(); - - const SbViewportRegion& vpr = renderer.getViewportRegion(); - SbVec2s size = vpr.getWindowSize(); - return Py::TupleN(Py::Long(size[0]), Py::Long(size[1])); -} - -Py::Object SoQtOffscreenRendererPy::setBackgroundColor(const Py::Tuple& args) -{ - float r, g, b, a = 1.0f; - if (!PyArg_ParseTuple(args.ptr(), "fff|f", &r, &g, &b, &a)) - throw Py::Exception(); - - renderer.setBackgroundColor(SbColor4f(r, g, b, a)); - return Py::None(); -} - -Py::Object SoQtOffscreenRendererPy::getBackgroundColor(const Py::Tuple& args) -{ - if (!PyArg_ParseTuple(args.ptr(), "")) - throw Py::Exception(); - - SbColor4f color = renderer.getBackgroundColor(); - return Py::TupleN(Py::Float(color[0]), Py::Float(color[1]), Py::Float(color[2]), Py::Float(color[3])); -} - -Py::Object SoQtOffscreenRendererPy::setNumPasses(const Py::Tuple& args) -{ - int num; - if (!PyArg_ParseTuple(args.ptr(), "i", &num)) - throw Py::Exception(); - - renderer.setNumPasses(num); - return Py::None(); -} - -Py::Object SoQtOffscreenRendererPy::getNumPasses(const Py::Tuple& args) -{ - if (!PyArg_ParseTuple(args.ptr(), "")) - throw Py::Exception(); - - int num = renderer.getNumPasses(); - return Py::Long(num); -} - -Py::Object SoQtOffscreenRendererPy::setInternalTextureFormat(const Py::Tuple& args) -{ - unsigned int format; - if (!PyArg_ParseTuple(args.ptr(), "I", &format)) - throw Py::Exception(); - - renderer.setInternalTextureFormat(format); - return Py::None(); -} - -Py::Object SoQtOffscreenRendererPy::getInternalTextureFormat(const Py::Tuple& args) -{ - if (!PyArg_ParseTuple(args.ptr(), "")) - throw Py::Exception(); - - unsigned long format = renderer.internalTextureFormat(); - return Py::Long(format); -} - -Py::Object SoQtOffscreenRendererPy::render(const Py::Tuple& args) -{ - PyObject* proxy; - if (!PyArg_ParseTuple(args.ptr(), "O", &proxy)) - throw Py::Exception(); - - try { - void* ptr = nullptr; - Base::Interpreter().convertSWIGPointerObj("pivy.coin", "SoNode *", proxy, &ptr, 0); - auto node = static_cast(ptr); - bool ok = false; - if (node) { - ok = renderer.render(node); - } - return Py::Boolean(ok); - } - catch (const Base::Exception& e) { - e.setPyException(); - throw Py::Exception(); - } -} - -Py::Object SoQtOffscreenRendererPy::writeToImage(const Py::Tuple& args) -{ - const char* filename; - if (!PyArg_ParseTuple(args.ptr(), "s", &filename)) - throw Py::Exception(); - - QImage img; - renderer.writeToImage(img); - img.save(QString::fromUtf8(filename)); - return Py::None(); -} - -Py::Object SoQtOffscreenRendererPy::getWriteImageFiletypeInfo(const Py::Tuple& args) -{ - if (!PyArg_ParseTuple(args.ptr(), "")) - throw Py::Exception(); - - QStringList list = renderer.getWriteImageFiletypeInfo(); - Py::Tuple tuple(list.size()); - for (int i = 0; i < list.size(); i++) { - tuple.setItem(i, Py::String(list[i].toStdString())); - } - - return tuple; -} diff --git a/src/Gui/SoFCOffscreenRenderer.h b/src/Gui/SoFCOffscreenRenderer.h index 844c641e4a..f72176b1a2 100644 --- a/src/Gui/SoFCOffscreenRenderer.h +++ b/src/Gui/SoFCOffscreenRenderer.h @@ -31,7 +31,6 @@ #include #include -#include #include @@ -150,40 +149,6 @@ private: QImage glImage; }; -class SoQtOffscreenRendererPy : public Py::PythonExtension -{ -public: - static void init_type(); - - explicit SoQtOffscreenRendererPy(const SbViewportRegion&); - ~SoQtOffscreenRendererPy() override; - - Py::Object repr() override; - - Py::Object setViewportRegion(const Py::Tuple&); - Py::Object getViewportRegion(const Py::Tuple&); - - Py::Object setBackgroundColor(const Py::Tuple&); - Py::Object getBackgroundColor(const Py::Tuple&); - - Py::Object setNumPasses(const Py::Tuple&); - Py::Object getNumPasses(const Py::Tuple&); - - Py::Object setInternalTextureFormat(const Py::Tuple&); - Py::Object getInternalTextureFormat(const Py::Tuple&); - - Py::Object render(const Py::Tuple&); - - Py::Object writeToImage(const Py::Tuple&); - Py::Object getWriteImageFiletypeInfo(const Py::Tuple&); - -private: - static PyObject *PyMake(struct _typeobject *, PyObject *, PyObject *); - -private: - SoQtOffscreenRenderer renderer; -}; - } // namespace Gui diff --git a/src/Gui/SoQtOffscreenRendererPy.cpp b/src/Gui/SoQtOffscreenRendererPy.cpp new file mode 100644 index 0000000000..faa23fbb7e --- /dev/null +++ b/src/Gui/SoQtOffscreenRendererPy.cpp @@ -0,0 +1,199 @@ +/*************************************************************************** + * Copyright (c) 2022 Werner Mayer * + * * + * 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 "SoQtOffscreenRendererPy.h" + + +using namespace Gui; + +SoQtOffscreenRendererPy::SoQtOffscreenRendererPy(Py::PythonClassInstance* self, Py::Tuple& args, Py::Dict& kwds) + : Py::PythonClass(self, args, kwds), renderer(SbViewportRegion()) +{ + this->setViewportRegion(args); +} + +SoQtOffscreenRendererPy::~SoQtOffscreenRendererPy() +{ +} + +Py::Object SoQtOffscreenRendererPy::repr() +{ + std::stringstream s; + s << ""; + return Py::String(s.str()); +} + +Py::Object SoQtOffscreenRendererPy::setViewportRegion(const Py::Tuple& args) +{ + short w, h; + if (!PyArg_ParseTuple(args.ptr(), "hh", &w, &h)) { + throw Py::Exception(); + } + + renderer.setViewportRegion(SbViewportRegion(w, h)); + return Py::None(); +} +PYCXX_VARARGS_METHOD_DECL(SoQtOffscreenRendererPy, setViewportRegion) + +Py::Object SoQtOffscreenRendererPy::getViewportRegion() +{ + const SbViewportRegion& vpr = renderer.getViewportRegion(); + SbVec2s size = vpr.getWindowSize(); + + return Py::TupleN(Py::Long(size[0]), Py::Long(size[1])); +} +PYCXX_NOARGS_METHOD_DECL(SoQtOffscreenRendererPy, getViewportRegion) + +Py::Object SoQtOffscreenRendererPy::setBackgroundColor(const Py::Tuple& args) +{ + float r, g, b, a = 1.0f; + if (!PyArg_ParseTuple(args.ptr(), "fff|f", &r, &g, &b, &a)) { + throw Py::Exception(); + } + + renderer.setBackgroundColor(SbColor4f(r, g, b, a)); + + return Py::None(); +} +PYCXX_VARARGS_METHOD_DECL(SoQtOffscreenRendererPy, setBackgroundColor) + +Py::Object SoQtOffscreenRendererPy::getBackgroundColor() +{ + SbColor4f color = renderer.getBackgroundColor(); + return Py::TupleN(Py::Float(color[0]), Py::Float(color[1]), Py::Float(color[2]), Py::Float(color[3])); +} +PYCXX_NOARGS_METHOD_DECL(SoQtOffscreenRendererPy, getBackgroundColor) + +Py::Object SoQtOffscreenRendererPy::setNumPasses(const Py::Tuple& args) +{ + int num; + if (!PyArg_ParseTuple(args.ptr(), "i", &num)) { + throw Py::Exception(); + } + + renderer.setNumPasses(num); + + return Py::None(); +} +PYCXX_VARARGS_METHOD_DECL(SoQtOffscreenRendererPy, setNumPasses) + +Py::Object SoQtOffscreenRendererPy::getNumPasses() +{ + return Py::Long(renderer.getNumPasses()); +} +PYCXX_NOARGS_METHOD_DECL(SoQtOffscreenRendererPy, getNumPasses) + +Py::Object SoQtOffscreenRendererPy::setInternalTextureFormat(const Py::Tuple& args) +{ + unsigned int format; + if (!PyArg_ParseTuple(args.ptr(), "I", &format)) { + throw Py::Exception(); + } + + renderer.setInternalTextureFormat(format); + + return Py::None(); +} +PYCXX_VARARGS_METHOD_DECL(SoQtOffscreenRendererPy, setInternalTextureFormat) + +Py::Object SoQtOffscreenRendererPy::getInternalTextureFormat() +{ + return Py::Long(static_cast(renderer.internalTextureFormat())); +} +PYCXX_NOARGS_METHOD_DECL(SoQtOffscreenRendererPy, getInternalTextureFormat) + +Py::Object SoQtOffscreenRendererPy::render(const Py::Tuple& args) +{ + PyObject* proxy; + if (!PyArg_ParseTuple(args.ptr(), "O", &proxy)) { + throw Py::Exception(); + } + + try { + void* ptr = nullptr; + Base::Interpreter().convertSWIGPointerObj("pivy.coin", "SoNode *", proxy, &ptr, 0); + auto node = static_cast(ptr); + bool ok = false; + if (node) { + ok = renderer.render(node); + } + return Py::Boolean(ok); + } + catch (const Base::Exception& e) { + e.setPyException(); + throw Py::Exception(); + } +} +PYCXX_VARARGS_METHOD_DECL(SoQtOffscreenRendererPy, render) + +Py::Object SoQtOffscreenRendererPy::writeToImage(const Py::Tuple& args) +{ + const char* filename; + if (!PyArg_ParseTuple(args.ptr(), "s", &filename)) { + throw Py::Exception(); + } + + QImage img; + renderer.writeToImage(img); + img.save(QString::fromUtf8(filename)); + + return Py::None(); +} +PYCXX_VARARGS_METHOD_DECL(SoQtOffscreenRendererPy, writeToImage) + +Py::Object SoQtOffscreenRendererPy::getWriteImageFiletypeInfo() +{ + QStringList list = renderer.getWriteImageFiletypeInfo(); + Py::Tuple tuple(list.size()); + int index = 0; + for (const auto& item : list) { + tuple[index++] = Py::String(item.toStdString()); + } + + return tuple; +} +PYCXX_NOARGS_METHOD_DECL(SoQtOffscreenRendererPy, getWriteImageFiletypeInfo) + +void SoQtOffscreenRendererPy::init_type() +{ + behaviors().name("Gui.SoQtOffscreenRenderer"); + behaviors().doc("Python interface for SoQtOffscreenRenderer"); + + // you must have overwritten the virtual functions + behaviors().supportRepr(); + + PYCXX_ADD_VARARGS_METHOD(setViewportRegion, setViewportRegion, "setViewportRegion(int, int)"); + PYCXX_ADD_NOARGS_METHOD(getViewportRegion, getViewportRegion, "getViewportRegion() -> tuple"); + PYCXX_ADD_VARARGS_METHOD(setBackgroundColor, setBackgroundColor, "setBackgroundColor(float, float, float, [float])"); + PYCXX_ADD_NOARGS_METHOD(getBackgroundColor, getBackgroundColor, "getBackgroundColor() -> tuple"); + PYCXX_ADD_VARARGS_METHOD(setNumPasses, setNumPasses, "setNumPasses(int)"); + PYCXX_ADD_NOARGS_METHOD(getNumPasses, getNumPasses, "getNumPasses() -> int"); + PYCXX_ADD_VARARGS_METHOD(setInternalTextureFormat, setInternalTextureFormat, "setInternalTextureFormat(int)"); + PYCXX_ADD_NOARGS_METHOD(getInternalTextureFormat, getInternalTextureFormat, "getInternalTextureFormat() -> int"); + PYCXX_ADD_VARARGS_METHOD(render, render, "render(node)"); + PYCXX_ADD_VARARGS_METHOD(writeToImage, writeToImage, "writeToImage(string)"); + PYCXX_ADD_NOARGS_METHOD(getWriteImageFiletypeInfo, getWriteImageFiletypeInfo, "getWriteImageFiletypeInfo() -> tuple"); + + behaviors().readyType(); +} diff --git a/src/Gui/SoQtOffscreenRendererPy.h b/src/Gui/SoQtOffscreenRendererPy.h new file mode 100644 index 0000000000..90384835a0 --- /dev/null +++ b/src/Gui/SoQtOffscreenRendererPy.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (c) 2022 Werner Mayer * + * * + * 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 * + * * + ***************************************************************************/ + +#ifndef GUI_SOQTOFFSCREENRENDERERPY_H +#define GUI_SOQTOFFSCREENRENDERERPY_H + +#include + +#include "SoFCOffscreenRenderer.h" + + +namespace Gui { + +class SoQtOffscreenRendererPy : public Py::PythonClass +{ +public: + static void init_type(); + + SoQtOffscreenRendererPy(Py::PythonClassInstance* self, Py::Tuple& args, Py::Dict& kwds); + ~SoQtOffscreenRendererPy() override; + + Py::Object repr() override; + + Py::Object setViewportRegion(const Py::Tuple&); + Py::Object getViewportRegion(); + + Py::Object setBackgroundColor(const Py::Tuple&); + Py::Object getBackgroundColor(); + + Py::Object setNumPasses(const Py::Tuple&); + Py::Object getNumPasses(); + + Py::Object setInternalTextureFormat(const Py::Tuple&); + Py::Object getInternalTextureFormat(); + + Py::Object render(const Py::Tuple&); + + Py::Object writeToImage(const Py::Tuple&); + Py::Object getWriteImageFiletypeInfo(); + +private: + SoQtOffscreenRenderer renderer; +}; + +} // namespace Gui + +#endif // GUI_SOQTOFFSCREENRENDERERPY_H