2.5
authorTon Roosendaal <ton@blender.org>
Wed, 7 Jan 2009 17:25:17 +0000 (17:25 +0000)
committerTon Roosendaal <ton@blender.org>
Wed, 7 Jan 2009 17:25:17 +0000 (17:25 +0000)
More files back in the 2.5 repo:
(Note, boolean stuff moved to blenkernel)

source/blender/blenkernel/BKE_booleanops.h
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/Makefile
source/blender/blenkernel/intern/booleanops.c [new file with mode: 0644]
source/blender/blenkernel/intern/booleanops_mesh.c [new file with mode: 0644]
source/blender/editors/interface/keyval.c [new file with mode: 0644]
source/blender/editors/screen/screendump.c [new file with mode: 0644]

index b83b9c89ae847739d24f289b1fcba1b3eb893850..b51ee2646fc7f69bedaf3f5891acaa68c1292b36 100644 (file)
@@ -17,7 +17,7 @@
  * 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.
+ * The Original Code is Copyright (C) Blender Foundation.
  * All rights reserved.
  *
  * The Original Code is: all of this file.
@@ -29,6 +29,7 @@
 #ifndef BKE_BOOLEANOPS_H
 #define BKE_BOOLEANOPS_H
 
+struct Scene;
 struct Object;
 struct Base;
 struct DerivedMesh;
@@ -36,7 +37,7 @@ struct DerivedMesh;
 /* Performs a boolean between two mesh objects, it is assumed that both objects
    are in fact a mesh object. On success returns 1 and creates a new mesh object
    into blender data structures. On failure returns 0 and reports an error. */
