Merge from trunk
authorIan Thompson <quornian@googlemail.com>
Sat, 26 Jul 2008 10:45:11 +0000 (10:45 +0000)
committerIan Thompson <quornian@googlemail.com>
Sat, 26 Jul 2008 10:45:11 +0000 (10:45 +0000)
revs. 15635:15771

136 files changed:
projectfiles_vc7/blender/makesdna/DNA_makesdna.vcproj
projectfiles_vc7/blender/src/BL_src.vcproj
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/BKE_idprop.h
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/idprop.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenlib/intern/arithb.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/BDR_drawaction.h
source/blender/include/BDR_gpencil.h [new file with mode: 0644]
source/blender/include/BIF_drawgpencil.h [new file with mode: 0644]
source/blender/include/BIF_editaction.h
source/blender/include/BIF_space.h
source/blender/include/BSE_drawview.h
source/blender/include/BSE_editaction_types.h
source/blender/include/transform.h
source/blender/makesdna/DNA_ID.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_actuator_types.h
source/blender/makesdna/DNA_gpencil_types.h [new file with mode: 0644]
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesdna/intern/makesdna.c
source/blender/nodes/intern/SHD_nodes/SHD_material.c
source/blender/nodes/intern/SHD_util.c
source/blender/nodes/intern/SHD_util.h
source/blender/python/BPY_interface.c
source/blender/python/api2_2x/Blender.c
source/blender/python/api2_2x/IDProp.c
source/blender/python/api2_2x/Library.c
source/blender/python/api2_2x/Particle.c
source/blender/python/api2_2x/doc/IDProp.py
source/blender/python/api2_2x/doc/Ipo.py
source/blender/python/api2_2x/doc/LibData.py
source/blender/python/api2_2x/doc/Particle.py
source/blender/python/api2_2x/sceneRender.c
source/blender/render/intern/source/shadeoutput.c
source/blender/src/buttons_editing.c
source/blender/src/buttons_logic.c
source/blender/src/drawaction.c
source/blender/src/drawgpencil.c [new file with mode: 0644]
source/blender/src/drawnode.c
source/blender/src/drawobject.c
source/blender/src/drawseq.c
source/blender/src/drawview.c
source/blender/src/editaction.c
source/blender/src/editaction_gpencil.c [new file with mode: 0644]
source/blender/src/editnode.c
source/blender/src/editseq.c
source/blender/src/gpencil.c [new file with mode: 0644]
source/blender/src/header_action.c
source/blender/src/header_node.c
source/blender/src/header_seq.c
source/blender/src/header_view3d.c
source/blender/src/interface.c
source/blender/src/interface_draw.c
source/blender/src/outliner.c
source/blender/src/space.c
source/blender/src/transform_conversions.c
source/blender/src/transform_generics.c
source/blender/src/usiblender.c
source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
source/gameengine/BlenderRoutines/KX_BlenderCanvas.h
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/BL_DeformableGameObject.h
source/gameengine/Converter/BL_ShapeActionActuator.cpp
source/gameengine/Converter/BL_ShapeActionActuator.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Converter/KX_IpoConvert.cpp
source/gameengine/Converter/KX_IpoConvert.h
source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
source/gameengine/GameLogic/SCA_ActuatorSensor.h
source/gameengine/GameLogic/SCA_ILogicBrick.cpp
source/gameengine/GameLogic/SCA_ILogicBrick.h
source/gameengine/GameLogic/SCA_ISensor.cpp
source/gameengine/GameLogic/SCA_ISensor.h
source/gameengine/GameLogic/SCA_PropertyActuator.cpp
source/gameengine/GameLogic/SCA_PropertyActuator.h
source/gameengine/GamePlayer/common/GPC_Canvas.h
source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
source/gameengine/Ketsji/KX_BulletPhysicsController.h
source/gameengine/Ketsji/KX_CameraActuator.cpp
source/gameengine/Ketsji/KX_CameraActuator.h
source/gameengine/Ketsji/KX_ConstraintActuator.cpp
source/gameengine/Ketsji/KX_ConstraintActuator.h
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_IPhysicsController.h
source/gameengine/Ketsji/KX_IpoActuator.cpp
source/gameengine/Ketsji/KX_IpoActuator.h
source/gameengine/Ketsji/KX_MaterialIpoController.cpp
source/gameengine/Ketsji/KX_MaterialIpoController.h
source/gameengine/Ketsji/KX_ObjectActuator.cpp
source/gameengine/Ketsji/KX_ObjectActuator.h
source/gameengine/Ketsji/KX_OdePhysicsController.cpp
source/gameengine/Ketsji/KX_OdePhysicsController.h
source/gameengine/Ketsji/KX_ParentActuator.cpp
source/gameengine/Ketsji/KX_ParentActuator.h
source/gameengine/Ketsji/KX_PyMath.h
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_RadarSensor.cpp
source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_SceneActuator.cpp
source/gameengine/Ketsji/KX_SceneActuator.h
source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
source/gameengine/Ketsji/KX_SumoPhysicsController.h
source/gameengine/Ketsji/KX_TrackToActuator.cpp
source/gameengine/Ketsji/KX_TrackToActuator.h
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
source/gameengine/PyDoc/BL_ShapeActionActuator.py [new file with mode: 0644]
source/gameengine/PyDoc/KX_ActuatorSensor.py [new file with mode: 0644]
source/gameengine/PyDoc/KX_ConstraintActuator.py
source/gameengine/PyDoc/KX_GameObject.py
source/gameengine/PyDoc/KX_IpoActuator.py
source/gameengine/PyDoc/KX_ObjectActuator.py
source/gameengine/PyDoc/KX_StateActuator.py [new file with mode: 0644]
source/gameengine/PyDoc/SCA_ISensor.py
source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
source/gameengine/Rasterizer/RAS_2DFilterManager.h
source/gameengine/Rasterizer/RAS_ICanvas.h
source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
source/gameengine/Rasterizer/RAS_MeshObject.cpp
source/gameengine/Rasterizer/RAS_MeshObject.h

index 04d964ba657b3c69d8545264ab22428330aff27e..6ad16dec52c102c11471f2909b18423f894598d3 100644 (file)
@@ -471,6 +471,9 @@ DNA_makesdna.exe dna.c
                        <File
                                RelativePath="..\..\..\source\blender\makesdna\DNA_fileglobal_types.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\makesdna\DNA_gpencil_types.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\makesdna\DNA_group_types.h">
                        </File>
index 226bedbbfd8567241622b0a864aa9d750ff6c74a..153d9a90b2392e463b5f86aef8a2f80b3a1c4ef9 100644 (file)
                        <File
                                RelativePath="..\..\..\source\blender\src\drawdeps.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\src\drawgpencil.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\src\drawimage.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\src\editaction.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\src\editaction_gpencil.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\src\editarmature.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\src\glutil.c">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\src\gpencil.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\src\hddaudio.c">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\include\BDR_editobject.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\include\BDR_gpencil.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\include\BDR_imagepaint.h">
                        </File>
                        <File
                                RelativePath="..\..\..\source\blender\include\BIF_cursors.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\source\blender\include\BIF_drawgpencil.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\source\blender\include\BIF_drawimage.h">
                        </File>
