2.5
More files back in the 2.5 repo: (Note, boolean stuff moved to blenkernel)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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
|
||||
|
||||
567
source/blender/blenkernel/intern/booleanops.c
Normal file
567
source/blender/blenkernel/intern/booleanops.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
293
source/blender/blenkernel/intern/booleanops_mesh.c
Normal file
293
source/blender/blenkernel/intern/booleanops_mesh.c
Normal file
@@ -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
|
||||
|
||||
540
source/blender/editors/interface/keyval.c
Normal file
540
source/blender/editors/interface/keyval.c
Normal file
@@ -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;
|
||||
}
|
||||
131
source/blender/editors/screen/screendump.c
Normal file
131
source/blender/editors/screen/screendump.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user