-int NewBooleanMesh(struct Base *base, struct Base *base_select, int op);
+int NewBooleanMesh(struct Scene *scene, struct Base *base, struct Base *base_select, int op);
 
 
 /* Performs a boolean between two mesh objects, it is assumed that both objects
index 9fef30381a875dfa3c94d7d696c0a7d545599497..a6b7120d72a7b2dc30cacab0719e46858b710d59 100644 (file)
@@ -9,7 +9,7 @@ incs += ' ../imbuf ../avi #/intern/elbeem/extern ../nodes'
 incs += ' #/intern/iksolver/extern ../blenloader'
 incs += ' #/extern/bullet2/src'
 incs += ' #/intern/bmfont'
-incs += ' #/intern/opennl/extern'
+incs += ' #/intern/opennl/extern #/intern/bsp/extern'
 incs += ' ../gpu #/extern/glew/include'
 
 incs += ' ' + env['BF_OPENGL_INC']
index 3d8a47e3683ad39b720d988daa4ceea5ef0dd663..acb1fd2deb65198462262d104ea51ffa2045d369 100644 (file)
@@ -69,6 +69,7 @@ CPPFLAGS += -I$(NAN_IKSOLVER)/include
 CPPFLAGS += -I$(NAN_DECIMATION)/include
 CPPFLAGS += -I$(NAN_ELBEEM)/include
 CPPFLAGS += -I$(NAN_OPENNL)/include
+CPPFLAGS += -I$(NAN_BSP)/include
 
 # path to zlib
 CPPFLAGS += -I$(NAN_ZLIB)/include
diff --git a/source/blender/blenkernel/intern/booleanops.c b/source/blender/blenkernel/intern/booleanops.c
new file mode 100644 (file)
index 0000000..51c4774
--- /dev/null
@@ -0,0 +1,567 @@
+/**
+ * $Id$
+ *
+ * ***** 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) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * CSG operations. 
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "CSG_BooleanOps.h"
+
+#include "BKE_booleanops.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+
+
+
+/**
+ * Here's the vertex iterator structure used to walk through
+ * the blender vertex structure.
+ */
+
+typedef struct {
+       Mesh *mesh;
+       Object *ob;
+       int pos;
+} VertexIt;
+
+/**
+ * Implementations of local vertex iterator functions.
+ * These describe a blender mesh to the CSG module.
+ */
+
+static void VertexIt_Destruct(CSG_VertexIteratorDescriptor * iterator)
+{
+       if (iterator->it) {
+               // deallocate memory for iterator
+               MEM_freeN(iterator->it);
+               iterator->it = 0;
+       }
+       iterator->Done = NULL;
+       iterator->Fill = NULL;
+       iterator->Reset = NULL;
+       iterator->Step = NULL;
+       iterator->num_elements = 0;
+
+}              
+
+static int VertexIt_Done(CSG_IteratorPtr it)
+{
+       VertexIt * iterator = (VertexIt *)it;
+       return(iterator->pos >= iterator->mesh->totvert);
+}
+
+static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert)
+{
+       VertexIt * iterator = (VertexIt *)it;
+       MVert *verts = iterator->mesh->mvert;
+
+       float global_pos[3];
+
+       /* boolean happens in global space, transform both with obmat */
+       VecMat4MulVecfl(
+               global_pos,
+               iterator->ob->obmat, 
+               verts[iterator->pos].co
+       );
+
+       vert->position[0] = global_pos[0];
+       vert->position[1] = global_pos[1];
+       vert->position[2] = global_pos[2];
+}
+
+static void VertexIt_Step(CSG_IteratorPtr it)
+{
+       VertexIt * iterator = (VertexIt *)it;
+       iterator->pos ++;
+} 
+static void VertexIt_Reset(CSG_IteratorPtr it)
+{
+       VertexIt * iterator = (VertexIt *)it;
+       iterator->pos = 0;
+}
+
+static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, Object *ob)
+{
+
+       VertexIt *it;
+       if (output == 0) return;
+
+       // allocate some memory for blender iterator
+       it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt),"Boolean_VIt"));
+       if (it == 0) {
+               return;
+       }
+       // assign blender specific variables
+       it->ob = ob;
+       it->mesh = ob->data;
+       
+       it->pos = 0;
+
+       // assign iterator function pointers.
+       output->Step = VertexIt_Step;
+       output->Fill = VertexIt_Fill;
+       output->Done = VertexIt_Done;
+       output->Reset = VertexIt_Reset;
+       output->num_elements = it->mesh->totvert;
+       output->it = it;
+}
+
+/**
+ * Blender Face iterator
+ */
+
+typedef struct {
+       Mesh *mesh;
+       int pos;
+       int offset;
+} FaceIt;
+
+static void FaceIt_Destruct(CSG_FaceIteratorDescriptor * iterator)
+{
+       MEM_freeN(iterator->it);
+       iterator->Done = NULL;
+       iterator->Fill = NULL;
+       iterator->Reset = NULL;
+       iterator->Step = NULL;
+       iterator->num_elements = 0;
+}
+
+static int FaceIt_Done(CSG_IteratorPtr it)
+{
+       // assume CSG_IteratorPtr is of the correct type.
+       FaceIt * iterator = (FaceIt *)it;
+       return(iterator->pos >= iterator->mesh->totface);
+}
+
+static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face)
+{
+       // assume CSG_IteratorPtr is of the correct type.
+       FaceIt *face_it = (FaceIt *)it;
+       MFace *mfaces = face_it->mesh->mface;
+       MFace *mface = &mfaces[face_it->pos];
+
+       face->vertex_index[0] = mface->v1;
+       face->vertex_index[1] = mface->v2;
+       face->vertex_index[2] = mface->v3;
+       if (mface->v4) {
+               face->vertex_index[3] = mface->v4;
+               face->vertex_number = 4;
+       } else {
+               face->vertex_number = 3;
+       }
+
+       face->orig_face = face_it->offset + face_it->pos;
+}
+
+static void FaceIt_Step(CSG_IteratorPtr it)
+{
+       FaceIt * face_it = (FaceIt *)it;                
+       face_it->pos ++;
+}
+
+static void FaceIt_Reset(CSG_IteratorPtr it)
+{
+       FaceIt * face_it = (FaceIt *)it;                
+       face_it->pos = 0;
+}      
+
+static void FaceIt_Construct(
+       CSG_FaceIteratorDescriptor *output, Object *ob, int offset)
+{
+       FaceIt *it;
+       if (output == 0) return;
+
+       // allocate some memory for blender iterator
+       it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt),"Boolean_FIt"));
+       if (it == 0) {
+               return ;
+       }
+       // assign blender specific variables
+       it->mesh = ob->data;
+       it->offset = offset;
+       it->pos = 0;
+
+       // assign iterator function pointers.
+       output->Step = FaceIt_Step;
+       output->Fill = FaceIt_Fill;
+       output->Done = FaceIt_Done;
+       output->Reset = FaceIt_Reset;
+       output->num_elements = it->mesh->totface;
+       output->it = it;
+}
+
+static Object *AddNewBlenderMesh(Scene *scene, Base *base)
+{
+       // This little function adds a new mesh object to the blender object list
+       // It uses ob to duplicate data as this seems to be easier than creating
+       // a new one. This new oject contains no faces nor vertices.
+       Mesh *old_me;
+       Base *basen;
+       Object *ob_new;
+
+       // now create a new blender object.
+       // duplicating all the settings from the previous object
+       // to the new one.
+       ob_new= copy_object(base->object);
+
+       // Ok we don't want to use the actual data from the
+       // last object, the above function incremented the 
+       // number of users, so decrement it here.
+       old_me= ob_new->data;
+       old_me->id.us--;
+
+       // Now create a new base to add into the linked list of 
+       // vase objects.
+       
+       basen= MEM_mallocN(sizeof(Base), "duplibase");
+       *basen= *base;
+       BLI_addhead(&scene->base, basen);       /* addhead: anders oneindige lus */
+       basen->object= ob_new;
+       basen->flag &= ~SELECT;
+                               
+       // Initialize the mesh data associated with this object.                                                
+       ob_new->data= add_mesh("Mesh");
+       G.totmesh++;
+
+       // Finally assign the object type.
+       ob_new->type= OB_MESH;
+
+       return ob_new;
+}
+
+static void InterpCSGFace(
+       DerivedMesh *dm, Mesh *orig_me, int index, int orig_index, int nr,
+       float mapmat[][4])
+{
+       float obco[3], *co[4], *orig_co[4], w[4][4];
+       MFace *mface, *orig_mface;
+       int j;
+
+       mface = CDDM_get_face(dm, index);
+       orig_mface = orig_me->mface + orig_index;
+
+       // get the vertex coordinates from the original mesh
+       orig_co[0] = (orig_me->mvert + orig_mface->v1)->co;
+       orig_co[1] = (orig_me->mvert + orig_mface->v2)->co;
+       orig_co[2] = (orig_me->mvert + orig_mface->v3)->co;
+       orig_co[3] = (orig_mface->v4)? (orig_me->mvert + orig_mface->v4)->co: NULL;
+
+       // get the vertex coordinates from the new derivedmesh
+       co[0] = CDDM_get_vert(dm, mface->v1)->co;
+       co[1] = CDDM_get_vert(dm, mface->v2)->co;
+       co[2] = CDDM_get_vert(dm, mface->v3)->co;
+       co[3] = (nr == 4)? CDDM_get_vert(dm, mface->v4)->co: NULL;
+
+       for (j = 0; j < nr; j++) {
+               // get coordinate into the space of the original mesh
+               if (mapmat)
+                       VecMat4MulVecfl(obco, mapmat, co[j]);
+               else
+                       VecCopyf(obco, co[j]);
+
+               InterpWeightsQ3Dfl(orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco, w[j]);
+       }
+
+       CustomData_interp(&orig_me->fdata, &dm->faceData, &orig_index, NULL, (float*)w, 1, index);
+}
+
+/* Iterate over the CSG Output Descriptors and create a new DerivedMesh
+   from them */
+static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
+       CSG_FaceIteratorDescriptor *face_it,
+       CSG_VertexIteratorDescriptor *vertex_it,
+       float parinv[][4],
+       float mapmat[][4],
+       Material **mat,
+       int *totmat,
+       Object *ob1,
+       Object *ob2)
+{
+       DerivedMesh *dm;
+       GHash *material_hash = NULL;
+       Mesh *me1= (Mesh*)ob1->data;
+       Mesh *me2= (Mesh*)ob2->data;
+       int i;
+
+       // create a new DerivedMesh
+       dm = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
+
+       CustomData_merge(&me1->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
+                        CD_DEFAULT, face_it->num_elements); 
+       CustomData_merge(&me2->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
+                        CD_DEFAULT, face_it->num_elements); 
+
+       // step through the vertex iterators:
+       for (i = 0; !vertex_it->Done(vertex_it->it); i++) {
+               CSG_IVertex csgvert;
+               MVert *mvert = CDDM_get_vert(dm, i);
+
+               // retrieve a csg vertex from the boolean module
+               vertex_it->Fill(vertex_it->it, &csgvert);
+               vertex_it->Step(vertex_it->it);
+
+               // we have to map the vertex coordinates back in the coordinate frame
+               // of the resulting object, since it was computed in world space
+               VecMat4MulVecfl(mvert->co, parinv, csgvert.position);
+       }
+
+       // a hash table to remap materials to indices
+       if (mat) {
+               material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+               *totmat = 0;
+       }
+
+       // step through the face iterators
+       for(i = 0; !face_it->Done(face_it->it); i++) {
+               Mesh *orig_me;
+               Object *orig_ob;
+               Material *orig_mat;
+               CSG_IFace csgface;
+               MFace *mface;
+               int orig_index, mat_nr;
+
+               // retrieve a csg face from the boolean module
+               face_it->Fill(face_it->it, &csgface);
+               face_it->Step(face_it->it);
+
+               // find the original mesh and data
+               orig_ob = (csgface.orig_face < me1->totface)? ob1: ob2;
+               orig_me = (orig_ob == ob1)? me1: me2;
+               orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - me1->totface;
+
+               // copy all face layers, including mface
+               CustomData_copy_data(&orig_me->fdata, &dm->faceData, orig_index, i, 1);
+
+               // set mface
+               mface = CDDM_get_face(dm, i);
+               mface->v1 = csgface.vertex_index[0];
+               mface->v2 = csgface.vertex_index[1];
+               mface->v3 = csgface.vertex_index[2];
+               mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0;
+
+               // set material, based on lookup in hash table
+               orig_mat= give_current_material(orig_ob, mface->mat_nr+1);
+
+               if (mat && orig_mat) {
+                       if (!BLI_ghash_haskey(material_hash, orig_mat)) {
+                               mat[*totmat] = orig_mat;
+                               mat_nr = mface->mat_nr = (*totmat)++;
+                               BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr));
+                       }
+                       else
+                               mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat));
+               }
+               else
+                       mface->mat_nr = 0;
+
+               InterpCSGFace(dm, orig_me, i, orig_index, csgface.vertex_number,
+                             (orig_me == me2)? mapmat: NULL);
+
+               test_index_face(mface, &dm->faceData, i, csgface.vertex_number);
+       }
+
+       if (material_hash)
+               BLI_ghash_free(material_hash, NULL, NULL);
+
+       CDDM_calc_edges(dm);
+       CDDM_calc_normals(dm);
+
+       return dm;
+}
+       
+static void BuildMeshDescriptors(
+       struct Object *ob,
+       int face_offset,
+       struct CSG_FaceIteratorDescriptor * face_it,
+       struct CSG_VertexIteratorDescriptor * vertex_it)
+{
+       VertexIt_Construct(vertex_it,ob);
+       FaceIt_Construct(face_it,ob,face_offset);
+}
+       
+static void FreeMeshDescriptors(
+       struct CSG_FaceIteratorDescriptor *face_it,
+       struct CSG_VertexIteratorDescriptor *vertex_it)
+{
+       VertexIt_Destruct(vertex_it);
+       FaceIt_Destruct(face_it);
+}
+
+DerivedMesh *NewBooleanDerivedMesh_intern(
+       struct Object *ob, struct Object *ob_select,
+       int int_op_type, Material **mat, int *totmat)
+{
+
+       float inv_mat[4][4];
+       float map_mat[4][4];
+
+       DerivedMesh *dm = NULL;
+       Mesh *me1 = get_mesh(ob_select);
+       Mesh *me2 = get_mesh(ob);
+
+       if (me1 == NULL || me2 == NULL) return 0;
+       if (!me1->totface || !me2->totface) return 0;
+
+       // we map the final object back into ob's local coordinate space. For this
+       // we need to compute the inverse transform from global to ob (inv_mat),
+       // and the transform from ob to ob_select for use in interpolation (map_mat)
+       Mat4Invert(inv_mat, ob->obmat);
+       Mat4MulMat4(map_mat, ob_select->obmat, inv_mat);
+       Mat4Invert(inv_mat, ob_select->obmat);
+
+       {
+               // interface with the boolean module:
+               //
+               // the idea is, we pass the boolean module verts and faces using the
+               // provided descriptors. once the boolean operation is performed, we
+               // get back output descriptors, from which we then build a DerivedMesh
+
+               CSG_VertexIteratorDescriptor vd_1, vd_2;
+               CSG_FaceIteratorDescriptor fd_1, fd_2;
+               CSG_OperationType op_type;
+               CSG_BooleanOperation *bool_op;
+
+               // work out the operation they chose and pick the appropriate 
+               // enum from the csg module.
+               switch (int_op_type) {
+                       case 1 : op_type = e_csg_intersection; break;
+                       case 2 : op_type = e_csg_union; break;
+                       case 3 : op_type = e_csg_difference; break;
+                       case 4 : op_type = e_csg_classify; break;
+                       default : op_type = e_csg_intersection;
+               }
+               
+               BuildMeshDescriptors(ob_select, 0, &fd_1, &vd_1);
+               BuildMeshDescriptors(ob, me1->totface, &fd_2, &vd_2);
+
+               bool_op = CSG_NewBooleanFunction();
+
+               // perform the operation
+               if (CSG_PerformBooleanOperation(bool_op, op_type, fd_1, vd_1, fd_2, vd_2)) {
+                       CSG_VertexIteratorDescriptor vd_o;
+                       CSG_FaceIteratorDescriptor fd_o;
+
+                       CSG_OutputFaceDescriptor(bool_op, &fd_o);
+                       CSG_OutputVertexDescriptor(bool_op, &vd_o);
+
+                       // iterate through results of operation and insert
+                       // into new object
+                       dm = ConvertCSGDescriptorsToDerivedMesh(
+                               &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, ob_select, ob);
+
+                       // free up the memory
+                       CSG_FreeVertexDescriptor(&vd_o);
+                       CSG_FreeFaceDescriptor(&fd_o);
+               }
+//             else
+// XXX                 error("Unknown internal error in boolean");
+
+               CSG_FreeBooleanOperation(bool_op);
+
+               FreeMeshDescriptors(&fd_1, &vd_1);
+               FreeMeshDescriptors(&fd_2, &vd_2);
+       }
+
+       return dm;
+}
+
+int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type)
+{
+       Mesh *me_new;
+       int a, maxmat, totmat= 0;
+       Object *ob_new, *ob, *ob_select;
+       Material **mat;
+       DerivedMesh *dm;
+
+       ob= base->object;
+       ob_select= base_select->object;
+
+       maxmat= ob->totcol + ob_select->totcol;
+       mat= (Material**)MEM_mallocN(sizeof(Material*)*maxmat, "NewBooleanMeshMat");
+       
+       /* put some checks in for nice user feedback */
+       if((!(get_mesh(ob)->totface)) || (!(get_mesh(ob_select)->totface)))
+       {
+               MEM_freeN(mat);
+               return -1;
+       }
+       
+       dm= NewBooleanDerivedMesh_intern(ob, ob_select, int_op_type, mat, &totmat);
+
+       if (dm == NULL) {
+               MEM_freeN(mat);
+               return 0;
+       }
+
+       /* create a new blender mesh object - using 'base' as  a template */
+       ob_new= AddNewBlenderMesh(scene, base_select);
+       me_new= ob_new->data;
+
+       DM_to_mesh(dm, me_new);
+       dm->release(dm);
+
+       /* add materials to object */
+       for (a = 0; a < totmat; a++)
+               assign_material(ob_new, mat[a], a+1);
+
+       MEM_freeN(mat);
+
+       /* update dag */
+       DAG_object_flush_update(scene, ob_new, OB_RECALC_DATA);
+
+       return 1;
+}
+
+DerivedMesh *NewBooleanDerivedMesh(struct Object *ob, struct Object *ob_select,
+                                   int int_op_type)
+{
+       return NewBooleanDerivedMesh_intern(ob, ob_select, int_op_type, NULL, NULL);
+}
+
diff --git a/source/blender/blenkernel/intern/booleanops_mesh.c b/source/blender/blenkernel/intern/booleanops_mesh.c
new file mode 100644 (file)
index 0000000..14e3287
--- /dev/null
@@ -0,0 +1,293 @@
+#if 0
+
+/**
+ * $Id$
+ *
+ * ***** 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 *****
+ */
+#include "CSG_BooleanOps.h"
+
+#include "BKE_booleanops.h"
+#include "BKE_booleanops_mesh.h"
+#include "MEM_guardedalloc.h"
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_displist.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_library.h"
+#include "BKE_material.h"
+
+#include "BLI_arithb.h"
+
+/**
+ * Implementation of boolean ops mesh interface.
+ */
+
+       void
+CSG_DestroyMeshDescriptor(
+       CSG_MeshDescriptor *mesh
+){
+       // Call mesh descriptors destroy function....
+       mesh->m_destroy_func(mesh);
+}
+       
+// Destroy function for blender mesh internals.
+
+static
+       void
+CSG_DestroyBlenderMeshInternals(
+       CSG_MeshDescriptor *mesh
+) {
+       // Free face and vertex iterators.
+       FreeMeshDescriptors(&(mesh->m_face_iterator),&(mesh->m_vertex_iterator));               
+}
+
+
+static
+       void
+CSG_DestroyCSGMeshInternals(
+       CSG_MeshDescriptor *mesh
+){
+       CSG_FreeVertexDescriptor(&(mesh->m_vertex_iterator));
+       CSG_FreeFaceDescriptor(&(mesh->m_face_iterator));
+}
+
+static
+       int
+MakeCSGMeshFromBlenderBase(
+       Base * base,
+       CSG_MeshDescriptor * output
+) {
+       Mesh *me;
+       if (output == NULL || base == NULL) return 0;
+
+       me = get_mesh(base->object);
+               
+       output->m_descriptor.user_face_vertex_data_size = 0;
+       output->m_descriptor.user_data_size = sizeof(FaceData);
+
+       output->base = base;
+       
+       BuildMeshDescriptors(
+               base->object,
+               &(output->m_face_iterator),
+               &(output->m_vertex_iterator)
+       );
+
+       output->m_destroy_func = CSG_DestroyBlenderMeshInternals;
+
+       return 1;
+}      
+
+       int
+CSG_LoadBlenderMesh(
+       Object * obj,
+       CSG_MeshDescriptor *output
+){
+
+       Mesh *me;
+       if (output == NULL || obj == NULL) return 0;
+
+       me = get_mesh(obj);
+               
+       output->m_descriptor.user_face_vertex_data_size = 0;
+       output->m_descriptor.user_data_size = sizeof(FaceData);
+
+       output->base = NULL;
+       
+       BuildMeshDescriptors(
+               obj,
+               &(output->m_face_iterator),
+               &(output->m_vertex_iterator)
+       );
+
+       output->m_destroy_func = CSG_DestroyBlenderMeshInternals;
+       output->base = NULL;
+
+       return 1;
+}
+       
+
+
+
+       int
+CSG_AddMeshToBlender(
+       CSG_MeshDescriptor *mesh
+){
+       Mesh *me_new = NULL;
+       Object *ob_new = NULL;
+       float inv_mat[4][4];
+
+       if (mesh == NULL) return 0;
+       if (mesh->base == NULL) return 0;
+
+       Mat4Invert(inv_mat,mesh->base->object->obmat);
+
+       // Create a new blender mesh object - using 'base' as 
+       // a template for the new object.
+       ob_new=  AddNewBlenderMesh(mesh->base);
+
+       me_new = ob_new->data;
+
+       // make sure the iterators are reset.
+       mesh->m_face_iterator.Reset(mesh->m_face_iterator.it);
+       mesh->m_vertex_iterator.Reset(mesh->m_vertex_iterator.it);
+
+       // iterate through results of operation and insert into new object
+       // see subsurf.c 
+
+       ConvertCSGDescriptorsToMeshObject(
+               ob_new,
+               &(mesh->m_descriptor),
+               &(mesh->m_face_iterator),
+               &(mesh->m_vertex_iterator),
+               inv_mat
+       );
+
+       return 1;
+}
+
+       int 
+CSG_PerformOp(
+       CSG_MeshDescriptor *mesh1,
+       CSG_MeshDescriptor *mesh2,
+       int int_op_type,
+       CSG_MeshDescriptor *output
+){
+
+       CSG_OperationType op_type;
+       CSG_BooleanOperation * bool_op = CSG_NewBooleanFunction();
+       int success = 0;
+
+       if (bool_op == NULL) return 0;
+
+       if ((mesh1 == NULL) || (mesh2 == NULL) || (output == NULL)) {
+               return 0;
+       }       
+       if ((int_op_type < 1) || (int_op_type > 3)) return 0;
+
+       switch (int_op_type) {
+               case 1 : op_type = e_csg_intersection; break;
+               case 2 : op_type = e_csg_union; break;
+               case 3 : op_type = e_csg_difference; break;
+               case 4 : op_type = e_csg_classify; break;
+               default : op_type = e_csg_intersection;
+       }
+       
+       output->m_descriptor = CSG_DescibeOperands(bool_op,mesh1->m_descriptor,mesh2->m_descriptor);
+       output->base = mesh1->base;
+
+       if (output->m_descriptor.user_face_vertex_data_size) {
+               // Then use the only interp function supported 
+               success = 
+               CSG_PerformBooleanOperation(
+                       bool_op,
+                       op_type,
+                       mesh1->m_face_iterator,
+                       mesh1->m_vertex_iterator,
+                       mesh2->m_face_iterator,
+                       mesh2->m_vertex_iterator,               
+                       InterpFaceVertexData    
+               );
+       } else {
+               success = 
+               CSG_PerformBooleanOperation(
+                       bool_op,
+                       op_type,
+                       mesh1->m_face_iterator,
+                       mesh1->m_vertex_iterator,
+                       mesh2->m_face_iterator,
+                       mesh2->m_vertex_iterator,               
+                       InterpNoUserData        
+               );
+       }
+
+       if (!success) {
+               CSG_FreeBooleanOperation(bool_op);
+               bool_op = NULL;
+               return 0;
+       }
+               
+       // get the ouput mesh descriptors.
+
+       CSG_OutputFaceDescriptor(bool_op,&(output->m_face_iterator));
+       CSG_OutputVertexDescriptor(bool_op,&(output->m_vertex_iterator));
+       output->m_destroy_func = CSG_DestroyCSGMeshInternals;
+
+       return 1;
+}
+
+       int
+NewBooleanMeshTest(
+       struct Base * base,
+       struct Base * base_select,
+       int op_type
+){
+
+       CSG_MeshDescriptor m1,m2,output;
+       CSG_MeshDescriptor output2,output3;
+       
+       if (!MakeCSGMeshFromBlenderBase(base,&m1)) {
+               return 0;
+       }
+       
+       if (!MakeCSGMeshFromBlenderBase(base_select,&m2)) {
+               return 0;
+       }
+       
+       CSG_PerformOp(&m1,&m2,1,&output);
+       CSG_PerformOp(&m1,&m2,2,&output2);
+       CSG_PerformOp(&m1,&m2,3,&output3);
+
+       if (!CSG_AddMeshToBlender(&output)) {
+               return 0;
+       }
+       if (!CSG_AddMeshToBlender(&output2)) {
+               return 0;
+       }
+       if (!CSG_AddMeshToBlender(&output3)) {
+               return 0;
+       }
+
+       
+       CSG_DestroyMeshDescriptor(&m1);
+       CSG_DestroyMeshDescriptor(&m2);
+       CSG_DestroyMeshDescriptor(&output);
+       CSG_DestroyMeshDescriptor(&output2);
+       CSG_DestroyMeshDescriptor(&output3);
+
+       return 1;
+}
+
+#endif
+
diff --git a/source/blender/editors/interface/keyval.c b/source/blender/editors/interface/keyval.c
new file mode 100644 (file)
index 0000000..f2172ac
--- /dev/null
@@ -0,0 +1,540 @@
+/**
+ * $Id$
+ *
+ * ***** 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 *****
+ */
+
+#include "stdio.h"
+#include "ctype.h"
+#include "string.h"
+
+#include "BKE_global.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "WM_types.h"
+
+char *key_event_to_string(unsigned short event)
+{
+
+       switch(event) {
+       case AKEY:
+               return "A";
+               break;
+       case BKEY:
+               return "B";
+               break;
+       case CKEY:
+               return "C";
+               break;
+       case DKEY:
+               return "D";
+               break;
+       case EKEY:
+               return "E";
+               break;
+       case FKEY:
+               return "F";
+               break;
+       case GKEY:
+               return "G";
+               break;
+       case HKEY:
+               return "H";
+               break;
+       case IKEY:
+               return "I";
+               break;
+       case JKEY:
+               return "J";
+               break;
+       case KKEY:
+               return "K";
+               break;
+       case LKEY:
+               return "L";
+               break;
+       case MKEY:
+               return "M";
+               break;
+       case NKEY:
+               return "N";
+               break;
+       case OKEY:
+               return "O";
+               break;
+       case PKEY:
+               return "P";
+               break;
+       case QKEY:
+               return "Q";
+               break;
+       case RKEY:
+               return "R";
+               break;
+       case SKEY:
+               return "S";
+               break;
+       case TKEY:
+               return "T";
+               break;
+       case UKEY:
+               return "U";
+               break;
+       case VKEY:
+               return "V";
+               break;
+       case WKEY:
+               return "W";
+               break;
+       case XKEY:
+               return "X";
+               break;
+       case YKEY:
+               return "Y";
+               break;
+       case ZKEY:
+               return "Z";
+               break;
+
+       case ZEROKEY:
+               return "Zero";
+               break;
+       case ONEKEY:
+               return "One";
+               break;
+       case TWOKEY:
+               return "Two";
+               break;
+       case THREEKEY:
+               return "Three";
+               break;
+       case FOURKEY:
+               return "Four";
+               break;
+       case FIVEKEY:
+               return "Five";
+               break;
+       case SIXKEY:
+               return "Six";
+               break;
+       case SEVENKEY:
+               return "Seven";
+               break;
+       case EIGHTKEY:
+               return "Eight";
+               break;
+       case NINEKEY:
+               return "Nine";
+               break;
+
+       case LEFTCTRLKEY:
+               return "Leftctrl";
+               break;
+       case LEFTALTKEY:
+               return "Leftalt";
+               break;
+       case    RIGHTALTKEY:
+               return "Rightalt";
+               break;
+       case    RIGHTCTRLKEY:
+               return "Rightctrl";
+               break;
+       case RIGHTSHIFTKEY:
+               return "Rightshift";
+               break;
+       case LEFTSHIFTKEY:
+               return "Leftshift";
+               break;
+
+       case ESCKEY:
+               return "Esc";
+               break;
+       case TABKEY:
+               return "Tab";
+               break;
+       case RETKEY:
+               return "Ret";
+               break;
+       case SPACEKEY:
+               return "Space";
+               break;
+       case LINEFEEDKEY:
+               return "Linefeed";
+               break;
+       case BACKSPACEKEY:
+               return "Backspace";
+               break;
+       case DELKEY:
+               return "Del";
+               break;
+       case SEMICOLONKEY:
+               return "Semicolon";
+               break;
+       case PERIODKEY:
+               return "Period";
+               break;
+       case COMMAKEY:
+               return "Comma";
+               break;
+       case QUOTEKEY:
+               return "Quote";
+               break;
+       case ACCENTGRAVEKEY:
+               return "Accentgrave";
+               break;
+       case MINUSKEY:
+               return "Minus";
+               break;
+       case SLASHKEY:
+               return "Slash";
+               break;
+       case BACKSLASHKEY:
+               return "Backslash";
+               break;
+       case EQUALKEY:
+               return "Equal";
+               break;
+       case LEFTBRACKETKEY:
+               return "Leftbracket";
+               break;
+       case RIGHTBRACKETKEY:
+               return "Rightbracket";
+               break;
+
+       case LEFTARROWKEY:
+               return "Leftarrow";
+               break;
+       case DOWNARROWKEY:
+               return "Downarrow";
+               break;
+       case RIGHTARROWKEY:
+               return "Rightarrow";
+               break;
+       case UPARROWKEY:
+               return "Uparrow";
+               break;
+
+       case PAD2:
+               return "Pad2";
+               break;
+       case PAD4:
+               return "Pad4";
+               break;
+       case PAD6:
+               return "Pad6";
+               break;
+       case PAD8:
+               return "Pad8";
+               break;
+       case PAD1:
+               return "Pad1";
+               break;
+       case PAD3:
+               return "Pad3";
+               break;
+       case PAD5:
+               return "Pad5";
+               break;
+       case PAD7:
+               return "Pad7";
+               break;
+       case PAD9:
+               return "Pad9";
+               break;
+
+       case PADPERIOD:
+               return "Padperiod";
+               break;
+       case PADSLASHKEY:
+               return "Padslash";
+               break;
+       case PADASTERKEY:
+               return "Padaster";
+               break;
+
+       case PAD0:
+               return "Pad0";
+               break;
+       case PADMINUS:
+               return "Padminus";
+               break;
+       case PADENTER:
+               return "Padenter";
+               break;
+       case PADPLUSKEY:
+               return "Padplus";
+               break;
+
+       case    F1KEY:
+               return "F1";
+               break;
+       case    F2KEY:
+               return "F2";
+               break;
+       case    F3KEY:
+               return "F3";
+               break;
+       case    F4KEY:
+               return "F4";
+               break;
+       case    F5KEY:
+               return "F5";
+               break;
+       case    F6KEY:
+               return "F6";
+               break;
+       case    F7KEY:
+               return "F7";
+               break;
+       case    F8KEY:
+               return "F8";
+               break;
+       case    F9KEY:
+               return "F9";
+               break;
+       case    F10KEY:
+               return "F10";
+               break;
+       case    F11KEY:
+               return "F11";
+               break;
+       case    F12KEY:
+               return "F12";
+               break;
+
+       case    PAUSEKEY:
+               return "Pause";
+               break;
+       case    INSERTKEY:
+               return "Insert";
+               break;
+       case    HOMEKEY:
+               return "Home";
+               break;
+       case    PAGEUPKEY:
+               return "Pageup";
+               break;
+       case    PAGEDOWNKEY:
+               return "Pagedown";
+               break;
+       case    ENDKEY:
+               return "End";
+               break;
+       }
+       
+       return "";
+}
+
+/* 
+ * Decodes key combination strings [qual1+[qual2+[...]]]keyname
+ * The '+'s may be replaced by '-' or ' ' characters to support different
+ * formats. No additional whitespace is allowed. The keyname may be an internal
+ * name, like "RETKEY", or a more common name, like "Return". Decoding is case-
+ * insensitive.
+ *
+ * Example strings: "Ctrl+L", "ALT-ESC", "Shift A"
+ *
+ * Returns 1 if successful. 
+ */
+int decode_key_string(char *str, unsigned short *key, unsigned short *qual)
+{
+       int i, prev, len, invalid=0;
+
+       len= strlen(str);
+       *key= *qual= 0;
+
+       /* Convert to upper case */
+       for (i=0; i<len; i++) {
+               str[i]= toupper(str[i]);
+       }
+
+       /* Handle modifiers */
+       for (prev=i=0; i<len; i++) {
+               if (str[i]==' ' || str[i]=='+' || str[i]=='-') {
+// XXX                 if (!strncmp(str+prev, "CTRL", i-prev)) *qual |= LR_CTRLKEY;
+//                     else if (!strncmp(str+prev, "ALT", i-prev)) *qual |= LR_ALTKEY;
+//                     else if (!strncmp(str+prev, "SHIFT", i-prev)) *qual |= LR_SHIFTKEY;
+//                     else if (!strncmp(str+prev, "COMMAND", i-prev)) *qual |= LR_COMMANDKEY;
+                       prev=i+1;
+               }
+       }
+
+       /* Compare last part against key names */
+       if ((len-prev==1) || ((len-prev==4) && !strncmp(str+prev, "KEY", 3))) {
+               
+               if (str[prev]>='A' && str[prev]<='Z') {
+                       *key= str[prev]-'A'+AKEY;
+               } else if (str[prev]>='0' && str[prev]<='9') {
+                       *key= str[prev]-'0'+ZEROKEY;
+               } else {
+                       invalid= 1;
+               }
+       
+       } else if (!strncmp(str+prev, "ZEROKEY", len-prev) || !strncmp(str+prev, "ZERO", len-prev)) {
+               *key= ZEROKEY;
+       } else if (!strncmp(str+prev, "ONEKEY", len-prev) || !strncmp(str+prev, "ONE", len-prev)) {
+               *key= ONEKEY;
+       } else if (!strncmp(str+prev, "TWOKEY", len-prev) || !strncmp(str+prev, "TWO", len-prev)) {
+               *key= TWOKEY;
+       } else if (!strncmp(str+prev, "THREEKEY", len-prev) || !strncmp(str+prev, "THREE", len-prev)) {
+               *key= THREEKEY;
+       } else if (!strncmp(str+prev, "FOURKEY", len-prev) || !strncmp(str+prev, "FOUR", len-prev)) {
+               *key= FOURKEY;
+       } else if (!strncmp(str+prev, "FIVEKEY", len-prev) || !strncmp(str+prev, "FIVE", len-prev)) {
+               *key= FIVEKEY;
+       } else if (!strncmp(str+prev, "SIZEKEY", len-prev) || !strncmp(str+prev, "SIX", len-prev)) {
+               *key= SIXKEY;
+       } else if (!strncmp(str+prev, "SEVENKEY", len-prev) || !strncmp(str+prev, "SEVEN", len-prev)) {
+               *key= SEVENKEY;
+       } else if (!strncmp(str+prev, "EIGHTKEY", len-prev) || !strncmp(str+prev, "EIGHT", len-prev)) {
+               *key= EIGHTKEY;
+       } else if (!strncmp(str+prev, "NINEKEY", len-prev) || !strncmp(str+prev, "NINE", len-prev)) {
+               *key= NINEKEY;
+
+       } else if (!strncmp(str+prev, "ESCKEY", len-prev) || !strncmp(str+prev, "ESC", len-prev)) {
+               *key= ESCKEY;
+       } else if (!strncmp(str+prev, "TABKEY", len-prev) || !strncmp(str+prev, "TAB", len-prev)) {
+               *key= TABKEY;
+       } else if (!strncmp(str+prev, "RETKEY", len-prev) || !strncmp(str+prev, "RETURN", len-prev) || !strncmp(str+prev, "ENTER", len-prev)) {
+               *key= RETKEY;
+       } else if (!strncmp(str+prev, "SPACEKEY", len-prev) || !strncmp(str+prev, "SPACE", len-prev)) {
+               *key= SPACEKEY;
+       } else if (!strncmp(str+prev, "LINEFEEDKEY", len-prev) || !strncmp(str+prev, "LINEFEED", len-prev)) {
+               *key= LINEFEEDKEY;
+       } else if (!strncmp(str+prev, "BACKSPACEKEY", len-prev) || !strncmp(str+prev, "BACKSPACE", len-prev)) {
+               *key= BACKSPACEKEY;
+       } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) {
+               *key= DELKEY;
+       
+       } else if (!strncmp(str+prev, "SEMICOLONKEY", len-prev) || !strncmp(str+prev, "SEMICOLON", len-prev)) {
+               *key= SEMICOLONKEY;
+       } else if (!strncmp(str+prev, "PERIODKEY", len-prev) || !strncmp(str+prev, "PERIOD", len-prev)) {
+               *key= PERIODKEY;
+       } else if (!strncmp(str+prev, "COMMAKEY", len-prev) || !strncmp(str+prev, "COMMA", len-prev)) {
+               *key= COMMAKEY;
+       } else if (!strncmp(str+prev, "QUOTEKEY", len-prev) || !strncmp(str+prev, "QUOTE", len-prev)) {
+               *key= QUOTEKEY;
+       } else if (!strncmp(str+prev, "ACCENTGRAVEKEY", len-prev) || !strncmp(str+prev, "ACCENTGRAVE", len-prev)) {
+               *key= ACCENTGRAVEKEY;
+       } else if (!strncmp(str+prev, "MINUSKEY", len-prev) || !strncmp(str+prev, "MINUS", len-prev)) {
+               *key= MINUSKEY;
+       } else if (!strncmp(str+prev, "SLASHKEY", len-prev) || !strncmp(str+prev, "SLASH", len-prev)) {
+               *key= SLASHKEY;
+       } else if (!strncmp(str+prev, "BACKSLASHKEY", len-prev) || !strncmp(str+prev, "BACKSLASH", len-prev)) {
+               *key= BACKSLASHKEY;
+       } else if (!strncmp(str+prev, "EQUALKEY", len-prev) || !strncmp(str+prev, "EQUAL", len-prev)) {
+               *key= EQUALKEY;
+       } else if (!strncmp(str+prev, "LEFTBRACKETKEY", len-prev) || !strncmp(str+prev, "LEFTBRACKET", len-prev)) {
+               *key= LEFTBRACKETKEY;
+       } else if (!strncmp(str+prev, "RIGHTBRACKETKEY", len-prev) || !strncmp(str+prev, "RIGHTBRACKET", len-prev)) {
+               *key= RIGHTBRACKETKEY;
+       } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) {
+               *key= DELKEY;
+       
+       } else if (!strncmp(str+prev, "LEFTARROWKEY", len-prev) || !strncmp(str+prev, "LEFTARROW", len-prev)) {
+               *key= LEFTARROWKEY;
+       } else if (!strncmp(str+prev, "DOWNARROWKEY", len-prev) || !strncmp(str+prev, "DOWNARROW", len-prev)) {
+               *key= DOWNARROWKEY;
+       } else if (!strncmp(str+prev, "RIGHTARROWKEY", len-prev) || !strncmp(str+prev, "RIGHTARROW", len-prev)) {
+               *key= RIGHTARROWKEY;
+       } else if (!strncmp(str+prev, "UPARROWKEY", len-prev) || !strncmp(str+prev, "UPARROW", len-prev)) {
+               *key= UPARROWKEY;
+
+       } else if (!strncmp(str+prev, "PAD", 3)) {
+               
+               if (len-prev<=4) {
+               
+                       if (str[prev]>='0' && str[prev]<='9') {
+                               *key= str[prev]-'0'+ZEROKEY;
+                       } else {
+                               invalid= 1;
+                       }
+               
+               } else if (!strncmp(str+prev+3, "PERIODKEY", len-prev-3) || !strncmp(str+prev+3, "PERIOD", len-prev-3)) {
+                       *key= PADPERIOD;
+               } else if (!strncmp(str+prev+3, "SLASHKEY", len-prev-3) || !strncmp(str+prev+3, "SLASH", len-prev-3)) {
+                       *key= PADSLASHKEY;
+               } else if (!strncmp(str+prev+3, "ASTERKEY", len-prev-3) || !strncmp(str+prev+3, "ASTERISK", len-prev-3)) {
+                       *key= PADASTERKEY;
+               } else if (!strncmp(str+prev+3, "MINUSKEY", len-prev-3) || !strncmp(str+prev+3, "MINUS", len-prev-3)) {
+                       *key= PADMINUS;
+               } else if (!strncmp(str+prev+3, "ENTERKEY", len-prev-3) || !strncmp(str+prev+3, "ENTER", len-prev-3)) {
+                       *key= PADENTER;
+               } else if (!strncmp(str+prev+3, "PLUSKEY", len-prev-3) || !strncmp(str+prev+3, "PLUS", len-prev-3)) {
+                       *key= PADPLUSKEY;
+               } else {
+                       invalid= 1;
+               }
+
+       } else if (!strncmp(str+prev, "F1KEY", len-prev) || !strncmp(str+prev, "F1", len-prev)) {
+               *key= F1KEY;
+       } else if (!strncmp(str+prev, "F2KEY", len-prev) || !strncmp(str+prev, "F2", len-prev)) {
+               *key= F2KEY;
+       } else if (!strncmp(str+prev, "F3KEY", len-prev) || !strncmp(str+prev, "F3", len-prev)) {
+               *key= F3KEY;
+       } else if (!strncmp(str+prev, "F4KEY", len-prev) || !strncmp(str+prev, "F4", len-prev)) {
+               *key= F4KEY;
+       } else if (!strncmp(str+prev, "F5KEY", len-prev) || !strncmp(str+prev, "F5", len-prev)) {
+               *key= F5KEY;
+       } else if (!strncmp(str+prev, "F6KEY", len-prev) || !strncmp(str+prev, "F6", len-prev)) {
+               *key= F6KEY;
+       } else if (!strncmp(str+prev, "F7KEY", len-prev) || !strncmp(str+prev, "F7", len-prev)) {
+               *key= F7KEY;
+       } else if (!strncmp(str+prev, "F8KEY", len-prev) || !strncmp(str+prev, "F8", len-prev)) {
+               *key= F8KEY;
+       } else if (!strncmp(str+prev, "F9KEY", len-prev) || !strncmp(str+prev, "F9", len-prev)) {
+               *key= F9KEY;
+       } else if (!strncmp(str+prev, "F10KEY", len-prev) || !strncmp(str+prev, "F10", len-prev)) {
+               *key= F10KEY;
+       } else if (!strncmp(str+prev, "F11KEY", len-prev) || !strncmp(str+prev, "F11", len-prev)) {
+               *key= F11KEY;
+       } else if (!strncmp(str+prev, "F12KEY", len-prev) || !strncmp(str+prev, "F12", len-prev)) {
+               *key= F12KEY;
+
+       } else if (!strncmp(str+prev, "PAUSEKEY", len-prev) || !strncmp(str+prev, "PAUSE", len-prev)) {
+               *key= PAUSEKEY;
+       } else if (!strncmp(str+prev, "INSERTKEY", len-prev) || !strncmp(str+prev, "INSERT", len-prev)) {
+               *key= INSERTKEY;
+       } else if (!strncmp(str+prev, "HOMEKEY", len-prev) || !strncmp(str+prev, "HOME", len-prev)) {
+               *key= HOMEKEY;
+       } else if (!strncmp(str+prev, "PAGEUPKEY", len-prev) || !strncmp(str+prev, "PAGEUP", len-prev)) {
+               *key= PAGEUPKEY;
+       } else if (!strncmp(str+prev, "PAGEDOWNKEY", len-prev) || !strncmp(str+prev, "PAGEDOWN", len-prev)) {
+               *key= PAGEDOWNKEY;
+       } else if (!strncmp(str+prev, "ENDKEY", len-prev) || !strncmp(str+prev, "END", len-prev)) {
+               *key= ENDKEY;
+       
+       } else {
+               invalid= 1;
+       }
+
+       if (!invalid && *key) {
+               return 1;
+       }
+       
+       return 0;
+}
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
new file mode 100644 (file)
index 0000000..34094c9
--- /dev/null
@@ -0,0 +1,131 @@
+/**
+ * $Id$
+ *
+ * ***** 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.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * Making screendumps.
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+static unsigned int *dumprect= NULL;
+static int dumpsx, dumpsy;
+
+/* XXX */
+static int saveover() {return 0;}
+
+/* Callback */
+void write_screendump(bContext *C, char *name)
+{
+       Scene *scene= CTX_data_scene(C);
+       ImBuf *ibuf;
+       
+       if(dumprect) {
+
+               strcpy(G.ima, name);
+               BLI_convertstringcode(name, G.sce);
+               BLI_convertstringframe(name, scene->r.cfra); /* TODO - is this ever used? */
+               
+               /* BKE_add_image_extension() checks for if extension was already set */
+               if(scene->r.scemode & R_EXTENSION) 
+                       if(strlen(name)<FILE_MAXDIR+FILE_MAXFILE-5)
+                               BKE_add_image_extension(scene, name, scene->r.imtype);
+               
+               if(saveover(name)) {
+//                     waitcursor(1);
+                       
+                       ibuf= IMB_allocImBuf(dumpsx, dumpsy, 24, 0, 0);
+                       ibuf->rect= dumprect;
+                       
+                       if(scene->r.planes == 8) IMB_cspace(ibuf, rgb_to_bw);
+                       
+                       BKE_write_ibuf(scene, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality);
+
+                       IMB_freeImBuf(ibuf);
+               
+//                     waitcursor(0);
+               }
+               MEM_freeN(dumprect);
+               dumprect= NULL;
+       }
+}
+
+/* get dump from frontbuffer */
+void ED_screendump(bContext *C, int fscreen)
+{
+       wmWindow *win= CTX_wm_window(C);
+       ScrArea *curarea= CTX_wm_area(C);
+       int x=0, y=0;
+//     char imstr[64];
+
+       if(dumprect) MEM_freeN(dumprect);
+       dumprect= NULL;
+       
+       if(fscreen) {   /* full screen */
+               x= 0;
+               y= 0;
+               dumpsx= win->sizex;
+               dumpsy= win->sizey;
+               
+       } 
+       else {
+               x= curarea->totrct.xmin;
+               y= curarea->totrct.ymin;
+               dumpsx= curarea->totrct.xmax-x;
+               dumpsy= curarea->totrct.ymax-y;
+       }
+       
+       if (dumpsx && dumpsy) {
+               
+               dumprect= MEM_mallocN(sizeof(int)*dumpsx*dumpsy, "dumprect");
+               glReadBuffer(GL_FRONT);
+               glReadPixels(x, y, dumpsx, dumpsy, GL_RGBA, GL_UNSIGNED_BYTE, dumprect);
+               glFinish();
+               glReadBuffer(GL_BACK);
+
+               //                      save_image_filesel_str(imstr);
+               //                      activate_fileselect(FILE_SPECIAL, imstr, G.ima, write_screendump);
+       }
+
+}