Files
test/source/blender/python/bmesh/bmesh_py_ops.cc
Campbell Barton e955c94ed3 License Headers: Set copyright to "Blender Authors", add AUTHORS
Listing the "Blender Foundation" as copyright holder implied the Blender
Foundation holds copyright to files which may include work from many
developers.

While keeping copyright on headers makes sense for isolated libraries,
Blender's own code may be refactored or moved between files in a way
that makes the per file copyright holders less meaningful.

Copyright references to the "Blender Foundation" have been replaced with
"Blender Authors", with the exception of `./extern/` since these this
contains libraries which are more isolated, any changed to license
headers there can be handled on a case-by-case basis.

Some directories in `./intern/` have also been excluded:

- `./intern/cycles/` it's own `AUTHORS` file is planned.
- `./intern/opensubdiv/`.

An "AUTHORS" file has been added, using the chromium projects authors
file as a template.

Design task: #110784

Ref !110783.
2023-08-16 00:20:26 +10:00

268 lines
6.8 KiB
C++

/* SPDX-FileCopyrightText: 2012 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup pybmesh
*
* This file defines the 'bmesh.ops' module.
* Operators from 'opdefines' are wrapped.
*/
#include <Python.h>
#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
#include "bmesh.h"
#include "bmesh_py_ops.h" /* own include */
#include "bmesh_py_ops_call.h"
/* bmesh operator 'bmesh.ops.*' callable types
* ******************************************* */
static PyObject *bpy_bmesh_op_repr(BPy_BMeshOpFunc *self)
{
return PyUnicode_FromFormat("<%.200s bmesh.ops.%.200s()>", Py_TYPE(self)->tp_name, self->opname);
}
/* methods
* ======= */
/* __doc__
* ------- */
static char *bmp_slots_as_args(const BMOSlotType slot_types[BMO_OP_MAX_SLOTS], const bool is_out)
{
DynStr *dyn_str = BLI_dynstr_new();
char *ret;
bool quoted;
bool set;
int i = 0;
while (*slot_types[i].name) {
quoted = false;
set = false;
/* cut off '.out' by using a string size arg */
const int name_len = is_out ? (strchr(slot_types[i].name, '.') - slot_types[i].name) :
sizeof(slot_types[i].name);
const char *value = "<Unknown>";
switch (slot_types[i].type) {
case BMO_OP_SLOT_BOOL:
value = "False";
break;
case BMO_OP_SLOT_INT:
if (slot_types[i].subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_ENUM) {
value = slot_types[i].enum_flags[0].identifier;
quoted = true;
}
else if (slot_types[i].subtype.intg == BMO_OP_SLOT_SUBTYPE_INT_FLAG) {
value = "";
set = true;
}
else {
value = "0";
}
break;
case BMO_OP_SLOT_FLT:
value = "0.0";
break;
case BMO_OP_SLOT_PTR:
value = "None";
break;
case BMO_OP_SLOT_MAT:
value = "Matrix()";
break;
case BMO_OP_SLOT_VEC:
value = "Vector()";
break;
case BMO_OP_SLOT_ELEMENT_BUF:
value = (slot_types[i].subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) ? "None" : "[]";
break;
case BMO_OP_SLOT_MAPPING:
value = "{}";
break;
}
BLI_dynstr_appendf(dyn_str,
i ? ", %.*s=%s%s%s%s%s" : "%.*s=%s%s%s%s%s",
name_len,
slot_types[i].name,
set ? "{" : "",
quoted ? "'" : "",
value,
quoted ? "'" : "",
set ? "}" : "");
i++;
}
ret = BLI_dynstr_get_cstring(dyn_str);
BLI_dynstr_free(dyn_str);
return ret;
}
static PyObject *bpy_bmesh_op_doc_get(BPy_BMeshOpFunc *self, void * /*closure*/)
{
PyObject *ret;
char *slot_in;
char *slot_out;
int i;
i = BMO_opcode_from_opname(self->opname);
slot_in = bmp_slots_as_args(bmo_opdefines[i]->slot_types_in, false);
slot_out = bmp_slots_as_args(bmo_opdefines[i]->slot_types_out, true);
ret = PyUnicode_FromFormat("%.200s bmesh.ops.%.200s(bmesh, %s)\n -> dict(%s)",
Py_TYPE(self)->tp_name,
self->opname,
slot_in,
slot_out);
MEM_freeN(slot_in);
MEM_freeN(slot_out);
return ret;
}
static PyGetSetDef bpy_bmesh_op_getseters[] = {
{"__doc__", (getter)bpy_bmesh_op_doc_get, (setter) nullptr, nullptr, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
/* Types
* ===== */
static PyTypeObject bmesh_op_Type = {
/*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
/*tp_name*/ "BMeshOpFunc",
/*tp_basicsize*/ sizeof(BPy_BMeshOpFunc),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ nullptr,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ nullptr,
/*tp_setattr*/ nullptr,
/*tp_as_async*/ nullptr,
/*tp_repr*/ (reprfunc)bpy_bmesh_op_repr,
/*tp_as_number*/ nullptr,
/*tp_as_sequence*/ nullptr,
/*tp_as_mapping*/ nullptr,
/*tp_hash*/ nullptr,
/*tp_call*/ (ternaryfunc)BPy_BMO_call,
/*tp_str*/ nullptr,
/*tp_getattro*/ nullptr,
/*tp_setattro*/ nullptr,
/*tp_as_buffer*/ nullptr,
/*tp_flags*/ Py_TPFLAGS_DEFAULT,
/*tp_doc*/ nullptr,
/*tp_traverse*/ nullptr,
/*tp_clear*/ nullptr,
/*tp_richcompare*/ nullptr,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ nullptr,
/*tp_iternext*/ nullptr,
/*tp_methods*/ nullptr,
/*tp_members*/ nullptr,
/*tp_getset*/ bpy_bmesh_op_getseters,
/*tp_base*/ nullptr,
/*tp_dict*/ nullptr,
/*tp_descr_get*/ nullptr,
/*tp_descr_set*/ nullptr,
/*tp_dictoffset*/ 0,
/*tp_init*/ nullptr,
/*tp_alloc*/ nullptr,
/*tp_new*/ nullptr,
/*tp_free*/ nullptr,
/*tp_is_gc*/ nullptr,
/*tp_bases*/ nullptr,
/*tp_mro*/ nullptr,
/*tp_cache*/ nullptr,
/*tp_subclasses*/ nullptr,
/*tp_weaklist*/ nullptr,
/*tp_del*/ nullptr,
/*tp_version_tag*/ 0,
/*tp_finalize*/ nullptr,
/*tp_vectorcall*/ nullptr,
};
/* bmesh module 'bmesh.ops'
* ************************ */
static PyObject *bpy_bmesh_op_CreatePyObject(const char *opname)
{
BPy_BMeshOpFunc *self = PyObject_New(BPy_BMeshOpFunc, &bmesh_op_Type);
self->opname = opname;
return (PyObject *)self;
}
static PyObject *bpy_bmesh_ops_module_getattro(PyObject * /*self*/, PyObject *pyname)
{
const char *opname = PyUnicode_AsUTF8(pyname);
if (BMO_opcode_from_opname(opname) != -1) {
return bpy_bmesh_op_CreatePyObject(opname);
}
PyErr_Format(PyExc_AttributeError, "BMeshOpsModule: operator \"%.200s\" doesn't exist", opname);
return nullptr;
}
static PyObject *bpy_bmesh_ops_module_dir(PyObject * /*self*/)
{
const uint tot = bmo_opdefines_total;
uint i;
PyObject *ret;
ret = PyList_New(bmo_opdefines_total);
for (i = 0; i < tot; i++) {
PyList_SET_ITEM(ret, i, PyUnicode_FromString(bmo_opdefines[i]->opname));
}
return ret;
}
#if (defined(__GNUC__) && !defined(__clang__))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
static PyMethodDef BPy_BM_ops_methods[] = {
{"__getattr__", (PyCFunction)bpy_bmesh_ops_module_getattro, METH_O, nullptr},
{"__dir__", (PyCFunction)bpy_bmesh_ops_module_dir, METH_NOARGS, nullptr},
{nullptr, nullptr, 0, nullptr},
};
#if (defined(__GNUC__) && !defined(__clang__))
# pragma GCC diagnostic pop
#endif
PyDoc_STRVAR(BPy_BM_ops_doc, "Access to BMesh operators");
static PyModuleDef BPy_BM_ops_module_def = {
/*m_base*/ PyModuleDef_HEAD_INIT,
/*m_name*/ "bmesh.ops",
/*m_doc*/ BPy_BM_ops_doc,
/*m_size*/ 0,
/*m_methods*/ BPy_BM_ops_methods,
/*m_slots*/ nullptr,
/*m_traverse*/ nullptr,
/*m_clear*/ nullptr,
/*m_free*/ nullptr,
};
PyObject *BPyInit_bmesh_ops()
{
PyObject *submodule = PyModule_Create(&BPy_BM_ops_module_def);
if (PyType_Ready(&bmesh_op_Type) < 0) {
return nullptr;
}
return submodule;
}