index 62289d227c762f74a67d3543f208db45a2c89ef4..8c9634cba06051e5df877e3be8ef539bc14497ec 100644 (file)
@@ -175,6 +175,7 @@ typedef struct Global {
 #define G_WEIGHTPAINT  (1 << 15)       
 #define G_TEXTUREPAINT (1 << 16)
 /* #define G_NOFROZEN  (1 << 17) also removed */
+#define G_GREASEPENCIL         (1 << 17)
 #define G_DRAWEDGES            (1 << 18)
 #define G_DRAWCREASES  (1 << 19)
 #define G_DRAWSEAMS     (1 << 20)
@@ -265,3 +266,4 @@ extern Global G;
        
 #endif
 
+
index 2d7d0e9286fceda6c1a1c8c83a6d7ac3ebf66da5..2274c54ad3bdea8a58207d1b4ac33e0901c5fc9c 100644 (file)
@@ -46,6 +46,7 @@ struct ID;
 typedef union {
        int i;
        float f;
+       double d;
        char *str;
        struct ID *id;
        struct {
index c913820205b4ac8cadb66fb6174f2b40414fe355..0feb055eec93cb5298b36178651a96e8511f09d8 100644 (file)
@@ -1,4 +1,3 @@
-
 /**
  * $Id$
  *
@@ -356,6 +355,8 @@ TimeMarker *get_frame_marker(int frame){return 0;};
 /* editseq.c */
 Sequence *get_forground_frame_seq(int frame){return 0;};
 void set_last_seq(Sequence *seq){};
+void clear_last_seq(Sequence *seq){};
+    
 
 /* modifier.c stub */
 void harmonic_coordinates_bind(struct MeshDeformModifierData *mmd,
index 26c5d186d8703b995d22aca66ccd1ede9d293ece..6dfb77504fb3d7cf6babdf2104fc0dd07fc620f0 100644 (file)
@@ -1437,6 +1437,9 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj)
 
                                        if(coll_ob == self)
                                                continue;
+                                       
+                                       if( !collmd->bvhtree)
+                                               continue;
 
                                        if(numobj >= maxobj)
                                        {
index 2ef2f3a1b770ba095633b7ed5707a39811e5ffdc..b16f52571f63bbedb006f52154537ebdfa86ba29 100644 (file)
@@ -54,7 +54,8 @@ static char idp_size_table[] = {
        sizeof(float)*16, /*Matrix type, deprecated*/
        0, /*arrays don't have a fixed size*/
        sizeof(ListBase), /*Group type*/
-       sizeof(void*)
+       sizeof(void*),
+       sizeof(double)
 };
 
 
@@ -365,10 +366,14 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, char *name)
                        prop = MEM_callocN(sizeof(IDProperty), "IDProperty float");
                        *(float*)&prop->data.val = val.f;
                        break;
+               case IDP_DOUBLE:
+                       prop = MEM_callocN(sizeof(IDProperty), "IDProperty float");
+                       *(double*)&prop->data.val = val.d;
+                       break;          
                case IDP_ARRAY:
                {
-                       /*for now, we only support float and int arrays*/
-                       if (val.array.type == IDP_FLOAT || val.array.type == IDP_INT) {
+                       /*for now, we only support float and int and double arrays*/
+                       if (val.array.type == IDP_FLOAT || val.array.type == IDP_INT || val.array.type == IDP_DOUBLE) {
                                prop = MEM_callocN(sizeof(IDProperty), "IDProperty array");
                                prop->len = prop->totallen = val.array.len;
                                prop->subtype = val.array.type;
@@ -411,6 +416,10 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, char *name)
 
        prop->type = type;
        strncpy(prop->name, name, MAX_IDPROP_NAME);
+       
+       /*security null byte*/
+       prop->name[MAX_IDPROP_NAME-1] = 0;
+       
        return prop;
 }
 
index e8bcae42d5a97764732e1a237d345427747cd5f1..54915058bab7b21778a8c29ff0a3db9d86e04ab2 100644 (file)
@@ -915,7 +915,10 @@ void lattice_calc_modifiers(Object *ob)
                mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
        }
 
-       if (vertexCos) {
+       /* always displist to make this work like derivedmesh */
+       if (!vertexCos) vertexCos = lattice_getVertexCos(ob, &numVerts);
+       
+       {
                DispList *dl = MEM_callocN(sizeof(*dl), "lt_dl");
                dl->type = DL_VERTS;
                dl->parts = 1;
index f70648965f413a5b9474f12cc2ae1150f1ee8c90..7dca87d5c135ad53b2de60acda7a7af89b365e44 100644 (file)
@@ -2797,7 +2797,10 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
                                epart= epsys->part;
                                pd= epart->pd;
                                totepart= epsys->totpart;
-
+                               
+                               if(totepart <= 0)
+                                       continue;
+                               
                                if(pd->forcefield==PFIELD_HARMONIC){
                                        /* every particle is mapped to only one harmonic effector particle */
                                        p= pa_no%epsys->totpart;
index 2898dca767c66406703d4f706d96bd5318885f47..553107dd2648aa782251243f34a72664ebcec1bb 100644 (file)
@@ -303,7 +303,7 @@ void set_scene_bg(Scene *sce)
        int flag;
        
        // Note: this here is defined in editseq.c (BIF_editseq.h), NOT in blenkernel! 
-       set_last_seq(NULL);
+       clear_last_seq();
        
        G.scene= sce;
        
index 9005db1312fa47c1c680033d9676bda0d94b993b..d5b5ab6d63e65eb5dd61bee4a794948b5be0897c 100644 (file)
@@ -2053,7 +2053,6 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
        
        /* check conditions for various options */
        do_deflector= query_external_colliders(ob);
-       do_effector= pdInitEffectors(ob,NULL);
        do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
        do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
        do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
@@ -2061,9 +2060,10 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int
        iks  = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
        bproot= sb->bpoint; /* need this for proper spring addressing */
        
-
-       
        if (do_springcollision || do_aero)  scan_for_ext_spring_forces(ob,timenow);
+       /* after spring scan because it uses Effoctors too */
+       do_effector= pdInitEffectors(ob,NULL);
+
        if (do_deflector) {
                float defforce[3];
                do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow);
index b7598ec0c4d1f9fc96d73d6d786fb78188128bf6..8bd7ad405af82b5e2ef492a69830c83051ad65bc 100644 (file)
@@ -2536,11 +2536,6 @@ int IsectPQ2Df(float pt[2], float v1[2], float v2[2], float v3[2], float v4[2])
 }
 
 
-
-                       /* copied from Geometry.c - todo - move to arithb.c or some other generic place we can reuse */
-#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1]))
-#define POINT_IN_TRI(p0,p1,p2,p3)      ((SIDE_OF_LINE(p1,p2,p0)>=0) && (SIDE_OF_LINE(p2,p3,p0)>=0) && (SIDE_OF_LINE(p3,p1,p0)>=0))
-
 /**
  * 
  * @param min 
index 3c629818b2dd0204fe899b1804aeeebd584ae36d..ad004dd5c8216509e59c967dec8cadf947351978 100644 (file)
@@ -69,6 +69,7 @@
 #include "DNA_effect_types.h"
 #include "DNA_fileglobal_types.h"
 #include "DNA_group_types.h"
+#include "DNA_gpencil_types.h"
 #include "DNA_ipo_types.h"
 #include "DNA_image_types.h"
 #include "DNA_key_types.h"
@@ -1346,8 +1347,14 @@ void IDP_DirectLinkArray(IDProperty *prop, int switch_endian, void *fd)
        prop->data.pointer = newdataadr(fd, prop->data.pointer);
 
        if (switch_endian) {
-               for (i=0; i<prop->len; i++) {
-                       SWITCH_INT(((int*)prop->data.pointer)[i]);
+               if (prop->subtype != IDP_DOUBLE) {
+                       for (i=0; i<prop->len; i++) {
+                               SWITCH_INT(((int*)prop->data.pointer)[i]);
+                       }
+               } else {
+                       for (i=0; i<prop->len; i++) {
+                               SWITCH_LONGINT(((double*)prop->data.pointer)[i]);
+                       }
                }
        }
 }
@@ -1383,6 +1390,24 @@ void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, void *fd)
                        break;
                case IDP_ARRAY:
                        IDP_DirectLinkArray(prop, switch_endian, fd);
+                       break;
+               case IDP_DOUBLE:
+                       /*erg, stupid doubles.  since I'm storing them
+                        in the same field as int val; val2 in the
+                        IDPropertyData struct, they have to deal with
+                        endianness specifically
+                        
+                        in theory, val and val2 would've already been swapped
+                        if switch_endian is true, so we have to first unswap
+                        them then reswap them as a single 64-bit entity.
+                        */
+                       
+                       if (switch_endian) {
+                               SWITCH_INT(prop->data.val);
+                               SWITCH_INT(prop->data.val2);
+                               SWITCH_LONGINT(prop->data.val);
+                       }
+                       
                        break;
        }
 }
@@ -3698,6 +3723,32 @@ static void lib_link_screen_sequence_ipos(Main *main)
 
 /* ************ READ SCREEN ***************** */
 
+/* relinks grease-pencil data for 3d-view(s) - used for direct_link */
+static void link_gpencil(FileData *fd, bGPdata *gpd)
+{
+       bGPDlayer *gpl;
+       bGPDframe *gpf;
+       bGPDstroke *gps;
+       
+       /* relink layers */
+       link_list(fd, &gpd->layers);
+       
+       for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+               /* relink frames */
+               link_list(fd, &gpl->frames);
+               gpl->actframe= newdataadr(fd, gpl->actframe);
+               
+               for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+                       /* relink strokes (and their points) */
+                       link_list(fd, &gpf->strokes);
+                       
+                       for (gps= gpf->strokes.first; gps; gps= gps->next) {
+                               gps->points= newdataadr(fd, gps->points);
+                       }
+               }
+       }
+}
+
 /* note: file read without screens option G_FILE_NO_UI; 
    check lib pointers in call below */
 static void lib_link_screen(FileData *fd, Main *main)
@@ -3709,23 +3760,23 @@ static void lib_link_screen(FileData *fd, Main *main)
                if(sc->id.flag & LIB_NEEDLINK) {
                        sc->id.us= 1;
                        sc->scene= newlibadr(fd, sc->id.lib, sc->scene);
-
+                       
                        sa= sc->areabase.first;
                        while(sa) {
                                SpaceLink *sl;
-
+                               
                                sa->full= newlibadr(fd, sc->id.lib, sa->full);
-
+                               
                                /* space handler scriptlinks */
                                lib_link_scriptlink(fd, &sc->id, &sa->scriptlink);
-
+                               
                                for (sl= sa->spacedata.first; sl; sl= sl->next) {
                                        if(sl->spacetype==SPACE_VIEW3D) {
                                                View3D *v3d= (View3D*) sl;
-
+                                               
                                                v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
                                                v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre);
-
+                                               
                                                if(v3d->bgpic) {
                                                        v3d->bgpic->ima= newlibadr_us(fd, sc->id.lib, v3d->bgpic->ima);
                                                }
@@ -4081,6 +4132,10 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                v3d->bgpic= newdataadr(fd, v3d->bgpic);
                                if(v3d->bgpic)
                                        v3d->bgpic->iuser.ok= 1;
+                               if(v3d->gpd) {
+                                       v3d->gpd= newdataadr(fd, v3d->gpd);
+                                       link_gpencil(fd, v3d->gpd);
+                               }
                                v3d->localvd= newdataadr(fd, v3d->localvd);
                                v3d->afterdraw.first= v3d->afterdraw.last= NULL;
                                v3d->clipbb= newdataadr(fd, v3d->clipbb);
@@ -4115,9 +4170,21 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                        }
                        else if(sl->spacetype==SPACE_NODE) {
                                SpaceNode *snode= (SpaceNode *)sl;
+                               
+                               if(snode->gpd) {
+                                       snode->gpd= newdataadr(fd, snode->gpd);
+                                       link_gpencil(fd, snode->gpd);
+                               }
                                snode->nodetree= snode->edittree= NULL;
                                snode->flag |= SNODE_DO_PREVIEW;
                        }
+                       else if(sl->spacetype==SPACE_SEQ) {
+                               SpaceSeq *sseq= (SpaceSeq *)sl;
+                               if(sseq->gpd) {
+                                       sseq->gpd= newdataadr(fd, sseq->gpd);
+                                       link_gpencil(fd, sseq->gpd);
+                               }
+                       }
                }
 
                sa->v1= newdataadr(fd, sa->v1);
index ca91f1dc3461f7bcd4dc7d33737cde89f0d786ea..73abf362d12d9d0875c8660ac76f01f488fab08b 100644 (file)
@@ -112,6 +112,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi
 #include "DNA_customdata_types.h"
 #include "DNA_effect_types.h"
 #include "DNA_group_types.h"
+#include "DNA_gpencil_types.h"
 #include "DNA_image_types.h"
 #include "DNA_ipo_types.h"
 #include "DNA_fileglobal_types.h"
@@ -532,6 +533,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
                if(part->id.us>0 || wd->current) {
                        /* write LibData */
                        writestruct(wd, ID_PA, "ParticleSettings", 1, part);
+                       if (part->id.properties) IDP_WriteProperty(part->id.properties, wd);
                        writestruct(wd, DATA, "PartDeflect", 1, part->pd);
                }
                part= part->id.next;
@@ -1565,6 +1567,32 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
        mywrite(wd, MYWRITE_FLUSH, 0);
 }
 
+static void write_gpencil(WriteData *wd, bGPdata *gpd)
+{
+       bGPDlayer *gpl;
+       bGPDframe *gpf;
+       bGPDstroke *gps;
+       
+       /* write gpd data block to file */
+       writestruct(wd, DATA, "bGPdata", 1, gpd);
+       
+       /* write grease-pencil layers to file */
+       for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+               writestruct(wd, DATA, "bGPDlayer", 1, gpl);
+               
+               /* write this layer's frames to file */
+               for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+                       writestruct(wd, DATA, "bGPDframe", 1, gpf);
+                       
+                       /* write strokes */
+                       for (gps= gpf->strokes.first; gps; gps= gps->next) {
+                               writestruct(wd, DATA, "bGPDstroke", 1, gps);
+                               writestruct(wd, DATA, "bGPDspoint", gps->totpoints, gps->points);                               
+                       }
+               }
+       }
+}
+
 static void write_screens(WriteData *wd, ListBase *scrbase)
 {
        bScreen *sc;
@@ -1610,11 +1638,12 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                        sl= sa->spacedata.first;
                        while(sl) {
                                if(sl->spacetype==SPACE_VIEW3D) {
-                                       View3D *v3d= (View3D*) sl;
+                                       View3D *v3d= (View3D *) sl;
                                        writestruct(wd, DATA, "View3D", 1, v3d);
                                        if(v3d->bgpic) writestruct(wd, DATA, "BGpic", 1, v3d->bgpic);
                                        if(v3d->localvd) writestruct(wd, DATA, "View3D", 1, v3d->localvd);
                                        if(v3d->clipbb) writestruct(wd, DATA, "BoundBox", 1, v3d->clipbb);
+                                       if(v3d->gpd) write_gpencil(wd, v3d->gpd);
                                }
                                else if(sl->spacetype==SPACE_IPO) {
                                        writestruct(wd, DATA, "SpaceIpo", 1, sl);
@@ -1626,7 +1655,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                                        writestruct(wd, DATA, "SpaceFile", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_SEQ) {
+                                       SpaceSeq *sseq= (SpaceSeq *)sl;
                                        writestruct(wd, DATA, "SpaceSeq", 1, sl);
+                                       if(sseq->gpd) write_gpencil(wd, sseq->gpd);
                                }
                                else if(sl->spacetype==SPACE_OOPS) {
                                        SpaceOops *so= (SpaceOops *)sl;
@@ -1689,7 +1720,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                                        writestruct(wd, DATA, "SpaceTime", 1, sl);
                                }
                                else if(sl->spacetype==SPACE_NODE){
+                                       SpaceNode *snode= (SpaceNode *)sl;
                                        writestruct(wd, DATA, "SpaceNode", 1, sl);
+                                       if(snode->gpd) write_gpencil(wd, snode->gpd);
                                }
                                sl= sl->next;
                        }
index 91635123cb7e1642a805e4bc6ea2c147c4181c39..7cb0768e83250d45b28b907cde89a994d4992179 100644 (file)
@@ -38,6 +38,7 @@ struct bAction;
 struct bActionGroup;
 struct Object;
 struct ListBase;
+struct bGPDlayer;
 
 /* ****************************** Base Structs ****************************** */
 
@@ -82,6 +83,7 @@ void draw_ipo_channel(struct gla2DDrawInfo *di, struct Ipo *ipo, float ypos);
 void draw_agroup_channel(struct gla2DDrawInfo *di, struct bActionGroup *agrp, float ypos);
 void draw_action_channel(struct gla2DDrawInfo *di, struct bAction *act, float ypos);
 void draw_object_channel(struct gla2DDrawInfo *di, struct Object *ob, float ypos);
+void draw_gpl_channel(struct gla2DDrawInfo *di, struct bGPDlayer *gpl, float ypos);
 
 /* Keydata Generation */
 void icu_to_keylist(struct IpoCurve *icu, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
@@ -89,6 +91,7 @@ void ipo_to_keylist(struct Ipo *ipo, ListBase *keys, ListBase *blocks, ActKeysIn
 void agroup_to_keylist(struct bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
 void action_to_keylist(struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
 void ob_to_keylist(struct Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void gpl_to_keylist(struct bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
 
 #endif  /*  BDR_DRAWACTION_H */
 
diff --git a/source/blender/include/BDR_gpencil.h b/source/blender/include/BDR_gpencil.h
new file mode 100644 (file)
index 0000000..d2fc7be
--- /dev/null
@@ -0,0 +1,74 @@
+/**
+ * $Id: BDR_gpencil.h 14444 2008-04-16 22:40:48Z aligorith $
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BDR_GPENCIL_H
+#define BDR_GPENCIL_H
+
+struct ListBase;
+struct bScreen;
+struct ScrArea;
+struct View3D;
+struct SpaceNode;
+struct SpaceSeq;
+struct bGPdata;
+struct bGPDlayer;
+struct bGPDframe;
+
+/* ------------ Grease-Pencil API ------------------ */
+
+void free_gpencil_strokes(struct bGPDframe *gpf);
+void free_gpencil_frames(struct bGPDlayer *gpl);
+void free_gpencil_layers(struct ListBase *list);
+void free_gpencil_data(struct bGPdata *gpd);
+
+struct bGPDframe *gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe);
+struct bGPDlayer *gpencil_layer_addnew(struct bGPdata *gpd);
+struct bGPdata *gpencil_data_addnew(void);
+
+struct bGPdata *gpencil_data_duplicate(struct bGPdata *gpd);
+
+struct bGPdata *gpencil_data_getactive(struct ScrArea *sa);
+short gpencil_data_setactive(struct ScrArea *sa, struct bGPdata *gpd);
+
+void gpencil_frame_delete_laststroke(struct bGPDframe *gpf);
+
+struct bGPDframe *gpencil_layer_getframe(struct bGPDlayer *gpl, int cframe, short addnew);
+void gpencil_layer_delframe(struct bGPDlayer *gpl, struct bGPDframe *gpf);
+struct bGPDlayer *gpencil_layer_getactive(struct bGPdata *gpd);
+void gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active);
+void gpencil_layer_delactive(struct bGPdata *gpd);
+
+void gpencil_delete_actframe(struct bGPdata *gpd);
+void gpencil_delete_laststroke(struct bGPdata *gpd);
+
+void gpencil_delete_operation(short mode);
+void gpencil_delete_menu(void);
+
+//short gpencil_paint(short mousebutton);
+short gpencil_do_paint(struct ScrArea *sa, short mousebutton);
+
+#endif /*  BDR_GPENCIL_H */
diff --git a/source/blender/include/BIF_drawgpencil.h b/source/blender/include/BIF_drawgpencil.h
new file mode 100644 (file)
index 0000000..4184463
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * $Id: BIF_drawgpencil.h 14444 2008-04-16 22:40:48Z aligorith $
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BIF_DRAWGPENCIL_H
+#define BIF_DRAWGPENCIL_H
+
+struct ScrArea;
+struct View3D;
+struct SpaceNode;
+struct SpaceSeq;
+struct bGPdata;
+struct uiBlock;
+
+short draw_gpencil_panel(struct uiBlock *block, struct bGPdata *gpd, struct ScrArea *sa); 
+
+void draw_gpencil_2dview(struct ScrArea *sa, short onlyv2d);
+void draw_gpencil_3dview(struct ScrArea *sa, short only3d);
+void draw_gpencil_oglrender(struct View3D *v3d, int winx, int winy);
+
+#endif /*  BIF_DRAWGPENCIL_H */ 
index 7e0f703681b4aec57c1a7b34323d450aa8c2e7dd..77c2f19bb9b524ded1bc61b7e998721be855218d 100644 (file)
@@ -48,7 +48,10 @@ enum {
        ACTTYPE_FILLIPO,
        ACTTYPE_FILLCON,
        ACTTYPE_IPO,
-       ACTTYPE_SHAPEKEY
+       ACTTYPE_SHAPEKEY,
+       ACTTYPE_GPDATABLOCK,
+       ACTTYPE_GPLAYER,
+       ACTTYPE_SPECIALDATA
 };
 
 /* Macros for easier/more consistant state testing */
@@ -69,7 +72,12 @@ enum {
 #define EDITABLE_ICU(icu) ((icu->flag & IPO_PROTECT)==0)
 #define SEL_ICU(icu) (icu->flag & IPO_SELECT)
 
-#define NLA_ACTION_SCALED (G.saction->pin==0 && OBACT && OBACT->action)
+#define EXPANDED_GPD(gpd) (gpd->flag & GP_DATA_EXPAND) 
+
+#define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED)==0)
+#define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT))
+
+#define NLA_ACTION_SCALED (G.saction->mode==SACTCONT_ACTION && G.saction->pin==0 && OBACT && OBACT->action)
 #define NLA_IPO_SCALED (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname)
 
 /* constants for setting ipo-interpolation type */
@@ -114,6 +122,8 @@ struct BWinEvent;
 struct Key;
 struct ListBase;
 struct TimeMarker;
+struct bGPdata;
+struct bGPDlayer;
 
 /* Key operations */
 void transform_action_keys(int mode, int dummy);
@@ -176,11 +186,29 @@ void action_add_localmarker(struct bAction *act, int frame);
 void action_rename_localmarker(struct bAction *act);
 void action_remove_localmarkers(struct bAction *act);
 
+/* Grease-Pencil Data */
+void gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, short onlysel);
+
+void deselect_gpencil_layers(void *data, short select_mode);
+
+short is_gplayer_frame_selected(struct bGPDlayer *gpl);
+void set_gplayer_frame_selection(struct bGPDlayer *gpl, short mode);
+void select_gpencil_frames(struct bGPDlayer *gpl, short select_mode);
+void select_gpencil_frame(struct bGPDlayer *gpl, int selx, short select_mode);
+void borderselect_gplayer_frames(struct bGPDlayer *gpl, float min, float max, short select_mode);
+
+void delete_gpencil_layers(void);
+void delete_gplayer_frames(struct bGPDlayer *gpl);
+void duplicate_gplayer_frames(struct bGPDlayer *gpd);
+
+void snap_gplayer_frames(struct bGPDlayer *gpl, short mode);
+void mirror_gplayer_frames(struct bGPDlayer *gpl, short mode);
+
 /* ShapeKey stuff */
 struct Key *get_action_mesh_key(void);
 int get_nearest_key_num(struct Key *key, short *mval, float *x);
 
-void *get_nearest_act_channel(short mval[], short *ret_type);
+void *get_nearest_act_channel(short mval[], short *ret_type, void **owner);
 
 /* Action */
 struct bActionChannel *get_hilighted_action_channel(struct bAction* action);
index 37be4a9eafc5c29b8cf7afd1bdd4aae8d40e8d6a..4b2b8e14bb63da606ca3ce8c399d307805ab41be 100644 (file)
@@ -53,6 +53,7 @@ struct SpaceOops;
 #define VIEW3D_HANDLER_PREVIEW         4
 #define VIEW3D_HANDLER_MULTIRES         5
 #define VIEW3D_HANDLER_TRANSFORM       6
+#define VIEW3D_HANDLER_GREASEPENCIL 7
 
 /* ipo handler codes */
 #define IPO_HANDLER_PROPERTIES 20
@@ -73,11 +74,15 @@ struct SpaceOops;
 #define NLA_HANDLER_PROPERTIES 50
 
 /* sequence handler codes */
-#define SEQ_HANDLER_PROPERTIES 60
+#define SEQ_HANDLER_PROPERTIES         60
+#define SEQ_HANDLER_GREASEPENCIL       61
 
 /* imasel handler codes */
 #define IMASEL_HANDLER_IMAGE   70
 
+/* nodes handler codes */
+#define NODES_HANDLER_GREASEPENCIL             80
+
 /* theme codes */
 #define B_ADD_THEME    3301
 #define B_DEL_THEME    3302
@@ -145,3 +150,4 @@ extern               void mainwindow_close(void);
 
 #endif
 
+
index 83031ff3bad8158d16ddb174fb09cd8c93ff7527..e6f22a4fb67af534c163ca9d2c15074df54c7d35 100644 (file)
@@ -76,6 +76,7 @@ void inner_play_anim_loop(int init, int mode);
 int play_anim(int mode);
 
 void make_axis_color(char *col, char *col2, char axis);
+char *view3d_get_name(struct View3D *v3d);
 
 /* SMOOTHVIEW */
 void smooth_view(struct View3D *v3d, float *ofs, float *quat, float *dist, float *lens);
index c531383accc8b684b86494136976909c222e9599..be21041597312e29c08f741b02a95e10ef5bebdf 100644 (file)
@@ -38,7 +38,8 @@ typedef enum ALE_KEYTYPE {
        ALE_NONE = 0,
        ALE_IPO,        
        ALE_ICU,
-       ALE_GROUP       
+       ALE_GROUP,
+       ALE_GPFRAME,
 } ALE_KEYTYPE;
 
 /* This struct defines a structure used for quick access */
@@ -78,7 +79,8 @@ typedef enum ACTFILTER_FLAGS {
 typedef enum ACTCONT_TYPES {
        ACTCONT_NONE = 0,
        ACTCONT_ACTION,
-       ACTCONT_SHAPEKEY
+       ACTCONT_SHAPEKEY,
+       ACTCONT_GPENCIL
 } ACTCONT_TYPES;
 
 #endif
index 4e3b80134f9e2487c1daa7188127dbd87727b172..720b856a14941e9c31a5ab7911f1960631d88c0d 100644 (file)
@@ -397,6 +397,7 @@ int Align(TransInfo *t, short mval[2]);
 
 /*********************** transform_conversions.c ********** */
 struct ListBase;
+void flushTransGPactionData(TransInfo *t);
 void flushTransIpoData(TransInfo *t);
 void flushTransUVs(TransInfo *t);
 void flushTransParticles(TransInfo *t);
index 60050ea010ec4d84158f24dc7c562e22a4318d0a..3054e038ba2b114bc67937c499113001a11642a5 100644 (file)
@@ -46,7 +46,7 @@ struct ID;
 typedef struct IDPropertyData {
        void *pointer;
        ListBase group;
-       int val, pad;
+       int val, val2; /*note, we actually fit a double into these two ints*/
 } IDPropertyData;
 
 typedef struct IDProperty {
@@ -77,6 +77,7 @@ typedef struct IDProperty {
 /*the ID link property type hasn't been implemented yet, this will require
   some cleanup of blenkernel, most likely.*/
 #define IDP_ID         7
+#define IDP_DOUBLE     8
 
 /*add any future new id property types here.*/
 
index 18d2a1cb6f3a61c32497ce67855ec007d8253b0d..2e8d95335cca72ac8bb6ce8b29ffa4d6af67a7b5 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "DNA_listBase.h"
 #include "DNA_ID.h"
+#include "DNA_gpencil_types.h"
 #include "DNA_view2d_types.h"
 #include "DNA_userdef_types.h"
 
@@ -183,8 +184,10 @@ typedef struct SpaceAction {
        View2D v2d;     
        
        bAction         *action;                /* the currently active action */
-       short flag, autosnap;           /* flag: bitmapped settings; autosnap: automatic keyframe snapping mode */
-       short pin, actnr, lock;         /* pin: keep showing current action; actnr: used for finding chosen action from menu; lock: lock time to other windows */
+       
+       char  mode, autosnap;           /* mode: editing context; autosnap: automatic keyframe snapping mode   */
+       short flag, actnr;                      /* flag: bitmapped settings; */
+       short pin, lock;                        /* pin: keep showing current action; actnr: used for finding chosen action from menu; lock: lock time to other windows */
        short actwidth;                         /* width of the left-hand side name panel (in pixels?) */
        float timeslide;                        /* for Time-Slide transform mode drawing - current frame? */
 } SpaceAction;
@@ -238,6 +241,18 @@ typedef enum SACTION_FLAG {
        SACTION_NODRAWGCOLORS = (1<<7)
 } SACTION_FLAG;        
 
+/* SpaceAction Mode Settings */
+typedef enum SACTCONT_MODES {
+               /* action (default) */
+       SACTCONT_ACTION = 0,
+               /* editing of shapekey's IPO block */
+       SACTCONT_SHAPEKEY,
+               /* editing of gpencil data */
+       SACTCONT_GPENCIL,
+               /* dopesheet (unimplemented... future idea?) */
+       SACTCONT_DOPESHEET
+} SACTCONTEXT_MODES;
+
 /* SpaceAction AutoSnap Settings (also used by SpaceNLA) */
 typedef enum SACTSNAP_MODES {
                /* no auto-snap */
index ac9761f165df751684a088809f128ad20126ddb4..7444ce95f56a47de24e3e868b6290d48bfc805ba 100644 (file)
@@ -368,9 +368,9 @@ typedef struct FreeCamera {
 #define ACT_CONST_DIRPX                1
 #define ACT_CONST_DIRPY                2
 #define ACT_CONST_DIRPZ                4
-#define ACT_CONST_DIRMX                8
-#define ACT_CONST_DIRMY                16
-#define ACT_CONST_DIRMZ                32
+#define ACT_CONST_DIRNX                8
+#define ACT_CONST_DIRNY                16
+#define ACT_CONST_DIRNZ                32
 
 /* constraint type */
 #define ACT_CONST_TYPE_LOC     0
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
new file mode 100644 (file)
index 0000000..b88dd69
--- /dev/null
@@ -0,0 +1,143 @@
+/**
+ * $Id: DNA_gpencil_types.h 8768 2006-11-07 00:10:37Z aligorith $
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation.
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef DNA_GPENCIL_TYPES_H
+#define DNA_GPENCIL_TYPES_H
+
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
+
+/* Grease-Pencil Annotations - 'Stroke Point'
+ *     -> Coordinates may either be 2d or 3d depending on settings at the time
+ *     -> Coordinates of point on stroke, in proportions of window size
+ *             (i.e. n/1000). This assumes that the bottom-left corner is (0,0)
+ */
+typedef struct bGPDspoint {
+       float x, y, z;                  /* co-ordinates of point (usually 2d, but can be 3d as well) */                         
+       float pressure;                 /* pressure of input device (from 0 to 1) at this point */
+} bGPDspoint;
+
+/* Grease-Pencil Annotations - 'Stroke'
+ *     -> A stroke represents a (simplified version) of the curve
+ *        drawn by the user in one 'mousedown'->'mouseup' operation
+ */
+typedef struct bGPDstroke {
+       struct bGPDstroke *next, *prev;
+       
+       bGPDspoint *points;             /* array of data-points for stroke */
+       int totpoints;                  /* number of data-points in array */
+       
+       short thickness;                /* thickness of stroke (currently not used) */  
+       short flag;                             /* various settings about this stroke */
+} bGPDstroke;
+
+/* bGPDstroke->flag */
+       /* stroke is in 3d-space */
+#define GP_STROKE_3DSPACE              (1<<0)
+       /* stroke is in 2d-space */
+#define GP_STROKE_2DSPACE              (1<<1)
+       /* stroke is an "eraser" stroke */
+#define GP_STROKE_ERASER               (1<<2)
+
+
+/* Grease-Pencil Annotations - 'Frame'
+ *     -> Acts as storage for the 'image' formed by strokes
+ */
+typedef struct bGPDframe {
+       struct bGPDframe *next, *prev;
+       
+       ListBase strokes;       /* list of the simplified 'strokes' that make up the frame's data */
+       
+       int framenum;           /* frame number of this frame */
+       int flag;                       /* temp settings */
+} bGPDframe;
+
+/* bGPDframe->flag */  
+       /* frame is being painted on */
+#define GP_FRAME_PAINT         (1<<0)
+       /* for editing in Action Editor */
+#define GP_FRAME_SELECT                (1<<1)
+
+
+/* Grease-Pencil Annotations - 'Layer' */
+typedef struct bGPDlayer {
+       struct bGPDlayer *next, *prev;
+       
+       ListBase frames;                /* list of annotations to display for frames (bGPDframe list) */
+       bGPDframe *actframe;    /* active frame (should be the frame that is currently being displayed) */
+       
+       int flag;                               /* settings for layer */                
+       short thickness;                /* current thickness to apply to strokes */
+       short gstep;                    /* max number of frames between active and ghost to show (0=only those on either side) */
+       
+       float color[4];                 /* color that should be used to draw all the strokes in this layer */
+       
+       char info[128];                 /* optional reference info about this layer (i.e. "director's comments, 12/3") */
+} bGPDlayer;
+
+/* bGPDlayer->flag */
+       /* don't display layer */
+#define GP_LAYER_HIDE          (1<<0)
+       /* protected from further editing */
+#define GP_LAYER_LOCKED                (1<<1)  
+       /* layer is 'active' layer being edited */
+#define GP_LAYER_ACTIVE                (1<<2)
+       /* draw points of stroke for debugging purposes */
+#define GP_LAYER_DRAWDEBUG     (1<<3)
+       /* do onionskinning */
+#define GP_LAYER_ONIONSKIN     (1<<4)
+       /* for editing in Action Editor */
+#define GP_LAYER_SELECT                (1<<5)
+
+
+/* Grease-Pencil Annotations - 'DataBlock' */
+typedef struct bGPdata {
+       /* saved Grease-Pencil data */
+       ListBase layers;                /* bGPDlayers */
+       int flag;                               /* settings for this datablock */
+       
+       /* not-saved stroke buffer data (only used during paint-session) 
+        *      - buffer must be initialised before use, but freed after 
+        *        whole paint operation is over
+        */
+       short sbuffer_size;                     /* number of elements currently in cache */
+       short sbuffer_sflag;            /* flags for stroke that cache represents */
+       bGPDspoint *sbuffer;            /* stroke buffer (can hold GP_STROKE_BUFFER_MAX) */
+} bGPdata;
+
+/* bGPdata->flag */
+       /* don't allow painting to occur at all */
+#define GP_DATA_LMBPLOCK       (1<<0)
+       /* show debugging info in viewport (i.e. status print) */
+#define GP_DATA_DISPINFO       (1<<1)
+       /* in Action Editor, show as expanded channel */
+#define GP_DATA_EXPAND         (1<<2)
+       /* is the block overriding all clicks? */
+#define GP_DATA_EDITPAINT      (1<<3)
+       /* new strokes are added in viewport space */
+#define GP_DATA_VIEWALIGN      (1<<4)
+
+#endif /*  DNA_GPENCIL_TYPES_H */
index c0b9a6b95907fbc52be8ff4d94b2f7bdd7633f5f..7bad8ec3b44397461e990b5d94106fadc00fc721 100644 (file)
@@ -257,6 +257,7 @@ typedef struct SpeedControlVars {
 #define SEQ_USE_CROP                           131072
 #define SEQ_USE_COLOR_BALANCE                  262144
 #define SEQ_USE_PROXY_CUSTOM_DIR               524288
+#define SEQ_ACTIVE                            1048576
 
 #define SEQ_COLOR_BALANCE_INVERSE_GAIN 1
 #define SEQ_COLOR_BALANCE_INVERSE_GAMMA 2
index 36265e25996c1a1f416f29df3167111cc361aaa3..f42eb2e1a9484d20b9a9cbdd879768589ffe3f8c 100644 (file)
@@ -50,6 +50,7 @@ struct RenderInfo;
 struct bNodeTree;
 struct uiBlock;
 struct FileList;
+struct bGPdata;
 
        /**
         * The base structure all the other spaces
@@ -150,6 +151,8 @@ typedef struct SpaceSeq {
        short zebra;
        int flag;
        float zoom;
+       
+       struct bGPdata *gpd;            /* grease-pencil data */
 } SpaceSeq;
 
 typedef struct SpaceFile {
@@ -339,6 +342,8 @@ typedef struct SpaceNode {
        float blockscale;
        struct ScrArea *area;
        
+       short blockhandler[8];
+       
        View2D v2d;
        
        struct ID *id, *from;           /* context, no need to save in file? well... pinning... */
@@ -351,11 +356,13 @@ typedef struct SpaceNode {
        struct bNodeTree *nodetree, *edittree;
        int treetype, pad;                      /* treetype: as same nodetree->type */
        
+       struct bGPdata *gpd;            /* grease-pencil data */
 } SpaceNode;
 
 /* snode->flag */
 #define SNODE_DO_PREVIEW       1
 #define SNODE_BACKDRAW         2
+#define SNODE_DISPGP           4
 
 typedef struct SpaceImaSel {
        SpaceLink *next, *prev;
@@ -657,6 +664,7 @@ typedef struct SpaceImaSel {
 #define SEQ_MARKER_TRANS 2
 #define SEQ_DRAW_COLOR_SEPERATED     4
 #define SEQ_DRAW_SAFE_MARGINS        8
+#define SEQ_DRAW_GPENCIL                       16
 
 /* space types, moved from DNA_screen_types.h */
 enum {
index c21d629be831668c58c88fe549016dc07b2854dc..135272b9ac244dc1433fe2aa8829fc9e0b5d0061 100644 (file)
@@ -40,6 +40,7 @@ struct Base;
 struct BoundBox;
 struct RenderInfo;
 struct RetopoViewData;
+struct bGPdata;
 
 /* This is needed to not let VC choke on near and far... old
  * proprietary MS extensions... */
@@ -53,9 +54,12 @@ struct RetopoViewData;
 #include "DNA_listBase.h"
 #include "DNA_image_types.h"
 
+/* ******************************** */
+
 /* The near/far thing is a Win EXCEPTION. Thus, leave near/far in the
  * code, and patch for windows. */
-
+/* Background Picture in 3D-View */
 typedef struct BGpic {
     struct Image *ima;
        struct ImageUser iuser;
@@ -63,6 +67,9 @@ typedef struct BGpic {
     short xim, yim;
 } BGpic;
 
+/* ********************************* */
+
+/* 3D ViewPort Struct */
 typedef struct View3D {
        struct SpaceLink *next, *prev;
        int spacetype;
@@ -135,9 +142,10 @@ typedef struct View3D {
        char ndoffilter;                /*filter for 6DOF devices 0 normal, 1 dominant */
        
        void *properties_storage;       /* Nkey panel stores stuff here, not in file */
-
+       struct bGPdata *gpd;            /* Grease-Pencil Data (annotation layers) */
 } View3D;
 
+
 /* View3D->flag (short) */
 #define V3D_MODE                       (16+32+64+128+256+512)
 #define V3D_DISPIMAGE          1
@@ -158,10 +166,12 @@ typedef struct View3D {
 #define V3D_DRAW_CENTERS       32768
 
 /* View3d->flag2 (short) */
+#define V3D_MODE2                      (32)
 #define V3D_OPP_DIRECTION_NAME 1
 #define V3D_FLYMODE                            2
 #define V3D_DEPRECATED                 4 /* V3D_TRANSFORM_SNAP, moved to a scene setting */
 #define V3D_SOLID_TEX                  8
+#define V3D_DISPGP                             16
 
 /* View3D->around */
 #define V3D_CENTER              0
@@ -203,3 +213,4 @@ typedef struct View3D {
 
 #endif
 
+
index 83f4e633fa1670303de53f430d3ebbe1e1eb7e18..3818d66b39ca96ba42b0f966ada09a1a523c2c21 100644 (file)
@@ -126,6 +126,7 @@ char *includefiles[] = {
        "DNA_customdata_types.h",
        "DNA_particle_types.h",
        "DNA_cloth_types.h",
+       "DNA_gpencil_types.h",
        // if you add files here, please add them at the end
        // of makesdna.c (this file) as well
 
@@ -1147,4 +1148,5 @@ int main(int argc, char ** argv)
 #include "DNA_customdata_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_cloth_types.h"
+#include "DNA_gpencil_types.h"
 /* end of list */
index bdceb134c0d15acb4360378180343ba08965583d..9396410f850ec2db7a7e8cca018163668f98db56 100644 (file)
@@ -54,7 +54,6 @@ static bNodeSocketType sh_node_material_ext_in[]= {
        {       SOCK_VALUE, 1, "Refl",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
        {       SOCK_VECTOR, 1, "Normal",       0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
        {       SOCK_RGBA, 1, "Mirror",         0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
-       {       SOCK_RGBA, 1, "AmbCol",         0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 1, "Ambient",       0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 1, "Emit",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 1, "SpecTra",       0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
@@ -117,8 +116,6 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in,
                if (node->type == SH_NODE_MATERIAL_EXT) {
                        if(in[MAT_IN_MIR]->hasinput)
                                nodestack_get_vec(&shi->mirr, SOCK_VECTOR, in[MAT_IN_MIR]);
-                       if(in[MAT_IN_AMBCOL]->hasinput)
-                               nodestack_get_vec(&shi->ambr, SOCK_VECTOR, in[MAT_IN_AMBCOL]);
                        if(in[MAT_IN_AMB]->hasinput)
                                nodestack_get_vec(&shi->amb, SOCK_VALUE, in[MAT_IN_AMB]);
                        if(in[MAT_IN_EMIT]->hasinput)
index c9f58fbce492c6bfeb96f455c1a130b278df0ecb..f673834d2b77280fa83bc34f89660aa8b08d417a 100644 (file)
@@ -164,7 +164,7 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
                                                case MAT_IN_MIR:
                                                        VECCOPY(&ma->mirr, sock->ns.vec); break;
                                                case MAT_IN_AMB:
-                                                       VECCOPY(&ma->ambr, sock->ns.vec); break;
+                                                       ma->amb= sock->ns.vec[0]; break;
                                                case MAT_IN_EMIT:
                                                        ma->emit= sock->ns.vec[0]; break;
                                                case MAT_IN_SPECTRA:
@@ -188,7 +188,7 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
                                                case MAT_IN_MIR:
                                                        VECCOPY(sock->ns.vec, &ma->mirr); break;
                                                case MAT_IN_AMB:
-                                                       VECCOPY(sock->ns.vec, &ma->ambr); break;
+                                                       sock->ns.vec[0]= ma->amb; break;
                                                case MAT_IN_EMIT:
                                                        sock->ns.vec[0]= ma->emit; break;
                                                case MAT_IN_SPECTRA:
index f75802b7c15759e10ca4fbcd39c0ac68e8e420d9..bdb2bb3707dbbd04169649a6bb18fabdd078d12a 100644 (file)
@@ -117,13 +117,12 @@ typedef struct ShaderCallData {
 #define MAT_IN_REFL            2
 #define MAT_IN_NORMAL  3
 #define MAT_IN_MIR             4
-#define MAT_IN_AMBCOL  5
-#define MAT_IN_AMB             6
-#define MAT_IN_EMIT    7
-#define MAT_IN_SPECTRA 8
-#define MAT_IN_RAY_MIRROR      9
-#define MAT_IN_ALPHA   10
-#define MAT_IN_TRANSLUCENCY    11
+#define MAT_IN_AMB             5
+#define MAT_IN_EMIT    6
+#define MAT_IN_SPECTRA 7
+#define MAT_IN_RAY_MIRROR      8
+#define MAT_IN_ALPHA   9
+#define MAT_IN_TRANSLUCENCY    10
 
 /* output socket defines */
 #define MAT_OUT_COLOR          0
index 2a6d28c8cb3eb14c94c44e6469b7a2b800902b9e..36a8ee27a5003595318fbd6f9c8ece54253d82b9 100644 (file)
@@ -410,12 +410,14 @@ void BPY_rebuild_syspath( void )
        mod = PyImport_ImportModule( "sys" );   
        if (!mod) {
                printf("error: could not import python sys module. some modules may not import.\n");
+               PyGILState_Release(gilstate);
                return;
        }
        
        if (!bpy_orig_syspath_List) { /* should never happen */
                printf("error refershing python path\n");
                Py_DECREF(mod);
+               PyGILState_Release(gilstate);
                return;
        }
        
index d8385c1d6609d61f75783b04cb1aa5d809f9ad98..420d292cdcef7073eec1c18f12e0ad6ba2eda759 100644 (file)
@@ -708,7 +708,7 @@ static PyObject *Blender_Save( PyObject * self, PyObject * args )
                                              "expected filename and optional int (overwrite flag) as arguments" );
 
        for( li = G.main->library.first; li; li = li->id.next ) {
-               if( BLI_streq( li->name, fname ) ) {
+               if( li->parent==NULL && BLI_streq( li->name, fname ) ) {
                        return EXPP_ReturnPyObjError( PyExc_AttributeError,
                                                      "cannot overwrite used library" );
                }
index f60ebf8dee1991addbe82a1364b61edb7547ed93..4a51619aec417bbb45fed56aa52c3811ae094ebe 100644 (file)
@@ -60,6 +60,8 @@ PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop )
                        return PyInt_FromLong( (long)prop->data.val );
                case IDP_FLOAT:
                        return PyFloat_FromDouble( (double)(*(float*)(&prop->data.val)) );
+               case IDP_DOUBLE:
+                       return PyFloat_FromDouble( (*(double*)(&prop->data.val)) );
                case IDP_GROUP:
                        /*blegh*/
                        {
@@ -128,7 +130,19 @@ int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject *value)
                        Py_XDECREF(value);
                        break;
                }
-
+               case IDP_DOUBLE:
+               {
+                       double dvalue;
+                       if (!PyNumber_Check(value))
+                               return EXPP_ReturnIntError(PyExc_TypeError, "expected a float!");
+                       value = PyNumber_Float(value);
+                       if (!value)
+                               return EXPP_ReturnIntError(PyExc_TypeError, "expected a float!");
+                       dvalue = (float) PyFloat_AsDouble(value);
+                       *(double*)&self->prop->data.val = dvalue;
+                       Py_XDECREF(value);
+                       break;
+               }
                default:
                        return EXPP_ReturnIntError(PyExc_AttributeError, "attempt to set read-only attribute!");
        }
@@ -204,8 +218,8 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje
        IDPropertyTemplate val = {0};
        
        if (PyFloat_Check(ob)) {
-               val.f = (float) PyFloat_AsDouble(ob);
-               prop = IDP_New(IDP_FLOAT, val, name);
+               val.d = PyFloat_AsDouble(ob);
+               prop = IDP_New(IDP_DOUBLE, val, name);
        } else if (PyInt_Check(ob)) {
                val.i = (int) PyInt_AsLong(ob);
                prop = IDP_New(IDP_INT, val, name);
@@ -223,7 +237,7 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje
                val.array.len = PySequence_Length(ob);
                for (i=0; i<val.array.len; i++) {
                        item = PySequence_GetItem(ob, i);
-                       if (PyFloat_Check(item)) val.array.type = IDP_FLOAT;
+                       if (PyFloat_Check(item)) val.array.type = IDP_DOUBLE;
                        else if (!PyInt_Check(item)) return "only floats and ints are allowed in ID property arrays";
                        Py_XDECREF(item);
                }
@@ -236,7 +250,7 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje
                                ((int*)prop->data.pointer)[i] = (int)PyInt_AsLong(item);
                        } else {
                                item = PyNumber_Float(item);
-                               ((float*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item);
+                               ((double*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item);
                        }
                        Py_XDECREF(item);
                }
@@ -334,6 +348,9 @@ PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
                case IDP_FLOAT:
                        return PyFloat_FromDouble(*((float*)&prop->data.val));
                        break;
+               case IDP_DOUBLE:
+                       return PyFloat_FromDouble(*((double*)&prop->data.val));
+                       break;
                case IDP_INT:
                        return PyInt_FromLong( (long)prop->data.val );
                        break;
@@ -347,12 +364,15 @@ PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
                                           "PyList_New() failed" );
                        
                        for (i=0; i<prop->len; i++) {
-                               if (prop->subtype == IDP_FLOAT)
+                               if (prop->subtype == IDP_FLOAT) {
                                                PyList_SetItem(seq, i,
                                                PyFloat_FromDouble(((float*)prop->data.pointer)[i]));
-                               
-                               else    PyList_SetItem(seq, i,
-                                               PyInt_FromLong(((int*)prop->data.pointer)[i]));
+                               } else if (prop->subtype == IDP_DOUBLE) {
+                                               PyList_SetItem(seq, i,
+                                               PyFloat_FromDouble(((double*)prop->data.pointer)[i]));                          
+                               } else  { PyList_SetItem(seq, i,
+                                                 PyInt_FromLong(((int*)prop->data.pointer)[i]));
+                               }
                        }
                        return seq;
                }
@@ -451,7 +471,7 @@ PyObject *BPy_IDGroup_GetKeys(BPy_IDProperty *self)
                /*set correct group length*/
                self->prop->len = i;
                
-               /*free the old list*/
+               /*free the list*/
                Py_DECREF(seq);
                
                /*call self again*/
@@ -688,6 +708,9 @@ PyObject *BPy_IDArray_GetItem(BPy_IDArray *self, int index)
                case IDP_FLOAT:
                        return PyFloat_FromDouble( (double)(((float*)self->prop->data.pointer)[index]));
                        break;
+               case IDP_DOUBLE:
+                       return PyFloat_FromDouble( (((double*)self->prop->data.pointer)[index]));
+                       break;          
                case IDP_INT:
                        return PyInt_FromLong( (long)((int*)self->prop->data.pointer)[index] );
                        break;
@@ -700,7 +723,8 @@ int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *val)
 {
        int i;
        float f;
-
+       double d;
+       
        if (index < 0 || index >= self->prop->len)
                return EXPP_ReturnIntError( PyExc_RuntimeError,
                                "index out of range!");
@@ -717,6 +741,17 @@ int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *val)
                        ((float*)self->prop->data.pointer)[index] = f;
                        Py_XDECREF(val);
                        break;
+               case IDP_DOUBLE:
+                       if (!PyNumber_Check(val)) return EXPP_ReturnIntError( PyExc_TypeError,
+                               "expected a float");
+                       val = PyNumber_Float(val);
+                       if (!val) return EXPP_ReturnIntError( PyExc_TypeError,
+                               "expected a float");
+
+                       d = (double) PyFloat_AsDouble(val);
+                       ((double*)self->prop->data.pointer)[index] = d;
+                       Py_XDECREF(val);
+                       break;
                case IDP_INT:
                        if (!PyNumber_Check(val)) return EXPP_ReturnIntError( PyExc_TypeError,
                                "expected an int");
index 799735c2062fc31aebe2b57bd4d4f8f0140df1d0..468263c420817d107099d5631b9120f0b2ce795b 100644 (file)
@@ -1135,9 +1135,78 @@ static PyObject *M_Library_Load(PyObject *self, PyObject * args)
        return (PyObject *)lib;
 }
 
+static PyObject *M_Library_GetPaths(PyObject *self, PyObject * args)
+{      
+       PyObject *list;
+       PyObject *name;
+       int type=0;
+       Library *lib;
+       
+       if( !PyArg_ParseTuple( args, "|i", &type ) || type < 0 || type > 2 ) {
+               return EXPP_ReturnPyObjError( PyExc_TypeError,
+                       "expected an int between 0 and 2." );
+       }
+       
+       list = PyList_New(0);
+       
+       for(lib= G.main->library.first; lib; lib= lib->id.next) {
+               if (type==0) {
+                       /* any type is ok */
+               } else if (type==1 && lib->parent == 0) {
+                       /* only direct linked */
+               } else if (type==2 && lib->parent != 0) {
+                       /* only indirect */
+               } else {
+                       continue; /* incompatible type */
+               }
+               
+               name = PyString_FromString(lib->name);
+               PyList_Append(list, name);
+               Py_DECREF(name);
+       }
+       return list;
+}
+
+static PyObject *M_Library_ReplacePath(PyObject *self, PyObject * args)
+{
+       char *name_from, *name_to;
+       Library *lib;
+       
+       if( !PyArg_ParseTuple( args, "ss", &name_from, &name_to )) {
+               return EXPP_ReturnPyObjError( PyExc_TypeError,
+                       "expected the name of a library path" );
+       }
+       
+       for(lib= G.main->library.first; lib; lib= lib->id.next) {
+               if (strcmp(lib->name, name_from)==0) {
+                       if (lib->parent) {
+                               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                                       "path is indirectly linked, cannot be changed." );
+                       }
+                       
+                       if (strlen(name_to) > sizeof(lib->name)) {
+                               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                                       "string length too long, cannot set path." );
+                       }
+                       
+                       strcpy(lib->name, name_to);
+                       Py_RETURN_NONE;
+               }
+       }
+       
+       return EXPP_ReturnPyObjError( PyExc_ValueError,
+               "path given does not exist as a library" );
+}
+
+
+
 static struct PyMethodDef M_Library_methods[] = {
        {"load", (PyCFunction)M_Library_Load, METH_VARARGS,
        "(string) - declare a .blend file for use as a library"},
+       {"paths", (PyCFunction)M_Library_GetPaths, METH_VARARGS,
+       "(type) - return a list of library paths, type 0 for all, 1 only direct links, 2 only indirect links"},
+       {"replace", (PyCFunction)M_Library_ReplacePath, METH_VARARGS,
+       "(from, to) - replace the path of an existing, directly linked library."},
        {NULL, NULL, 0, NULL}
 };
 
index 95de9757b8709c3f81ea686535841ddcf480ff07..2c2e724129ed7a63b048e6d4e78c6a297a5eaaa9 100644 (file)
@@ -40,6 +40,7 @@
 #include "BKE_material.h"
 #include "BKE_utildefines.h"
 #include "BKE_pointcache.h"
+#include "BKE_DerivedMesh.h"
 #include "BIF_editparticle.h"
 #include "BIF_space.h"
 #include "blendef.h"
@@ -799,22 +800,27 @@ static PyObject *Part_freeEdit( BPy_PartSys * self, PyObject * args ){
        Py_RETURN_NONE;
 }
 
-static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args ){
+static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args )
+{
        ParticleSystem *psys = 0L;
        Object *ob = 0L;
        PyObject *partlist,*seglist;
-       PyObject* loc = 0L;
        ParticleCacheKey **cache,*path;
+       PyObject* loc = 0L;
        ParticleKey state;
-       float cfra=bsystem_time(ob,(float)CFRA,0.0);
+       DerivedMesh* dm;
+       float cfra;
        int i,j,k;
+       float vm[4][4],wm[4][4];
        int     childexists = 0;
        int all = 0;
        int id = 0;
 
+       cfra = bsystem_time(ob,(float)CFRA,0.0);
+
        if( !PyArg_ParseTuple( args, "|ii", &all,&id ) )
                return EXPP_ReturnPyObjError( PyExc_TypeError,
-                               "expected one optional integer as argument" );
+                               "expected two optional integers as arguments" );
 
        psys = self->psys;
        ob = self->object;
@@ -822,88 +828,118 @@ static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args ){
        if (!ob || !psys)
                Py_RETURN_NONE;
 
-       if (psys->part->type == 2){
-               cache=psys->pathcache;
+       G.rendering = 1;
 
-               /* little hack to calculate hair steps in render mode */
-               psys->renderdata = (void*)(int)1;
+       /* Just to create a valid rendering context */
+       psys_render_set(ob,psys,vm,wm,0,0,0);
 
-               psys_cache_paths(ob, psys, cfra, 1);
+       dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+       dm->release(dm);
 
-               psys->renderdata = NULL;
+       if ( !psys_check_enabled(ob,psys) ){
+               G.rendering = 0;
+               psys_render_restore(ob,psys);
+               Particle_Recalc(self,1);
+               Py_RETURN_NONE;
+       }
 
-               partlist = PyList_New( 0 );
-               if( !partlist )
-                       return EXPP_ReturnPyObjError( PyExc_MemoryError, "PyList() failed" );
+       partlist = PyList_New( 0 );
+       if( !partlist ){
+               PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
+               goto error;
+       }
 
-               for(i = 0; i < psys->totpart; i++){
-                       path=cache[i];
-                       seglist = PyList_New( 0 );
-                       k = path->steps+1;
-                       for( j = 0; j < k ; j++){
-                               loc = PyTuple_New(3);
-
-                               PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)path->co[0]));
-                               PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)path->co[1]));
-                               PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)path->co[2]));
-
-                               if ( (PyList_Append(seglist,loc) < 0) ){
-                                       Py_DECREF(seglist);
-                                       Py_DECREF(partlist);
-                                       Py_XDECREF(loc);
-                                       return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                                       "Couldn't append item to PyList" );
+       if (psys->part->type == PART_HAIR){
+               cache = psys->pathcache;
+
+               if ( ((self->psys->part->draw & PART_DRAW_PARENT) && (self->psys->part->childtype != 0)) || (self->psys->part->childtype == 0) ){
+
+                       for(i = 0; i < psys->totpart; i++){
+                               seglist = PyList_New( 0 );
+                               if (!seglist){
+                                       PyErr_SetString( PyExc_MemoryError,
+                                                       "PyList_New() failed" );
+                                       goto error;
+                               }
+
+                               path=cache[i];
+                               k = path->steps+1;
+                               for( j = 0; j < k ; j++, path++){
+                                       loc = Py_BuildValue("(fff)",(double)path->co[0],
+                                                       (double)path->co[1], (double)path->co[2]);
+
+                                       if (!loc){
+                                               PyErr_SetString( PyExc_RuntimeError,
+                                                               "Couldn't build tuple" );
+                                               goto error;
+                                       }
+
+                                       if ( (PyList_Append(seglist,loc) < 0) ){
+                                               PyErr_SetString( PyExc_RuntimeError,
+                                                               "Couldn't append item to PyList" );
+                                               goto error;
+                                       }
+                                       Py_DECREF(loc); /* PyList_Append increfs */
+                                       loc = NULL;
                                }
-                               Py_DECREF(loc); /* PyList_Append increfs */
-                               path++;
-                       }
 
-                       if ( PyList_Append(partlist,seglist) < 0 ){
-                               Py_DECREF(seglist);
-                               Py_DECREF(partlist);
-                               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                               "Couldn't append item to PyList" );             
+                               if ( PyList_Append(partlist,seglist) < 0 ){
+                                       PyErr_SetString( PyExc_RuntimeError,
+                                                       "Couldn't append item to PyList" );             
+                                       goto error;
+                               }
+                               Py_DECREF(seglist); /* PyList_Append increfs */
+                               seglist = NULL;
                        }
-                       Py_DECREF(seglist); /* PyList_Append increfs */
                }
 
                cache=psys->childcache;
 
                for(i = 0; i < psys->totchild; i++){
-                       path=cache[i];
                        seglist = PyList_New( 0 );
-                       k = path->steps+1;
-                       for( j = 0; j < k ; j++){
-                               loc = PyTuple_New(3);
+                       if (!seglist){
+                               PyErr_SetString( PyExc_MemoryError,
+                                               "PyList_New() failed" );
+                               goto error;
+                       }
 
-                               PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)path->co[0]));
-                               PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)path->co[1]));
-                               PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)path->co[2]));
+                       path=cache[i];
+                       k = path->steps+1;
+                       for( j = 0; j < k ; j++, path++ ){
+                               loc = Py_BuildValue("(fff)",(double)path->co[0],
+                                               (double)path->co[1], (double)path->co[2]);
+
+                               if (!loc){
+                                       PyErr_SetString( PyExc_RuntimeError,
+                                                       "Couldn't build tuple" );
+                                       goto error;
+                               }
 
                                if ( PyList_Append(seglist,loc) < 0){
-                                       Py_DECREF(partlist);
-                                       Py_XDECREF(loc);
-                                       return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                                       PyErr_SetString( PyExc_RuntimeError,
                                                        "Couldn't append item to PyList" );
+                                       goto error;
                                }
                                Py_DECREF(loc);/* PyList_Append increfs */
-                               path++;
+                               loc = NULL;
                        }
 
                        if ( PyList_Append(partlist,seglist) < 0){
-                               Py_DECREF(partlist);
-                               Py_XDECREF(loc);
-                               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               PyErr_SetString( PyExc_RuntimeError,
                                                "Couldn't append item to PyList" );     
+                               goto error;
                        }
                        Py_DECREF(seglist); /* PyList_Append increfs */
+                       seglist = NULL;
                }
-               
        } else {
                int init;
-               partlist = PyList_New( 0 );
-               if( !partlist )
-                       return EXPP_ReturnPyObjError( PyExc_MemoryError, "PyList() failed" );
+               char *fmt = NULL;
+
+               if(id)
+                       fmt = "(fffi)";
+               else
+                       fmt = "(fff)";
 
                if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
                        childexists = 1;
@@ -919,55 +955,67 @@ static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args ){
                                init = 1;
 
                        if (init){
-                               if (!id)
-                                       loc = PyTuple_New(3);
-                               else
-                                       loc = PyTuple_New(4);
-                               PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)state.co[0]));
-                               PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)state.co[1]));
-                               PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)state.co[2]));
-                               if (id)
-                                       PyTuple_SetItem(loc,3,PyInt_FromLong(i));
+                               loc = Py_BuildValue(fmt,(double)state.co[0],
+                                               (double)state.co[1], (double)state.co[2],i);
+                               
+                               if (!loc){
+                                       PyErr_SetString( PyExc_RuntimeError,
+                                                       "Couldn't build tuple" );
+                                       goto error;
+                               }
 
                                if ( PyList_Append(partlist,loc) < 0 ){
-                                       Py_DECREF(partlist);
-                                       Py_XDECREF(loc);
-                                       return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                                               "Couldn't append item to PyList" );
+                                       PyErr_SetString( PyExc_RuntimeError,
+                                                       "Couldn't append item to PyList" );
+                                       goto error;
                                }
