pgraph: custom binding for set_shader_input()

Should be faster and more reliable at PTA handling
We no longer need the interrogate perf hack for the first-arg InternalName

Fixes: #161
This commit is contained in:
rdb 2017-10-08 15:56:30 +02:00
parent 8ed85c80c8
commit 0e2b14cf4c
11 changed files with 738 additions and 245 deletions

View File

@ -4389,57 +4389,6 @@ write_function_forset(ostream &out,
std::sort(remaps.begin(), remaps.end(), RemapCompareLess); std::sort(remaps.begin(), remaps.end(), RemapCompareLess);
std::vector<FunctionRemap *>::const_iterator sii; std::vector<FunctionRemap *>::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; int num_coercion_possible = 0;
sii = remaps.begin(); sii = remaps.begin();
while (sii != remaps.end()) { while (sii != remaps.end()) {
@ -4474,7 +4423,7 @@ write_function_forset(ostream &out,
write_function_instance(out, remap, min_num_args, max_num_args, write_function_instance(out, remap, min_num_args, max_num_args,
expected_params, indent_level + 2, expected_params, indent_level + 2,
false, false, args_type, return_flags, false, false, args_type, return_flags,
check_exceptions, first_pexpr2); check_exceptions, first_pexpr);
indent(out, indent_level) << "}\n\n"; 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, write_function_instance(out, remap, min_num_args, max_num_args,
ignore_expected_params, indent_level + 2, ignore_expected_params, indent_level + 2,
true, false, args_type, return_flags, true, false, args_type, return_flags,
check_exceptions, first_pexpr2); check_exceptions, first_pexpr);
indent(out, indent_level) << "}\n\n"; 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 { } else {
// There is only one possible overload with this number of parameters. // There is only one possible overload with this number of parameters.
// Just call it. // Just call it.

View File

@ -630,9 +630,12 @@ PUBLISHED:
void clear_shader(); void clear_shader();
void set_shader_input(ShaderInput input); 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, 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); 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, 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 NodePath &np, int priority=0);
INLINE void set_shader_input(CPT_InternalName id, const PTA_float &v, 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, 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); 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)); EXTENSION(void set_shader_inputs(PyObject *args, PyObject *kwargs));
void clear_shader_input(CPT_InternalName id); void clear_shader_input(CPT_InternalName id);

View File

@ -13,6 +13,7 @@
#include "nodePath_ext.h" #include "nodePath_ext.h"
#include "typedWritable_ext.h" #include "typedWritable_ext.h"
#include "shaderInput_ext.h"
#include "shaderAttrib.h" #include "shaderAttrib.h"
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
@ -25,35 +26,7 @@ extern struct Dtool_PyTypedObject Dtool_LPoint3d;
#else #else
extern struct Dtool_PyTypedObject Dtool_LPoint3f; extern struct Dtool_PyTypedObject Dtool_LPoint3f;
#endif #endif
extern struct Dtool_PyTypedObject Dtool_Texture;
extern struct Dtool_PyTypedObject Dtool_NodePath; 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 #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); return NodePath::decode_from_bam_stream(data, reader);
} }
/**
* Sets a single shader input.
*/
void Extension<NodePath>::
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 * 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. * more efficient if many inputs need to be set at the same time.
@ -278,154 +273,14 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) {
} }
CPT_InternalName name(string(buffer, length)); CPT_InternalName name(string(buffer, length));
ShaderInput input(nullptr, 0); ShaderInput &input = attrib->_inputs[name];
invoke_extension(&input).__init__(move(name), value);
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);
} }
if (!_PyErr_OCCURRED()) {
node->set_attrib(ShaderAttrib::return_new(attrib)); node->set_attrib(ShaderAttrib::return_new(attrib));
} }
}
/** /**
* Returns the tight bounds as a 2-tuple of LPoint3 objects. This is a * Returns the tight bounds as a 2-tuple of LPoint3 objects. This is a

View File

@ -49,6 +49,7 @@ public:
// This is defined to implement cycle detection in Python tags. // This is defined to implement cycle detection in Python tags.
INLINE int __traverse__(visitproc visit, void *arg); 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); void set_shader_inputs(PyObject *args, PyObject *kwargs);
PyObject *get_tight_bounds(const NodePath &other = NodePath()) const; PyObject *get_tight_bounds(const NodePath &other = NodePath()) const;

View File

@ -2,4 +2,6 @@
#include "nodePathCollection_ext.cxx" #include "nodePathCollection_ext.cxx"
#include "pandaNode_ext.cxx" #include "pandaNode_ext.cxx"
#include "renderState_ext.cxx" #include "renderState_ext.cxx"
#include "shaderAttrib_ext.cxx"
#include "shaderInput_ext.cxx"
#include "transformState_ext.cxx" #include "transformState_ext.cxx"

View File

@ -73,6 +73,7 @@ PUBLISHED:
// Shader Inputs // Shader Inputs
CPT(RenderAttrib) set_shader_input(ShaderInput input) const; 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, 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 NodePath &np, int priority=0) const;
INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, const PTA_float &v, 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, 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; 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_instance_count(int instance_count) const;
CPT(RenderAttrib) set_flag(int flag, bool value) const; CPT(RenderAttrib) set_flag(int flag, bool value) const;
@ -150,6 +155,7 @@ private:
Inputs _inputs; Inputs _inputs;
friend class Extension<NodePath>; friend class Extension<NodePath>;
friend class Extension<ShaderAttrib>;
PUBLISHED: PUBLISHED:
static int get_class_slot() { static int get_class_slot() {

View File

@ -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<ShaderAttrib>::
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<ShaderAttrib>::
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

View File

@ -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<ShaderAttrib> : public ExtensionBase<ShaderAttrib> {
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

View File

@ -46,7 +46,11 @@ PUBLISHED:
}; };
static const ShaderInput &get_blank(); 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, Texture *tex, int priority=0);
INLINE ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority=0); INLINE ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority=0);
INLINE ShaderInput(CPT_InternalName name, ShaderBuffer *buf, 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); INLINE ShaderInput(CPT_InternalName name, const LVecBase2i &vec, int priority=0);
ShaderInput(CPT_InternalName name, const NodePath &np, 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, 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); ShaderInput(CPT_InternalName name, Texture *tex, const SamplerState &sampler, int priority=0);
@ -132,6 +138,7 @@ private:
int _type; int _type;
friend class ShaderAttrib; friend class ShaderAttrib;
friend class Extension<ShaderInput>;
}; };
#include "shaderInput.I" #include "shaderInput.I"

View File

@ -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<ShaderInput>::
__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

View File

@ -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<ShaderInput> : public ExtensionBase<ShaderInput> {
public:
void __init__(CPT_InternalName name, PyObject *value, int priority=0);
};
#endif // HAVE_PYTHON
#endif // SHADERINPUT_EXT_H