svn merge -r 15688:15908 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorAndre Susano Pinto <andresusanopinto@gmail.com>
Fri, 1 Aug 2008 21:37:36 +0000 (21:37 +0000)
committerAndre Susano Pinto <andresusanopinto@gmail.com>
Fri, 1 Aug 2008 21:37:36 +0000 (21:37 +0000)
195 files changed:
bin/.blender/.Blanguages
intern/boolop/intern/BOP_Edge.cpp
intern/boolop/intern/BOP_Edge.h
intern/boolop/intern/BOP_Face.cpp
intern/boolop/intern/BOP_Face.h
intern/boolop/intern/BOP_Interface.cpp
intern/boolop/intern/BOP_Merge.cpp
intern/boolop/intern/BOP_Merge.h
intern/boolop/intern/BOP_Merge2.cpp [new file with mode: 0644]
intern/boolop/intern/BOP_Merge2.h [new file with mode: 0644]
intern/boolop/intern/BOP_Mesh.cpp
intern/boolop/intern/BOP_Mesh.h
intern/boolop/intern/BOP_Misc.h [new file with mode: 0644]
intern/boolop/intern/BOP_Tag.h
intern/boolop/intern/BOP_Vertex.cpp
intern/boolop/intern/BOP_Vertex.h
projectfiles_vc7/blender/makesdna/DNA_makesdna.vcproj
projectfiles_vc7/blender/src/BL_src.vcproj
projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj
release/scripts/rvk1_torvk2.py
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_idprop.h
source/blender/blenkernel/BKE_shrinkwrap.h
source/blender/blenkernel/BKE_texture.h
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/idprop.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenkernel/intern/texture.c
source/blender/blenlib/intern/arithb.c
source/blender/blenlib/intern/freetypefont.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/BDR_gpencil.h
source/blender/include/BIF_editaction.h
source/blender/include/BIF_editarmature.h
source/blender/include/BIF_editview.h
source/blender/include/BSE_drawview.h
source/blender/include/butspace.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_armature_types.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesdna/DNA_customdata_types.h
source/blender/makesdna/DNA_gpencil_types.h
source/blender/makesdna/DNA_meshdata_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_sequence_types.h
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/Armature.c
source/blender/python/api2_2x/Bone.c
source/blender/python/api2_2x/IDProp.c
source/blender/python/api2_2x/doc/Armature.py
source/blender/python/api2_2x/doc/IDProp.py
source/blender/python/api2_2x/doc/Ipo.py
source/blender/python/api2_2x/sceneRender.c
source/blender/src/buttons_editing.c
source/blender/src/buttons_logic.c
source/blender/src/buttons_object.c
source/blender/src/drawaction.c
source/blender/src/drawgpencil.c
source/blender/src/drawnode.c
source/blender/src/drawseq.c
source/blender/src/drawview.c
source/blender/src/editaction.c
source/blender/src/editaction_gpencil.c
source/blender/src/editarmature.c
source/blender/src/editipo.c
source/blender/src/editnode.c
source/blender/src/editobject.c
source/blender/src/editseq.c
source/blender/src/editview.c
source/blender/src/gpencil.c
source/blender/src/header_action.c
source/blender/src/header_ipo.c
source/blender/src/header_view3d.c
source/blender/src/interface.c
source/blender/src/interface_draw.c
source/blender/src/meshlaplacian.c
source/blender/src/outliner.c
source/blender/src/poseobject.c
source/blender/src/sequence.c
source/blender/src/space.c
source/blender/src/transform_conversions.c
source/blender/src/transform_manipulator.c
source/creator/creator.c
source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp [deleted file]
source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h [deleted file]
source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
source/gameengine/Converter/BL_ActionActuator.cpp
source/gameengine/Converter/BL_ArmatureObject.cpp
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/BL_ShapeActionActuator.cpp
source/gameengine/Converter/BL_ShapeActionActuator.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Converter/KX_ConvertSensors.cpp
source/gameengine/Converter/KX_IpoConvert.cpp
source/gameengine/Converter/KX_IpoConvert.h
source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp
source/gameengine/GameLogic/SCA_ActuatorEventManager.h
source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
source/gameengine/GameLogic/SCA_ActuatorSensor.h
source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp
source/gameengine/GameLogic/SCA_AlwaysEventManager.h
source/gameengine/GameLogic/SCA_EventManager.cpp
source/gameengine/GameLogic/SCA_EventManager.h
source/gameengine/GameLogic/SCA_IObject.cpp
source/gameengine/GameLogic/SCA_ISensor.cpp
source/gameengine/GameLogic/SCA_ISensor.h
source/gameengine/GameLogic/SCA_JoystickManager.cpp
source/gameengine/GameLogic/SCA_JoystickManager.h
source/gameengine/GameLogic/SCA_KeyboardManager.cpp
source/gameengine/GameLogic/SCA_KeyboardManager.h
source/gameengine/GameLogic/SCA_LogicManager.cpp
source/gameengine/GameLogic/SCA_LogicManager.h
source/gameengine/GameLogic/SCA_MouseManager.cpp
source/gameengine/GameLogic/SCA_MouseManager.h
source/gameengine/GameLogic/SCA_PropertyEventManager.cpp
source/gameengine/GameLogic/SCA_PropertyEventManager.h
source/gameengine/GameLogic/SCA_RandomEventManager.cpp
source/gameengine/GameLogic/SCA_RandomEventManager.h
source/gameengine/GameLogic/SCA_TimeEventManager.cpp
source/gameengine/GameLogic/SCA_TimeEventManager.h
source/gameengine/Ketsji/BL_BlenderShader.cpp
source/gameengine/Ketsji/BL_BlenderShader.h
source/gameengine/Ketsji/BL_Material.h
source/gameengine/Ketsji/BL_Texture.cpp
source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp
source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h
source/gameengine/Ketsji/KX_BlenderMaterial.cpp
source/gameengine/Ketsji/KX_BlenderMaterial.h
source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
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_IpoActuator.cpp
source/gameengine/Ketsji/KX_IpoActuator.h
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_MaterialIpoController.cpp
source/gameengine/Ketsji/KX_MaterialIpoController.h
source/gameengine/Ketsji/KX_NearSensor.cpp
source/gameengine/Ketsji/KX_NearSensor.h
source/gameengine/Ketsji/KX_ObjectActuator.cpp
source/gameengine/Ketsji/KX_ObjectActuator.h
source/gameengine/Ketsji/KX_PolygonMaterial.cpp
source/gameengine/Ketsji/KX_PolygonMaterial.h
source/gameengine/Ketsji/KX_PyMath.h
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_RayEventManager.cpp
source/gameengine/Ketsji/KX_RayEventManager.h
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_TouchEventManager.cpp
source/gameengine/Ketsji/KX_TouchEventManager.h
source/gameengine/Ketsji/KX_TouchSensor.cpp
source/gameengine/Ketsji/KX_TouchSensor.h
source/gameengine/Ketsji/KX_TrackToActuator.cpp
source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp
source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
source/gameengine/Physics/common/PHY_IPhysicsEnvironment.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_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_BucketManager.cpp
source/gameengine/Rasterizer/RAS_BucketManager.h
source/gameengine/Rasterizer/RAS_CameraData.h
source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
source/gameengine/Rasterizer/RAS_IRasterizer.h
source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
source/gameengine/Rasterizer/RAS_MaterialBucket.h
source/gameengine/Rasterizer/RAS_MeshObject.cpp
source/gameengine/Rasterizer/RAS_MeshObject.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
source/gameengine/Rasterizer/RAS_Polygon.cpp

index 0f98ce0..de8d8c4 100644 (file)
@@ -20,3 +20,4 @@ Romanian:ro
 Arabic:ar
 Bulgarian:bg
 Greek:el
+Korean:kr
index ac302b5..44e7d5c 100644 (file)
@@ -75,4 +75,47 @@ void BOP_Edge::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex)
        else if (m_vertexs[1] == oldIndex) m_vertexs[1] = newIndex;
 }
 
+#ifdef BOP_NEW_MERGE
+
+/**
+ * Returns if this edge contains the specified face index.
+ * @param i face index
+ * @return true if this edge contains the specified face index, false otherwise
+ */
+bool BOP_Edge::removeFace(BOP_Index i)
+{
+       int pos=0;
+       for(BOP_IT_Indexs it = m_faces.begin();it!=m_faces.end();pos++,it++) {
+               if ((*it) == i) {
+                       m_faces.erase(it);
+                       return true;
+               }
+       }
+       
+       return false;
+}
+
+#endif
+
+#ifdef BOP_DEBUG
+
+#include <iostream>
+using namespace std;
+
+/**
+ * Implements operator <<.
+ */
+ostream &operator<<(ostream &stream, BOP_Edge *e)
+{
+       stream << "Edge[" << e->getVertex1() << "," << e->getVertex2();
+#ifdef BOP_NEW_MERGE
+       if(e->m_used)
+               stream << "] (used)";
+       else
+               stream << "] (unused)";
+#endif
+       return stream;
+}
+#endif
+
 
index 13426f6..a817b3d 100644 (file)
 #define BOP_EDGE_H
 
 #include "BOP_Indexs.h"
+#include "BOP_Misc.h"
 
 class BOP_Edge
 {
 private:
        BOP_Index  m_vertexs[2];
        BOP_Indexs m_faces;
+#ifdef BOP_NEW_MERGE
+       bool m_used;
+#endif
 
        bool containsFace(BOP_Index i);
 
@@ -47,6 +51,15 @@ public:
        inline unsigned int getNumFaces(){return m_faces.size();};
        inline BOP_Indexs &getFaces(){return m_faces;};
        void addFace(BOP_Index face);
+#ifdef BOP_NEW_MERGE
+       bool removeFace(BOP_Index i);
+       bool getUsed() { return m_used;};
+       void setUsed(bool setting) { m_used=setting;};
+#endif
+#ifdef BOP_DEBUG
+       friend ostream &operator<<(ostream &stream, BOP_Edge *e);
+#endif
+
 };
 
 #endif
index 12c9462..01308de 100644 (file)
@@ -402,6 +402,7 @@ bool BOP_Face4::getEdgeIndex(BOP_Index v1, BOP_Index v2, unsigned int &e)
        return  true;
 }  
 
+#ifdef BOP_DEBUG
 /**
  * Implements operator <<.
  */
@@ -421,3 +422,4 @@ ostream &operator<<(ostream &stream, BOP_Face *f)
 
        return stream;
 }
+#endif
index e16425f..965882d 100644 (file)
@@ -32,6 +32,7 @@
 #include "MT_Plane3.h"
 #include "BOP_Indexs.h"
 #include "BOP_BBox.h"
+#include "BOP_Misc.h"
 #include <iostream>
 #include <vector>
 using namespace std;
@@ -80,7 +81,9 @@ public:
        virtual void replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex) = 0;
        virtual bool containsVertex(BOP_Index v) = 0;
                
+#ifdef BOP_DEBUG
        friend ostream &operator<<(ostream &stream, BOP_Face *f);
+#endif
 };
 
 class BOP_Face3: public BOP_Face 
index 2a19810..898ca70 100644 (file)
 #include "BOP_Mesh.h"
 #include "BOP_Face2Face.h"
 #include "BOP_Merge.h"
+#include "BOP_Merge2.h"
 #include "BOP_Chrono.h"
 
-//#define DEBUG
+#if defined(BOP_ORIG_MERGE) && defined(BOP_NEW_MERGE) 
+#include "../../source/blender/blenkernel/BKE_global.h"
+#endif
 
 BoolOpState BOP_intersectionBoolOp(BOP_Mesh*  meshC,
                                                                   BOP_Faces* facesA,
@@ -208,7 +211,32 @@ BoolOpState BOP_intersectionBoolOp(BOP_Mesh*  meshC,
        #endif
 
        // Merge faces
+#ifdef BOP_ORIG_MERGE
+#ifndef BOP_NEW_MERGE
        BOP_Merge::getInstance().mergeFaces(meshC,numVertices);
+#endif
+#endif
+
+#ifdef BOP_NEW_MERGE
+#ifndef BOP_ORIG_MERGE
+       BOP_Merge2::getInstance().mergeFaces(meshC,numVertices);
+#else
+       static int state = -1;
+       if (G.rt == 100) {
+               if( state != 1 ) {
+                       cout << "Boolean code using old merge technique." << endl;
+                       state = 1;
+               }
+               BOP_Merge::getInstance().mergeFaces(meshC,numVertices);
+       } else {
+               if( state != 0 ) {
+                       cout << "Boolean code using new merge technique." << endl;
+                       state = 0;
+               }
+               BOP_Merge2::getInstance().mergeFaces(meshC,numVertices);
+       }
+#endif
+#endif
 
        #ifdef DEBUG
        c = chrono.stamp(); t += c;
index 1e4139a..012d340 100644 (file)
@@ -30,6 +30,7 @@
  
 #include "BOP_Merge.h"
 
+#ifdef BOP_ORIG_MERGE
 
 #ifdef _MSC_VER
 #if _MSC_VER < 1300
@@ -802,3 +803,5 @@ void BOP_Merge::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, B
        }
        }
 }
+
+#endif  /* BOP_ORIG_MERGE */
index 88999b2..ceb8ec1 100644 (file)
@@ -28,6 +28,9 @@
 #ifndef BOP_MERGE_H
 #define BOP_MERGE_H
 
+#include "BOP_Misc.h"
+
+#ifdef BOP_ORIG_MERGE
 #include "BOP_Mesh.h"
 #include "BOP_Tag.h"
 #include "BOP_MathUtils.h"
@@ -68,4 +71,6 @@ class BOP_Merge {
                void mergeFaces(BOP_Mesh *m, BOP_Index v);
 };
 
+#endif /* BOP_ORIG_MERGE */
+
 #endif
