mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
Add set_shader_inputs for efficiently setting multiple shader inputs
This commit is contained in:
parent
c3a196860a
commit
cfe810ace7
@ -791,6 +791,15 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
||||
_args_type = InterfaceMaker::AT_single_arg;
|
||||
} else {
|
||||
_args_type = InterfaceMaker::AT_varargs;
|
||||
|
||||
// If the arguments are named "args" and "kwargs", we will be directly
|
||||
// passing the argument tuples to the function.
|
||||
if (_parameters.size() == first_param + 2 &&
|
||||
_parameters[first_param]._name == "args" &&
|
||||
(_parameters[first_param + 1]._name == "kwargs" ||
|
||||
_parameters[first_param + 1]._name == "kwds")) {
|
||||
_flags |= F_explicit_args;
|
||||
}
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
@ -890,7 +899,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
|
||||
if (_args_type == InterfaceMaker::AT_varargs) {
|
||||
// Every other method can take keyword arguments, if they take more
|
||||
// than one argument.
|
||||
_args_type = InterfaceMaker::AT_keyword_args;
|
||||
_args_type |= InterfaceMaker::AT_keyword_args;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -100,6 +100,7 @@ public:
|
||||
F_coerce_constructor = 0x1000,
|
||||
F_divide_float = 0x2000,
|
||||
F_hash = 0x4000,
|
||||
F_explicit_args = 0x8000,
|
||||
};
|
||||
|
||||
typedef vector<Parameter> Parameters;
|
||||
|
@ -3453,7 +3453,13 @@ write_function_for_name(ostream &out, Object *obj,
|
||||
max_required_args = collapse_default_remaps(map_sets, max_required_args);
|
||||
}
|
||||
|
||||
if (map_sets.size() > 1 && (args_type == AT_varargs || args_type == AT_keyword_args)) {
|
||||
if (remap->_flags & FunctionRemap::F_explicit_args) {
|
||||
// We have a remap that wants to handle the wrapper itself.
|
||||
string expected_params;
|
||||
write_function_instance(out, remap, 0, 0, expected_params, 2, true, true,
|
||||
args_type, return_flags);
|
||||
|
||||
} else if (map_sets.size() > 1 && (args_type == AT_varargs || args_type == AT_keyword_args)) {
|
||||
switch (args_type) {
|
||||
case AT_keyword_args:
|
||||
indent(out, 2) << "int parameter_count = (int)PyTuple_Size(args);\n";
|
||||
@ -4536,19 +4542,23 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
||||
expected_params += methodNameFromCppName(remap, "", false);
|
||||
expected_params += "(";
|
||||
|
||||
int num_params = max_num_args;
|
||||
if (remap->_has_this) {
|
||||
num_params += 1;
|
||||
}
|
||||
if (num_params > (int)remap->_parameters.size()) {
|
||||
// Limit to how many parameters this remap actually has.
|
||||
num_params = (int)remap->_parameters.size();
|
||||
max_num_args = num_params;
|
||||
int num_params = 0;
|
||||
|
||||
if ((remap->_flags & FunctionRemap::F_explicit_args) == 0) {
|
||||
num_params = max_num_args;
|
||||
if (remap->_has_this) {
|
||||
--max_num_args;
|
||||
num_params += 1;
|
||||
}
|
||||
if (num_params > (int)remap->_parameters.size()) {
|
||||
// Limit to how many parameters this remap actually has.
|
||||
num_params = (int)remap->_parameters.size();
|
||||
max_num_args = num_params;
|
||||
if (remap->_has_this) {
|
||||
--max_num_args;
|
||||
}
|
||||
}
|
||||
nassertv(num_params <= (int)remap->_parameters.size());
|
||||
}
|
||||
nassertv(num_params <= (int)remap->_parameters.size());
|
||||
|
||||
bool only_pyobjects = true;
|
||||
|
||||
@ -4584,6 +4594,17 @@ write_function_instance(ostream &out, FunctionRemap *remap,
|
||||
}
|
||||
}
|
||||
|
||||
if (remap->_flags & FunctionRemap::F_explicit_args) {
|
||||
// The function handles the arguments by itself.
|
||||
expected_params += "*args";
|
||||
pexprs.push_back("args");
|
||||
if (args_type == AT_keyword_args) {
|
||||
expected_params += ", **kwargs";
|
||||
pexprs.push_back("kwds");
|
||||
}
|
||||
num_params = 0;
|
||||
}
|
||||
|
||||
// Now convert (the rest of the) actual arguments, one by one.
|
||||
for (; pn < num_params; ++pn) {
|
||||
ParameterRemap *param = remap->_parameters[pn]._remap;
|
||||
|
@ -659,6 +659,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);
|
||||
|
||||
EXTENSION(void set_shader_inputs(PyObject *args, PyObject *kwargs));
|
||||
|
||||
void clear_shader_input(CPT_InternalName id);
|
||||
void set_instance_count(int instance_count);
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "nodePath_ext.h"
|
||||
#include "typedWritable_ext.h"
|
||||
#include "shaderAttrib.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
@ -24,6 +25,35 @@ 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
|
||||
|
||||
/**
|
||||
@ -211,6 +241,192 @@ py_decode_NodePath_from_bam_stream_persist(PyObject *unpickler, const string &da
|
||||
return NodePath::decode_from_bam_stream(data, reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void Extension<NodePath>::
|
||||
set_shader_inputs(PyObject *args, PyObject *kwargs) {
|
||||
if (PyObject_Size(args) > 0) {
|
||||
Dtool_Raise_TypeError("NodePath.set_shader_inputs takes only keyword arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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("NodePath.set_shader_inputs accepts only string keywords");
|
||||
return;
|
||||
}
|
||||
|
||||
CPT_InternalName name(string(buffer, length));
|
||||
ShaderInput *input = nullptr;
|
||||
|
||||
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 = new ShaderInput(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 = new ShaderInput(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 = new ShaderInput(name, (Texture *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_NodePath))) {
|
||||
input = new ShaderInput(name, *(const NodePath *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_float))) {
|
||||
input = new ShaderInput(name, *(const PTA_float *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_double))) {
|
||||
input = new ShaderInput(name, *(const PTA_double *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_int))) {
|
||||
input = new ShaderInput(name, *(const PTA_int *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4f))) {
|
||||
input = new ShaderInput(name, *(const PTA_LVecBase4f *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3f))) {
|
||||
input = new ShaderInput(name, *(const PTA_LVecBase3f *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2f))) {
|
||||
input = new ShaderInput(name, *(const PTA_LVecBase2f *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4f))) {
|
||||
input = new ShaderInput(name, *(const PTA_LMatrix4f *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3f))) {
|
||||
input = new ShaderInput(name, *(const PTA_LMatrix3f *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4d))) {
|
||||
input = new ShaderInput(name, *(const PTA_LVecBase4d *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3d))) {
|
||||
input = new ShaderInput(name, *(const PTA_LVecBase3d *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2d))) {
|
||||
input = new ShaderInput(name, *(const PTA_LVecBase2d *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4d))) {
|
||||
input = new ShaderInput(name, *(const PTA_LMatrix4d *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3d))) {
|
||||
input = new ShaderInput(name, *(const PTA_LMatrix3d *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4i))) {
|
||||
input = new ShaderInput(name, *(const PTA_LVecBase4i *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3i))) {
|
||||
input = new ShaderInput(name, *(const PTA_LVecBase3i *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2i))) {
|
||||
input = new ShaderInput(name, *(const PTA_LVecBase2i *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4f))) {
|
||||
input = new ShaderInput(name, *(const LVecBase4f *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3f))) {
|
||||
input = new ShaderInput(name, *(const LVecBase3f *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2f))) {
|
||||
input = new ShaderInput(name, *(const LVecBase2f *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4d))) {
|
||||
input = new ShaderInput(name, *(const LVecBase4d *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3d))) {
|
||||
input = new ShaderInput(name, *(const LVecBase3d *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2d))) {
|
||||
input = new ShaderInput(name, *(const LVecBase2d *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4i))) {
|
||||
input = new ShaderInput(name, *(const LVecBase4i *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3i))) {
|
||||
input = new ShaderInput(name, *(const LVecBase3i *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2i))) {
|
||||
input = new ShaderInput(name, *(const LVecBase2i *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ShaderBuffer))) {
|
||||
input = new ShaderInput(name, (ShaderBuffer *)ptr);
|
||||
|
||||
} else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ParamValueBase))) {
|
||||
input = new ShaderInput(name, (ParamValueBase *)ptr);
|
||||
|
||||
} else {
|
||||
Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs");
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (PyFloat_Check(value)) {
|
||||
input = new ShaderInput(name, LVecBase4(PyFloat_AS_DOUBLE(value), 0, 0, 0));
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
} else if (PyInt_Check(value)) {
|
||||
input = new ShaderInput(name, LVecBase4i((int)PyInt_AS_LONG(value), 0, 0, 0));
|
||||
#endif
|
||||
|
||||
} else if (PyLong_Check(value)) {
|
||||
input = new ShaderInput(name, LVecBase4i((int)PyLong_AsLong(value), 0, 0, 0));
|
||||
|
||||
} else {
|
||||
Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs");
|
||||
return;
|
||||
}
|
||||
|
||||
attrib->_inputs[move(name)] = input;
|
||||
}
|
||||
|
||||
node->set_attrib(ShaderAttrib::return_new(attrib));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tight bounds as a 2-tuple of LPoint3 objects. This is a
|
||||
* convenience function for Python users, among which the use of
|
||||
|
@ -49,6 +49,8 @@ public:
|
||||
// This is defined to implement cycle detection in Python tags.
|
||||
INLINE int __traverse__(visitproc visit, void *arg);
|
||||
|
||||
void set_shader_inputs(PyObject *args, PyObject *kwargs);
|
||||
|
||||
PyObject *get_tight_bounds(const NodePath &other = NodePath()) const;
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "pta_LVecBase4.h"
|
||||
#include "pta_LVecBase3.h"
|
||||
#include "pta_LVecBase2.h"
|
||||
#include "extension.h"
|
||||
|
||||
/**
|
||||
*
|
||||
@ -147,6 +148,8 @@ private:
|
||||
typedef pmap<CPT_InternalName, CPT(ShaderInput)> Inputs;
|
||||
Inputs _inputs;
|
||||
|
||||
friend class Extension<NodePath>;
|
||||
|
||||
PUBLISHED:
|
||||
static int get_class_slot() {
|
||||
return _attrib_slot;
|
||||
|
Loading…
x
Reference in New Issue
Block a user