From 074c5187b02a04e97663e353f5152d713a2ddb80 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 12 Nov 2018 16:58:01 +0100 Subject: [PATCH] Adopt new WindowProperties(size=(x, y), ...) short-hand This is intended as replacement for WindowProperties.size(x, y), which is deprecated since it conflicts with the `size` property. See #444. --- dtool/src/interrogate/functionRemap.cxx | 9 +- makepanda/makepanda.py | 8 +- panda/src/display/p3display_ext_composite.cxx | 4 + panda/src/display/windowProperties.cxx | 2 + panda/src/display/windowProperties.h | 9 +- panda/src/display/windowProperties_ext.cxx | 82 +++++++++++++++++++ panda/src/display/windowProperties_ext.h | 37 +++++++++ samples/shadows/advanced.py | 2 +- 8 files changed, 142 insertions(+), 11 deletions(-) create mode 100644 panda/src/display/p3display_ext_composite.cxx create mode 100644 panda/src/display/windowProperties_ext.cxx create mode 100644 panda/src/display/windowProperties_ext.h diff --git a/dtool/src/interrogate/functionRemap.cxx b/dtool/src/interrogate/functionRemap.cxx index 9836a23bfc..fabbb8a311 100644 --- a/dtool/src/interrogate/functionRemap.cxx +++ b/dtool/src/interrogate/functionRemap.cxx @@ -960,8 +960,13 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak } else if (!_has_this && _parameters.size() > 0 && (_cppfunc->_storage_class & CPPInstance::SC_explicit) == 0) { - // A non-explicit non-copy constructor might be eligible for coercion. - _flags |= F_coerce_constructor; + // A non-explicit non-copy constructor might be eligible for coercion, + // as long as it does not require explicit keyword args. + if ((_flags & F_explicit_args) == 0 || + _args_type != InterfaceMaker::AT_keyword_args) { + + _flags |= F_coerce_constructor; + } } // Constructors always take varargs, and possibly keyword args. diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 895b306d38..736434fb92 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -3875,9 +3875,7 @@ if (not RUNTIME): IGATEFILES.remove("renderBuffer.h") TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES) TargetAdd('libp3display.in', opts=['IMOD:panda3d.core', 'ILIB:libp3display', 'SRCDIR:panda/src/display']) - PyTargetAdd('p3display_graphicsStateGuardian_ext.obj', opts=OPTS, input='graphicsStateGuardian_ext.cxx') - PyTargetAdd('p3display_graphicsWindow_ext.obj', opts=OPTS, input='graphicsWindow_ext.cxx') - PyTargetAdd('p3display_pythonGraphicsWindowProc.obj', opts=OPTS, input='pythonGraphicsWindowProc.cxx') + PyTargetAdd('p3display_ext_composite.obj', opts=OPTS, input='p3display_ext_composite.cxx') if RTDIST and GetTarget() == 'darwin': OPTS=['DIR:panda/src/display'] @@ -4277,9 +4275,7 @@ if (not RUNTIME): PyTargetAdd('core.pyd', input='p3event_pythonTask.obj') PyTargetAdd('core.pyd', input='p3gobj_ext_composite.obj') PyTargetAdd('core.pyd', input='p3pgraph_ext_composite.obj') - PyTargetAdd('core.pyd', input='p3display_graphicsStateGuardian_ext.obj') - PyTargetAdd('core.pyd', input='p3display_graphicsWindow_ext.obj') - PyTargetAdd('core.pyd', input='p3display_pythonGraphicsWindowProc.obj') + PyTargetAdd('core.pyd', input='p3display_ext_composite.obj') PyTargetAdd('core.pyd', input='core_module.obj') if not GetLinkAllStatic() and GetTarget() != 'emscripten': diff --git a/panda/src/display/p3display_ext_composite.cxx b/panda/src/display/p3display_ext_composite.cxx new file mode 100644 index 0000000000..b3147c4e3f --- /dev/null +++ b/panda/src/display/p3display_ext_composite.cxx @@ -0,0 +1,4 @@ +#include "graphicsStateGuardian_ext.cxx" +#include "graphicsWindow_ext.cxx" +#include "pythonGraphicsWindowProc.cxx" +#include "windowProperties_ext.cxx" diff --git a/panda/src/display/windowProperties.cxx b/panda/src/display/windowProperties.cxx index 93cd0a7144..3d6ebeb91b 100644 --- a/panda/src/display/windowProperties.cxx +++ b/panda/src/display/windowProperties.cxx @@ -135,6 +135,8 @@ clear_default() { /** * Returns a WindowProperties structure with only the size specified. The * size is the only property that matters to buffers. + * + * @deprecated in the Python API, use WindowProperties(size=(x, y)) instead. */ WindowProperties WindowProperties:: size(const LVecBase2i &size) { diff --git a/panda/src/display/windowProperties.h b/panda/src/display/windowProperties.h index 68ba4e7f1d..0d9b162c6c 100644 --- a/panda/src/display/windowProperties.h +++ b/panda/src/display/windowProperties.h @@ -27,6 +27,10 @@ * properties for a window after it has been opened. */ class EXPCL_PANDA_DISPLAY WindowProperties { +public: + WindowProperties(); + INLINE WindowProperties(const WindowProperties ©); + PUBLISHED: enum ZOrder { Z_bottom, @@ -40,8 +44,9 @@ PUBLISHED: M_confined, }; - WindowProperties(); - INLINE WindowProperties(const WindowProperties ©); + EXTENSION(WindowProperties(PyObject *self, PyObject *args, PyObject *kwds)); + +PUBLISHED: void operator = (const WindowProperties ©); INLINE ~WindowProperties(); diff --git a/panda/src/display/windowProperties_ext.cxx b/panda/src/display/windowProperties_ext.cxx new file mode 100644 index 0000000000..5c8a711415 --- /dev/null +++ b/panda/src/display/windowProperties_ext.cxx @@ -0,0 +1,82 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file windowProperties_ext.cxx + * @author rdb + * @date 2018-11-12 + */ + +#include "windowProperties_ext.h" + +#ifdef HAVE_PYTHON + +extern struct Dtool_PyTypedObject Dtool_WindowProperties; + +/** + * Creates a new WindowProperties initialized with the given properties. + */ +void Extension:: +__init__(PyObject *self, PyObject *args, PyObject *kwds) { + nassertv_always(_this != nullptr); + + // We need to initialize the self object before we can use it. + DtoolInstance_INIT_PTR(self, _this); + + // Support copy constructor by extracting the one positional argument. + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + if (nargs != 0) { + if (nargs != 1) { + PyErr_Format(PyExc_TypeError, + "WindowProperties() takes at most 1 positional argument (%d given)", + (int)nargs); + return; + } + + PyObject *arg = PyTuple_GET_ITEM(args, 0); + const WindowProperties *copy_from; + if (DtoolInstance_GetPointer(arg, copy_from, Dtool_WindowProperties)) { + *_this = *copy_from; + } else { + Dtool_Raise_ArgTypeError(arg, 0, "WindowProperties", "WindowProperties"); + return; + } + } + + // Now iterate over the keyword arguments, which define the default values + // for the different properties. + if (kwds != nullptr) { + PyTypeObject *type = Py_TYPE(self); + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(kwds, &pos, &key, &value)) { + // Look for a writable property on the type by this name. + PyObject *descr = _PyType_Lookup(type, key); + + if (descr != nullptr && Py_TYPE(descr)->tp_descr_set != nullptr) { + if (Py_TYPE(descr)->tp_descr_set(descr, self, value) < 0) { + return; + } + } else { + PyObject *key_repr = PyObject_Repr(key); + PyErr_Format(PyExc_TypeError, + "%.100s is an invalid keyword argument for WindowProperties()", +#if PY_MAJOR_VERSION >= 3 + PyUnicode_AsUTF8(key_repr) +#else + PyString_AsString(key_repr) +#endif + ); + Py_DECREF(key_repr); + return; + } + } + } +} + +#endif // HAVE_PYTHON diff --git a/panda/src/display/windowProperties_ext.h b/panda/src/display/windowProperties_ext.h new file mode 100644 index 0000000000..093bd49036 --- /dev/null +++ b/panda/src/display/windowProperties_ext.h @@ -0,0 +1,37 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file windowProperties_ext.h + * @author rdb + * @date 2018-11-12 + */ + +#ifndef WINDOWPROPERTIES_EXT_H +#define WINDOWPROPERTIES_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "windowProperties.h" +#include "py_panda.h" + +/** + * This class defines the extension methods for WindowProperties, which are + * called instead of any C++ methods with the same prototype. + */ +template<> +class Extension : public ExtensionBase { +public: + void __init__(PyObject *self, PyObject *args, PyObject *kwds); +}; + +#endif // HAVE_PYTHON + +#endif // WINDOWPROPERTIES_EXT_H diff --git a/samples/shadows/advanced.py b/samples/shadows/advanced.py index e11ed2645a..4091192d00 100755 --- a/samples/shadows/advanced.py +++ b/samples/shadows/advanced.py @@ -40,7 +40,7 @@ class World(DirectObject): # creating the offscreen buffer. - winprops = WindowProperties.size(512, 512) + winprops = WindowProperties(size=(512, 512)) props = FrameBufferProperties() props.setRgbColor(1) props.setAlphaBits(1)