diff --git a/intern/boolop/intern/BOP_Merge2.cpp b/intern/boolop/intern/BOP_Merge2.cpp
new file mode 100644 (file)
index 0000000..bbf3f8b
--- /dev/null
@@ -0,0 +1,944 @@
+/**
+ *
+ * $Id: BOP_Merge22.cpp 14444 2008-04-16 22:40:48Z hos $
+ *
+ * ***** 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Marc Freixas, Ken Hughes
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#include "BOP_Merge2.h"
+
+#ifdef BOP_NEW_MERGE
+
+static void deleteFace(BOP_Mesh *m, BOP_Face *face);
+
+/**
+ * SINGLETON (use method BOP_Merge2.getInstance).
+ */
+BOP_Merge2 BOP_Merge2::SINGLETON;
+
+#ifdef BOP_DEBUG
+void dumpmesh ( BOP_Mesh *m, bool force )
+{
+       unsigned int nonmanifold = 0;
+       {
+       BOP_Edges edges = m->getEdges();
+       int count = 0;
+    for (BOP_IT_Edges edge = edges.begin(); edge != edges.end();
+               ++count, ++edge) {
+               if (!(*edge)->getUsed() && (*edge)->getFaces().size() == 0 ) continue;
+               BOP_Vertex * v1 = m->getVertex((*edge)->getVertex1());
+               BOP_Vertex * v2 = m->getVertex((*edge)->getVertex2());
+
+               if(v1->getTAG()!= BROKEN || v2->getTAG()!= BROKEN ) {
+                       int fcount = 0;
+                       BOP_Indexs faces = (*edge)->getFaces();
+                       for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); face++) {
+                               BOP_Face *f = m->getFace(*face);
+                               if(f->getTAG()== UNCLASSIFIED) ++fcount;
+                       }
+
+
+                       if(fcount !=0 && fcount !=2 ) {
+                               ++nonmanifold;
+                       }
+               }
+       }
+       if (!force && nonmanifold == 0) return;
+       }
+       if( nonmanifold )
+               cout << nonmanifold << " edges detected" << endl;
+#ifdef DEBUG
+       cout << "---------------------------" << endl;
+
+       BOP_Edges edges = m->getEdges();
+       int count = 0;
+    for (BOP_IT_Edges edge = edges.begin(); edge != edges.end();
+               ++count, ++edge) {
+               BOP_Vertex * v1 = m->getVertex((*edge)->getVertex1());
+               BOP_Vertex * v2 = m->getVertex((*edge)->getVertex2());
+
+               if(v1->getTAG()!= BROKEN || v2->getTAG()!= BROKEN ) {
+                       int fcount = 0;
+                       BOP_Indexs faces = (*edge)->getFaces();
+                       cout << count << ", " << (*edge) << ", " << faces.size() << endl;
+                       for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); face++) {
+                               BOP_Face *f = m->getFace(*face);
+                               if(f->getTAG()== UNCLASSIFIED) ++fcount;
+                               cout << "  face " << f << endl;
+                       }
+
+
+                       if(fcount !=0 && fcount !=2 )
+                               cout << "    NON-MANIFOLD" << endl;
+               }
+       }
+
+       BOP_Faces faces = m->getFaces();
+       count = 0;
+    for (BOP_IT_Faces face = faces.begin(); face != faces.end(); face++) {
+               if( count < 12*2 || (*face)->getTAG() != BROKEN ) {
+                       cout << count << ", " << *face << endl;
+               }
+               ++count;
+       }
+
+       BOP_Vertexs verts = m->getVertexs();
+       count = 0;
+    for (BOP_IT_Vertexs vert = verts.begin(); vert != verts.end(); vert++) {
+               cout << count++ << ", " << *vert << " " << (*vert)->getNumEdges() << endl;
+               BOP_Indexs edges = (*vert)->getEdges();
+           for( BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it) {
+                       BOP_Edge *edge = m->getEdge(*it);
+                       cout << "   " << edge << endl;
+               }
+       }
+       cout << "===========================" << endl;
+#endif
+}
+#endif
+
+/**
+ * Simplifies a mesh, merging its faces.
+ * @param m mesh
+ * @param v index of the first mergeable vertex (can be removed by merge) 
+ */
+
+void BOP_Merge2::mergeFaces(BOP_Mesh *m, BOP_Index v)
+{
+       m_mesh = m;
+
+#ifdef DEBUG
+       cout << "##############################" << endl;
+#endif
+       cleanup( );
+
+       m_firstVertex = v;
+       bool cont = false;
+
+       // Merge faces
+       mergeFaces();   
+
+       do {
+               // Add quads ...
+               cont = createQuads();
+               // ... and merge new faces
+               if( cont ) cont = mergeFaces();
+
+#ifdef DEBUG
+               cout << "called mergeFaces " << cont << endl;
+#endif
+               // ... until the merge is not succesful
+       } while(cont);
+}
+
+void clean_nonmanifold( BOP_Mesh *m )
+{
+       return;
+
+       BOP_Edges nme;
+       BOP_Edges e = m->getEdges();
+       for( BOP_IT_Edges it = e.begin(); it != e.end(); ++it ) {
+               BOP_Indexs faces = (*it)->getFaces();
+               if( faces.size() & ~2 )
+                       nme.push_back(*it);
+       }
+       if (nme.size() == 0) return;
+       for( BOP_IT_Edges it = nme.begin(); it != nme.end(); ++it ) {
+               if( (*it)->getFaces().size() > 1 ) {
+                       BOP_Indexs faces = (*it)->getFaces();
+                       for( BOP_IT_Indexs face = faces.begin(); face != faces.end(); ++face ) {
+                               MT_Point3 vertex1 = m->getVertex(m->getFace(*face)->getVertex(0))->getPoint();
+                               MT_Point3 vertex2 = m->getVertex(m->getFace(*face)->getVertex(1))->getPoint();
+                               MT_Point3 vertex3 = m->getVertex(m->getFace(*face)->getVertex(2))->getPoint();
+                               if (BOP_collinear(vertex1,vertex2,vertex3)) // collinear triangle
+                                       deleteFace(m,m->getFace(*face));
+                       }
+                       continue;
+               }
+               BOP_Face *oface1 = m->getFace((*it)->getFaces().front());
+               BOP_Face *oface2, *tmpface;
+               BOP_Index first =(*it)->getVertex1();
+               BOP_Index next =(*it)->getVertex2();
+               BOP_Index last = first;
+               unsigned short facecount = 0;
+               bool found = false;
+               BOP_Indexs vertList;
+#ifdef DEBUG
+               cout << "  first edge is " << (*it) << endl;
+#endif
+               vertList.push_back(first);
+               BOP_Edge *edge;
+               while(true) {
+                       BOP_Vertex *vert = m->getVertex(next);
+                       BOP_Indexs edges = vert->getEdges();
+                       edge = NULL;
+                       for( BOP_IT_Indexs eit = edges.begin(); eit != edges.end(); ++eit) {
+                               edge = m->getEdge(*eit);
+                               if( edge->getFaces().size() > 1) {
+                                       edge = NULL;
+                                       continue;
+                               }
+                               if( edge->getVertex1() == next && edge->getVertex2() != last ) {
+                                       last = next;
+                                       next = edge->getVertex2();
+                                       break;
+                               }
+                               if( edge->getVertex2() == next && edge->getVertex1() != last ) {
+                                       last = next;
+                                       next = edge->getVertex1();
+                                       break;
+                               }
+                               edge = NULL;
+                       }
+                       if( !edge ) break;
+#ifdef DEBUG
+                       cout << "   next edge is " << edge << endl;
+#endif
+                       tmpface = m->getFace(edge->getFaces().front());
+                       if( oface1->getOriginalFace() != tmpface->getOriginalFace() )
+                               oface2 = tmpface;
+                       else
+                               ++facecount;
+                       vertList.push_back(last);
+                       if( vertList.size() > 3 ) break;
+                       if( next == first ) {
+                               found = true;
+                               break;
+                       }
+               }
+               if(found) {
+                       edge = *it;
+#ifdef DEBUG
+                       cout << "   --> found a loop" << endl;
+#endif
+                       if( vertList.size() == 3 ) {
+                               BOP_Face3 *face = (BOP_Face3 *)m->getFace(edge->getFaces().front());
+                               face->getNeighbours(first,last,next);
+                       } else if( vertList.size() == 4 ) {
+                               BOP_Face4 *face = (BOP_Face4 *)m->getFace(edge->getFaces().front());
+                               face->getNeighbours(first,last,next,last);
+                       } else {
+#ifdef DEBUG
+                               cout << "loop has " << vertList.size() << "verts"; 
+#endif
+                               continue;
+                       }
+                       if(facecount == 1) oface1 = oface2;
+                       next = vertList[1];
+                       last = vertList[2];
+                       if( edge->getVertex2() == next ) { 
+                               BOP_Face3 *f = new BOP_Face3(next,first,last,
+                                       oface1->getPlane(),oface1->getOriginalFace());
+                               m->addFace( f );
+#ifdef DEBUG
+                               cout << "   face is backward: " << f << endl;
+#endif
+                               
+                       } else {
+                               BOP_Face3 *f = new BOP_Face3(last,first,next,
+                                       oface1->getPlane(),oface1->getOriginalFace());
+                               m->addFace( f );
+#ifdef DEBUG
+                               cout << "   face is forward: " << f << endl;
+#endif
+                       }
+               }
+       }
+}
+
+/**
+ * Runs through mesh and makes sure vert/face/edge data is consistent.  Most
+ * importantly:
+ * (1) mark edges which are no longer used
+ * (2) remove broken faces from edges
+ * (3) remove faces from mesh which have a single edge belonging to no other
+ *     face (non-manifold edges)
+ */
+
+void BOP_Merge2::cleanup( void )
+{
+       BOP_Edges edges = m_mesh->getEdges();
+       for (BOP_IT_Edges edge = edges.begin(); edge != edges.end(); ++edge) {
+               BOP_Indexs faces = (*edge)->getFaces();
+               for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); ++face) {
+                       BOP_Face *f = m_mesh->getFace(*face);
+                       if(f->getTAG()== UNCLASSIFIED) ;
+                       else (*edge)->removeFace(*face);
+               }
+               if( (*edge)->getFaces().size() == 0) (*edge)->setUsed(false);
+       }
+
+       BOP_Vertexs v = m_mesh->getVertexs();
+       for( BOP_IT_Vertexs it = v.begin(); it != v.end(); ++it ) {
+               if( (*it)->getTAG() != BROKEN) {
+                       BOP_Indexs edges = (*it)->getEdges();
+                       for(BOP_IT_Indexs i = edges.begin();i!=edges.end();i++)
+                               if( m_mesh->getEdge((*i))->getUsed( ) == false) (*it)->removeEdge( *i );
+                       if( (*it)->getEdges().size() == 0 ) (*it)->setTAG(BROKEN);
+               }
+       }
+       // clean_nonmanifold( m_mesh );
+}
+
+/**
+ * Simplifies a mesh, merging its faces.
+ */
+bool BOP_Merge2::mergeFaces()
+{
+       BOP_Indexs mergeVertices;
+       BOP_Vertexs vertices = m_mesh->getVertexs();
+       BOP_IT_Vertexs v = vertices.begin();
+       const BOP_IT_Vertexs verticesEnd = vertices.end();
+
+       // Advance to first mergeable vertex
+       advance(v,m_firstVertex);
+       BOP_Index pos = m_firstVertex;
+
+       // Add unbroken vertices to the list
+       while(v!=verticesEnd) {
+               if ((*v)->getTAG() != BROKEN) {
+                       mergeVertices.push_back(pos);
+               }
+
+               v++;
+               pos++;
+       }
+
+       // Merge faces with that vertices
+       return mergeFaces(mergeVertices);
+}
+
+/**
+ * remove edges from vertices when the vertex is removed
+ */
+void BOP_Merge2::freeVerts(BOP_Index v, BOP_Vertex *vert)
+{
+       BOP_Indexs edges = vert->getEdges();
+       BOP_Vertex *other;
+
+       for( BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it) {
+               BOP_Edge *edge = m_mesh->getEdge(*it);
+               BOP_Indexs edges2;
+               if( edge->getVertex1() != v )
+                       other = m_mesh->getVertex( edge->getVertex1() );
+               else
+                       other = m_mesh->getVertex( edge->getVertex2() );
+               other->removeEdge(*it);
+               vert->removeEdge(*it);
+       }
+}
+
+/**
+ * Simplifies a mesh, merging the faces with the specified vertices.
+ * @param mergeVertices vertices to test
+ * @return true if a face merge was performed
+ */
+bool BOP_Merge2::mergeFaces(BOP_Indexs &mergeVertices)
+{
+       // Check size > 0!
+       if (mergeVertices.size() == 0) return false;
+       bool didMerge = false;
+
+       for( BOP_Index i = 0; i < mergeVertices.size(); ++i ) {
+               BOP_LFaces facesByOriginalFace;
+               BOP_Index v = mergeVertices[i];
+               BOP_Vertex *vert = m_mesh->getVertex(v);
+#ifdef DEBUG
+               cout << "i = " << i << ", v = " << v << ", vert = " << vert << endl;
+               if (v==48)
+                       cout << "found vert 48" << endl;
+#endif
+               if ( vert->getTAG() != BROKEN ) {
+                       getFaces(facesByOriginalFace,v);
+
+                       switch (facesByOriginalFace.size()) {
+                       case 0:
+                               // v has no unbroken faces (so it's a new BROKEN vertex)
+                               freeVerts( v, vert );
+                               vert->setTAG(BROKEN);
+                               break;
+                       case 2: {
+#ifdef DEBUG
+                               cout << "size of fBOF = " << facesByOriginalFace.size() << endl;
+#endif
+                               BOP_Faces ff = facesByOriginalFace.front();
+                               BOP_Faces fb = facesByOriginalFace.back();
+                               BOP_Index eindexs[2];
+                               int ecount = 0;
+
+                               // look for two edges adjacent to v which contain both ofaces
+                               BOP_Indexs edges = vert->getEdges();
+#ifdef DEBUG
+                               cout << "   ff has " << ff.size() << " faces" << endl;
+                               cout << "   fb has " << fb.size() << " faces" << endl;
+                               cout << "   v  has " << edges.size() << " edges" << endl;
+#endif
+                               for(BOP_IT_Indexs it = edges.begin(); it != edges.end(); 
+                                               ++it ) {
+                                       BOP_Edge *edge = m_mesh->getEdge(*it);
+                                       BOP_Indexs faces = edge->getFaces();
+#ifdef DEBUG
+                                       cout << "  " << edge << " has " << edge->getFaces().size() << " faces" << endl;
+#endif
+                                       if( faces.size() == 2 ) {
+                                               BOP_Face *f0 = m_mesh->getFace(faces[0]);
+                                               BOP_Face *f1 = m_mesh->getFace(faces[1]);
+                                               if( f0->getOriginalFace() != f1->getOriginalFace() ) {
+#ifdef DEBUG
+                                                       cout << "   " << f0 << endl;
+                                                       cout << "   " << f1 << endl;
+#endif
+                                                       eindexs[ecount++] = (*it);
+                                               }
+                                       }
+                               }
+                               if(ecount == 2) {
+#ifdef DEBUG
+                                       cout << "   edge indexes are " << eindexs[0];
+                                       cout << " and " << eindexs[1] << endl;
+#endif
+                                       BOP_Edge *edge = m_mesh->getEdge(eindexs[0]);
+                                       BOP_Index N = edge->getVertex1();
+                                       if(N == v) N = edge->getVertex2();
+#ifdef DEBUG
+                                       cout << "    ## OK, replace "<<v<<" with "<<N << endl;
+#endif
+                                       mergeVertex(ff , v, N );
+                                       mergeVertex(fb , v, N );
+// now remove v and its edges
+                                       vert->setTAG(BROKEN);
+                                       for(BOP_IT_Indexs it = edges.begin(); it != edges.end(); 
+                                                       ++it ) {
+                                               BOP_Edge *edge = m_mesh->getEdge(*it);
+                                               edge->setUsed(false);
+                                       }
+                                       didMerge = true;
+                               }       
+#ifdef DEBUG
+                               else {
+                                       cout << "   HUH: ecount was " << ecount << endl;
+                               }
+#endif
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       return didMerge;
+}
+
+void BOP_Merge2::mergeVertex(BOP_Faces &faces, BOP_Index v1, BOP_Index v2)
+{
+       for(BOP_IT_Faces face=faces.begin();face!=faces.end();face++) {
+               if( (*face)->size() == 3)
+                       mergeVertex((BOP_Face3 *) *face, v1, v2);
+               else
+                       mergeVertex((BOP_Face4 *) *face, v1, v2);
+               (*face)->setTAG(BROKEN);
+#ifdef DEBUG
+               cout << "  breaking " << (*face) << endl;
+#endif
+       }
+}
+
+/*
+ * Remove a face from the mesh and from each edges's face list
+ */
+
+static void deleteFace(BOP_Mesh *m, BOP_Face *face)
+{
+       BOP_Index l2 = face->getVertex(0);
+       BOP_Faces faces = m->getFaces();
+       for(int i = face->size(); i-- ; ) {
+               BOP_Indexs edges = m->getVertex(l2)->getEdges();
+               BOP_Index l1 = face->getVertex(i);
+               for(BOP_IT_Indexs it1 = edges.begin(); it1 != edges.end(); ++it1 ) {
+                       BOP_Edge *edge = m->getEdge(*it1);
+                       if( ( edge->getVertex1() == l1 && edge->getVertex2() == l2 ) ||
+                               ( edge->getVertex1() == l2 && edge->getVertex2() == l1 ) ) {
+                               BOP_Indexs ef = edge->getFaces();
+                               for(BOP_IT_Indexs it = ef.begin(); it != ef.end(); ++it ) {
+                                       if( m->getFace(*it) == face) {
+                                               edge->removeFace(*it);
+                                               break;
+                                       }
+                               }
+                               break;
+                       }
+               }
+               l2 = l1;
+       }
+       face->setTAG(BROKEN);
+}
+
+void BOP_Merge2::mergeVertex(BOP_Face3 *face, BOP_Index v1, BOP_Index v2)
+{
+       BOP_Index next, prev;
+       face->getNeighbours(v1,prev,next);
+
+       // if new vertex is not already in the tri, make a new tri
+       if( prev != v2 && next != v2 ) {
+               m_mesh->addFace( new BOP_Face3(prev,v2,next,
+                                       face->getPlane(),face->getOriginalFace()) );
+#ifdef DEBUG
+               cout << "mv3: add " << prev << "," << v2 << "," << next << endl;
+       } else {
+               cout << "mv3: vertex already in tri: doing nothing" << endl;
+#endif
+       }
+       deleteFace(m_mesh, face);
+}
+
+void BOP_Merge2::mergeVertex(BOP_Face4 *face, BOP_Index v1, BOP_Index v2)
+{
+       BOP_Index next, prev, opp;
+       face->getNeighbours(v1,prev,next,opp);
+
+       // if new vertex is already in the quad, replace quad with new tri
+       if( prev == v2 || next == v2 ) {
+               m_mesh->addFace( new BOP_Face3(prev,next,opp,
+                                       face->getPlane(),face->getOriginalFace()) );
+#ifdef DEBUG
+               cout << "mv4a: add " << prev << "," << next << "," << opp << endl;
+#endif
+       }
+       // otherwise make a new quad
+       else {
+               m_mesh->addFace( new BOP_Face4(prev,v2,next,opp,
+                                       face->getPlane(),face->getOriginalFace()) );
+#ifdef DEBUG
+               cout << "mv4b: add "<<prev<<","<<v2<<","<<next<<","<<opp<<endl;
+#endif
+       }
+       deleteFace(m_mesh, face);
+}
+
+// #define OLD_QUAD
+
+/** 
+ * Simplifies the mesh, merging the pairs of triangles that come frome the
+ * same original face and define a quad.
+ * @return true if a quad was added, false otherwise
+ */
+bool BOP_Merge2::createQuads()
+{
+  
+       BOP_Faces quads;
+       
+       // Get mesh faces
+       BOP_Faces faces = m_mesh->getFaces();
+       
+    // Merge mesh triangles
+       const BOP_IT_Faces facesIEnd = (faces.end()-1);
+       const BOP_IT_Faces facesJEnd = faces.end();
+       for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) {
+#ifdef OLD_QUAD
+               if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue;
+               for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) {
+                       if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 ||
+                               (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue;
+
+
+                       BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ);
+                       if (faceK != NULL) {
+                               // Set triangles to BROKEN
+                               deleteFace(m_mesh, *faceI);
+                               deleteFace(m_mesh, *faceJ);
+#ifdef DEBUG
+                       cout << "createQuad: del " << *faceI << endl;
+                       cout << "createQuad: del " << *faceJ << endl;
+                       cout << "createQuad: add " << faceK << endl;
+#endif
+                               quads.push_back(faceK);
+                               break;
+                       }
+               }
+#else
+               if ((*faceI)->getTAG() == BROKEN ) continue;
+               for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) {
+                       if ((*faceJ)->getTAG() == BROKEN ||
+                               (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue;
+
+                       BOP_Face *faceK = NULL;
+                       if((*faceI)->size() == 3) {
+                               if((*faceJ)->size() == 3)
+                                       faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ);
+                               else
+                                       faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face4*)*faceJ);
+                       } else {
+                               if((*faceJ)->size() == 3)
+                                       faceK = createQuad((BOP_Face3*)*faceJ,(BOP_Face4*)*faceI);
+                               else
+                                       faceK = createQuad((BOP_Face4*)*faceI,(BOP_Face4*)*faceJ);
+                       }
+
+                       if (faceK != NULL) {
+                               // Set triangles to BROKEN
+                               deleteFace(m_mesh, *faceI);
+                               deleteFace(m_mesh, *faceJ);
+#ifdef DEBUG
+                       cout << "createQuad: del " << *faceI << endl;
+                       cout << "createQuad: del " << *faceJ << endl;
+                       cout << "createQuad: add " << faceK << endl;
+#endif
+                               quads.push_back(faceK);
+                               break;
+                       }
+               }
+#endif
+       }
+
+    // Add quads to mesh
+       const BOP_IT_Faces quadsEnd = quads.end();
+       for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad);
+       return (quads.size() > 0);
+}
+
+/** 
+ * Returns a new quad (convex) from the merge of two triangles that share the
+ * vertex index v.
+ * @param faceI mesh triangle
+ * @param faceJ mesh triangle
+ * @param v vertex index shared by both triangles
+ * @return a new convex quad if the merge is possible
+ */
+BOP_Face* BOP_Merge2::createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ)
+{
+       // Test if both triangles share a vertex index
+       BOP_Index v;
+       unsigned int i;
+       for(i=0;i<3 ;i++) {
+               v = faceI->getVertex(i);
+               if( faceJ->containsVertex(v) ) break;
+       }
+       if (i == 3) return NULL;
+
+       BOP_Face *faceK = NULL;
+
+       // Get faces data
+       BOP_Index prevI, nextI, prevJ, nextJ;
+       faceI->getNeighbours(v,prevI,nextI);
+       faceJ->getNeighbours(v,prevJ,nextJ);
+       MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
+       MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
+       MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
+       MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
+       MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
+
+       // Quad test
+       if (prevI == nextJ) {
+               if (!BOP_collinear(vNextI,vertex,vPrevJ) && !BOP_collinear(vNextI,vPrevI,vPrevJ) &&
+                       BOP_convex(vertex,vNextI,vPrevI,vPrevJ)) {
+                               faceK = new BOP_Face4(v,nextI,prevI,prevJ,faceI->getPlane(),faceI->getOriginalFace());
+                               faceK->setTAG(faceI->getTAG());
+                               BOP_Index edge;
+                               m_mesh->getIndexEdge(v,prevI,edge);
+                               m_mesh->getVertex(v)->removeEdge(edge);
+                               m_mesh->getVertex(prevI)->removeEdge(edge);
+               }
+       }
+       else if (nextI == prevJ) {
+               if (!BOP_collinear(vPrevI,vertex,vNextJ) && !BOP_collinear(vPrevI,vNextI,vNextJ) &&
+                       BOP_convex(vertex,vNextJ,vNextI,vPrevI)) {
+                               faceK = new BOP_Face4(v,nextJ,nextI,prevI,faceI->getPlane(),faceI->getOriginalFace());
+                               faceK->setTAG(faceI->getTAG());
+                               BOP_Index edge;
+                               m_mesh->getIndexEdge(v,nextI,edge);
+                               m_mesh->getVertex(v)->removeEdge(edge);
+                               m_mesh->getVertex(nextI)->removeEdge(edge);
+                       }
+       }
+       return faceK;
+}
+
+/** 
+ * Returns a new quad (convex) from the merge of two triangles that share the
+ * vertex index v.
+ * @param faceI mesh triangle
+ * @param faceJ mesh triangle
+ * @param v vertex index shared by both triangles
+ * @return a new convex quad if the merge is possible
+ */
+BOP_Face* BOP_Merge2::createQuad(BOP_Face3 *faceI, BOP_Face4 *faceJ)
+{
+       // Test if triangle and quad share a vertex index
+       BOP_Index v;
+       unsigned int i;
+       for(i=0;i<3 ;i++) {
+               v = faceI->getVertex(i);
+               if( faceJ->containsVertex(v) ) break;
+       }
+       if (i == 3) return NULL;
+
+       BOP_Face *faceK = NULL;
+
+       // Get faces data
+       BOP_Index prevI, nextI, prevJ, nextJ, oppJ;
+       faceI->getNeighbours(v,prevI,nextI);
+       faceJ->getNeighbours(v,prevJ,nextJ,oppJ);
+
+       // Quad test
+       BOP_Index edge;
+       if (nextI == prevJ) {
+               if (prevI == nextJ) {   // v is in center
+                       faceK = new BOP_Face3(nextJ,oppJ,prevJ,faceI->getPlane(),faceI->getOriginalFace());
+                       faceK->setTAG(faceI->getTAG());
+                       m_mesh->getIndexEdge(v,prevI,edge);
+                       m_mesh->getVertex(v)->removeEdge(edge);
+                       m_mesh->getVertex(prevI)->removeEdge(edge);
+                       m_mesh->getIndexEdge(v,nextI,edge);
+                       m_mesh->getVertex(v)->removeEdge(edge);
+                       m_mesh->getVertex(nextI)->removeEdge(edge);
+                       freeVerts(v, m_mesh->getVertex(v));
+               } else if (prevI == oppJ) {     // nextI is in center
+                       faceK = new BOP_Face3(v,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace());
+                       faceK->setTAG(faceI->getTAG());
+                       m_mesh->getIndexEdge(v,nextI,edge);
+                       m_mesh->getVertex(v)->removeEdge(edge);
+                       m_mesh->getVertex(nextI)->removeEdge(edge);
+                       m_mesh->getIndexEdge(prevI,nextI,edge);
+                       m_mesh->getVertex(prevI)->removeEdge(edge);
+                       m_mesh->getVertex(nextI)->removeEdge(edge);
+                       freeVerts(nextI, m_mesh->getVertex(nextI));
+               }
+       } else if (nextI == oppJ && prevI == nextJ ) { // prevI is in center
+               faceK = new BOP_Face3(prevJ,v,oppJ,faceI->getPlane(),faceI->getOriginalFace());
+               faceK->setTAG(faceI->getTAG());
+               m_mesh->getIndexEdge(v,prevI,edge);
+               m_mesh->getVertex(v)->removeEdge(edge);
+               m_mesh->getVertex(prevI)->removeEdge(edge);
+               m_mesh->getIndexEdge(nextI,prevI,edge);
+               m_mesh->getVertex(nextI)->removeEdge(edge);
+               m_mesh->getVertex(prevI)->removeEdge(edge);
+               freeVerts(prevI, m_mesh->getVertex(prevI));
+       }
+       return faceK;
+}
+
+/** 
+ * Returns a new quad (convex) from the merge of two triangles that share the
+ * vertex index v.
+ * @param faceI mesh triangle
+ * @param faceJ mesh triangle
+ * @param v vertex index shared by both triangles
+ * @return a new convex quad if the merge is possible
+ */
+BOP_Face* BOP_Merge2::createQuad(BOP_Face4 *faceI, BOP_Face4 *faceJ)
+{
+       BOP_Face *faceK = NULL;
+       //
+       // Test if both quads share a vertex index
+       //
+       BOP_Index v;
+       unsigned int i;
+       for(i=0;i<4 ;i++) {
+               v = faceI->getVertex(i);
+               if( faceJ->containsVertex(v) ) break;
+       }
+       if (i == 3) return NULL;
+
+
+       // Get faces data
+       BOP_Index prevI, nextI, oppI, prevJ, nextJ, oppJ;
+       faceI->getNeighbours(v,prevI,nextI,oppI);
+       faceJ->getNeighbours(v,prevJ,nextJ,oppJ);
+
+       // Quad test
+       BOP_Index edge;
+       if (nextI == prevJ) {
+               if (prevI == nextJ) {   // v is in center
+                       faceK = new BOP_Face4(nextI,oppI,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace());
+                       faceK->setTAG(faceI->getTAG());
+                       m_mesh->getIndexEdge(v,prevI,edge);
+                       m_mesh->getVertex(v)->removeEdge(edge);
+                       m_mesh->getVertex(prevI)->removeEdge(edge);
+                       m_mesh->getIndexEdge(v,nextI,edge);
+                       m_mesh->getVertex(v)->removeEdge(edge);
+                       m_mesh->getVertex(nextI)->removeEdge(edge);
+                       freeVerts(v, m_mesh->getVertex(v));
+               } else if (oppI == oppJ) {      // nextI is in center
+                       faceK = new BOP_Face4(v,nextJ,oppJ,prevI,faceI->getPlane(),faceI->getOriginalFace());
+                       faceK->setTAG(faceI->getTAG());
+                       m_mesh->getIndexEdge(v,nextI,edge);
+                       m_mesh->getVertex(v)->removeEdge(edge);
+                       m_mesh->getVertex(nextI)->removeEdge(edge);
+                       m_mesh->getIndexEdge(prevI,nextI,edge);
+                       m_mesh->getVertex(prevI)->removeEdge(edge);
+                       m_mesh->getVertex(nextI)->removeEdge(edge);
+                       freeVerts(nextI, m_mesh->getVertex(nextI));
+               }
+       } else if (prevI == nextJ && oppI == oppJ) { // prevI is in center
+               faceK = new BOP_Face4(v,nextI,oppJ,prevJ,faceI->getPlane(),faceI->getOriginalFace());
+               faceK->setTAG(faceI->getTAG());
+               m_mesh->getIndexEdge(v,prevI,edge);
+               m_mesh->getVertex(v)->removeEdge(edge);
+               m_mesh->getVertex(prevI)->removeEdge(edge);
+               m_mesh->getIndexEdge(nextI,prevI,edge);
+               m_mesh->getVertex(nextI)->removeEdge(edge);
+               m_mesh->getVertex(prevI)->removeEdge(edge);
+               freeVerts(prevI, m_mesh->getVertex(prevI));
+       }
+       return faceK;
+}
+
+/**
+ * Returns if a index is inside a set of indexs.
+ * @param indexs set of indexs
+ * @param i index
+ * @return true if the index is inside the set, false otherwise
+ */
+bool BOP_Merge2::containsIndex(BOP_Indexs indexs, BOP_Index i)
+{
+  const BOP_IT_Indexs indexsEnd = indexs.end();
+       for(BOP_IT_Indexs it=indexs.begin();it!=indexsEnd;it++) {
+               if (*it == i) return true;
+       }
+       return false;
+}
+
+/**
+ * Creates a list of lists L1, L2, ... LN where
+ *   LX = mesh faces with vertex v that come from the same original face
+ * @param facesByOriginalFace list of faces lists
+ * @param v vertex index
+ */
+void BOP_Merge2::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Index v)
+{
+       // Get edges with vertex v
+
+       BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges();
+       const BOP_IT_Indexs edgeEnd = edgeIndexs.end();
+       for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) {    
+               // For each edge, add its no broken faces to the output list
+               BOP_Edge* edge = m_mesh->getEdge(*edgeIndex);
+               BOP_Indexs faceIndexs = edge->getFaces();
+               const BOP_IT_Indexs faceEnd = faceIndexs.end();
+               for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) {
+                       BOP_Face* face = m_mesh->getFace(*faceIndex);
+                       if (face->getTAG() != BROKEN) {
+                               bool found = false;
+                               // Search if we already have created a list for the 
+                               // faces that come from the same original face
+                               const BOP_IT_LFaces lfEnd = facesByOriginalFace.end();
+                               for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin();
+                               facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) {
+                                       if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) {
+                                               // Search that the face has not been added to the list before
+                                               for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) {
+                                                       if ((*facesByOriginalFaceX)[i] == face) {
+                                                               found = true;
+                                                               break;
+                                                       }
+                                               }
+                                               if (!found) {
+                                                       // Add the face to the list
+                                                 if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face);
+                                                 else facesByOriginalFaceX->push_back(face);
+                                                 found = true;
+                                               }
+                                               break;
+                                       }
+                               }
+                               if (!found) {
+                                       // Create a new list and add the current face
+                                       BOP_Faces facesByOriginalFaceX;
+                                       facesByOriginalFaceX.push_back(face);
+                                       facesByOriginalFace.push_back(facesByOriginalFaceX);
+                               }
+                       }
+               }
+       }
+}
+
+/**
+ * Creates a list of lists L1, L2, ... LN where
+ *   LX = mesh faces with vertex v that come from the same original face
+ *        and without any of the vertices that appear before v in vertices
+ * @param facesByOriginalFace list of faces lists
+ * @param vertices vector with vertices indexs that contains v
+ * @param v vertex index
+ */
+void BOP_Merge2::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v)
+{
+       // Get edges with vertex v
+       BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges();
+       const BOP_IT_Indexs edgeEnd = edgeIndexs.end();
+       for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) {    
+               // Foreach edge, add its no broken faces to the output list
+               BOP_Edge* edge = m_mesh->getEdge(*edgeIndex);
+               BOP_Indexs faceIndexs = edge->getFaces();
+               const BOP_IT_Indexs faceEnd = faceIndexs.end();
+               for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) {
+                       BOP_Face* face = m_mesh->getFace(*faceIndex);
+                       if (face->getTAG() != BROKEN) {
+                               // Search if the face contains any of the forbidden vertices
+                               bool found = false;
+                               for(BOP_IT_Indexs vertex = vertices.begin();*vertex!= v;vertex++) {
+                                       if (face->containsVertex(*vertex)) {
+                                               // face contains a forbidden vertex!
+                                               found = true;
+                                               break;
+                               }
+                       }
+                       if (!found) {
+                               // Search if we already have created a list with the 
+                               // faces that come from the same original face
+                         const BOP_IT_LFaces lfEnd = facesByOriginalFace.end();
+                               for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin();
+                                       facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) {
+                                       if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) {
+                                               // Search that the face has not been added to the list before
+                                               for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) {
+                                                       if ((*facesByOriginalFaceX)[i] == face) {
+                                                               found = true;
+                                                               break;
+                                                       }
+                                               }
+                                               if (!found) {
+                                                 // Add face to the list
+                                                 if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face);
+                                                 else facesByOriginalFaceX->push_back(face);
+                                                 found = true;
+                                               }
+                                               break;
+                                       }
+                               }
+                               if (!found) {
+                                       // Create a new list and add the current face
+                                       BOP_Faces facesByOriginalFaceX;
+                                       facesByOriginalFaceX.push_back(face);
+                                       facesByOriginalFace.push_back(facesByOriginalFaceX);
+                               }
+                       }
+               }
+       }
+       }
+}
+
+#endif  /* BOP_NEW_MERGE */
diff --git a/intern/boolop/intern/BOP_Merge2.h b/intern/boolop/intern/BOP_Merge2.h
new file mode 100644 (file)
index 0000000..1e5945a
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * ***** 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef BOP_MERGE2_H
+#define BOP_MERGE2_H
+
+#include "BOP_Misc.h"
+
+#ifdef BOP_NEW_MERGE
+
+#include "BOP_Mesh.h"
+#include "BOP_Tag.h"
+#include "BOP_MathUtils.h"
+#include "MEM_SmartPtr.h"
+
+typedef vector< BOP_Faces > BOP_LFaces;
+typedef vector< BOP_Faces >::iterator BOP_IT_LFaces;
+
+class BOP_Merge2 {
+       private:
+               BOP_Mesh* m_mesh;
+               BOP_Index m_firstVertex;
+               static BOP_Merge2 SINGLETON;
+
+               BOP_Merge2() {};
+               bool mergeFaces();
+               bool mergeFaces(BOP_Indexs &mergeVertices);
+               bool mergeFaces(BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v);
+               bool mergeFaces(BOP_Faces &faces, BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v);
+               BOP_Face *mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v);
+               BOP_Face *mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Indexs &pending, BOP_Index v);
+               BOP_Face *mergeFaces(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v);
+               BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Index v);
+               BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Indexs &pending, BOP_Index v);
+               BOP_Face *mergeFaces(BOP_Face4 *faceI, BOP_Face4 *faceJ, BOP_Indexs &pending, BOP_Index v);
+               bool createQuads();
+               bool containsIndex(BOP_Indexs indexs, BOP_Index index);
+               void getFaces(BOP_LFaces &facesByOriginalFace, BOP_Index v);
+               void getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v);
+               BOP_Face *createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ);
+               BOP_Face *createQuad(BOP_Face3 *faceI, BOP_Face4 *faceJ);
+               BOP_Face *createQuad(BOP_Face4 *faceI, BOP_Face4 *faceJ);
+
+               bool mergeVertex(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v,
+                               BOP_Indexs &mergeVertices);
+               bool mergeVertex(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v,
+                               BOP_Indexs &pending, BOP_Faces &oldFaces, BOP_Faces &newFaces );
+               BOP_Face *find3Neighbor(BOP_Face *faceI, BOP_Face *faceJ,
+                               BOP_Index X, BOP_Index I, BOP_Index P, BOP_Index N );
+               BOP_Face *find4Neighbor(BOP_Face *faceI, BOP_Face *faceJ,
+                               BOP_Index X, BOP_Index I, BOP_Index P, BOP_Index N,
+                       BOP_Face **faceL, BOP_Index &O);
+               BOP_Face3 *collapse(BOP_Face4 *faceC, BOP_Index X);
+               void mergeFaces(BOP_Face *A, BOP_Face *B, BOP_Index X,
+                       BOP_Index I, BOP_Index N, BOP_Index P, BOP_Faces &newFaces );
+               void freeVerts(BOP_Index v, BOP_Vertex *vert);
+
+               void mergeVertex(BOP_Faces&, BOP_Index, BOP_Index);
+               void mergeVertex(BOP_Face3 *, BOP_Index, BOP_Index);
+               void mergeVertex(BOP_Face4 *, BOP_Index, BOP_Index);
+               void cleanup( void );
+
+       public:
+
+               static BOP_Merge2 &getInstance() {
+                       return SINGLETON;
+               }
+
+               void mergeFaces(BOP_Mesh *m, BOP_Index v);
+};
+
+void dumpmesh(BOP_Mesh *, bool);
+
+#endif /* BOP_NEW_MERGE2 */
+#endif
index 5659cd6..075884a 100644 (file)
@@ -449,6 +449,13 @@ bool BOP_Mesh::getIndexEdge(BOP_Index v1, BOP_Index v2, BOP_Index &e)
                        printf ("found edge (%d %d)\n",v1,v2);
 #endif
                        e = edge->index;
