==Python API==
authorCampbell Barton <ideasman42@gmail.com>
Fri, 26 Oct 2007 08:19:40 +0000 (08:19 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 26 Oct 2007 08:19:40 +0000 (08:19 +0000)
layerMask access for bone and armatures
Window.PoseMode() similar to Window.EditMode()

source/blender/python/api2_2x/Armature.c
source/blender/python/api2_2x/Bone.c
source/blender/python/api2_2x/Bone.h
source/blender/python/api2_2x/Window.c
source/blender/python/api2_2x/doc/Armature.py
source/blender/python/api2_2x/doc/Window.py
source/blender/src/drawimage.c

index 1ad5938c17ee7906dc3833ebbe84d95999385e99..47ee2564698e25028e302b7707a088cfcd89b258 100644 (file)
@@ -297,9 +297,7 @@ static int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value
                editbone->zwidth = ((BPy_EditBone*)value)->zwidth;
                VECCOPY(editbone->head, ((BPy_EditBone*)value)->head);
                VECCOPY(editbone->tail, ((BPy_EditBone*)value)->tail);
-               
-               // FIXME, should be exposed via python. this avoids creating bones with no layers.
-               editbone->layer= 1;
+               editbone->layer= ((BPy_EditBone*)value)->layer;
                
                //set object pointer
                ((BPy_EditBone*)value)->editbone = editbone;
@@ -927,6 +925,36 @@ AttributeError:
        return EXPP_intError(PyExc_AttributeError, "%s%s", 
                sArmatureError, "You are not allowed to change the .Bones attribute");
 }
+
+//------------------------Bone.layerMask (get)
+static PyObject *Armature_getLayerMask(BPy_Armature *self)
+{
+       /* do this extra stuff because the short's bits can be negative values */
+       unsigned short laymask = 0;
+       laymask |= self->armature->layer;
+       return PyInt_FromLong((int)laymask);
+}
+//------------------------Bone.layerMask (set)
+static int Armature_setLayerMask(BPy_Armature *self, PyObject *value)
+{
+       int laymask;
+       if (!PyInt_Check(value)) {
+               return EXPP_ReturnIntError( PyExc_AttributeError,
+                                                                       "expected an integer (bitmask) as argument" );
+       }
+       
+       laymask = PyInt_AsLong(value);
+
+       if (laymask <= 0 || laymask > (1<<16) - 1)
+               return EXPP_ReturnIntError( PyExc_AttributeError,
+                                                                       "bitmask must have from 1 up to 16 bits set");
+
+       self->armature->layer = 0;
+       self->armature->layer |= laymask;
+
+       return 0;
+}
+
 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
 //------------------------tp_doc
 //The __doc__ string for this object
@@ -974,6 +1002,8 @@ static PyGetSetDef BPy_Armature_getset[] = {
                "Adds temporal IK chains while grabbing bones", NULL},
        {"layers", (getter)Armature_getLayers, (setter)Armature_setLayers, 
                "List of layers for the armature", NULL},
+       {"layerMask", (getter)Armature_getLayerMask, (setter)Armature_setLayerMask, 
+               "Layer bitmask", NULL },
        {NULL, NULL, NULL, NULL, NULL}
 };
 //------------------------tp_new
index 733b825121528c7d9cf3cc522f5c07a4cf451192..5eeb4bb28174d77fbd1a223c119e1d9c237e386e 100644 (file)
@@ -709,6 +709,40 @@ AttributeError:
                sEditBoneError, ".tailRadius: ", "expects a float");
 }
 
+//------------------------Bone.layerMask (get)
+static PyObject *EditBone_getLayerMask(BPy_EditBone *self)
+{
+       /* do this extra stuff because the short's bits can be negative values */
+       unsigned short laymask = 0;
+       if (self->editbone)     laymask |= self->editbone->layer;
+       else                            laymask |= self->layer;
+       return PyInt_FromLong((int)laymask);
+}
+//------------------------Bone.layerMask (set)
+static int EditBone_setLayerMask(BPy_EditBone *self, PyObject *value)
+{
+       int laymask;
+       if (!PyInt_Check(value)) {
+               return EXPP_ReturnIntError( PyExc_AttributeError,
+                                                                       "expected an integer (bitmask) as argument" );
+       }
+       
+       laymask = PyInt_AsLong(value);
+
+       if (laymask <= 0 || laymask > (1<<16) - 1)
+               return EXPP_ReturnIntError( PyExc_AttributeError,
+                                                                       "bitmask must have from 1 up to 16 bits set");
+       
+       if (self->editbone) {
+               self->editbone->layer = 0;
+               self->editbone->layer |= laymask;
+       } else {
+               self->layer = 0;
+               self->layer |= laymask;
+       }
+       
+       return 0;
+}
 
 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
 //------------------------tp_methods
