diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 7b9aa8487a..9f8820ffee 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -4389,57 +4389,6 @@ write_function_forset(ostream &out, std::sort(remaps.begin(), remaps.end(), RemapCompareLess); std::vector::const_iterator sii; - // Check if all of them have an InternalName pointer as first parameter. - // This is a dirty hack, of course, to work around an awkward overload - // resolution problem in NodePath::set_shader_input() (while perhaps also - // improving its performance). If I had more time I'd create a better - // solution. - bool first_internalname = false; - string first_pexpr2(first_pexpr); - if (first_pexpr.empty() && args_type != AT_no_args) { - first_internalname = true; - - for (sii = remaps.begin(); sii != remaps.end(); ++sii) { - remap = (*sii); - if (remap->_parameters.size() > (size_t)remap->_has_this) { - ParameterRemap *param = remap->_parameters[(size_t)remap->_has_this]._remap; - string param_name = param->get_orig_type()->get_local_name(&parser); - - if (param_name != "CPT_InternalName" && - param_name != "InternalName const *" && - param_name != "InternalName *") { - // Aw. - first_internalname = false; - break; - } - } else { - first_internalname = false; - break; - } - } - if (first_internalname) { - // Yeah, all remaps have a first InternalName parameter, so process - // that and remove it from the args tuple. - if (args_type == AT_single_arg) { - // Bit of a weird case, but whatever. - indent(out, indent_level) << "PyObject *name_obj = arg;\n"; - args_type = AT_no_args; - } else if (min_num_args == 2 && max_num_args == 2) { - indent(out, indent_level) << "PyObject *name_obj = PyTuple_GET_ITEM(args, 0);\n"; - indent(out, indent_level) << "PyObject *arg = PyTuple_GET_ITEM(args, 1);\n"; - args_type = AT_single_arg; - } else { - indent(out, indent_level) << "PyObject *name_obj = PyTuple_GET_ITEM(args, 0);\n"; - indent(out, indent_level) << "args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));\n"; - return_flags |= RF_decref_args; - } - indent(out, indent_level) << "PT(InternalName) name;\n"; - indent(out, indent_level) << "if (Dtool_Coerce_InternalName(name_obj, name)) {\n"; - indent_level += 2; - first_pexpr2 = "name"; - } - } - int num_coercion_possible = 0; sii = remaps.begin(); while (sii != remaps.end()) { @@ -4474,7 +4423,7 @@ write_function_forset(ostream &out, write_function_instance(out, remap, min_num_args, max_num_args, expected_params, indent_level + 2, false, false, args_type, return_flags, - check_exceptions, first_pexpr2); + check_exceptions, first_pexpr); indent(out, indent_level) << "}\n\n"; } @@ -4507,28 +4456,11 @@ write_function_forset(ostream &out, write_function_instance(out, remap, min_num_args, max_num_args, ignore_expected_params, indent_level + 2, true, false, args_type, return_flags, - check_exceptions, first_pexpr2); + check_exceptions, first_pexpr); indent(out, indent_level) << "}\n\n"; } } - - if (first_internalname) { - indent_level -= 2; - if (report_errors) { - indent(out, indent_level) << "} else {\n"; - - string class_name = remap->_cpptype->get_simple_name(); - ostringstream msg; - msg << classNameFromCppName(class_name, false) << "." - << methodNameFromCppName(remap, class_name, false) - << "() first argument must be str or InternalName"; - - error_raise_return(out, indent_level + 2, return_flags, - "TypeError", msg.str()); - } - indent(out, indent_level) << "}\n"; - } } else { // There is only one possible overload with this number of parameters. // Just call it. diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index e6eaca10cd..85eb068d55 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -630,9 +630,12 @@ PUBLISHED: void clear_shader(); void set_shader_input(ShaderInput input); - INLINE void set_shader_input(CPT_InternalName id, Texture *tex, int priority=0); + INLINE void set_shader_input(CPT_InternalName id, Texture *tex, const SamplerState &sampler, int priority=0); INLINE void set_shader_input(CPT_InternalName id, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0); + +public: + INLINE void set_shader_input(CPT_InternalName id, Texture *tex, int priority=0); INLINE void set_shader_input(CPT_InternalName id, ShaderBuffer *buf, int priority=0); INLINE void set_shader_input(CPT_InternalName id, const NodePath &np, int priority=0); INLINE void set_shader_input(CPT_InternalName id, const PTA_float &v, int priority=0); @@ -659,6 +662,8 @@ PUBLISHED: INLINE void set_shader_input(CPT_InternalName id, PN_stdfloat n1, PN_stdfloat n2=0, PN_stdfloat n3=0, PN_stdfloat n4=0, int priority=0); +PUBLISHED: + EXTENSION(void set_shader_input(CPT_InternalName, PyObject *, int priority=0)); EXTENSION(void set_shader_inputs(PyObject *args, PyObject *kwargs)); void clear_shader_input(CPT_InternalName id); diff --git a/panda/src/pgraph/nodePath_ext.cxx b/panda/src/pgraph/nodePath_ext.cxx index 1d1449b423..4c0eba1ab0 100644 --- a/panda/src/pgraph/nodePath_ext.cxx +++ b/panda/src/pgraph/nodePath_ext.cxx @@ -13,6 +13,7 @@ #include "nodePath_ext.h" #include "typedWritable_ext.h" +#include "shaderInput_ext.h" #include "shaderAttrib.h" #ifdef HAVE_PYTHON @@ -25,35 +26,7 @@ extern struct Dtool_PyTypedObject Dtool_LPoint3d; #else extern struct Dtool_PyTypedObject Dtool_LPoint3f; #endif -extern struct Dtool_PyTypedObject Dtool_Texture; extern struct Dtool_PyTypedObject Dtool_NodePath; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_float; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_double; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_int; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4f; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3f; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2f; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLMatrix4f; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_LMatrix3f; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4d; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3d; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2d; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLMatrix4d; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_LMatrix3d; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4i; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3i; -extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2i; -extern struct Dtool_PyTypedObject Dtool_LVecBase4f; -extern struct Dtool_PyTypedObject Dtool_LVecBase3f; -extern struct Dtool_PyTypedObject Dtool_LVecBase2f; -extern struct Dtool_PyTypedObject Dtool_LVecBase4d; -extern struct Dtool_PyTypedObject Dtool_LVecBase3d; -extern struct Dtool_PyTypedObject Dtool_LVecBase2d; -extern struct Dtool_PyTypedObject Dtool_LVecBase4i; -extern struct Dtool_PyTypedObject Dtool_LVecBase3i; -extern struct Dtool_PyTypedObject Dtool_LVecBase2i; -extern struct Dtool_PyTypedObject Dtool_ShaderBuffer; -extern struct Dtool_PyTypedObject Dtool_ParamValueBase; #endif // CPPPARSER /** @@ -241,6 +214,28 @@ py_decode_NodePath_from_bam_stream_persist(PyObject *unpickler, const string &da return NodePath::decode_from_bam_stream(data, reader); } +/** + * Sets a single shader input. + */ +void Extension:: +set_shader_input(CPT_InternalName name, PyObject *value, int priority) { + PT(PandaNode) node = _this->node(); + CPT(RenderAttrib) prev_attrib = node->get_attrib(ShaderAttrib::get_class_slot()); + PT(ShaderAttrib) attrib; + if (prev_attrib == nullptr) { + attrib = new ShaderAttrib(); + } else { + attrib = new ShaderAttrib(*(const ShaderAttrib *)prev_attrib.p()); + } + + ShaderInput &input = attrib->_inputs[name]; + invoke_extension(&input).__init__(move(name), value); + + if (!_PyErr_OCCURRED()) { + node->set_attrib(ShaderAttrib::return_new(attrib)); + } +} + /** * Sets multiple shader inputs at the same time. This can be significantly * more efficient if many inputs need to be set at the same time. @@ -278,153 +273,13 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) { } CPT_InternalName name(string(buffer, length)); - ShaderInput input(nullptr, 0); - - if (PyTuple_CheckExact(value)) { - // A tuple is interpreted as a vector. - Py_ssize_t size = PyTuple_GET_SIZE(value); - if (size > 4) { - Dtool_Raise_TypeError("NodePath.set_shader_inputs tuple input should not have more than 4 scalars"); - return; - } - // If any of them is a float, we are storing it as a float vector. - bool is_float = false; - for (Py_ssize_t i = 0; i < size; ++i) { - if (PyFloat_CheckExact(PyTuple_GET_ITEM(value, i))) { - is_float = true; - break; - } - } - if (is_float) { - LVecBase4 vec(0); - for (Py_ssize_t i = 0; i < size; ++i) { - vec[i] = (PN_stdfloat)PyFloat_AsDouble(PyTuple_GET_ITEM(value, i)); - } - input = ShaderInput(move(name), vec); - } else { - LVecBase4i vec(0); - for (Py_ssize_t i = 0; i < size; ++i) { - vec[i] = (int)PyLong_AsLong(PyTuple_GET_ITEM(value, i)); - } - input = ShaderInput(move(name), vec); - } - - } else if (DtoolCanThisBeAPandaInstance(value)) { - Dtool_PyInstDef *inst = (Dtool_PyInstDef *)value; - void *ptr; - - if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_Texture))) { - input = ShaderInput(move(name), (Texture *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_NodePath))) { - input = ShaderInput(move(name), *(const NodePath *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_float))) { - input = ShaderInput(move(name), *(const PTA_float *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_double))) { - input = ShaderInput(move(name), *(const PTA_double *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_int))) { - input = ShaderInput(move(name), *(const PTA_int *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4f))) { - input = ShaderInput(move(name), *(const PTA_LVecBase4f *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3f))) { - input = ShaderInput(move(name), *(const PTA_LVecBase3f *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2f))) { - input = ShaderInput(move(name), *(const PTA_LVecBase2f *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4f))) { - input = ShaderInput(move(name), *(const PTA_LMatrix4f *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3f))) { - input = ShaderInput(move(name), *(const PTA_LMatrix3f *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4d))) { - input = ShaderInput(move(name), *(const PTA_LVecBase4d *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3d))) { - input = ShaderInput(move(name), *(const PTA_LVecBase3d *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2d))) { - input = ShaderInput(move(name), *(const PTA_LVecBase2d *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4d))) { - input = ShaderInput(move(name), *(const PTA_LMatrix4d *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3d))) { - input = ShaderInput(move(name), *(const PTA_LMatrix3d *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4i))) { - input = ShaderInput(move(name), *(const PTA_LVecBase4i *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3i))) { - input = ShaderInput(move(name), *(const PTA_LVecBase3i *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2i))) { - input = ShaderInput(move(name), *(const PTA_LVecBase2i *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4f))) { - input = ShaderInput(move(name), *(const LVecBase4f *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3f))) { - input = ShaderInput(move(name), *(const LVecBase3f *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2f))) { - input = ShaderInput(move(name), *(const LVecBase2f *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4d))) { - input = ShaderInput(move(name), *(const LVecBase4d *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3d))) { - input = ShaderInput(move(name), *(const LVecBase3d *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2d))) { - input = ShaderInput(move(name), *(const LVecBase2d *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4i))) { - input = ShaderInput(move(name), *(const LVecBase4i *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3i))) { - input = ShaderInput(move(name), *(const LVecBase3i *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2i))) { - input = ShaderInput(move(name), *(const LVecBase2i *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ShaderBuffer))) { - input = ShaderInput(move(name), (ShaderBuffer *)ptr); - - } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ParamValueBase))) { - input = ShaderInput(move(name), (ParamValueBase *)ptr); - - } else { - Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs"); - return; - } - - } else if (PyFloat_Check(value)) { - input = ShaderInput(move(name), LVecBase4(PyFloat_AS_DOUBLE(value), 0, 0, 0)); - -#if PY_MAJOR_VERSION < 3 - } else if (PyInt_Check(value)) { - input = ShaderInput(move(name), LVecBase4i((int)PyInt_AS_LONG(value), 0, 0, 0)); -#endif - - } else if (PyLong_Check(value)) { - input = ShaderInput(move(name), LVecBase4i((int)PyLong_AsLong(value), 0, 0, 0)); - - } else { - Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs"); - return; - } - - attrib->_inputs[input.get_name()] = move(input); + ShaderInput &input = attrib->_inputs[name]; + invoke_extension(&input).__init__(move(name), value); } - node->set_attrib(ShaderAttrib::return_new(attrib)); + if (!_PyErr_OCCURRED()) { + node->set_attrib(ShaderAttrib::return_new(attrib)); + } } /** diff --git a/panda/src/pgraph/nodePath_ext.h b/panda/src/pgraph/nodePath_ext.h index 44c78378db..aa83f8be42 100644 --- a/panda/src/pgraph/nodePath_ext.h +++ b/panda/src/pgraph/nodePath_ext.h @@ -49,6 +49,7 @@ public: // This is defined to implement cycle detection in Python tags. INLINE int __traverse__(visitproc visit, void *arg); + void set_shader_input(CPT_InternalName id, PyObject *value, int priority=0); void set_shader_inputs(PyObject *args, PyObject *kwargs); PyObject *get_tight_bounds(const NodePath &other = NodePath()) const; diff --git a/panda/src/pgraph/p3pgraph_ext_composite.cxx b/panda/src/pgraph/p3pgraph_ext_composite.cxx index 6dc854b914..d16f600c0a 100644 --- a/panda/src/pgraph/p3pgraph_ext_composite.cxx +++ b/panda/src/pgraph/p3pgraph_ext_composite.cxx @@ -2,4 +2,6 @@ #include "nodePathCollection_ext.cxx" #include "pandaNode_ext.cxx" #include "renderState_ext.cxx" +#include "shaderAttrib_ext.cxx" +#include "shaderInput_ext.cxx" #include "transformState_ext.cxx" diff --git a/panda/src/pgraph/shaderAttrib.h b/panda/src/pgraph/shaderAttrib.h index 7f704cc10f..cb1eec37d9 100644 --- a/panda/src/pgraph/shaderAttrib.h +++ b/panda/src/pgraph/shaderAttrib.h @@ -73,6 +73,7 @@ PUBLISHED: // Shader Inputs CPT(RenderAttrib) set_shader_input(ShaderInput input) const; +public: INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, Texture *tex, int priority=0) const; INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, const NodePath &np, int priority=0) const; INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, const PTA_float &v, int priority=0) const; @@ -90,6 +91,10 @@ PUBLISHED: INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, double n1=0, double n2=0, double n3=0, double n4=1, int priority=0) const; +PUBLISHED: + EXTENSION(CPT(RenderAttrib) set_shader_input(CPT_InternalName, PyObject *, int priority=0) const); + EXTENSION(CPT(RenderAttrib) set_shader_inputs(PyObject *args, PyObject *kwargs) const); + CPT(RenderAttrib) set_instance_count(int instance_count) const; CPT(RenderAttrib) set_flag(int flag, bool value) const; @@ -150,6 +155,7 @@ private: Inputs _inputs; friend class Extension; + friend class Extension; PUBLISHED: static int get_class_slot() { diff --git a/panda/src/pgraph/shaderAttrib_ext.cxx b/panda/src/pgraph/shaderAttrib_ext.cxx new file mode 100644 index 0000000000..b98badf71b --- /dev/null +++ b/panda/src/pgraph/shaderAttrib_ext.cxx @@ -0,0 +1,71 @@ +/** + * 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 shaderAttrib_ext.cxx + * @author rdb + * @date 2017-10-08 + */ + +#include "shaderAttrib_ext.h" +#include "shaderInput_ext.h" + +#ifdef HAVE_PYTHON + +/** + * Returns a new ShaderAttrib with the given shader input set. + */ +CPT(RenderAttrib) Extension:: +set_shader_input(CPT_InternalName name, PyObject *value, int priority) const { + ShaderAttrib *attrib = new ShaderAttrib(*_this); + + ShaderInput &input = attrib->_inputs[name]; + invoke_extension(&input).__init__(move(name), value); + + return ShaderAttrib::return_new(attrib); +} + +/** + * Returns a new ShaderAttrib with the given shader inputs set. This is a + * more efficient way to set multiple shader inputs than calling + * set_shader_input multiple times. + */ +CPT(RenderAttrib) Extension:: +set_shader_inputs(PyObject *args, PyObject *kwargs) const { + if (PyObject_Size(args) > 0) { + Dtool_Raise_TypeError("ShaderAttrib.set_shader_inputs takes only keyword arguments"); + return nullptr; + } + + ShaderAttrib *attrib = new ShaderAttrib(*_this); + + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(kwargs, &pos, &key, &value)) { + char *buffer; + Py_ssize_t length; +#if PY_MAJOR_VERSION >= 3 + buffer = (char *)PyUnicode_AsUTF8AndSize(key, &length); + if (buffer == nullptr) { +#else + if (PyString_AsStringAndSize(key, &buffer, &length) == -1) { +#endif + Dtool_Raise_TypeError("ShaderAttrib.set_shader_inputs accepts only string keywords"); + delete attrib; + return nullptr; + } + + CPT_InternalName name(string(buffer, length)); + ShaderInput &input = attrib->_inputs[name]; + invoke_extension(&input).__init__(move(name), value); + } + + return ShaderAttrib::return_new(attrib); +} + +#endif // HAVE_PYTHON diff --git a/panda/src/pgraph/shaderAttrib_ext.h b/panda/src/pgraph/shaderAttrib_ext.h new file mode 100644 index 0000000000..abf4fca751 --- /dev/null +++ b/panda/src/pgraph/shaderAttrib_ext.h @@ -0,0 +1,38 @@ +/** + * 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 shaderAttrib_ext.h + * @author rdb + * @date 2017-10-08 + */ + +#ifndef SHADERATTRIB_EXT_H +#define SHADERATTRIB_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "shaderAttrib.h" +#include "py_panda.h" + +/** + * This class defines the extension methods for ShaderAttrib, which are called + * instead of any C++ methods with the same prototype. + */ +template<> +class Extension : public ExtensionBase { +public: + CPT(RenderAttrib) set_shader_input(CPT_InternalName id, PyObject *value, int priority=0) const; + CPT(RenderAttrib) set_shader_inputs(PyObject *args, PyObject *kwargs) const; +}; + +#endif // HAVE_PYTHON + +#endif // SHADERATTRIB_EXT_H diff --git a/panda/src/pgraph/shaderInput.h b/panda/src/pgraph/shaderInput.h index ebf630fcaa..1947dc0f86 100644 --- a/panda/src/pgraph/shaderInput.h +++ b/panda/src/pgraph/shaderInput.h @@ -46,7 +46,11 @@ PUBLISHED: }; static const ShaderInput &get_blank(); - INLINE ShaderInput(CPT_InternalName name, int priority=0); + INLINE explicit ShaderInput(CPT_InternalName name, int priority=0); + + EXTENSION(explicit ShaderInput(CPT_InternalName name, PyObject *value, int priority=0)); + +public: INLINE ShaderInput(CPT_InternalName name, Texture *tex, int priority=0); INLINE ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority=0); INLINE ShaderInput(CPT_InternalName name, ShaderBuffer *buf, int priority=0); @@ -83,6 +87,8 @@ PUBLISHED: INLINE ShaderInput(CPT_InternalName name, const LVecBase2i &vec, int priority=0); ShaderInput(CPT_InternalName name, const NodePath &np, int priority=0); + +PUBLISHED: ShaderInput(CPT_InternalName name, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0); ShaderInput(CPT_InternalName name, Texture *tex, const SamplerState &sampler, int priority=0); @@ -132,6 +138,7 @@ private: int _type; friend class ShaderAttrib; + friend class Extension; }; #include "shaderInput.I" diff --git a/panda/src/pgraph/shaderInput_ext.cxx b/panda/src/pgraph/shaderInput_ext.cxx new file mode 100644 index 0000000000..00f42d7d53 --- /dev/null +++ b/panda/src/pgraph/shaderInput_ext.cxx @@ -0,0 +1,539 @@ +/** + * 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 shaderInput_ext.cxx + * @author rdb + * @date 2017-10-06 + */ + +#include "shaderInput_ext.h" +#include "paramNodePath.h" + +#ifdef HAVE_PYTHON + +#ifndef CPPPARSER +extern struct Dtool_PyTypedObject Dtool_Texture; +extern struct Dtool_PyTypedObject Dtool_NodePath; +extern struct Dtool_PyTypedObject Dtool_PointerToVoid; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_float; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_double; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_int; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4f; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3f; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2f; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLMatrix4f; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_LMatrix3f; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4d; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3d; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2d; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLMatrix4d; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_LMatrix3d; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4i; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3i; +extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2i; +extern struct Dtool_PyTypedObject Dtool_LMatrix4f; +extern struct Dtool_PyTypedObject Dtool_LMatrix3f; +extern struct Dtool_PyTypedObject Dtool_LMatrix4d; +extern struct Dtool_PyTypedObject Dtool_LMatrix3d; +extern struct Dtool_PyTypedObject Dtool_LVecBase4f; +extern struct Dtool_PyTypedObject Dtool_LVecBase3f; +extern struct Dtool_PyTypedObject Dtool_LVecBase2f; +extern struct Dtool_PyTypedObject Dtool_LVecBase4d; +extern struct Dtool_PyTypedObject Dtool_LVecBase3d; +extern struct Dtool_PyTypedObject Dtool_LVecBase2d; +extern struct Dtool_PyTypedObject Dtool_LVecBase4i; +extern struct Dtool_PyTypedObject Dtool_LVecBase3i; +extern struct Dtool_PyTypedObject Dtool_LVecBase2i; +extern struct Dtool_PyTypedObject Dtool_ShaderBuffer; +extern struct Dtool_PyTypedObject Dtool_ParamValueBase; +#endif // CPPPARSER + +/** + * Sets a shader input from an arbitrary Python object. + */ +void Extension:: +__init__(CPT_InternalName name, PyObject *value, int priority) { + _this->_name = move(name); + _this->_priority = priority; + + if (PyTuple_CheckExact(value) && PyTuple_GET_SIZE(value) <= 4) { + // A tuple is interpreted as a vector. + Py_ssize_t size = PyTuple_GET_SIZE(value); + + // If any of them is a float, we are storing it as a float vector. + bool is_float = false; + for (Py_ssize_t i = 0; i < size; ++i) { + if (PyFloat_CheckExact(PyTuple_GET_ITEM(value, i))) { + is_float = true; + break; + } + } + if (is_float) { + LVecBase4 vec(0); + for (Py_ssize_t i = 0; i < size; ++i) { + vec[i] = (PN_stdfloat)PyFloat_AsDouble(PyTuple_GET_ITEM(value, i)); + } + _this->_type = ShaderInput::M_vector; + _this->_stored_ptr = vec; + _this->_stored_vector = vec; + } else { + LVecBase4i vec(0); + for (Py_ssize_t i = 0; i < size; ++i) { + vec[i] = (int)PyLong_AsLong(PyTuple_GET_ITEM(value, i)); + } + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = vec; + _this->_stored_vector = LCAST(PN_stdfloat, vec); + } + + } else if (DtoolCanThisBeAPandaInstance(value)) { + Dtool_PyInstDef *inst = (Dtool_PyInstDef *)value; + void *ptr; + + if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_Texture))) { + _this->_type = ShaderInput::M_texture; + _this->_value = (Texture *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_NodePath))) { + _this->_type = ShaderInput::M_nodepath; + _this->_value = new ParamNodePath(*(const NodePath *)ptr); + + } else if (inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToVoid)) { + if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_float))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_float *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_double))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_double *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_int))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_int *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4f))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LVecBase4f *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3f))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LVecBase3f *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2f))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LVecBase2f *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4f))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LMatrix4f *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3f))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LMatrix3f *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4d))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LVecBase4d *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3d))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LVecBase3d *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2d))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LVecBase2d *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4d))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LMatrix4d *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3d))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LMatrix3d *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4i))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LVecBase4i *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3i))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LVecBase3i *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2i))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const PTA_LVecBase2i *)ptr; + + } else { + Dtool_Raise_TypeError("unknown type passed to ShaderInput"); + return; + } + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LMatrix4f))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const LMatrix4f *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LMatrix3f))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const LMatrix3f *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LMatrix4d))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const LMatrix4d *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LMatrix3d))) { + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = *(const LMatrix3d *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4f))) { + const LVecBase4f &vec = *(const LVecBase4f *)ptr; + _this->_type = ShaderInput::M_vector; + _this->_stored_ptr = vec; + _this->_stored_vector = LCAST(PN_stdfloat, vec); + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3f))) { + const LVecBase3f &vec = *(const LVecBase3f *)ptr; + _this->_type = ShaderInput::M_vector; + _this->_stored_ptr = vec; + _this->_stored_vector.set(vec[0], vec[1], vec[2], 0); + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2f))) { + const LVecBase2f &vec = *(const LVecBase2f *)ptr; + _this->_type = ShaderInput::M_vector; + _this->_stored_ptr = vec; + _this->_stored_vector.set(vec[0], vec[1], 0, 0); + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4d))) { + const LVecBase4d &vec = *(const LVecBase4d *)ptr; + _this->_type = ShaderInput::M_vector; + _this->_stored_ptr = vec; + _this->_stored_vector = LCAST(PN_stdfloat, vec); + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3d))) { + const LVecBase3d &vec = *(const LVecBase3d *)ptr; + _this->_type = ShaderInput::M_vector; + _this->_stored_ptr = vec; + _this->_stored_vector.set(vec[0], vec[1], vec[2], 0); + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2d))) { + const LVecBase2d &vec = *(const LVecBase2d *)ptr; + _this->_type = ShaderInput::M_vector; + _this->_stored_ptr = vec; + _this->_stored_vector.set(vec[0], vec[1], 0, 0); + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4i))) { + const LVecBase4i &vec = *(const LVecBase4i *)ptr; + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = vec; + _this->_stored_vector = LCAST(PN_stdfloat, vec); + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3i))) { + const LVecBase3i &vec = *(const LVecBase3i *)ptr; + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = vec; + _this->_stored_vector.set(vec[0], vec[1], vec[2], 0); + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2i))) { + const LVecBase2i &vec = *(const LVecBase2i *)ptr; + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = vec; + _this->_stored_vector.set(vec[0], vec[1], 0, 0); + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ShaderBuffer))) { + _this->_type = ShaderInput::M_buffer; + _this->_value = (ShaderBuffer *)ptr; + + } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ParamValueBase))) { + _this->_type = ShaderInput::M_param; + _this->_value = (ParamValueBase *)ptr; + + } else { + Dtool_Raise_TypeError("unknown type passed to ShaderInput"); + return; + } + + } else if (PyFloat_Check(value)) { + LVecBase4 vec(PyFloat_AS_DOUBLE(value), 0, 0, 0); + _this->_type = ShaderInput::M_vector; + _this->_stored_ptr = vec; + _this->_stored_vector = vec; + +#if PY_MAJOR_VERSION < 3 + } else if (PyInt_Check(value)) { + LVecBase4i vec((int)PyInt_AS_LONG(value), 0, 0, 0); + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = vec; + _this->_stored_vector.set((PN_stdfloat)vec[0], 0, 0, 0); +#endif + + } else if (PyLong_Check(value)) { + LVecBase4i vec((int)PyLong_AsLong(value), 0, 0, 0); + _this->_type = ShaderInput::M_numeric; + _this->_stored_ptr = vec; + _this->_stored_vector.set((PN_stdfloat)vec[0], 0, 0, 0); + + } else if (PySequence_Check(value) && !PyUnicode_CheckExact(value)) { + // Iterate over the sequence to make sure all have the same type. + PyObject *fast = PySequence_Fast(value, "unknown type passed to ShaderInput"); + if (fast == nullptr) { + return; + } + + Py_ssize_t num_items = PySequence_Fast_GET_SIZE(value); + if (num_items <= 0) { + // We can't determine the type of a list of size 0. + _this->_type = ShaderInput::M_numeric; + Py_DECREF(fast); + return; + } + + bool has_float = false; + Py_ssize_t known_itemsize = -1; + + PyObject **items = PySequence_Fast_ITEMS(fast); + for (Py_ssize_t i = 0; i < num_items; ++i) { + PyObject *item = items[i]; + + if (PySequence_Check(item)) { + Py_ssize_t itemsize = PySequence_Size(item); + if (known_itemsize >= 0 && itemsize != known_itemsize) { + Dtool_Raise_TypeError("inconsistent sequence length among elements of sequence passed to ShaderInput"); + Py_DECREF(fast); + return; + } + known_itemsize = itemsize; + + // Check their types. + for (Py_ssize_t j = 0; j < itemsize; ++j) { + PyObject *subitem = PySequence_ITEM(item, j); + if (PyFloat_CheckExact(subitem)) { + Py_DECREF(subitem); + has_float = true; + break; + } else if (PyLongOrInt_Check(subitem)) { + } else { + Dtool_Raise_TypeError("unknown element type in sequence passed as element of sequence passed to ShaderInput"); + Py_DECREF(subitem); + Py_DECREF(fast); + break; + } + Py_DECREF(subitem); + } + } else if (PyFloat_CheckExact(item)) { + has_float = true; + } else if (PyLongOrInt_Check(item)) { + } else { + Dtool_Raise_TypeError("unknown element type in sequence passed to ShaderInput"); + Py_DECREF(fast); + return; + } + } + + // Now that we have verified the dimensions and type of the PTA, we can + // read in the actual elements. + switch (known_itemsize) { + case -1: + if (has_float) { + PTA_float pta; + pta.reserve(num_items); + for (Py_ssize_t i = 0; i < num_items; ++i) { + pta.push_back(PyFloat_AsDouble(items[i])); + } + _this->_stored_ptr = pta; + } else { + PTA_int pta; + pta.reserve(num_items); + for (Py_ssize_t i = 0; i < num_items; ++i) { + pta.push_back((int)PyLongOrInt_AS_LONG(items[i])); + } + _this->_stored_ptr = pta; + } + break; + + case 1: + if (has_float) { + PTA_float pta; + pta.reserve(num_items); + for (Py_ssize_t i = 0; i < num_items; ++i) { + PyObject *item = items[i]; + if (PySequence_Check(item)) { + PyObject *subitem = PySequence_ITEM(item, 0); + pta.push_back(PyFloat_AsDouble(subitem)); + Py_DECREF(subitem); + } else { + pta.push_back(PyFloat_AsDouble(item)); + } + } + _this->_stored_ptr = pta; + } else { + PTA_int pta; + pta.reserve(num_items); + for (Py_ssize_t i = 0; i < num_items; ++i) { + PyObject *item = items[i]; + if (PySequence_Check(item)) { + PyObject *subitem = PySequence_ITEM(item, 0); + pta.push_back((int)PyLongOrInt_AS_LONG(subitem)); + Py_DECREF(subitem); + } else { + pta.push_back((int)PyLongOrInt_AS_LONG(item)); + } + } + _this->_stored_ptr = pta; + } + break; + + case 2: + if (has_float) { + PTA_LVecBase2f pta; + pta.reserve(num_items); + for (Py_ssize_t i = 0; i < num_items; ++i) { + PyObject *item = items[i]; + if (PySequence_Check(item)) { + PyObject *subitem0 = PySequence_ITEM(item, 0); + PyObject *subitem1 = PySequence_ITEM(item, 1); + pta.push_back(LVecBase2f(PyFloat_AsDouble(subitem0), + PyFloat_AsDouble(subitem1))); + Py_DECREF(subitem0); + Py_DECREF(subitem1); + } else { + pta.push_back(PyFloat_AsDouble(item)); + } + } + _this->_stored_ptr = pta; + } else { + PTA_LVecBase2i pta; + pta.reserve(num_items); + for (Py_ssize_t i = 0; i < num_items; ++i) { + PyObject *item = items[i]; + if (PySequence_Check(item)) { + PyObject *subitem0 = PySequence_ITEM(item, 0); + PyObject *subitem1 = PySequence_ITEM(item, 1); + pta.push_back(LVecBase2i((int)PyLongOrInt_AS_LONG(subitem0), + (int)PyLongOrInt_AS_LONG(subitem1))); + Py_DECREF(subitem0); + Py_DECREF(subitem1); + } else { + pta.push_back((int)PyLongOrInt_AS_LONG(item)); + } + } + _this->_stored_ptr = pta; + } + break; + + case 3: + if (has_float) { + PTA_LVecBase3f pta; + pta.reserve(num_items); + for (Py_ssize_t i = 0; i < num_items; ++i) { + PyObject *item = items[i]; + if (PySequence_Check(item)) { + PyObject *subitem0 = PySequence_ITEM(item, 0); + PyObject *subitem1 = PySequence_ITEM(item, 1); + PyObject *subitem2 = PySequence_ITEM(item, 2); + pta.push_back(LVecBase3f(PyFloat_AsDouble(subitem0), + PyFloat_AsDouble(subitem1), + PyFloat_AsDouble(subitem2))); + Py_DECREF(subitem0); + Py_DECREF(subitem1); + Py_DECREF(subitem2); + } else { + pta.push_back(PyFloat_AsDouble(item)); + } + } + _this->_stored_ptr = pta; + } else { + PTA_LVecBase3i pta; + pta.reserve(num_items); + for (Py_ssize_t i = 0; i < num_items; ++i) { + PyObject *item = items[i]; + if (PySequence_Check(item)) { + PyObject *subitem0 = PySequence_ITEM(item, 0); + PyObject *subitem1 = PySequence_ITEM(item, 1); + PyObject *subitem2 = PySequence_ITEM(item, 2); + pta.push_back(LVecBase3i((int)PyLongOrInt_AS_LONG(subitem0), + (int)PyLongOrInt_AS_LONG(subitem1), + (int)PyLongOrInt_AS_LONG(subitem2))); + Py_DECREF(subitem0); + Py_DECREF(subitem1); + Py_DECREF(subitem2); + } else { + pta.push_back((int)PyLongOrInt_AS_LONG(item)); + } + } + _this->_stored_ptr = pta; + } + break; + + case 4: + if (has_float) { + PTA_LVecBase4f pta; + pta.reserve(num_items); + for (Py_ssize_t i = 0; i < num_items; ++i) { + PyObject *item = items[i]; + if (PySequence_Check(item)) { + PyObject *subitem0 = PySequence_ITEM(item, 0); + PyObject *subitem1 = PySequence_ITEM(item, 1); + PyObject *subitem2 = PySequence_ITEM(item, 2); + PyObject *subitem3 = PySequence_ITEM(item, 3); + pta.push_back(LVecBase4f(PyFloat_AsDouble(subitem0), + PyFloat_AsDouble(subitem1), + PyFloat_AsDouble(subitem2), + PyFloat_AsDouble(subitem3))); + Py_DECREF(subitem0); + Py_DECREF(subitem1); + Py_DECREF(subitem2); + Py_DECREF(subitem3); + } else { + pta.push_back(PyFloat_AsDouble(item)); + } + } + _this->_stored_ptr = pta; + } else { + PTA_LVecBase4i pta; + pta.reserve(num_items); + for (Py_ssize_t i = 0; i < num_items; ++i) { + PyObject *item = items[i]; + if (PySequence_Check(item)) { + PyObject *subitem0 = PySequence_ITEM(item, 0); + PyObject *subitem1 = PySequence_ITEM(item, 1); + PyObject *subitem2 = PySequence_ITEM(item, 2); + PyObject *subitem3 = PySequence_ITEM(item, 3); + pta.push_back(LVecBase4i((int)PyLongOrInt_AS_LONG(subitem0), + (int)PyLongOrInt_AS_LONG(subitem1), + (int)PyLongOrInt_AS_LONG(subitem2), + (int)PyLongOrInt_AS_LONG(subitem3))); + Py_DECREF(subitem0); + Py_DECREF(subitem1); + Py_DECREF(subitem2); + Py_DECREF(subitem3); + } else { + pta.push_back((int)PyLongOrInt_AS_LONG(item)); + } + } + _this->_stored_ptr = pta; + } + break; + + case 0: + Dtool_Raise_TypeError("sequence passed to ShaderInput contains an empty sequence"); + break; + + default: + Dtool_Raise_TypeError("sequence passed to ShaderInput contains a sequence of more than 4 elements"); + break; + } + + _this->_type = ShaderInput::M_numeric; + + Py_DECREF(fast); + + } else { + Dtool_Raise_TypeError("unknown type passed to ShaderInput"); + } +} + +#endif // HAVE_PYTHON diff --git a/panda/src/pgraph/shaderInput_ext.h b/panda/src/pgraph/shaderInput_ext.h new file mode 100644 index 0000000000..c624a45ef8 --- /dev/null +++ b/panda/src/pgraph/shaderInput_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 shaderInput_ext.h + * @author rdb + * @date 2017-10-06 + */ + +#ifndef SHADERINPUT_EXT_H +#define SHADERINPUT_EXT_H + +#include "dtoolbase.h" + +#ifdef HAVE_PYTHON + +#include "extension.h" +#include "shaderInput.h" +#include "py_panda.h" + +/** + * This class defines the extension methods for NodePath, which are called + * instead of any C++ methods with the same prototype. + */ +template<> +class Extension : public ExtensionBase { +public: + void __init__(CPT_InternalName name, PyObject *value, int priority=0); +}; + +#endif // HAVE_PYTHON + +#endif // SHADERINPUT_EXT_H