+#ifdef BOP_NEW_MERGE
+                       if( m_edges[e]->getUsed() == false ) {
+                               m_edges[e]->setUsed(true);
+                               m_vertexs[v1]->addEdge(e);
+                               m_vertexs[v2]->addEdge(e);
+                       }
+#endif
                        return true;
                }
 #ifdef HASH_PRINTF_DEBUG
@@ -794,7 +801,8 @@ bool BOP_Mesh::isClosedMesh()
 }
 
 
-/** ***************************************************************************
+#ifdef BOP_DEBUG
+/******************************************************************************
  * DEBUG METHODS                                                              * 
  * This functions are used to test the mesh state and debug program errors.   *
  ******************************************************************************/
@@ -1075,3 +1083,4 @@ void BOP_Mesh::updatePlanes()
        }
 }
 
+#endif
index 9abff52..46c8fa5 100644 (file)
@@ -1,10 +1,3 @@
-/*
- * TEMPORARY defines to enable hashing support
- */
-
-#define HASH(x) ((x) >> 5)             /* each "hash" covers 32 indices */
-// #define HASH_PRINTF_DEBUG   /* uncomment to enable debug output */
-
 /**
  *
  * $Id$
diff --git a/intern/boolop/intern/BOP_Misc.h b/intern/boolop/intern/BOP_Misc.h
new file mode 100644 (file)
index 0000000..d021579
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ *
+ * $Id: BOP_Misc.h 14444 2008-04-16 22:40:48Z khughes $
+ *
+ * ***** 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Ken Hughes
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+/*
+ * This file contains various definitions used across the modules
+ */
+
+/*
+ * define operator>> for faces, edges and vertices, and also add some
+ * debugging functions for displaying various internal data structures
+ */
+
+// #define     BOP_DEBUG
+
+#define HASH(x) ((x) >> 5)             /* each "hash" covers 32 indices */
+// #define HASH_PRINTF_DEBUG   /* uncomment to enable debug output */
+
+/*
+ * temporary: control which method is used to merge final triangles and
+ * quads back together after an operation.  If both methods are included,
+ * the "rt" debugging button on the Scene panel (F10) is used to control
+ * which is active.  Setting it to 100 enables the original method, any
+ * other value enables the new method.
+ */
+
+#define BOP_ORIG_MERGE                 /* include original merge code */
+#define BOP_NEW_MERGE                  /* include new merge code */
index 705f488..ead10fa 100644 (file)
@@ -39,7 +39,7 @@
 #define OUTON_TAG        0x11  // Above and on the plane  
 #define UNCLASSIFIED_TAG 0x0F  // Expecting to be classified
 