-                               Py_DECREF(loc);/* PyList_Append increfs */
-                       }
-                       else {
-                               if ( all ){
-                                       if ( PyList_Append(partlist,Py_None) < 0 ){
-                                               Py_DECREF(partlist);
-                                               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                                                       "Couldn't append item to PyList" );
-                                       }
-                                       Py_DECREF(Py_None); /* PyList_Append increfs */
+                               Py_DECREF(loc);
+                               loc = NULL;
+                       } else {
+                               if ( all && PyList_Append(partlist,Py_None) < 0 ){
+                                       PyErr_SetString( PyExc_RuntimeError,
+                                                       "Couldn't append item to PyList" );
+                                       goto error;
                                }
                        }
                }
        }
+
+       psys_render_restore(ob,psys);
+       G.rendering = 0;
+       Particle_Recalc(self,1);
        return partlist;
+
+error:
+       Py_XDECREF(partlist);
+       Py_XDECREF(seglist);
+       Py_XDECREF(loc);
+       psys_render_restore(ob,psys);
+       G.rendering = 0;
+       Particle_Recalc(self,1);
+       return NULL;
 }
 
-static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args ){
+static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args )
+{
        ParticleSystem *psys = 0L;
        Object *ob = 0L;
        PyObject *partlist = 0L;
        PyObject* loc = 0L;
        ParticleKey state;
+       DerivedMesh* dm;
+       float vm[4][4],wm[4][4];
        int i;
        int childexists = 0;
        int all = 0;
        int id = 0;
+    char *fmt = NULL;
 
        float cfra=bsystem_time(ob,(float)CFRA,0.0);
 
        if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
                return EXPP_ReturnPyObjError( PyExc_TypeError,
-                               "expected one optional integer as argument" );
+                               "expected two optional integers as arguments" );
 
        psys = self->psys;
        ob = self->object;
