Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Wed, 29 Nov 2017 10:30:03 +0000 (21:30 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 29 Nov 2017 10:32:16 +0000 (21:32 +1100)
1  2 
source/blender/python/intern/CMakeLists.txt
source/blender/python/intern/bpy.c
source/blender/python/intern/bpy_interface.c
source/blender/python/intern/bpy_library_load.c
source/blender/python/intern/bpy_rna.c
source/blender/python/intern/bpy_rna_manipulator.c

index 26fbc5d9eb267630f0366a853882615c654517c1,cdbf65546d3bdb1ea7c43cada18488688b690c2f..36aa310fe10be8ab7db54592c93dcc3cd9625d53
@@@ -78,14 -74,13 +75,16 @@@ set(SR
        bpy_rna_callback.c
        bpy_rna_driver.c
        bpy_rna_id_collection.c
 +      bpy_rna_manipulator.c
        bpy_traceback.c
-       bpy_util.c
        bpy_utils_previews.c
        bpy_utils_units.c
+       gpu.c
+       gpu_offscreen.c
++      gpu_py_matrix.c
++      gpu_py_select.c
        stubs.c
  
-       gpu.h
        bpy.h
        bpy_app.h
        bpy_app_alembic.h
        bpy_rna_callback.h
        bpy_rna_driver.h
        bpy_rna_id_collection.h
 +      bpy_rna_manipulator.h
        bpy_traceback.h
-       bpy_util.h
        bpy_utils_previews.h
        bpy_utils_units.h
+       gpu.h
        ../BPY_extern.h
  )
  
Simple merge
index 1b1d6294db65632933e2b64c2e61f7be01e067ba,20226ffe6a3050e5f9f3c7e3d0dd8578a7d2b463..4cd5e21bc22d72fe126521417756c3986ccb9d59
@@@ -46,9 -48,7 +46,9 @@@
  
  #include "DNA_space_types.h" /* FILE_LINK, FILE_RELPATH */
  
- #include "bpy_util.h"
 +#include "BLO_readfile.h"
 +
+ #include "bpy_capi_utils.h"
  #include "bpy_library.h"
  
  #include "../generic/py_capi_utils.h"
index 4a326ae657b33294663d76641fd574c61597c87c,0000000000000000000000000000000000000000..950f7f98be093e0b76423c38605da5e3d8cf86a4
mode 100644,000000..100644
--- /dev/null
@@@ -1,565 -1,0 +1,565 @@@
- #include "bpy_util.h"
 +/*
 + * ***** BEGIN GPL LICENSE BLOCK *****
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 + *
 + * ***** END GPL LICENSE BLOCK *****
 + */
 +
 +/** \file blender/python/intern/bpy_rna_manipulator.c
 + *  \ingroup pythonintern
 + *
 + * .
 + */
 +
 +#include <Python.h>
 +#include <stddef.h>
 +
 +#include "MEM_guardedalloc.h"
 +
 +#include "BLI_utildefines.h"
 +#include "BLI_alloca.h"
 +
 +#include "BKE_main.h"
 +
 +#include "WM_api.h"
 +#include "WM_types.h"
 +
++#include "bpy_capi_utils.h"
 +#include "bpy_rna_manipulator.h"
 +
 +#include "../generic/py_capi_utils.h"
 +#include "../generic/python_utildefines.h"
 +
 +#include "RNA_access.h"
 +#include "RNA_types.h"
 +#include "RNA_enum_types.h"
 +
 +#include "bpy_rna.h"
 +
 +
 +/* -------------------------------------------------------------------- */
 +/** \name Manipulator Target Property Define API
 + * \{ */
 +
 +enum {
 +      BPY_MANIPULATOR_FN_SLOT_GET = 0,
 +      BPY_MANIPULATOR_FN_SLOT_SET,
 +      BPY_MANIPULATOR_FN_SLOT_RANGE_GET,
 +};
 +#define BPY_MANIPULATOR_FN_SLOT_LEN (BPY_MANIPULATOR_FN_SLOT_RANGE_GET + 1)
 +
 +struct BPyManipulatorHandlerUserData {
 +
 +      PyObject *fn_slots[BPY_MANIPULATOR_FN_SLOT_LEN];
 +};
 +
 +static void py_rna_manipulator_handler_get_cb(
 +        const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
 +        void *value_p)
 +{
 +      PyGILState_STATE gilstate = PyGILState_Ensure();
 +
 +      struct BPyManipulatorHandlerUserData *data = mpr_prop->custom_func.user_data;
 +      PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_MANIPULATOR_FN_SLOT_GET], NULL);
 +      if (ret == NULL) {
 +              goto fail;
 +      }
 +
 +      if (mpr_prop->type->data_type == PROP_FLOAT) {
 +              float *value = value_p;
 +              if (mpr_prop->type->array_length == 1) {
 +                      if ((*value = PyFloat_AsDouble(ret)) == -1.0f && PyErr_Occurred()) {
 +                              goto fail;
 +                      }
 +              }
 +              else {
 +                      if (PyC_AsArray(value, ret, mpr_prop->type->array_length, &PyFloat_Type, false,
 +                                      "Manipulator get callback: ") == -1)
 +                      {
 +                              goto fail;
 +                      }
 +              }
 +      }
 +      else {
 +              PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
 +              goto fail;
 +      }
 +
 +      Py_DECREF(ret);
 +
 +      PyGILState_Release(gilstate);
 +      return;
 +
 +fail:
 +      PyErr_Print();
 +      PyErr_Clear();
 +
 +      PyGILState_Release(gilstate);
 +}
 +
 +static void py_rna_manipulator_handler_set_cb(
 +        const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
 +        const void *value_p)
 +{
 +      PyGILState_STATE gilstate = PyGILState_Ensure();
 +
 +      struct BPyManipulatorHandlerUserData *data = mpr_prop->custom_func.user_data;
 +
 +      PyObject *args = PyTuple_New(1);
 +
 +      if (mpr_prop->type->data_type == PROP_FLOAT) {
 +              const float *value = value_p;
 +              PyObject *py_value;
 +              if (mpr_prop->type->array_length == 1) {
 +                      py_value = PyFloat_FromDouble(*value);
 +              }
 +              else {
 +                      py_value =  PyC_Tuple_PackArray_F32(value, mpr_prop->type->array_length);
 +              }
 +              if (py_value == NULL) {
 +                      goto fail;
 +              }
 +              PyTuple_SET_ITEM(args, 0, py_value);
 +      }
 +      else {
 +              PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
 +              goto fail;
 +      }
 +
 +      PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_MANIPULATOR_FN_SLOT_SET], args);
 +      if (ret == NULL) {
 +              goto fail;
 +      }
 +      Py_DECREF(ret);
 +
 +      PyGILState_Release(gilstate);
 +      return;
 +
 +fail:
 +      PyErr_Print();
 +      PyErr_Clear();
 +
 +      Py_DECREF(args);
 +
 +      PyGILState_Release(gilstate);
 +}
 +
 +static void py_rna_manipulator_handler_range_get_cb(
 +        const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
 +        void *value_p)
 +{
 +      struct BPyManipulatorHandlerUserData *data = mpr_prop->custom_func.user_data;
 +
 +      PyGILState_STATE gilstate = PyGILState_Ensure();
 +
 +      PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_MANIPULATOR_FN_SLOT_RANGE_GET], NULL);
 +      if (ret == NULL) {
 +              goto fail;
 +      }
 +
 +      if (!PyTuple_Check(ret)) {
 +              PyErr_Format(PyExc_TypeError,
 +                           "Expected a tuple, not %.200s",
 +                           Py_TYPE(ret)->tp_name);
 +              goto fail;
 +      }
 +
 +      if (PyTuple_GET_SIZE(ret) != 2) {
 +              PyErr_Format(PyExc_TypeError,
 +                           "Expected a tuple of size 2, not %d",
 +                           PyTuple_GET_SIZE(ret));
 +              goto fail;
 +      }
 +
 +      if (mpr_prop->type->data_type == PROP_FLOAT) {
 +              float range[2];
 +              for (int i = 0; i < 2; i++) {
 +                      if (((range[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(ret, i))) == -1.0f && PyErr_Occurred()) == 0) {
 +                              /* pass */
 +                      }
 +                      else {
 +                              goto fail;
 +                      }
 +              }
 +              memcpy(value_p, range, sizeof(range));
 +      }
 +      else {
 +              PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type");
 +              goto fail;
 +      }
 +
 +      Py_DECREF(ret);
 +      PyGILState_Release(gilstate);
 +      return;
 +
 +fail:
 +      Py_XDECREF(ret);
 +
 +      PyErr_Print();
 +      PyErr_Clear();
 +
 +      PyGILState_Release(gilstate);
 +}
 +
 +static void py_rna_manipulator_handler_free_cb(
 +        const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop)
 +{
 +      struct BPyManipulatorHandlerUserData *data = mpr_prop->custom_func.user_data;
 +
 +      PyGILState_STATE gilstate = PyGILState_Ensure();
 +      for (int i = 0; i < BPY_MANIPULATOR_FN_SLOT_LEN; i++) {
 +              Py_XDECREF(data->fn_slots[i]);
 +      }
 +      PyGILState_Release(gilstate);
 +
 +      MEM_freeN(data);
 +
 +}
 +
 +PyDoc_STRVAR(bpy_manipulator_target_set_handler_doc,
 +".. method:: target_set_handler(target, get, set, range=None):\n"
 +"\n"
 +"   Assigns callbacks to a manipulators property.\n"
 +"\n"
 +"   :arg get: Function that returns the value for this property (single value or sequence).\n"
 +"   :type get: callable\n"
 +"   :arg set: Function that takes a single value argument and applies it.\n"
 +"   :type set: callable\n"
 +"   :arg range: Function that returns a (min, max) tuple for manipulators that use a range.\n"
 +"   :type range: callable\n"
 +);
 +static PyObject *bpy_manipulator_target_set_handler(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
 +{
 +      PyGILState_STATE gilstate = PyGILState_Ensure();
 +
 +      struct {
 +              PyObject *self;
 +              char *target;
 +              PyObject *py_fn_slots[BPY_MANIPULATOR_FN_SLOT_LEN];
 +      } params = {
 +              .self = NULL,
 +              .target = NULL,
 +              .py_fn_slots = {NULL},
 +      };
 +
 +      /* Note: this is a counter-part to functions:
 +       * 'Manipulator.target_set_prop & target_set_operator'
 +       * (see: rna_wm_manipulator_api.c). conventions should match. */
 +      static const char * const _keywords[] = {"self", "target", "get", "set", "range", NULL};
 +      static _PyArg_Parser _parser = {"Os|$OOO:target_set_handler", _keywords, 0};
 +      if (!_PyArg_ParseTupleAndKeywordsFast(
 +              args, kw, &_parser,
 +              &params.self,
 +              &params.target,
 +              &params.py_fn_slots[BPY_MANIPULATOR_FN_SLOT_GET],
 +              &params.py_fn_slots[BPY_MANIPULATOR_FN_SLOT_SET],
 +              &params.py_fn_slots[BPY_MANIPULATOR_FN_SLOT_RANGE_GET]))
 +      {
 +              goto fail;
 +      }
 +
 +      wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
 +
 +      const wmManipulatorPropertyType *mpr_prop_type =
 +              WM_manipulatortype_target_property_find(mpr->type, params.target);
 +      if (mpr_prop_type == NULL) {
 +              PyErr_Format(PyExc_ValueError,
 +                           "Manipulator target property '%s.%s' not found",
 +                           mpr->type->idname, params.target);
 +              goto fail;
 +      }
 +
 +      {
 +              const int slots_required = 2;
 +              const int slots_start = 2;
 +              for (int i = 0; i < BPY_MANIPULATOR_FN_SLOT_LEN; i++) {
 +                      if (params.py_fn_slots[i] == NULL) {
 +                              if (i < slots_required) {
 +                                      PyErr_Format(PyExc_ValueError, "Argument '%s' not given", _keywords[slots_start + i]);
 +                                      goto fail;
 +                              }
 +                      }
 +                      else if (!PyCallable_Check(params.py_fn_slots[i])) {
 +                              PyErr_Format(PyExc_ValueError, "Argument '%s' not callable", _keywords[slots_start + i]);
 +                              goto fail;
 +                      }
 +              }
 +      }
 +
 +      struct BPyManipulatorHandlerUserData *data = MEM_callocN(sizeof(*data), __func__);
 +
 +      for (int i = 0; i < BPY_MANIPULATOR_FN_SLOT_LEN; i++) {
 +              data->fn_slots[i] = params.py_fn_slots[i];
 +              Py_XINCREF(params.py_fn_slots[i]);
 +      }
 +
 +      WM_manipulator_target_property_def_func_ptr(
 +              mpr, mpr_prop_type,
 +              &(const struct wmManipulatorPropertyFnParams) {
 +                  .value_get_fn = py_rna_manipulator_handler_get_cb,
 +                  .value_set_fn = py_rna_manipulator_handler_set_cb,
 +                  .range_get_fn = py_rna_manipulator_handler_range_get_cb,
 +                  .free_fn = py_rna_manipulator_handler_free_cb,
 +                  .user_data = data,
 +              });
 +
 +      PyGILState_Release(gilstate);
 +
 +      Py_RETURN_NONE;
 +
 +fail:
 +      PyGILState_Release(gilstate);
 +      return NULL;
 +}
 +
 +/** \} */
 +
 +/* -------------------------------------------------------------------- */
 +/** \name Manipulator Target Property Access API
 + * \{ */
 +
 +PyDoc_STRVAR(bpy_manipulator_target_get_value_doc,
 +".. method:: target_get_value(target):\n"
 +"\n"
 +"   Get the value of this target property.\n"
 +"\n"
 +"   :arg target: Target property name.\n"
 +"   :type target: string\n"
 +"   :return: The value of the target property.\n"
 +"   :rtype: Single value or array based on the target type\n"
 +);
 +static PyObject *bpy_manipulator_target_get_value(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
 +{
 +      struct {
 +              PyObject *self;
 +              char *target;
 +      } params = {
 +              .self = NULL,
 +              .target = NULL,
 +      };
 +
 +      static const char * const _keywords[] = {"self", "target", NULL};
 +      static _PyArg_Parser _parser = {"Os:target_get_value", _keywords, 0};
 +      if (!_PyArg_ParseTupleAndKeywordsFast(
 +              args, kw, &_parser,
 +              &params.self,
 +              &params.target))
 +      {
 +              goto fail;
 +      }
 +
 +      wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
 +
 +      wmManipulatorProperty *mpr_prop =
 +              WM_manipulator_target_property_find(mpr, params.target);
 +      if (mpr_prop == NULL) {
 +              PyErr_Format(PyExc_ValueError,
 +                           "Manipulator target property '%s.%s' not found",
 +                           mpr->type->idname, params.target);
 +              goto fail;
 +      }
 +
 +      const int array_len = WM_manipulator_target_property_array_length(mpr, mpr_prop);
 +      switch (mpr_prop->type->data_type) {
 +              case PROP_FLOAT:
 +              {
 +                      if (array_len != 0) {
 +                              float *value = BLI_array_alloca(value, array_len);
 +                              WM_manipulator_target_property_value_get_array(mpr, mpr_prop, value);
 +                              return PyC_Tuple_PackArray_F32(value, array_len);
 +                      }
 +                      else {
 +                              float value = WM_manipulator_target_property_value_get(mpr, mpr_prop);
 +                              return PyFloat_FromDouble(value);
 +                      }
 +                      break;
 +              }
 +              default:
 +              {
 +                      PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
 +                      goto fail;
 +              }
 +      }
 +
 +fail:
 +      return NULL;
 +}
 +
 +PyDoc_STRVAR(bpy_manipulator_target_set_value_doc,
 +".. method:: target_set_value(target):\n"
 +"\n"
 +"   Set the value of this target property.\n"
 +"\n"
 +"   :arg target: Target property name.\n"
 +"   :type target: string\n"
 +);
 +static PyObject *bpy_manipulator_target_set_value(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
 +{
 +      struct {
 +              PyObject *self;
 +              char *target;
 +              PyObject *value;
 +      } params = {
 +              .self = NULL,
 +              .target = NULL,
 +              .value = NULL,
 +      };
 +
 +      static const char * const _keywords[] = {"self", "target", "value", NULL};
 +      static _PyArg_Parser _parser = {"OsO:target_set_value", _keywords, 0};
 +      if (!_PyArg_ParseTupleAndKeywordsFast(
 +              args, kw, &_parser,
 +              &params.self,
 +              &params.target,
 +              &params.value))
 +      {
 +              goto fail;
 +      }
 +
 +      wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
 +
 +      wmManipulatorProperty *mpr_prop =
 +              WM_manipulator_target_property_find(mpr, params.target);
 +      if (mpr_prop == NULL) {
 +              PyErr_Format(PyExc_ValueError,
 +                           "Manipulator target property '%s.%s' not found",
 +                           mpr->type->idname, params.target);
 +              goto fail;
 +      }
 +
 +      const int array_len = WM_manipulator_target_property_array_length(mpr, mpr_prop);
 +      switch (mpr_prop->type->data_type) {
 +              case PROP_FLOAT:
 +              {
 +                      if (array_len != 0) {
 +                              float *value = BLI_array_alloca(value, array_len);
 +                              if (PyC_AsArray(value, params.value, mpr_prop->type->array_length, &PyFloat_Type, false,
 +                                              "Manipulator target property array") == -1)
 +                              {
 +                                      goto fail;
 +                              }
 +                              WM_manipulator_target_property_value_set_array(BPy_GetContext(), mpr, mpr_prop, value);
 +                      }
 +                      else {
 +                              float value;
 +                              if ((value = PyFloat_AsDouble(params.value)) == -1.0f && PyErr_Occurred()) {
 +                                      goto fail;
 +                              }
 +                              WM_manipulator_target_property_value_set(BPy_GetContext(), mpr, mpr_prop, value);
 +                      }
 +                      Py_RETURN_NONE;
 +              }
 +              default:
 +              {
 +                      PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
 +                      goto fail;
 +              }
 +      }
 +
 +fail:
 +      return NULL;
 +}
 +
 +
 +PyDoc_STRVAR(bpy_manipulator_target_get_range_doc,
 +".. method:: target_get_range(target):\n"
 +"\n"
 +"   Get the range for this target property.\n"
 +"\n"
 +"   :arg target: Target property name.\n"
 +"   :Get the range for this target property"
 +"   :return: The range of this property (min, max).\n"
 +"   :rtype: tuple pair.\n"
 +);
 +static PyObject *bpy_manipulator_target_get_range(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
 +{
 +      struct {
 +              PyObject *self;
 +              char *target;
 +      } params = {
 +              .self = NULL,
 +              .target = NULL,
 +      };
 +
 +      static const char * const _keywords[] = {"self", "target", NULL};
 +      static _PyArg_Parser _parser = {"Os:target_get_range", _keywords, 0};
 +      if (!_PyArg_ParseTupleAndKeywordsFast(
 +              args, kw, &_parser,
 +              &params.self,
 +              &params.target))
 +      {
 +              goto fail;
 +      }
 +
 +      wmManipulator *mpr = ((BPy_StructRNA *)params.self)->ptr.data;
 +
 +      wmManipulatorProperty *mpr_prop =
 +              WM_manipulator_target_property_find(mpr, params.target);
 +      if (mpr_prop == NULL) {
 +              PyErr_Format(PyExc_ValueError,
 +                           "Manipulator target property '%s.%s' not found",
 +                           mpr->type->idname, params.target);
 +              goto fail;
 +      }
 +
 +      switch (mpr_prop->type->data_type) {
 +              case PROP_FLOAT:
 +              {
 +                      float range[2];
 +                      WM_manipulator_target_property_range_get(mpr, mpr_prop, range);
 +                      return PyC_Tuple_PackArray_F32(range, 2);
 +              }
 +              default:
 +              {
 +                      PyErr_SetString(PyExc_RuntimeError, "Not yet supported type");
 +                      goto fail;
 +              }
 +      }
 +
 +fail:
 +      return NULL;
 +}
 +
 +/** \} */
 +
 +int BPY_rna_manipulator_module(PyObject *mod_par)
 +{
 +      static PyMethodDef method_def_array[] = {
 +              /* Manipulator Target Property Define API */
 +              {"target_set_handler", (PyCFunction)bpy_manipulator_target_set_handler,
 +               METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_set_handler_doc},
 +              /* Manipulator Target Property Access API */
 +              {"target_get_value", (PyCFunction)bpy_manipulator_target_get_value,
 +               METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_get_value_doc},
 +              {"target_set_value", (PyCFunction)bpy_manipulator_target_set_value,
 +               METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_set_value_doc},
 +              {"target_get_range", (PyCFunction)bpy_manipulator_target_get_range,
 +               METH_VARARGS | METH_KEYWORDS, bpy_manipulator_target_get_range_doc},
 +              /* no sentinel needed. */
 +      };
 +
 +      for (int i = 0; i < ARRAY_SIZE(method_def_array); i++) {
 +              PyMethodDef *m = &method_def_array[i];
 +              PyObject *func = PyCFunction_New(m, NULL);
 +              PyObject *func_inst = PyInstanceMethod_New(func);
 +              char name_prefix[128];
 +              PyOS_snprintf(name_prefix, sizeof(name_prefix), "_rna_manipulator_%s", m->ml_name);
 +              /* TODO, return a type that binds nearly to a method. */
 +              PyModule_AddObject(mod_par, name_prefix, func_inst);
 +      }
 +
 +      return 0;
 +}