-#define PHANTOM_TAG      0x0C  // Phantom face
+#define PHANTOM_TAG      0x0C  // Phantom face: verts form collinear triangle
 #define OVERLAPPED_TAG   0x0D  // Overlapped face
 #define BROKEN_TAG       0x0B  // Splitted and unused ... 
 
index a429c26..edb53ea 100644 (file)
@@ -89,3 +89,22 @@ bool BOP_Vertex::containsEdge(BOP_Index i)
        
        return false;
 }
+
+#ifdef BOP_DEBUG
+/**
+ * Implements operator <<.
+ */
+#include <iomanip>
+
+ostream &operator<<(ostream &stream, BOP_Vertex *v)
+{
+       char aux[20];
+       BOP_stringTAG(v->m_tag,aux);
+       MT_Point3 point = v->getPoint();
+       stream << setprecision(6) << showpoint << fixed;
+       stream << "Vertex[" << point[0] << "," << point[1] << ",";
+       stream << point[2] << "] ("  <<  aux  <<  ")";
+       return stream;
+}
+#endif
+
index 3a9895d..18b2f16 100644 (file)
@@ -31,6 +31,7 @@
 #include "BOP_Tag.h"
 #include "BOP_Indexs.h"
 #include "MT_Point3.h"
+#include "BOP_Misc.h"
 
 class BOP_Vertex 
 {
@@ -52,6 +53,10 @@ public:
        inline MT_Point3 getPoint() const { return m_point;};
        inline BOP_TAG getTAG() { return m_tag;};
        inline void setTAG(BOP_TAG t) { m_tag = t;};
+#ifdef BOP_DEBUG
+       friend ostream &operator<<(ostream &stream, BOP_Vertex *v);
+#endif
+
 };
 
 #endif
index 04d964b..6ad16de 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 226bedb..153d9a9 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 b020d88..edf0faf 100644 (file)
                        <File
                                RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderMouseDevice.cpp">
                        </File>
-                       <File
-                               RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderPolyMaterial.cpp">
-                       </File>
                        <File
                                RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderRenderTools.cpp">
                        </File>
                        <File
                                RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderMouseDevice.h">
                        </File>
-                       <File
-                               RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderPolyMaterial.h">
-                       </File>
                        <File
                                RelativePath="..\..\..\source\gameengine\BlenderRoutines\KX_BlenderRenderTools.h">
                        </File>