@@ -975,63 +1023,105 @@ static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args ){
        if (!ob || !psys)
                Py_RETURN_NONE;
 
-       if (psys->part->type != 2){
+       G.rendering = 1;
+
+       /* Just to create a valid rendering context */
+       psys_render_set(ob,psys,vm,wm,0,0,0);
+
+       dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+       dm->release(dm);
+
+       if ( !psys_check_enabled(ob,psys) ){
+               G.rendering = 0;
+               psys_render_restore(ob,psys);
+               Particle_Recalc(self,1);
+               Py_RETURN_NONE;
+       }
+
+       if (psys->part->type != PART_HAIR){
                partlist = PyList_New( 0 );
 
+               if( !partlist ){
+                       PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
+                       goto error;
+               }
+
                if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
                        childexists = 1;
 
+               if(id)
+                       fmt = "(ffffi)";
+               else
+                       fmt = "(ffff)";
+
                for (i = 0; i < psys->totpart + psys->totchild; i++){
                        if (childexists && (i < psys->totpart))
                                continue;
 
                        state.time = cfra;
                        if(psys_get_particle_state(ob,psys,i,&state,0)==0){
-                               if ( all ){
-                                       PyList_Append(partlist,Py_None);
-                                       Py_DECREF(Py_None); /* PyList_Append increfs */
-                                       continue;
-                               } else {
-                                       continue;
+                               if ( all && PyList_Append(partlist,Py_None) < 0){
+                                       PyErr_SetString( PyExc_RuntimeError,
+                                               "Couldn't append item to PyList" );
+                                       goto error;
+                               }
+                       } else {
+                               loc = Py_BuildValue(fmt,(double)state.rot[0], (double)state.rot[1],
+                                               (double)state.rot[2], (double)state.rot[3], i);
+
+                               if (!loc){
+                                       PyErr_SetString( PyExc_RuntimeError,
+                                                       "Couldn't build tuple" );
+                                       goto error;
+                               }
+                               if (PyList_Append(partlist,loc) < 0){
+                                       PyErr_SetString ( PyExc_RuntimeError,
+                                                       "Couldn't append item to PyList" );
+                                       goto error;
                                }
+                               Py_DECREF(loc); /* PyList_Append increfs */
+                               loc = NULL;
                        }
-                       if (!id)
-                               loc = PyTuple_New(4);
-                       else
-                               loc = PyTuple_New(5);
-                       PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)state.rot[0]));
-                       PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)state.rot[1]));
-                       PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)state.rot[2]));
-                       PyTuple_SetItem(loc,3,PyFloat_FromDouble((double)state.rot[3]));
-                       if (id)
-                               PyTuple_SetItem(loc,4,PyInt_FromLong(i));
-                       PyList_Append(partlist,loc);
-                       Py_DECREF(loc); /* PyList_Append increfs */
                }
+       } else {
+               partlist = EXPP_incr_ret( Py_None );
        }
+
+       psys_render_restore(ob,psys);
+       G.rendering = 0;
+       Particle_Recalc(self,1);
        return partlist;
+
+error:
+       Py_XDECREF(partlist);
+       Py_XDECREF(loc);
+       psys_render_restore(ob,psys);
+       G.rendering = 0;
+       Particle_Recalc(self,1);
+       return NULL;
 }
 
-static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args ){
+static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args )
+{
        ParticleKey state;
        ParticleSystem *psys = 0L;
        ParticleData *data;
        Object *ob = 0L;
        PyObject *partlist,*tuple;
-       PyObject* siz = 0L;
+       DerivedMesh* dm;
+       float vm[4][4],wm[4][4];
        float size;
        int i;
        int childexists = 0;
        int all = 0;
        int id = 0;
+    char *fmt = NULL;
 
        float cfra=bsystem_time(ob,(float)CFRA,0.0);
 
        if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
                return EXPP_ReturnPyObjError( PyExc_TypeError,
-                               "expected one optional integer as argument" );
-
-       data = self->psys->particles;
+                               "expected two optional integers as arguments" );
 
        psys = self->psys;
        ob = self->object;
@@ -1039,13 +1129,39 @@ static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args ){
        if (!ob || !psys)
                Py_RETURN_NONE;
 
-               partlist = PyList_New( 0 );
+       G.rendering = 1;
 
-               if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
-                       childexists = 1;
+       /* Just to create a valid rendering context */
+       psys_render_set(ob,psys,vm,wm,0,0,0);
+
+       dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+       dm->release(dm);
+       data = self->psys->particles;
+
+       if ( !psys_check_enabled(ob,psys) ){
+               psys_render_restore(ob,psys);
+               G.rendering = 0;
+               Particle_Recalc(self,1);
+               Py_RETURN_NONE;
+       }
+
+       partlist = PyList_New( 0 );
+
+       if( !partlist ){
+               PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
+               goto error;
+       }
+
+       if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
+               childexists = 1;
+
+       if(id)
+               fmt = "(fi)";
+       else
+               fmt = "f";
 
-               for (i = 0; i < psys->totpart + psys->totchild; i++, data++){
-               if (psys->part->type != 2){
+       for (i = 0; i < psys->totpart + psys->totchild; i++, data++){
+               if (psys->part->type != PART_HAIR){
                        if (childexists && (i < psys->totpart))
                                continue;
 
@@ -1061,43 +1177,61 @@ static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args ){
                                ChildParticle *cpa= &psys->child[i-psys->totpart];
                                size = psys_get_child_size(psys,cpa,cfra,0);
                        }
-                       if (id){
-                               tuple = PyTuple_New(2);
-                               PyTuple_SetItem(tuple,0,PyFloat_FromDouble((double)size));
-                               PyTuple_SetItem(tuple,1,PyInt_FromLong(i));
-                               PyList_Append(partlist,tuple);
-                               Py_DECREF(tuple);
-                       } else {
-                               siz = PyFloat_FromDouble((double)size);
-                               PyList_Append(partlist,siz);
-                               Py_DECREF(siz);
+
+                       tuple = Py_BuildValue(fmt,(double)size,i);
+
+                       if (!tuple){
+                               PyErr_SetString( PyExc_RuntimeError,
+                                               "Couldn't build tuple" );
+                               goto error;
+                       }
+
+                       if (PyList_Append(partlist,tuple) < 0){
+                               PyErr_SetString( PyExc_RuntimeError,
+                                               "Couldn't append item to PyList" );
+                               goto error;
                        }
+                       Py_DECREF(tuple);
+                       tuple = NULL;
                }
        }
+
+       psys_render_restore(ob,psys);
+       G.rendering = 0;
+       Particle_Recalc(self,1);
        return partlist;
+
+error:
+       Py_XDECREF(partlist);
+       Py_XDECREF(tuple);
+       psys_render_restore(ob,psys);
+       G.rendering = 0;
+       Particle_Recalc(self,1);
+       return NULL;
 }
 
 
-static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args ){
+static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args )
+{
        ParticleKey state;
        ParticleSystem *psys = 0L;
        ParticleData *data;
        Object *ob = 0L;
        PyObject *partlist,*tuple;
-       PyObject* lif = 0L;
+       DerivedMesh* dm;
+       float vm[4][4],wm[4][4];
        float life;
        int i;
        int childexists = 0;
        int all = 0;
        int id = 0;
+       char *fmt = NULL;
 
        float cfra=bsystem_time(ob,(float)CFRA,0.0);
 
        if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
                return EXPP_ReturnPyObjError( PyExc_TypeError,
-                               "expected one optional integer as argument" );
-
-       data = self->psys->particles;
+                               "expected two optional integers as arguments" );
 
        psys = self->psys;
        ob = self->object;
@@ -1105,13 +1239,37 @@ static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args ){
        if (!ob || !psys)
                Py_RETURN_NONE;
 
-               partlist = PyList_New( 0 );
+       G.rendering = 1;
 
-               if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
-                       childexists = 1;
+       /* Just to create a valid rendering context */
+       psys_render_set(ob,psys,vm,wm,0,0,0);
+
+       dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
+       dm->release(dm);
+       data = self->psys->particles;
+
+       if ( !psys_check_enabled(ob,psys) ){
+               psys_render_restore(ob,psys);
+               G.rendering = 0;
+               Py_RETURN_NONE;
+       }
+
+       partlist = PyList_New( 0 );
+       if( !partlist ){
+               PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
+               goto error;
+       }
+
+       if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
+               childexists = 1;
+
+       if(id)
+               fmt = "(fi)";
+       else
+               fmt = "f";
 
-               for (i = 0; i < psys->totpart + psys->totchild; i++, data++){
-               if (psys->part->type != 2){
+       for (i = 0; i < psys->totpart + psys->totchild; i++, data++){
+               if (psys->part->type != PART_HAIR){
 
                        if (childexists && (i < psys->totpart))
                                continue;
@@ -1128,20 +1286,37 @@ static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args ){
                                ChildParticle *cpa= &psys->child[i-psys->totpart];
                                life = psys_get_child_time(psys,cpa,cfra);
                        }
-                       if (id){
-                               tuple = PyTuple_New(2);
-                               PyTuple_SetItem(tuple,0,PyFloat_FromDouble((double)life));
-                               PyTuple_SetItem(tuple,1,PyInt_FromLong(i));
-                               PyList_Append(partlist,tuple);
-                               Py_DECREF(tuple);
-                       } else {
-                               lif = PyFloat_FromDouble((double)life);
-                               PyList_Append(partlist,lif);
-                               Py_DECREF(lif);
+
+                       tuple = Py_BuildValue(fmt,(double)life,i);
+
+                       if (!tuple){
+                               PyErr_SetString( PyExc_RuntimeError,
+                                               "Couldn't build tuple" );
+                               goto error;
                        }
+
+                       if (PyList_Append(partlist,tuple) < 0){
+                               PyErr_SetString( PyExc_RuntimeError,
+                                               "Couldn't append item to PyList" );
+                               goto error;
+                       }
+                       Py_DECREF(tuple);
+                       tuple = NULL;
                }
        }
+
+       psys_render_restore(ob,psys);
+       G.rendering = 0;
+       Particle_Recalc(self,1);
        return partlist;
+
+error:
+       Py_XDECREF(partlist);
+       Py_XDECREF(tuple);
+       psys_render_restore(ob,psys);
+       G.rendering = 0;
+       Particle_Recalc(self,1);
+       return NULL;
 }
 
 
@@ -1376,11 +1551,8 @@ static int Part_set2d( BPy_PartSys * self, PyObject * args )
 {
        int number;
 
-       if( !PyInt_Check( args ) ) {
-               char errstr[128];
-               sprintf ( errstr, "expected int argument" );
-               return EXPP_ReturnIntError( PyExc_TypeError, errstr );
-       }
+       if( !PyInt_Check( args ) )
+               return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
 
        number = PyInt_AS_LONG( args );
 
@@ -1526,7 +1698,7 @@ static int Part_setRandEmission( BPy_PartSys * self, PyObject * args )
 
 static PyObject *Part_getRandEmission( BPy_PartSys * self )
 {
-       return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BOIDS_2D )) > 0 );
+       return PyInt_FromLong( ((long)( self->psys->part->flag & PART_TRAND )) > 0 );
 }
 
 static int Part_setParticleDist( BPy_PartSys * self, PyObject * args )
@@ -1546,7 +1718,7 @@ static int Part_setParticleDist( BPy_PartSys * self, PyObject * args )
                return EXPP_ReturnIntError( PyExc_TypeError, errstr );
        }
 
-       self->psys->part->from = number;
+       self->psys->part->from = (short)number;
 
        Particle_RecalcPsys_distr(self,1);
 
@@ -1603,7 +1775,7 @@ static int Part_setDist( BPy_PartSys * self, PyObject * args )
                return EXPP_ReturnIntError( PyExc_TypeError, errstr );
        }
 
-       self->psys->part->distr = number;
+       self->psys->part->distr = (short)number;
 
        Particle_RecalcPsys_distr(self,1);
 
@@ -1731,7 +1903,7 @@ static int Part_setTargetPsys( BPy_PartSys * self, PyObject * args ){
 
        res = EXPP_setIValueRange( args, &self->psys->target_psys, 0, tottpsys, 'h' );
 
-       if((psys=psys_get_current(ob))){
+       if( ( psys = psys_get_current(ob) ) ){
                if(psys->keyed_ob==ob || psys->target_ob==ob){
                        if(psys->keyed_ob==ob)
                                psys->keyed_ob=NULL;
index 0a0df335fa3e76f6c68935a0a1cd5976b332cad9..01d5136cd70bd921c0305fc051cb94df111d5529 100644 (file)
@@ -18,7 +18,9 @@ class IDGroup:
        
        Note that for arrays, the array type defaults to int unless a float is found
        while scanning the template list; if any floats are found, then the whole
-       array is float.
+       array is float.  Note that double-precision floating point numbers are used for
+       python-created float ID properties and arrays (though the internal C api does 
+       support single-precision floats, and the python code will read them).
        
        You can also delete properties with the del operator.  For example:
        
index c479926ccf3a915713d9513642a6d8a763cadc99..d1c72f8cb86cfb06c5751336546463e0011a9426 100644 (file)
@@ -250,7 +250,7 @@ class Ipo:
                        OfsZ, SizeX, SizeY, SizeZ, texR, texG, texB, DefVar, Col, Nor, Var,
                        Disp.
                        3. Object Ipo: LocX, LocY, LocZ, dLocX, dLocY, dLocZ, RotX, RotY, RotZ,
-                       dRotX, dRotY, dRotZ, SizeX, SizeY, SizeZ, dSizeX, dSizeY, dSizeZ,
+                       dRotX, dRotY, dRotZ, ScaleX, ScaleY, ScaleZ, dScaleX, dScaleY, dScaleZ,
                        Layer, Time, ColR, ColG, ColB, ColA, FStreng, FFall, Damping,
                        RDamp, Perm.
                        4. Lamp Ipo: Energ, R, G, B, Dist, SpoSi, SpoBl, Quad1, Quad2, HaInt.
@@ -289,7 +289,7 @@ class Ipo:
                        OfsZ, SizeX, SizeY, SizeZ, texR, texG, texB, DefVar, Col, Nor, Var,
                        Disp.
                        3. Object Ipo: LocX, LocY, LocZ, dLocX, dLocY, dLocZ, RotX, RotY, RotZ,
-                       dRotX, dRotY, dRotZ, SizeX, SizeY, SizeZ, dSizeX, dSizeY, dSizeZ,
+                       dRotX, dRotY, dRotZ, ScaleX, ScaleY, ScaleZ, dScaleX, dScaleY, dScaleZ,
                        Layer, Time, ColR, ColG, ColB, ColA, FStreng, FFall, Damping,
                        RDamp, Perm.
                        4. Lamp Ipo: Energ, R, G, B, Dist, SpoSi, SpoBl, Quad1, Quad2, HaInt.
index 47bd7fdb763efafd334438c4eea7bfe24f2efff2..daa6a186531958a3e555b90671efe661bdc7034c 100644 (file)
@@ -27,17 +27,37 @@ Example::
 """
 
 def load(filename,relative=False):
-  """
-  Select an existing .blend file for use as a library.  Unlike the 
-  Library module, multiple libraries can be defined at the same time.  
-  
-  @type filename: string
-  @param filename: The filename of a Blender file. Filenames starting with "//" will be loaded relative to the blend file's location.
-  @type relative: boolean
-  @param relative: Convert relative paths to absolute paths (default).  Setting this parameter to True will leave paths relative.
-  @rtype: Library
-  @return: return a L{Library} object.
-  """
+       """
+       Select an existing .blend file for use as a library.  Unlike the 
+       Library module, multiple libraries can be defined at the same time.  
+       
+       @type filename: string
+       @param filename: The filename of a Blender file. Filenames starting with "//" will be loaded relative to the blend file's location.
+       @type relative: boolean
+       @param relative: Convert relative paths to absolute paths (default).  Setting this parameter to True will leave paths relative.
+       @rtype: Library
+       @return: return a L{Library} object.
+       """
+
+def paths(link=0):
+       """
+       Returns a list of paths used in the current blend file.
+       
+       @type link: int
+       @param link: 0 (default if no args given) for all library paths, 1 for directly linked library paths only, 2 for indirectly linked library paths only.
+       @rtype: List
+       @return: return a list of path strings.
+       """
+
+def replace(pathFrom, pathTo):
+       """
+       Replaces an existing directly linked path.
+       
+       @type pathFrom: string
+       @param pathFrom: An existing library path.
+       @type pathTo: string
+       @param pathTo: A new library path.
+       """
 
 class Libraries:
        """
index 192ecd5355b3a92383239d16e8a0efdd7b00b28e..511ad81b45f0ccc5fe51ed305e6ca2f084e25f60 100644 (file)
@@ -56,17 +56,17 @@ class Particle:
        @type type: int
        @ivar resolutionGrid: The resolution of the particle grid.
        @type resolutionGrid: int
-       @ivar startFrame: Frame # to start emitting particles.
+       @ivar startFrame: Frame number to start emitting particles.
        @type startFrame: float
-       @ivar endFrame: Frame # to stop emitting particles.
+       @ivar endFrame: Frame number to stop emitting particles.
        @type endFrame: float
        @ivar editable: Finalize hair to enable editing in particle mode.
        @type editable: int
        @ivar amount: The total number of particles.
        @type amount: int
-       @ivar multireact: React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] ).
+       @ivar multireact: React multiple times ( Particle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] ).
        @type multireact: int
-       @ivar reactshape: Power of reaction strength dependence on distance to target.
+       @ivar reactshape: Power of reaction strength, dependent on distance to target.
        @type reactshape: float
        @ivar hairSegments: Amount of hair segments.
        @type hairSegments: int
@@ -74,13 +74,13 @@ class Particle:
        @type lifetime: float
        @ivar randlife: Give the particle life a random variation.
        @type randlife: float
-       @ivar randemission: Give the particle life a random variation
+       @ivar randemission: Emit particles in random order.
        @type randemission: int
-       @ivar particleDistribution: Where to emit particles from  Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] )
+       @ivar particleDistribution: Where to emit particles from  ( Particle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] )
        @type particleDistribution: int
        @ivar evenDistribution: Use even distribution from faces based on face areas or edge lengths.
        @type evenDistribution: int
-       @ivar distribution: How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] ).
+       @ivar distribution: How to distribute particles on selected element ( Particle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] ).
        @type distribution: int
        @ivar jitterAmount: Amount of jitter applied to the sampling.
        @type jitterAmount: float
@@ -131,237 +131,56 @@ class Particle:
                Get the particles locations.
                A list of tuple is returned in particle mode.
                A list of list of tuple is returned in hair mode.
-               The tuple is a vector list of 3 or 4 floats in world space (x,y,z, optionnaly the particle's id).
+               The tuple is a vector of 3 or 4 floats in world space (x,y,z,
+optionally the particle's id).
                @type all: int
                @param all: if not 0 export all particles (uninitialized (unborn or died)particles exported as None).
                @type id: int
                @param id: add the particle id in the end of the vector tuple
-               @rtype: list of vectors (tuple of 3 floats and optionnaly the id) or list of list of vectors
-               @return: list of vectors or list of list of vectors (hair mode)
+               @rtype: list of vectors (tuple of 3 floats and optionally the id) or list of list of vectors
+               @return: list of vectors or list of list of vectors (hair mode) or None if system is disabled
                """
        def getRot(all=0,id=0):
                """
-               Get the particles rotations as quaternion.
+               Get the particles' rotations as quaternion.
                A list of tuple is returned in particle mode.
-               The tuple is a vector list of 4 or 5 floats (x,y,z,w, optionnaly the id of the particle).
+               The tuple is vector of 4 or 5 floats (x,y,z,w, optionally the id of the particle).
                
                @type all: int
-               @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None).
+               @param all: if not 0, export all particles (uninitialized (unborn or died) particles exported as None).
                @type id: int
                @param id: add the particle id in the return tuple
                @rtype: list of tuple of 4 or 5 elements (if id is not zero)
-               @return: list of 4-tuples
+               @return: list of 4-tuples or None if system is disabled
                """
                
        def getMat():
                """
-               Get the particles material.
+               Get the particles' material.
                @rtype: Blender Material
-               @return: The marterial assigned to particles
+               @return: The material assigned to particles
                """
                
        def getSize(all=0,id=0):
                """
-               Get the particles size.
+               Get the particles' size.
                A list of float or list of tuple (particle's size,particle's id).
                @type all: int
-               @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None).
+               @param all: if not 0, export all particles (uninitialized (unborn or died) particles exported as None).
                @type id: int
                @param id: add the particle id in the return tuple
                @rtype: list of floats
-               @return: list of floats or list of tuples if id is not zero (size,id).
+               @return: list of floats or list of tuples if id is not zero (size,id) or None if system is disabled.
                """
                
        def getAge(all=0,id=0):
                """
-               Get the particles age.
-               A list of float or list of tuple (particle's age,particle's id).
+               Get the particles' age.
+               A list of float or list of tuple (particle's age, particle's id).
                @type all: int
-               @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None).
+               @param all: if not 0, export all particles (uninitialized (unborn or died) particles exported as None).
                @type id: int
                @param id: add the particle id in the return tuple
                @rtype: list of floats
