Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_booleanops.h5
-rw-r--r--source/blender/blenkernel/SConscript2
-rw-r--r--source/blender/blenkernel/intern/Makefile1
-rw-r--r--source/blender/blenkernel/intern/booleanops.c567
-rw-r--r--source/blender/blenkernel/intern/booleanops_mesh.c293
-rw-r--r--source/blender/editors/interface/keyval.c540
-rw-r--r--source/blender/editors/screen/screendump.c131
7 files changed, 1536 insertions, 3 deletions
diff --git a/source/blender/blenkernel/BKE_booleanops.h b/source/blender/blenkernel/BKE_booleanops.h
index b83b9c89ae8..b51ee2646fc 100644
--- a/source/blender/blenkernel/BKE_booleanops.h
+++ b/source/blender/blenkernel/BKE_booleanops.h
@@ -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
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 9fef30381a8..a6b7120d72a 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -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']
diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile
index 3d8a47e3683..acb1fd2deb6 100644
--- a/source/blender/blenkernel/intern/Makefile
+++ b/source/blender/blenkernel/intern/Makefile
@@ -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
index 00000000000..51c47746b99
--- /dev/null
+++ b/source/blender/blenkernel/intern/booleanops.c
@@ -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
index 00000000000..14e32873dbd
--- /dev/null
+++ b/source/blender/blenkernel/intern/booleanops_mesh.c
@@ -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
index 00000000000..f2172ac8cf0
--- /dev/null
+++ b/source/blender/editors/interface/keyval.c
@@ -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
index 00000000000..34094c99120
--- /dev/null
+++ b/source/blender/editors/screen/screendump.c
@@ -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);
+ }
+
+}