index c723efb..a48d065 100644 (file)
@@ -14,7 +14,7 @@ __url__ = ("blender", "blenderartists.org",
 __version__ = "2007/04/27"
 
 __bpydoc__ = """\
-"DEFORM to RVK2" copies deform data (except EDGESPLIT,DECIMATE,SUBSURF,BOOLEAN, 
+"DEFORM to RVK2" copies deform data (except EDGESPLIT,DECIMATE,SUBSURF,BOOLEAN,
 BUILD,MIRROR,ARRAY) of the active object to the RVK (relative vertex key) of
 the other selected object.
 
@@ -25,7 +25,7 @@ key.
 The new version of this scrit (Blender 2.43) manages the modifier changes.
 There are a lot of modifiers but only the ones which just deforms the shape
 can be used : LATTICE, CURVE, WAVE, ARMATURE. You can unset these modifiers
-from the script. 
+from the script.
 
 Usage:
 
@@ -35,7 +35,7 @@ the 3d View.  If the active object has subsurf turned on and nonzero subdiv
 level, the script will ask if it should change that.  Before copying data to
 the rvk it will also ask whether it should replace or add a new vertex group.
 
+
 """
 
 #----------------------------------------------
@@ -70,7 +70,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 """
 # Copy the rvk (1, or armature, lattice, or
 # any mesh deformation except surface
@@ -83,7 +83,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 # download the script :
 # http://jmsoler.free.fr/util/blenderfile/py/rvk1_torvk2.py
 # Communicate upon problems or errors:
-# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender 
+# http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
 #----------------------------------------------
 # Page officielle :
 #   http://jmsoler.free.fr/util/blenderfile/py/rvk1_torvk2.py
@@ -101,22 +101,22 @@ def Value(t):
        exec "t=Modifier.Types.%s"%t
        return t
 
-def deform2rvk():  
+def deform2rvk():
        POSSMOD_list=['EDGESPLIT',
                                                                'DECIMATE',
-                                                               'SUBSURF', 
-                                                               'BOOLEAN', 
+                                                               'SUBSURF',
+                                                               'BOOLEAN',
                                                                'BUILD',
-                                                               'MIRROR', 
+                                                               'MIRROR',
                                                                'ARRAY']
 
        AUTHMOD_list=['LATTICE',
-                     'CURVE', 
+                     'CURVE',
                      'WAVE',
                      'ARMATURE']
 
        MODIFIERS=0
-       
+
        BMOD=[['Possible Modifiers'],
                                ['Allowed Modifiers']]
 
@@ -129,8 +129,8 @@ def deform2rvk():
                # =============================================================
                # must be 2 meshes ============================================
                # =============================================================
-               if RVK1.getType()=='Mesh' and RVK2.getType()=='Mesh': 
-                       FRAME=Blender.Get('curframe') 
+               if RVK1.getType()=='Mesh' and RVK2.getType()=='Mesh':
+                       FRAME=Blender.Get('curframe')
                        DATA2=RVK2.getData()
                        if DEBUG: print DATA2.getKey()
                        # ============================================================
@@ -151,7 +151,7 @@ def deform2rvk():
                                        # ===  Bloc Menu Modifiers ===1 doc =================
                                        # ===================================================
                                        m=0
-                                       for mod in  MODRVK1: 
+                                       for mod in  MODRVK1:
                                                if DEBUG: print mod.type
                                                if mod.type in POSSMOD:
                                                        BMOD[0].append([Draw.Create(0),mod.type,
@@ -183,7 +183,7 @@ def deform2rvk():
                                        retval = Blender.Draw.PupBlock("MESH 2 RVK", block)
                                        # ===================================================
                                        # ===  unset Modifiers  =============================
-                                       # ===================================================   
+                                       # ===================================================
                                        for     B in BMOD[0][1:]:
                                                if DEBUG: print B[2]
                                                MODRVK1[B[2]][Modifier.Settings.RENDER]=0
@@ -193,12 +193,12 @@ def deform2rvk():
                                        # ===================================================
                                        # ===  update Modifiers =============================
                                        # ===================================================
-                                       RVK1.makeDisplayList()                                                                  
+                                       #RVK1.makeDisplayList()
                                # =======================================================
                                # ===  get deformed mesh ================================
                                # =======================================================
                                RVK1NAME=Object.GetSelected()[0].getName()
-                               meshrvk1=NMesh.GetRawFromObject(RVK1NAME)  
+                               meshrvk1=NMesh.GetRawFromObject(RVK1NAME)
                                if DEBUG: print len(meshrvk1.verts)
                                # =======================================================
                                # ===  get normal mesh for vertex group =================
@@ -209,18 +209,18 @@ def deform2rvk():
                                # =======================================================
                                DATA2=RVK2.getData()
                                if DEBUG: print len(meshrvk1.verts)
-                               if DEBUG: print len(DATA2.verts)                                                        
+                               if DEBUG: print len(DATA2.verts)
                                # ========================================================
                                # ===== is there the same number of vertices =============
                                # ========================================================
-                               if len(meshrvk1.verts)==len(DATA2.verts): 
-                                       name = "Do you want to replace or add vertex groups ? %t| YES %x1| NO ? %x2 " 
+                               if len(meshrvk1.verts)==len(DATA2.verts):
+                                       name = "Do you want to replace or add vertex groups ? %t| YES %x1| NO ? %x2 "
                                        result = Draw.PupMenu(name)
-                                       if result==1:       
+                                       if result==1:
                                                # =====================================================
                                                # ===== Do we save vertex groups ?  ===================
                                                # =====================================================
-                                               GROUPNAME2=DATA2.getVertGroupNames() 
+                                               GROUPNAME2=DATA2.getVertGroupNames()
                                                if len(GROUPNAME2)!=0:
                                                        for GROUP2 in GROUPNAME2:
                                                                DATA2.removeVertGroup(GROUP2)
@@ -233,11 +233,11 @@ def deform2rvk():
                                        # ===== now copy the vertices coords =====================
                                        # ========================================================
                                        for v in meshrvk1.verts:
-                                               i= meshrvk1.verts.index(v) 
+                                               i= meshrvk1.verts.index(v)
                                                v1=DATA2.verts[i]
                                                for n in [0,1,2]:
                                                        v1.co[n]=v.co[n]
-                                       DATA2.update() 
+                                       DATA2.update()
                                        DATA2.insertKey(FRAME,'relative')
                                        DATA2.update()
                                        RVK2.makeDisplayList()
@@ -251,23 +251,23 @@ def deform2rvk():
                                                        if not B[1]:
                                                                MODRVK1[B[2]][Modifier.Settings.RENDER]|=B[-2]
                                else:
-                                       name = "Meshes Objects must the same number of vertices %t| Ok. %x1" 
+                                       name = "Meshes Objects must the same number of vertices %t| Ok. %x1"
                                        result = Draw.PupMenu(name)
                                        return
                        else:
-                               name = "Second Object must have  at least a shape key %t| Ok. %x1" 
+                               name = "Second Object must have  at least a shape key %t| Ok. %x1"
                                result = Draw.PupMenu(name)
                                return
-               else:   
-                       name = "Object must be Meshes %t| Ok. %x1" 
+               else:
+                       name = "Object must be Meshes %t| Ok. %x1"
                        result = Draw.PupMenu(name)
-                       return 
+                       return
        else :
-               name = "At least 2 Meshes as to be selected %t| Ok. %x1" 
+               name = "At least 2 Meshes as to be selected %t| Ok. %x1"
                result = Draw.PupMenu(name)
                return
-       Blender.Redraw()  
+       Blender.Redraw()
 EDITMODE=Blender.Window.EditMode()
 Blender.Window.EditMode(0)
 deform2rvk()
-Blender.Window.EditMode(EDITMODE)
+Blender.Window.EditMode(EDITMODE)
\ No newline at end of file
index f61b300..7dc10c5 100644 (file)
@@ -437,5 +437,7 @@ void weight_to_rgb(float input, float *fr, float *fg, float *fb);
 /* determines required DerivedMesh data according to view and edit modes */
 CustomDataMask get_viewedit_datamask();
 
+void DM_add_tangent_layer(DerivedMesh *dm);
+
 #endif
 
index f76cdbc..d951c84 100644 (file)
@@ -41,7 +41,7 @@ struct ListBase;
 struct MemFile;
 
 #define BLENDER_VERSION                        246
-#define BLENDER_SUBVERSION             0
+#define BLENDER_SUBVERSION             1
 
 #define BLENDER_MINVERSION             245
 #define BLENDER_MINSUBVERSION  15
index 2d7d0e9..2274c54 100644 (file)
@@ -46,6 +46,7 @@ struct ID;
 typedef union {
        int i;
        float f;
+       double d;
        char *str;
        struct ID *id;
        struct {
index 739027f..1b07ce5 100644 (file)
 #ifndef BKE_SHRINKWRAP_H
 #define BKE_SHRINKWRAP_H
 
+/* mesh util */
+//TODO move this somewhere else
+#include "BKE_customdata.h"
+struct DerivedMesh;
+struct Object;
+struct DerivedMesh *object_get_derived_final(struct Object *ob, CustomDataMask dataMask);
+
 /* bitset stuff */
 //TODO: should move this to other generic lib files?
 typedef char* BitSet;
index 78a8f60..fade0f8 100644 (file)
@@ -62,6 +62,7 @@ struct Tex *copy_texture(struct Tex *tex);
 void make_local_texture(struct Tex *tex);
 void autotexname(struct Tex *tex);
 struct Tex *give_current_texture(struct Object *ob, int act);
+struct Tex *give_current_world_texture(void);
 
 struct TexMapping *add_mapping(void);
 void init_mapping(struct TexMapping *texmap);
index c913820..3ad11a6 100644 (file)
@@ -1,4 +1,3 @@
-
 /**
  * $Id$
  *
@@ -355,7 +354,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 4d3f914..67cf89d 100644 (file)
@@ -59,6 +59,7 @@
 #include "BLI_edgehash.h"
 #include "BLI_editVert.h"
 #include "BLI_linklist.h"
+#include "BLI_memarena.h"
 
 #include "BKE_cdderivedmesh.h"
 #include "BKE_customdata.h"
@@ -2844,6 +2845,127 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo
        return numleft;
 }
 
+void DM_add_tangent_layer(DerivedMesh *dm)
+{
+       /* mesh vars */
+       MTFace *mtface, *tf;
+       MFace *mface, *mf;
+       MVert *mvert, *v1, *v2, *v3, *v4;
+       MemArena *arena= NULL;
+       VertexTangent **vtangents= NULL;
+       float (*orco)[3]= NULL, (*tangent)[3];
+       float *uv1, *uv2, *uv3, *uv4, *vtang;
+       float fno[3], tang[3], uv[4][2];
+       int i, j, len, mf_vi[4], totvert, totface;
+
+       if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
+               return;
+
+       /* check we have all the needed layers */
+       totvert= dm->getNumVerts(dm);
+       totface= dm->getNumFaces(dm);
+
+       mvert= dm->getVertArray(dm);
+       mface= dm->getFaceArray(dm);
+       mtface= dm->getFaceDataArray(dm, CD_MTFACE);
+
+       if(!mtface) {
+               orco= dm->getVertDataArray(dm, CD_ORCO);
+               if(!orco)
+                       return;
+       }
+       
+       /* create tangent layer */
+       DM_add_face_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
+       tangent= DM_get_face_data_layer(dm, CD_TANGENT);
+       
+       /* allocate some space */
+       arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+       BLI_memarena_use_calloc(arena);
+       vtangents= MEM_callocN(sizeof(VertexTangent*)*totvert, "VertexTangent");
+       
+       /* sum tangents at connected vertices */
+       for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++) {
+               v1= &mvert[mf->v1];
+               v2= &mvert[mf->v2];
+               v3= &mvert[mf->v3];
+
+               if (mf->v4) {
+                       v4= &mvert[mf->v4];
+                       CalcNormFloat4(v4->co, v3->co, v2->co, v1->co, fno);
+               }
+               else {
+                       v4= NULL;
+                       CalcNormFloat(v3->co, v2->co, v1->co, fno);
+               }
+               
+               if(mtface) {
+                       uv1= tf->uv[0];
+                       uv2= tf->uv[1];
+                       uv3= tf->uv[2];
+                       uv4= tf->uv[3];
+               }
+               else {
+                       uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
+                       spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]);
+                       spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]);
+                       spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]);
+                       if(v4)
+                               spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]);
+               }
+               
+               tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang);
+               sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
+               sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2);
+               sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
+               
+               if(mf->v4) {
+                       v4= &mvert[mf->v4];
+                       
+                       tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang);
+                       sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
+                       sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
+                       sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4);
+               }
+       }
+       
+       /* write tangent to layer */
+       for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) {
+               len= (mf->v4)? 4 : 3; 
+               
+               if(mtface) {
+                       uv1= tf->uv[0];
+                       uv2= tf->uv[1];
+                       uv3= tf->uv[2];
+                       uv4= tf->uv[3];
+               }
+               else {
+                       uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
+                       spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]);
+                       spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]);
+                       spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]);
+                       if(len==4)
+                               spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]);
+               }
+               
+               mf_vi[0]= mf->v1;
+               mf_vi[1]= mf->v2;
+               mf_vi[2]= mf->v3;
+               mf_vi[3]= mf->v4;
+               
+               for(j=0; j<len; j++) {
+                       vtang= find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]);
+
+                       VECCOPY(tangent[j], vtang);
+                       Normalize(tangent[j]);
+               }
+       }
+       
+       BLI_memarena_free(arena);
+       MEM_freeN(vtangents);
+}
+
+
 /* ************************* fluidsim bobj file handling **************************** */
 
 #ifndef DISABLE_ELBEEM
index 6dfb775..5b3cec2 100644 (file)
@@ -1547,7 +1547,7 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f
 {
        Cloth *cloth=NULL;
        BVHTree *cloth_bvh=NULL;
-       long i=0, numfaces = 0, numverts = 0;
+       int i=0, numfaces = 0, numverts = 0;
        int rounds = 0; // result counts applied collisions; ic is for debug output;
        ClothVertex *verts = NULL;
        int ret = 0, ret2 = 0;
index 0685017..93ba30f 100644 (file)
@@ -40,6 +40,7 @@
 
 #include "DNA_armature_types.h"
 #include "DNA_constraint_types.h"
+#include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_action_types.h"
 #include "DNA_curve_types.h"
@@ -63,6 +64,7 @@
 #include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_idprop.h"
+#include "BKE_shrinkwrap.h"
 
 
 #include "BPY_extern.h"
@@ -457,7 +459,6 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
                                                        Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
                                                        VECCOPY(offs_bone[3], pchan->bone->head);
                                                        offs_bone[3][1]+= pchan->bone->parent->length;
-                                                       
                                                        if (pchan->bone->flag & BONE_HINGE) {
                                                                /* pose_mat = par_pose-space_location * chan_mat */
                                                                float tmat[4][4];
@@ -558,8 +559,8 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
        if (dgroup < 0) return;
        
        /* get DerivedMesh */
-       if (G.obedit && G.editMesh) {
-               /* we are in editmode, so get a special derived mesh */
+       if ((G.obedit == ob) && (G.editMesh)) {
+               /* target is in editmode, so get a special derived mesh */
                dm = CDDM_from_editmesh(G.editMesh, ob->data);
        }
        else {
@@ -3228,6 +3229,140 @@ static bConstraintTypeInfo CTI_TRANSFORM = {
        transform_evaluate /* evaluate */
 };
 
+/* ---------- Shrinkwrap Constraint ----------- */
+static void shrinkwrap_new_data (void *cdata)
+{
+       bShrinkwrapConstraint *data= (bShrinkwrapConstraint *)cdata;
+
+       data->target = NULL;
+       data->dist = 0.0f;
+       data->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE;
+}
+
+static int shrinkwrap_get_tars (bConstraint *con, ListBase *list)
+{
+       if (con && list) {
+               bShrinkwrapConstraint *data = con->data;
+               bConstraintTarget *ct;
+               
+               SINGLETARGETNS_GET_TARS(con, data->target, ct, list)
+               
+               return 1;
+       }
+       
+       return 0;
+}
+
+static void shrinkwrap_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+       if (con && list) {
+               bShrinkwrapConstraint *data = con->data;
+               bConstraintTarget *ct= list->first;
+               
+               SINGLETARGETNS_FLUSH_TARS(con, data->target, ct, list, nocopy)
+       }
+}
+
+static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+       if (ct)
+               Mat4One(ct->matrix);
+}
+
+static void shrinkwrap_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+       bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
+       bConstraintTarget *ct = targets->first;
+       
+       if( VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH) )
+       {
+               float co[3] = {0.0f, 0.0f, 0.0f};
+               float no[3] = {0.0f, 0.0f, 1.0f};
+               float dist;
+
+               SpaceTransform transform;
+               DerivedMesh *target = CDDM_copy( object_get_derived_final(ct->tar, CD_MASK_BAREMESH) );
+               BVHTreeRayHit hit;
+               BVHTreeNearest nearest;
+
+               //TODO
+               //Its stupid to create a bvhtree.. if we are only going to project one vertex
+               //But lets do it this way.. (so that in future maybe bvhtree gets a cache system and then the tree would already be build)
+               BVHTreeFromMesh treeData;
+               memset( &treeData, 0, sizeof(treeData) );
+
+               nearest.index = -1;
+               nearest.dist = 100000.0f; //TODO should use FLT_MAX.. but normal projection doenst yet supports it
+
+               if(target != NULL)
+               {
+
+                       space_transform_from_matrixs(&transform, cob->matrix, ct->matrix);
+
+                       space_transform_apply(&transform, co);
+                       space_transform_apply_normal(&transform, no);
+
+
+                       switch(scon->shrinkType)
+                       {
+                               case MOD_SHRINKWRAP_NEAREST_SURFACE:
+                                       if(bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6) == NULL) return;
+                                       BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
+                                       VECCOPY(co, nearest.co);
+                                       
+                                       dist = VecLenf(co, nearest.co);
+                                       VecLerpf(co, co, nearest.co, (dist - scon->dist)/dist); //linear interpolation
+                               break;
+
+                               case MOD_SHRINKWRAP_NEAREST_VERTEX:
+                                       if(bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6) == NULL) return;
+                                       BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
+                                       VECCOPY(co, nearest.co);
+
+                                       dist = VecLenf(co, nearest.co);
+                                       VecLerpf(co, co, nearest.co, (dist - scon->dist)/dist); //linear interpolation
+                               break;
+
+                               case MOD_SHRINKWRAP_NORMAL:
+                                       if(bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6) == NULL) return;
+                                       if(normal_projection_project_vertex(0, co, no, &transform, treeData.tree, &hit, treeData.raycast_callback, &treeData) == FALSE)
+                                               return;
+
+                                       VECCOPY(co, hit.co);
+                               break;
+                       }
+
+                       space_transform_invert(&transform, co);
+                       VECADD(cob->matrix[3], cob->matrix[3], co);
+
+
+                       if(treeData.tree)
+                               BLI_bvhtree_free(treeData.tree);
+
+                       target->release(target);
+               }
+               
+
+       }
+}
+
+static bConstraintTypeInfo CTI_SHRINKWRAP = {
+       CONSTRAINT_TYPE_SHRINKWRAP, /* type */
+       sizeof(bShrinkwrapConstraint), /* size */
+       "Shrinkwrap", /* name */
+       "bShrinkwrapConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       NULL, /* copy data */
+       shrinkwrap_new_data, /* new data */
+       shrinkwrap_get_tars, /* get constraint targets */
+       shrinkwrap_flush_tars, /* flush constraint targets */
+       shrinkwrap_get_tarmat, /* get a target matrix */
+       shrinkwrap_evaluate /* evaluate */
+};
+
+
+
 /* ************************* Constraints Type-Info *************************** */
 /* All of the constraints api functions use bConstraintTypeInfo structs to carry out
  * and operations that involve constraint specifc code.
@@ -3259,6 +3394,7 @@ static void constraints_init_typeinfo () {
        constraintsTypeInfo[17]= &CTI_RIGIDBODYJOINT;   /* RigidBody Constraint */
        constraintsTypeInfo[18]= &CTI_CLAMPTO;                  /* ClampTo Constraint */        
        constraintsTypeInfo[19]= &CTI_TRANSFORM;                /* Transformation Constraint */
+       constraintsTypeInfo[20]= &CTI_SHRINKWRAP;               /* Shrinkwrap Constraint */
 }
 
 /* This function should be used for getting the appropriate type-info when only
index 501293e..9012adb 100644 (file)
@@ -532,13 +532,14 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
        {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
        {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL},
        {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL},
-       {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol} 
+       {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol},
+       {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}
 };
 
 const char *LAYERTYPENAMES[CD_NUMTYPES] = {
        "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace",
        "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty",
-       "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", "CDMloopCol"};
+       "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent"};
 
 const CustomDataMask CD_MASK_BAREMESH =
        CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE;
@@ -552,7 +553,7 @@ const CustomDataMask CD_MASK_EDITMESH =
 const CustomDataMask CD_MASK_DERIVEDMESH =
        CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
        CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
-       CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO;
+       CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT;
 const CustomDataMask CD_MASK_BMESH = 
        CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
 const CustomDataMask CD_MASK_FACECORNERS =
index 2ef2f3a..b16f525 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 2898dca..553107d 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 9005db1..d5b5ab6 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 37804bf..ad13922 100644 (file)
@@ -53,6 +53,7 @@
 #include "DNA_world_types.h"
 #include "DNA_brush_types.h"
 #include "DNA_node_types.h"
+#include "DNA_scene_types.h"
 
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
@@ -731,7 +732,7 @@ Tex *give_current_texture(Object *ob, int act)
        bNode *node;
        
        if(ob==0) return 0;
-       if(ob->totcol==0) return 0;
+       if(ob->totcol==0 && !(ob->type==OB_LAMP)) return 0;
        
        if(ob->type==OB_LAMP) {
                la=(Lamp *)ob->data;
@@ -775,6 +776,18 @@ Tex *give_current_texture(Object *ob, int act)
        return tex;
 }
 
+Tex *give_current_world_texture(void)
+{
+       MTex *mtex = 0;
+       Tex *tex = 0;
+       
+       if(!(G.scene->world)) return 0;
+       
+       mtex= G.scene->world->mtex[(int)(G.scene->world->texact)];
+       if(mtex) tex= mtex->tex;
+       
+       return tex;
+}
 
 /* ------------------------------------------------------------------------- */
 
index a31c769..c1edb7d 100644 (file)
@@ -2535,11 +2535,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 8b979f9..74f152a 100644 (file)
@@ -405,7 +405,7 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
                lcode = charcode;
        }
        
-       err = FT_Set_Charmap( face, (FT_CharMap) FT_ENCODING_UNICODE );
+       err = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
 
        return vfd;     
 }
index 090b1d7..ad19cde 100644 (file)
@@ -1347,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]);
+                       }
                }
        }
 }
@@ -1384,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;
        }
 }
@@ -4161,15 +4185,6 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                        link_gpencil(fd, sseq->gpd);
                                }
                        }
-                       else if(sl->spacetype==SPACE_ACTION) {
-                               SpaceAction *sact= (SpaceAction *)sl;
-                               
-                               /* WARNING: action-editor doesn't have it's own gpencil data! 
-                                * so only adjust pointer, but DON'T LINK
-                                */
-                               if (sact->gpd) 
-                                       sact->gpd= newdataadr(fd, sact->gpd);
-                       }
                }
 
                sa->v1= newdataadr(fd, sa->v1);
@@ -4855,6 +4870,49 @@ void idproperties_fix_group_lengths(ListBase idlist)
        }
 }
 
+void alphasort_version_246(FileData *fd, Library *lib, Mesh *me)
+{
+       Material *ma;
+       MFace *mf;
+       MTFace *tf;
+       int a, b, texalpha;
+
+       /* verify we have a tface layer */
+       for(b=0; b<me->fdata.totlayer; b++)
+               if(me->fdata.layers[b].type == CD_MTFACE)
+                       break;
+       
+       if(b == me->fdata.totlayer)
+               return;
+
+       /* if we do, set alpha sort if the game engine did it before */
+       for(a=0, mf=me->mface; a<me->totface; a++, mf++) {
+               if(mf->mat_nr < me->totcol) {
+                       ma= newlibadr(fd, lib, me->mat[mf->mat_nr]);
+                       texalpha = 0;
+
+                       for(b=0; ma && b<MAX_MTEX; b++)
+                               if(ma->mtex && ma->mtex[b] && ma->mtex[b]->mapto & MAP_ALPHA)
+                                       texalpha = 1;
+               }
+               else {
+                       ma= NULL;
+                       texalpha = 0;
+               }
+
+               for(b=0; b<me->fdata.totlayer; b++) {
+                       if(me->fdata.layers[b].type == CD_MTFACE) {
+                               tf = ((MTFace*)me->fdata.layers[b].data) + a;
+
+                               tf->mode &= ~TF_ALPHASORT;
+                               if(ma && (ma->mode & MA_ZTRA))
+                                       if(ELEM(tf->transp, TF_ALPHA, TF_ADD) || (texalpha && (tf->transp != TF_CLIP)))
+                                               tf->mode |= TF_ALPHASORT;
+                       }
+               }
+       }
+}
+
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
        /* WATCH IT!!!: pointers from libdata have not been converted */
@@ -7699,8 +7757,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        }
 
        /* sun/sky */
-       if ((main->versionfile < 246) ){
+       if(main->versionfile < 246) {
                Lamp *la;
+
                for(la=main->lamp.first; la; la= la->id.next) {
                        la->sun_effect_type = 0;
                        la->horizon_brightness = 1.0;
@@ -7716,6 +7775,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
+       if(main->versionfile <= 246 && main->subversionfile < 1){
+               Mesh *me;
+
+               for(me=main->mesh.first; me; me= me->id.next)
+                       alphasort_version_246(fd, lib, me);
+       }
+
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
 
index b59dd85..73abf36 100644 (file)
@@ -533,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;
index d0ebd09..eb749cf 100644 (file)
@@ -38,6 +38,15 @@ struct bGPdata;
 struct bGPDlayer;
 struct bGPDframe;
 
+/* ------------- Grease-Pencil Helpers -------------- */
+
+/* Temporary 'Stroke Point' data */
+typedef struct tGPspoint {
+       short x, y;                             /* x and y coordinates of cursor (in relative to area) */
+       float xf, yf;                   /* same as x and y, but as floats */
+       float pressure;                 /* pressure of tablet at this point */
+} tGPspoint;
+
 /* ------------ Grease-Pencil API ------------------ */
 
 void free_gpencil_strokes(struct bGPDframe *gpf);
@@ -53,8 +62,6 @@ 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);
-struct bGPdata *gpencil_data_getetime(struct bScreen *sc);
-void gpencil_data_setetime(struct bScreen *sc, struct bGPdata *gpd);
 
 void gpencil_frame_delete_laststroke(struct bGPDframe *gpf);
 
@@ -71,6 +78,6 @@ void gpencil_delete_operation(short mode);
 void gpencil_delete_menu(void);
 
 //short gpencil_paint(short mousebutton);
-short gpencil_do_paint(struct ScrArea *sa);
+short gpencil_do_paint(struct ScrArea *sa, short mousebutton);
 
 #endif /*  BDR_GPENCIL_H */
index 9f6751d..77c2f19 100644 (file)
@@ -49,7 +49,9 @@ enum {
        ACTTYPE_FILLCON,
        ACTTYPE_IPO,
        ACTTYPE_SHAPEKEY,
-       ACTTYPE_GPLAYER
+       ACTTYPE_GPDATABLOCK,
+       ACTTYPE_GPLAYER,
+       ACTTYPE_SPECIALDATA
 };
 
 /* Macros for easier/more consistant state testing */
@@ -70,6 +72,8 @@ enum {
 #define EDITABLE_ICU(icu) ((icu->flag & IPO_PROTECT)==0)
 #define SEL_ICU(icu) (icu->flag & IPO_SELECT)
 
+#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))
 
@@ -185,7 +189,7 @@ 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(struct bGPdata *gpd, short select_mode);
+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);
@@ -204,7 +208,7 @@ void mirror_gplayer_frames(struct bGPDlayer *gpl, short mode);
 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 24112c7..da98eb3 100644 (file)
@@ -134,6 +134,7 @@ void        transform_armature_mirror_update(void);
 void   hide_selected_armature_bones(void);
 void   hide_unselected_armature_bones(void);
 void   show_all_armature_bones(void);
+void   set_locks_armature_bones(short lock);
 
 #define        BONESEL_ROOT    0x10000000
 #define        BONESEL_TIP             0x20000000
index 4ed3d0d..d2c6c56 100644 (file)
@@ -34,9 +34,12 @@ struct Base;
 struct Object;
 struct Camera;
 struct View3D;
+struct rcti;
 
 void   arrows_move_cursor(unsigned short event);
+void   lasso_select_boundbox(struct rcti *rect, short mcords[][2], short moves);
 int            lasso_inside(short mcords[][2], short moves, short sx, short sy);
+int    lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1);
 void   borderselect(void);
 void   circle_select(void);
 void   deselectall(void);
index 83031ff..e6f22a4 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 c0542e3..af74946 100644 (file)
@@ -721,7 +721,8 @@ enum {
        B_CONSTRAINT_ADD_PYTHON,
        B_CONSTRAINT_ADD_CLAMPTO,
        B_CONSTRAINT_ADD_TRANSFORM,
-       B_CONSTRAINT_INF
+       B_CONSTRAINT_INF,
+       B_CONSTRAINT_ADD_SHRINKWRAP
 };
 
 /* *********************** */
index 60050ea..3054e03 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 d7969a7..2e8d953 100644 (file)
@@ -184,7 +184,6 @@ typedef struct SpaceAction {
        View2D v2d;     
        
        bAction         *action;                /* the currently active action */
-       bGPdata         *gpd;           /* the currently active gpencil block (for editing) */
        
        char  mode, autosnap;           /* mode: editing context; autosnap: automatic keyframe snapping mode   */
        short flag, actnr;                      /* flag: bitmapped settings; */
index ac9761f..7444ce9 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
index 673855a..0648c53 100644 (file)
@@ -154,7 +154,8 @@ typedef enum eBone_Flag {
        BONE_NO_SCALE                           = (1<<15),      /* No parent scale */
        BONE_HIDDEN_PG                          = (1<<16),      /* hidden bone when drawing PoseChannels (for ghost drawing) */
        BONE_DRAWWIRE                           = (1<<17),      /* bone should be drawn as OB_WIRE, regardless of draw-types of view+armature */
-       BONE_NO_CYCLICOFFSET            = (1<<18)       /* when no parent, bone will not get cyclic offset */
+       BONE_NO_CYCLICOFFSET            = (1<<18),      /* when no parent, bone will not get cyclic offset */
+       BONE_EDITMODE_LOCKED            = (1<<19),      /* bone transforms are locked in EditMode */
 } eBone_Flag;
 
 #endif
index 0fe0dac..e78855b 100644 (file)
@@ -317,6 +317,13 @@ typedef struct bDistLimitConstraint {
        int             pad;
 } bDistLimitConstraint;
 
+typedef struct bShrinkwrapConstraint {
+       Object          *target;
+       float           dist;                   /* distance to kept from target */
+       short           shrinkType;             /* shrink type (look on MOD shrinkwrap for values) */
+       short           pad[5];
+} bShrinkwrapConstraint;
+
 /* ------------------------------------------ */
 
 /* bConstraint->type 
@@ -344,10 +351,9 @@ typedef enum B_CONSTAINT_TYPES {
        CONSTRAINT_TYPE_RIGIDBODYJOINT,         /* rigidbody constraint */
        CONSTRAINT_TYPE_CLAMPTO,                        /* clampto constraint */        
        CONSTRAINT_TYPE_TRANSFORM,                      /* transformation (loc/rot/size -> loc/rot/size) constraint */  
+       CONSTRAINT_TYPE_SHRINKWRAP,                     /* shrinkwrap (loc/rot) constraint */
        
-       
-       /* NOTE: everytime a new constraint is added, update this */
-       NUM_CONSTRAINT_TYPES= CONSTRAINT_TYPE_TRANSFORM
+       NUM_CONSTRAINT_TYPES
 } B_CONSTRAINT_TYPES; 
 
 /* bConstraint->flag */
@@ -375,11 +381,13 @@ typedef enum B_CONSTRAINT_SPACETYPES {
                /* for objects (relative to parent/without parent influence), 
                 * for bones (along normals of bone, without parent/restpositions) 
                 */
-       CONSTRAINT_SPACE_LOCAL,
+       CONSTRAINT_SPACE_LOCAL, /* = 1 */
                /* for posechannels - pose space  */
-       CONSTRAINT_SPACE_POSE,
-               /* for posechannels - local with parent  */
-       CONSTRAINT_SPACE_PARLOCAL,
+       CONSTRAINT_SPACE_POSE, /* = 2 */
+               /* for posechannels - local with parent  */
+       CONSTRAINT_SPACE_PARLOCAL, /* = 3 */
+               /* for files from between 2.43-2.46 (should have been parlocal) */
+       CONSTRAINT_SPACE_INVALID, /* = 4. do not exchange for anything! */
 } B_CONSTRAINT_SPACETYPES;
 
 /* bConstraintChannel.flag */
index 7255714..6c098e2 100644 (file)
@@ -71,7 +71,8 @@ typedef struct CustomData {
 #define CD_MTEXPOLY            15
 #define CD_MLOOPUV             16
 #define CD_MLOOPCOL            17
-#define CD_NUMTYPES            18
+#define CD_TANGENT             18
+#define CD_NUMTYPES            19
 
 /* Bits for CustomDataMask */
 #define CD_MASK_MVERT          (1 << CD_MVERT)
@@ -92,6 +93,7 @@ typedef struct CustomData {
 #define CD_MASK_MTEXPOLY       (1 << CD_MTEXPOLY)
 #define CD_MASK_MLOOPUV                (1 << CD_MLOOPUV)
 #define CD_MASK_MLOOPCOL       (1 << CD_MLOOPCOL)
+#define CD_MASK_TANGENT                (1 << CD_TANGENT)
 
 
 /* CustomData.flag */
index eafd886..dca4e28 100644 (file)
@@ -59,6 +59,8 @@ typedef struct bGPDstroke {
 #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'
@@ -123,16 +125,16 @@ typedef struct bGPdata {
         */
        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) */
+       void *sbuffer;                          /* stroke buffer (can hold GP_STROKE_BUFFER_MAX) */
 } bGPdata;
 
 /* bGPdata->flag */
-       /* draw this datablock's data (not used) */
-#define GP_DATA_DISP           (1<<0)
+       /* 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)
-       /* is the block being shown in Action Editor */
-#define GP_DATA_EDITTIME       (1<<2)
+       /* 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 */
index 6d02583..4e427ed 100644 (file)
@@ -228,7 +228,7 @@ typedef struct PartialVisibility {
 
 /* mtface->mode */
 #define TF_DYNAMIC             1
-#define TF_DEPRECATED  2
+#define TF_ALPHASORT   2
 #define TF_TEX                 4
 #define TF_SHAREDVERT  8
 #define TF_LIGHT               16
index c4e8cb4..85c49a0 100644 (file)
@@ -466,9 +466,11 @@ extern Object workob;
 #define OB_LOCK_ROTX   8
 #define OB_LOCK_ROTY   16
 #define OB_LOCK_ROTZ   32
+#define OB_LOCK_ROT            56
 #define OB_LOCK_SCALEX 64
 #define OB_LOCK_SCALEY 128
 #define OB_LOCK_SCALEZ 256
+#define OB_LOCK_SCALE  448
 
 /* ob->softflag in DNA_object_force.h */
 
index c0b9a6b..7bad8ec 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 bdceb13..9396410 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 c9f58fb..f673834 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 f75802b..bdb2bb3 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 2266576..7120e97 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 e9dff09..0db87c0 100644 (file)
@@ -1469,6 +1469,8 @@ PyObject *Armature_Init(void)
                PyConstant_NewInt("BONE_SELECTED", BONE_SELECTED));
        PyModule_AddObject(module, "TIP_SELECTED", 
                PyConstant_NewInt("TIP_SELECTED", BONE_TIPSEL));
+       PyModule_AddObject(module, "LOCKED_EDIT", 
+               PyConstant_NewInt("LOCKED_EDIT", BONE_EDITMODE_LOCKED));
 
        PyModule_AddObject(module, "OCTAHEDRON", 
                PyConstant_NewInt("OCTAHEDRON", ARM_OCTA));
index 84faf41..948eb00 100644 (file)
@@ -368,6 +368,10 @@ static PyObject *EditBone_getOptions(BPy_EditBone *self, void *closure)
                        if (PyList_Append(list, 
                                EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
                                goto RuntimeError;
+               if(self->editbone->flag & BONE_EDITMODE_LOCKED)
+                       if (PyList_Append(list, 
+                               EXPP_GetModuleConstant("Blender.Armature", "LOCKED_EDIT")) == -1)
+                               goto RuntimeError;
        }else{
                if(self->flag & BONE_CONNECTED)
                        if (PyList_Append(list, 
@@ -401,6 +405,10 @@ static PyObject *EditBone_getOptions(BPy_EditBone *self, void *closure)
                        if (PyList_Append(list, 
                                EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
                                goto RuntimeError;
+               if(self->flag & BONE_EDITMODE_LOCKED)
+                       if (PyList_Append(list, 
+                               EXPP_GetModuleConstant("Blender.Armature", "LOCKED_EDIT")) == -1)
+                               goto RuntimeError;
        }
 
        return list;
@@ -422,7 +430,7 @@ static int EditBone_CheckValidConstant(PyObject *constant)
                                return 0;
                        if (!STREQ3(PyString_AsString(name), "CONNECTED", "HINGE", "NO_DEFORM") &&
                                !STREQ3(PyString_AsString(name), "ROOT_SELECTED", "BONE_SELECTED", "TIP_SELECTED")      &&
-                               !STREQ2(PyString_AsString(name), "MULTIPLY", "HIDDEN_EDIT"))
+                               !STREQ3(PyString_AsString(name), "MULTIPLY", "HIDDEN_EDIT", "LOCKED_EDIT"))
                                return 0;
                        else
                                return 1;
index f60ebf8..4a51619 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 68916af..9aceb01 100644 (file)
@@ -89,6 +89,8 @@ Example::
 @type BONE_SELECTED: Constant
 @var TIP_SELECTED: Tip of the Bone is selected
 @type TIP_SELECTED: Constant
+@var LOCKED_EDIT: Prevents the bone from being transformed in editmode
+@type LOCKED_EDIT: Constant
 @var OCTAHEDRON: Bones drawn as octahedrons
 @type OCTAHEDRON: Constant
 @var STICK: Bones drawn as a line
@@ -286,6 +288,7 @@ class Bone:
                         - Armature.ROOT_SELECTED: Selection of root ball of bone
                         - Armature.BONE_SELECTED: Selection of bone
                         - Armature.TIP_SELECTED: Selection of tip ball of bone
+                        - Armature.LOCKED_EDIT: Prevents the bone from being transformed in editmode
        @type options: List of Constants
        @ivar subdivision: The number of bone subdivisions.
        @type subdivision: Int
index 0a0df33..01d5136 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 c479926..d1c72f8 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 d382d45..22e165c 100644 (file)
@@ -56,6 +56,7 @@ struct View3D; /* keep me up here */
 #include "gen_utils.h"
 #include "gen_library.h"
 
+#include "../BPY_extern.h" /* for BPY_do_all_scripts() */
 #include "Scene.h"
 #include "Group.h"
 
@@ -469,19 +470,20 @@ PyObject *M_Render_EnableDispWin( PyObject * self )
 PyObject *RenderData_Render( BPy_RenderData * self )
 {
        Scene *oldsce;
+       /* unlock to prevent a deadlock when there are pynodes: */
+       PyThreadState *tstate = NULL;
 
        if (!G.background) {
                oldsce = G.scene;
                set_scene( self->scene );
+               tstate = PyEval_SaveThread();
                BIF_do_render( 0 );
                set_scene( oldsce );
        }
-
        else { /* background mode (blender -b file.blend -P script) */
+               int slink_flag = 0;
                Render *re= RE_NewRender(G.scene->id.name);
 
-
-
                int end_frame = G.scene->r.efra;
 
                if (G.scene != self->scene)
@@ -490,11 +492,25 @@ PyObject *RenderData_Render( BPy_RenderData * self )
 
                G.scene->r.efra = G.scene->r.sfra;
 
+               if (G.f & G_DOSCRIPTLINKS) {
+                       BPY_do_all_scripts(SCRIPT_RENDER);
+                       G.f &= ~G_DOSCRIPTLINKS; /* avoid FRAMECHANGED events*/
+                       slink_flag = 1;
+               }
+
+               tstate = PyEval_SaveThread();
+
                RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra);
 
+               if (slink_flag) {
+                       G.f |= G_DOSCRIPTLINKS;
+                       BPY_do_all_scripts(SCRIPT_POSTRENDER);
+               }
+
                G.scene->r.efra = end_frame;
        }
 
+       PyEval_RestoreThread(tstate);
        Py_RETURN_NONE;
 }
 
@@ -565,10 +581,13 @@ PyObject *RenderData_SaveRenderedImage ( BPy_RenderData * self, PyObject *args )
 PyObject *RenderData_RenderAnim( BPy_RenderData * self )
 {
        Scene *oldsce;
-
+       /* unlock to prevent a deadlock when there are pynodes: */
+       PyThreadState *tstate = NULL;
+               
        if (!G.background) {
                oldsce = G.scene;
                set_scene( self->scene );
+               tstate = PyEval_SaveThread();
                BIF_do_render( 1 );
                set_scene( oldsce );
        }
@@ -582,9 +601,18 @@ 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");
-               
+
+               if (G.f & G_DOSCRIPTLINKS)
+                       BPY_do_all_scripts(SCRIPT_RENDER);
+
+               tstate = PyEval_SaveThread();
                RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra);
+
+               if (G.f & G_DOSCRIPTLINKS)
+                       BPY_do_all_scripts(SCRIPT_POSTRENDER);
        }
+
+       PyEval_RestoreThread(tstate);
        Py_RETURN_NONE;
 }
 
index 252350e..31f4596 100644 (file)
@@ -2013,7 +2013,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,
@@ -4518,11 +4518,12 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm)
                        uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", 225, by-19,105, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight");
                        
                        /* bone types */
-                       uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge",         -10,by-38,80,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
-                       uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S",          70,by-38,20,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone");
-                       uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   90, by-38, 80, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
-                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 170,by-38,80,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
-                       uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide",   250,by-38,80,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
+                       uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge",         -10,by-38,60,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
+                       uiDefButBitI(block, TOG, BONE_NO_SCALE, B_ARM_RECALCDATA, "S",          50,by-38,20,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit scale from parent Bone");
+                       uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform",   70, by-38, 80, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
+                       uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 150,by-38,60,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
+                       uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide",   210,by-38,60,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
+                       uiDefButBitI(block, TOG, BONE_EDITMODE_LOCKED, REDRAWVIEW3D, "Lock",    270,by-38,60,18, &curBone->flag, 0, 0, 0, 0, "Prevents this bone from being transformed in Edit Mode");
                        
                        /* layers */
                        uiBlockBeginAlign(block);
@@ -6335,6 +6336,7 @@ static void editing_panel_mesh_texface(void)
                uiDefButBitS(block, TOG, TF_BILLBOARD2, B_TFACE_BILLB, "Billboard",660,110,60,19, &tf->mode, 0, 0, 0, 0, "Billboard with Z-axis constraint");
                uiDefButBitS(block, TOG, TF_SHADOW, REDRAWVIEW3D, "Shadow", 720,110,60,19, &tf->mode, 0, 0, 0, 0, "Face is used for shadow");
                uiDefButBitS(block, TOG, TF_BMFONT, REDRAWVIEW3D, "Text", 780,110,60,19, &tf->mode, 0, 0, 0, 0, "Enable bitmap text on face");
+               uiDefButBitS(block, TOG, TF_ALPHASORT, REDRAWVIEW3D, "Sort", 840,110,60,19, &tf->mode, 0, 0, 0, 0, "Enable sorting of faces for correct alpha drawing (slow, use Clip Alpha instead when possible)");
 
                uiBlockBeginAlign(block);
                uiBlockSetCol(block, TH_BUT_SETTING1);
index 441d00f..5cf1958 100644 (file)
@@ -1654,53 +1654,66 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
                        wval = (width-100)/3;
                        if (oa->type == ACT_OBJECT_NORMAL)
                        {
-                               ysize= 175;
-                               
+                               if ( ob->gameflag & OB_DYNAMIC )
+                               {
+                                       ysize= 175;
+                               }
+                               else
+                               {
+                                       ysize= 72;
+                               }
+
                                glRects(xco, yco-ysize, xco+width, yco);
                                uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
                                
-                               uiDefBut(block, LABEL, 0, "Force",      xco, yco-45, 55, 19, NULL, 0, 0, 0, 0, "Sets the force");
-                               uiDefButF(block, NUM, 0, "",            xco+45, yco-45, wval, 19, oa->forceloc, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-45, wval, 19, oa->forceloc+1, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-45, wval, 19, oa->forceloc+2, -10000.0, 10000.0, 10, 0, "");
-                               
-                               uiDefBut(block, LABEL, 0, "Torque", xco, yco-64, 55, 19, NULL, 0, 0, 0, 0, "Sets the torque");
-                               uiDefButF(block, NUM, 0, "",            xco+45, yco-64, wval, 19, oa->forcerot, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-64, wval, 19, oa->forcerot+1, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-64, wval, 19, oa->forcerot+2, -10000.0, 10000.0, 10, 0, "");
+                               uiDefBut(block, LABEL, 0, "Loc",        xco, yco-45, 45, 19, NULL, 0, 0, 0, 0, "Sets the location");
+                               uiDefButF(block, NUM, 0, "",            xco+45, yco-45, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, "");
+                               uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-45, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, "");
+                               uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-45, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, "");
                                
-                               uiDefBut(block, LABEL, 0, "dLoc",       xco, yco-87, 45, 19, NULL, 0, 0, 0, 0, "Sets the dLoc");
-                               uiDefButF(block, NUM, 0, "",            xco+45, yco-87, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-87, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-87, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, "");
-                               
-                               uiDefBut(block, LABEL, 0, "dRot",       xco, yco-106, 45, 19, NULL, 0, 0, 0, 0, "Sets the dRot");
-                               uiDefButF(block, NUM, 0, "",            xco+45, yco-106, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-106, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-106, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, "");
+                               uiDefBut(block, LABEL, 0, "Rot",        xco, yco-64, 45, 19, NULL, 0, 0, 0, 0, "Sets the rotation");
+                               uiDefButF(block, NUM, 0, "",            xco+45, yco-64, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, "");
+                               uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-64, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, "");
+                               uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-64, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, "");
+
+                               uiDefButBitS(block, TOG, ACT_DLOC_LOCAL, 0, "L",                xco+45+3*wval, yco-45, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+                               uiDefButBitS(block, TOG, ACT_DROT_LOCAL, 0, "L",                xco+45+3*wval, yco-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+       
+                               if ( ob->gameflag & OB_DYNAMIC )
+                               {
+                                       uiDefBut(block, LABEL, 0, "Force",      xco, yco-87, 55, 19, NULL, 0, 0, 0, 0, "Sets the force");
+                                       uiDefButF(block, NUM, 0, "",            xco+45, yco-87, wval, 19, oa->forceloc, -10000.0, 10000.0, 10, 0, "");
+                                       uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-87, wval, 19, oa->forceloc+1, -10000.0, 10000.0, 10, 0, "");
+                                       uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-87, wval, 19, oa->forceloc+2, -10000.0, 10000.0, 10, 0, "");
                                
-                               uiDefBut(block, LABEL, 0, "linV",       xco, yco-129, 45, 19, NULL, 0, 0, 0, 0, "Sets the linear velocity");
-                               uiDefButF(block, NUM, 0, "",            xco+45, yco-129, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-129, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-129, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, "");
+                                       uiDefBut(block, LABEL, 0, "Torque", xco, yco-106, 55, 19, NULL, 0, 0, 0, 0, "Sets the torque");
+                                       uiDefButF(block, NUM, 0, "",            xco+45, yco-106, wval, 19, oa->forcerot, -10000.0, 10000.0, 10, 0, "");
+                                       uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-106, wval, 19, oa->forcerot+1, -10000.0, 10000.0, 10, 0, "");
+                                       uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-6106, wval, 19, oa->forcerot+2, -10000.0, 10000.0, 10, 0, "");                               
+                               }
                                
-                               uiDefBut(block, LABEL, 0, "angV",       xco, yco-148, 45, 19, NULL, 0, 0, 0, 0, "Sets the angular velocity");
-                               uiDefButF(block, NUM, 0, "",            xco+45, yco-148, wval, 19, oa->angularvelocity, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-148, wval, 19, oa->angularvelocity+1, -10000.0, 10000.0, 10, 0, "");
-                               uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-148, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, "");
+                               if ( ob->gameflag & OB_DYNAMIC )
+                               {
+                                       uiDefBut(block, LABEL, 0, "LinV",       xco, yco-129, 45, 19, NULL, 0, 0, 0, 0, "Sets the linear velocity");
+                                       uiDefButF(block, NUM, 0, "",            xco+45, yco-129, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, "");
+                                       uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-129, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, "");
+                                       uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-129, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, "");
                                
-                               uiDefBut(block, LABEL, 0, "damp",       xco, yco-171, 45, 19, NULL, 0, 0, 0, 0, "Number of frames to reach the target velocity");
-                               uiDefButS(block, NUM, 0, "",            xco+45, yco-171, wval, 19, &oa->damping, 0.0, 1000.0, 100, 0, "");
-
-                               uiDefButBitS(block, TOG, ACT_FORCE_LOCAL, 0, "L",               xco+45+3*wval, yco-45, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
-                               uiDefButBitS(block, TOG, ACT_TORQUE_LOCAL, 0, "L",              xco+45+3*wval, yco-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
-                               uiDefButBitS(block, TOG, ACT_DLOC_LOCAL, 0, "L",                xco+45+3*wval, yco-87, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
-                               uiDefButBitS(block, TOG, ACT_DROT_LOCAL, 0, "L",                xco+45+3*wval, yco-106, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
-                               uiDefButBitS(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L",             xco+45+3*wval, yco-129, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
-                               uiDefButBitS(block, TOG, ACT_ANG_VEL_LOCAL, 0, "L",             xco+45+3*wval, yco-148, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+                                       uiDefBut(block, LABEL, 0, "AngV",       xco, yco-148, 45, 19, NULL, 0, 0, 0, 0, "Sets the angular velocity");
+                                       uiDefButF(block, NUM, 0, "",            xco+45, yco-148, wval, 19, oa->angularvelocity, -10000.0, 10000.0, 10, 0, "");
+                                       uiDefButF(block, NUM, 0, "",            xco+45+wval, yco-148, wval, 19, oa->angularvelocity+1, -10000.0, 10000.0, 10, 0, "");
+                                       uiDefButF(block, NUM, 0, "",            xco+45+2*wval, yco-148, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, "");
                                
-                               uiDefButBitS(block, TOG, ACT_ADD_LIN_VEL, 0, "add",xco+45+3*wval+15, yco-129, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV");
+                                       uiDefBut(block, LABEL, 0, "Damp",       xco, yco-171, 45, 19, NULL, 0, 0, 0, 0, "Number of frames to reach the target velocity");
+                                       uiDefButS(block, NUM, 0, "",            xco+45, yco-171, wval, 19, &oa->damping, 0.0, 1000.0, 100, 0, "");
+
+                                       uiDefButBitS(block, TOG, ACT_FORCE_LOCAL, 0, "L",               xco+45+3*wval, yco-87, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+                                       uiDefButBitS(block, TOG, ACT_TORQUE_LOCAL, 0, "L",              xco+45+3*wval, yco-106, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+                                       uiDefButBitS(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L",             xco+45+3*wval, yco-129, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
+                                       uiDefButBitS(block, TOG, ACT_ANG_VEL_LOCAL, 0, "L",             xco+45+3*wval, yco-148, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation");
                                
+                                       uiDefButBitS(block, TOG, ACT_ADD_LIN_VEL, 0, "add",xco+45+3*wval+15, yco-129, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV");
+                               }                               
                        } else if (oa->type == ACT_OBJECT_SERVO)
                        {
                                ysize= 172;
@@ -2062,7 +2075,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 +2097,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 +2137,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 +2146,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 ebe770c..c2643aa 100644 (file)
@@ -480,7 +480,7 @@ static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short
        
        /* Target-Space */
        if (target == 1) {
-               uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Pose Space %x3|Local with Parent %x4|Local Space %x1", 
+               uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Pose Space %x2|Local with Parent %x3|Local Space %x1", 
                                                                                                tarx, yco, bwidth, 18, &con->tarspace, 0, 0, 0, 0, "Choose space that target is evaluated in"); 
        }
        else if (target == 0) {
@@ -490,7 +490,7 @@ static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short
        
        /* Owner-Space */
        if (owner == 1) {
-               uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Owner Space %t|World Space %x0|Pose Space %x3|Local with Parent %x4|Local Space %x1", 
+               uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Owner Space %t|World Space %x0|Pose Space %x2|Local with Parent %x3|Local Space %x1", 
                                                                                                ownx, yco, bwidth, 18, &con->ownspace, 0, 0, 0, 0, "Choose space that owner is evaluated in");  
        }
        else if (owner == 0) {
@@ -1739,6 +1739,16 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
                        }
                        break;
+
+               case CONSTRAINT_TYPE_SHRINKWRAP:
+                       {
+                               bShrinkwrapConstraint *data = con->data;
+
+                               height = 44;
+                               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->target, "Target Object");
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "dist", *xco+120, *yco-44, 135, 18, &data->dist, 0.0f, 100.0f, 1.0f, 0.0f, "Distance to target"); 
+                       }
+                       break;
                default:
                        height = 0;
                        break;
@@ -1800,6 +1810,7 @@ static uiBlock *add_constraintmenu(void *arg_unused)
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_MINMAX, "Floor", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCKTRACK, "Locked Track", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH, "Follow Path", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+       uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SHRINKWRAP, "Shrinkwrap" , 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
                
        uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
        
@@ -2035,6 +2046,14 @@ void do_constraintbuts(unsigned short event)
                        BIF_undo_push("Add constraint");
                }
                break;
+       case B_CONSTRAINT_ADD_SHRINKWRAP:
+               {
+                       con = add_new_constraint(CONSTRAINT_TYPE_SHRINKWRAP);
+                       add_constraint_to_active(ob, con);
+                       
+                       BIF_undo_push("Add constraint");
+               }
+               break;
 
        default:
                break;
index 9b1af3f..0782ccf 100644 (file)
@@ -89,6 +89,7 @@
 
 #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"
@@ -467,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) {
@@ -625,6 +626,72 @@ 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;
@@ -632,7 +699,8 @@ static void draw_channel_names(void)
                                        indent = 0;
                                        special = -1;
                                        expand = -1;
-                                               
+                                       group = 1;
+                                       
                                        if (EDITABLE_GPL(gpl))
                                                protect = ICON_UNLOCKED;
                                        else
@@ -651,8 +719,19 @@ static void draw_channel_names(void)
 
                        /* 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
@@ -698,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 */
@@ -720,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);
                        }
@@ -1148,12 +1233,6 @@ void drawactionspace(ScrArea *sa, void *spacedata)
                                        G.saction->action= NULL;
                        }
                                break;
-                       case SACTCONT_GPENCIL:
-                       {
-                               /* this searching could be slow (so users should pin after this is found) */
-                               G.saction->gpd= gpencil_data_getetime(G.curscreen);
-                       }
-                               break;
                }
        }
        
index 55d0464..733310b 100644 (file)
@@ -94,6 +94,7 @@
 void gp_ui_activelayer_cb (void *gpd, void *gpl)
 {
        gpencil_layer_setactive(gpd, gpl);
+       allqueue(REDRAWACTION, 0);
 }
 
 /* rename layer and set active */
@@ -104,18 +105,21 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *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 */
@@ -134,28 +138,17 @@ void gp_ui_delframe_cb (void *gpd, void *gpl)
        
        gpencil_layer_setactive(gpd, gpl);
        gpencil_layer_delframe(gpl, gpf);
-}
-
-
-/* set this set of gpencil data for editing in action editor */
-void gp_ui_dotime_cb (void *gpd_arg, void *dummy)
-{
-       bGPdata *gpd= (bGPdata *)gpd_arg;
        
-       /* check if setting or clearing (note: setting was just set...) */
-       if (gpd->flag & GP_DATA_EDITTIME)
-               gpencil_data_setetime(G.curscreen, gpd);
-       else    
-               gpencil_data_setetime(G.curscreen, NULL);
+       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;
@@ -168,40 +161,41 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
                uiBlockSetEmboss(block, UI_EMBOSSN);
                
                /* rounded header */
-               rb_col= (gpl->flag & GP_LAYER_ACTIVE)?50: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_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, don't draw the rest of its settings */
+       /* when layer is locked or hidden, only draw header */
        if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) {
-               height= 26;
+               char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
                
-               /* draw rest of header */
-               {
-                       /* 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 */
-                       uiDefBut(block, LABEL, 1, gpl->info,    *xco+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "Short description of what this layer is for (optional)");
-               }
+               height= 26;
                
-               /* draw backdrop */
-               uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
+               /* 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");
                
-               /* draw settings... (i.e. just warning for this one) */
+               /* name */
                if (gpl->flag & GP_LAYER_HIDE)
-                       uiDefBut(block, LABEL, 1, "Grease Pencil Layer Hidden", *xco+60, *yco-26, 205, 20, NULL, 0.0, 0.0, 0, 0, "");
+                       sprintf(name, "%s (Hidden)", gpl->info);
                else
-                       uiDefBut(block, LABEL, 1, "Grease Pencil Layer Locked", *xco+60, *yco-26, 205, 20, NULL, 0.0, 0.0, 0, 0, "");
+                       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)");
                        
+               /* delete button (only if hidden but not locked!) */
+               if ((gpl->flag & GP_LAYER_HIDE) & !(gpl->flag & GP_LAYER_LOCKED)) {
+                       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);
        }
        else {
-               height= 100;
+               height= 97;
                
                /* draw rest of header */
                {
@@ -211,7 +205,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
                        uiBlockSetEmboss(block, UI_EMBOSS);
                        
                        /* name */
-                       but= uiDefButC(block, TEX, B_REDR, "Info:",     *xco+35, *yco, 240, 20, gpl->info, 0, 127, 0, 0, "Short description of what this layer is for (optional)");
+                       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' */
@@ -224,7 +218,9 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
                }
                
                /* draw backdrop */
-               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_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 */
                {
@@ -237,21 +233,25 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
                        /* stroke thickness */
                        uiDefButS(block, NUMSLI, B_REDR, "Thickness:",  *xco, *yco-75, 150, 20, &gpl->thickness, 1, 10, 0, 0, "Thickness of strokes (in pixels)");
                        
+                       /* debugging options */
+                       if (G.f & G_DEBUG) {
+                               uiDefButBitI(block, TOG, GP_LAYER_DRAWDEBUG, B_REDR, "Show Points", *xco, *yco-95, 150, 20, &gpl->flag, 0, 0, 0, 0, "Show points which form the strokes");
+                       }
                        
                        /* 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, "Maximum frame range on either side of active frame to show (0 = just 'first' available frame on either side)");
+                               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 */
-                       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");
-                       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");
-                       uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl);
-                       
-                       //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");
+                       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);
                }
        }
        
@@ -262,36 +262,40 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short
 /* 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= 155;
+       short xco= 10, yco= 170;
        
        /* draw gpd settings first */
        {
-               /* show status info button */
-               uiDefButBitI(block, TOG, GP_DATA_DISPINFO, B_REDR, "Show Status Info", 10, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "Display status info about current status of Grease Pencil");
-               
-               /* add new/duplicate layer buttons */
-               but= uiDefBut(block, BUT, B_REDR, "Add New Layer", 10,182,150,20, 0, 0, 0, 0, 0, "Adds a new Grease Pencil Layer");
+               /* 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 */
-               uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 150, 20, &gpd->flag, 0, 0, 0, 0, "Interpret LMB-click as new strokes (same as holding Shift-Key per stroke)");
+               /* show override lmb-clicks button + painting lock */
+               uiBlockBeginAlign(block);
+                       if ((gpd->flag & GP_DATA_EDITPAINT)==0) {
+                               uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 130, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes");
+                               
+                               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);
+                       }
+                       else
+                               uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 150, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes");
+               uiBlockEndAlign(block);
                
                /* 'view align' button (naming depends on context) */
                if (sa->spacetype == SPACE_VIEW3D)
-                       uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Draw in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space");
+                       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");
-               
-               /* show edit-in-action button */
-               but= uiDefButBitI(block, TOG, GP_DATA_EDITTIME, B_REDR, "Edit Timing", 170, 182, 150, 20, &gpd->flag, 0, 0, 0, 0, "Edit timing of frames for the Grease Pencil block");
-               uiButSetFunc(but, gp_ui_dotime_cb, gpd, NULL);
        }
        
        /* draw for each layer */
@@ -313,6 +317,66 @@ enum {
        GP_DRAWDATA_ONLYV2D             = (1<<2),       /* only draw 'canvas' strokes */
 };
 
+/* draw stroke in buffer */
+static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thickness, short dflag, short sflag)
+{
+       tGPspoint *pt;
+       int i;
+       
+       /* error checking */
+       if ((points == NULL) || (totpoints <= 0))
+               return;
+       
+       /* check if buffer can be drawn */
+       if (dflag & (GP_DRAWDATA_ONLY3D|GP_DRAWDATA_ONLYV2D))
+               return;
+       
+       /* if drawing a single point, draw it larger */ 
+       if (totpoints == 1) {           
+               /* draw point */
+               glBegin(GL_POINTS);
+                       glVertex2f(points->x, points->y);
+               glEnd();
+       }
+       else if (sflag & GP_STROKE_ERASER) {
+               /* draw stroke curve - just standard thickness */
+               setlinestyle(4);
+               glLineWidth(1.0f);
+               
+               glBegin(GL_LINE_STRIP);
+               for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
+                       glVertex2f(pt->x, pt->y);
+               }
+               glEnd();
+               
+               setlinestyle(0);
+       }
+       else {
+               float oldpressure = 0.0f;
+               
+               /* draw stroke curve */
+               setlinestyle(2);
+               
+               glBegin(GL_LINE_STRIP);
+               for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
+                       if (fabs(pt->pressure - oldpressure) > 0.2f) {
+                               glEnd();
+                               glLineWidth(pt->pressure * thickness);
+                               glBegin(GL_LINE_STRIP);
+                               
+                               glVertex2f(pt->x, pt->y);
+                               
+                               oldpressure = pt->pressure;
+                       }
+                       else
+                               glVertex2f(pt->x, pt->y);
+               }
+               glEnd();
+               
+               setlinestyle(0);
+       }
+}
+
 /* 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)
 {
@@ -422,6 +486,21 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
        }
 }
 
+/* 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) {    
+               /* 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)
 {
@@ -437,11 +516,10 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
        /* loop over layers, drawing them */
        for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
                bGPDframe *gpf;
-               bGPDstroke *gps;
                
                short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0;
                short lthick= gpl->thickness;
-               float color[4];
+               float color[4], tcolor[4];
                
                /* don't draw layer if hidden */
                if (gpl->flag & GP_LAYER_HIDE) 
@@ -459,6 +537,7 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
                /* 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);
                
@@ -474,11 +553,8 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
                                        /* check if frame is drawable */
                                        if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
                                                /* alpha decreases with distance from curframe index */
-                                               glColor4f(color[0], color[1], color[2], (color[3]-(i*0.7)));
-                                               
-                                               for (gps= gf->strokes.first; gps; gps= gps->next) {     
-                                                       gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
-                                               }
+                                               tcolor[3] = color[3] - (i/gpl->gstep);
+                                               gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor);
                                        }
                                        else 
                                                break;
@@ -489,11 +565,8 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
                                        /* check if frame is drawable */
                                        if ((gf->framenum - gpf->framenum) <= gpl->gstep) {
                                                /* alpha decreases with distance from curframe index */
-                                               glColor4f(color[0], color[1], color[2], (color[3]-(i*0.7)));
-                                               
-                                               for (gps= gf->strokes.first; gps; gps= gps->next) {                                                             
-                                                       gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
-                                               }
+                                               tcolor[3] = color[3] - (i/gpl->gstep);
+                                               gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor);
                                        }
                                        else 
                                                break;
@@ -504,19 +577,14 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
                        }
                        else {
                                /* draw the strokes for the ghost frames (at half of the alpha set by user) */
-                               glColor4f(color[0], color[1], color[2], (color[3] / 7));
-                               
                                if (gpf->prev) {
-                                       for (gps= gpf->prev->strokes.first; gps; gps= gps->next) {
-                                               gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
-                                       }
+                                       tcolor[3] = (color[3] / 7);
+                                       gp_draw_strokes(gpf->prev, winx, winy, dflag, debug, lthick, tcolor);
                                }
                                
-                               glColor4f(color[0], color[1], color[2], (color[3] / 4));
                                if (gpf->next) {
-                                       for (gps= gpf->next->strokes.first; gps; gps= gps->next) {      
-                                               gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
-                                       }
+                                       tcolor[3] = (color[3] / 4);
+                                       gp_draw_strokes(gpf->next, winx, winy, dflag, debug, lthick, tcolor);
                                }
                                
                                /* restore alpha */
@@ -525,20 +593,17 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag)
                }
                
                /* draw the strokes already in active frame */
-               for (gps= gpf->strokes.first; gps; gps= gps->next) {    
-                       gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
-               }
+               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)
+                * that is being edited. (Stroke buffer 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);
+                       gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
                }
        }
        
index 3a73ee8..853df3b 100644 (file)
@@ -3336,7 +3336,7 @@ static void nodes_panel_gpencil(short cntrl)      // NODES_HANDLER_GREASEPENCIL
                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");
+               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); 
index c8c74ad..cc431c7 100644 (file)
@@ -134,7 +134,7 @@ static void seq_panel_gpencil(short cntrl)  // SEQ_HANDLER_GREASEPENCIL
                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");
+               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); 
index 1443450..2030eb6 100644 (file)
@@ -1502,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);
@@ -1987,6 +1995,8 @@ static void v3d_editarmature_buts(uiBlock *block, Object *ob, float lim)
        tfp->ob_eul[0]= 180.0*ebone->roll/M_PI;
        uiDefButF(block, NUM, B_ARMATUREPANEL1, "Roll:",        10, 100, 140, 19, tfp->ob_eul, -lim, lim, 1000, 3, "");
 
+       uiDefButBitI(block, TOG, BONE_EDITMODE_LOCKED, REDRAWVIEW3D, "Lock", 160, 100, 140, 19, &(ebone->flag), 0, 0, 0, 0, "Prevents bone from being transformed in edit mode");
+       
        uiBlockBeginAlign(block);
        uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailRadius:",  10, 150, 140, 19, &ebone->rad_tail, 0, lim, 10, 3, "");
        if (ebone->parent && ebone->flag & BONE_CONNECTED )
@@ -2654,7 +2664,7 @@ static void view3d_panel_gpencil(short cntrl)     // VIEW3D_HANDLER_GREASEPENCIL
                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");
+               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); 
index 3251cb3..c454715 100644 (file)
@@ -517,23 +517,43 @@ static void actdata_filter_shapekey (ListBase *act_data, Key *key, int filter_mo
        }
 }
  
-static void actdata_filter_gpencil (ListBase *act_data, bGPdata *gpd, int filter_mode)
+
+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 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, NULL, ACTTYPE_NONE);
-                                       if (ale) BLI_addtail(act_data, ale);
+               /* 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);
+                                               }
+                                       }
                                }
                        }
                }
@@ -637,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;
@@ -652,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) {
@@ -679,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);
                        
@@ -854,10 +875,7 @@ void *get_action_context (short *datatype)
                                
                        case SACTCONT_GPENCIL:
                                *datatype= ACTCONT_GPENCIL;
-                               if (G.saction->pin)
-                                       return G.saction->gpd;
-                               else
-                                       return gpencil_data_getetime(G.curscreen);
+                               return G.curscreen; // FIXME: add that dopesheet type thing here!
                        
                        default: /* includes SACTCONT_DOPESHEET for now */
                                *datatype= ACTCONT_NONE;
@@ -2327,7 +2345,7 @@ static void numbuts_action ()
        void *data;
        short datatype;
        
-       void *act_channel;
+       void *act_channel, *channel_owner;
        short chantype;
        
        bActionGroup *agrp= NULL;
@@ -2335,6 +2353,7 @@ static void numbuts_action ()
        bConstraintChannel *conchan= NULL;
        IpoCurve *icu= NULL;
        KeyBlock *kb= NULL;
+       bGPdata *gpd= NULL;
        bGPDlayer *gpl= NULL;
        
        short mval[2];
@@ -2353,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) {
@@ -2451,6 +2470,7 @@ static void numbuts_action ()
        }
        else if (chantype == ACTTYPE_GPLAYER) {
                /* Grease-Pencil Layer */
+               gpd= (bGPdata *)channel_owner;
                gpl= (bGPDlayer *)act_channel;
                
                strcpy(str, gpl->info);
@@ -2511,7 +2531,7 @@ static void numbuts_action ()
                }
                else if (gpl) {
                        strcpy(gpl->info, str);
-                       BLI_uniquename(&( ((bGPdata *)data)->layers ), gpl, "GP_Layer", offsetof(bGPDlayer, info), 128);
+                       BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info), 128);
                        
                        if (mute) gpl->flag |= GP_LAYER_HIDE;
                        else gpl->flag &= ~GP_LAYER_HIDE;;
@@ -2871,9 +2891,10 @@ int select_gplayer_channel (bGPdata *gpd, bGPDlayer *gpl, int selectmode)
                gpl->flag ^= GP_LAYER_SELECT;
                break;
        }
+       
        flag = (gpl->flag & GP_LAYER_SELECT) ? 1 : 0;
-
-       gpencil_layer_setactive(gpd, gpl);
+       if (flag)
+               gpencil_layer_setactive(gpd, gpl);
 
        return flag;
 }
@@ -3100,11 +3121,11 @@ void selectall_action_keys (short mval[], short mode, short select_mode)
        switch (mode) {