@@ -749,6 +783,8 @@ static PyGetSetDef BPy_EditBone_getset[] = {
                "Set the radius of this bones tip", NULL},
        {"headRadius", (getter)EditBone_getHeadRadius, (setter)EditBone_setHeadRadius, 
                "Set the radius of this bones head", NULL},
+       {"layerMask", (getter)EditBone_getLayerMask, (setter)EditBone_setLayerMask, 
+               "Layer bitmask", NULL },
        {NULL, NULL, NULL, NULL,NULL}
 };
 
@@ -803,6 +839,7 @@ static PyObject *EditBone_new(PyTypeObject *type, PyObject *args, PyObject *kwds
        py_editBone->rad_head= 0.10f;
        py_editBone->rad_tail= 0.05f;
        py_editBone->segments= 1;
+       py_editBone->layer= 1;
        py_editBone->flag = 0;
        py_editBone->roll = 0.0f;
 
@@ -1203,6 +1240,35 @@ AttributeError:
                sEditBoneError, ".headRadius: ", "expects a float");
 }
 
+//------------------------Bone.layerMask (get)
+static PyObject *Bone_getLayerMask(BPy_Bone *self)
+{
+       /* do this extra stuff because the short's bits can be negative values */
+       unsigned short laymask = 0;
+       laymask |= self->bone->layer;
+       return PyInt_FromLong((int)laymask);
+}
+//------------------------Bone.layerMask (set)
+static int Bone_setLayerMask(BPy_Bone *self, PyObject *value)
+{
+       int laymask;
+       if (!PyInt_Check(value)) {
+               return EXPP_ReturnIntError( PyExc_AttributeError,
+                                                                       "expected an integer (bitmask) as argument" );
+       }
+       
+       laymask = PyInt_AsLong(value);
+
+       if (laymask <= 0 || laymask > (1<<16) - 1)
+               return EXPP_ReturnIntError( PyExc_AttributeError,
+                                                                       "bitmask must have from 1 up to 16 bits set");
+
+       self->bone->layer = 0;
+       self->bone->layer |= laymask;
+
+       return 0;
+}
+
 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
 //------------------------tp_methods
 //This contains a list of all methods the object contains
@@ -1246,6 +1312,8 @@ static PyGetSetDef BPy_Bone_getset[] = {
                "Set the radius of this bones tip", NULL},
        {"headRadius", (getter)Bone_getHeadRadius, (setter)Bone_setHeadRadius, 
                "Set the radius of this bones head", NULL},
+       {"layerMask", (getter)Bone_getLayerMask, (setter)Bone_setLayerMask, 
+               "Layer bitmask", NULL },
        {NULL, NULL, NULL, NULL,NULL}
 };
 //------------------------tp_repr
index c3f5de81714606d8f499a1943052172d22c09f2e..aa076afbed75f63d6c52a303e46ac348541d6dc0 100644 (file)
@@ -65,6 +65,7 @@ typedef struct {
        float rad_head;
        float rad_tail;
        short segments;
+       short layer;
 } BPy_EditBone;
 /*-------------------VISIBLE PROTOTYPES-------------------------*/
 PyObject *PyBone_FromBone(struct Bone *bone);
index 9bcf1290bb0ae5e96214d802529ae924dda821e3..323f209651aa7ea358bda4c98406e543ad7db578 100644 (file)
@@ -47,6 +47,7 @@
 #include "BIF_screen.h"
 #include "BIF_space.h"
 #include "BIF_drawtext.h"
+#include "BIF_poseobject.h"
 #include "DNA_view3d_types.h"
 #include "DNA_space_types.h"
 #include "DNA_scene_types.h"
@@ -86,6 +87,7 @@ static PyObject *M_Window_GetPerspMatrix( PyObject * self );
 static PyObject *M_Window_FileSelector( PyObject * self, PyObject * args );
 static PyObject *M_Window_ImageSelector( PyObject * self, PyObject * args );
 static PyObject *M_Window_EditMode( PyObject * self, PyObject * args );
+static PyObject *M_Window_PoseMode( PyObject * self, PyObject * args );
 static PyObject *M_Window_ViewLayers( PyObject * self, PyObject * args );
 static PyObject *M_Window_CameraView( PyObject * self, PyObject * args );
 static PyObject *M_Window_QTest( PyObject * self );
@@ -180,6 +182,9 @@ Returns the current status.  This function is mostly useful to leave\n\
 edit mode before applying changes to a mesh (otherwise the changes will\n\
 be lost) and then returning to it upon leaving.";
 