-               @return: list of floats or list of tuples if id is not zero (size,id).
-               """
-# Blender.Object module and the Object PyType object
-
-"""
-The Blender.Particle submodule
-
-
-Particle
-========
-
-This module provides access to the B{Particle} in Blender.
-
-@type TYPE: readonly dictionary
-@var TYPE: Constant dict used for with L{Particle.TYPE}
-               - HAIR: set particle system to hair mode.
-               - REACTOR: set particle system to reactor mode.
-               - EMITTER: set particle system to emitter mode.
-@type DISTRIBUTION: readonly dictionary
-@var DISTRIBUTION: Constant dict used for with L{Particle.DISTRIBUTION}
-               - GRID: set grid distribution.
-               - RANDOM: set random distribution.
-               - JITTERED: set jittered distribution.
-@type EMITFROM: readonly dictionary
-@var EMITFROM: Constant dict used for with L{Particle.EMITFROM}
-               - VERTS: set particles emit from vertices
-               - FACES: set particles emit from faces
-               - VOLUME: set particles emit from volume
-               - PARTICLE: set particles emit from particles
-@type REACTON: readonly dictionary
-@var REACTON: Constant dict used for with L{Particle.REACTON}
-               - NEAR: react on near
-               - COLLISION: react on collision
-               - DEATH: react on death
-@type DRAWAS: readonly dictionary
-@var DRAWAS: Constant dict used for with L{Particle.DRAWAS}
-               - NONE: Don't draw
-               - POINT: Draw as point
-               - CIRCLE: Draw as circles
-               - CROSS: Draw as crosses
-               - AXIS: Draw as axis
-               - LINE: Draw as lines
-               - PATH: Draw pathes
-               - OBJECT: Draw object
-               - GROUP: Draw goup
-               - BILLBOARD: Draw as billboard 
-"""
-
-def Get(name):
-               """
-               Get the particle system of the object "name".
-               @type name: string
-               @return: The particle system of the object.
-               """
-def New(name):
-               """
-               Assign a new particle system to the object "name".
-               @type name: string
-               @return: The newly created particle system.
-               """
-
-class Particle:
-       """
-       The Particle object
-       ===================
-               This object gives access to paticles data.
-               
-       @ivar seed: Set an offset in the random table.
-       @type seed: int
-       @ivar type: Type of particle system ( Particle.TYPE[ 'HAIR' | 'REACTOR' | 'EMITTER' ] ).
-       @type type: int
-       @ivar resolutionGrid: The resolution of the particle grid.
-       @type resolutionGrid: int
-       @ivar startFrame: Frame # to start emitting particles.
-       @type startFrame: float
-       @ivar endFrame: Frame # to stop emitting particles.
-       @type endFrame: float
-       @ivar editable: Finalize hair to enable editing in particle mode.
-       @type editable: int
-       @ivar amount: The total number of particles.
-       @type amount: int
-       @ivar multireact: React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] ).
-       @type multireact: int
-       @ivar reactshape: Power of reaction strength dependence on distance to target.
-       @type reactshape: float
-       @ivar hairSegments: Amount of hair segments.
-       @type hairSegments: int
-       @ivar lifetime: Specify the life span of the particles.
-       @type lifetime: float
-       @ivar randlife: Give the particle life a random variation.
-       @type randlife: float
-       @ivar randemission: Give the particle life a random variation
-       @type randemission: int
-       @ivar particleDistribution: Where to emit particles from  Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] )
-       @type particleDistribution: int
-       @ivar evenDistribution: Use even distribution from faces based on face areas or edge lengths.
-       @type evenDistribution: int
-       @ivar distribution: How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] ).
-       @type distribution: int
-       @ivar jitterAmount: Amount of jitter applied to the sampling.
-       @type jitterAmount: float
-       @ivar pf: Emission locations / face (0 = automatic).
-       @type pf:int
-       @ivar invert: Invert what is considered object and what is not.
-       @type invert: int
-       @ivar targetObject: The object that has the target particle system (empty if same object).
-       @type targetObject: Blender object
-       @ivar targetpsys: The target particle system number in the object.
-       @type targetpsys: int
-       @ivar 2d: Constrain boids to a surface.
-       @type 2d: float
-       @ivar maxvel: Maximum velocity.
-       @type maxvel: float
-       @ivar avvel: The usual speed % of max velocity.
-       @type avvel: float
-       @ivar latacc: Lateral acceleration % of max velocity
-       @type latacc: float
-       @ivar tanacc: Tangential acceleration % of max velocity
-       @type tanacc: float
-       @ivar groundz: Default Z value.
-       @type groundz: float
-       @ivar object: Constrain boids to object's surface.
-       @type object: Blender Object
-       @ivar renderEmitter: Render emitter object.
-       @type renderEmitter: int
-       @ivar displayPercentage: Particle display percentage.
-       @type displayPercentage: int
-       @ivar hairDisplayStep: How many steps paths are drawn with (power of 2) in visu mode.
-       @type hairDisplayStep: int
-       @ivar hairRenderStep: How many steps paths are rendered with (power of 2) in render mode."
-       @type hairRenderStep: int
-       @ivar duplicateObject: Get the duplicate object.
-       @type duplicateObject: Blender Object
-       @ivar drawAs: Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ]).
-       @type drawAs: int
-       """
-       def freeEdit():
-               """
-               Free edit mode.
-               @return: None
-               """
-
-       def getLoc(all=0,id=0):
-               """
-               Get the particles locations.
-               A list of tuple is returned in particle mode.
-               A list of list of tuple is returned in hair mode.
-               The tuple is a vector list of 3 floats in world space.
-               @type all: int
-               @param all: if not 0 export all particles (uninitialized (unborn or died)particles exported as None).
-               @type id: int
-               @param id: add the particle id in the end of the vector tuple
-               @rtype: list of vectors (tuple of 3 floats and optionnaly the id) or list of list of vectors
-               @return: list of vectors or list of list of vectors (hair mode)
-               """
-       def getRot(all=0,id=0):
-               """
-               Get the particles rotations as quaternion.
-               A list of tuple is returned in particle mode.
-               The tuple is a vector list of 4 floats (quaternion).
-               @type all: int
-               @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None).
-               @type id: int
-               @param id: add the particle id in the return tuple
-               @rtype: list of tuple of 4 or 5 elements (if id is not zero)
-               @return: list of 4-tuples
-               """
-       def getMat():
-               """
-               Get the particles material.
-               @rtype: Blender Material
-               @return: The marterial assigned to particles
-               """
-       def getSize(all=0,id=0):
-               """
-               Get the particles size.
-               A list of float.
-               @type all: int
-               @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None).
-               @type id: int
-               @param id: add the particle id in the return tuple
-               @rtype: list of floats
-               @return: list of floats or list of tuples if id is not zero (size,id).
+               @return: list of floats or list of tuples if id is not zero (size,id) or None if system is disabled.
                """
index d382d4509703321dd5ce1e039c57c09dd1671224..8f251fc84525dcddffb73393d633e0cc5c319442 100644 (file)
@@ -565,6 +565,8 @@ PyObject *RenderData_SaveRenderedImage ( BPy_RenderData * self, PyObject *args )
 PyObject *RenderData_RenderAnim( BPy_RenderData * self )
 {
        Scene *oldsce;
+       /* this prevents a deadlock when there are pynodes: */
+       PyThreadState *tstate = PyEval_SaveThread();
 
        if (!G.background) {
                oldsce = G.scene;
@@ -582,9 +584,9 @@ PyObject *RenderData_RenderAnim( BPy_RenderData * self )
                if (G.scene->r.sfra > G.scene->r.efra)
                        return EXPP_ReturnPyObjError (PyExc_RuntimeError,
                                "start frame must be less or equal to end frame");
-               
                RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra);
        }
+       PyEval_RestoreThread(tstate);
        Py_RETURN_NONE;
 }
 
index 0928042729a5c65a26cf3fb467e3246e43fbb567..5b69323667edce2188c09b7045d5431f0c430a8b 100644 (file)
@@ -1379,6 +1379,8 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int
                }
                
                /* specularity */
+               shadfac[3]*= phongcorr; /* note, shadfac not allowed to be stored nonlocal */
+               
                if(shadfac[3]>0.0f && shi->spec!=0.0f && !(lar->mode & LA_NO_SPEC) && !(lar->mode & LA_ONLYSHADOW)) {
                        
                        if(!(passflag & (SCE_PASS_COMBINED|SCE_PASS_SPEC)));
index 529a795a101e90c7167b07838b04ae01e5d1e48f..4a4eaf3c81faf0da2c4b50a45ae1364fe3d0a0a4 100644 (file)
@@ -1929,7 +1929,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                        uiBlockBeginAlign(block);
                        uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
                                          lx, (cy -= 19), buttonWidth, 19, &bmd->value,
-                                         0.0, 0.5, 5, 2,
+                                         0.0, 0.5, 5, 4,
                                          "Bevel value/amount");
                        /*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
                                          lx, (cy -= 19), buttonWidth, 19, &bmd->res,
index 441d00ffc30cc9d173a833ec50eb8d63c253a9b3..498edc0dfed3f3214ecb6f43e6ec8e79aa2629ba 100644 (file)
@@ -2062,7 +2062,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
                        coa->time = 0;
                        uiDefButS(block, MENU, 1, str,          xco+10, yco-65, 70, 19, &coa->flag, 0.0, 0.0, 0, 0, "");
                
-                       uiDefButS(block, NUM,           0, "Damp:",     xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "");
+                       uiDefButS(block, NUM,           0, "damp",      xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter");
                        uiDefBut(block, LABEL,                  0, "Min",       xco+80, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, "");
                        uiDefBut(block, LABEL,                  0, "Max",       xco+80+(width-90)/2, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, "");
 
@@ -2084,12 +2084,12 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
                        str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4|-X axis %x8|-Y axis %x16|-Z axis %x32";
                        uiDefButS(block, MENU, B_REDR, str,             xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Set the direction of the ray");
                
-                       uiDefButS(block, NUM,           0, "Damp:",     xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "");
+                       uiDefButS(block, NUM,           0, "damp",      xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter");
                        uiDefBut(block, LABEL,                  0, "Range",     xco+80, yco-45, (width-115)/2, 19, NULL, 0.0, 0.0, 0, 0, "Set the maximum length of ray");
                        uiDefButBitS(block, TOG, ACT_CONST_DISTANCE, B_REDR, "Dist",    xco+80+(width-115)/2, yco-45, (width-115)/2, 19, &coa->flag, 0.0, 0.0, 0, 0, "Force distance of object to point of impact of ray");
 
-                       if(coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRMX)) fp= coa->minloc;
-                       else if(coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRMY)) fp= coa->minloc+1;
+                       if(coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc;
+                       else if(coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1;
                        else fp= coa->minloc+2;
 
                        uiDefButF(block, NUM, 0, "",            xco+80, yco-65, (width-115)/2, 19, fp+3, 0.0, 2000.0, 10, 0, "Maximum length of ray");
@@ -2124,7 +2124,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
                        str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4";
                        uiDefButS(block, MENU, B_REDR, str,             xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Select the axis to be aligned along the reference direction");
                
-                       uiDefButS(block, NUM,           0, "Damp:",     xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "");
+                       uiDefButS(block, NUM,           0, "damp",      xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter");
                        uiDefBut(block, LABEL,                  0, "X", xco+80, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, "");
                        uiDefBut(block, LABEL,                  0, "Y", xco+80+(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, "");
                        uiDefBut(block, LABEL,                  0, "Z", xco+80+2*(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, "");
@@ -2133,7 +2133,9 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
                        uiDefButF(block, NUM, 0, "",            xco+80+(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[1], -2000.0, 2000.0, 10, 0, "Y component of reference direction");
                        uiDefButF(block, NUM, 0, "",            xco+80+2*(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[2], -2000.0, 2000.0, 10, 0, "Z component of reference direction");
 
-                       uiDefButS(block, NUM, 0, "time", xco+10, yco-84, 70+(width-115)/3, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited");
+                       uiDefButS(block, NUM, 0, "time", xco+10, yco-84, 70, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited");
+                       uiDefButF(block, NUM, 0, "min", xco+80, yco-84, (width-115)/2, 19, &(coa->minloc[0]), 0.0, 180.0, 10, 1, "Minimum angle (in degree) to maintain with target direction. No correction is done if angle with target direction is between min and max");
+                       uiDefButF(block, NUM, 0, "max", xco+80+(width-115)/2, yco-84, (width-115)/2, 19, &(coa->maxloc[0]), 0.0, 180.0, 10, 1, "Maximum angle (in degree) allowed with target direction. No correction is done if angle with target direction is between min and max");
                }
                str= "Constraint Type %t|Location %x0|Distance %x1|Orientation %x2";
                but = uiDefButS(block, MENU, B_REDR, str,               xco+40, yco-23, (width-80), 19, &coa->type, 0.0, 0.0, 0, 0, "");
index 6fe37c1c6e50b569773ba527b55ce448d97d9982..0782ccfc7ee1ab0fdf000637c9519d6bc043deee 100644 (file)
@@ -58,6 +58,7 @@
 #include "DNA_constraint_types.h"
 #include "DNA_key_types.h"
 #include "DNA_userdef_types.h"
+#include "DNA_gpencil_types.h"
 
 #include "BKE_action.h"
 #include "BKE_depsgraph.h"
@@ -74,6 +75,7 @@
 #include "BIF_editnla.h"
 #include "BIF_interface.h"
 #include "BIF_interface_icons.h"
+#include "BIF_drawgpencil.h"
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 #include "BIF_resources.h"
 
 #include "BDR_drawaction.h"
 #include "BDR_editcurve.h"
+#include "BDR_gpencil.h"
 
 #include "BSE_drawnla.h"
 #include "BSE_drawipo.h"
+#include "BSE_drawview.h"
 #include "BSE_editaction_types.h"
 #include "BSE_editipo.h"
 #include "BSE_time.h"
@@ -464,7 +468,7 @@ static void draw_channel_names(void)
                        bActionGroup *grp = NULL;
                        short indent= 0, offset= 0, sel= 0, group=0;
                        int expand= -1, protect = -1, special= -1, mute = -1;
-                       char name[32];
+                       char name[64];
                        
                        /* determine what needs to be drawn */
                        switch (ale->type) {
@@ -622,12 +626,112 @@ static void draw_channel_names(void)
                                        sprintf(name, "Constraint");
                                }
                                        break;
+                               case ACTTYPE_GPDATABLOCK: /* gpencil datablock */
+                               {
+                                       bGPdata *gpd = (bGPdata *)ale->data;
+                                       ScrArea *sa = (ScrArea *)ale->owner;
+                                       
+                                       indent = 0;
+                                       group= 3;
+                                       
+                                       /* only show expand if there are any channels */
+                                       if (gpd->layers.first) {
+                                               if (gpd->flag & GP_DATA_EXPAND)
+                                                       expand = ICON_TRIA_DOWN;
+                                               else
+                                                       expand = ICON_TRIA_RIGHT;
+                                       }
+                                       
+                                       switch (sa->spacetype) {
+                                               case SPACE_VIEW3D:
+                                               {
+                                                       /* this shouldn't cause any overflow... */
+                                                       sprintf(name, "3DView: %s", view3d_get_name(sa->spacedata.first));
+                                                       special= ICON_VIEW3D;
+                                               }
+                                                       break;
+                                               case SPACE_NODE:
+                                               {
+                                                       SpaceNode *snode= sa->spacedata.first;
+                                                       char treetype[12];
+                                                       
+                                                       if (snode->treetype == 1)
+                                                               sprintf(treetype, "Composite");
+                                                       else
+                                                               sprintf(treetype, "Material");
+                                                       sprintf(name, "Nodes: %s", treetype);
+                                                       
+                                                       special= ICON_NODE;
+                                               }
+                                                       break;
+                                               case SPACE_SEQ:
+                                               {
+                                                       SpaceSeq *sseq= sa->spacedata.first;
+                                                       char imgpreview[10];
+                                                       
+                                                       switch (sseq->mainb) {
+                                                               case 1:         sprintf(imgpreview, "Image...");        break;
+                                                               case 2:         sprintf(imgpreview, "Luma...");         break;
+                                                               case 3:         sprintf(imgpreview, "Chroma...");       break;
+                                                               case 4:         sprintf(imgpreview, "Histogram");       break;
+                                                               
+                                                               default:        sprintf(imgpreview, "Sequence");        break;
+                                                       }
+                                                       sprintf(name, "Sequencer: %s", imgpreview);
+                                                       
+                                                       special= ICON_SEQUENCE;
+                                               }
+                                                       break;
+                                               
+                                               default:
+                                               {
+                                                       sprintf(name, "<Unknown GP-Data Source>");
+                                                       special= -1;
+                                               }
+                                                       break;
+                                       }
+                               }
+                                       break;
+                               case ACTTYPE_GPLAYER: /* gpencil layer */
+                               {
+                                       bGPDlayer *gpl = (bGPDlayer *)ale->data;
+                                       
+                                       indent = 0;
+                                       special = -1;
+                                       expand = -1;
+                                       group = 1;
+                                       
+                                       if (EDITABLE_GPL(gpl))
+                                               protect = ICON_UNLOCKED;
+                                       else
+                                               protect = ICON_LOCKED;
+                                               
+                                       if (gpl->flag & GP_LAYER_HIDE)
+                                               mute = ICON_MUTE_IPO_ON;
+                                       else
+                                               mute = ICON_MUTE_IPO_OFF;
+                                       
+                                       sel = SEL_GPL(gpl);
+                                       BLI_snprintf(name, 32, gpl->info);
+                               }
+                                       break;
                        }       
 
                        /* now, start drawing based on this information */
                        /* draw backing strip behind channel name */
-                       if (group == 2) {
-                               /* only for group-channels */
+                       if (group == 3) {
+                               /* only for gp-data channels */
+                               if (ale->owner == curarea) // fixme... currently useless
+                                       BIF_ThemeColorShade(TH_GROUP_ACTIVE, 10);
+                               else
+                                       BIF_ThemeColorShade(TH_GROUP, 20);
+                               uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
+                               gl_round_box(GL_POLYGON, x,  yminc, (float)NAMEWIDTH, ymaxc, 8);
+                               
+                               offset = 0;
+                       }
+                       else if (group == 2) {
+                               /* only for action group channels */
                                if (ale->flag & AGRP_ACTIVE)
                                        BIF_ThemeColorShade(TH_GROUP_ACTIVE, 10);
                                else
@@ -673,13 +777,19 @@ static void draw_channel_names(void)
                                offset += 17;
                        }
                        
-                       /* draw special icon indicating type of ipo-blocktype? 
-                        *      only for expand widgets for Ipo and Constraint Channels 
-                        */
-                       if (special > 0) {
-                               offset = (group) ? 29 : 24;
-                               BIF_icon_draw(x+offset, yminc, special);
-                               offset += 17;
+                       /* draw special icon indicating certain data-types */
+                       if (special > -1) {
+                               if (group == 3) {
+                                       /* for gpdatablock channels */
+                                       BIF_icon_draw(x+offset, yminc, special);
+                                       offset += 17;
+                               }
+                               else {
+                                       /* for ipo/constraint channels */
+                                       offset = (group) ? 29 : 24;
+                                       BIF_icon_draw(x+offset, yminc, special);
+                                       offset += 17;
+                               }
                        }
                                
                        /* draw name */
@@ -695,13 +805,13 @@ static void draw_channel_names(void)
                        offset = 0;
                        
                        /* draw protect 'lock' */
-                       if (protect > 0) {
+                       if (protect > -1) {
                                offset = 16;
                                BIF_icon_draw(NAMEWIDTH-offset, yminc, protect);
                        }
                        
                        /* draw mute 'eye' */
-                       if (mute > 0) {
+                       if (mute > -1) {
                                offset += 16;
                                BIF_icon_draw(NAMEWIDTH-offset, yminc, mute);
                        }
@@ -827,6 +937,12 @@ static void draw_channel_strips(void)
                                        sel = SEL_ICU(icu);
                                }
                                        break;
+                               case ACTTYPE_GPLAYER:
+                               {
+                                       bGPDlayer *gpl = (bGPDlayer *)ale->data;
+                                       sel = SEL_GPL(gpl);
+                               }
+                                       break;
                        }
                        
                        if (datatype == ACTCONT_ACTION) {
@@ -865,6 +981,19 @@ static void draw_channel_strips(void)
                                glColor4ub(col2[0], col2[1], col2[2], 0x44);
                                glRectf(frame1_x, channel_y-CHANNELHEIGHT/2, G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
                        }
+                       else if (datatype == ACTCONT_GPENCIL) {
+                               gla2DDrawTranslatePt(di, G.v2d->cur.xmin, y, &frame1_x, &channel_y);
+                               
+                               /* frames less than one get less saturated background */
+                               if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
+                               else glColor4ub(col2[0], col2[1], col2[2], 0x22);
+                               glRectf(0, channel_y-CHANNELHEIGHT/2, frame1_x, channel_y+CHANNELHEIGHT/2);
+                               
+                               /* frames one and higher get a saturated background */
+                               if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
+                               else glColor4ub(col2[0], col2[1], col2[2], 0x44);
+                               glRectf(frame1_x, channel_y-CHANNELHEIGHT/2, G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
+                       }
                }
                
                /*      Increment the step */
@@ -899,6 +1028,9 @@ static void draw_channel_strips(void)
                                case ALE_ICU:
                                        draw_icu_channel(di, ale->key_data, y);
                                        break;
+                               case ALE_GPFRAME:
+                                       draw_gpl_channel(di, ale->data, y);
+                                       break;
                        }
                }
                
@@ -1075,6 +1207,7 @@ void drawactionspace(ScrArea *sa, void *spacedata)
 {
        bAction *act = NULL;
        Key *key = NULL;
+       bGPdata *gpd = NULL;
        void *data;
        short datatype;
        
@@ -1090,18 +1223,32 @@ void drawactionspace(ScrArea *sa, void *spacedata)
 
        /* only try to refresh action that's displayed if not pinned */
        if (G.saction->pin==0) {
-               if (OBACT)
-                       G.saction->action = OBACT->action;
-               else
-                       G.saction->action= NULL;
+               /* depends on mode */
+               switch (G.saction->mode) {
+                       case SACTCONT_ACTION:
+                       {
+                               if (OBACT)
+                                       G.saction->action = OBACT->action;
+                               else
+                                       G.saction->action= NULL;
+                       }
+                               break;
+               }
        }
        
        /* get data */
        data = get_action_context(&datatype);
-       if (datatype == ACTCONT_ACTION)
-               act = data;
-       else if (datatype == ACTCONT_SHAPEKEY)
-               key = data;
+       switch (datatype) {
+               case ACTCONT_ACTION:
+                       act = data;
+                       break;
+               case ACTCONT_SHAPEKEY:
+                       key = data;
+                       break;
+               case ACTCONT_GPENCIL:
+                       gpd = data;
+                       break;
+       }
        
        /* Lets make sure the width of the left hand of the screen
         * is set to an appropriate value based on whether sliders
@@ -1450,10 +1597,15 @@ static ActKeysInc *init_aki_data()
        static ActKeysInc aki;
        
        /* init data of static struct here */
-       if ((curarea->spacetype == SPACE_ACTION) && NLA_ACTION_SCALED)
+       if ((curarea->spacetype == SPACE_ACTION) && NLA_ACTION_SCALED &&
+               (G.saction->mode == SACTCONT_ACTION))
+       {
                aki.ob= OBACT;
+       }
        else if (curarea->spacetype == SPACE_NLA)
+       {
                aki.ob= NULL; // FIXME
+       }
        else
                aki.ob= NULL;
                
@@ -1528,6 +1680,16 @@ void draw_action_channel(gla2DDrawInfo *di, bAction *act, float ypos)
        BLI_freelistN(&keys);
 }
 
+void draw_gpl_channel(gla2DDrawInfo *di, bGPDlayer *gpl, float ypos)
+{
+       ListBase keys = {0, 0};
+       ActKeysInc *aki = init_aki_data();
+       
+       gpl_to_keylist(gpl, &keys, NULL, aki);
+       draw_keylist(di, &keys, NULL, ypos);
+       BLI_freelistN(&keys);
+}
+
 /* --------------- Conversion: data -> keyframe list ------------------ */
 
 void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
@@ -1674,3 +1836,26 @@ void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks, ActKeysIn
        }
 }
 
+void gpl_to_keylist(bGPDlayer *gpl, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
+{
+       bGPDframe *gpf;
+       ActKeyColumn *ak;
+       
+       if (gpl && keys) {
+               /* loop over frames, converting directly to 'keyframes' (should be in order too) */
+               for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+                       ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
+                       BLI_addtail(keys, ak);
+                       
+                       ak->cfra= gpf->framenum;
+                       ak->modified = 1;
+                       ak->handle_type= 0; 
+                       
+                       if (gpf->flag & GP_FRAME_SELECT)
+                               ak->sel = SELECT;
+                       else
+                               ak->sel = 0;
+               }
+       }
+}
+
diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c
new file mode 100644 (file)
index 0000000..aacae08
--- /dev/null
@@ -0,0 +1,673 @@
+/**
+ * $Id: drawgpencil.c 14881 2008-05-18 10:41:42Z aligorith $
+ *
+ * ***** 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+#include "DNA_listBase.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+#include "BKE_blender.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+#include "BIF_butspace.h"
+#include "BIF_graphics.h"
+#include "BIF_interface.h"
+#include "BIF_mywindow.h"
+#include "BIF_resources.h"
+#include "BIF_space.h"
+#include "BIF_screen.h"
+#include "BIF_toolbox.h"
+#include "BIF_toets.h"
+
+#include "BDR_gpencil.h"
+#include "BIF_drawgpencil.h"
+
+#include "BSE_drawipo.h"
+#include "BSE_headerbuttons.h"
+#include "BSE_view.h"
+
+#include "blendef.h"
+#include "butspace.h"
+
+#include "PIL_time.h"                  /* sleep                                */
+#include "mydevice.h"
+
+/* ************************************************** */
+/* GREASE PENCIL PANEL-UI DRAWING */
+
+/* Every space which implements Grease-Pencil functionality should have a panel
+ * for the settings. All of the space-dependent parts should be coded in the panel
+ * code for that space, but the rest is all handled by generic panel here.
+ */
+
+/* ------- Callbacks ----------- */
+/* These are just 'dummy wrappers' around gpencil api calls */
+
+/* make layer active one after being clicked on */
+void gp_ui_activelayer_cb (void *gpd, void *gpl)
+{
+       gpencil_layer_setactive(gpd, gpl);
+       allqueue(REDRAWACTION, 0);
+}
+
+/* rename layer and set active */
+void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg)
+{
+       bGPdata *gpd= (bGPdata *)gpd_arg;
+       bGPDlayer *gpl= (bGPDlayer *)gpl_arg;
+       
+       BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info[0]), 128);
+       gpencil_layer_setactive(gpd, gpl);
+       allqueue(REDRAWACTION, 0);
+}
+
+/* add a new layer */
+void gp_ui_addlayer_cb (void *gpd, void *dummy)
+{
+       gpencil_layer_addnew(gpd);
+       allqueue(REDRAWACTION, 0);
+}
+
+/* delete active layer */
+void gp_ui_dellayer_cb (void *gpd, void *dummy)
+{
+       gpencil_layer_delactive(gpd);
+       allqueue(REDRAWACTION, 0);
+}
+
+/* delete last stroke of active layer */
+void gp_ui_delstroke_cb (void *gpd, void *gpl)
+{
+       bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
+       
+       gpencil_layer_setactive(gpd, gpl);
+       gpencil_frame_delete_laststroke(gpf);
+}
+
+/* delete active frame of active layer */
+void gp_ui_delframe_cb (void *gpd, void *gpl)
+{
+       bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
+       
+       gpencil_layer_setactive(gpd, gpl);
+       gpencil_layer_delframe(gpl, gpf);
+       
+       allqueue(REDRAWACTION, 0);
+}
+
+/* ------- Drawing Code ------- */
+
+/* draw the controls for a given layer */
+static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short *xco, short *yco)
+{
+       uiBut *but;
+       short active= (gpl->flag & GP_LAYER_ACTIVE);
+       short width= 314;
+       short height;
+       int rb_col;
+       
+       /* unless button has own callback, it adds this callback to button */
+       uiBlockSetFunc(block, gp_ui_activelayer_cb, gpd, gpl);
+       
+       /* draw header */
+       {
+               uiBlockSetEmboss(block, UI_EMBOSSN);
+               
+               /* rounded header */
+               if (active) uiBlockSetCol(block, TH_BUT_ACTION);
+                       rb_col= (active)?-20:20;
+                       uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, ""); 
+               if (active) uiBlockSetCol(block, TH_AUTO);
+               
+               /* lock toggle */
+               uiDefIconButBitI(block, ICONTOG, GP_LAYER_LOCKED, B_REDR, ICON_UNLOCKED,        *xco-7, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Layer cannot be modified");
+       }
+       
+       /* when layer is locked or hidden, only draw header */
+       if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) {
+               char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
+               
+               height= 26;
+               
+               /* visibility button (only if hidden but not locked!) */
+               if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
+                       uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
+               
+               /* name */
+               if (gpl->flag & GP_LAYER_HIDE)
+                       sprintf(name, "%s (Hidden)", gpl->info);
+               else
+                       sprintf(name, "%s (Locked)", gpl->info);
+               uiDefBut(block, LABEL, 1, name, *xco+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "Short description of what this layer is for (optional)");
+                       
+               uiBlockSetEmboss(block, UI_EMBOSS);
+       }
+       else {
+               height= 100;
+               
+               /* draw rest of header */
+               {
+                       /* visibility button */
+                       uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
+                       
+                       uiBlockSetEmboss(block, UI_EMBOSS);
+                       
+                       /* name */
+                       but= uiDefButC(block, TEX, B_REDR, "Info:",     *xco+36, *yco, 240, 19, gpl->info, 0, 127, 0, 0, "Short description of what this layer is for (optional)");
+                       uiButSetFunc(but, gp_ui_renamelayer_cb, gpd, gpl);
+                       
+                       /* delete 'button' */
+                       uiBlockSetEmboss(block, UI_EMBOSSN);
+                       
+                       but= uiDefIconBut(block, BUT, B_REDR, ICON_X, *xco+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
+                       uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
+                       
+                       uiBlockSetEmboss(block, UI_EMBOSS);
+               }
+               
+               /* draw backdrop */
+               if (active) uiBlockSetCol(block, TH_BUT_ACTION);
+                       uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
+               if (active) uiBlockSetCol(block, TH_AUTO);
+               
+               /* draw settings */
+               {
+                       /* color */
+                       uiBlockBeginAlign(block);
+                               uiDefButF(block, COL, B_REDR, "",               *xco, *yco-26, 150, 19, gpl->color, 0, 0, 0, 0, "Color to use for all strokes on this Grease Pencil Layer");
+                               uiDefButF(block, NUMSLI, B_REDR, "Opacity: ",           *xco,*yco-45,150,19, &gpl->color[3], 0.3, 1.0, 0, 0, "Visibility of stroke (0.3 to 1.0)");
+                       uiBlockEndAlign(block);
+                       
+                       /* stroke thickness */
+                       uiDefButS(block, NUMSLI, B_REDR, "Thickness:",  *xco, *yco-75, 150, 20, &gpl->thickness, 1, 10, 0, 0, "Thickness of strokes (in pixels)");
+                       
+                       
+                       /* onion-skinning */
+                       uiBlockBeginAlign(block);
+                               uiDefButBitI(block, TOG, GP_LAYER_ONIONSKIN, B_REDR, "Onion-Skin", *xco+160, *yco-26, 140, 20, &gpl->flag, 0, 0, 0, 0, "Ghost frames on either side of frame");
+                               uiDefButS(block, NUMSLI, B_REDR, "GStep:",      *xco+160, *yco-46, 140, 20, &gpl->gstep, 0, 120, 0, 0, "Max number of frames on either side of active frame to show (0 = just 'first' available sketch on either side)");
+                       uiBlockEndAlign(block);
+                       
+                       /* options */
+                       uiBlockBeginAlign(block);
+                               but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)");
+                               uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl);
+                               
+                               but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)");
+                               uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl);
+                       uiBlockEndAlign(block);
+                       
+                       //uiDefButBitI(block, TOG, GP_LAYER_DRAWDEBUG, B_REDR, "Show Points", *xco+160, *yco-75, 130, 20, &gpl->flag, 0, 0, 0, 0, "Show points which form the strokes");
+               }
+       }
+       
+       /* adjust height for new to start */
+       (*yco) -= (height + 27); 
+} 
+
+/* Draw the contents for a grease-pencil panel. This assumes several things:
+ *     - that panel has been created, is 318 x 204. max yco is 225
+ *     - that a toggle for turning on/off gpencil drawing is 150 x 20, starting from (10,225)
+ *             which is basically the top left-hand corner
+ * It will return the amount of extra space to extend the panel by
+ */
+short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa)
+{
+       uiBut *but;
+       bGPDlayer *gpl;
+       short xco= 10, yco= 170;
+       
+       /* draw gpd settings first */
+       {
+               /* add new layer buttons */
+               but= uiDefBut(block, BUT, B_REDR, "Add New Layer", 10,205,150,20, 0, 0, 0, 0, 0, "Adds a new Grease Pencil Layer");
+               uiButSetFunc(but, gp_ui_addlayer_cb, gpd, NULL);
+               
+               
+               /* show override lmb-clicks button + painting lock */
+               uiBlockBeginAlign(block);
+                       uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 130, 20, &gpd->flag, 0, 0, 0, 0, "Interpret LMB-click as new strokes (same as holding Shift-Key per stroke)");
+                       
+                       uiBlockSetCol(block, TH_BUT_SETTING);
+                               uiDefIconButBitI(block, ICONTOG, GP_DATA_LMBPLOCK, B_REDR, ICON_UNLOCKED,       300, 225, 20, 20, &gpd->flag, 0.0, 0.0, 0, 0, "Painting cannot occur with Shift-LMB (when making selections)");
+                       uiBlockSetCol(block, TH_AUTO);
+               uiBlockEndAlign(block);
+               
+               /* 'view align' button (naming depends on context) */
+               if (sa->spacetype == SPACE_VIEW3D)
+                       uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Sketch in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space");
+               else if (sa->spacetype != SPACE_SEQ) /* not available for sequencer yet */
+                       uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Stick to View", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added on 2d-canvas");
+       }
+       
+       /* draw for each layer */
+       for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+               gp_drawui_layer(block, gpd, gpl, &xco, &yco);
+       }
+       
+       /* return new height if necessary */
+       return (yco < 0) ? (204 - yco) : 204;
+}      
+
+/* ************************************************** */
+/* GREASE PENCIL DRAWING */
+
+/* flags for sflag */
+enum {
+       GP_DRAWDATA_NOSTATUS    = (1<<0),       /* don't draw status info */
+       GP_DRAWDATA_ONLY3D              = (1<<1),       /* only draw 3d-strokes */
+       GP_DRAWDATA_ONLYV2D             = (1<<2),       /* only draw 'canvas' strokes */
+};
+
+/* draw a given stroke */
+static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy)
+{
+       bGPDspoint *pt;
+       int i;
+       
+       /* error checking */
+       if ((points == NULL) || (totpoints <= 0))
+               return;
+       
+       /* check if stroke can be drawn */
+       if ((dflag & GP_DRAWDATA_ONLY3D) && !(sflag & GP_STROKE_3DSPACE))
+               return;
+       if (!(dflag & GP_DRAWDATA_ONLY3D) && (sflag & GP_STROKE_3DSPACE))
+               return;
+       if ((dflag & GP_DRAWDATA_ONLYV2D) && !(sflag & GP_STROKE_2DSPACE))
+               return;
+       if (!(dflag & GP_DRAWDATA_ONLYV2D) && (sflag & GP_STROKE_2DSPACE))
+               return;
+       
+       /* if drawing a single point, draw it larger */
+       if (totpoints == 1) {           
+               /* draw point */
+               if (sflag & GP_STROKE_3DSPACE) {
+                       glBegin(GL_POINTS);
+                               glVertex3f(points->x, points->y, points->z);
+                       glEnd();
+               }
+               else if (sflag & GP_STROKE_2DSPACE) {
+                       glBegin(GL_POINTS);
+                               glVertex2f(points->x, points->y);
+                       glEnd();
+               }
+               else {
+                       const float x= (points->x / 1000 * winx);
+                       const float y= (points->y / 1000 * winy);
+                       
+                       glBegin(GL_POINTS);
+                               glVertex2f(x, y);
+                       glEnd();
+               }
+       }
+       else {
+               float oldpressure = 0.0f;
+               
+               /* draw stroke curve */
+               glBegin(GL_LINE_STRIP);
+               for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
+                       float x, y, z;
+                       
+                       if (sflag & GP_STROKE_3DSPACE) {
+                               x= pt->x;
+                               y= pt->y;
+                               z= pt->z;
+                       }
+                       else if (sflag & GP_STROKE_2DSPACE) {
+                               x= pt->x;
+                               y= pt->y;
+                               z= 0;
+                       }
+                       else {
+                               x= (pt->x / 1000 * winx);
+                               y= (pt->y / 1000 * winy);
+                               z= 0;
+                       }
+                       
+                       if (fabs(pt->pressure - oldpressure) > 0.2f) {
+                               glEnd();
+                               glLineWidth(pt->pressure * thickness);
+                               glBegin(GL_LINE_STRIP);
+                               
+                               if (sflag & GP_STROKE_3DSPACE) 
+                                       glVertex3f(x, y, z);
+                               else
+                                       glVertex2f(x, y);
+                               
+                               oldpressure = pt->pressure;
+                       }
+                       else {
+                               if (sflag & GP_STROKE_3DSPACE) 
+                                       glVertex3f(x, y, z);
+                               else
+                                       glVertex2f(x, y);
+                       }
+               }
+               glEnd();
+               
+               /* draw debug points of curve on top? */
+               if (debug) {
+                       glBegin(GL_POINTS);
+                       for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
+                               if (sflag & GP_STROKE_3DSPACE) {
+                                       glVertex3f(pt->x, pt->y, pt->z);
+                               }
+                               else if (sflag & GP_STROKE_2DSPACE) {
+                                       glVertex2f(pt->x, pt->y);
+                               }
+                               else {
+                                       const float x= (pt->x / 1000 * winx);
+                                       const float y= (pt->y / 1000 * winy);
+                                       
+                                       glVertex2f(x, y);
+                               }
+                       }
+                       glEnd();
+               }
+       }
+}
+
+/* draw a set of strokes */
+static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, short debug, 
+                                                        short lthick, float color[4])
+{
+       bGPDstroke *gps;
+       
+       /* set color first (may need to reset it again later too) */
+       glColor4f(color[0], color[1], color[2], color[3]);
+       
+       for (gps= gpf->strokes.first; gps; gps= gps->next) {    
+               /* handle 'eraser' strokes differently */
+               if (gps->flag & GP_STROKE_ERASER) {
+                       // FIXME: this method is a failed experiment
+#if 0
+                       /* draw stroke twice, first time with 'white' to set a mask to invert
+                        * contents of framebuffer, then second-time the same again but to restore
+                        * the contents
+                        */
+                       glEnable(GL_COLOR_LOGIC_OP); 
+                       glLogicOp(GL_XOR);
+                       
+                       glColor4f(1, 1, 1, 1); /* white */
+                       
+                       gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, 0, winx, winy);
+                       gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, 0, winx, winy);
+                       
+                       glDisable(GL_COLOR_LOGIC_OP);
+                       
+                       /* reset color for drawing next stroke */
+                       glColor4f(color[0], color[1], color[2], color[3]);
+#endif
+               }
+               else {
+                       /* just draw the stroke once */
+                       gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
+               }
+       }
+}
+
+/* draw grease-pencil datablock */
+static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
+{
+       bGPDlayer *gpl, *actlay=NULL;
+       
+       /* turn on smooth lines (i.e. anti-aliasing) */
+       glEnable(GL_LINE_SMOOTH);
+       
+       /* turn on alpha-blending */
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glEnable(GL_BLEND);
+               
+       /* loop over layers, drawing them */
+       for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+               bGPDframe *gpf;
+               
+               short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0;
+               short lthick= gpl->thickness;
+               float color[4], tcolor[4];
+               
+               /* don't draw layer if hidden */
+               if (gpl->flag & GP_LAYER_HIDE) 
+                       continue;
+               
+               /* if layer is active one, store pointer to it */
+               if (gpl->flag & GP_LAYER_ACTIVE)
+                       actlay= gpl;
+               
+               /* get frame to draw */
+               gpf= gpencil_layer_getframe(gpl, CFRA, 0);
+               if (gpf == NULL) 
+                       continue;
+               
+               /* set color, stroke thickness, and point size */
+               glLineWidth(lthick);
+               QUATCOPY(color, gpl->color); // just for copying 4 array elements
+               QUATCOPY(tcolor, gpl->color); // additional copy of color (for ghosting)
+               glColor4f(color[0], color[1], color[2], color[3]);
+               glPointSize(gpl->thickness + 2);
+               
+               /* draw 'onionskins' (frame left + right) */
+               if (gpl->flag & GP_LAYER_ONIONSKIN) {
+                       /* drawing method - only immediately surrounding (gstep = 0), or within a frame range on either side (gstep > 0)*/                      
+                       if (gpl->gstep) {
+                               bGPDframe *gf;
+                               short i;
+                               
+                               /* draw previous frames first */
+                               for (gf=gpf->prev, i=0; gf; gf=gf->prev, i++) {
+                                       /* check if frame is drawable */
+                                       if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
+                                               /* alpha decreases with distance from curframe index */
+                                               tcolor[3] = color[3] - (i * 0.7);
+                                               gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor);
+                                       }
+                                       else 
+                                               break;
+                               }
+                               
+                               /* now draw next frames */
+                               for (gf= gpf->next, i=0; gf; gf=gf->next, i++) {
+                                       /* check if frame is drawable */
+                                       if ((gf->framenum - gpf->framenum) <= gpl->gstep) {
+                                               /* alpha decreases with distance from curframe index */
+                                               tcolor[3] = color[3] - (i * 0.7);
+                                               gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor);
+                                       }
+                                       else 
+                                               break;
+                               }       
+                               
+                               /* restore alpha */
+                               glColor4f(color[0], color[1], color[2], color[3]);
+                       }
+                       else {
+                               /* draw the strokes for the ghost frames (at half of the alpha set by user) */
+                               if (gpf->prev) {
+                                       tcolor[3] = (color[3] / 7);
+                                       gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor);
+                               }
+                               
+                               if (gpf->next) {
+                                       tcolor[3] = (color[3] / 4);
+                                       gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor);
+                               }
+                               
+                               /* restore alpha */
+                               glColor4f(color[0], color[1], color[2], color[3]);
+                       }
+               }
+               
+               /* draw the strokes already in active frame */
+               tcolor[3]= color[3];
+               gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor);
+               
+               /* Check if may need to draw the active stroke cache, only if this layer is the active layer
+                * that is being edited. (Stroke cache is currently stored in gp-data)
+                */
+               if ((G.f & G_GREASEPENCIL) && (gpl->flag & GP_LAYER_ACTIVE) &&
+                       (gpf->flag & GP_FRAME_PAINT)) 
+               {
+                       /* Buffer stroke needs to be drawn with a different linestyle to help differentiate them from normal strokes. */
+                       setlinestyle(2);
+                       gp_draw_stroke(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, debug, winx, winy);
+                       setlinestyle(0);
+               }
+       }
+       
+       /* turn off alpha blending, then smooth lines */
+       glDisable(GL_BLEND); // alpha blending
+       glDisable(GL_LINE_SMOOTH); // smooth lines
+       
+       /* show info for debugging the status of gpencil */
+       if ( ((dflag & GP_DRAWDATA_NOSTATUS)==0) && (gpd->flag & GP_DATA_DISPINFO) ) {
+               char printable[256];
+               short xmax;
+               
+               /* get text to display */
+               if (actlay) {
+                       if (gpd->flag & GP_DATA_EDITPAINT)
+                               BIF_ThemeColor(TH_BONE_POSE); // should be blue-ish
+                       else if (actlay->actframe == NULL)
+                               BIF_ThemeColor(TH_REDALERT);
+                       else if (actlay->actframe->framenum == CFRA)
+                               BIF_ThemeColor(TH_VERTEX_SELECT); // should be yellow
+                       else
+                               BIF_ThemeColor(TH_TEXT_HI);
+                       
+                       if (actlay->actframe) {
+                               sprintf(printable, "GPencil: Layer ('%s'), Frame (%d) %s", 
+                                       actlay->info, actlay->actframe->framenum,
+                                       ((gpd->flag & GP_DATA_EDITPAINT)?", Draw Mode On":"") );
+                       }
+                       else {
+                               sprintf(printable, "GPencil: Layer ('%s'), Frame <None> %s", 
+                                       actlay->info, ((gpd->flag & GP_DATA_EDITPAINT)?", Draw Mode On":"") );
+                       }
+               }
+               else {
+                       BIF_ThemeColor(TH_REDALERT);
+                       sprintf(printable, "GPencil: Layer <None>");
+               }
+               xmax= GetButStringLength(printable);
+               
+               /* only draw it if view is wide enough (assume padding of 20 is enough for now) */
+               if (winx > (xmax + 20)) { 
+                       glRasterPos2i(winx-xmax, winy-20);
+                       BMF_DrawString(G.fonts, printable);
+               }
+       }
+       
+       /* restore initial gl conditions */
+       glLineWidth(1.0);
+       glPointSize(1.0);
+       glColor4f(0, 0, 0, 1);
+}
+
+/* ----------- */
+
+/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly 
+ * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes, second time with onlyv2d=0 for screen-aligned strokes
+ */
+void draw_gpencil_2dview (ScrArea *sa, short onlyv2d)
+{
+       bGPdata *gpd;
+       int dflag = 0;
+       
+       /* check that we have grease-pencil stuff to draw */
+       if (sa == NULL) return;
+       gpd= gpencil_data_getactive(sa);
+       if (gpd == NULL) return;
+       
+       /* draw it! */
+       if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D|GP_DRAWDATA_NOSTATUS);
+       gp_draw_data(gpd, sa->winx, sa->winy, dflag);
+}
+
+/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly 
+ * Note: this gets called twice - first time with only3d=1 to draw 3d-strokes, second time with only3d=0 for screen-aligned strokes
+ */
+void draw_gpencil_3dview (ScrArea *sa, short only3d)
+{
+       bGPdata *gpd;
+       int dflag = 0;
+       
+       /* check that we have grease-pencil stuff to draw */
+       gpd= gpencil_data_getactive(sa);
+       if (gpd == NULL) return;
+       
+       /* draw it! */
+       if (only3d) dflag |= (GP_DRAWDATA_ONLY3D|GP_DRAWDATA_NOSTATUS);
+       gp_draw_data(gpd, sa->winx, sa->winy, dflag);
+}
+
+/* draw grease-pencil sketches to opengl render window assuming that matrices are already set correctly */
+void draw_gpencil_oglrender (View3D *v3d, int winx, int winy)
+{
+       bGPdata *gpd;
+       
+       /* assume gpencil data comes from v3d */
+       if (v3d == NULL) return;
+       gpd= v3d->gpd;
+       if (gpd == NULL) return;
+       
+       /* pass 1: draw 3d-strokes ------------ > */
+       gp_draw_data(gpd, winx, winy, (GP_DRAWDATA_NOSTATUS|GP_DRAWDATA_ONLY3D));
+       
+       /* pass 2: draw 2d-strokes ------------ > */
+               /* adjust view matrices */
+       myortho2(-0.375, (float)(winx)-0.375, -0.375, (float)(winy)-0.375);
+       glLoadIdentity();
+       
+               /* draw it! */
+       gp_draw_data(gpd, winx, winy, GP_DRAWDATA_NOSTATUS);
+}
+
+/* ************************************************** */
index 1169062fdd05da18e27a2018abf03f2233fec91e..853df3bedfcb380571023360668720562f5e71c5 100644 (file)
@@ -37,6 +37,7 @@
 #include "DNA_action_types.h"
 #include "DNA_color_types.h"
 #include "DNA_customdata_types.h"
+#include "DNA_gpencil_types.h"
 #include "DNA_ipo_types.h"
 #include "DNA_ID.h"
 #include "DNA_image_types.h"
 #include "CMP_node.h"
 #include "SHD_node.h"
 
+#include "BDR_gpencil.h"
+
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
+#include "BIF_drawgpencil.h"
 #include "BIF_interface.h"
 #include "BIF_interface_icons.h"
 #include "BIF_language.h"
@@ -3300,6 +3304,66 @@ static void node_draw_group(ScrArea *sa, SpaceNode *snode, bNode *gnode)
 }
 
 
+
+static void nodes_panel_gpencil(short cntrl)   // NODES_HANDLER_GREASEPENCIL
+{
+       uiBlock *block;
+       SpaceNode *snode;
+       
+       snode= curarea->spacedata.first;
+
+       block= uiNewBlock(&curarea->uiblocks, "nodes_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win);
+       uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
+       uiSetPanelHandler(NODES_HANDLER_GREASEPENCIL);  // for close and esc
+       if (uiNewPanel(curarea, block, "Grease Pencil", "SpaceNode", 100, 30, 318, 204)==0) return;
+       
+       /* we can only really draw stuff if there are nodes (otherwise no events are handled */
+       if (snode->nodetree == NULL)
+               return;
+       
+       /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
+       if (snode->flag & SNODE_DISPGP) {
+               if (snode->gpd == NULL)
+                       gpencil_data_setactive(curarea, gpencil_data_addnew());
+       }
+       
+       if (snode->flag & SNODE_DISPGP) {
+               bGPdata *gpd= snode->gpd;
+               short newheight;
+               
+               /* this is a variable height panel, newpanel doesnt force new size on existing panels */
+               /* so first we make it default height */
+               uiNewPanelHeight(block, 204);
+               
+               /* draw button for showing gpencil settings and drawings */
+               uiDefButBitS(block, TOG, SNODE_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &snode->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Node Editor (draw using Shift-LMB)");
+               
+               /* extend the panel if the contents won't fit */
+               newheight= draw_gpencil_panel(block, gpd, curarea); 
+               uiNewPanelHeight(block, newheight);
+       }
+       else {
+               uiDefButBitS(block, TOG, SNODE_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &snode->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Node Editor");
+               uiDefBut(block, LABEL, 1, " ",  160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
+       }
+}
+
+static void nodes_blockhandlers(ScrArea *sa)
+{
+       SpaceNode *snode= sa->spacedata.first;
+       short a;
+       
+       for(a=0; a<SPACE_MAXHANDLER; a+=2) {
+               /* clear action value for event */
+               switch(snode->blockhandler[a]) {
+                       case NODES_HANDLER_GREASEPENCIL:
+                               nodes_panel_gpencil(snode->blockhandler[a+1]);
+                               break;
+               }
+       }
+       uiDrawBlocksPanels(sa, 0);
+}
+
 void drawnodespace(ScrArea *sa, void *spacedata)
 {
        SpaceNode *snode= sa->spacedata.first;
@@ -3354,13 +3418,26 @@ void drawnodespace(ScrArea *sa, void *spacedata)
                }
        }
        
+       /* draw grease-pencil ('canvas' strokes) */
+       if ((snode->flag & SNODE_DISPGP) && (snode->nodetree))
+               draw_gpencil_2dview(sa, 1);
+       
        /* restore viewport (not needed yet) */
        mywinset(sa->win);
 
        /* ortho at pixel level curarea */
        myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
+       
+       /* draw grease-pencil (screen strokes) */
+       if ((snode->flag & SNODE_DISPGP) && (snode->nodetree))
+               draw_gpencil_2dview(sa, 0);
 
        draw_area_emboss(sa);
+       
+       /* it is important to end a view in a transform compatible with buttons */
+       bwin_scalematrix(sa->win, snode->blockscale, snode->blockscale, snode->blockscale);
+       nodes_blockhandlers(sa);
+       
        curarea->win_swap= WIN_BACK_OK;
        
        /* in the end, this is a delayed previewrender test, to allow buttons to be first */
index 045bf292446225718cd1e6bad03250c3d716d32c..1a469e8b3660b29e2e6b22008a13e6f6efb94ebb 100644 (file)
@@ -1199,7 +1199,12 @@ static void drawlattice(Object *ob)
        int use_wcol= 0;
 
        lt= (ob==G.obedit)?editLatt:ob->data;
+       
+       /* now we default make displist, this will modifiers work for non animated case */
+       if(ob->disp.first==NULL)
+               lattice_calc_modifiers(ob);
        dl= find_displist(&ob->disp, DL_VERTS);
+       
        if(ob==G.obedit) {
                cpack(0x004000);
                
index e554b91dd52a03bb400bdb845ebf57b3c16313b0..cc431c73a2ec45a97780062bc191475d3596e25a 100644 (file)
@@ -43,6 +43,7 @@
 
 #include "IMB_imbuf_types.h"
 
+#include "DNA_gpencil_types.h"
 #include "DNA_sequence_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
@@ -67,6 +68,9 @@
 #include "BIF_space.h"
 #include "BIF_interface.h"
 
+#include "BIF_drawgpencil.h"
+#include "BDR_gpencil.h"
+
 #include "BSE_view.h"
 #include "BSE_drawipo.h"
 #include "BSE_sequence.h"
@@ -98,6 +102,70 @@ static void draw_seq_text(Sequence *seq, float x1, float x2, float y1, float y2)
 static void draw_shadedstrip(Sequence *seq, char *col, float x1, float y1, float x2, float y2);
 static void draw_seq_strip(struct Sequence *seq, struct ScrArea *sa, struct SpaceSeq *sseq, int outline_tint, float pixelx);
 
+
+static void seq_panel_gpencil(short cntrl)     // SEQ_HANDLER_GREASEPENCIL
+{
+       uiBlock *block;
+       SpaceSeq *sseq;
+       
+       sseq= curarea->spacedata.first;
+
+       block= uiNewBlock(&curarea->uiblocks, "seq_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win);
+       uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
+       uiSetPanelHandler(SEQ_HANDLER_GREASEPENCIL);  // for close and esc
+       if (uiNewPanel(curarea, block, "Grease Pencil", "SpaceSeq", 100, 30, 318, 204)==0) return;
+       
+       /* only draw settings if right mode */
+       if (sseq->mainb == 0)
+               return;
+       
+       /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
+       if (sseq->flag & SEQ_DRAW_GPENCIL) {
+               if (sseq->gpd == NULL)
+                       gpencil_data_setactive(curarea, gpencil_data_addnew());
+       }
+       
+       if (sseq->flag & SEQ_DRAW_GPENCIL) {
+               bGPdata *gpd= sseq->gpd;
+               short newheight;
+               
+               /* this is a variable height panel, newpanel doesnt force new size on existing panels */
+               /* so first we make it default height */
+               uiNewPanelHeight(block, 204);
+               
+               /* draw button for showing gpencil settings and drawings */
+               uiDefButBitI(block, TOG, SEQ_DRAW_GPENCIL, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sseq->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Sequencer View (draw using Shift-LMB)");
+               
+               /* extend the panel if the contents won't fit */
+               newheight= draw_gpencil_panel(block, gpd, curarea); 
+               uiNewPanelHeight(block, newheight);
+       }
+       else {
+               uiDefButBitI(block, TOG, SEQ_DRAW_GPENCIL, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sseq->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Sequencer View");
+               uiDefBut(block, LABEL, 1, " ",  160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
+       }
+}
+
+static void seq_blockhandlers(ScrArea *sa)
+{
+       SpaceSeq *sseq= sa->spacedata.first;
+       short a;
+
+       /* warning; blocks need to be freed each time, handlers dont remove (for ipo moved to drawipospace) */
+       uiFreeBlocksWin(&sa->uiblocks, sa->win);
+
+       for(a=0; a<SPACE_MAXHANDLER; a+=2) {
+               switch(sseq->blockhandler[a]) {
+                       case SEQ_HANDLER_GREASEPENCIL:
+                               seq_panel_gpencil(sseq->blockhandler[a+1]);
+                               break;
+               }
+       }
+       uiDrawBlocksPanels(sa, 0);
+
+}
+
+
 static void draw_cfra_seq(void)
 {
        glColor3ub(0x30, 0x90, 0x50);
@@ -907,6 +975,17 @@ static void draw_image_seq(ScrArea *sa)
        if (free_ibuf) {
                IMB_freeImBuf(ibuf);
        } 
+       
+       /* draw grease-pencil (screen aligned) */
+       if (sseq->flag & SEQ_DRAW_GPENCIL)
+               draw_gpencil_2dview(sa, 0);
+       
+       /* ortho at pixel level sa */
+       myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
+       
+       /* it is important to end a view in a transform compatible with buttons */
+       bwin_scalematrix(sa->win, sseq->blockscale, sseq->blockscale, sseq->blockscale);
+       seq_blockhandlers(sa);
 
        sa->win_swap= WIN_BACK_OK;
 }
@@ -1023,24 +1102,6 @@ void seq_viewmove(SpaceSeq *sseq)
        window_set_cursor(win, oldcursor);
 }
 
-
-
-static void seq_blockhandlers(ScrArea *sa)
-{
-       SpaceSeq *sseq= sa->spacedata.first;
-       short a;
-
-       /* warning; blocks need to be freed each time, handlers dont remove (for ipo moved to drawipospace) */
-       uiFreeBlocksWin(&sa->uiblocks, sa->win);
-
-       for(a=0; a<SPACE_MAXHANDLER; a+=2) {
-               /* clear action value for event */
-               sseq->blockhandler[a+1]= 0;
-       }
-       uiDrawBlocksPanels(sa, 0);
-
-}
-
 void drawprefetchseqspace(ScrArea *sa, void *spacedata)
 {
        SpaceSeq *sseq= sa->spacedata.first;
index f595a101f63e3484a069430faa44f09bf2de62f8..8c7c78de83735b584930676475cbd1678f7baef1 100644 (file)
@@ -61,6 +61,7 @@
 #include "DNA_constraint_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_group_types.h"
+#include "DNA_gpencil_types.h"
 #include "DNA_image_types.h"
 #include "DNA_key_types.h"
 #include "DNA_lattice_types.h"
 
 #include "BIF_butspace.h"
 #include "BIF_drawimage.h"
+#include "BIF_drawgpencil.h"
 #include "BIF_editgroup.h"
 #include "BIF_editarmature.h"
 #include "BIF_editmesh.h"
 #include "BDR_editobject.h"
 #include "BDR_vpaint.h"
 #include "BDR_sculptmode.h"
+#include "BDR_gpencil.h"
 
 #include "BSE_drawview.h"
 #include "BSE_filesel.h"
@@ -1499,44 +1502,52 @@ static void draw_view_icon(void)
        glDisable(GL_BLEND);
 }
 
-static void draw_viewport_name(ScrArea *sa)
+char *view3d_get_name(View3D *v3d)
 {
        char *name = NULL;
-       char *printable = NULL;
        
-       switch(G.vd->view) {
+       switch (v3d->view) {
                case 1:
-                       if (G.vd->persp == V3D_ORTHO)
-                               name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Ortho" : "Front Ortho";
+                       if (v3d->persp == V3D_ORTHO)
+                               name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Ortho" : "Front Ortho";
                        else
-                               name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Persp" : "Front Persp";
+                               name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Back Persp" : "Front Persp";
                        break;
                case 3:
-                       if (G.vd->persp == V3D_ORTHO)
-                               name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Ortho" : "Right Ortho";
+                       if (v3d->persp == V3D_ORTHO)
+                               name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Ortho" : "Right Ortho";
                        else
-                               name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Persp" : "Right Persp";
+                               name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Left Persp" : "Right Persp";
                        break;
                case 7:
-                       if (G.vd->persp == V3D_ORTHO)
-                               name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Ortho" : "Top Ortho";
+                       if (v3d->persp == V3D_ORTHO)
+                               name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Ortho" : "Top Ortho";
                        else
-                               name = (G.vd->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Persp" : "Top Persp";
+                               name = (v3d->flag2 & V3D_OPP_DIRECTION_NAME) ? "Bottom Persp" : "Top Persp";
                        break;
                default:
-                       if (G.vd->persp==V3D_CAMOB) {
-                               if ((G.vd->camera) && (G.vd->camera->type == OB_CAMERA)) {
+                       if (v3d->persp==V3D_CAMOB) {
+                               if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
                                        Camera *cam;
-                                       cam = G.vd->camera->data;
+                                       cam = v3d->camera->data;
                                        name = (cam->type != CAM_ORTHO) ? "Camera Persp" : "Camera Ortho";
                                } else {
                                        name = "Object as Camera";
                                }
                        } else { 
-                               name = (G.vd->persp == V3D_ORTHO) ? "User Ortho" : "User Persp";
+                               name = (v3d->persp == V3D_ORTHO) ? "User Ortho" : "User Persp";
                        }
+                       break;
        }
        
+       return name;
+}
+
+static void draw_viewport_name(ScrArea *sa)
+{
+       char *name = view3d_get_name(sa->spacedata.first);
+       char *printable = NULL;
+       
        if (G.vd->localview) {
                printable = malloc(strlen(name) + strlen(" (Local)_")); /* '_' gives space for '\0' */
                strcpy(printable, name);
@@ -2498,7 +2509,7 @@ static void view3d_panel_background(short cntrl)  // VIEW3D_HANDLER_BACKGROUND
        uiSetPanelHandler(VIEW3D_HANDLER_BACKGROUND);  // for close and esc
        if(uiNewPanel(curarea, block, "Background Image", "View3d", 340, 10, 318, 204)==0) return;
 
-       if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT || G.f & G_TEXTUREPAINT) {
+       if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT || G.f & G_TEXTUREPAINT || G.f & G_GREASEPENCIL) {
                uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER);    // force old style frontbuffer draw
        }
        
@@ -2546,7 +2557,7 @@ static void view3d_panel_properties(short cntrl)  // VIEW3D_HANDLER_SETTINGS
        /* to force height */
        uiNewPanelHeight(block, 264);
 
-       if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT)) {
+       if(G.f & (G_VERTEXPAINT|G_FACESELECT|G_TEXTUREPAINT|G_WEIGHTPAINT|G_GREASEPENCIL)) {
                uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER);    // force old style frontbuffer draw
        }
 
@@ -2620,6 +2631,49 @@ static void view3d_panel_preview(ScrArea *sa, short cntrl)       // VIEW3D_HANDLER_PRE
        }
 }
 
+static void view3d_panel_gpencil(short cntrl)  // VIEW3D_HANDLER_GREASEPENCIL
+{
+       uiBlock *block;
+       View3D *vd;
+       
+       vd= G.vd;
+
+       block= uiNewBlock(&curarea->uiblocks, "view3d_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win);
+       uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
+       uiSetPanelHandler(VIEW3D_HANDLER_GREASEPENCIL);  // for close and esc
+       if (uiNewPanel(curarea, block, "Grease Pencil", "View3d", 100, 30, 318, 204)==0) return;
+
+       if (G.f & (G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT|G_GREASEPENCIL)) {
+               uiBlockSetFlag(block, UI_BLOCK_FRONTBUFFER);    // force old style frontbuffer draw
+       }
+       
+       /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
+       if (vd->flag2 & V3D_DISPGP) {
+               if (vd->gpd == NULL)
+                       gpencil_data_setactive(curarea, gpencil_data_addnew());
+       }
+       
+       if (vd->flag2 & V3D_DISPGP) {
+               bGPdata *gpd= vd->gpd;
+               short newheight;
+               
+               /* this is a variable height panel, newpanel doesnt force new size on existing panels */
+               /* so first we make it default height */
+               uiNewPanelHeight(block, 204);
+               
+               /* draw button for showing gpencil settings and drawings */
+               uiDefButBitS(block, TOG, V3D_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &vd->flag2, 0, 0, 0, 0, "Display freehand annotations overlay over this 3D View (draw using Shift-LMB)");
+               
+               /* extend the panel if the contents won't fit */
+               newheight= draw_gpencil_panel(block, gpd, curarea); 
+               uiNewPanelHeight(block, newheight);
+       }
+       else {
+               uiDefButBitS(block, TOG, V3D_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &vd->flag2, 0, 0, 0, 0, "Display freehand annotations overlay over this 3D View");
+               uiDefBut(block, LABEL, 1, " ",  160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
+       }
+}
+
 
 static void view3d_blockhandlers(ScrArea *sa)
 {
@@ -2634,9 +2688,7 @@ static void view3d_blockhandlers(ScrArea *sa)
        glDisable(GL_DEPTH_TEST); 
        
        for(a=0; a<SPACE_MAXHANDLER; a+=2) {
-       
                switch(v3d->blockhandler[a]) {
-
                case VIEW3D_HANDLER_PROPERTIES:
                        view3d_panel_properties(v3d->blockhandler[a+1]);
                        break;
@@ -2651,7 +2703,10 @@ static void view3d_blockhandlers(ScrArea *sa)
                        break;                  
                case VIEW3D_HANDLER_TRANSFORM:
                        view3d_panel_transform_spaces(v3d->blockhandler[a+1]);
-                       break;                  
+                       break;
+               case VIEW3D_HANDLER_GREASEPENCIL:
+                       view3d_panel_gpencil(v3d->blockhandler[a+1]);
+                       break;
                }
                /* clear action value for event */
                v3d->blockhandler[a+1]= 0;
@@ -3169,7 +3224,11 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
                v3d->zbuf= FALSE;
                glDisable(GL_DEPTH_TEST);
        }
-
+       
+       /* draw grease-pencil stuff */
+       if (v3d->flag2 & V3D_DISPGP)
+               draw_gpencil_3dview(sa, 1);
+       
        persp(PERSP_WIN);  // set ortho
 
        /* Draw Sculpt Mode brush */
@@ -3211,6 +3270,11 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
 
        if(v3d->persp>1) drawviewborder();
        if(v3d->flag2 & V3D_FLYMODE) drawviewborder_flymode();
+       
+       /* draw grease-pencil stuff */
+       if (v3d->flag2 & V3D_DISPGP)
+               draw_gpencil_3dview(sa, 0);
+       
        if(!(G.f & G_PLAYANIM)) drawcursor(v3d);
        if(U.uiflag & USER_SHOW_ROTVIEWICON)
                draw_view_axis();
@@ -3311,16 +3375,15 @@ void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]
 
        /* first draw set */
        if(G.scene->set) {
-       
                for(SETLOOPER(G.scene->set, base)) {
                        if(v3d->lay & base->lay) {
                                if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
                                else {
                                        where_is_object(base->object);
-       
+                                       
                                        BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
                                        draw_object(base, DRAW_CONSTCOLOR|DRAW_SCENESET);
-       
+                                       
                                        if(base->object->transflag & OB_DUPLI) {
                                                draw_dupli_objects(v3d, base);
                                        }
@@ -3377,6 +3440,13 @@ void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]
                glDisable(GL_DEPTH_TEST);
        }
        
+       if(v3d->gpd) {
+               /* draw grease-pencil overlays 
+                * WARNING: view matrices are altered here!
+                */
+               draw_gpencil_oglrender(v3d, winx, winy);
+       }
+       
        G.f &= ~G_SIMULATION;
 
        glFlush();
index 4cc0e52ce3f757a85ba8a39ac921310bf66c8157..c454715b1df3115b2ea57f0c8a20c0dd3ce92a7b 100644 (file)
@@ -52,6 +52,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_nla_types.h"
 #include "DNA_lattice_types.h"
+#include "DNA_gpencil_types.h"
 
 #include "BKE_action.h"
 #include "BKE_armature.h"
@@ -90,6 +91,7 @@
 
 #include "BDR_drawaction.h"
 #include "BDR_editobject.h"
+#include "BDR_gpencil.h"
 
 #include "mydevice.h"
 #include "blendef.h"
@@ -296,6 +298,16 @@ bActListElem *make_new_actlistelem (void *data, short datatype, void *owner, sho
                                ale->datatype= ALE_IPO;
                        }
                                break;
+                       case ACTTYPE_GPLAYER:
+                       {
+                               bGPDlayer *gpl= (bGPDlayer *)data;
+                               
+                               ale->flag= gpl->flag;
+                               
+                               ale->key_data= NULL;
+                               ale->datatype= ALE_GPFRAME;
+                       }
+                               break;
                }
        }
        
@@ -505,6 +517,49 @@ static void actdata_filter_shapekey (ListBase *act_data, Key *key, int filter_mo
        }
 }
  
+
+static void actdata_filter_gpencil (ListBase *act_data, bScreen *sc, int filter_mode)
+{
+       bActListElem *ale;
+       ScrArea *sa;
+       bGPdata *gpd;
+       bGPDlayer *gpl;
+       
+       /* check if filtering types are appropriate */
+       if ( !(filter_mode & (ACTFILTER_IPOKEYS|ACTFILTER_ONLYICU|ACTFILTER_ACTGROUPED)) ) 
+       {
+               /* loop over spaces in current screen, finding gpd blocks (could be slow!) */
+               for (sa= sc->areabase.first; sa; sa= sa->next) {
+                       /* try to get gp data */
+                       gpd= gpencil_data_getactive(sa);
+                       if (gpd == NULL) continue;
+                       
+                       /* add gpd as channel too (if for drawing, and it has layers) */
+                       if ((filter_mode & ACTFILTER_FORDRAWING) && (gpd->layers.first)) {
+                               /* add to list */
+                               ale= make_new_actlistelem(gpd, ACTTYPE_GPDATABLOCK, sa, ACTTYPE_SPECIALDATA);
+                               if (ale) BLI_addtail(act_data, ale);
+                       }
+                       
+                       /* only add layers if they will be visible (if drawing channels) */
+                       if ( !(filter_mode & ACTFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) {
+                               /* loop over layers as the conditions are acceptable */
+                               for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+                                       /* only if selected */
+                                       if (!(filter_mode & ACTFILTER_SEL) || SEL_GPL(gpl)) {
+                                               /* only if editable */
+                                               if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
+                                                       /* add to list */
+                                                       ale= make_new_actlistelem(gpl, ACTTYPE_GPLAYER, gpd, ACTTYPE_GPDATABLOCK);
+                                                       if (ale) BLI_addtail(act_data, ale);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
 /* This function filters the active data source to leave only the desired
  * data types. 'Public' api call.
  *     *act_data: is a pointer to a ListBase, to which the filtered action data 
@@ -525,6 +580,9 @@ void actdata_filter (ListBase *act_data, int filter_mode, void *data, short data
                        case ACTCONT_SHAPEKEY:
                                actdata_filter_shapekey(act_data, data, filter_mode);
                                break;
+                       case ACTCONT_GPENCIL:
+                               actdata_filter_gpencil(act_data, data, filter_mode);
+                               break;
                }
                        
                /* remove any weedy entries */
@@ -599,11 +657,8 @@ int get_nearest_key_num (Key *key, short *mval, float *x)
     return (num + 1);
 }
 
-/* this function is used to get a pointer to an action or shapekey 
- * datablock, thus simplying that process.
- */
-/* this function is intended for use */
-void *get_nearest_act_channel (short mval[], short *ret_type)
+/* this function finds the channel that mouse is floating over */
+void *get_nearest_act_channel (short mval[], short *ret_type, void **owner)
 {
        ListBase act_data = {NULL, NULL};
        bActListElem *ale;
@@ -614,6 +669,9 @@ void *get_nearest_act_channel (short mval[], short *ret_type)
        int clickmin, clickmax;
        float x,y;
        
+       /* init 'owner' return val */
+       *owner= NULL;
+       
        /* determine what type of data we are operating on */
        data = get_action_context(&datatype);
        if (data == NULL) {
@@ -641,6 +699,7 @@ void *get_nearest_act_channel (short mval[], short *ret_type)
                        /* found match */
                        *ret_type= ale->type;
                        data= ale->data;
+                       *owner= ale->owner;
                        
                        BLI_freelistN(&act_data);
                        
@@ -743,6 +802,10 @@ static void *get_nearest_action_key (float *selx, short *sel, short *ret_type, b
                                bActionGroup *agrp= (bActionGroup *)ale->data;
                                agroup_to_keylist(agrp, &act_keys, NULL, NULL);
                        }
+                       else if (ale->type == ACTTYPE_GPLAYER) {
+                               bGPDlayer *gpl= (bGPDlayer *)ale->data;
+                               gpl_to_keylist(gpl, &act_keys, NULL, NULL);
+                       }
                        
                        /* loop through keyframes, finding one that was clicked on */
                        for (ak= act_keys.first; ak; ak= ak->next) {
@@ -766,6 +829,10 @@ static void *get_nearest_action_key (float *selx, short *sel, short *ret_type, b
                                data = ale->key_data;
                                *ret_type= ACTTYPE_ICU;
                        }
+                       else if (datatype == ACTCONT_GPENCIL) {
+                               data = ale->data;
+                               *ret_type= ACTTYPE_GPLAYER;
+                       }
                        
                        /* cleanup tempolary lists */
                        BLI_freelistN(&act_keys);
@@ -795,17 +862,40 @@ void *get_action_context (short *datatype)
        act = (G.saction)? G.saction->action: NULL;
        key = get_action_mesh_key();
        
-       if (act) {
-               *datatype= ACTCONT_ACTION;
-               return act;
-       }
-       else if (key) {
-               *datatype= ACTCONT_SHAPEKEY;
-               return key;
+       /* check mode selector */
+       if (G.saction) {
+               switch (G.saction->mode) {
+                       case SACTCONT_ACTION: 
+                               *datatype= ACTCONT_ACTION;
+                               return act;
+                               
+                       case SACTCONT_SHAPEKEY:
+                               *datatype= ACTCONT_SHAPEKEY;
+                               return key;
+                               
+                       case SACTCONT_GPENCIL:
+                               *datatype= ACTCONT_GPENCIL;
+                               return G.curscreen; // FIXME: add that dopesheet type thing here!
+                       
+                       default: /* includes SACTCONT_DOPESHEET for now */
+                               *datatype= ACTCONT_NONE;
+                               return NULL;
+               }
        }
        else {
-               *datatype= ACTCONT_NONE;
-               return NULL;
+               /* resort to guessing based on what is available */
+               if (act) {
+                       *datatype= ACTCONT_ACTION;
+                       return act;
+               }
+               else if (key) {
+                       *datatype= ACTCONT_SHAPEKEY;
+                       return key;
+               }
+               else {
+                       *datatype= ACTCONT_NONE;
+                       return NULL;
+               }
        }
 }
 
@@ -1307,12 +1397,18 @@ void duplicate_action_keys (void)
        if (data == NULL) return;
        
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        /* loop through filtered data and duplicate selected keys */
        for (ale= act_data.first; ale; ale= ale->next) {
-               duplicate_ipo_keys((Ipo *)ale->key_data);
+               if (ale->type == ACTTYPE_GPLAYER)
+                       duplicate_gplayer_frames(ale->data);
+               else
+                       duplicate_ipo_keys((Ipo *)ale->key_data);
        }
        
        /* free filtered list */
@@ -1398,7 +1494,10 @@ void snap_action_keys(short mode)
        }
        
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        /* snap to frame */
@@ -1408,6 +1507,8 @@ void snap_action_keys(short mode)
                        snap_ipo_keys(ale->key_data, mode);
                        actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
                }
+               else if (ale->type == ACTTYPE_GPLAYER)
+                       snap_gplayer_frames(ale->data, mode);
                else 
                        snap_ipo_keys(ale->key_data, mode);
        }
@@ -1421,6 +1522,7 @@ void snap_action_keys(short mode)
        allqueue(REDRAWACTION, 0);
        allqueue(REDRAWIPO, 0);
        allqueue(REDRAWNLA, 0);
+       allqueue(REDRAWVIEW3D, 0);
 }
 
 /* this function is responsible for snapping keyframes to frame-times */
@@ -1456,7 +1558,10 @@ void mirror_action_keys(short mode)
        }
        
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        /* mirror */
@@ -1466,6 +1571,8 @@ void mirror_action_keys(short mode)
                        mirror_ipo_keys(ale->key_data, mode);
                        actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
                }
+               else if (ale->type == ACTTYPE_GPLAYER)
+                       mirror_gplayer_frames(ale->data, mode);
                else 
                        mirror_ipo_keys(ale->key_data, mode);
        }
@@ -1550,6 +1657,10 @@ void insertkey_action(void)
                        }
                }
        }
+       else {
+               /* this tool is not supported in this mode */
+               return;
+       }
        
        BIF_undo_push("Insert Key");
        allspace(REMAKEIPO, 0);
@@ -1573,12 +1684,18 @@ void delete_action_keys (void)
        if (data == NULL) return;
        
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        /* loop through filtered data and delete selected keys */
        for (ale= act_data.first; ale; ale= ale->next) {
-               delete_ipo_keys((Ipo *)ale->key_data);
+               if (ale->type == ACTTYPE_GPLAYER)
+                       delete_gplayer_frames((bGPDlayer *)ale->data);
+               else
+                       delete_ipo_keys((Ipo *)ale->key_data);
        }
        
        /* free filtered list */
@@ -1699,6 +1816,7 @@ void clean_action (void)
                                0.0000001f, 1.0, 0.001, 0.1,
                                "Clean Threshold");
        if (!ok) return;
+       if (datatype == ACTCONT_GPENCIL) return;
        
        /* filter data */
        filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_SEL | ACTFILTER_ONLYICU);
@@ -1737,6 +1855,7 @@ void sample_action_keys (void)
        /* sanity checks */
        data= get_action_context(&datatype);
        if (data == NULL) return;
+       if (datatype == ACTCONT_GPENCIL) return;
        
        /* filter data */
        filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU);
@@ -2096,6 +2215,7 @@ void action_set_ipo_flags (short mode, short event)
        /* determine what type of data we are operating on */
        data = get_action_context(&datatype);
        if (data == NULL) return;
+       if (datatype == ACTCONT_GPENCIL) return;
        
        /* determine which set of processing we are doing */
        switch (mode) {
@@ -2194,6 +2314,7 @@ void sethandles_action_keys (int code)
        /* determine what type of data we are operating on */
        data = get_action_context(&datatype);
        if (data == NULL) return;
+       if (datatype == ACTCONT_GPENCIL) return;
        
        /* filter data */
        filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
@@ -2224,7 +2345,7 @@ static void numbuts_action ()
        void *data;
        short datatype;
        
-       void *act_channel;
+       void *act_channel, *channel_owner;
        short chantype;
        
        bActionGroup *agrp= NULL;
@@ -2232,11 +2353,13 @@ static void numbuts_action ()
        bConstraintChannel *conchan= NULL;
        IpoCurve *icu= NULL;
        KeyBlock *kb= NULL;
+       bGPdata *gpd= NULL;
+       bGPDlayer *gpl= NULL;
        
        short mval[2];
        
        int but=0;
-    char str[64];
+    char str[128];
        short expand, protect, mute;
        float slidermin, slidermax;
        
@@ -2249,7 +2372,7 @@ static void numbuts_action ()
        getmouseco_areawin(mval);
        if (mval[0] > NAMEWIDTH) 
                return;
-       act_channel= get_nearest_act_channel(mval, &chantype);
+       act_channel= get_nearest_act_channel(mval, &chantype, &channel_owner);
        
        /* create items for clever-numbut */
        if (chantype == ACTTYPE_ACHAN) {
@@ -2345,6 +2468,19 @@ static void numbuts_action ()
                add_numbut(but++, TOG|SHO, "Expanded", 0, 24, &expand, "Action Group is Expanded");
                add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Group is Protected");
        }
+       else if (chantype == ACTTYPE_GPLAYER) {
+               /* Grease-Pencil Layer */
+               gpd= (bGPdata *)channel_owner;
+               gpl= (bGPDlayer *)act_channel;
+               
+               strcpy(str, gpl->info);
+               protect= (gpl->flag & GP_LAYER_LOCKED);
+               mute = (gpl->flag & GP_LAYER_HIDE);
+               
+               add_numbut(but++, TEX, "GP-Layer: ", 0, 128, str, "Name of Grease Pencil Layer");
+               add_numbut(but++, TOG|SHO, "Hide", 0, 24, &mute, "Grease Pencil Layer is Visible");
+               add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Grease Pencil Layer is Protected");
+       }
        else {
                /* nothing under-cursor */
                return;
@@ -2393,6 +2529,16 @@ static void numbuts_action ()
                        if (protect) agrp->flag |= AGRP_PROTECTED;
                        else agrp->flag &= ~AGRP_PROTECTED;
                }
+               else if (gpl) {
+                       strcpy(gpl->info, str);
+                       BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info), 128);
+                       
+                       if (mute) gpl->flag |= GP_LAYER_HIDE;
+                       else gpl->flag &= ~GP_LAYER_HIDE;;
+                       
+                       if (protect) gpl->flag |= GP_LAYER_LOCKED;
+                       else gpl->flag &= ~GP_LAYER_LOCKED;
+               }
                
         allqueue(REDRAWACTION, 0);
                allspace(REMAKEIPO, 0);
@@ -2524,6 +2670,31 @@ void setflag_action_channels (short mode)
                                }
                        }
                                break;
+                       case ACTTYPE_GPLAYER:
+                       {
+                               bGPDlayer *gpl= (bGPDlayer *)ale->data;
+                               
+                               /* 'protect' and 'mute' */
+                               if (val == 2) {
+                                       /* mute */
+                                       if (mode == 2)
+                                               gpl->flag &= ~GP_LAYER_HIDE;
+                                       else if (mode == 1)
+                                               gpl->flag |= GP_LAYER_HIDE;
+                                       else
+                                               gpl->flag ^= GP_LAYER_HIDE;
+                               }
+                               else if (val == 1) {
+                                       /* protected */
+                                       if (mode == 2)
+                                               gpl->flag &= ~GP_LAYER_LOCKED;
+                                       else if (mode == 1)
+                                               gpl->flag |= GP_LAYER_LOCKED;
+                                       else
+                                               gpl->flag ^= GP_LAYER_LOCKED;
+                               }
+                       }
+                               break;
                }
        }
        BLI_freelistN(&act_data);
@@ -2564,7 +2735,7 @@ static void select_action_group (bAction *act, bActionGroup *agrp, int selectmod
        set_active_actiongroup(act, agrp, select);
 }
 
-static void hilight_channel(bAction *act, bActionChannel *achan, short select)
+static void hilight_channel (bAction *act, bActionChannel *achan, short select)
 {
        bActionChannel *curchan;
 
@@ -2637,7 +2808,7 @@ void select_actionchannel_by_name (bAction *act, char *name, int select)
 
 /* exported for outliner (ton) */
 /* apparently within active object context */
-int select_channel(bAction *act, bActionChannel *achan, int selectmode) 
+int select_channel (bAction *act, bActionChannel *achan, int selectmode) 
 {
        /* Select the channel based on the selection mode */
        int flag;
@@ -2661,9 +2832,9 @@ int select_channel(bAction *act, bActionChannel *achan, int selectmode)
        return flag;
 }
 
-static int select_constraint_channel(bAction *act, 
-                                     bConstraintChannel *conchan, 
-                                     int selectmode) 
+static int select_constraint_channel (bAction *act, 
+                                      bConstraintChannel *conchan, 
+                                      int selectmode) 
 {
        /* Select the constraint channel based on the selection mode */
        int flag;
@@ -2684,7 +2855,7 @@ static int select_constraint_channel(bAction *act,
        return flag;
 }
 
-int select_icu_channel(bAction *act, IpoCurve *icu, int selectmode) 
+int select_icu_channel (bAction *act, IpoCurve *icu, int selectmode) 
 {
        /* Select the channel based on the selection mode */
        int flag;
@@ -2704,6 +2875,30 @@ int select_icu_channel(bAction *act, IpoCurve *icu, int selectmode)
        return flag;
 }
 
+int select_gplayer_channel (bGPdata *gpd, bGPDlayer *gpl, int selectmode) 
+{
+       /* Select the channel based on the selection mode */
+       int flag;
+
+       switch (selectmode) {
+       case SELECT_ADD:
+               gpl->flag |= GP_LAYER_SELECT;
+               break;
+       case SELECT_SUBTRACT:
+               gpl->flag &= ~GP_LAYER_SELECT;
+               break;
+       case SELECT_INVERT:
+               gpl->flag ^= GP_LAYER_SELECT;
+               break;
+       }
+       
+       flag = (gpl->flag & GP_LAYER_SELECT) ? 1 : 0;
+       if (flag)
+               gpencil_layer_setactive(gpd, gpl);
+
+       return flag;
+}
+
 
 /* select only the active action-group's action channels */
 void select_action_group_channels (bAction *act, bActionGroup *agrp)
@@ -2848,6 +3043,8 @@ void deselect_action_channels (short mode)
        /* based on type */
        if (datatype == ACTCONT_ACTION)
                deselect_actionchannels(data, mode);
+       else if (datatype == ACTCONT_GPENCIL)
+               deselect_gpencil_layers(data, mode);
        // should shapekey channels be allowed to do this? 
 }
 
@@ -2863,24 +3060,40 @@ void deselect_action_keys (short test, short sel)
        /* determine what type of data we are operating on */
        data = get_action_context(&datatype);
        if (data == NULL) return;
-               
+       
+       /* determine type-based settings */
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
+       
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        /* See if we should be selecting or deselecting */
        if (test) {
                for (ale= act_data.first; ale; ale= ale->next) {
-                       if (is_ipo_key_selected(ale->key_data)) {
-                               sel= 0;
-                               break;
+                       if (ale->type == ACTTYPE_GPLAYER) {
+                               if (is_gplayer_frame_selected(ale->data)) {
+                                       sel= 0;
+                                       break;
+                               }
+                       }
+                       else {
+                               if (is_ipo_key_selected(ale->key_data)) {
+                                       sel= 0;
+                                       break;
+                               }
                        }
                }
        }
                
        /* Now set the flags */
        for (ale= act_data.first; ale; ale= ale->next) {
-               set_ipo_key_selection(ale->key_data, sel);
+               if (ale->type == ACTTYPE_GPLAYER)
+                       set_gplayer_frame_selection(ale->data, sel);
+               else
+                       set_ipo_key_selection(ale->key_data, sel);
        }
        
        /* Cleanup */
@@ -2908,11 +3121,11 @@ void selectall_action_keys (short mval[], short mode, short select_mode)
        switch (mode) {
                case 0: /* all in channel*/
                {
-                       void *act_channel;
+                       void *act_channel, *channel_owner;
                        short chantype;
                        
                        /* get channel, and act according to type */
-                       act_channel= get_nearest_act_channel(mval, &chantype);
+                       act_channel= get_nearest_act_channel(mval, &chantype, &channel_owner);
                        switch (chantype) {
                                case ACTTYPE_GROUP:     
                                {
@@ -2946,6 +3159,12 @@ void selectall_action_keys (short mval[], short mode, short select_mode)
                                        select_icu_bezier_keys(icu, select_mode);
                                }
                                        break;
+                               case ACTTYPE_GPLAYER:
+                               {
+                                       bGPDlayer *gpl= (bGPDlayer *)act_channel;
+                                       select_gpencil_frames(gpl, select_mode);
+                               }
+                                       break;
                        }
                }
                        break;
@@ -2971,12 +3190,16 @@ void selectall_action_keys (short mval[], short mode, short select_mode)
                        rectf.xmax = rectf.xmax + 0.5;
                        
                        /* filter data */
-                       filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
+                       if (datatype == ACTCONT_GPENCIL)
+                               filter= (ACTFILTER_VISIBLE);
+                       else
+                               filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
                        actdata_filter(&act_data, filter, data, datatype);
                                
                        /* Now set the flags */
-                       for (ale= act_data.first; ale; ale= ale->next)
+                       for (ale= act_data.first; ale; ale= ale->next) {
                                borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, select_mode);
+                       }
                        
                        /* Cleanup */
                        BLI_freelistN(&act_data);
@@ -3058,19 +3281,23 @@ void selectkeys_leftright (short leftright, short select_mode)
        }
        
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
                
        /* select keys on the side where most data occurs */
        for (ale= act_data.first; ale; ale= ale->next) {
-               if(NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
+               if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
                        actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
                        borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
                        actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
                }
-               else {
+               else if (ale->type == ACTTYPE_GPLAYER)
+                       borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
+               else
                        borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
-               }
        }
        
        /* Cleanup */
@@ -3108,7 +3335,10 @@ void nextprev_action_keyframe (short dir)
                return;
        
        /* get list of keyframes that can be used (in global-time) */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        for (ale= act_data.first; ale; ale= ale->next) {
@@ -3117,6 +3347,8 @@ void nextprev_action_keyframe (short dir)
                        make_cfra_list(ale->key_data, &elems);
                        actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
                }
+               else if (ale->type == ACTTYPE_GPLAYER)
+                       gplayer_make_cfra_list(ale->key_data, &elems, 0);
                else 
                        make_cfra_list(ale->key_data, &elems);
        }
@@ -3199,11 +3431,20 @@ void column_select_action_keys (int mode)
        /* build list of columns */
        switch (mode) {
                case 1: /* list of selected keys */
-                       filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
-                       actdata_filter(&act_data, filter, data, datatype);
-                       
-                       for (ale= act_data.first; ale; ale= ale->next)
-                               make_sel_cfra_list(ale->key_data, &elems);
+                       if (datatype == ACTCONT_GPENCIL) {
+                               filter= (ACTFILTER_VISIBLE);
+                               actdata_filter(&act_data, filter, data, datatype);
+                               
+                               for (ale= act_data.first; ale; ale= ale->next)
+                                       gplayer_make_cfra_list(ale->data, &elems, 1);
+                       }
+                       else {
+                               filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
+                               actdata_filter(&act_data, filter, data, datatype);
+                               
+                               for (ale= act_data.first; ale; ale= ale->next)
+                                       make_sel_cfra_list(ale->key_data, &elems);
+                       }
                        
                        BLI_freelistN(&act_data);
                        break;
@@ -3231,19 +3472,34 @@ void column_select_action_keys (int mode)
        /* loop through all of the keys and select additional keyframes
         * based on the keys found to be selected above
         */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_ONLYICU);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_ONLYICU);
        actdata_filter(&act_data, filter, data, datatype);
        
        for (ale= act_data.first; ale; ale= ale->next) {
                for (ce= elems.first; ce; ce= ce->next) {
-                       for (icu= ale->key_data; icu; icu= icu->next) {
-                               BezTriple *bezt;
-                               int verts = 0;
+                       /* select elements with frame number matching cfraelem */
+                       if (ale->type == ACTTYPE_GPLAYER) {
+                               bGPDlayer *gpl= (bGPDlayer *)ale->data;
+                               bGPDframe *gpf;
                                
-                               for (bezt=icu->bezt; verts<icu->totvert; bezt++, verts++) {
-                                       if (bezt) {
-                                               if( (int)(ce->cfra) == (int)(bezt->vec[1][0]) )
-                                                       bezt->f2 |= 1;
+                               for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+                                       if ( (int)ce->cfra == gpf->framenum ) 
+                                               gpf->flag |= GP_FRAME_SELECT;
+                               }
+                       }
+                       else {
+                               for (icu= ale->key_data; icu; icu= icu->next) {
+                                       BezTriple *bezt;
+                                       int verts = 0;
+                                       
+                                       for (bezt=icu->bezt; verts<icu->totvert; bezt++, verts++) {
+                                               if (bezt) {
+                                                       if( (int)(ce->cfra) == (int)(bezt->vec[1][0]) )
+                                                               bezt->f2 |= 1;
+                                               }
                                        }
                                }
                        }
@@ -3272,7 +3528,7 @@ void borderselect_actionchannels (void)
        /* determine what type of data we are operating on */
        data = get_action_context(&datatype);
        if (data == NULL) return;
-       if (datatype != ACTCONT_ACTION) return;
+       if (ELEM(datatype, ACTCONT_ACTION, ACTCONT_GPENCIL)==0) return;
        
        /* draw and handle the borderselect stuff (ui) and get the select rect */
        if ( (val = get_border(&rect, 3)) ) {
@@ -3344,6 +3600,16 @@ void borderselect_actionchannels (void)
                                                        icu->flag &= ~IPO_SELECT;
                                        }
                                                break;
+                                       case ACTTYPE_GPLAYER: /* grease-pencil layer */
+                                       {
+                                               bGPDlayer *gpl = (bGPDlayer *)ale->data;
+                                               
+                                               if (selectmode == SELECT_ADD)
+                                                       gpl->flag |= GP_LAYER_SELECT;
+                                               else
+                                                       gpl->flag &= ~GP_LAYER_SELECT;
+                                       }
+                                               break;
                                }
                                
                                /* select action-channel 'owner' */
@@ -3460,6 +3726,9 @@ void borderselect_action (void)
                                                        borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode);
                                        }
                                }
+                               else if (ale->type == ACTTYPE_GPLAYER) {
+                                       borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
+                               }
                                break;
                        case ACTEDIT_BORDERSEL_CHA: /* all in channel(s) */
                                if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
@@ -3481,6 +3750,9 @@ void borderselect_action (void)
                                                                select_ipo_bezier_keys(conchan->ipo, selectmode);
                                                }
                                        }
+                                       else if (ale->type == ACTTYPE_GPLAYER) {
+                                               select_gpencil_frames(ale->data, selectmode);
+                                       }
                                }
                                break;
                        default: /* any keyframe inside region defined by region */
@@ -3503,6 +3775,9 @@ void borderselect_action (void)
                                                                borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode);
                                                }
                                        }
+                                       else if (ale->type == ACTTYPE_GPLAYER) {
+                                               borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
+                                       }
                                }
                        }
                        
@@ -3533,6 +3808,8 @@ static void mouse_action (int selectmode)
        bActionChannel *achan= NULL;
        bConstraintChannel *conchan= NULL;
        IpoCurve *icu= NULL;
+       bGPdata *gpd = NULL;
+       bGPDlayer *gpl = NULL;
        TimeMarker *marker, *pmarker;
        
        void *act_channel;
@@ -3543,6 +3820,7 @@ static void mouse_action (int selectmode)
        data = get_action_context(&datatype);
        if (data == NULL) return;
        if (datatype == ACTCONT_ACTION) act= (bAction *)data;
+       if (datatype == ACTCONT_GPENCIL) gpd= (bGPdata *)data;
 
        act_channel= get_nearest_action_key(&selx, &sel, &act_type, &achan);
        marker= find_nearest_marker(SCE_MARKERS, 1);
@@ -3615,6 +3893,9 @@ static void mouse_action (int selectmode)
                        case ACTTYPE_GROUP:
                                agrp= (bActionGroup *)act_channel;
                                break;
+                       case ACTTYPE_GPLAYER:
+                               gpl= (bGPDlayer *)act_channel;
+                               break;
                        default:
                                return;
                }
@@ -3638,6 +3919,13 @@ static void mouse_action (int selectmode)
                                        set_active_actiongroup(act, agrp, 1);
                                }
                        }
+                       else if (datatype == ACTCONT_GPENCIL) {
+                               deselect_action_channels(0);
+                               
+                               /* Highlight gpencil layer */
+                               gpl->flag |= GP_LAYER_SELECT;
+                               gpencil_layer_setactive(gpd, gpl);
+                       }
                }
                
                if (icu)
@@ -3654,6 +3942,8 @@ static void mouse_action (int selectmode)
                                        select_ipo_key(conchan->ipo, selx, selectmode);
                        }