+static char M_Window_PoseMode_doc[] =
+               "() - Get the current status -- 0: not in pose mode; 1: in edit mode";
+
 static char M_Window_ViewLayers_doc[] =
        "(layers = [], winid = None) - Get/set active layers in all 3d View windows.\n\
 () - Make no changes, only return currently visible layers.\n\
@@ -325,6 +330,8 @@ struct PyMethodDef M_Window_methods[] = {
         M_Window_GetPerspMatrix_doc},
        {"EditMode", ( PyCFunction ) M_Window_EditMode, METH_VARARGS,
         M_Window_EditMode_doc},
+       {"PoseMode", ( PyCFunction ) M_Window_PoseMode, METH_VARARGS,
+        M_Window_PoseMode_doc},
        {"ViewLayers", ( PyCFunction ) M_Window_ViewLayers, METH_VARARGS,
         M_Window_ViewLayers_doc},
         /* typo, deprecate someday: */
@@ -949,6 +956,32 @@ static PyObject *M_Window_EditMode( PyObject * self, PyObject * args )
        return Py_BuildValue( "h", G.obedit ? 1 : 0 );
 }
 
+static PyObject *M_Window_PoseMode( PyObject * self, PyObject * args )
+{
+       short status = -1;
+       short is_posemode = 0;
+       Base *base;
+       
+       if( !PyArg_ParseTuple( args, "|h", &status ) )
+               return EXPP_ReturnPyObjError( PyExc_TypeError,
+                                                                         "expected optional int (bool) as argument" );
+
+       if( status >= 0 ) {
+               if( status ) {
+                       enter_posemode();
+               } else if( G.obedit ) {
+                       exit_posemode();
+               }
+       }
+
+       base= BASACT;
+       if (base && base->object->flag & OB_POSEMODE) {
+               is_posemode = 1;
+       }
+       
+       return Py_BuildValue( "h", is_posemode );
+}
+
 static PyObject *M_Window_ViewLayers( PyObject * self, PyObject * args )
 {
        PyObject *item = NULL;
index 157e8b28656b6c5eb90b3c8ed79ee3292d55203c..0dbaf28d6f878f510a8010ab0c18c453bf9d65a5 100644 (file)
@@ -156,6 +156,11 @@ class Armature:
        @type mirrorEdit: Bool
        @ivar autoIK: Adds temporary IK chains while grabbing bones
        @type autoIK: Bool
+       @ivar layerMask: Layer bitmask
+               Example::
+                       # set armature to layers 14 and 16
+                       armature.layerMask = (1<<13) + (1<<15)
+       @type layerMask: Int
        """
 
        def __init__(name = 'myArmature'):
@@ -282,6 +287,11 @@ class Bone:
        @type headRadius: Float
        @ivar tailRadius: The radius of this bones head (used for envalope bones)
        @type tailRadius: Float
+       @ivar layerMask: Layer bitmask
+               Example::
+                       # set bone to layers 14 and 16
+                       bone.layerMask = (1<<13) + (1<<15)
+       @type layerMask: Int
        """
 
        def hasParent():
index d59b5ec9fa6079e8d45f2eee5bfb1fae9a60aa87..b5145d34ca2d68f16673545a67cf74d7bb305f6e 100644 (file)
@@ -284,6 +284,20 @@ def EditMode(enable = -1, undo_msg = 'From script', undo = 1):
       because the normal mesh will be rebuilt based on its unchanged edit mesh.
   """
 
+def PoseMode(enable = -1):
+  """
+  Get and optionally set the current pose mode status: in or out.
+  @type enable: int
+  @param enable: get/set current status:
+      - -1: just return current status (default);
+      -  0: leave edit mode;
+      -  1: enter edit mode.
+
+  @return: 0 if Blender is not in edit mode right now, 1 otherwise. 
+  @warn: This uses the active armature objects posemode status, enabling pose
+      mode for non armature objects will always fail.
+  """
+
 def ViewLayers (layers = [], winid = None):
   """
   Get and optionally set the currently visible layers in all 3d Views.
index 85be429892234cafa6837a77af3d9b3b525582f7..f75de0bb331690ccdb1f6f5803bc53d8d47c0d88 100644 (file)
@@ -424,7 +424,7 @@ static void drawcursor_sima(float xuser_asp, float yuser_asp)
        int wi, hi;
        float w, h;
        
-       if (!G.obedit) return;
+       if (!G.obedit || !CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE)) return;
        
        transform_width_height_tface_uv(&wi, &hi);
        w = (((float)wi)/256.0f)*G.sima->zoom * xuser_asp;