diff options
author | Joseph Eagar <joeedh@gmail.com> | 2009-01-09 21:32:33 +0300 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2009-01-09 21:32:33 +0300 |
commit | dbe6735ae5a33f9763e1eb58478bb562e421f65b (patch) | |
tree | 5ba1d86f8083a2858da0fe9b7b44022eed8282a9 /source | |
parent | 4746ada4e3618834103f392a1dc9bfcba159f80d (diff) | |
parent | e60be63d23bce8c8fe9b749a17c1f3dc3fd56711 (diff) |
merge with 2.5 at revision 18432, made bmesh compile, and also made msvc use incremental linking under scons
Diffstat (limited to 'source')
103 files changed, 7840 insertions, 936 deletions
diff --git a/source/Makefile b/source/Makefile index 2cacdf27985..29f3614666b 100644 --- a/source/Makefile +++ b/source/Makefile @@ -237,8 +237,8 @@ PULIB += $(OCGDIR)/blender/ed_time/libed_time.a PULIB += $(OCGDIR)/blender/ed_view3d/libed_view3d.a PULIB += $(OCGDIR)/blender/ed_interface/libed_interface.a PULIB += $(OCGDIR)/blender/ed_object/libed_object.a -PULIB += $(OCGDIR)/blender/ed_mesh/libed_mesh.a PULIB += $(OCGDIR)/blender/ed_armature/libed_armature.a +PULIB += $(OCGDIR)/blender/ed_mesh/libed_mesh.a PULIB += $(OCGDIR)/blender/ed_animation/libed_animation.a PULIB += $(OCGDIR)/blender/ed_transform/libed_transform.a PULIB += $(OCGDIR)/blender/ed_util/libed_util.a diff --git a/source/blender/SConscript b/source/blender/SConscript index 93acf8a8430..cd00776440a 100644 --- a/source/blender/SConscript +++ b/source/blender/SConscript @@ -3,6 +3,7 @@ Import ('env') import sys SConscript(['avi/SConscript', + 'bmesh/SConscript', 'blenkernel/SConscript', 'blenlib/SConscript', 'blenloader/SConscript', 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/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index 181c0cec45a..c0a6dc48d47 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -47,9 +47,11 @@ struct Lattice *copy_lattice(struct Lattice *lt); void free_lattice(struct Lattice *lt); void make_local_lattice(struct Lattice *lt); void calc_lat_fudu(int flag, int res, float *fu, float *du); + void init_latt_deform(struct Object *oblatt, struct Object *ob); -void calc_latt_deform(float *co, float weight); -void end_latt_deform(void); +void calc_latt_deform(struct Object *, float *co, float weight); +void end_latt_deform(struct Object *); + int object_deform_mball(struct Object *ob); void outside_lattice(struct Lattice *lt); diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 04b27f7bf3c..7604dc8170b 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -115,6 +115,9 @@ typedef struct ARegionType { /* return context data */ int (*context)(const struct bContext *, const void *, struct bContextDataResult *); + /* custom drawing callbacks */ + ListBase drawcalls; + /* hardcoded constraints, smaller than these values region is not visible */ int minsizex, minsizey; /* default keymaps to add */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 8f11928e63f..3948a2bf2af 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -33,6 +33,7 @@ SET(INC ../../../intern/iksolver/extern ../blenloader ../quicktime ../../../intern/bmfont ../../../extern/bullet2/src ../nodes ../../../extern/glew/include ../gpu ../makesrna + ../../../intern/bsp/extern ${SDL_INC} ${ZLIB_INC} ) 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/anim.c b/source/blender/blenkernel/intern/anim.c index 2845867b920..6a6d8c46f9e 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -946,8 +946,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p MEM_freeN(obcopylist); if(psys->lattice) { - end_latt_deform(); - psys->lattice = 0; + end_latt_deform(psys->lattice); + psys->lattice = NULL; } } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 262a2b35713..6f88d3381a9 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -378,7 +378,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename) /* last stage of do_versions actually, that sets recalc flags for recalc poses */ for(ob= G.main->object.first; ob; ob= ob->id.next) { if(ob->type==OB_ARMATURE) - if(ob->recalc) object_handle_update(curscene, ob); + if(ob->recalc) object_handle_update(CTX_data_scene(C), ob); } /* now tag update flags, to ensure deformers get calculated on redraw */ 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/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 85256045d49..46e7022c718 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -74,7 +74,6 @@ //XXX #include "BIF_editdeform.h" Lattice *editLatt=0; -static float *latticedata=0, latmat[4][4]; void calc_lat_fudu(int flag, int res, float *fu, float *du) { @@ -303,23 +302,23 @@ void init_latt_deform(Object *oblatt, Object *ob) if(lt->editlatt) lt= lt->editlatt; bp = lt->def; - fp= latticedata= MEM_mallocN(sizeof(float)*3*lt->pntsu*lt->pntsv*lt->pntsw, "latticedata"); + fp= lt->latticedata= MEM_mallocN(sizeof(float)*3*lt->pntsu*lt->pntsv*lt->pntsw, "latticedata"); /* for example with a particle system: ob==0 */ - if(ob==0) { + if(ob==NULL) { /* in deformspace, calc matrix */ - Mat4Invert(latmat, oblatt->obmat); + Mat4Invert(lt->latmat, oblatt->obmat); /* back: put in deform array */ - Mat4Invert(imat, latmat); + Mat4Invert(imat, lt->latmat); } else { /* in deformspace, calc matrix */ Mat4Invert(imat, oblatt->obmat); - Mat4MulMat4(latmat, ob->obmat, imat); + Mat4MulMat4(lt->latmat, ob->obmat, imat); /* back: put in deform array */ - Mat4Invert(imat, latmat); + Mat4Invert(imat, lt->latmat); } for(w=0,fw=lt->fw; w<lt->pntsw; w++,fw+=lt->dw) { @@ -341,19 +340,20 @@ void init_latt_deform(Object *oblatt, Object *ob) } } -void calc_latt_deform(float *co, float weight) +void calc_latt_deform(Object *ob, float *co, float weight) { - Lattice *lt; + Lattice *lt= ob->data; float u, v, w, tu[4], tv[4], tw[4]; float *fpw, *fpv, *fpu, vec[3]; int ui, vi, wi, uu, vv, ww; - if(latticedata==0) return; + if(lt->editlatt) lt= lt->editlatt; + if(lt->latticedata==NULL) return; /* co is in local coords, treat with latmat */ VECCOPY(vec, co); - Mat4MulVecfl(latmat, vec); + Mat4MulVecfl(lt->latmat, vec); /* u v w coords */ @@ -395,10 +395,10 @@ void calc_latt_deform(float *co, float weight) if(w!=0.0) { if(ww>0) { - if(ww<lt->pntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv; - else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv; + if(ww<lt->pntsw) fpw= lt->latticedata + 3*ww*lt->pntsu*lt->pntsv; + else fpw= lt->latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv; } - else fpw= latticedata; + else fpw= lt->latticedata; for(vv= vi-1; vv<=vi+2; vv++) { v= w*tv[vv-vi+1]; @@ -431,11 +431,15 @@ void calc_latt_deform(float *co, float weight) } } -void end_latt_deform() +void end_latt_deform(Object *ob) { - - MEM_freeN(latticedata); - latticedata= 0; + Lattice *lt= ob->data; + + if(lt->editlatt) lt= lt->editlatt; + + if(lt->latticedata) + MEM_freeN(lt->latticedata); + lt->latticedata= NULL; } /* calculations is in local space of deformed object @@ -767,17 +771,17 @@ void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm, if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); for(j = 0; j < dvert->totweight; j++) { if (dvert->dw[j].def_nr == index) { - calc_latt_deform(vertexCos[a], dvert->dw[j].weight); + calc_latt_deform(laOb, vertexCos[a], dvert->dw[j].weight); } } } } } else { for(a = 0; a < numVerts; a++) { - calc_latt_deform(vertexCos[a], 1.0f); + calc_latt_deform(laOb, vertexCos[a], 1.0f); } } - end_latt_deform(); + end_latt_deform(laOb); } int object_deform_mball(Object *ob) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 069f909289d..56868be6358 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6491,8 +6491,8 @@ static DerivedMesh * particleInstanceModifier_applyModifier( CDDM_calc_normals(result); if(psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } return result; @@ -7267,8 +7267,8 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, CDDM_calc_normals(explode); if(psmd->psys->lattice){ - end_latt_deform(); - psmd->psys->lattice=0; + end_latt_deform(psmd->psys->lattice); + psmd->psys->lattice= NULL; } return explode; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index ef48714b7c3..e9fabf7aa64 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2273,7 +2273,7 @@ void object_handle_update(Scene *scene, Object *ob) /* includes all keys and modifiers */ if(ob->type==OB_MESH) { - makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH); // here was vieweditdatamask? XXX + makeDerivedMesh(scene, ob, ((Mesh*)ob->data)->edit_mesh, CD_MASK_BAREMESH); // here was vieweditdatamask? XXX } else if(ob->type==OB_MBALL) { makeDispListMBall(scene, ob); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index ff4d934ab3d..783881f25bf 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2584,7 +2584,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra /* apply lattice */ if(psys->lattice && edit==0) - calc_latt_deform(ca->co, 1.0f); + calc_latt_deform(psys->lattice, ca->co, 1.0f); /* figure out rotation */ @@ -2664,8 +2664,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra psys->totcached = totpart; if(psys && psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } if(vg_effector) @@ -3473,7 +3473,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i } if(psys->lattice && edit==0) - calc_latt_deform(state->co,1.0f); + calc_latt_deform(psys->lattice, state->co,1.0f); } } } @@ -3696,7 +3696,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0); if(psys->lattice) - calc_latt_deform(state->co,1.0f); + calc_latt_deform(psys->lattice, state->co,1.0f); } else{ if (pa) { /* TODO PARTICLE - should this ever be NULL? - Campbell */ @@ -3748,7 +3748,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy } if(psys->lattice) - calc_latt_deform(state->co,1.0f); + calc_latt_deform(psys->lattice, state->co,1.0f); } } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 336b7037600..8fd12ea50d0 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1495,8 +1495,8 @@ void psys_threads_free(ParticleThread *threads) MEM_freeN(ctx->vg_roughe); if(ctx->psys->lattice){ - end_latt_deform(); - ctx->psys->lattice=0; + end_latt_deform(ctx->psys->lattice); + ctx->psys->lattice= NULL; } /* distribution */ @@ -2629,8 +2629,8 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P } if(epsys->lattice){ - end_latt_deform(); - epsys->lattice=0; + end_latt_deform(epsys->lattice); + epsys->lattice= NULL; } } } @@ -4254,8 +4254,8 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps } if(psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } if(pa->r_rot[0] > disp) @@ -4630,8 +4630,8 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle if(vg_size) MEM_freeN(vg_size); if(psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } } diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index b46d4af8887..fd15c69e775 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -52,6 +52,11 @@ static ListBase spacetypes= {NULL, NULL}; /* not SpaceType itself */ static void spacetype_free(SpaceType *st) { + ARegionType *art; + + for(art= st->regiontypes.first; art; art= art->next) + BLI_freelistN(&art->drawcalls); + BLI_freelistN(&st->regiontypes); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 042516e518e..ac0b819aa6b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3828,7 +3828,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) wm->operators.first= wm->operators.last= NULL; wm->keymaps.first= wm->keymaps.last= NULL; - + wm->paintcursors.first= wm->paintcursors.last= NULL; wm->queue.first= wm->queue.last= NULL; wm->reports.first= wm->reports.last= NULL; diff --git a/source/blender/bmesh/SConscript b/source/blender/bmesh/SConscript index 5cbe5f967f0..d7cfa9ca942 100644 --- a/source/blender/bmesh/SConscript +++ b/source/blender/bmesh/SConscript @@ -29,9 +29,10 @@ incs = ['#/intern/guardedalloc'] incs.append('../blenlib') incs.append('../makesdna') incs.append('../blenkernel') -incs.append('../include') incs.append('./') incs.append('./intern') +incs.append('../editors/mesh') +incs.append('../editors/include') defs = [] env.BlenderLib ( libname = 'bf_bmesh', sources = sources, includes = Split(incs), libtype = 'core', defines=defs, priority=100, compileflags=cflags ) diff --git a/source/blender/bmesh/intern/bmesh_to_editmesh.c b/source/blender/bmesh/intern/bmesh_to_editmesh.c index 8ddcac23bbb..1c2630a9804 100644 --- a/source/blender/bmesh/intern/bmesh_to_editmesh.c +++ b/source/blender/bmesh/intern/bmesh_to_editmesh.c @@ -10,9 +10,11 @@ #include "BKE_global.h" #include "BKE_DerivedMesh.h" #include "BKE_cdderivedmesh.h" + #include "BLI_editVert.h" -#include "BIF_editmesh.h" -#include "editmesh.h" +#include "mesh_intern.h" +#include "ED_mesh.h" + #include "BLI_blenlib.h" #include "BLI_edgehash.h" @@ -88,7 +90,7 @@ static EditVert *bmeshvert_to_editvert(BMesh *bm, EditMesh *em, BMVert *v, int i EditVert *eve = NULL; v->head.eflag1 = index; /*abuse!*/ - eve = addvertlist(v->co, NULL); + eve = addvertlist(em, v->co, NULL); eve->keyindex = index; evlist[index]= eve; @@ -125,8 +127,8 @@ static EditEdge *bmeshedge_to_editedge(BMesh *bm, EditMesh *em, BMEdge *e, EditV { EditEdge *eed = NULL; - if(!(findedgelist(evlist[e->v1->head.eflag1], evlist[e->v2->head.eflag1]))){ - eed= addedgelist(evlist[e->v1->head.eflag1], evlist[e->v2->head.eflag1], NULL); + if(!(findedgelist(em, evlist[e->v1->head.eflag1], evlist[e->v2->head.eflag1]))){ + eed= addedgelist(em, evlist[e->v1->head.eflag1], evlist[e->v2->head.eflag1], NULL); bmeshedge_to_editedge_internal(bm, em, e, eed); } @@ -151,7 +153,7 @@ static EditFace *bmeshface_to_editface(BMesh *bm, EditMesh *em, BMFace *f, EditV eve4= NULL; } - efa = addfacelist(eve1, eve2, eve3, eve4, NULL, NULL); + efa = addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL); bmeshedge_to_editedge_internal(bm, em, f->loopbase->e, efa->e1); bmeshedge_to_editedge_internal(bm, em, ((BMLoop*)(f->loopbase->head.next))->e, efa->e2); @@ -193,10 +195,8 @@ EditMesh *bmesh_to_editmesh_intern(BMesh *bm) int totvert, i, numTex, numCol; - em = G.editMesh; - - if (em == NULL) return NULL; //what? - em->act_face = NULL; + em = MEM_callocN(sizeof(EditMesh), "EditMesh from bmesh"); + em->selectmode= bm->selectmode; CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0); @@ -221,7 +221,6 @@ EditMesh *bmesh_to_editmesh_intern(BMesh *bm) bmeshface_to_editface(bm, em, f, evlist, numCol, numTex); MEM_freeN(evlist); - countall(); return em; } diff --git a/source/blender/bmesh/intern/editmesh_to_bmesh.c b/source/blender/bmesh/intern/editmesh_to_bmesh.c index 26c1a821fca..062a71181cf 100644 --- a/source/blender/bmesh/intern/editmesh_to_bmesh.c +++ b/source/blender/bmesh/intern/editmesh_to_bmesh.c @@ -10,9 +10,11 @@ #include "BKE_global.h" #include "BKE_DerivedMesh.h" #include "BKE_cdderivedmesh.h" + #include "BLI_editVert.h" -#include "BIF_editmesh.h" -#include "editmesh.h" +#include "mesh_intern.h" +#include "ED_mesh.h" + #include "BLI_blenlib.h" #include "BLI_edgehash.h" @@ -336,7 +338,7 @@ BMesh *editmesh_to_bmesh_intern(EditMesh *em, BMesh *bm) { int allocsize[4] = {512,512,2048,512}, numTex, numCol; /*make sure to update FGon flags*/ - EM_fgon_flags(); + EM_fgon_flags(em); /*copy custom data layout*/ CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0); @@ -356,9 +358,9 @@ BMesh *editmesh_to_bmesh_intern(EditMesh *em, BMesh *bm) { /*copy over selection mode*/ bm->selectmode = 0; - if(G.scene->selectmode & SCE_SELECT_VERTEX) bm->selectmode |= BM_VERT; - if(G.scene->selectmode & SCE_SELECT_EDGE) bm->selectmode |= BM_EDGE; - if(G.scene->selectmode & SCE_SELECT_FACE) bm->selectmode |= BM_FACE; + if(bm->selectmode & SCE_SELECT_VERTEX) bm->selectmode |= BM_VERT; + if(bm->selectmode & SCE_SELECT_EDGE) bm->selectmode |= BM_EDGE; + if(bm->selectmode & SCE_SELECT_FACE) bm->selectmode |= BM_FACE; /*begin editloop*/ diff --git a/source/blender/editors/armature/SConscript b/source/blender/editors/armature/SConscript index 95f20404c4b..e4e42a27b36 100644 --- a/source/blender/editors/armature/SConscript +++ b/source/blender/editors/armature/SConscript @@ -8,4 +8,4 @@ incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../render/extern/include #/intern/guardedalloc #intern/bmfont' incs += ' ../../gpu ../../makesrna #/intern/opennl/extern' -env.BlenderLib ( 'bf_editors_armature', sources, Split(incs), [], libtype=['core'], priority=[100] ) +env.BlenderLib ( 'bf_editors_armature', sources, Split(incs), [], libtype=['core'], priority=[44] ) diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 42d3629e3dd..06855d4446d 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -101,12 +101,8 @@ static void adduplicate() {} static void countall() {} static void vertexgroup_select_by_name() {} static void deselect_actionchannels() {} -static void *add_defgroup_name() {return NULL;} static void add_vert_to_defgroup() {} -#define WEIGHT_REPLACE 0 static void create_dverts() {} -static void remove_vert_defgroup() {} -static int mesh_get_x_mirror_vert() {return 0;} static void select_actionchannel_by_name() {} /* ************* XXX *************** */ @@ -1834,7 +1830,7 @@ void ED_armature_to_edit(Object *ob) /* adjust bone roll to align Z axis with vector * vec is in local space and is normalized */ -float rollBoneToVector(EditBone *bone, float new_up_axis[3]) +float ED_rollBoneToVector(EditBone *bone, float new_up_axis[3]) { float mat[3][3], nor[3], up_axis[3], vec[3]; float roll; diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 457e0741399..17d6b25b93b 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -92,6 +92,9 @@ int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int short hits, short extend); void mouse_armature(struct bContext *C, short mval[2], int extend); +float ED_rollBoneToVector(EditBone *bone, float new_up_axis[3]); + +void transform_armature_mirror_update(struct Object *obedit); /* poseobject.c */ void ED_armature_exit_posemode(struct Base *base); diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index c62990a69d9..c0efaab3786 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -28,6 +28,8 @@ #ifndef ED_FILES_H #define ED_FILES_H +struct SpaceFile; + typedef struct FileSelectParams { int type; /* the mode of the filebrowser, FILE_BLENDER, FILE_SPECIAL, FILE_MAIN or FILE_LOADLIB */ char title[24]; /* title, also used for the text of the execute button */ @@ -53,10 +55,12 @@ typedef struct FileSelectParams { /* XXX --- end unused -- */ } FileSelectParams; -FileSelectParams* ED_fileselect_get_params(const struct bContext *C); +FileSelectParams* ED_fileselect_get_params(struct SpaceFile *sfile); -short ED_fileselect_set_params(FileSelectParams *params, int type, const char *title, const char *path, +short ED_fileselect_set_params(struct SpaceFile *sfile, int type, const char *title, const char *path, short flag, short display, short filter); +void ED_fileselect_reset_params(struct SpaceFile *sfile); + #endif /* ED_FILES_H */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index e89bdff5325..02419b9aca9 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -38,6 +38,9 @@ struct bContext; struct wmWindowManager; struct EditSelection; struct ViewContext; +struct bDeformGroup; +struct MDeformWeight; +struct MDeformVert; // edge and face flag both #define EM_FGON 2 @@ -64,6 +67,7 @@ struct ViewContext; intptr_t mesh_octree_table(Object *ob, struct EditMesh *em, float *co, char mode); struct EditVert *editmesh_get_x_mirror_vert(Object *ob, struct EditMesh *em, float *co); +int mesh_get_x_mirror_vert(Object *ob, int index); /* mesh_ops.c */ void ED_operatortypes_mesh(void); @@ -119,6 +123,20 @@ void EM_free_backbuf(void); int EM_init_backbuf_border(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); int EM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short rads); +/* editdeform.c XXX rename functions? */ + +#define WEIGHT_REPLACE 1 +#define WEIGHT_ADD 2 +#define WEIGHT_SUBTRACT 3 + +void add_defgroup (Object *ob); +void remove_vert_defgroup (Object *ob, struct bDeformGroup *dg, int vertnum); +void remove_verts_defgroup (Object *obedit, int allverts); +struct bDeformGroup *add_defgroup_name (Object *ob, char *name); +struct MDeformWeight *verify_defweight (struct MDeformVert *dv, int defgroup); +struct MDeformWeight *get_defweight (struct MDeformVert *dv, int defgroup); +bDeformGroup *add_defgroup_name (Object *ob, char *name); + #endif /* ED_MESH_H */ diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h index b705c050aa3..20b1e2b5499 100644 --- a/source/blender/editors/include/ED_space_api.h +++ b/source/blender/editors/include/ED_space_api.h @@ -29,6 +29,9 @@ #ifndef ED_SPACE_API_H #define ED_SPACE_API_H +struct ARegionType; +struct bContext; + /* the pluginnable API for export to editors */ /* calls for registering default spaces */ @@ -54,5 +57,14 @@ void ED_spacetype_sequencer(void); void ED_file_init(void); void ED_file_exit(void); +#define REGION_DRAW_PRE 1 +#define REGION_DRAW_POST 0 + +void *ED_region_draw_cb_activate(struct ARegionType *, + void (*draw)(const struct bContext *, struct ARegion *), + int type); +void ED_region_draw_cb_draw(const struct bContext *, struct ARegion *, int); +void ED_region_draw_cb_exit(struct ARegionType *, void *); + #endif /* ED_SPACE_API_H */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 7b3b31cbe30..60a5ff8481e 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -40,6 +40,7 @@ struct EditEdge; struct EditFace; struct ImBuf; struct Scene; +struct bContext; /* for derivedmesh drawing callbacks, for view3d_select, .... */ typedef struct ViewContext { @@ -60,6 +61,8 @@ typedef struct VPaint { int tot, pad; /* allocation size of prev buffers */ unsigned int *vpaint_prev; /* previous mesh colors */ struct MDeformVert *wpaint_prev; /* previous vertex weights */ + + void *paintcursor; /* wm handle */ } VPaint; /* Gvp.flag and Gwp.flag */ @@ -112,6 +115,9 @@ unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y); #define MAXPICKBUF 10000 short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, rcti *input); +/* modes */ +void ED_view3d_exit_paint_modes(struct bContext *C); + #endif /* ED_VIEW3D_H */ 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/mesh/SConscript b/source/blender/editors/mesh/SConscript index e99351e1a70..bd6d355d84c 100644 --- a/source/blender/editors/mesh/SConscript +++ b/source/blender/editors/mesh/SConscript @@ -7,5 +7,6 @@ incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' #/intern/guardedalloc #intern/bmfont ../../gpu' incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern' +incs += ' ../../bmesh ' env.BlenderLib ( 'bf_editors_mesh', sources, Split(incs), [], libtype=['core'], priority=[45] ) diff --git a/source/blender/editors/mesh/editdeform.c b/source/blender/editors/mesh/editdeform.c new file mode 100644 index 00000000000..703ae2b9fc8 --- /dev/null +++ b/source/blender/editors/mesh/editdeform.c @@ -0,0 +1,1063 @@ +/** + * $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 ***** + * Creator-specific support for vertex deformation groups + * Added: apply deform function (ton) + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_cloth_types.h" +#include "DNA_curve_types.h" +#include "DNA_lattice_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_scene_types.h" +#include "DNA_particle_types.h" + +#include "BLI_blenlib.h" +#include "BLI_editVert.h" + +#include "BKE_customdata.h" +#include "BKE_DerivedMesh.h" +#include "BKE_depsgraph.h" +#include "BKE_deform.h" +#include "BKE_displist.h" +#include "BKE_global.h" +#include "BKE_lattice.h" +#include "BKE_mesh.h" +#include "BKE_utildefines.h" + +#include "ED_mesh.h" +#include "ED_view3d.h" +#include "mesh_intern.h" + +/* XXX */ +static void BIF_undo_push() {} +static void error() {} + +/* only in editmode */ +void sel_verts_defgroup (Object *obedit, int select) +{ + EditVert *eve; + Object *ob; + int i; + MDeformVert *dvert; + + ob= obedit; + + if (!ob) + return; + + switch (ob->type){ + case OB_MESH: + { + Mesh *me= ob->data; + + for (eve=me->edit_mesh->verts.first; eve; eve=eve->next){ + dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT); + + if (dvert && dvert->totweight){ + for (i=0; i<dvert->totweight; i++){ + if (dvert->dw[i].def_nr == (ob->actdef-1)){ + if (select) eve->f |= SELECT; + else eve->f &= ~SELECT; + + break; + } + } + } + } + /* this has to be called, because this function operates on vertices only */ + if(select) EM_select_flush(me->edit_mesh); // vertices to edges/faces + else EM_deselect_flush(me->edit_mesh); + } + break; + case OB_LATTICE: + if(editLatt->dvert) { + BPoint *bp; + int a, tot; + + dvert= editLatt->dvert; + + tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; + for(a=0, bp= editLatt->def; a<tot; a++, bp++, dvert++) { + for (i=0; i<dvert->totweight; i++){ + if (dvert->dw[i].def_nr == (ob->actdef-1)) { + if(select) bp->f1 |= SELECT; + else bp->f1 &= ~SELECT; + + break; + } + } + } + } + break; + + default: + break; + } +} + +/* check if deform vertex has defgroup index */ +MDeformWeight *get_defweight (MDeformVert *dv, int defgroup) +{ + int i; + + if (!dv || defgroup<0) + return NULL; + + for (i=0; i<dv->totweight; i++){ + if (dv->dw[i].def_nr == defgroup) + return dv->dw+i; + } + return NULL; +} + +/* Ensures that mv has a deform weight entry for + the specified defweight group */ +/* Note this function is mirrored in editmesh_tools.c, for use for editvertices */ +MDeformWeight *verify_defweight (MDeformVert *dv, int defgroup) +{ + MDeformWeight *newdw; + + /* do this check always, this function is used to check for it */ + if (!dv || defgroup<0) + return NULL; + + newdw = get_defweight (dv, defgroup); + if (newdw) + return newdw; + + newdw = MEM_callocN (sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight"); + if (dv->dw){ + memcpy (newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight); + MEM_freeN (dv->dw); + } + dv->dw=newdw; + + dv->dw[dv->totweight].weight=0.0f; + dv->dw[dv->totweight].def_nr=defgroup; + /* Group index */ + + dv->totweight++; + + return dv->dw+(dv->totweight-1); +} + +bDeformGroup *add_defgroup_name (Object *ob, char *name) +{ + bDeformGroup *defgroup; + + if (!ob) + return NULL; + + defgroup = MEM_callocN (sizeof(bDeformGroup), "add deformGroup"); + + BLI_strncpy (defgroup->name, name, 32); + + BLI_addtail(&ob->defbase, defgroup); + unique_vertexgroup_name(defgroup, ob); + + ob->actdef = BLI_countlist(&ob->defbase); + + return defgroup; +} + +void add_defgroup (Object *ob) +{ + add_defgroup_name (ob, "Group"); +} + + +void duplicate_defgroup ( Object *ob ) +{ + bDeformGroup *dg, *cdg; + char name[32], s[32]; + MDeformWeight *org, *cpy; + MDeformVert *dvert; + Mesh *me; + int i, idg, icdg; + + if (ob->type != OB_MESH) + return; + + dg = BLI_findlink (&ob->defbase, (ob->actdef-1)); + if (!dg) + return; + + if (strstr(dg->name, "_copy")) { + BLI_strncpy (name, dg->name, 32); /* will be renamed _copy.001... etc */ + } else { + BLI_snprintf (name, 32, "%s_copy", dg->name); + while (get_named_vertexgroup (ob, name)) { + if ((strlen (name) + 6) > 32) { + error ("Error: the name for the new group is > 32 characters"); + return; + } + strcpy (s, name); + BLI_snprintf (name, 32, "%s_copy", s); + } + } + + cdg = copy_defgroup (dg); + strcpy (cdg->name, name); + unique_vertexgroup_name(cdg, ob); + + BLI_addtail (&ob->defbase, cdg); + + idg = (ob->actdef-1); + ob->actdef = BLI_countlist (&ob->defbase); + icdg = (ob->actdef-1); + + me = get_mesh (ob); + if (!me->dvert) + return; + + for (i = 0; i < me->totvert; i++) { + dvert = me->dvert+i; + org = get_defweight (dvert, idg); + if (org) { + cpy = verify_defweight (dvert, icdg); + cpy->weight = org->weight; + } + } +} + +static void del_defgroup_update_users(Object *ob, int id) +{ + ExplodeModifierData *emd; + ModifierData *md; + ParticleSystem *psys; + ClothModifierData *clmd; + ClothSimSettings *clsim; + int a; + + /* these cases don't use names to refer to vertex groups, so when + * they get deleted the numbers get out of sync, this corrects that */ + + if(ob->soft) { + if(ob->soft->vertgroup == id) + ob->soft->vertgroup= 0; + else if(ob->soft->vertgroup > id) + ob->soft->vertgroup--; + } + + for(md=ob->modifiers.first; md; md=md->next) { + if(md->type == eModifierType_Explode) { + emd= (ExplodeModifierData*)md; + + if(emd->vgroup == id) + emd->vgroup= 0; + else if(emd->vgroup > id) + emd->vgroup--; + } + else if(md->type == eModifierType_Cloth) { + clmd= (ClothModifierData*)md; + clsim= clmd->sim_parms; + + if(clsim) { + if(clsim->vgroup_mass == id) + clsim->vgroup_mass= 0; + else if(clsim->vgroup_mass > id) + clsim->vgroup_mass--; + + if(clsim->vgroup_bend == id) + clsim->vgroup_bend= 0; + else if(clsim->vgroup_bend > id) + clsim->vgroup_bend--; + + if(clsim->vgroup_struct == id) + clsim->vgroup_struct= 0; + else if(clsim->vgroup_struct > id) + clsim->vgroup_struct--; + } + } + } + + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + for(a=0; a<PSYS_TOT_VG; a++) + if(psys->vgroup[a] == id) + psys->vgroup[a]= 0; + else if(psys->vgroup[a] > id) + psys->vgroup[a]--; + } +} + +void del_defgroup_in_object_mode ( Object *ob ) +{ + bDeformGroup *dg; + MDeformVert *dvert; + Mesh *me; + int i, e; + + if ((!ob) || (ob->type != OB_MESH)) + return; + + dg = BLI_findlink (&ob->defbase, (ob->actdef-1)); + if (!dg) + return; + + me = get_mesh (ob); + if (me->dvert) { + for (i = 0; i < me->totvert; i++) { + dvert = me->dvert + i; + if (dvert) { + if (get_defweight (dvert, (ob->actdef-1))) + remove_vert_defgroup (ob, dg, i); + } + } + + for (i = 0; i < me->totvert; i++) { + dvert = me->dvert+i; + if (dvert) { + for (e = 0; e < dvert->totweight; e++) { + if (dvert->dw[e].def_nr > (ob->actdef-1)) + dvert->dw[e].def_nr--; + } + } + } + } + + del_defgroup_update_users(ob, ob->actdef); + + /* Update the active deform index if necessary */ + if (ob->actdef == BLI_countlist(&ob->defbase)) + ob->actdef--; + + /* Remove the group */ + BLI_freelinkN (&ob->defbase, dg); +} + +void del_defgroup (Object *ob) +{ + bDeformGroup *defgroup; + int i; + + if (!ob) + return; + + if (!ob->actdef) + return; + + defgroup = BLI_findlink(&ob->defbase, ob->actdef-1); + if (!defgroup) + return; + + /* Make sure that no verts are using this group */ + remove_verts_defgroup(ob, 1); + + /* Make sure that any verts with higher indices are adjusted accordingly */ + if(ob->type==OB_MESH) { + Mesh *me= ob->data; + EditMesh *em = me->edit_mesh; + EditVert *eve; + MDeformVert *dvert; + + for (eve=em->verts.first; eve; eve=eve->next){ + dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT); + + if (dvert) + for (i=0; i<dvert->totweight; i++) + if (dvert->dw[i].def_nr > (ob->actdef-1)) + dvert->dw[i].def_nr--; + } + } + else { + BPoint *bp; + MDeformVert *dvert= editLatt->dvert; + int a, tot; + + if (dvert) { + tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; + for(a=0, bp= editLatt->def; a<tot; a++, bp++, dvert++) { + for (i=0; i<dvert->totweight; i++){ + if (dvert->dw[i].def_nr > (ob->actdef-1)) + dvert->dw[i].def_nr--; + } + } + } + } + + del_defgroup_update_users(ob, ob->actdef); + + /* Update the active deform index if necessary */ + if (ob->actdef==BLI_countlist(&ob->defbase)) + ob->actdef--; + + /* Remove the group */ + BLI_freelinkN (&ob->defbase, defgroup); + + /* remove all dverts */ + if(ob->actdef==0) { + if(ob->type==OB_MESH) { + Mesh *me= ob->data; + CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); + me->dvert= NULL; + } + else { + if (editLatt->dvert) { + MEM_freeN(editLatt->dvert); + editLatt->dvert= NULL; + } + } + } +} + +void del_all_defgroups (Object *ob) +{ + /* Sanity check */ + if (ob == NULL) + return; + + /* Remove all DVerts */ + if (ob->type==OB_MESH) { + Mesh *me= ob->data; + CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); + me->dvert= NULL; + } + else { + if (editLatt->dvert) { + MEM_freeN(editLatt->dvert); + editLatt->dvert= NULL; + } + } + + /* Remove all DefGroups */ + BLI_freelistN(&ob->defbase); + + /* Fix counters/indices */ + ob->actdef= 0; +} + +void create_dverts(ID *id) +{ + /* create deform verts + */ + + if( GS(id->name)==ID_ME) { + Mesh *me= (Mesh *)id; + me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert); + } + else if( GS(id->name)==ID_LT) { + Lattice *lt= (Lattice *)id; + lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert"); + } +} + +/* for mesh in object mode + lattice can be in editmode */ +void remove_vert_def_nr (Object *ob, int def_nr, int vertnum) +{ + /* This routine removes the vertex from the deform + * group with number def_nr. + * + * This routine is meant to be fast, so it is the + * responsibility of the calling routine to: + * a) test whether ob is non-NULL + * b) test whether ob is a mesh + * c) calculate def_nr + */ + + MDeformWeight *newdw; + MDeformVert *dvert= NULL; + int i; + + /* get the deform vertices corresponding to the + * vertnum + */ + if(ob->type==OB_MESH) { + if( ((Mesh*)ob->data)->dvert ) + dvert = ((Mesh*)ob->data)->dvert + vertnum; + } + else if(ob->type==OB_LATTICE) { + Lattice *lt= ob->data; + + if(lt->editlatt) lt= lt->editlatt; + if(lt->dvert) + dvert = lt->dvert + vertnum; + } + + if(dvert==NULL) + return; + + /* for all of the deform weights in the + * deform vert + */ + for (i=dvert->totweight - 1 ; i>=0 ; i--){ + + /* if the def_nr is the same as the one + * for our weight group then remove it + * from this deform vert. + */ + if (dvert->dw[i].def_nr == def_nr) { + dvert->totweight--; + + /* if there are still other deform weights + * attached to this vert then remove this + * deform weight, and reshuffle the others + */ + if (dvert->totweight) { + newdw = MEM_mallocN (sizeof(MDeformWeight)*(dvert->totweight), + "deformWeight"); + if (dvert->dw){ + memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*i); + memcpy (newdw+i, dvert->dw+i+1, + sizeof(MDeformWeight)*(dvert->totweight-i)); + MEM_freeN (dvert->dw); + } + dvert->dw=newdw; + } + /* if there are no other deform weights + * left then just remove the deform weight + */ + else { + MEM_freeN (dvert->dw); + dvert->dw = NULL; + break; + } + } + } + +} + +/* for Mesh in Object mode */ +/* allows editmode for Lattice */ +void add_vert_defnr (Object *ob, int def_nr, int vertnum, + float weight, int assignmode) +{ + /* add the vert to the deform group with the + * specified number + */ + MDeformVert *dv= NULL; + MDeformWeight *newdw; + int i; + + /* get the vert */ + if(ob->type==OB_MESH) { + if(((Mesh*)ob->data)->dvert) + dv = ((Mesh*)ob->data)->dvert + vertnum; + } + else if(ob->type==OB_LATTICE) { + Lattice *lt= ob->data; + + if(lt->editlatt) lt= lt->editlatt; + + if(lt->dvert) + dv = lt->dvert + vertnum; + } + + if(dv==NULL) + return; + + /* Lets first check to see if this vert is + * already in the weight group -- if so + * lets update it + */ + for (i=0; i<dv->totweight; i++){ + + /* if this weight cooresponds to the + * deform group, then add it using + * the assign mode provided + */ + if (dv->dw[i].def_nr == def_nr){ + + switch (assignmode) { + case WEIGHT_REPLACE: + dv->dw[i].weight=weight; + break; + case WEIGHT_ADD: + dv->dw[i].weight+=weight; + if (dv->dw[i].weight >= 1.0) + dv->dw[i].weight = 1.0; + break; + case WEIGHT_SUBTRACT: + dv->dw[i].weight-=weight; + /* if the weight is zero or less then + * remove the vert from the deform group + */ + if (dv->dw[i].weight <= 0.0) + remove_vert_def_nr(ob, def_nr, vertnum); + break; + } + return; + } + } + + /* if the vert wasn't in the deform group then + * we must take a different form of action ... + */ + + switch (assignmode) { + case WEIGHT_SUBTRACT: + /* if we are subtracting then we don't + * need to do anything + */ + return; + + case WEIGHT_REPLACE: + case WEIGHT_ADD: + /* if we are doing an additive assignment, then + * we need to create the deform weight + */ + newdw = MEM_callocN (sizeof(MDeformWeight)*(dv->totweight+1), + "deformWeight"); + if (dv->dw){ + memcpy (newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight); + MEM_freeN (dv->dw); + } + dv->dw=newdw; + + dv->dw[dv->totweight].weight=weight; + dv->dw[dv->totweight].def_nr=def_nr; + + dv->totweight++; + break; + } +} + +/* called while not in editmode */ +void add_vert_to_defgroup (Object *ob, bDeformGroup *dg, int vertnum, + float weight, int assignmode) +{ + /* add the vert to the deform group with the + * specified assign mode + */ + int def_nr; + + /* get the deform group number, exit if + * it can't be found + */ + def_nr = get_defgroup_num(ob, dg); + if (def_nr < 0) return; + + /* if there's no deform verts then + * create some + */ + if(ob->type==OB_MESH) { + if (!((Mesh*)ob->data)->dvert) + create_dverts(ob->data); + } + else if(ob->type==OB_LATTICE) { + if (!((Lattice*)ob->data)->dvert) + create_dverts(ob->data); + } + + /* call another function to do the work + */ + add_vert_defnr (ob, def_nr, vertnum, weight, assignmode); +} + +/* Only available in editmode */ +void assign_verts_defgroup (Object *obedit) +{ + float editbutvweight; /* XXX */ + Object *ob; + EditVert *eve; + bDeformGroup *dg, *eg; + MDeformWeight *newdw; + MDeformVert *dvert; + int i, done; + +// XXX if(multires_level1_test()) return; + + ob= obedit; + + if (!ob) + return; + + dg=BLI_findlink(&ob->defbase, ob->actdef-1); + if (!dg){ + error ("No vertex group is active"); + return; + } + + switch (ob->type){ + case OB_MESH: + { + Mesh *me= ob->data; + + if (!CustomData_has_layer(&me->edit_mesh->vdata, CD_MDEFORMVERT)) + EM_add_data_layer(me->edit_mesh, &me->edit_mesh->vdata, CD_MDEFORMVERT); + + /* Go through the list of editverts and assign them */ + for (eve=me->edit_mesh->verts.first; eve; eve=eve->next){ + dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT); + + if (dvert && (eve->f & 1)){ + done=0; + /* See if this vert already has a reference to this group */ + /* If so: Change its weight */ + done=0; + for (i=0; i<dvert->totweight; i++){ + eg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr); + /* Find the actual group */ + if (eg==dg){ + dvert->dw[i].weight=editbutvweight; + done=1; + break; + } + } + /* If not: Add the group and set its weight */ + if (!done){ + newdw = MEM_callocN (sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight"); + if (dvert->dw){ + memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*dvert->totweight); + MEM_freeN (dvert->dw); + } + dvert->dw=newdw; + + dvert->dw[dvert->totweight].weight= editbutvweight; + dvert->dw[dvert->totweight].def_nr= ob->actdef-1; + + dvert->totweight++; + + } + } + } + } + break; + case OB_LATTICE: + { + BPoint *bp; + int a, tot; + + if(editLatt->dvert==NULL) + create_dverts(&editLatt->id); + + tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; + for(a=0, bp= editLatt->def; a<tot; a++, bp++) { + if(bp->f1 & SELECT) + add_vert_defnr (ob, ob->actdef-1, a, editbutvweight, WEIGHT_REPLACE); + } + } + break; + default: + printf ("Assigning deformation groups to unknown object type\n"); + break; + } + +} + +/* mesh object mode, lattice can be in editmode */ +void remove_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum) +{ + /* This routine removes the vertex from the specified + * deform group. + */ + + int def_nr; + + /* if the object is NULL abort + */ + if (!ob) + return; + + /* get the deform number that cooresponds + * to this deform group, and abort if it + * can not be found. + */ + def_nr = get_defgroup_num(ob, dg); + if (def_nr < 0) return; + + /* call another routine to do the work + */ + remove_vert_def_nr (ob, def_nr, vertnum); +} + +/* for mesh in object mode lattice can be in editmode */ +static float get_vert_def_nr (Object *ob, int def_nr, int vertnum) +{ + MDeformVert *dvert= NULL; + int i; + + /* get the deform vertices corresponding to the + * vertnum + */ + if(ob->type==OB_MESH) { + if( ((Mesh*)ob->data)->dvert ) + dvert = ((Mesh*)ob->data)->dvert + vertnum; + } + else if(ob->type==OB_LATTICE) { + Lattice *lt= ob->data; + + if(lt->editlatt) lt= lt->editlatt; + + if(lt->dvert) + dvert = lt->dvert + vertnum; + } + + if(dvert==NULL) + return 0.0f; + + for(i=dvert->totweight-1 ; i>=0 ; i--) + if(dvert->dw[i].def_nr == def_nr) + return dvert->dw[i].weight; + + return 0.0f; +} + +/* mesh object mode, lattice can be in editmode */ +float get_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum) +{ + int def_nr; + + if(!ob) + return 0.0f; + + def_nr = get_defgroup_num(ob, dg); + if(def_nr < 0) return 0.0f; + + return get_vert_def_nr (ob, def_nr, vertnum); +} + +/* Only available in editmode */ +/* removes from active defgroup, if allverts==0 only selected vertices */ +void remove_verts_defgroup (Object *obedit, int allverts) +{ + Object *ob; + EditVert *eve; + MDeformVert *dvert; + MDeformWeight *newdw; + bDeformGroup *dg, *eg; + int i; + +// XXX if(multires_level1_test()) return; + + ob= obedit; + + if (!ob) + return; + + dg=BLI_findlink(&ob->defbase, ob->actdef-1); + if (!dg){ + error ("No vertex group is active"); + return; + } + + switch (ob->type){ + case OB_MESH: + { + Mesh *me= ob->data; + + for (eve=me->edit_mesh->verts.first; eve; eve=eve->next){ + dvert= CustomData_em_get(&me->edit_mesh->vdata, eve->data, CD_MDEFORMVERT); + + if (dvert && dvert->dw && ((eve->f & 1) || allverts)){ + for (i=0; i<dvert->totweight; i++){ + /* Find group */ + eg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr); + if (eg == dg){ + dvert->totweight--; + if (dvert->totweight){ + newdw = MEM_mallocN (sizeof(MDeformWeight)*(dvert->totweight), "deformWeight"); + + if (dvert->dw){ + memcpy (newdw, dvert->dw, sizeof(MDeformWeight)*i); + memcpy (newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i)); + MEM_freeN (dvert->dw); + } + dvert->dw=newdw; + } + else{ + MEM_freeN (dvert->dw); + dvert->dw=NULL; + break; + } + } + } + } + } + } + break; + case OB_LATTICE: + + if(editLatt->dvert) { + BPoint *bp; + int a, tot= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; + + for(a=0, bp= editLatt->def; a<tot; a++, bp++) { + if(allverts || (bp->f1 & SELECT)) + remove_vert_defgroup (ob, dg, a); + } + } + break; + + default: + printf ("Removing deformation groups from unknown object type\n"); + break; + } +} + +/* Only available in editmode */ +/* removes from all defgroup, if allverts==0 only selected vertices */ +void remove_verts_defgroups(Object *obedit, int allverts) +{ + Object *ob; + int actdef, defCount; + +// XXX if (multires_level1_test()) return; + + ob= obedit; + if (ob == NULL) return; + + actdef= ob->actdef; + defCount= BLI_countlist(&ob->defbase); + + if (defCount == 0) { + error("Object has no vertex groups"); + return; + } + + /* To prevent code redundancy, we just use remove_verts_defgroup, but that + * only operates on the active vgroup. So we iterate through all groups, by changing + * active group index + */ + for (ob->actdef= 1; ob->actdef <= defCount; ob->actdef++) + remove_verts_defgroup(ob, allverts); + + ob->actdef= actdef; +} + +void vertexgroup_select_by_name(Object *ob, char *name) +{ + bDeformGroup *curdef; + int actdef= 1; + + if(ob==NULL) return; + + for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++){ + if (!strcmp(curdef->name, name)) { + ob->actdef= actdef; + return; + } + } + ob->actdef=0; // this signals on painting to create a new one, if a bone in posemode is selected */ +} + +/* This function provides a shortcut for adding/removing verts from + * vertex groups. It is called by the Ctrl-G hotkey in EditMode for Meshes + * and Lattices. (currently only restricted to those two) + * It is only responsible for + */ +void vgroup_assign_with_menu(Object *ob) +{ + int defCount; + int mode; + + /* prevent crashes */ + if (ob==NULL) return; + + defCount= BLI_countlist(&ob->defbase); + + /* give user choices of adding to current/new or removing from current */ +// XXX if (defCount && ob->actdef) +// mode = pupmenu("Vertex Groups %t|Add Selected to New Group %x1|Add Selected to Active Group %x2|Remove Selected from Active Group %x3|Remove Selected from All Groups %x4"); +// else +// mode= pupmenu("Vertex Groups %t|Add Selected to New Group %x1"); + + /* handle choices */ + switch (mode) { + case 1: /* add to new group */ + add_defgroup(ob); + assign_verts_defgroup(ob); + BIF_undo_push("Assign to vertex group"); + break; + case 2: /* add to current group */ + assign_verts_defgroup(ob); + BIF_undo_push("Assign to vertex group"); + break; + case 3: /* remove from current group */ + remove_verts_defgroup(ob, 0); + BIF_undo_push("Remove from vertex group"); + break; + case 4: /* remove from all groups */ + remove_verts_defgroups(ob, 0); + BIF_undo_push("Remove from all vertex groups"); + break; + } +} + +/* This function provides a shortcut for commonly used vertex group + * functions - change weight (not implemented), change active group, delete active group, + * when Ctrl-Shift-G is used in EditMode, for Meshes and Lattices (only for now). + */ +void vgroup_operation_with_menu(Object *ob) +{ + int defCount; + int mode; + + /* prevent crashes and useless cases */ + if (ob==NULL) return; + + defCount= BLI_countlist(&ob->defbase); + if (defCount == 0) return; + + /* give user choices of adding to current/new or removing from current */ +// XXX if (ob->actdef) +// mode = pupmenu("Vertex Groups %t|Change Active Group%x1|Delete Active Group%x2|Delete All Groups%x3"); +// else +// mode= pupmenu("Vertex Groups %t|Change Active Group%x1|Delete All Groups%x3"); + + /* handle choices */ + switch (mode) { + case 1: /* change active group*/ + { + char *menustr= NULL; // XXX get_vertexgroup_menustr(ob); + short nr; + + if (menustr) { +// XXX nr= pupmenu(menustr); + + if ((nr >= 1) && (nr <= defCount)) + ob->actdef= nr; + + MEM_freeN(menustr); + } + } + break; + case 2: /* delete active group */ + { + del_defgroup(ob); + BIF_undo_push("Delete vertex group"); + } + break; + case 3: /* delete all groups */ + { + del_all_defgroups(ob); + BIF_undo_push("Delete all vertex groups"); + } + break; + } +} + + diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 90a328bb49a..bd49c2e8cf6 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -34,6 +34,7 @@ struct bContext; struct wmOperatorType; +struct ViewContext; #define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float)); @@ -45,7 +46,6 @@ int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge /* ******************* meshtools.c */ -int mesh_get_x_mirror_vert(Object *ob, int index); /* XXX move to uv editor? */ enum { @@ -92,7 +92,7 @@ int editedge_containsVert(struct EditEdge *eed, struct EditVert *eve); int editface_containsVert(struct EditFace *efa, struct EditVert *eve); int editface_containsEdge(struct EditFace *efa, struct EditEdge *eed); -void em_setup_viewcontext(struct bContext *C, ViewContext *vc); +void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* ******************* editmesh_add.c */ @@ -162,7 +162,7 @@ extern struct EditFace *EM_face_from_faces(EditMesh *em, struct EditFace *efa1, void MESH_OT_de_select_all(struct wmOperatorType *ot); -extern EditEdge *findnearestedge(ViewContext *vc, int *dist); +extern EditEdge *findnearestedge(struct ViewContext *vc, int *dist); extern void EM_automerge(int update); void editmesh_select_by_material(EditMesh *em, int index); void righthandfaces(EditMesh *em, int select); /* makes faces righthand turning */ @@ -177,7 +177,7 @@ void EM_select_more(EditMesh *em); * if 0, unselected vertice are given the bias * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased */ -extern EditVert *findnearestvert(ViewContext *vc, int *dist, short sel, short strict); +extern EditVert *findnearestvert(struct ViewContext *vc, int *dist, short sel, short strict); /* ******************* editmesh_tools.c */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 8b749b3e829..e3fa8b22463 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -180,8 +180,8 @@ void ED_base_object_activate(bContext *C, Base *base) Base *tbase; /* activating a non-mesh, should end a couple of modes... */ - // if(base && base->object->type!=OB_MESH) - // XXX exit_paint_modes(); + if(base && base->object->type!=OB_MESH) + ED_view3d_exit_paint_modes(C); /* sets scene->basact */ BASACT= base; @@ -235,19 +235,6 @@ int object_data_is_libdata(Object *ob) -void exit_paint_modes(void) -{ -#if 0 - if(G.f & G_VERTEXPAINT) set_vpaint(); - if(G.f & G_TEXTUREPAINT) set_texturepaint(); - if(G.f & G_WEIGHTPAINT) set_wpaint(); - if(G.f & G_SCULPTMODE) set_sculptmode(); - if(G.f & G_PARTICLEEDIT) PE_set_particle_edit(); - - G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT+G_SCULPTMODE+G_PARTICLEEDIT); -#endif -} - /* exported */ void ED_object_base_init_from_view(Scene *scene, View3D *v3d, Base *base) { @@ -284,7 +271,7 @@ void add_object_draw(Scene *scene, View3D *v3d, int type) /* for toolbox or menu { Object *ob; - exit_paint_modes(); +// ED_view3d_exit_paint_modes(C); // XXX if (obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */ ob= add_object(scene, type); @@ -362,7 +349,7 @@ void delete_obj(Scene *scene, View3D *v3d, int ok) } } - exit_paint_modes(); +// ED_view3d_exit_paint_modes(C); if(base->object->type==OB_LAMP) islamp= 1; @@ -1639,36 +1626,78 @@ void OBJECT_OT_set_restrictview(wmOperatorType *ot) RNA_def_property_enum_items(prop, prop_set_restrictview_types); } -/* ******************** **************** */ +/* ************* Slow Parent ******************* */ +static int object_set_slowparent_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); -void reset_slowparents(Scene *scene, View3D *v3d) + CTX_DATA_BEGIN(C, Base*, base, visible_bases) { + + if(base->object->parent) base->object->partype |= PARSLOW; + base->object->recalc |= OB_RECALC_OB; + + } + CTX_DATA_END; + + ED_anim_dag_flush_update(C); + ED_undo_push(C,"Set Slow Parent"); + + WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C)); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_set_slowparent(wmOperatorType *ot) { - /* back to original locations */ - Base *base; + + /* identifiers */ + ot->name= "Set Slow Parent"; + ot->idname= "OBJECT_OT_set_slow_parent"; + + /* api callbacks */ + ot->invoke= WM_operator_confirm; + ot->exec= object_set_slowparent_exec; + ot->poll= ED_operator_view3d_active; +} - for(base= FIRSTBASE; base; base= base->next) { +static int object_clear_slowparent_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + + CTX_DATA_BEGIN(C, Base*, base, visible_bases) { if(base->object->parent) { if(base->object->partype & PARSLOW) { base->object->partype -= PARSLOW; where_is_object(scene, base->object); base->object->partype |= PARSLOW; + base->object->recalc |= OB_RECALC_OB; } } + } -} -void set_slowparent(Scene *scene, View3D *v3d) -{ - Base *base; + CTX_DATA_END; - if( okee("Set slow parent")==0 ) return; + ED_anim_dag_flush_update(C); + ED_undo_push(C,"Clear Slow Parent"); + + WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C)); + + return OPERATOR_FINISHED; +} - for(base= FIRSTBASE; base; base= base->next) { - if(TESTBASELIB(v3d, base)) { - if(base->object->parent) base->object->partype |= PARSLOW; - } - } - BIF_undo_push("Slow parent"); +void OBJECT_OT_clear_slowparent(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Clear Slow Parent"; + ot->idname= "OBJECT_OT_clear_slow_parent"; + + /* api callbacks */ + ot->invoke= WM_operator_confirm; + ot->exec= object_clear_slowparent_exec; + ot->poll= ED_operator_view3d_active; } +/* ******************** **************** */ // XXX #define BEZSELECTED_HIDDENHANDLES(bezt) ((G.f & G_HIDDENHANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt)) @@ -6308,55 +6337,3 @@ void hookmenu(Scene *scene, View3D *v3d) allqueue(REDRAWBUTSEDIT, 0); } } - -void hide_objects(Scene *scene, View3D *v3d, int select) -{ - Base *base; - short changed = 0, changed_act = 0; - for(base = FIRSTBASE; base; base=base->next){ - if ((base->lay & v3d->lay) && TESTBASELIB(v3d, base)==select) { - base->flag &= ~SELECT; - base->object->flag = base->flag; - base->object->restrictflag |= OB_RESTRICT_VIEW; - changed = 1; - if (base==BASACT) { - BASACT= NULL; - changed_act = 1; - } - } - } - if (changed) { - if(select) BIF_undo_push("Hide Selected Objects"); - else if(select) BIF_undo_push("Hide Unselected Objects"); - DAG_scene_sort(scene); - allqueue(REDRAWVIEW3D,0); - allqueue(REDRAWOOPS,0); - allqueue(REDRAWDATASELECT,0); - if (changed_act) { /* these spaces depend on the active object */ - allqueue(REDRAWBUTSALL,0); - allqueue(REDRAWIPO,0); - allqueue(REDRAWACTION,0); - } - } -} - -void show_objects(Scene *scene, View3D *v3d) -{ - Base *base; - int changed = 0; - - for(base = FIRSTBASE; base; base=base->next){ - if((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) { - base->flag |= SELECT; - base->object->flag = base->flag; - base->object->restrictflag &= ~OB_RESTRICT_VIEW; - changed = 1; - } - } - if (changed) { - BIF_undo_push("Unhide Objects"); - DAG_scene_sort(scene); - allqueue(REDRAWVIEW3D,0); - allqueue(REDRAWOOPS,0); - } -} diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 21dace8e0d6..f9143ce26da 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -51,6 +51,8 @@ void OBJECT_OT_clear_scale(wmOperatorType *ot); void OBJECT_OT_clear_origin(wmOperatorType *ot); void OBJECT_OT_clear_restrictview(wmOperatorType *ot); void OBJECT_OT_set_restrictview(wmOperatorType *ot); +void OBJECT_OT_set_slowparent(wmOperatorType *ot); +void OBJECT_OT_clear_slowparent(wmOperatorType *ot); #endif /* ED_OBJECT_INTERN_H */ diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index a15e606c12e..9c287302c10 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -79,6 +79,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_clear_origin); WM_operatortype_append(OBJECT_OT_clear_restrictview); WM_operatortype_append(OBJECT_OT_set_restrictview); + WM_operatortype_append(OBJECT_OT_set_slowparent); + WM_operatortype_append(OBJECT_OT_clear_slowparent); } void ED_keymap_object(wmWindowManager *wm) diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index e2cafeceb9e..5aa8a5b466b 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -206,33 +206,31 @@ void ED_region_do_draw(bContext *C, ARegion *ar) /* note; this sets state, so we can use wmOrtho and friends */ wmSubWindowSet(win, ar->swinid); - if(ar->swinid) { - /* optional header info instead? */ - if(ar->headerstr) { - float col[3]; - UI_SetTheme(sa); - UI_GetThemeColor3fv(TH_HEADER, col); - glClearColor(col[0], col[1], col[2], 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - UI_ThemeColor(TH_MENU_TEXT); - glRasterPos2i(20, 6); - BMF_DrawString(G.font, ar->headerstr); - } - else if(at->draw) { - UI_SetTheme(sa); - at->draw(C, ar); - UI_SetTheme(NULL); - } - - if(sa) - region_draw_emboss(ar); - - uiFreeInactiveBlocks(C, &ar->uiblocks); + /* optional header info instead? */ + if(ar->headerstr) { + float col[3]; + UI_SetTheme(sa); + UI_GetThemeColor3fv(TH_HEADER, col); + glClearColor(col[0], col[1], col[2], 0.0); + glClear(GL_COLOR_BUFFER_BIT); - /* XXX test: add convention to end regions always in pixel space, for drawing of borders/gestures etc */ - ED_region_pixelspace(ar); + UI_ThemeColor(TH_MENU_TEXT); + glRasterPos2i(20, 6); + BMF_DrawString(G.font, ar->headerstr); } + else if(at->draw) { + UI_SetTheme(sa); + at->draw(C, ar); + UI_SetTheme(NULL); + } + + if(sa) + region_draw_emboss(ar); + + uiFreeInactiveBlocks(C, &ar->uiblocks); + + /* XXX test: add convention to end regions always in pixel space, for drawing of borders/gestures etc */ + ED_region_pixelspace(ar); ar->do_draw= 0; } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 536ce9cee74..d78fdbbae6e 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1119,7 +1119,8 @@ static void screen_cursor_set(wmWindow *win, wmEvent *event) } -/* called in wm_event_system.c. sets state var in screen */ +/* called in wm_event_system.c. sets state vars in screen, cursors */ +/* event type is mouse move */ void ED_screen_set_subwinactive(wmWindow *win, wmEvent *event) { if(win->screen) { 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); + } + +} diff --git a/source/blender/editors/sculpt/sculpt.c b/source/blender/editors/sculpt/sculpt.c index 4a81744a79a..cf670434e50 100644 --- a/source/blender/editors/sculpt/sculpt.c +++ b/source/blender/editors/sculpt/sculpt.c @@ -32,8 +32,6 @@ * */ -// XXX #include "GHOST_Types.h" - #include "MEM_guardedalloc.h" #include "BLI_arithb.h" @@ -164,39 +162,25 @@ typedef struct ProjVert { static Object *active_ob= NULL; -SculptData *sculpt_data(void) -{ - return NULL; /*XXX: return &G.scene->sculptdata; */ -} - -static void sculpt_init_session(void); -static void init_brushaction(BrushAction *a, short *, short *); -static void sculpt_undo_push(const short); +static void init_brushaction(SculptData *sd, BrushAction *a, short *, short *); -SculptSession *sculpt_session(void) -{ - if(!sculpt_data()->session) - sculpt_init_session(); - return sculpt_data()->session; -} /* ===== MEMORY ===== * * Allocate/initialize/free data */ -static void sculpt_init_session(void) +static void sculpt_init_session(SculptData *sd) { - if(sculpt_data()->session) + if(sd->session) ;/*XXX: sculptsession_free(G.scene); */ - sculpt_data()->session= MEM_callocN(sizeof(SculptSession), "SculptSession"); + sd->session= MEM_callocN(sizeof(SculptSession), "SculptSession"); } /* vertex_users is an array of Lists that store all the faces that use a particular vertex. vertex_users is in the same order as mesh.mvert */ -static void calc_vertex_users() +static void calc_vertex_users(SculptSession *ss) { - SculptSession *ss= sculpt_session(); int i,j; IndexNode *node= NULL; @@ -236,7 +220,7 @@ void sculptmode_rem_tex(void *junk0,void *junk1) MEM_freeN(ss->texcache); ss->texcache= NULL; } - BIF_undo_push("Unlink brush texture"); + // XXX BIF_undo_push("Unlink brush texture"); allqueue(REDRAWBUTSEDIT, 0); allqueue(REDRAWOOPS, 0); } @@ -292,9 +276,8 @@ float get_depth(short x, short y) /* Uses window coordinates (x,y) and depth component z to find a point in modelspace */ -void unproject(float out[3], const short x, const short y, const float z) +void unproject(SculptSession *ss, float out[3], const short x, const short y, const float z) { - SculptSession *ss= sculpt_session(); double ux, uy, uz; gluUnProject(x,y,z, ss->mats->modelview, ss->mats->projection, @@ -305,9 +288,8 @@ void unproject(float out[3], const short x, const short y, const float z) } /* Convert a point in model coordinates to 2D screen coordinates. */ -static void projectf(const float v[3], float p[2]) +static void projectf(SculptSession *ss, const float v[3], float p[2]) { - SculptSession *ss= sculpt_session(); double ux, uy, uz; gluProject(v[0],v[1],v[2], ss->mats->modelview, ss->mats->projection, @@ -316,10 +298,10 @@ static void projectf(const float v[3], float p[2]) p[1]= uy; } -static void project(const float v[3], short p[2]) +static void project(SculptSession *ss, const float v[3], short p[2]) { float f[2]; - projectf(v, f); + projectf(ss, v, f); p[0]= f[0]; p[1]= f[1]; @@ -333,12 +315,11 @@ static void project(const float v[3], short p[2]) shrink the brush. Skipped for grab brush because only the first mouse down size is used, which is small if the user has just touched the pen to the tablet */ -char brush_size(Brush *b) +char brush_size(SculptData *sd, Brush *b) { - SculptData *sd = NULL; /* XXX */ float size= b->size; float pressure= 0; /* XXX: get_pressure(); */ - short activedevice= get_activedevice(); + short activedevice= 0; /* XXX: get_activedevice(); */ if(b->sculpt_tool!=SCULPT_TOOL_GRAB) { const float size_factor= sd->tablet_size / 10.0f; @@ -355,12 +336,11 @@ char brush_size(Brush *b) /* Return modified brush strength. Includes the direction of the brush, positive values pull vertices, negative values push. Uses tablet pressure and a special multiplier found experimentally to scale the strength factor. */ -float brush_strength(Brush *b, BrushAction *a) +float brush_strength(SculptData *sd, Brush *b, BrushAction *a) { - SculptData *sd = NULL; /* XXX */ float dir= b->flag & BRUSH_DIR_IN ? -1 : 1; float pressure= 1; - short activedevice= get_activedevice(); + short activedevice= 0;/*XXX: get_activedevice(); */ float flip= a->flip ? -1:1; float anchored = b->flag & BRUSH_ANCHORED ? 25 : 1; @@ -408,9 +388,8 @@ void sculpt_clip(const BrushAction *a, float *co, const float val[3]) } } -void sculpt_axislock(float *co) +void sculpt_axislock(SculptData *sd, float *co) { - SculptData *sd = sculpt_data(); if (sd->flags & (SCULPT_LOCK_X|SCULPT_LOCK_Y|SCULPT_LOCK_Z)) return; /* XXX: if(G.vd->twmode == V3D_MANIP_LOCAL) { */ if(0) { @@ -444,16 +423,15 @@ static void add_norm_if(float view_vec[3], float out[3], float out_flip[3], cons /* Currently only for the draw brush; finds average normal for all active vertices */ -void calc_area_normal(float out[3], const BrushAction *a, const float *outdir, const ListBase* active_verts) +void calc_area_normal(SculptData *sd, float out[3], const BrushAction *a, const float *outdir, const ListBase* active_verts) { ActiveData *node = active_verts->first; - SculptData *sd = sculpt_data(); const int view = 0; /* XXX: should probably be a flag, not number: sd->brush_type==SCULPT_TOOL_DRAW ? sculptmode_brush()->view : 0; */ float out_flip[3]; out[0]=out[1]=out[2] = out_flip[0]=out_flip[1]=out_flip[2] = 0; - if(sculptmode_brush()->flag & BRUSH_ANCHORED) { + if(sd->brush->flag & BRUSH_ANCHORED) { for(; node; node = node->next) add_norm_if(((BrushAction*)a)->symm.out, out, out_flip, a->orig_norms[node->Index]); } @@ -477,14 +455,14 @@ void calc_area_normal(float out[3], const BrushAction *a, const float *outdir, c Normalize(out); } -void do_draw_brush(SculptSession *ss, const BrushAction *a, const ListBase* active_verts) +void do_draw_brush(SculptData *sd, SculptSession *ss, const BrushAction *a, const ListBase* active_verts) { float area_normal[3]; ActiveData *node= active_verts->first; - calc_area_normal(area_normal, a, a->symm.out, active_verts); + calc_area_normal(sd, area_normal, a, a->symm.out, active_verts); - sculpt_axislock(area_normal); + sculpt_axislock(sd, area_normal); while(node){ float *co= ss->mvert[node->Index].co; @@ -576,14 +554,14 @@ void do_pinch_brush(SculptSession *ss, const BrushAction *a, const ListBase* act } } -void do_grab_brush(SculptSession *ss, BrushAction *a) +void do_grab_brush(SculptData *sd, SculptSession *ss, BrushAction *a) { ActiveData *node= a->grab_active_verts[a->symm.index].first; float add[3]; float grab_delta[3]; VecCopyf(grab_delta, a->symm.grab_delta); - sculpt_axislock(grab_delta); + sculpt_axislock(sd, grab_delta); while(node) { float *co= ss->mvert[node->Index].co; @@ -598,13 +576,13 @@ void do_grab_brush(SculptSession *ss, BrushAction *a) } -void do_layer_brush(SculptSession *ss, BrushAction *a, const ListBase *active_verts) +void do_layer_brush(SculptData *sd, SculptSession *ss, BrushAction *a, const ListBase *active_verts) { float area_normal[3]; ActiveData *node= active_verts->first; - const float bstr= brush_strength(sculptmode_brush(), a); + const float bstr= brush_strength(sd, sd->brush, a); - calc_area_normal(area_normal, a, NULL, active_verts); + calc_area_normal(sd, area_normal, a, NULL, active_verts); while(node){ float *disp= &a->layer_disps[node->Index]; @@ -682,14 +660,14 @@ void calc_flatten_center(SculptSession *ss, ActiveData *node, float co[3]) VecMulf(co, 1.0f / FLATTEN_SAMPLE_SIZE); } -void do_flatten_brush(SculptSession *ss, const BrushAction *a, const ListBase *active_verts) +void do_flatten_brush(SculptData *sd, SculptSession *ss, const BrushAction *a, const ListBase *active_verts) { ActiveData *node= active_verts->first; /* area_normal and cntr define the plane towards which vertices are squashed */ float area_normal[3]; float cntr[3]; - calc_area_normal(area_normal, a, a->symm.out, active_verts); + calc_area_normal(sd, area_normal, a, a->symm.out, active_verts); calc_flatten_center(ss, node, cntr); while(node){ @@ -733,17 +711,15 @@ void flip_coord(float co[3], const char symm) } /* Use the warpfac field in MTex to store a rotation value for sculpt textures. Value is in degrees */ -float sculpt_tex_angle(void) +float sculpt_tex_angle(SculptData *sd) { - SculptData *sd= sculpt_data(); if(sd->texact!=-1 && sd->mtex[sd->texact]) return sd->mtex[sd->texact]->warpfac; return 0; } -void set_tex_angle(const float f) +void set_tex_angle(SculptData *sd, const float f) { - SculptData *sd = sculpt_data(); if(sd->texact != -1 && sd->mtex[sd->texact]) sd->mtex[sd->texact]->warpfac = f; } @@ -796,10 +772,9 @@ static float get_texcache_pixel_bilinear(const SculptSession *ss, float u, float } /* Return a multiplier for brush strength on a particular vertex. */ -float tex_strength(BrushAction *a, float *point, const float len,const unsigned vindex) +float tex_strength(SculptData *sd, BrushAction *a, float *point, const float len,const unsigned vindex) { - SculptData *sd= sculpt_data(); - SculptSession *ss= sculpt_session(); + SculptSession *ss= sd->session; float avg= 1; if(sd->texact==-1 || !sd->mtex[sd->texact]) @@ -824,7 +799,7 @@ float tex_strength(BrushAction *a, float *point, const float len,const unsigned } else if(ss->texcache) { const float bsize= a->radius * 2; - const float rot= to_rad(sculpt_tex_angle()) + a->anchored_rot; + const float rot= to_rad(sculpt_tex_angle(sd)) + a->anchored_rot; int px, py; float flip[3], point_2d[2]; @@ -833,7 +808,7 @@ float tex_strength(BrushAction *a, float *point, const float len,const unsigned that the brush texture will be oriented correctly. */ VecCopyf(flip, point); flip_coord(flip, a->symm.index); - projectf(flip, point_2d); + projectf(ss, flip, point_2d); /* For Tile and Drag modes, get the 2D screen coordinates of the and scale them up or down to the texture size. */ @@ -881,22 +856,21 @@ float tex_strength(BrushAction *a, float *point, const float len,const unsigned /* Mark area around the brush as damaged. projverts are marked if they are inside the area and the damaged rectangle in 2D screen coordinates is added to damaged_rects. */ -void sculpt_add_damaged_rect(BrushAction *a) +void sculpt_add_damaged_rect(SculptSession *ss, BrushAction *a) { short p[2]; RectNode *rn= MEM_mallocN(sizeof(RectNode),"RectNode"); - SculptSession *ss = sculpt_session(); const float radius = a->radius > a->prev_radius ? a->radius : a->prev_radius; unsigned i; /* Find center */ - project(a->symm.center_3d, p); + project(ss, a->symm.center_3d, p); rn->r.xmin= p[0] - radius; rn->r.ymin= p[1] - radius; rn->r.xmax= p[0] + radius; rn->r.ymax= p[1] + radius; - BLI_addtail(&sculpt_session()->damaged_rects, rn); + BLI_addtail(&ss->damaged_rects, rn); /* Update insides */ for(i=0; i<ss->totvert; ++i) { @@ -939,7 +913,7 @@ void sculpt_clear_damaged_areas(SculptSession *ss) } } -void do_brush_action(Brush *b, BrushAction *a) +void do_brush_action(SculptData *sd, BrushAction *a) { int i; float av_dist; @@ -947,12 +921,12 @@ void do_brush_action(Brush *b, BrushAction *a) ActiveData *adata= 0; float *vert; Mesh *me= NULL; /*XXX: get_mesh(OBACT); */ - const float bstrength= brush_strength(sculptmode_brush(), a); + const float bstrength= brush_strength(sd, sd->brush, a); KeyBlock *keyblock= NULL; /*XXX: ob_get_keyblock(OBACT); */ - SculptData *sd = sculpt_data(); - SculptSession *ss = sculpt_session(); + SculptSession *ss = sd->session; + Brush *b = sd->brush; - sculpt_add_damaged_rect(a); + sculpt_add_damaged_rect(ss, a); /* Build a list of all vertices that are potentially within the brush's area of influence. Only do this once for the grab brush. */ @@ -969,7 +943,7 @@ void do_brush_action(Brush *b, BrushAction *a) adata->Index = i; /* Fade is used to store the final strength at which the brush should modify a particular vertex. */ - adata->Fade= tex_strength(a, vert, av_dist, i) * bstrength; + adata->Fade= tex_strength(sd, a, vert, av_dist, i) * bstrength; adata->dist = av_dist; if(b->sculpt_tool == SCULPT_TOOL_GRAB && a->firsttime) @@ -986,7 +960,7 @@ void do_brush_action(Brush *b, BrushAction *a) /* Apply one type of brush action */ switch(b->sculpt_tool){ case SCULPT_TOOL_DRAW: - do_draw_brush(ss, a, &active_verts); + do_draw_brush(sd, ss, a, &active_verts); break; case SCULPT_TOOL_SMOOTH: do_smooth_brush(ss, a, &active_verts); @@ -998,13 +972,13 @@ void do_brush_action(Brush *b, BrushAction *a) do_inflate_brush(ss, a, &active_verts); break; case SCULPT_TOOL_GRAB: - do_grab_brush(ss, a); + do_grab_brush(sd, ss, a); break; case SCULPT_TOOL_LAYER: - do_layer_brush(ss, a, &active_verts); + do_layer_brush(sd, ss, a, &active_verts); break; case SCULPT_TOOL_FLATTEN: - do_flatten_brush(ss, a, &active_verts); + do_flatten_brush(sd, ss, a, &active_verts); break; } @@ -1046,16 +1020,15 @@ void calc_brushdata_symm(BrushAction *a, const char symm) flip_coord(a->symm.grab_delta, symm); } -void do_symmetrical_brush_actions(BrushAction *a, short co[2], short pr_co[2]) +void do_symmetrical_brush_actions(SculptData *sd, BrushAction *a, short co[2], short pr_co[2]) { - SculptData *sd = NULL; // XXX const char symm = sd->flags & 7; BrushActionSymm orig; int i; - init_brushaction(a, co, pr_co); + init_brushaction(sd, a, co, pr_co); orig = a->symm; - do_brush_action(sd->brush, a); + do_brush_action(sd, a); for(i = 1; i <= symm; ++i) { if(symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5))) { @@ -1063,7 +1036,7 @@ void do_symmetrical_brush_actions(BrushAction *a, short co[2], short pr_co[2]) a->symm = orig; calc_brushdata_symm(a, i); - do_brush_action(sd->brush, a); + do_brush_action(sd, a); } } @@ -1093,14 +1066,13 @@ void add_face_normal(vec3f *norm, MVert *mvert, const MFace* face, float *fn) norm->z+= final[2]; } -void update_damaged_vert(ListBase *lb, BrushAction *a) +void update_damaged_vert(SculptSession *ss, ListBase *lb, BrushAction *a) { ActiveData *vert; - SculptSession *ss = sculpt_session(); for(vert= lb->first; vert; vert= vert->next) { vec3f norm= {0,0,0}; - IndexNode *face= sculpt_session()->vertex_users[vert->Index].first; + IndexNode *face= ss->vertex_users[vert->Index].first; while(face){ float *fn = NULL; @@ -1117,16 +1089,16 @@ void update_damaged_vert(ListBase *lb, BrushAction *a) } } -void calc_damaged_verts(ListBase *damaged_verts, BrushAction *a) +void calc_damaged_verts(SculptSession *ss, BrushAction *a) { int i; for(i=0; i<8; ++i) - update_damaged_vert(&a->grab_active_verts[i], a); + update_damaged_vert(ss, &a->grab_active_verts[i], a); - update_damaged_vert(damaged_verts, a); - BLI_freelistN(damaged_verts); - damaged_verts->first = damaged_verts->last = NULL; + update_damaged_vert(ss, &ss->damaged_verts, a); + BLI_freelistN(&ss->damaged_verts); + ss->damaged_verts.first = ss->damaged_verts.last = NULL; } void projverts_clear_inside(SculptSession *ss) @@ -1136,10 +1108,9 @@ void projverts_clear_inside(SculptSession *ss) ss->projverts[i].inside = 0; } -void sculptmode_update_tex() +void sculptmode_update_tex(SculptData *sd) { - SculptData *sd= sculpt_data(); - SculptSession *ss= sculpt_session(); + SculptSession *ss= sd->session; MTex *mtex = sd->mtex[sd->texact]; TexResult texres = {0}; float x, y, step=2.0/TC_SIZE, co[3]; @@ -1188,10 +1159,9 @@ void sculptmode_update_tex() } /* pr_mouse is only used for the grab brush, can be NULL otherwise */ -static void init_brushaction(BrushAction *a, short *mouse, short *pr_mouse) +static void init_brushaction(SculptData *sd, BrushAction *a, short *mouse, short *pr_mouse) { - SculptData *sd = sculpt_data(); - SculptSession *ss = sculpt_session(); + SculptSession *ss = sd->session; Brush *b = sd->brush; Object *ob = NULL; /* XXX */ const float mouse_depth = get_depth(mouse[0], mouse[1]); @@ -1199,9 +1169,9 @@ static void init_brushaction(BrushAction *a, short *mouse, short *pr_mouse) ModifierData *md; int i; const char flip = 0; /*XXX: (get_qual() == LR_SHIFTKEY); */ - const char anchored = sculptmode_brush()->flag & BRUSH_ANCHORED; + const int anchored = sd->brush->flag & BRUSH_ANCHORED; short orig_mouse[2], dx=0, dy=0; - float size = brush_size(b); + float size = brush_size(sd, b); a->flip = flip; a->symm.index = 0; @@ -1212,23 +1182,23 @@ static void init_brushaction(BrushAction *a, short *mouse, short *pr_mouse) /* Convert the location and size of the brush to modelspace coords */ if(a->firsttime || !anchored) { - unproject(a->symm.center_3d, mouse[0], mouse[1], mouse_depth); + unproject(ss, a->symm.center_3d, mouse[0], mouse[1], mouse_depth); a->mouse[0] = mouse[0]; a->mouse[1] = mouse[1]; } if(anchored) { - project(a->symm.center_3d, orig_mouse); + project(ss, a->symm.center_3d, orig_mouse); dx = mouse[0] - orig_mouse[0]; dy = mouse[1] - orig_mouse[1]; } if(anchored) { - unproject(brush_edge_loc, mouse[0], mouse[1], a->depth); + unproject(ss, brush_edge_loc, mouse[0], mouse[1], a->depth); a->anchored_rot = atan2(dy, dx); } else - unproject(brush_edge_loc, mouse[0] + size, mouse[1], mouse_depth); + unproject(ss, brush_edge_loc, mouse[0] + size, mouse[1], mouse_depth); a->size_3d = VecLenf(a->symm.center_3d, brush_edge_loc); @@ -1244,10 +1214,10 @@ static void init_brushaction(BrushAction *a, short *mouse, short *pr_mouse) VecCopyf(sd->pivot, a->symm.center_3d); /* Now project the Up, Right, and Out normals from view to model coords */ - unproject(zero_loc, 0, 0, 0); - unproject(a->symm.up, 0, -1, 0); - unproject(a->symm.right, 1, 0, 0); - unproject(a->symm.out, 0, 0, -1); + unproject(ss, zero_loc, 0, 0, 0); + unproject(ss, a->symm.up, 0, -1, 0); + unproject(ss, a->symm.right, 1, 0, 0); + unproject(ss, a->symm.out, 0, 0, -1); VecSubf(a->symm.up, a->symm.up, zero_loc); VecSubf(a->symm.right, a->symm.right, zero_loc); VecSubf(a->symm.out, a->symm.out, zero_loc); @@ -1276,8 +1246,8 @@ static void init_brushaction(BrushAction *a, short *mouse, short *pr_mouse) float gcenter[3]; /* Find the delta */ - unproject(gcenter, mouse[0], mouse[1], a->depth); - unproject(oldloc, pr_mouse[0], pr_mouse[1], a->depth); + unproject(ss, gcenter, mouse[0], mouse[1], a->depth); + unproject(ss, oldloc, pr_mouse[0], pr_mouse[1], a->depth); VecSubf(a->symm.grab_delta, gcenter, oldloc); } else if(b->sculpt_tool == SCULPT_TOOL_LAYER) { @@ -1444,16 +1414,15 @@ void sculptmode_selectbrush_menu(void) }*/ } -void sculptmode_update_all_projverts(float *vertcosnos) +void sculptmode_update_all_projverts(SculptSession *ss) { - SculptSession *ss = sculpt_session(); unsigned i; if(!ss->projverts) ss->projverts = MEM_mallocN(sizeof(ProjVert)*ss->totvert,"ProjVerts"); for(i=0; i<ss->totvert; ++i) { - project(vertcosnos ? &vertcosnos[i * 6] : ss->mvert[i].co, ss->projverts[i].co); + project(ss, ss->vertexcosnos ? &ss->vertexcosnos[i * 6] : ss->mvert[i].co, ss->projverts[i].co); ss->projverts[i].inside= 0; } } @@ -1593,21 +1562,43 @@ void sculptmode_draw_mesh(int only_damaged) } #endif -void sculptmode_correct_state(void) + +static void sculpt_undo_push(SculptData *sd) { - if(!sculpt_session()) - sculpt_init_session(); + /*XXX: switch(sd->brush->sculpt_tool) { + case SCULPT_TOOL_DRAW: + BIF_undo_push("Draw Brush"); break; + case SCULPT_TOOL_SMOOTH: + BIF_undo_push("Smooth Brush"); break; + case SCULPT_TOOL_PINCH: + BIF_undo_push("Pinch Brush"); break; + case SCULPT_TOOL_INFLATE: + BIF_undo_push("Inflate Brush"); break; + case SCULPT_TOOL_GRAB: + BIF_undo_push("Grab Brush"); break; + case SCULPT_TOOL_LAYER: + BIF_undo_push("Layer Brush"); break; + case SCULPT_TOOL_FLATTEN: + BIF_undo_push("Flatten Brush"); break; + default: + BIF_undo_push("Sculpting"); break; + }*/ +} + +void sculptmode_correct_state(SculptData *sd) +{ + if(!sd->session) + sculpt_init_session(sd); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - if(!sculpt_session()->vertex_users) calc_vertex_users(); + if(!sd->session->vertex_users) calc_vertex_users(sd->session); } -void sculpt(void) +void sculpt(SculptData *sd) { - SculptData *sd= sculpt_data(); - SculptSession *ss= sculpt_session(); + SculptSession *ss= sd->session; Object *ob= NULL; /*XXX */ Mesh *me; MultiresModifierData *mmd = NULL; @@ -1634,11 +1625,11 @@ void sculpt(void) }*/ if(!ss) { - sculpt_init_session(); + sculpt_init_session(sd); ss= sd->session; } - anchored = sculptmode_brush()->flag & BRUSH_ANCHORED; + anchored = sd->brush->flag & BRUSH_ANCHORED; smooth_stroke = (sd->flags & SCULPT_INPUT_SMOOTH) && (sd->brush->sculpt_tool != SCULPT_TOOL_GRAB) && !anchored; if(smooth_stroke) @@ -1654,7 +1645,7 @@ void sculpt(void) /* Check that vertex users are up-to-date */ if(ob != active_ob || !ss->vertex_users || ss->vertex_users_size != ss->totvert) { sculpt_vertexusers_free(ss); - calc_vertex_users(); + calc_vertex_users(ss); if(ss->projverts) MEM_freeN(ss->projverts); ss->projverts = NULL; @@ -1671,9 +1662,9 @@ void sculpt(void) /* Init texture FIXME: Shouldn't be doing this every time! */ if(sd->texrept!=SCULPTREPT_3D) - sculptmode_update_tex(); + sculptmode_update_tex(sd); - getmouseco_areawin(mouse); + /*XXX: getmouseco_areawin(mouse); */ mvalo[0]= mouse[0]; mvalo[1]= mouse[1]; lastSigMouse[0]=mouse[0]; @@ -1689,7 +1680,7 @@ void sculpt(void) if(modifier_calculations) ss->vertexcosnos= mesh_get_mapped_verts_nors(NULL, ob); /* XXX: scene = ? */ - sculptmode_update_all_projverts(ss->vertexcosnos); + sculptmode_update_all_projverts(ss); /* Set scaling adjustment */ a->scale[0]= 1.0f / ob->size[0]; @@ -1704,27 +1695,27 @@ void sculpt(void) glGetIntegerv(GL_SCISSOR_BOX, scissor_box); /* For raking, get the original angle*/ - offsetRot=sculpt_tex_angle(); + offsetRot=sculpt_tex_angle(sd); me = get_mesh(ob); - while (get_mbut() & mousebut) { - getmouseco_areawin(mouse); + while (/*XXX:get_mbut() & mousebut*/0) { + /* XXX: getmouseco_areawin(mouse); */ /* If rake, and the mouse has moved over 10 pixels (euclidean) (prevents jitter) then get the new angle */ if (rake && (pow(lastSigMouse[0]-mouse[0],2)+pow(lastSigMouse[1]-mouse[1],2))>100){ /*Nasty looking, but just orig + new angle really*/ - set_tex_angle(offsetRot+180.+to_deg(atan2((float)(mouse[1]-lastSigMouse[1]),(float)(mouse[0]-lastSigMouse[0])))); + set_tex_angle(sd, offsetRot+180.+to_deg(atan2((float)(mouse[1]-lastSigMouse[1]),(float)(mouse[0]-lastSigMouse[0])))); lastSigMouse[0]=mouse[0]; lastSigMouse[1]=mouse[1]; } if(firsttime || mouse[0]!=mvalo[0] || mouse[1]!=mvalo[1] || - sculptmode_brush()->flag & BRUSH_AIRBRUSH) { + sd->brush->flag & BRUSH_AIRBRUSH) { a->firsttime = firsttime; firsttime= 0; if(smooth_stroke) - sculpt_stroke_add_point(mouse[0], mouse[1]); + sculpt_stroke_add_point(ss->stroke, mouse[0], mouse[1]); spacing+= sqrt(pow(mvalo[0]-mouse[0],2)+pow(mvalo[1]-mouse[1],2)); @@ -1743,32 +1734,32 @@ void sculpt(void) } } - do_symmetrical_brush_actions(a, mouse, NULL); + do_symmetrical_brush_actions(sd, a, mouse, NULL); } else { if(smooth_stroke) { - sculpt_stroke_apply(a); + sculpt_stroke_apply(sd, ss->stroke, a); } else if(sd->spacing==0 || spacing>sd->spacing) { - do_symmetrical_brush_actions(a, mouse, NULL); + do_symmetrical_brush_actions(sd, a, mouse, NULL); spacing= 0; } } } else { - do_symmetrical_brush_actions(a, mouse, mvalo); - unproject(sd->pivot, mouse[0], mouse[1], a->depth); + do_symmetrical_brush_actions(sd, a, mouse, mvalo); + unproject(ss, sd->pivot, mouse[0], mouse[1], a->depth); } if((!ss->multires && modifier_calculations) || ob_get_keyblock(ob)) ;/* XXX: DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); */ if(modifier_calculations || sd->brush->sculpt_tool == SCULPT_TOOL_GRAB || !(sd->flags & SCULPT_DRAW_FAST)) { - calc_damaged_verts(&ss->damaged_verts, a); - /*XXX: scrarea_do_windraw(curarea); */ - screen_swapbuffers(); + calc_damaged_verts(ss, a); + /*XXX: scrarea_do_windraw(curarea); + screen_swapbuffers(); */ } else { /* Optimized drawing */ - calc_damaged_verts(&ss->damaged_verts, a); + calc_damaged_verts(ss, a); /* Draw the stored image to the screen */ glAccum(GL_RETURN, 1); @@ -1777,7 +1768,7 @@ void sculpt(void) /* Draw all the polygons that are inside the modified area(s) */ glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]); - sculptmode_draw_mesh(1); + /* XXX: sculptmode_draw_mesh(1); */ glAccum(GL_LOAD, 1); projverts_clear_inside(ss); @@ -1786,12 +1777,12 @@ void sculpt(void) glDisable(GL_DEPTH_TEST); /* Draw cursor */ - if(sculpt_data()->flags & SCULPT_TOOL_DRAW) - fdrawXORcirc((float)mouse[0],(float)mouse[1],sculptmode_brush()->size); - if(smooth_stroke) - sculpt_stroke_draw(); + if(sd->flags & SCULPT_TOOL_DRAW) + fdrawXORcirc((float)mouse[0],(float)mouse[1],sd->brush->size); + /* XXX: if(smooth_stroke) + sculpt_stroke_draw(); - myswapbuffers(); + myswapbuffers(); */ } BLI_freelistN(&ss->damaged_rects); @@ -1806,15 +1797,15 @@ void sculpt(void) } } - else BIF_wait_for_statechange(); + else ;/*XXX:BIF_wait_for_statechange();*/ } /* Set the rotation of the brush back to what it was before any rake */ - set_tex_angle(offsetRot); + set_tex_angle(sd, offsetRot); if(smooth_stroke) { - sculpt_stroke_apply_all(a); - calc_damaged_verts(&ss->damaged_verts, a); + sculpt_stroke_apply_all(sd, ss->stroke, a); + calc_damaged_verts(ss, a); BLI_freelistN(&ss->damaged_rects); } @@ -1824,7 +1815,8 @@ void sculpt(void) for(i=0; i<8; ++i) BLI_freelistN(&a->grab_active_verts[i]); MEM_freeN(a); - sculpt_stroke_free(); + sculpt_stroke_free(ss->stroke); + ss->stroke = NULL; if(mmd) { if(mmd->undo_verts && mmd->undo_verts != ss->mvert) @@ -1834,65 +1826,44 @@ void sculpt(void) mmd->undo_verts_tot = ss->totvert; } - /* XXX: sculpt_undo_push(G.scene->sculptdata.brush_type); */ + sculpt_undo_push(sd); /* XXX: if(G.vd->depths) G.vd->depths->damaged= 1; allqueue(REDRAWVIEW3D, 0); */ } -static void sculpt_undo_push(const short brush_type) +void ED_sculpt_enter_sculptmode() { - switch(brush_type) { - case SCULPT_TOOL_DRAW: - BIF_undo_push("Draw Brush"); break; - case SCULPT_TOOL_SMOOTH: - BIF_undo_push("Smooth Brush"); break; - case SCULPT_TOOL_PINCH: - BIF_undo_push("Pinch Brush"); break; - case SCULPT_TOOL_INFLATE: - BIF_undo_push("Inflate Brush"); break; - case SCULPT_TOOL_GRAB: - BIF_undo_push("Grab Brush"); break; - case SCULPT_TOOL_LAYER: - BIF_undo_push("Layer Brush"); break; - case SCULPT_TOOL_FLATTEN: - BIF_undo_push("Flatten Brush"); break; - default: - BIF_undo_push("Sculpting"); break; - } + G.f |= G_SCULPTMODE; + + sculpt_init_session(NULL /*XXX*/); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + active_ob = NULL; } -void set_sculptmode(void) +void ED_sculpt_exit_sculptmode() { - if(G.f & G_SCULPTMODE) { - Object *ob = NULL; /*XXX: OBACT; */ - Mesh *me= get_mesh(ob); + Object *ob = NULL; /*XXX: OBACT; */ + Mesh *me= get_mesh(ob); - multires_force_update(ob); + multires_force_update(ob); - G.f &= ~G_SCULPTMODE; + G.f &= ~G_SCULPTMODE; - /* XXX: sculptsession_free(G.scene); */ - if(me && me->pv) - mesh_pmv_off(ob, me); - } - else { - G.f |= G_SCULPTMODE; + /* XXX: sculptsession_free(G.scene); */ + if(me && me->pv) + mesh_pmv_off(ob, me); - /* Called here to sanity-check the brush */ - sculptmode_brush(); - - sculpt_init_session(); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - } - - active_ob= NULL; + active_ob = NULL; } /* Partial Mesh Visibility */ +/* XXX: Partial vis. always was a mess, have to figure something out */ +#if 0 /* mode: 0=hide outside selection, 1=hide inside selection */ static void sculptmode_do_pmv(Object *ob, rcti *hb_2d, int mode) { @@ -2115,3 +2086,4 @@ void sculptmode_pmv(int mode) waitcursor(0); } +#endif diff --git a/source/blender/editors/sculpt/sculpt_intern.h b/source/blender/editors/sculpt/sculpt_intern.h index 35a9861eceb..b25182cfb36 100644 --- a/source/blender/editors/sculpt/sculpt_intern.h +++ b/source/blender/editors/sculpt/sculpt_intern.h @@ -47,17 +47,7 @@ struct ScrArea; struct SculptData; struct SculptStroke; -struct SculptSession *sculpt_session(void); -struct SculptData *sculpt_data(void); - -/* Memory */ -void sculptmode_correct_state(void); - /* Interface */ -void sculptmode_draw_interface_tools(struct uiBlock *block,unsigned short cx, unsigned short cy); -void sculptmode_draw_interface_brush(struct uiBlock *block,unsigned short cx, unsigned short cy); -void sculptmode_draw_interface_textures(struct uiBlock *block,unsigned short cx, unsigned short cy); -void sculptmode_rem_tex(void*,void*); void sculptmode_selectbrush_menu(void); void sculptmode_draw_mesh(int); void sculpt_paint_brush(char clear); @@ -65,21 +55,17 @@ void sculpt_stroke_draw(); void sculpt_radialcontrol_start(int mode); struct Brush *sculptmode_brush(void); -void do_symmetrical_brush_actions(struct BrushAction *a, short *, short *); +void do_symmetrical_brush_actions(struct SculptData *sd, struct BrushAction *a, short *, short *); -void sculptmode_update_tex(void); char sculpt_modifiers_active(struct Object *ob); -void sculpt(void); -void set_sculptmode(void); +void sculpt(SculptData *sd); /* Stroke */ -void sculpt_stroke_new(const int max); -void sculpt_stroke_free(); -void sculpt_stroke_add_point(const short x, const short y); -void sculpt_stroke_apply(struct BrushAction *); -void sculpt_stroke_apply_all(struct BrushAction *); -void sculpt_stroke_draw(); - +struct SculptStroke *sculpt_stroke_new(const int max); +void sculpt_stroke_free(struct SculptStroke *); +void sculpt_stroke_add_point(struct SculptStroke *, const short x, const short y); +void sculpt_stroke_apply(struct SculptData *sd, struct SculptStroke *, struct BrushAction *); +void sculpt_stroke_apply_all(struct SculptData *sd, struct SculptStroke *, struct BrushAction *); /* Partial Mesh Visibility */ void sculptmode_pmv(int mode); diff --git a/source/blender/editors/sculpt/stroke.c b/source/blender/editors/sculpt/stroke.c index 482b2fcefe0..76523f1ff35 100644 --- a/source/blender/editors/sculpt/stroke.c +++ b/source/blender/editors/sculpt/stroke.c @@ -58,31 +58,27 @@ typedef struct SculptStroke { float offset; } SculptStroke; -void sculpt_stroke_new(const int max) +SculptStroke *sculpt_stroke_new(const int max) { - SculptSession *ss = sculpt_session(); - - ss->stroke = MEM_callocN(sizeof(SculptStroke), "SculptStroke"); - ss->stroke->loc = MEM_callocN(sizeof(short) * 4 * max, "SculptStroke.loc"); - ss->stroke->max = max; - ss->stroke->index = -1; + SculptStroke *stroke = MEM_callocN(sizeof(SculptStroke), "SculptStroke"); + stroke->loc = MEM_callocN(sizeof(short) * 4 * max, "SculptStroke.loc"); + stroke->max = max; + stroke->index = -1; + return stroke; } -void sculpt_stroke_free() +void sculpt_stroke_free(SculptStroke *stroke) { - SculptSession *ss = sculpt_session(); - if(ss && ss->stroke) { - if(ss->stroke->loc) MEM_freeN(ss->stroke->loc); - if(ss->stroke->final_mem) MEM_freeN(ss->stroke->final_mem); + if(stroke) { + if(stroke->loc) MEM_freeN(stroke->loc); + if(stroke->final_mem) MEM_freeN(stroke->final_mem); - MEM_freeN(ss->stroke); - ss->stroke = NULL; + MEM_freeN(stroke); } } -void sculpt_stroke_add_point(const short x, const short y) +void sculpt_stroke_add_point(SculptStroke *stroke, const short x, const short y) { - SculptStroke *stroke = sculpt_session()->stroke; const int next = stroke->index + 1; if(stroke->index == -1) { @@ -112,10 +108,8 @@ void sculpt_stroke_smooth(SculptStroke *stroke) } } -static void sculpt_stroke_create_final() +static void sculpt_stroke_create_final(SculptStroke *stroke) { - SculptStroke *stroke = sculpt_session()->stroke; - if(stroke) { StrokePoint *p, *pnext; int i; @@ -178,9 +172,9 @@ float sculpt_stroke_final_length(SculptStroke *stroke) } /* If partial is nonzero, cuts off apply after that length has been processed */ -static StrokePoint *sculpt_stroke_apply_generic(SculptStroke *stroke, struct BrushAction *a, const int partial) +static StrokePoint *sculpt_stroke_apply_generic(SculptData *sd, SculptStroke *stroke, struct BrushAction *a, const int partial) { - const int sdspace = sculpt_data()->spacing; + const int sdspace = sd->spacing; const short spacing = sdspace > 0 ? sdspace : 2; const int dots = sculpt_stroke_final_length(stroke) / spacing; int i; @@ -215,24 +209,23 @@ static StrokePoint *sculpt_stroke_apply_generic(SculptStroke *stroke, struct Bru co[0] = p->x*v + p->next->x*u; co[1] = p->y*v + p->next->y*u; - do_symmetrical_brush_actions(a, co, NULL); + do_symmetrical_brush_actions(sd, a, co, NULL); } return p ? p->next : NULL; } -void sculpt_stroke_apply(struct BrushAction *a) +void sculpt_stroke_apply(SculptData *sd, SculptStroke *stroke, struct BrushAction *a) { - SculptStroke *stroke = sculpt_session()->stroke; /* TODO: make these values user-modifiable? */ const int partial_len = 100; const int min_len = 200; if(stroke) { - sculpt_stroke_create_final(); + sculpt_stroke_create_final(stroke); if(sculpt_stroke_final_length(stroke) > min_len) { - StrokePoint *p = sculpt_stroke_apply_generic(stroke, a, partial_len); + StrokePoint *p = sculpt_stroke_apply_generic(sd, stroke, a, partial_len); /* Replace remaining values in stroke->loc with remaining stroke->final values */ stroke->index = -1; @@ -249,21 +242,18 @@ void sculpt_stroke_apply(struct BrushAction *a) } } -void sculpt_stroke_apply_all(struct BrushAction *a) +void sculpt_stroke_apply_all(SculptData *sd, SculptStroke *stroke, struct BrushAction *a) { - SculptStroke *stroke = sculpt_session()->stroke; - - sculpt_stroke_create_final(); + sculpt_stroke_create_final(stroke); if(stroke) { - sculpt_stroke_apply_generic(stroke, a, 0); + sculpt_stroke_apply_generic(sd, stroke, a, 0); } } -void sculpt_stroke_draw() +/* XXX: drawing goes elsewhere */ +void sculpt_stroke_draw(SculptStroke *stroke) { - SculptStroke *stroke = sculpt_session()->stroke; - if(stroke) { StrokePoint *p; diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 325227a2fc5..8ed9bb10fd5 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -123,7 +123,60 @@ void ED_spacetypes_keymap(wmWindowManager *wm) } } -/* ****************************** space template *********************** */ +/* ********************** custom drawcall api ***************** */ + +/* type */ +#define REGION_DRAW_PRE 1 +#define REGION_DRAW_POST 0 + +typedef struct RegionDrawCB { + struct RegionDrawCB *next, *prev; + + void (*draw)(const struct bContext *, struct ARegion *); + + int type; + +} RegionDrawCB; + +void *ED_region_draw_cb_activate(ARegionType *art, + void (*draw)(const struct bContext *, struct ARegion *), + int type) +{ + RegionDrawCB *rdc= MEM_callocN(sizeof(RegionDrawCB), "RegionDrawCB"); + + BLI_addtail(&art->drawcalls, rdc); + rdc->draw= draw; + rdc->type= type; + + return rdc; +} + +void ED_region_draw_cb_exit(ARegionType *art, void *handle) +{ + RegionDrawCB *rdc; + + for(rdc= art->drawcalls.first; rdc; rdc= rdc->next) { + if(rdc==(RegionDrawCB *)handle) { + BLI_remlink(&art->drawcalls, rdc); + MEM_freeN(rdc); + return; + } + } +} + +void ED_region_draw_cb_draw(const bContext *C, ARegion *ar, int type) +{ + RegionDrawCB *rdc; + + for(rdc= ar->type->drawcalls.first; rdc; rdc= rdc->next) { + if(rdc->type==type) + rdc->draw(C, ar); + } +} + + + +/* ********************* space template *********************** */ /* allocate and init some vars */ static SpaceLink *xxx_new(const bContext *C) diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 78e4116faef..c45993d71cb 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -128,7 +128,7 @@ static void do_file_buttons(bContext *C, void *arg, int event) void file_draw_buttons(const bContext *C, ARegion *ar) { SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); - FileSelectParams* params = sfile->params; + FileSelectParams* params = ED_fileselect_get_params(sfile); uiBlock *block; int loadbutton; char name[20]; @@ -277,7 +277,7 @@ static int file_view_columns(SpaceFile* sfile, View2D *v2d) void file_calc_previews(const bContext *C, ARegion *ar) { SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); - FileSelectParams* params = sfile->params; + FileSelectParams* params = ED_fileselect_get_params(sfile); View2D *v2d= &ar->v2d; int width=0, height=0; int rows, columns; @@ -316,7 +316,7 @@ void file_calc_previews(const bContext *C, ARegion *ar) void file_draw_previews(const bContext *C, ARegion *ar) { SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); - FileSelectParams* params=sfile->params; + FileSelectParams* params= ED_fileselect_get_params(sfile); View2D *v2d= &ar->v2d; static double lasttime= 0; struct FileList* files = sfile->files; @@ -471,7 +471,7 @@ void file_draw_previews(const bContext *C, ARegion *ar) void file_draw_list(const bContext *C, ARegion *ar) { SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); - FileSelectParams* params = sfile->params; + FileSelectParams* params = ED_fileselect_get_params(sfile); struct FileList* files = sfile->files; struct direntry *file; int numfiles; @@ -558,7 +558,7 @@ void file_draw_list(const bContext *C, ARegion *ar) void file_draw_fsmenu(const bContext *C, ARegion *ar) { SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); - FileSelectParams* params = sfile->params; + FileSelectParams* params = ED_fileselect_get_params(sfile); char bookmark[FILE_MAX]; int nentries = fsmenu_get_nentries(); int linestep = U.fontsize*3/2; diff --git a/source/blender/editors/space_file/file_header.c b/source/blender/editors/space_file/file_header.c index 2aeb8ed0684..cbe36f28c9d 100644 --- a/source/blender/editors/space_file/file_header.c +++ b/source/blender/editors/space_file/file_header.c @@ -117,7 +117,7 @@ void file_header_buttons(const bContext *C, ARegion *ar) { ScrArea *sa= CTX_wm_area(C); SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C); - FileSelectParams* params = sfile->params; + FileSelectParams* params = ED_fileselect_get_params(sfile); uiBlock *block; int xco, yco= 3; diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index d9e831c84da..49014a69b68 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -116,7 +116,7 @@ static void set_active_file(SpaceFile *sfile, FileSelectParams* params, struct A } -static void set_active_bookmark(SpaceFile *sfile, FileSelectParams* params, struct ARegion* ar, short y) +static void set_active_bookmark(FileSelectParams* params, struct ARegion* ar, short y) { int nentries = fsmenu_get_nentries(); short posy = ar->v2d.mask.ymax - TILE_BORDER_Y - y; @@ -187,7 +187,7 @@ static void mouse_select_bookmark(SpaceFile* sfile, ARegion* ar, short *mval) if(mval[0]>ar->v2d.mask.xmin && mval[0]<ar->v2d.mask.xmax && mval[1]>ar->v2d.mask.ymin && mval[1]<ar->v2d.mask.ymax) { char *selected; - set_active_bookmark(sfile, sfile->params, ar, mval[1]); + set_active_bookmark(sfile->params, ar, mval[1]); selected= fsmenu_get_entry(sfile->params->active_bookmark); /* which string */ if (selected) { diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index d1cfdb07c39..f2eb7ad58ea 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -76,15 +76,26 @@ #include "filelist.h" -short ED_fileselect_set_params(FileSelectParams *params, int type, const char *title, const char *path, +FileSelectParams* ED_fileselect_get_params(struct SpaceFile *sfile) +{ + if (!sfile->params) { + ED_fileselect_set_params(sfile, FILE_UNIX, "", "/", 0, 0, 0); + } + return sfile->params; +} + +short ED_fileselect_set_params(SpaceFile *sfile, int type, const char *title, const char *path, short flag, short display, short filter) { char name[FILE_MAX], dir[FILE_MAX], file[FILE_MAX]; + FileSelectParams *params; - if (!params) { - return 0; + if (!sfile->params) { + sfile->params= MEM_callocN(sizeof(FileSelectParams), "fileselparams"); } + params = sfile->params; + params->type = type; params->flag = flag; params->display = display; @@ -115,3 +126,9 @@ short ED_fileselect_set_params(FileSelectParams *params, int type, const char *t return 1; } +void ED_fileselect_reset_params(SpaceFile *sfile) +{ + sfile->params->type = FILE_UNIX; + sfile->params->flag = 0; + sfile->params->title[0] = '\0'; +} diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 703d351af2b..aa364bfb093 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -74,13 +74,7 @@ static SpaceLink *file_new(const bContext *C) SpaceFile *sfile; sfile= MEM_callocN(sizeof(SpaceFile), "initfile"); - sfile->spacetype= SPACE_FILE; - sfile->params= MEM_callocN(sizeof(FileSelectParams), "fileselparams"); - sfile->files = filelist_new(); - - ED_fileselect_set_params(sfile->params, FILE_UNIX, "", "/", 0, 0, 0); - filelist_setdir(sfile->files, sfile->params->dir); - filelist_settype(sfile->files, sfile->params->type); + sfile->spacetype= SPACE_FILE; /* header */ ar= MEM_callocN(sizeof(ARegion), "header for file"); @@ -122,14 +116,14 @@ static void file_free(SpaceLink *sl) filelist_free(sfile->files); filelist_freelib(sfile->files); MEM_freeN(sfile->files); - sfile->files = 0; + sfile->files= NULL; } if (sfile->params) { if(sfile->params->pupmenu) MEM_freeN(sfile->params->pupmenu); MEM_freeN(sfile->params); - sfile->params = 0; + sfile->params= NULL; } if (sfile->op) { @@ -142,16 +136,15 @@ static void file_free(SpaceLink *sl) static void file_init(struct wmWindowManager *wm, ScrArea *sa) { SpaceFile *sfile= sa->spacedata.first; /* XXX get through context? */ - if (!sfile->params) { - sfile->params= MEM_callocN(sizeof(FileSelectParams), "fileselparams"); - ED_fileselect_set_params(sfile->params, FILE_UNIX, "", "/", 0, 0, 0); + if (sfile->params) { + ED_fileselect_reset_params(sfile); } - if (!sfile->files) { - sfile->files = filelist_new(); + if (sfile->files) { + filelist_free(sfile->files); + filelist_freelib(sfile->files); + MEM_freeN(sfile->files); + sfile->files= NULL; } - - filelist_setdir(sfile->files, sfile->params->dir); - filelist_settype(sfile->files, sfile->params->type); } static SpaceLink *file_duplicate(SpaceLink *sl) @@ -165,9 +158,10 @@ static SpaceLink *file_duplicate(SpaceLink *sl) sfilen->params= MEM_dupallocN(sfileo->params); if (!sfilen->params) { sfilen->params= MEM_callocN(sizeof(FileSelectParams), "fileselparams"); - ED_fileselect_set_params(sfilen->params, FILE_UNIX, "", "/", 0, 0, 0); + ED_fileselect_set_params(sfilen, FILE_UNIX, "", "/", 0, 0, 0); sfilen->params->pupmenu = NULL; } + sfilen->files = filelist_new(); filelist_setdir(sfilen->files, sfilen->params->dir); filelist_settype(sfilen->files, sfilen->params->type); diff --git a/source/blender/editors/space_ipo/ipo_draw.c b/source/blender/editors/space_ipo/ipo_draw.c new file mode 100644 index 00000000000..b24c4ca59a0 --- /dev/null +++ b/source/blender/editors/space_ipo/ipo_draw.c @@ -0,0 +1,713 @@ +/** + * $Id: drawipo.c 17512 2008-11-20 05:55:42Z aligorith $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) Blender Foundation + * + * Contributor(s): Joshua Leung (2009 Recode) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <math.h> +#include <string.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef _WIN32 +#include <unistd.h> +#else +#include <io.h> +#endif + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "DNA_action_types.h" +#include "DNA_curve_types.h" +#include "DNA_ipo_types.h" +#include "DNA_key_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_sequence_types.h" +#include "DNA_userdef_types.h" +#include "DNA_view2d_types.h" +#include "DNA_windowmanager_types.h" + +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_ipo.h" +#include "BKE_key.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "ED_anim_api.h" +#include "ED_util.h" + +#include "UI_resources.h" +#include "UI_view2d.h" + +/* **************************** */ +// XXX stubs to remove! + +// NOTE: the code in this file has yet to be rewritten to get rid of the editipo system which is past its use-by-date - Aligorith + +typedef struct EditIpo { + IpoCurve *icu; + short disptype; + short flag; + unsigned int col; +} EditIpo; + +#define ISPOIN(a, b, c) ( (a->b) && (a->c) ) +#define ISPOIN3(a, b, c, d) ( (a->b) && (a->c) && (a->d) ) +#define ISPOIN4(a, b, c, d, e) ( (a->b) && (a->c) && (a->d) && (a->e) ) + +/* *************************** */ + +/* helper func - draw keyframe vertices only for an IPO-curve */ +static void draw_ipovertices_keyframes(IpoCurve *icu, View2D *v2d, short disptype, short edit, short sel) +{ + BezTriple *bezt= icu->bezt; + float v1[2]; + int a, b; + + bglBegin(GL_POINTS); + + for (a = 0; a < icu->totvert; a++, bezt++) { + /* IPO_DISPBITS is used for displaying curves for bitflag variables */ + if (disptype == IPO_DISPBITS) { + /*if (v2d->cur.xmin < bezt->vec[1][0] < v2d->cur.xmax) {*/ + short ok= 0; + + if (edit) { + if ((bezt->f2 & SELECT) == sel) + ok= 1; + } + else ok= 1; + + if (ok) { + int val= (int)bezt->vec[1][1]; + v1[0]= bezt->vec[1][0]; + + for (b= 0; b < 31; b++) { + if (val & (1<<b)) { + v1[1]= b + 1; + bglVertex3fv(v1); + } + } + } + /*}*/ + } + else { /* normal (non bit) curves */ + if (edit) { + /* Only the vertex of the line, the + * handler are drawn later + */ + if ((bezt->f2 & SELECT) == sel) /* && G.v2d->cur.xmin < bezt->vec[1][0] < G.v2d->cur.xmax)*/ + bglVertex3fv(bezt->vec[1]); + } + else { + /* draw only if in bounds */ + /*if (G.v2d->cur.xmin < bezt->vec[1][0] < G.v2d->cur.xmax)*/ + bglVertex3fv(bezt->vec[1]); + } + } + } + bglEnd(); +} + +/* helper func - draw handle vertex for an IPO-Curve as a round unfilled circle */ +static void draw_ipohandle_control(float x, float y, float xscale, float yscale, float hsize) +{ + static GLuint displist=0; + + /* initialise round circle shape */ + if (displist == 0) { + GLUquadricObj *qobj; + + displist= glGenLists(1); + glNewList(displist, GL_COMPILE_AND_EXECUTE); + + qobj = gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); + gluDisk(qobj, 0.07, 0.8, 12, 1); + gluDeleteQuadric(qobj); + + glEndList(); + } + + /* adjust view transform before starting */ + glTranslatef(x, y, 0.0f); + glScalef(1.0/xscale*hsize, 1.0/yscale*hsize, 1.0); + + /* draw! */ + glCallList(displist); + + /* restore view transform */ + glScalef(xscale/hsize, yscale/hsize, 1.0); + glTranslatef(-x, -y, 0.0f); +} + +/* helper func - draw handle vertices only for an IPO-curve (if it is in EditMode) */ +static void draw_ipovertices_handles(IpoCurve *icu, View2D *v2d, short disptype, short sel) +{ + BezTriple *bezt= icu->bezt; + BezTriple *prevbezt = NULL; + float hsize, xscale, yscale; + int a; + + /* get view settings */ + hsize= UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); + UI_view2d_getscale(v2d, &xscale, &yscale); + + /* set handle color */ + if (sel) UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); + else UI_ThemeColor(TH_HANDLE_VERTEX); + + for (a= 0; a < icu->totvert; a++, prevbezt=bezt, bezt++) { + if (disptype != IPO_DISPBITS) { + if (ELEM(icu->ipo, IPO_BEZ, IPO_MIXED)) { + /* Draw the editmode handels for a bezier curve (others don't have handles) + * if their selection status matches the selection status we're drawing for + * - first handle only if previous beztriple was bezier-mode + * - second handle only if current beztriple is bezier-mode + */ + if ( (!prevbezt && (bezt->ipo==IPO_BEZ)) || (prevbezt && (prevbezt->ipo==IPO_BEZ)) ) { + if ((bezt->f1 & SELECT) == sel)/* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/ + draw_ipohandle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize); + } + + if (bezt->ipo==IPO_BEZ) { + if ((bezt->f3 & SELECT) == sel)/* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/ + draw_ipohandle_control(bezt->vec[2][0], bezt->vec[2][1], xscale, yscale, hsize); + } + } + } + } +} + +static void draw_ipovertices(SpaceIpo *sipo, ARegion *ar, int sel) +{ + View2D *v2d= &ar->v2d; + EditIpo *ei= sipo->editipo; + int nr, val = 0; + + /* this shouldn't get called while drawing in selection-buffer anyway */ + //if (G.f & G_PICKSEL) return; + + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + for (nr=0; nr<sipo->totipo; nr++, ei++) { + if ISPOIN(ei, flag & IPO_VISIBLE, icu) { + /* select colors to use to draw keyframes */ + if (sipo->showkey) { + if (sel) UI_ThemeColor(TH_TEXT_HI); + else UI_ThemeColor(TH_TEXT); + } + else if (ei->flag & IPO_EDIT) { + if (sel) UI_ThemeColor(TH_VERTEX_SELECT); + else UI_ThemeColor(TH_VERTEX); + } + else { + if (sel) UI_ThemeColor(TH_TEXT_HI); + else UI_ThemeColor(TH_TEXT); + + val= (ei->icu->flag & IPO_SELECT)!=0; + if (sel != val) continue; + } + + /* We can't change the color in the middle of + * GL_POINTS because then Blender will segfault + * on TNT2 / Linux with NVidia's drivers + * (at least up to ver. 4349) + */ + + /* draw keyframes, then the handles (if in editmode) */ + draw_ipovertices_keyframes(ei->icu, v2d, ei->disptype, (ei->flag & IPO_EDIT), sel); + + /* Now draw the two vertex of the handles, + * This needs to be done after the keyframes, + * because we can't call glPointSize + * in the middle of a glBegin/glEnd also the + * bug comment before. + */ + if ((ei->flag & IPO_EDIT) && (sipo->flag & SIPO_NOHANDLES)==0) + draw_ipovertices_handles(ei->icu, v2d, ei->disptype, sel); + } + } + + glPointSize(1.0); +} + +/* draw lines for IPO-curve handles only (this is only done in EditMode) */ +static void draw_ipohandles(SpaceIpo *sipo, ARegion *ar, int sel) +{ + EditIpo *ei; + extern unsigned int nurbcol[]; + unsigned int *col; + int a, b; + + /* don't draw handle lines if handles are not shown */ + if (sipo->flag & SIPO_NOHANDLES) + return; + + if (sel) col= nurbcol+4; + else col= nurbcol; + + ei= sipo->editipo; + for (a=0; a<sipo->totipo; a++, ei++) { + if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, disptype!=IPO_DISPBITS) { + if (ELEM(ei->icu->ipo, IPO_BEZ, IPO_MIXED)) { + BezTriple *bezt=ei->icu->bezt, *prevbezt=NULL; + float *fp; + + for (b= 0; b < ei->icu->totvert; b++, prevbezt=bezt, bezt++) { + if ((bezt->f2 & SELECT)==sel) { + fp= bezt->vec[0]; + + /* only draw first handle if previous segment had handles */ + if ( (!prevbezt && (bezt->ipo==IPO_BEZ)) || (prevbezt && (prevbezt->ipo==IPO_BEZ)) ) + { + cpack(col[bezt->h1]); + glBegin(GL_LINE_STRIP); + glVertex2fv(fp); glVertex2fv(fp+3); + glEnd(); + + } + + /* only draw second handle if this segment is bezier */ + if (bezt->ipo == IPO_BEZ) + { + cpack(col[bezt->h2]); + glBegin(GL_LINE_STRIP); + glVertex2fv(fp+3); glVertex2fv(fp+6); + glEnd(); + } + } + else { + /* only draw first handle if previous segment was had handles, and selection is ok */ + if ( ((bezt->f1 & SELECT)==sel) && + ( (!prevbezt && (bezt->ipo==IPO_BEZ)) || (prevbezt && (prevbezt->ipo==IPO_BEZ)) ) ) + { + fp= bezt->vec[0]; + cpack(col[bezt->h1]); + + glBegin(GL_LINE_STRIP); + glVertex2fv(fp); glVertex2fv(fp+3); + glEnd(); + } + + /* only draw second handle if this segment is bezier, and selection is ok */ + if ( ((bezt->f3 & SELECT)==sel) && + (bezt->ipo == IPO_BEZ) ) + { + fp= bezt->vec[1]; + cpack(col[bezt->h2]); + + glBegin(GL_LINE_STRIP); + glVertex2fv(fp); glVertex2fv(fp+3); + glEnd(); + } + } + } + } + } + } +} + +/* helper func - draw one repeat of an ipo-curve: bitflag curve only (this is evil stuff to expose to user like this) */ +static void draw_ipocurve_repeat_bits (IpoCurve *icu, View2D *v2d, float cycxofs) +{ + BezTriple *bezt= icu->bezt; + int a; + + /* loop over each keyframe, drawing a line extending from that point */ + for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) { + int val= (int)bezt->vec[1][1]; + int b= 0; + + /* for each bit in the int, draw a line if the keyframe incorporates it */ + for (b = 0; b < 31; b++) { + if (val & (1<<b)) { + float v1[2]; + + /* value stays constant */ + v1[1]= b+1; + + glBegin(GL_LINE_STRIP); + /* extend left too if first keyframe, and not cyclic extrapolation */ + if ((a == 0) && !(icu->extrap & IPO_CYCL)) { + v1[0]= v2d->cur.xmin+cycxofs; + glVertex2fv(v1); + } + + /* must pass through current keyframe */ + v1[0]= bezt->vec[1][0] + cycxofs; + glVertex2fv(v1); + + /* 1. if there is a next keyframe, extend until then OR + * 2. extend until 'infinity' if not cyclic extrapolation + */ + if ((a+1) < icu->totvert) v1[0]= (bezt+1)->vec[1][0]+cycxofs; + else if ((icu->extrap & IPO_CYCL)==0) v1[0]= v2d->cur.xmax+cycxofs; + + glVertex2fv(v1); + glEnd(); + } + } + } +} + +/* helper func - draw one repeat of an ipo-curve: normal curve */ +static void draw_ipocurve_repeat_normal (IpoCurve *icu, View2D *v2d, float cycxofs, float cycyofs, float *facp) +{ + BezTriple *prevbezt= icu->bezt; + BezTriple *bezt= prevbezt+1; + float v1[2], v2[2], v3[2], v4[2]; + float *fp, data[120]; + float fac= *(facp); + int b= icu->totvert-1; + int resol; + + glBegin(GL_LINE_STRIP); + + /* extrapolate to left? */ + if ((icu->extrap & IPO_CYCL)==0) { + /* left-side of view comes before first keyframe, so need to extend as not cyclic */ + if (prevbezt->vec[1][0] > v2d->cur.xmin) { + v1[0]= v2d->cur.xmin; + + /* y-value depends on the interpolation */ + if ((icu->extrap==IPO_HORIZ) || (prevbezt->ipo==IPO_CONST) || (icu->totvert==1)) { + /* just extend across the first keyframe's value */ + v1[1]= prevbezt->vec[1][1]; + } + else if (prevbezt->ipo==IPO_LIN) { + /* extrapolate linear dosnt use the handle, use the next points center instead */ + fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]); + if (fac) fac= 1.0f/fac; + v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]); + } + else { + /* based on angle of handle 1 (relative to keyframe) */ + fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]); + if (fac) fac= 1.0f/fac; + v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]); + } + + glVertex2fv(v1); + } + } + + /* if only one keyframe, add it now */ + if (icu->totvert == 1) { + v1[0]= prevbezt->vec[1][0] + cycxofs; + v1[1]= prevbezt->vec[1][1] + cycyofs; + glVertex2fv(v1); + } + + /* draw curve between first and last keyframe (if there are enough to do so) */ + while (b--) { + if (prevbezt->ipo==IPO_CONST) { + /* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */ + v1[0]= prevbezt->vec[1][0]+cycxofs; + v1[1]= prevbezt->vec[1][1]+cycyofs; + glVertex2fv(v1); + + v1[0]= bezt->vec[1][0]+cycxofs; + v1[1]= prevbezt->vec[1][1]+cycyofs; + glVertex2fv(v1); + } + else if (prevbezt->ipo==IPO_LIN) { + /* Linear interpolation: just add one point (which should add a new line segment) */ + v1[0]= prevbezt->vec[1][0]+cycxofs; + v1[1]= prevbezt->vec[1][1]+cycyofs; + glVertex2fv(v1); + } + else { + /* Bezier-Interpolation: draw curve as series of segments between keyframes + * - resol determines number of points to sample in between keyframes + */ + + /* resol not depending on horizontal resolution anymore, drivers for example... */ + if (icu->driver) + resol= 32; + else + resol= 3.0*sqrt(bezt->vec[1][0] - prevbezt->vec[1][0]); + + if (resol < 2) { + /* only draw one */ + v1[0]= prevbezt->vec[1][0]+cycxofs; + v1[1]= prevbezt->vec[1][1]+cycyofs; + glVertex2fv(v1); + } + else { + /* clamp resolution to max of 32 */ + if (resol > 32) resol= 32; + + v1[0]= prevbezt->vec[1][0]+cycxofs; + v1[1]= prevbezt->vec[1][1]+cycyofs; + v2[0]= prevbezt->vec[2][0]+cycxofs; + v2[1]= prevbezt->vec[2][1]+cycyofs; + + v3[0]= bezt->vec[0][0]+cycxofs; + v3[1]= bezt->vec[0][1]+cycyofs; + v4[0]= bezt->vec[1][0]+cycxofs; + v4[1]= bezt->vec[1][1]+cycyofs; + + correct_bezpart(v1, v2, v3, v4); + + forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, 3); + forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data+1, resol, 3); + + for (fp= data; resol; resol--, fp+= 3) + glVertex2fv(fp); + } + } + + /* get next pointers */ + prevbezt= bezt; + bezt++; + + /* last point? */ + if (b == 0) { + v1[0]= prevbezt->vec[1][0]+cycxofs; + v1[1]= prevbezt->vec[1][1]+cycyofs; + glVertex2fv(v1); + } + } + + /* extrapolate to right? (see code for left-extrapolation above too) */ + if ((icu->extrap & IPO_CYCL)==0) { + if (prevbezt->vec[1][0] < v2d->cur.xmax) { + v1[0]= v2d->cur.xmax; + + /* y-value depends on the interpolation */ + if ((icu->extrap==IPO_HORIZ) || (prevbezt->ipo==IPO_CONST) || (icu->totvert==1)) { + /* based on last keyframe's value */ + v1[1]= prevbezt->vec[1][1]; + } + else if (prevbezt->ipo==IPO_LIN) { + /* extrapolate linear dosnt use the handle, use the previous points center instead */ + bezt = prevbezt-1; + fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]); + if (fac) fac= 1.0f/fac; + v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]); + } + else { + /* based on angle of handle 1 (relative to keyframe) */ + fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]); + if (fac) fac= 1.0f/fac; + v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]); + } + + glVertex2fv(v1); + } + } + + glEnd(); + + /* return fac, as we alter it */ + *(facp) = fac; +} + +/* draw all ipo-curves */ +static void draw_ipocurves(SpaceIpo *sipo, ARegion *ar, int sel) +{ + View2D *v2d= &ar->v2d; + EditIpo *ei; + int nr, val/*, pickselcode=0*/; + + /* if we're drawing for GL_SELECT, reset pickselcode first + * - there's only one place that will do this, so it should be fine + */ + //if (G.f & G_PICKSEL) + // pickselcode= 1; + + ei= sipo->editipo; + for (nr=0; nr<sipo->totipo; nr++, ei++) { + if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) { + /* val is used to indicate if curve can be edited */ + //if (G.f & G_PICKSEL) { + // /* when using OpenGL to select stuff (on mouseclick) */ + // glLoadName(pickselcode++); + // val= 1; + //} + //else { + /* filter to only draw those that are selected or unselected (based on drawing mode */ + val= (ei->flag & (IPO_SELECT+IPO_EDIT)) != 0; + val= (val==sel); + //} + + /* only draw those curves that we can draw */ + if (val) { + IpoCurve *icu= ei->icu; + float cycdx=0.0f, cycdy=0.0f, cycxofs=0.0f, cycyofs=0.0f; + const int lastindex= (icu->totvert-1); + float fac= 0.0f; + int cycount=1; + + /* set color for curve curve: + * - bitflag curves (evil) must always be drawn coloured as they cannot work with IPO-Keys + * - when IPO-Keys are shown, individual curves are not editable, so we show by drawing them all black + */ + if ((sipo->showkey) && (ei->disptype!=IPO_DISPBITS)) UI_ThemeColor(TH_TEXT); + else cpack(ei->col); + + /* cyclic curves - get offset and number of repeats to display */ + if (icu->extrap & IPO_CYCL) { + BezTriple *bezt= icu->bezt; + BezTriple *lastbezt= bezt + lastindex; + + /* calculate cycle length and amplitude */ + cycdx= lastbezt->vec[1][0] - bezt->vec[1][0]; + cycdy= lastbezt->vec[1][1] - bezt->vec[1][1]; + + /* check that the cycle does have some length */ + if (cycdx > 0.01f) { + /* count cycles before first frame */ + while (icu->bezt->vec[1][0]+cycxofs > v2d->cur.xmin) { + cycxofs -= cycdx; + if (icu->extrap & IPO_DIR) cycyofs-= cycdy; + cycount++; + } + + /* count cycles after last frame (and adjust offset) */ + fac= 0.0f; + while (lastbezt->vec[1][0]+fac < v2d->cur.xmax) { + cycount++; + fac += cycdx; + } + } + } + + /* repeat process for each repeat */ + while (cycount--) { + /* bitflag curves are drawn differently to normal curves */ + if (ei->disptype==IPO_DISPBITS) + draw_ipocurve_repeat_bits(icu, v2d, cycxofs); + else + draw_ipocurve_repeat_normal(icu, v2d, cycxofs, cycyofs, &fac); + + /* prepare for next cycle by adjusing offsets */ + cycxofs += cycdx; + if (icu->extrap & IPO_DIR) cycyofs += cycdy; + } + + /* vertical line that indicates the end of a speed curve */ + if ((sipo->blocktype==ID_CU) && (icu->adrcode==CU_SPEED)) { + int b= icu->totvert-1; + + if (b) { + BezTriple *bezt= icu->bezt+b; + + glColor3ub(0, 0, 0); + + glBegin(GL_LINES); + glVertex2f(bezt->vec[1][0], 0.0f); + glVertex2f(bezt->vec[1][0], bezt->vec[1][1]); + glEnd(); + } + } + } + } + } +} + +#if 0 +static void draw_ipokey(SpaceIpo *sipo, ARegion *ar) +{ + View2D *v2d= &ar->v2d; + IpoKey *ik; + + glBegin(GL_LINES); + for (ik= sipo->ipokey.first; ik; ik= ik->next) { + if (ik->flag & SELECT) glColor3ub(0xFF, 0xFF, 0x99); + else glColor3ub(0xAA, 0xAA, 0x55); + + glVertex2f(ik->val, v2d->cur.ymin); + glVertex2f(ik->val, v2d->cur.ymax); + } + glEnd(); +} +#endif + +void drawipospace(ScrArea *sa, ARegion *ar) +{ + SpaceIpo *sipo= sa->spacedata.first; + //View2D *v2d= &ar->v2d; + EditIpo *ei; + + + if(sipo->editipo) { + + /* correct scale for degrees? */ + // XXX this should be calculated elsewhere +#if 0 + disptype= -1; + ei= sipo->editipo; + for(a=0; a<sipo->totipo; a++, ei++) { + if(ei->flag & IPO_VISIBLE) { + if(disptype== -1) disptype= ei->disptype; + else if(disptype!=ei->disptype) disptype= 0; + } + } +#endif + // now set grid size (done elsehwere now) + + /* ipokeys */ +#if 0 + if(sipo->showkey) { + //if(sipo->ipokey.first==0) make_ipokey(); + //else update_ipokey_val(); + make_ipokey(); + draw_ipokey(sipo); + } +#endif + + /* map ipo-points for drawing if scaled ipo */ + //if (NLA_IPO_SCALED) + // ANIM_nla_mapping_apply_ipo(OBACT, sipo->ipo, 0, 0); + + /* draw deselect */ + draw_ipocurves(sipo, ar, 0); + draw_ipohandles(sipo, ar, 0); + draw_ipovertices(sipo, ar, 0); + + /* draw select */ + draw_ipocurves(sipo, ar, 1); + draw_ipohandles(sipo, ar, 1); + draw_ipovertices(sipo, ar, 1); + + /* undo mapping of ipo-points for drawing if scaled ipo */ + //if (NLA_IPO_SCALED) + // ANIM_nla_mapping_apply_ipo(OBACT, sipo->ipo, 1, 0); + + } +} diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index cc8e03e0b44..bf028f374bd 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -99,7 +99,6 @@ static void node_mouse_select(SpaceNode *snode, ARegion *ar, short *mval, short ;// node_link_viewer(snode, node); //std_rmouse_transform(node_transform_ext); /* does undo push for select */ - ED_region_tag_redraw(ar); } } @@ -121,6 +120,9 @@ static int node_select_exec(bContext *C, wmOperator *op) node_mouse_select(snode, ar, mval, extend); break; } + + WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); /* Do we need to pass the scene? */ + return OPERATOR_FINISHED; } @@ -227,6 +229,8 @@ static int node_borderselect_exec(bContext *C, wmOperator *op) } } + WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); /* Do we need to pass the scene? */ + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index 743f1edba3e..fad19f6a023 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -1357,7 +1357,7 @@ static void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) else if(soops->outlinevis==SO_USERDEF) { PointerRNA userdefptr; - RNA_pointer_create(NULL, NULL, &RNA_UserPreferences, &U, &userdefptr); + RNA_pointer_create(NULL, &RNA_UserPreferences, &U, &userdefptr); ten= outliner_add_element(soops, &soops->tree, (void*)&userdefptr, NULL, TSE_RNA_STRUCT, -1); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index ccd6e52f577..dfb4e0dea55 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3480,8 +3480,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, Base *base, Part psys->flag &= ~PSYS_DRAWING; if(psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } wmLoadMatrix(v3d->viewmat); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 8ac672eb260..675fbc5aab2 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -181,15 +181,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) return (SpaceLink *)v3dn; } -static void view3d_main_area_draw(const bContext *C, ARegion *ar) -{ - /* draw entirely, view changes should be handled here */ - ScrArea *sa= CTX_wm_area(C); - View3D *v3d= sa->spacedata.first; /* XXX get from region */ - - drawview3dspace(CTX_wm_screen(C), CTX_data_scene(C), ar, v3d); -} - /* add handlers, stuff you only do once or on area/region changes */ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar) { diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 48fb6d76703..4fc64782fe8 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -51,6 +51,7 @@ #include "BLI_rand.h" #include "BKE_anim.h" +#include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_image.h" #include "BKE_ipo.h" @@ -76,6 +77,7 @@ #include "ED_keyframing.h" #include "ED_mesh.h" #include "ED_screen.h" +#include "ED_space_api.h" #include "ED_util.h" #include "ED_types.h" @@ -1835,10 +1837,11 @@ static CustomDataMask get_viewedit_datamask(bScreen *screen) return mask; } - - -void drawview3dspace(bScreen *screen, Scene *scene, ARegion *ar, View3D *v3d) +void view3d_main_area_draw(const bContext *C, ARegion *ar) { + Scene *scene= CTX_data_scene(C); + ScrArea *sa= CTX_wm_area(C); + View3D *v3d= sa->spacedata.first; /* XXX get from region */ Scene *sce; Base *base; Object *ob; @@ -1846,7 +1849,7 @@ void drawview3dspace(bScreen *screen, Scene *scene, ARegion *ar, View3D *v3d) Object *obact = OBACT; /* from now on all object derived meshes check this */ - v3d->customdata_mask= get_viewedit_datamask(screen); + v3d->customdata_mask= get_viewedit_datamask(CTX_wm_screen(C)); /* update all objects, ipos, matrices, displists, etc. Flags set by depgraph or manual, no layer check here, gets correct flushed */ @@ -1999,12 +2002,7 @@ void drawview3dspace(bScreen *screen, Scene *scene, ARegion *ar, View3D *v3d) view3d_update_depths(ar, v3d); } - if(G.moving) { -// BIF_drawConstraint(); -// if(obedit || (G.f & G_PARTICLEEDIT)) -// BIF_drawPropCircle(); // only editmode and particles have proportional edit -// BIF_drawSnap(); - } + ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST); // REEB_draw(); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 6f638131679..90bc976f015 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -69,6 +69,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "ED_space_api.h" #include "ED_screen.h" #include "ED_types.h" @@ -96,6 +97,7 @@ typedef struct ViewOpsData { int origx, origy, oldx, oldy; int origkey; + void *vh; // XXX temp } ViewOpsData; #define TRACKBALLSIZE (1.1) @@ -362,6 +364,10 @@ static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event) default: if(event->type==vod->origkey && event->val==0) { + if(vod->vh) { + ED_region_draw_cb_exit(CTX_wm_region(C)->type, vod->vh); + ED_region_tag_redraw(CTX_wm_region(C)); + } MEM_freeN(vod); op->customdata= NULL; @@ -372,6 +378,12 @@ static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +static void vh_draw(const bContext *C, ARegion *ar) +{ + glColor3ub(100, 200, 100); + glRectf(-0.2, -0.2, 0.2, 0.2); +} + static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) { ViewOpsData *vod; @@ -380,6 +392,8 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) viewops_data(C, op, event); vod= op->customdata; + vod->vh= ED_region_draw_cb_activate(CTX_wm_region(C)->type, vh_draw, REGION_DRAW_POST); + /* switch from camera view when: */ if(vod->v3d->persp != V3D_PERSP) { @@ -1344,41 +1358,6 @@ void VIEW3D_OT_drawtype(wmOperatorType *ot) /* ********************************************************* */ -void set_render_border(Scene *scene, ARegion *ar, View3D *v3d) -{ - rcti rect; - short val; - - val= 0; // XXX get_border(&rect, 3); - if(val) { - rctf vb; - - calc_viewborder(scene, ar, v3d, &vb); - - scene->r.border.xmin= ((float)rect.xmin-vb.xmin)/(vb.xmax-vb.xmin); - scene->r.border.ymin= ((float)rect.ymin-vb.ymin)/(vb.ymax-vb.ymin); - scene->r.border.xmax= ((float)rect.xmax-vb.xmin)/(vb.xmax-vb.xmin); - scene->r.border.ymax= ((float)rect.ymax-vb.ymin)/(vb.ymax-vb.ymin); - - CLAMP(scene->r.border.xmin, 0.0, 1.0); - CLAMP(scene->r.border.ymin, 0.0, 1.0); - CLAMP(scene->r.border.xmax, 0.0, 1.0); - CLAMP(scene->r.border.ymax, 0.0, 1.0); - - /* drawing a border surrounding the entire camera view switches off border rendering - * or the border covers no pixels */ - if ((scene->r.border.xmin <= 0.0 && scene->r.border.xmax >= 1.0 && - scene->r.border.ymin <= 0.0 && scene->r.border.ymax >= 1.0) || - (scene->r.border.xmin == scene->r.border.xmax || - scene->r.border.ymin == scene->r.border.ymax )) - { - scene->r.mode &= ~R_BORDER; - } else { - scene->r.mode |= R_BORDER; - } - } -} - void view3d_border_zoom(Scene *scene, ARegion *ar, View3D *v3d) { diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 3caa2d25da7..d8025698f02 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -136,6 +136,25 @@ static int retopo_mesh_paint_check() {return 0;} /* end XXX ************* */ + +/* well... in this file a lot of view mode manipulation happens, so let's have it defined here */ +void ED_view3d_exit_paint_modes(bContext *C) +{ + if(G.f & G_VERTEXPAINT) + WM_operator_name_call(C, "VIEW3D_OT_vpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); + +// if(G.f & G_TEXTUREPAINT) set_texturepaint(); +// if(G.f & G_WEIGHTPAINT) set_wpaint(); +// if(G.f & G_SCULPTMODE) set_sculptmode(); +// if(G.f & G_PARTICLEEDIT) PE_set_particle_edit(); + + G.f &= ~(G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT+G_SCULPTMODE+G_PARTICLEEDIT); +} + + + + + static void do_view3d_buttons(bContext *C, void *arg, int event); #define B_SCENELOCK 101 @@ -5368,7 +5387,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) if (v3d->modeselect == V3D_OBJECTMODE_SEL) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); ED_armature_exit_posemode(basact); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ @@ -5376,7 +5395,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) else if (v3d->modeselect == V3D_EDITMODE_SEL) { if(!obedit) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); ED_object_enter_editmode(C, EM_WAITCURSOR); ED_undo_push(C, "Original"); /* here, because all over code enter_editmode is abused */ } @@ -5384,7 +5403,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) else if (v3d->modeselect == V3D_SCULPTMODE_SEL) { if (!(G.f & G_SCULPTMODE)) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEUNDO); /* exit editmode and undo */ // XXX set_sculptmode(); @@ -5393,16 +5412,16 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) else if (v3d->modeselect == V3D_VERTEXPAINTMODE_SEL) { if (!(G.f & G_VERTEXPAINT)) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ - -// XXX set_vpaint(); + + WM_operator_name_call(C, "VIEW3D_OT_vpaint_toggle", WM_OP_EXEC_REGION_WIN, NULL, NULL); } } else if (v3d->modeselect == V3D_TEXTUREPAINTMODE_SEL) { if (!(G.f & G_TEXTUREPAINT)) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ // XXX set_texturepaint(); @@ -5411,7 +5430,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) else if (v3d->modeselect == V3D_WEIGHTPAINTMODE_SEL) { if (!(G.f & G_WEIGHTPAINT) && (ob && ob->type == OB_MESH) ) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ @@ -5431,7 +5450,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event) else if(v3d->modeselect == V3D_PARTICLEEDITMODE_SEL){ if (!(G.f & G_PARTICLEEDIT)) { v3d->flag &= ~V3D_MODE; -// XXX exit_paint_modes(); + ED_view3d_exit_paint_modes(C); if(obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* exit editmode and undo */ // XXX PE_set_particle_edit(); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index d9d58b188ea..8fc00ffd538 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -33,6 +33,7 @@ /* internal exports only */ struct bScreen; +struct ARegion; struct BoundBox; struct Object; struct DerivedMesh; @@ -64,7 +65,7 @@ typedef struct ViewDepths { #define IS_CLIPPED 12000 /* view3d_header.c */ -void view3d_header_buttons(const struct bContext *C, ARegion *ar); +void view3d_header_buttons(const struct bContext *C, struct ARegion *ar); /* view3d_ops.c */ void view3d_operatortypes(void); @@ -83,7 +84,7 @@ void VIEW3D_OT_render_border(struct wmOperatorType *ot); void VIEW3D_OT_drawtype(struct wmOperatorType *ot); /* drawobject.c */ -void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag); +void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, int flag); int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt); void drawcircball(int mode, float *cent, float rad, float tmat[][4]); void draw_object_instance(Scene *scene, View3D *v3d, Object *ob, int dt, int outline); @@ -97,17 +98,17 @@ int draw_armature(Scene *scene, View3D *v3d, Base *base, int dt, int flag); void draw_mesh_textured(Scene *scene, View3D *v3d, Object *ob, struct DerivedMesh *dm, int faceselect); /* view3d_draw.c */ -void drawview3dspace(struct bScreen *screen, Scene *scene, ARegion *ar, View3D *v3d); -void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *)); +void view3d_main_area_draw(const struct bContext *C, struct ARegion *ar); +void draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, int (* func)(void *)); void view3d_clr_clipping(void); void view3d_set_clipping(View3D *v3d); void add_view3d_after(View3D *v3d, Base *base, int type, int flag); void make_axis_color(char *col, char *col2, char axis); -void calc_viewborder(Scene *scene, ARegion *ar, View3D *v3d, rctf *viewborder_r); +void calc_viewborder(Scene *scene, struct ARegion *ar, View3D *v3d, rctf *viewborder_r); void circf(float x, float y, float rad); void circ(float x, float y, float rad); -void view3d_update_depths(ARegion *ar, View3D *v3d); +void view3d_update_depths(struct ARegion *ar, View3D *v3d); /* view3d_select.c */ void VIEW3D_OT_select(struct wmOperatorType *ot); @@ -116,6 +117,12 @@ void VIEW3D_OT_circle_select(struct wmOperatorType *ot); void VIEW3D_OT_borderselect(struct wmOperatorType *ot); void VIEW3D_OT_lasso_select(struct wmOperatorType *ot); +void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc); + +/* vpaint.c */ +void VIEW3D_OT_vpaint_toggle(struct wmOperatorType *ot); +void VIEW3D_OT_vpaint(struct wmOperatorType *ot); + /* view3d_view.c */ void VIEW3D_OT_smoothview(struct wmOperatorType *ot); void VIEW3D_OT_setcameratoview(struct wmOperatorType *ot); @@ -124,19 +131,19 @@ void view3d_operator_needs_opengl(const struct bContext *C); int boundbox_clip(View3D *v3d, float obmat[][4], struct BoundBox *bb); -void view3d_project_short_clip(ARegion *ar, View3D *v3d, float *vec, short *adr, float projmat[4][4], float wmat[4][4]); -void view3d_project_short_noclip(ARegion *ar, float *vec, short *adr, float mat[4][4]); -void view3d_project_float(ARegion *a, float *vec, float *adr, float mat[4][4]); +void view3d_project_short_clip(struct ARegion *ar, View3D *v3d, float *vec, short *adr, float projmat[4][4], float wmat[4][4]); +void view3d_project_short_noclip(struct ARegion *ar, float *vec, short *adr, float mat[4][4]); +void view3d_project_float(struct ARegion *a, float *vec, float *adr, float mat[4][4]); void view3d_get_object_project_mat(View3D *v3d, struct Object *ob, float pmat[4][4], float vmat[4][4]); -void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4]); +void view3d_project_float(struct ARegion *ar, float *vec, float *adr, float mat[4][4]); int get_view3d_viewplane(View3D *v3d, int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize); -void initlocalview(Scene *scene, ARegion *ar, View3D *v3d); +void initlocalview(Scene *scene, struct ARegion *ar, View3D *v3d); void restore_localviewdata(View3D *vd); void endlocalview(Scene *scene, ScrArea *sa); -void centerview(ARegion *ar, View3D *v3d); +void centerview(struct ARegion *ar, View3D *v3d); void smooth_view(struct bContext *C, Object *, Object *, float *ofs, float *quat, float *dist, float *lens); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 73329ac5aa3..da4b752f370 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -79,6 +79,8 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_lasso_select); WM_operatortype_append(VIEW3D_OT_setcameratoview); WM_operatortype_append(VIEW3D_OT_drawtype); + WM_operatortype_append(VIEW3D_OT_vpaint_toggle); + WM_operatortype_append(VIEW3D_OT_vpaint); transform_operatortypes(); } @@ -88,6 +90,9 @@ void view3d_keymap(wmWindowManager *wm) ListBase *keymap= WM_keymap_listbase(wm, "View3D", SPACE_VIEW3D, 0); wmKeymapItem *km; + /* paint poll checks mode */ + WM_keymap_verify_item(keymap, "VIEW3D_OT_vpaint", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_viewrotate", MIDDLEMOUSE, KM_PRESS, 0, 0); @@ -148,6 +153,8 @@ void view3d_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "VIEW3D_OT_render_border", BKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_set_camera_to_view", PAD0, KM_PRESS, KM_ALT|KM_CTRL, 0); + + WM_keymap_add_item(keymap, "VIEW3D_OT_vpaint_toggle", VKEY, KM_PRESS, 0, 0); /* TODO - this is just while we have no way to load a text datablock */ RNA_string_set(WM_keymap_add_item(keymap, "SCRIPT_OT_run_pyfile", PKEY, KM_PRESS, 0, 0)->ptr, "filename", "test.py"); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index e1cc1f65c15..6664ac11877 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -89,7 +89,7 @@ #include "view3d_intern.h" // own include -static void view3d_set_viewcontext(bContext *C, ViewContext *vc) +void view3d_set_viewcontext(bContext *C, ViewContext *vc) { memset(vc, 0, sizeof(ViewContext)); vc->ar= CTX_wm_region(C); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 933523cfe54..cc80645ad76 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -993,28 +993,6 @@ void setviewmatrixview3d(Scene *scene, View3D *v3d) } } -void setcameratoview3d(View3D *v3d) -{ - Object *ob; - float dvec[3]; - - ob= v3d->camera; - dvec[0]= v3d->dist*v3d->viewinv[2][0]; - dvec[1]= v3d->dist*v3d->viewinv[2][1]; - dvec[2]= v3d->dist*v3d->viewinv[2][2]; - VECCOPY(ob->loc, dvec); - VecSubf(ob->loc, ob->loc, v3d->ofs); - v3d->viewquat[0]= -v3d->viewquat[0]; - /* */ - /*if (ob->transflag & OB_QUAT) { - QUATCOPY(ob->quat, v3d->viewquat); - } else {*/ - QuatToEul(v3d->viewquat, ob->rot); - /*}*/ - v3d->viewquat[0]= -v3d->viewquat[0]; -} - - /* IGLuint-> GLuint*/ /* Warning: be sure to account for a negative return value * This is an error, "Too many objects in select buffer" diff --git a/source/blender/editors/space_view3d/vpaint.c b/source/blender/editors/space_view3d/vpaint.c new file mode 100644 index 00000000000..f253612259f --- /dev/null +++ b/source/blender/editors/space_view3d/vpaint.c @@ -0,0 +1,1684 @@ +/** + * $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 <math.h> +#include <string.h> + +#ifdef WIN32 +#include <io.h> +#else +#include <unistd.h> +#endif + +#include "MEM_guardedalloc.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "MTC_matrixops.h" + +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_brush_types.h" +#include "DNA_cloth_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_particle_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" +#include "DNA_view3d_types.h" +#include "DNA_userdef_types.h" + +#include "BKE_armature.h" +#include "BKE_DerivedMesh.h" +#include "BKE_cloth.h" +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_deform.h" +#include "BKE_displist.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "ED_mesh.h" +#include "ED_object.h" +#include "ED_screen.h" +#include "ED_util.h" +#include "ED_view3d.h" + +#include "view3d_intern.h" + + /* Gvp.mode */ +#define VP_MIX 0 +#define VP_ADD 1 +#define VP_SUB 2 +#define VP_MUL 3 +#define VP_BLUR 4 +#define VP_LIGHTEN 5 +#define VP_DARKEN 6 + +#define MAXINDEX 512000 + +/* XXX */ +static void BIF_undo_push() {} +static void error() {} +static int get_mbut() {return 0;} + +VPaint Gvp= {1.0, 1.0, 1.0, 0.2, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT+VP_SPRAY, 0}; +VPaint Gwp= {1.0, 1.0, 1.0, 1.0, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT, 0}; + +static int *get_indexarray(void) +{ + return MEM_mallocN(sizeof(int)*MAXINDEX + 2, "vertexpaint"); +} + +void free_vertexpaint() +{ + + if(Gvp.vpaint_prev) MEM_freeN(Gvp.vpaint_prev); + Gvp.vpaint_prev= NULL; + + mesh_octree_table(NULL, NULL, NULL, 'e'); +} + +/* in contradiction to cpack drawing colors, the MCOL colors (vpaint colors) are per byte! + so not endian sensitive. Mcol = ABGR!!! so be cautious with cpack calls */ + +unsigned int rgba_to_mcol(float r, float g, float b, float a) +{ + int ir, ig, ib, ia; + unsigned int col; + char *cp; + + ir= floor(255.0*r); + if(ir<0) ir= 0; else if(ir>255) ir= 255; + ig= floor(255.0*g); + if(ig<0) ig= 0; else if(ig>255) ig= 255; + ib= floor(255.0*b); + if(ib<0) ib= 0; else if(ib>255) ib= 255; + ia= floor(255.0*a); + if(ia<0) ia= 0; else if(ia>255) ia= 255; + + cp= (char *)&col; + cp[0]= ia; + cp[1]= ib; + cp[2]= ig; + cp[3]= ir; + + return col; + +} + +static unsigned int vpaint_get_current_col(VPaint *vp) +{ + return rgba_to_mcol(vp->r, vp->g, vp->b, 1.0f); +} + +void do_shared_vertexcol(Mesh *me) +{ + /* if no mcol: do not do */ + /* if tface: only the involved faces, otherwise all */ + MFace *mface; + MTFace *tface; + int a; + short *scolmain, *scol; + char *mcol; + + if(me->mcol==0 || me->totvert==0 || me->totface==0) return; + + scolmain= MEM_callocN(4*sizeof(short)*me->totvert, "colmain"); + + tface= me->mtface; + mface= me->mface; + mcol= (char *)me->mcol; + for(a=me->totface; a>0; a--, mface++, mcol+=16) { + if((tface && tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) { + scol= scolmain+4*mface->v1; + scol[0]++; scol[1]+= mcol[1]; scol[2]+= mcol[2]; scol[3]+= mcol[3]; + scol= scolmain+4*mface->v2; + scol[0]++; scol[1]+= mcol[5]; scol[2]+= mcol[6]; scol[3]+= mcol[7]; + scol= scolmain+4*mface->v3; + scol[0]++; scol[1]+= mcol[9]; scol[2]+= mcol[10]; scol[3]+= mcol[11]; + if(mface->v4) { + scol= scolmain+4*mface->v4; + scol[0]++; scol[1]+= mcol[13]; scol[2]+= mcol[14]; scol[3]+= mcol[15]; + } + } + if(tface) tface++; + } + + a= me->totvert; + scol= scolmain; + while(a--) { + if(scol[0]>1) { + scol[1]/= scol[0]; + scol[2]/= scol[0]; + scol[3]/= scol[0]; + } + scol+= 4; + } + + tface= me->mtface; + mface= me->mface; + mcol= (char *)me->mcol; + for(a=me->totface; a>0; a--, mface++, mcol+=16) { + if((tface && tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) { + scol= scolmain+4*mface->v1; + mcol[1]= scol[1]; mcol[2]= scol[2]; mcol[3]= scol[3]; + scol= scolmain+4*mface->v2; + mcol[5]= scol[1]; mcol[6]= scol[2]; mcol[7]= scol[3]; + scol= scolmain+4*mface->v3; + mcol[9]= scol[1]; mcol[10]= scol[2]; mcol[11]= scol[3]; + if(mface->v4) { + scol= scolmain+4*mface->v4; + mcol[13]= scol[1]; mcol[14]= scol[2]; mcol[15]= scol[3]; + } + } + if(tface) tface++; + } + + MEM_freeN(scolmain); +} + +void make_vertexcol(Scene *scene, int shade) /* single ob */ +{ + Object *ob; + Mesh *me; + + if(scene->obedit) { + error("Unable to perform function in Edit Mode"); + return; + } + + ob= OBACT; + if(!ob || ob->id.lib) return; + me= get_mesh(ob); + if(me==0) return; + + /* copies from shadedisplist to mcol */ + if(!me->mcol) { + CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface); + mesh_update_customdata_pointers(me); + } + + if(shade) + shadeMeshMCol(scene, ob, me); + else + memset(me->mcol, 255, 4*sizeof(MCol)*me->totface); + +// XXX if (me->mr) multires_load_cols(me); + + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + +} + +static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot) +{ + if(vp->vpaint_prev) { + MEM_freeN(vp->vpaint_prev); + vp->vpaint_prev= NULL; + } + vp->tot= tot; + + if(mcol==NULL || tot==0) return; + + vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev"); + memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot); + +} + +static void copy_wpaint_prev (VPaint *vp, MDeformVert *dverts, int dcount) +{ + if (vp->wpaint_prev) { + free_dverts(vp->wpaint_prev, vp->tot); + vp->wpaint_prev= NULL; + } + + if(dverts && dcount) { + + vp->wpaint_prev = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaint prev"); + vp->tot = dcount; + copy_dverts (vp->wpaint_prev, dverts, dcount); + } +} + + +void clear_vpaint(Scene *scene) +{ + Mesh *me; + Object *ob; + unsigned int *to, paintcol; + int a; + + if((G.f & G_VERTEXPAINT)==0) return; + + ob= OBACT; + me= get_mesh(ob); + if(!ob || ob->id.lib) return; + + if(me==0 || me->mcol==0 || me->totface==0) return; + + paintcol= vpaint_get_current_col(&Gvp); + + to= (unsigned int *)me->mcol; + a= 4*me->totface; + while(a--) { + *to= paintcol; + to++; + } + BIF_undo_push("Clear vertex colors"); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + +} + +void clear_vpaint_selectedfaces(Scene *scene) +{ + Mesh *me; + MFace *mf; + Object *ob; + unsigned int paintcol, *mcol; + int i; + + ob= OBACT; + me= get_mesh(ob); + if(me==0 || me->totface==0) return; + + if(!me->mcol) + make_vertexcol(scene, 0); + + paintcol= vpaint_get_current_col(&Gvp); + + mf = me->mface; + mcol = (unsigned int*)me->mcol; + for (i = 0; i < me->totface; i++, mf++, mcol+=4) { + if (mf->flag & ME_FACE_SEL) { + mcol[0] = paintcol; + mcol[1] = paintcol; + mcol[2] = paintcol; + mcol[3] = paintcol; + } + } + + BIF_undo_push("Clear vertex colors"); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); +} + + +/* fills in the selected faces with the current weight and vertex group */ +void clear_wpaint_selectedfaces(Scene *scene) +{ + float editbutvweight; + float paintweight= editbutvweight; + Mesh *me; + MFace *mface; + Object *ob; + MDeformWeight *dw, *uw; + int *indexar; + int index, vgroup; + unsigned int faceverts[5]={0,0,0,0,0}; + unsigned char i; + int vgroup_mirror= -1; + + ob= OBACT; + me= ob->data; + if(me==0 || me->totface==0 || me->dvert==0 || !me->mface) return; + + indexar= get_indexarray(); + for(index=0, mface=me->mface; index<me->totface; index++, mface++) { + if((mface->flag & ME_FACE_SEL)==0) + indexar[index]= 0; + else + indexar[index]= index+1; + } + + vgroup= ob->actdef-1; + + /* directly copied from weight_paint, should probaby split into a seperate function */ + /* if mirror painting, find the other group */ + if(Gwp.flag & VP_MIRROR_X) { + bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1); + if(defgroup) { + bDeformGroup *curdef; + int actdef= 0; + char name[32]; + + BLI_strncpy(name, defgroup->name, 32); + bone_flip_name(name, 0); /* 0 = don't strip off number extensions */ + + for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++) + if (!strcmp(curdef->name, name)) + break; + if(curdef==NULL) { + int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */ + curdef= add_defgroup_name (ob, name); + ob->actdef= olddef; + } + + if(curdef && curdef!=defgroup) + vgroup_mirror= actdef; + } + } + /* end copy from weight_paint*/ + + copy_wpaint_prev(&Gwp, me->dvert, me->totvert); + + for(index=0; index<me->totface; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + mface= me->mface + (indexar[index]-1); + /* just so we can loop through the verts */ + faceverts[0]= mface->v1; + faceverts[1]= mface->v2; + faceverts[2]= mface->v3; + faceverts[3]= mface->v4; + for (i=0; i<3 || faceverts[i]; i++) { + if(!((me->dvert+faceverts[i])->flag)) { + dw= verify_defweight(me->dvert+faceverts[i], vgroup); + if(dw) { + uw= verify_defweight(Gwp.wpaint_prev+faceverts[i], vgroup); + uw->weight= dw->weight; /* set the undio weight */ + dw->weight= paintweight; + + if(Gwp.flag & VP_MIRROR_X) { /* x mirror painting */ + int j= mesh_get_x_mirror_vert(ob, faceverts[i]); + if(j>=0) { + /* copy, not paint again */ + if(vgroup_mirror != -1) { + dw= verify_defweight(me->dvert+j, vgroup_mirror); + uw= verify_defweight(Gwp.wpaint_prev+j, vgroup_mirror); + } else { + dw= verify_defweight(me->dvert+j, vgroup); + uw= verify_defweight(Gwp.wpaint_prev+j, vgroup); + } + uw->weight= dw->weight; /* set the undo weight */ + dw->weight= paintweight; + } + } + } + (me->dvert+faceverts[i])->flag= 1; + } + } + } + } + + index=0; + while (index<me->totvert) { + (me->dvert+index)->flag= 0; + index++; + } + + MEM_freeN(indexar); + copy_wpaint_prev(&Gwp, NULL, 0); + + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + BIF_undo_push("Set vertex weight"); +} + + +void vpaint_dogamma(Scene *scene) +{ + Mesh *me; + Object *ob; + float igam, fac; + int a, temp; + char *cp, gamtab[256]; + + if((G.f & G_VERTEXPAINT)==0) return; + + ob= OBACT; + me= get_mesh(ob); + if(me==0 || me->mcol==0 || me->totface==0) return; + + igam= 1.0/Gvp.gamma; + for(a=0; a<256; a++) { + + fac= ((float)a)/255.0; + fac= Gvp.mul*pow( fac, igam); + + temp= 255.9*fac; + + if(temp<=0) gamtab[a]= 0; + else if(temp>=255) gamtab[a]= 255; + else gamtab[a]= temp; + } + + a= 4*me->totface; + cp= (char *)me->mcol; + while(a--) { + + cp[1]= gamtab[ cp[1] ]; + cp[2]= gamtab[ cp[2] ]; + cp[3]= gamtab[ cp[3] ]; + + cp+= 4; + } +} + +/* used for both 3d view and image window */ +void sample_vpaint(Scene *scene, ARegion *ar) /* frontbuf */ +{ + unsigned int col; + int x, y; + short mval[2]; + char *cp; + +// getmouseco_areawin(mval); + x= mval[0]; y= mval[1]; + + if(x<0 || y<0) return; + if(x>=ar->winx || y>=ar->winy) return; + + x+= ar->winrct.xmin; + y+= ar->winrct.ymin; + + glReadBuffer(GL_FRONT); + glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); + glReadBuffer(GL_BACK); + + cp = (char *)&col; + + if(G.f & (G_VERTEXPAINT|G_WEIGHTPAINT)) { + Gvp.r= cp[0]/255.0f; + Gvp.g= cp[1]/255.0f; + Gvp.b= cp[2]/255.0f; + } + else { + Brush *brush= scene->toolsettings->imapaint.brush; + + if(brush) { + brush->rgb[0]= cp[0]/255.0f; + brush->rgb[1]= cp[1]/255.0f; + brush->rgb[2]= cp[2]/255.0f; + + } + } + +} + +static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac) +{ + char *cp1, *cp2, *cp; + int mfac; + unsigned int col=0; + + if(fac==0) return col1; + if(fac>=255) return col2; + + mfac= 255-fac; + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + cp[0]= 255; + cp[1]= (mfac*cp1[1]+fac*cp2[1])/255; + cp[2]= (mfac*cp1[2]+fac*cp2[2])/255; + cp[3]= (mfac*cp1[3]+fac*cp2[3])/255; + + return col; +} + +static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac) +{ + char *cp1, *cp2, *cp; + int temp; + unsigned int col=0; + + if(fac==0) return col1; + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + cp[0]= 255; + temp= cp1[1] + ((fac*cp2[1])/255); + if(temp>254) cp[1]= 255; else cp[1]= temp; + temp= cp1[2] + ((fac*cp2[2])/255); + if(temp>254) cp[2]= 255; else cp[2]= temp; + temp= cp1[3] + ((fac*cp2[3])/255); + if(temp>254) cp[3]= 255; else cp[3]= temp; + + return col; +} + +static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac) +{ + char *cp1, *cp2, *cp; + int temp; + unsigned int col=0; + + if(fac==0) return col1; + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + cp[0]= 255; + temp= cp1[1] - ((fac*cp2[1])/255); + if(temp<0) cp[1]= 0; else cp[1]= temp; + temp= cp1[2] - ((fac*cp2[2])/255); + if(temp<0) cp[2]= 0; else cp[2]= temp; + temp= cp1[3] - ((fac*cp2[3])/255); + if(temp<0) cp[3]= 0; else cp[3]= temp; + + return col; +} + +static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac) +{ + char *cp1, *cp2, *cp; + int mfac; + unsigned int col=0; + + if(fac==0) return col1; + + mfac= 255-fac; + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + /* first mul, then blend the fac */ + cp[0]= 255; + cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])/255) )/255; + cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])/255) )/255; + cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])/255) )/255; + + + return col; +} + +static unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int fac) +{ + char *cp1, *cp2, *cp; + int mfac; + unsigned int col=0; + + if(fac==0) return col1; + if(fac>=255) return col2; + + mfac= 255-fac; + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + /* See if are lighter, if so mix, else dont do anything. + if the paint col is darker then the original, then ignore */ + if (cp1[1]+cp1[2]+cp1[3] > cp2[1]+cp2[2]+cp2[3]) + return col1; + + cp[0]= 255; + cp[1]= (mfac*cp1[1]+fac*cp2[1])/255; + cp[2]= (mfac*cp1[2]+fac*cp2[2])/255; + cp[3]= (mfac*cp1[3]+fac*cp2[3])/255; + + return col; +} + +static unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fac) +{ + char *cp1, *cp2, *cp; + int mfac; + unsigned int col=0; + + if(fac==0) return col1; + if(fac>=255) return col2; + + mfac= 255-fac; + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + /* See if were darker, if so mix, else dont do anything. + if the paint col is brighter then the original, then ignore */ + if (cp1[1]+cp1[2]+cp1[3] < cp2[1]+cp2[2]+cp2[3]) + return col1; + + cp[0]= 255; + cp[1]= (mfac*cp1[1]+fac*cp2[1])/255; + cp[2]= (mfac*cp1[2]+fac*cp2[2])/255; + cp[3]= (mfac*cp1[3]+fac*cp2[3])/255; + return col; +} + +static void vpaint_blend( unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha) +{ + + if(Gvp.mode==VP_MIX || Gvp.mode==VP_BLUR) *col= mcol_blend( *col, paintcol, alpha); + else if(Gvp.mode==VP_ADD) *col= mcol_add( *col, paintcol, alpha); + else if(Gvp.mode==VP_SUB) *col= mcol_sub( *col, paintcol, alpha); + else if(Gvp.mode==VP_MUL) *col= mcol_mul( *col, paintcol, alpha); + else if(Gvp.mode==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha); + else if(Gvp.mode==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha); + + /* if no spray, clip color adding with colorig & orig alpha */ + if((Gvp.flag & VP_SPRAY)==0) { + unsigned int testcol=0, a; + char *cp, *ct, *co; + + alpha= (int)(255.0*Gvp.a); + + if(Gvp.mode==VP_MIX || Gvp.mode==VP_BLUR) testcol= mcol_blend( *colorig, paintcol, alpha); + else if(Gvp.mode==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha); + else if(Gvp.mode==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha); + else if(Gvp.mode==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha); + else if(Gvp.mode==VP_LIGHTEN) testcol= mcol_lighten( *colorig, paintcol, alpha); + else if(Gvp.mode==VP_DARKEN) testcol= mcol_darken( *colorig, paintcol, alpha); + + cp= (char *)col; + ct= (char *)&testcol; + co= (char *)colorig; + + for(a=0; a<4; a++) { + if( ct[a]<co[a] ) { + if( cp[a]<ct[a] ) cp[a]= ct[a]; + else if( cp[a]>co[a] ) cp[a]= co[a]; + } + else { + if( cp[a]<co[a] ) cp[a]= co[a]; + else if( cp[a]>ct[a] ) cp[a]= ct[a]; + } + } + } +} + + +static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x, int y, float size) +{ + struct ImBuf *ibuf; + int a, tot=0, index; + + if(totface+4>=MAXINDEX) return 0; + + if(size>64.0) size= 64.0; + + ibuf= view3d_read_backbuf(vc, x-size, y-size, x+size, y+size); + if(ibuf) { + unsigned int *rt= ibuf->rect; + + memset(indexar, 0, sizeof(int)*totface+4); /* plus 2! first element is total, +2 was giving valgrind errors, +4 seems ok */ + + size= ibuf->x*ibuf->y; + while(size--) { + + if(*rt) { + index= WM_framebuffer_to_index(*rt); + if(index>0 && index<=totface) + indexar[index] = 1; + } + + rt++; + } + + for(a=1; a<=totface; a++) { + if(indexar[a]) indexar[tot++]= a; + } + + IMB_freeImBuf(ibuf); + } + + return tot; +} + +static int calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], float *vert_nor, short *mval) +{ + float fac, dx, dy; + int alpha; + short vertco[2]; + + if(vp->flag & VP_SOFT) { + project_short_noclip(vc->ar, vc->v3d, vert_nor, vertco); + dx= mval[0]-vertco[0]; + dy= mval[1]-vertco[1]; + + fac= sqrt(dx*dx + dy*dy); + if(fac > vp->size) return 0; + if(vp->flag & VP_HARD) + alpha= 255; + else + alpha= 255.0*vp->a*(1.0-fac/vp->size); + } + else { + alpha= 255.0*vp->a; + } + + if(vp->flag & VP_NORMALS) { + float *no= vert_nor+3; + + /* transpose ! */ + fac= vpimat[2][0]*no[0]+vpimat[2][1]*no[1]+vpimat[2][2]*no[2]; + if(fac>0.0) { + dx= vpimat[0][0]*no[0]+vpimat[0][1]*no[1]+vpimat[0][2]*no[2]; + dy= vpimat[1][0]*no[0]+vpimat[1][1]*no[1]+vpimat[1][2]*no[2]; + + alpha*= fac/sqrt(dx*dx + dy*dy + fac*fac); + } + else return 0; + } + + return alpha; +} + +static void wpaint_blend(MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval) +{ + + if(dw==NULL || uw==NULL) return; + + if(Gwp.mode==VP_MIX || Gwp.mode==VP_BLUR) + dw->weight = paintval*alpha + dw->weight*(1.0-alpha); + else if(Gwp.mode==VP_ADD) + dw->weight += paintval*alpha; + else if(Gwp.mode==VP_SUB) + dw->weight -= paintval*alpha; + else if(Gwp.mode==VP_MUL) + /* first mul, then blend the fac */ + dw->weight = ((1.0-alpha) + alpha*paintval)*dw->weight; + else if(Gwp.mode==VP_LIGHTEN) { + if (dw->weight < paintval) + dw->weight = paintval*alpha + dw->weight*(1.0-alpha); + } else if(Gwp.mode==VP_DARKEN) { + if (dw->weight > paintval) + dw->weight = paintval*alpha + dw->weight*(1.0-alpha); + } + CLAMP(dw->weight, 0.0f, 1.0f); + + /* if no spray, clip result with orig weight & orig alpha */ + if((Gwp.flag & VP_SPRAY)==0) { + float testw=0.0f; + + alpha= Gwp.a; + if(Gwp.mode==VP_MIX || Gwp.mode==VP_BLUR) + testw = paintval*alpha + uw->weight*(1.0-alpha); + else if(Gwp.mode==VP_ADD) + testw = uw->weight + paintval*alpha; + else if(Gwp.mode==VP_SUB) + testw = uw->weight - paintval*alpha; + else if(Gwp.mode==VP_MUL) + /* first mul, then blend the fac */ + testw = ((1.0-alpha) + alpha*paintval)*uw->weight; + else if(Gwp.mode==VP_LIGHTEN) { + if (uw->weight < paintval) + testw = paintval*alpha + uw->weight*(1.0-alpha); + else + testw = uw->weight; + } else if(Gwp.mode==VP_DARKEN) { + if (uw->weight > paintval) + testw = paintval*alpha + uw->weight*(1.0-alpha); + else + testw = uw->weight; + } + CLAMP(testw, 0.0f, 1.0f); + + if( testw<uw->weight ) { + if(dw->weight < testw) dw->weight= testw; + else if(dw->weight > uw->weight) dw->weight= uw->weight; + } + else { + if(dw->weight > testw) dw->weight= testw; + else if(dw->weight < uw->weight) dw->weight= uw->weight; + } + } + +} + +/* ----------------------------------------------------- */ + +/* used for 3d view, on active object, assumes me->dvert exists */ +/* if mode==1: */ +/* samples cursor location, and gives menu with vertex groups to activate */ +/* else */ +/* sets editbutvweight to the closest weight value to vertex */ +/* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */ +static void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) +{ + ViewContext vc; + Object *ob= OBACT; + Mesh *me= get_mesh(ob); + int index; + short mval[2], sco[2]; + + if (!me) return; + +// getmouseco_areawin(mval); + index= view3d_sample_backbuf(&vc, mval[0], mval[1]); + + if(index && index<=me->totface) { + MFace *mface; + + mface= ((MFace *)me->mface) + index-1; + + if(mode==1) { /* sampe which groups are in here */ + MDeformVert *dv; + int a, totgroup; + + totgroup= BLI_countlist(&ob->defbase); + if(totgroup) { + int totmenu=0; + int *groups=MEM_callocN(totgroup*sizeof(int), "groups"); + + dv= me->dvert+mface->v1; + for(a=0; a<dv->totweight; a++) { + if (dv->dw[a].def_nr<totgroup) + groups[dv->dw[a].def_nr]= 1; + } + dv= me->dvert+mface->v2; + for(a=0; a<dv->totweight; a++) { + if (dv->dw[a].def_nr<totgroup) + groups[dv->dw[a].def_nr]= 1; + } + dv= me->dvert+mface->v3; + for(a=0; a<dv->totweight; a++) { + if (dv->dw[a].def_nr<totgroup) + groups[dv->dw[a].def_nr]= 1; + } + if(mface->v4) { + dv= me->dvert+mface->v4; + for(a=0; a<dv->totweight; a++) { + if (dv->dw[a].def_nr<totgroup) + groups[dv->dw[a].def_nr]= 1; + } + } + for(a=0; a<totgroup; a++) + if(groups[a]) totmenu++; + + if(totmenu==0) { + //notice("No Vertex Group Selected"); + } + else { + bDeformGroup *dg; + short val; + char item[40], *str= MEM_mallocN(40*totmenu+40, "menu"); + + strcpy(str, "Vertex Groups %t"); + for(a=0, dg=ob->defbase.first; dg && a<totgroup; a++, dg= dg->next) { + if(groups[a]) { + sprintf(item, "|%s %%x%d", dg->name, a); + strcat(str, item); + } + } + + val= 0; // XXX pupmenu(str); + if(val>=0) { + ob->actdef= val+1; + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + } + MEM_freeN(str); + } + MEM_freeN(groups); + } +// else notice("No Vertex Groups in Object"); + } + else { + DerivedMesh *dm; + MDeformWeight *dw; + float editbutvweight; + float w1, w2, w3, w4, co[3], fac; + + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + if(dm->getVertCo==NULL) { + //notice("Not supported yet"); + } + else { + /* calc 3 or 4 corner weights */ + dm->getVertCo(dm, mface->v1, co); + project_short_noclip(ar, v3d, co, sco); + w1= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1])); + + dm->getVertCo(dm, mface->v2, co); + project_short_noclip(ar, v3d, co, sco); + w2= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1])); + + dm->getVertCo(dm, mface->v3, co); + project_short_noclip(ar, v3d, co, sco); + w3= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1])); + + if(mface->v4) { + dm->getVertCo(dm, mface->v4, co); + project_short_noclip(ar, v3d, co, sco); + w4= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1])); + } + else w4= 1.0e10; + + fac= MIN4(w1, w2, w3, w4); + if(w1==fac) { + dw= get_defweight(me->dvert+mface->v1, ob->actdef-1); + if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f; + } + else if(w2==fac) { + dw= get_defweight(me->dvert+mface->v2, ob->actdef-1); + if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f; + } + else if(w3==fac) { + dw= get_defweight(me->dvert+mface->v3, ob->actdef-1); + if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f; + } + else if(w4==fac) { + if(mface->v4) { + dw= get_defweight(me->dvert+mface->v4, ob->actdef-1); + if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f; + } + } + } + dm->release(dm); + } + + } + +} + +static void do_weight_paint_vertex(Object *ob, int index, int alpha, float paintweight, int vgroup_mirror) +{ + Mesh *me= ob->data; + MDeformWeight *dw, *uw; + int vgroup= ob->actdef-1; + + if(Gwp.flag & VP_ONLYVGROUP) { + dw= get_defweight(me->dvert+index, vgroup); + uw= get_defweight(Gwp.wpaint_prev+index, vgroup); + } + else { + dw= verify_defweight(me->dvert+index, vgroup); + uw= verify_defweight(Gwp.wpaint_prev+index, vgroup); + } + if(dw==NULL || uw==NULL) + return; + + wpaint_blend(dw, uw, (float)alpha/255.0, paintweight); + + if(Gwp.flag & VP_MIRROR_X) { /* x mirror painting */ + int j= mesh_get_x_mirror_vert(ob, index); + if(j>=0) { + /* copy, not paint again */ + if(vgroup_mirror != -1) + uw= verify_defweight(me->dvert+j, vgroup_mirror); + else + uw= verify_defweight(me->dvert+j, vgroup); + + uw->weight= dw->weight; + } + } +} + + +void weight_paint(Scene *scene, ARegion *ar, View3D *v3d) +{ + ViewContext vc; + float editbutvweight; // XXX + Object *ob; + Mesh *me; + MFace *mface; + float mat[4][4], imat[4][4], paintweight, *vertexcosnos; + float vpimat[3][3]; + int *indexar, index, totindex, alpha, totw; + int vgroup_mirror= -1; + short mval[2], mvalo[2], firsttime=1; + + if((G.f & G_WEIGHTPAINT)==0) return; + if(scene->obedit) return; +// XXX if(multires_level1_test()) return; + + ob= OBACT; + if(!ob || ob->id.lib) return; + + me= get_mesh(ob); + if(me==NULL || me->totface==0) return; + + /* if nothing was added yet, we make dverts and a vertex deform group */ +// if (!me->dvert) +// create_dverts(&me->id); + +// if(qual & LR_CTRLKEY) { + sample_wpaint(scene, ar, v3d, 0); +// return; +// } +// if(qual & LR_SHIFTKEY) { +// sample_wpaint(scene, ar, v3d, 1); +// return; +// } + + /* ALLOCATIONS! no return after this line */ + /* painting on subsurfs should give correct points too, this returns me->totvert amount */ + vertexcosnos= mesh_get_mapped_verts_nors(scene, ob); + indexar= get_indexarray(); + copy_wpaint_prev(&Gwp, me->dvert, me->totvert); + + /* this happens on a Bone select, when no vgroup existed yet */ + if(ob->actdef<=0) { + Object *modob; + if((modob = modifiers_isDeformedByArmature(ob))) { + bPoseChannel *pchan; + for(pchan= modob->pose->chanbase.first; pchan; pchan= pchan->next) + if(pchan->bone->flag & SELECT) + break; + if(pchan) { + bDeformGroup *dg= get_named_vertexgroup(ob, pchan->name); + if(dg==NULL) + dg= add_defgroup_name(ob, pchan->name); /* sets actdef */ + else + ob->actdef= get_defgroup_num(ob, dg); + } + } + } + if(ob->defbase.first==NULL) { + add_defgroup(ob); + } + + if(ob->lay & v3d->lay); else error("Active object is not in this layer"); + +// XXX persp(PERSP_VIEW); + /* imat for normals */ + Mat4MulMat4(mat, ob->obmat, v3d->viewmat); + Mat4Invert(imat, mat); + Mat3CpyMat4(vpimat, imat); + + /* load projection matrix */ + wmMultMatrix(ob->obmat); + wmGetSingleMatrix(mat); + wmLoadMatrix(v3d->viewmat); + +// getmouseco_areawin(mvalo); + +// getmouseco_areawin(mval); + mvalo[0]= mval[0]; + mvalo[1]= mval[1]; + + /* if mirror painting, find the other group */ + if(Gwp.flag & VP_MIRROR_X) { + bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1); + if(defgroup) { + bDeformGroup *curdef; + int actdef= 0; + char name[32]; + + BLI_strncpy(name, defgroup->name, 32); + bone_flip_name(name, 0); /* 0 = don't strip off number extensions */ + + for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++) + if (!strcmp(curdef->name, name)) + break; + if(curdef==NULL) { + int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */ + curdef= add_defgroup_name (ob, name); + ob->actdef= olddef; + } + + if(curdef && curdef!=defgroup) + vgroup_mirror= actdef; + } + } + + while (get_mbut() & 0) { +// getmouseco_areawin(mval); + + if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { + firsttime= 0; + + /* which faces are involved */ + if(Gwp.flag & VP_AREA) { + totindex= sample_backbuf_area(&vc, indexar, me->totface, mval[0], mval[1], Gwp.size); + } + else { + indexar[0]= view3d_sample_backbuf(&vc, mval[0], mval[1]); + if(indexar[0]) totindex= 1; + else totindex= 0; + } + + MTC_Mat4SwapMat4(v3d->persmat, mat); + + if(Gwp.flag & VP_COLINDEX) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + + mface= ((MFace *)me->mface) + (indexar[index]-1); + + if(mface->mat_nr!=ob->actcol-1) { + indexar[index]= 0; + } + } + } + } + + if((G.f & G_FACESELECT) && me->mface) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + + mface= ((MFace *)me->mface) + (indexar[index]-1); + + if((mface->flag & ME_FACE_SEL)==0) { + indexar[index]= 0; + } + } + } + } + + /* make sure each vertex gets treated only once */ + /* and calculate filter weight */ + totw= 0; + if(Gwp.mode==VP_BLUR) + paintweight= 0.0f; + else + paintweight= editbutvweight; + + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + mface= me->mface + (indexar[index]-1); + + (me->dvert+mface->v1)->flag= 1; + (me->dvert+mface->v2)->flag= 1; + (me->dvert+mface->v3)->flag= 1; + if(mface->v4) (me->dvert+mface->v4)->flag= 1; + + if(Gwp.mode==VP_BLUR) { + MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = verify_defweight; + + if(Gwp.flag & VP_ONLYVGROUP) + dw_func= get_defweight; + + dw= dw_func(me->dvert+mface->v1, ob->actdef-1); + if(dw) {paintweight+= dw->weight; totw++;} + dw= dw_func(me->dvert+mface->v2, ob->actdef-1); + if(dw) {paintweight+= dw->weight; totw++;} + dw= dw_func(me->dvert+mface->v3, ob->actdef-1); + if(dw) {paintweight+= dw->weight; totw++;} + if(mface->v4) { + dw= dw_func(me->dvert+mface->v4, ob->actdef-1); + if(dw) {paintweight+= dw->weight; totw++;} + } + } + } + } + + if(Gwp.mode==VP_BLUR) + paintweight/= (float)totw; + + for(index=0; index<totindex; index++) { + + if(indexar[index] && indexar[index]<=me->totface) { + mface= me->mface + (indexar[index]-1); + + if((me->dvert+mface->v1)->flag) { + alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v1, mval); + if(alpha) { + do_weight_paint_vertex(ob, mface->v1, alpha, paintweight, vgroup_mirror); + } + (me->dvert+mface->v1)->flag= 0; + } + + if((me->dvert+mface->v2)->flag) { + alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v2, mval); + if(alpha) { + do_weight_paint_vertex(ob, mface->v2, alpha, paintweight, vgroup_mirror); + } + (me->dvert+mface->v2)->flag= 0; + } + + if((me->dvert+mface->v3)->flag) { + alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v3, mval); + if(alpha) { + do_weight_paint_vertex(ob, mface->v3, alpha, paintweight, vgroup_mirror); + } + (me->dvert+mface->v3)->flag= 0; + } + + if((me->dvert+mface->v4)->flag) { + if(mface->v4) { + alpha= calc_vp_alpha_dl(&Gwp, &vc, vpimat, vertexcosnos+6*mface->v4, mval); + if(alpha) { + do_weight_paint_vertex(ob, mface->v4, alpha, paintweight, vgroup_mirror); + } + (me->dvert+mface->v4)->flag= 0; + } + } + } + } + + MTC_Mat4SwapMat4(v3d->persmat, mat); + + } + + if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { + + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + + if(Gwp.flag & (VP_AREA|VP_SOFT)) { + /* draw circle in backbuf! */ +// XXX persp(PERSP_WIN); +// XXX fdrawXORcirc((float)mval[0], (float)mval[1], Gwp.size); +// XXX persp(PERSP_VIEW); + } + + mvalo[0]= mval[0]; + mvalo[1]= mval[1]; + } + } + + if(vertexcosnos) + MEM_freeN(vertexcosnos); + MEM_freeN(indexar); + copy_wpaint_prev(&Gwp, NULL, 0); + + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + + /* and particles too */ + if(ob->particlesystem.first) { + ParticleSystem *psys; + int i; + + psys= ob->particlesystem.first; + while(psys) { + for(i=0; i<PSYS_TOT_VG; i++) { + if(psys->vgroup[i]==ob->actdef) { + psys->recalc |= PSYS_RECALC_HAIR; + break; + } + } + + psys= psys->next; + } + } + + BIF_undo_push("Weight Paint"); +} + +void set_wpaint(bContext *C, wmOperator *op) /* toggle */ +{ + Object *ob= CTX_data_active_object(C); + Scene *scene= CTX_data_scene(C); + Mesh *me; + + ob= OBACT; + if(!ob || ob->id.lib) return; + me= get_mesh(ob); + + if(me && me->totface>=MAXINDEX) { + error("Maximum number of faces: %d", MAXINDEX-1); + G.f &= ~G_WEIGHTPAINT; + return; + } + + if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT; + else G.f |= G_WEIGHTPAINT; + + + /* Weightpaint works by overriding colors in mesh, + * so need to make sure we recalc on enter and + * exit (exit needs doing regardless because we + * should redeform). + */ + if (me) { + DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA); + } + + if(G.f & G_WEIGHTPAINT) { + Object *par; + + mesh_octree_table(ob, NULL, NULL, 's'); + + /* verify if active weight group is also active bone */ + par= modifiers_isDeformedByArmature(ob); + if(par && (par->flag & OB_POSEMODE)) { + bPoseChannel *pchan; + for(pchan= par->pose->chanbase.first; pchan; pchan= pchan->next) + if(pchan->bone->flag & BONE_ACTIVE) + break; + // if(pchan) + // XXX vertexgroup_select_by_name(ob, pchan->name); + } + } + else { + mesh_octree_table(ob, NULL, NULL, 'e'); + } +} + +/* ************ set / clear vertex paint mode ********** */ + +/* retrieve whether cursor should be set or operator should be done */ +static int vp_poll(bContext *C) +{ + if(G.f & G_VERTEXPAINT) { + ScrArea *sa= CTX_wm_area(C); + if(sa->spacetype==SPACE_VIEW3D) { + ARegion *ar= CTX_wm_region(C); + if(ar->regiontype==RGN_TYPE_WINDOW) + return 1; + } + } + return 0; +} + +static void vp_drawcursor(bContext *C, int x, int y) +{ + glTranslatef((float)x, (float)y, 0.0f); + + glColor4ub(255, 255, 255, 128); + glEnable( GL_LINE_SMOOTH ); + glEnable(GL_BLEND); + glutil_draw_lined_arc(0.0, M_PI*2.0, Gvp.size, 40); + glDisable(GL_BLEND); + glDisable( GL_LINE_SMOOTH ); + + glTranslatef((float)-x, (float)-y, 0.0f); +} + +static int set_vpaint(bContext *C, wmOperator *op) /* toggle */ +{ + Object *ob= CTX_data_active_object(C); + Scene *scene= CTX_data_scene(C); + Mesh *me; + + if(object_data_is_libdata(ob)) { + G.f &= ~G_VERTEXPAINT; + return OPERATOR_FINISHED; + } + + me= get_mesh(ob); + + if(me && me->totface>=MAXINDEX) { + error("Maximum number of faces: %d", MAXINDEX-1); + G.f &= ~G_VERTEXPAINT; + return OPERATOR_FINISHED; + } + + if(me && me->mcol==NULL) make_vertexcol(scene, 0); + + /* toggle: end vpaint */ + if(G.f & G_VERTEXPAINT){ + G.f &= ~G_VERTEXPAINT; + + WM_paint_cursor_end(CTX_wm_manager(C), Gvp.paintcursor); + Gvp.paintcursor= NULL; + } + else { + G.f |= G_VERTEXPAINT; + /* Turn off weight painting */ + if (G.f & G_WEIGHTPAINT) + set_wpaint(C, op); + + Gvp.paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C), vp_poll, vp_drawcursor); + } + + if (me) + /* update modifier stack for mapping requirements */ + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + + WM_event_add_notifier(C, NC_SCENE|ND_MODE, ob); + + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_vpaint_toggle(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Vpaint mode"; + ot->idname= "VIEW3D_OT_vpaint_toggle"; + + /* api callbacks */ + ot->exec= set_vpaint; + ot->poll= ED_operator_object_active; + +} + + + +/* ********************** vertex paint operator ******************* */ + +/* Implementation notes: + +Operator->invoke() + - validate context (add mcol) + - create customdata storage + - call paint once (mouse click) + - add modal handler + +Operator->modal() + - for every mousemove, apply vertex paint + - exit on mouse release, free customdata + (return OPERATOR_FINISHED also removes handler and operator) + +For future: + - implement a stroke event (or mousemove with past positons) + - revise whether customdata should be added in object, in set_vpaint + - store Gvp locally (in scene?) + +*/ + +struct VPaintData { + ViewContext vc; + unsigned int paintcol; + int *indexar; + float *vertexcosnos; + float vpimat[3][3]; +}; + +static void vpaint_exit(bContext *C, wmOperator *op) +{ + struct VPaintData *vpd= op->customdata; + + if(vpd->vertexcosnos) + MEM_freeN(vpd->vertexcosnos); + MEM_freeN(vpd->indexar); + + /* frees prev buffer */ + copy_vpaint_prev(&Gvp, NULL, 0); + + ED_undo_push(C, "Vertex Paint"); + + MEM_freeN(vpd); + op->customdata= NULL; +} + +static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + + switch(event->type) { + case LEFTMOUSE: + if(event->val==0) { /* release */ + vpaint_exit(C, op); + return OPERATOR_FINISHED; + } + /* pass on, first press gets painted too */ + + case MOUSEMOVE: + { + struct VPaintData *vpd= op->customdata; + ViewContext *vc= &vpd->vc; + Object *ob= vc->obact; + Mesh *me= ob->data; + float mat[4][4]; + int *indexar= vpd->indexar; + int totindex, index; + short mval[2]; + + view3d_operator_needs_opengl(C); + + /* load projection matrix */ + wmMultMatrix(ob->obmat); + wmGetSingleMatrix(mat); + wmLoadMatrix(vc->v3d->viewmat); + + mval[0]= event->x - vc->ar->winrct.xmin; + mval[1]= event->y - vc->ar->winrct.ymin; + + /* which faces are involved */ + if(Gvp.flag & VP_AREA) { + totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], Gvp.size); + } + else { + indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]); + if(indexar[0]) totindex= 1; + else totindex= 0; + } + + MTC_Mat4SwapMat4(vc->v3d->persmat, mat); + + if(Gvp.flag & VP_COLINDEX) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + + if(mface->mat_nr!=ob->actcol-1) { + indexar[index]= 0; + } + } + } + } + if((G.f & G_FACESELECT) && me->mface) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + + if((mface->flag & ME_FACE_SEL)==0) + indexar[index]= 0; + } + } + } + + for(index=0; index<totindex; index++) { + + if(indexar[index] && indexar[index]<=me->totface) { + MFace *mface= ((MFace *)me->mface) + (indexar[index]-1); + unsigned int *mcol= ( (unsigned int *)me->mcol) + 4*(indexar[index]-1); + unsigned int *mcolorig= ( (unsigned int *)Gvp.vpaint_prev) + 4*(indexar[index]-1); + int alpha; + + if(Gvp.mode==VP_BLUR) { + unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128); + if(mface->v4) { + unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128); + vpd->paintcol= mcol_blend( fcol1, fcol2, 128); + } + else { + vpd->paintcol= mcol_blend( mcol[2], fcol1, 170); + } + + } + + alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v1, mval); + if(alpha) vpaint_blend( mcol, mcolorig, vpd->paintcol, alpha); + + alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v2, mval); + if(alpha) vpaint_blend( mcol+1, mcolorig+1, vpd->paintcol, alpha); + + alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v3, mval); + if(alpha) vpaint_blend( mcol+2, mcolorig+2, vpd->paintcol, alpha); + + if(mface->v4) { + alpha= calc_vp_alpha_dl(&Gvp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v4, mval); + if(alpha) vpaint_blend( mcol+3, mcolorig+3, vpd->paintcol, alpha); + } + } + } + + MTC_Mat4SwapMat4(vc->v3d->persmat, mat); + + do_shared_vertexcol(me); + + ED_region_tag_redraw(vc->ar); + + DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA); + } + break; + } + + return OPERATOR_RUNNING_MODAL; +} + +static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + struct VPaintData *vpd; + Object *ob= CTX_data_active_object(C); + Mesh *me; + float mat[4][4], imat[4][4]; + + /* context checks could be a poll() */ + me= get_mesh(ob); + if(me==NULL || me->totface==0) return OPERATOR_CANCELLED; + + if(me->mcol==NULL) make_vertexcol(CTX_data_scene(C), 0); + if(me->mcol==NULL) return OPERATOR_CANCELLED; + + /* make customdata storage */ + op->customdata= vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData"); + view3d_set_viewcontext(C, &vpd->vc); + + vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob); + vpd->indexar= get_indexarray(); + vpd->paintcol= vpaint_get_current_col(&Gvp); + + /* for filtering */ + copy_vpaint_prev(&Gvp, (unsigned int *)me->mcol, me->totface); + + /* some old cruft to sort out later */ + Mat4MulMat4(mat, ob->obmat, vpd->vc.v3d->viewmat); + Mat4Invert(imat, mat); + Mat3CpyMat4(vpd->vpimat, imat); + + /* do paint once for click only paint */ + vpaint_modal(C, op, event); + + /* add modal handler */ + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + + return OPERATOR_RUNNING_MODAL; +} + +void VIEW3D_OT_vpaint(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Vpaint"; + ot->idname= "VIEW3D_OT_vpaint"; + + /* api callbacks */ + ot->invoke= vpaint_invoke; + ot->modal= vpaint_modal; + /* ot->exec= vpaint_exec; <-- needs stroke property */ + ot->poll= vp_poll; + +} + + diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 6f9b34d610c..c0ef862a9c3 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -101,6 +101,7 @@ #include "ED_util.h" #include "UI_view2d.h" #include "WM_types.h" +#include "WM_api.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -329,13 +330,12 @@ void convertDisplayNumToVec(float *num, float *vec) #endif } -static void viewRedrawForce(TransInfo *t) +static void viewRedrawForce(bContext *C, TransInfo *t) { if (t->spacetype == SPACE_VIEW3D) { - // TRANSFORM_FIX_ME - // need to redraw ALL 3d view - ED_area_tag_redraw(t->sa); + /* Do we need more refined tags? */ + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); } else if (t->spacetype == SPACE_ACTION) { SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; @@ -347,8 +347,10 @@ static void viewRedrawForce(TransInfo *t) else ED_area_tag_redraw(t->sa); } - else if(t->spacetype == SPACE_NODE) { - ED_area_tag_redraw(t->sa); + else if(t->spacetype == SPACE_NODE) + { + //ED_area_tag_redraw(t->sa); + WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); } #if 0 // TRANSFORM_FIX_ME else if (t->spacetype==SPACE_IMAGE) { @@ -1101,7 +1103,7 @@ void initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) } -void transformApply(TransInfo *t) +void transformApply(bContext *C, TransInfo *t) { if (t->redraw) { @@ -1111,6 +1113,7 @@ void transformApply(TransInfo *t) selectConstraint(t); if (t->transform) { t->transform(t, t->mval); // calls recalcData() + viewRedrawForce(C, t); } t->redraw = 0; } @@ -1140,6 +1143,7 @@ int transformEnd(bContext *C, TransInfo *t) { exit_code = OPERATOR_CANCELLED; restoreTransObjects(t); // calls recalcData() + viewRedrawForce(C, t); } else { @@ -1850,8 +1854,6 @@ int Warp(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - helpline(t, gcursor); return 1; @@ -1974,8 +1976,6 @@ int Shear(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - helpline (t, t->center); return 1; @@ -2247,8 +2247,6 @@ int Resize(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); return 1; @@ -2340,8 +2338,6 @@ int ToSphere(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - return 1; } @@ -2656,8 +2652,6 @@ int Rotation(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); return 1; @@ -2765,8 +2759,6 @@ int Trackball(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); return 1; @@ -2959,8 +2951,6 @@ int Translation(TransInfo *t, short mval[2]) recalcData(t); ED_area_headerprint(t->sa, str); - - viewRedrawForce(t); drawSnapping(t); @@ -3039,8 +3029,6 @@ int ShrinkFatten(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - return 1; } @@ -3113,8 +3101,6 @@ int Tilt(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - helpline (t, t->center); return 1; @@ -3181,8 +3167,6 @@ int CurveShrinkFatten(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); return 1; @@ -3272,8 +3256,6 @@ int PushPull(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - return 1; } @@ -3387,8 +3369,6 @@ int Bevel(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - return 1; } @@ -3460,8 +3440,6 @@ int BevelWeight(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - helpline (t, t->center); return 1; @@ -3538,8 +3516,6 @@ int Crease(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - helpline (t, t->center); return 1; @@ -3657,8 +3633,6 @@ int BoneSize(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); return 1; @@ -3727,8 +3701,6 @@ int BoneEnvelope(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); return 1; @@ -3795,8 +3767,6 @@ int BoneRoll(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center); return 1; @@ -3875,8 +3845,6 @@ int BakeTime(TransInfo *t, short mval[2]) ED_area_headerprint(t->sa, str); - viewRedrawForce(t); - helpline (t, t->center); return 1; @@ -3933,8 +3901,6 @@ int Mirror(TransInfo *t, short mval[2]) recalcData(t); ED_area_headerprint(t->sa, str); - - viewRedrawForce(t); } else { @@ -3955,8 +3921,6 @@ int Mirror(TransInfo *t, short mval[2]) recalcData(t); ED_area_headerprint(t->sa, "Select a mirror axis (X, Y, Z)"); - - viewRedrawForce(t); } return 1; @@ -4275,8 +4239,6 @@ int TimeTranslate(TransInfo *t, short mval[2]) recalcData(t); ED_area_headerprint(t->sa, str); - - viewRedrawForce(t); return 1; } @@ -4403,8 +4365,6 @@ int TimeSlide(TransInfo *t, short mval[2]) recalcData(t); ED_area_headerprint(t->sa, str); - - viewRedrawForce(t); return 1; } @@ -4519,8 +4479,6 @@ int TimeScale(TransInfo *t, short mval[2]) recalcData(t); ED_area_headerprint(t->sa, str); - - viewRedrawForce(t); return 1; } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index a2eb86100bb..75edfb78aba 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -344,7 +344,7 @@ void TFM_OT_transform(struct wmOperatorType *ot); void initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, struct wmEvent *event); void saveTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op); void transformEvent(TransInfo *t, struct wmEvent *event); -void transformApply(TransInfo *t); +void transformApply(struct bContext *C, TransInfo *t); int transformEnd(struct bContext *C, TransInfo *t); void setTransformViewMatrices(TransInfo *t); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 974c02c89e4..e197e0788f7 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1021,25 +1021,29 @@ static void createTransPose(bContext *C, TransInfo *t, Object *ob) static void createTransArmatureVerts(bContext *C, TransInfo *t) { - // TRANSFORM_FIX_ME -#if 0 EditBone *ebo; bArmature *arm= t->obedit->data; + ListBase *edbo = arm->edbo; TransData *td; float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3]; t->total = 0; - for (ebo=G.edbo.first;ebo;ebo=ebo->next) { - if(ebo->layer & arm->layer) { - if (t->mode==TFM_BONESIZE) { + for (ebo = edbo->first; ebo; ebo = ebo->next) + { + if(ebo->layer & arm->layer) + { + if (t->mode==TFM_BONESIZE) + { if (ebo->flag & BONE_SELECTED) t->total++; } - else if (t->mode==TFM_BONE_ROLL) { + else if (t->mode==TFM_BONE_ROLL) + { if (ebo->flag & BONE_SELECTED) t->total++; } - else { + else + { if (ebo->flag & BONE_TIPSEL) t->total++; if (ebo->flag & BONE_ROOTSEL) @@ -1055,13 +1059,15 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone"); - for (ebo=G.edbo.first;ebo;ebo=ebo->next){ - ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points + for (ebo = edbo->first; ebo; ebo = ebo->next) + { + ebo->oldlength = ebo->length; // length==0.0 on extrude, used for scaling radius of bone points if(ebo->layer & arm->layer) { - if (t->mode==TFM_BONE_ENVELOPE) { - - if (ebo->flag & BONE_ROOTSEL){ + if (t->mode==TFM_BONE_ENVELOPE) + { + if (ebo->flag & BONE_ROOTSEL) + { td->val= &ebo->rad_head; td->ival= *td->val; @@ -1077,7 +1083,8 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td++; } - if (ebo->flag & BONE_TIPSEL){ + if (ebo->flag & BONE_TIPSEL) + { td->val= &ebo->rad_tail; td->ival= *td->val; VECCOPY (td->center, ebo->tail); @@ -1094,14 +1101,17 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) } } - else if (t->mode==TFM_BONESIZE) { + else if (t->mode==TFM_BONESIZE) + { if (ebo->flag & BONE_SELECTED) { - if(arm->drawtype==ARM_ENVELOPE) { + if(arm->drawtype==ARM_ENVELOPE) + { td->loc= NULL; td->val= &ebo->dist; td->ival= ebo->dist; } - else { + else + { // abusive storage of scale in the loc pointer :) td->loc= &ebo->xwidth; VECCOPY (td->iloc, td->loc); @@ -1125,8 +1135,10 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td++; } } - else if (t->mode==TFM_BONE_ROLL) { - if (ebo->flag & BONE_SELECTED) { + else if (t->mode==TFM_BONE_ROLL) + { + if (ebo->flag & BONE_SELECTED) + { td->loc= NULL; td->val= &(ebo->roll); td->ival= ebo->roll; @@ -1140,8 +1152,10 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td++; } } - else { - if (ebo->flag & BONE_TIPSEL){ + else + { + if (ebo->flag & BONE_TIPSEL) + { VECCOPY (td->iloc, ebo->tail); VECCOPY (td->center, td->iloc); td->loc= ebo->tail; @@ -1166,7 +1180,8 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td++; } - if (ebo->flag & BONE_ROOTSEL){ + if (ebo->flag & BONE_ROOTSEL) + { VECCOPY (td->iloc, ebo->head); VECCOPY (td->center, td->iloc); td->loc= ebo->head; @@ -1191,7 +1206,6 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) } } } -#endif } /* ********************* meta elements ********* */ diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 8cc20454600..69d2e1c119e 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -421,30 +421,7 @@ void recalcData(TransInfo *t) } } else if (t->obedit) { - if (t->obedit->type == OB_MESH) { - if(t->spacetype==SPACE_IMAGE) { - flushTransUVs(t); - if (G.sima->flag & SI_LIVE_UNWRAP) - unwrap_lscm_live_re_solve(); - } else { - EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh - /* mirror modifier clipping? */ - if(t->state != TRANS_CANCEL) { - if ((G.qual & LR_CTRLKEY)==0) { - /* Only retopo if not snapping, Note, this is the only case of G.qual being used, but we have no T_SHIFT_MOD - Campbell */ - retopo_do_all(); - } - clipMirrorModifier(t, t->obedit); - } - if((t->options & CTX_NO_MIRROR) == 0 && (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR)) - editmesh_apply_to_mirror(t); - - DAG_object_flush_update(G.scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */ - - recalc_editnormals(em); - } - } - else if ELEM(t->obedit->type, OB_CURVE, OB_SURF) { + if ELEM(t->obedit->type, OB_CURVE, OB_SURF) { Nurb *nu= editNurb.first; DAG_object_flush_update(G.scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */ @@ -463,14 +440,68 @@ void recalcData(TransInfo *t) retopo_do_all(); } } - else if(t->obedit->type==OB_ARMATURE){ /* no recalc flag, does pose */ + else if(t->obedit->type==OB_LATTICE) { + DAG_object_flush_update(G.scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */ + + if(editLatt->flag & LT_OUTSIDE) outside_lattice(editLatt); + } + else { + DAG_object_flush_update(G.scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */ + } + } + else if( (t->flag & T_POSE) && t->poseobj) { + Object *ob= t->poseobj; + bArmature *arm= ob->data; + + /* old optimize trick... this enforces to bypass the depgraph */ + if (!(arm->flag & ARM_DELAYDEFORM)) { + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); /* sets recalc flags */ + } + else + where_is_pose(ob); + } + else if(G.f & G_PARTICLEEDIT) { + flushTransParticles(t); + } +#endif + if (t->spacetype==SPACE_NODE) { + flushTransNodes(t); + } + else if (t->obedit) { + if (t->obedit->type == OB_MESH) { + if(t->spacetype==SPACE_IMAGE) { + flushTransUVs(t); + /* TRANSFORM_FIX_ME */ +// if (G.sima->flag & SI_LIVE_UNWRAP) +// unwrap_lscm_live_re_solve(); + } else { + EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh; + /* mirror modifier clipping? */ + if(t->state != TRANS_CANCEL) { + /* TRANSFORM_FIX_ME */ +// if ((G.qual & LR_CTRLKEY)==0) { +// /* Only retopo if not snapping, Note, this is the only case of G.qual being used, but we have no T_SHIFT_MOD - Campbell */ +// retopo_do_all(); +// } + clipMirrorModifier(t, t->obedit); + } + if((t->options & CTX_NO_MIRROR) == 0 && (t->scene->toolsettings->editbutflag & B_MESH_X_MIRROR)) + editmesh_apply_to_mirror(t); + + DAG_object_flush_update(t->scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */ + + recalc_editnormals(em); + } + } + else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */ bArmature *arm= t->obedit->data; + ListBase *edbo = arm->edbo; EditBone *ebo; TransData *td = t->data; int i; /* Ensure all bones are correctly adjusted */ - for (ebo=G.edbo.first; ebo; ebo=ebo->next){ + for (ebo = edbo->first; ebo; ebo = ebo->next){ if ((ebo->flag & BONE_CONNECTED) && ebo->parent){ /* If this bone has a parent tip that has been moved */ @@ -531,67 +562,14 @@ void recalcData(TransInfo *t) Mat3MulVecfl(t->mat, up_axis); } - ebo->roll = rollBoneToVector(ebo, up_axis); + ebo->roll = ED_rollBoneToVector(ebo, up_axis); } } } if(arm->flag & ARM_MIRROR_EDIT) - transform_armature_mirror_update(); - - } - else if(t->obedit->type==OB_LATTICE) { - DAG_object_flush_update(G.scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */ + transform_armature_mirror_update(t->obedit); - if(editLatt->flag & LT_OUTSIDE) outside_lattice(editLatt); - } - else { - DAG_object_flush_update(G.scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */ - } - } - else if( (t->flag & T_POSE) && t->poseobj) { - Object *ob= t->poseobj; - bArmature *arm= ob->data; - - /* old optimize trick... this enforces to bypass the depgraph */ - if (!(arm->flag & ARM_DELAYDEFORM)) { - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); /* sets recalc flags */ - } - else - where_is_pose(ob); - } - else if(G.f & G_PARTICLEEDIT) { - flushTransParticles(t); - } -#endif - if (t->spacetype==SPACE_NODE) { - flushTransNodes(t); - } - else if (t->obedit) { - if (t->obedit->type == OB_MESH) { - if(t->spacetype==SPACE_IMAGE) { - flushTransUVs(t); - /* TRANSFORM_FIX_ME */ -// if (G.sima->flag & SI_LIVE_UNWRAP) -// unwrap_lscm_live_re_solve(); - } else { - EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh; - /* mirror modifier clipping? */ - if(t->state != TRANS_CANCEL) { - /* TRANSFORM_FIX_ME */ -// if ((G.qual & LR_CTRLKEY)==0) { -// /* Only retopo if not snapping, Note, this is the only case of G.qual being used, but we have no T_SHIFT_MOD - Campbell */ -// retopo_do_all(); -// } - clipMirrorModifier(t, t->obedit); - } - if((t->options & CTX_NO_MIRROR) == 0 && (t->scene->toolsettings->editbutflag & B_MESH_X_MIRROR)) - editmesh_apply_to_mirror(t); - - DAG_object_flush_update(t->scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */ - - recalc_editnormals(em); - } } } else { @@ -1026,10 +1004,10 @@ void calculateCenter(TransInfo *t) case V3D_ACTIVE: { /* set median, and if if if... do object center */ +#if 0 // TRANSFORM_FIX_ME EditSelection ese; /* EDIT MODE ACTIVE EDITMODE ELEMENT */ -#if 0 // TRANSFORM_FIX_ME if (t->obedit && t->obedit->type == OB_MESH && EM_get_actSelection(&ese)) { EM_editselection_center(t->center, &ese); calculateCenter2D(t); diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index e15fd3780ea..a810f66af06 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -70,7 +70,7 @@ static int transform_modal(bContext *C, wmOperator *op, wmEvent *event) transformEvent(t, event); - transformApply(t); + transformApply(C, t); exit_code = transformEnd(C, t); @@ -104,7 +104,7 @@ static int transform_exec(bContext *C, wmOperator *op) t->options |= CTX_AUTOCONFIRM; - transformApply(t); + transformApply(C, t); transformEnd(C, t); diff --git a/source/blender/makesdna/DNA_lattice_types.h b/source/blender/makesdna/DNA_lattice_types.h index 3f45a3c1fb0..a2748617f18 100644 --- a/source/blender/makesdna/DNA_lattice_types.h +++ b/source/blender/makesdna/DNA_lattice_types.h @@ -53,6 +53,10 @@ typedef struct Lattice { struct MDeformVert *dvert; + /* used while deforming, always free and NULL after use */ + float *latticedata; + float latmat[4][4]; + struct Lattice *editlatt; } Lattice; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 4ef2f32c914..85a8520bfd7 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -331,5 +331,11 @@ extern UserDef U; /* from blenkernel blender.c */ #define GP_PAINT_DOSMOOTH (1<<0) #define GP_PAINT_DOSIMPLIFY (1<<1) +/* theme drawtypes */ +#define TH_MINIMAL 0 +#define TH_ROUNDSHADED 1 +#define TH_ROUNDED 2 +#define TH_OLDSKOOL 3 +#define TH_SHADED 4 #endif diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index a563e2af210..5b1ffdd35f2 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -68,6 +68,8 @@ typedef struct wmWindowManager { ListBase reports; /* information and error reports */ + ListBase paintcursors; /* extra overlay cursors to draw, like circles */ + /* used keymaps, optionally/partially saved */ ListBase keymaps; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index abf6bac9786..f6a568d8e93 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -36,6 +36,8 @@ struct Main; extern BlenderRNA BLENDER_RNA; extern StructRNA RNA_Action; +extern StructRNA RNA_ActionChannel; +extern StructRNA RNA_ActionGroup; extern StructRNA RNA_Actuator; extern StructRNA RNA_ActuatorSensor; extern StructRNA RNA_AlwaysSensor; @@ -55,8 +57,8 @@ extern StructRNA RNA_BuildModifier; extern StructRNA RNA_Camera; extern StructRNA RNA_CastModifier; extern StructRNA RNA_CharInfo; -extern StructRNA RNA_ClothModifier; extern StructRNA RNA_ClothCollisionSettings; +extern StructRNA RNA_ClothModifier; extern StructRNA RNA_ClothSettings; extern StructRNA RNA_CollectionProperty; extern StructRNA RNA_CollisionModifier; @@ -118,7 +120,6 @@ extern StructRNA RNA_Lattice; extern StructRNA RNA_LatticeModifier; extern StructRNA RNA_LatticePoint; extern StructRNA RNA_Library; -extern StructRNA RNA_MappingTexture; extern StructRNA RNA_MCol; extern StructRNA RNA_MColLayer; extern StructRNA RNA_MFloatProperty; @@ -223,11 +224,30 @@ extern StructRNA RNA_TextBox; extern StructRNA RNA_TextLine; extern StructRNA RNA_TextMarker; extern StructRNA RNA_Texture; +extern StructRNA RNA_TextureSlot; +extern StructRNA RNA_Theme; +extern StructRNA RNA_ThemeActionEditor; +extern StructRNA RNA_ThemeAudioWindow; +extern StructRNA RNA_ThemeBoneColorSet; +extern StructRNA RNA_ThemeButtonsWindow; +extern StructRNA RNA_ThemeFileBrowser; +extern StructRNA RNA_ThemeImageEditor; +extern StructRNA RNA_ThemeIpoEditor; +extern StructRNA RNA_ThemeNLAEditor; +extern StructRNA RNA_ThemeNodeEditor; +extern StructRNA RNA_ThemeOutliner; +extern StructRNA RNA_ThemeSequenceEditor; +extern StructRNA RNA_ThemeTextEditor; +extern StructRNA RNA_ThemeTimeline; +extern StructRNA RNA_ThemeUserInterface; +extern StructRNA RNA_ThemeUserPreferences; +extern StructRNA RNA_ThemeView3D; extern StructRNA RNA_TouchSensor; extern StructRNA RNA_TransformSequence; extern StructRNA RNA_UVProjectModifier; extern StructRNA RNA_UnknownType; extern StructRNA RNA_UserPreferences; +extern StructRNA RNA_UserSolidLight; extern StructRNA RNA_VectorFont; extern StructRNA RNA_VertexGroup; extern StructRNA RNA_WaveModifier; @@ -250,8 +270,8 @@ extern StructRNA RNA_XorController; */ void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr); -void RNA_id_pointer_create(StructRNA *idtype, struct ID *id, PointerRNA *r_ptr); -void RNA_pointer_create(StructRNA *idtype, struct ID *id, StructRNA *type, void *data, PointerRNA *r_ptr); +void RNA_id_pointer_create(struct ID *id, PointerRNA *r_ptr); +void RNA_pointer_create(struct ID *id, StructRNA *type, void *data, PointerRNA *r_ptr); void RNA_blender_rna_pointer_create(PointerRNA *r_ptr); diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index 49cb09ff020..72891ddb06e 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -43,6 +43,7 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char * void RNA_def_struct_sdna(StructRNA *srna, const char *structname); void RNA_def_struct_sdna_from(StructRNA *srna, const char *structname, const char *propname); void RNA_def_struct_name_property(StructRNA *srna, PropertyRNA *prop); +void RNA_def_struct_parent(StructRNA *srna, StructRNA *parent); void RNA_def_struct_flag(StructRNA *srna, int flag); void RNA_def_struct_refine_func(StructRNA *srna, const char *refine); void RNA_def_struct_identifier(StructRNA *srna, const char *identifier); diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index e4aceb0a81b..fc98a0ad594 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -132,7 +132,8 @@ typedef enum StructFlag { STRUCT_ID = 1, /* internal flags */ - STRUCT_RUNTIME = 2 + STRUCT_RUNTIME = 2, + STRUCT_GENERATED = 4 } StructFlag; typedef struct StructRNA StructRNA; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 4a537d031a0..5eaef1ab246 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -24,8 +24,7 @@ # # ***** END GPL LICENSE BLOCK ***** -SET(SRC - makesrna.c +SET(DEFSRC rna_action.c rna_actuator.c rna_armature.c @@ -36,7 +35,6 @@ SET(SRC rna_constraint.c rna_controller.c rna_curve.c - rna_define.c rna_fluidsim.c rna_group.c rna_ID.c @@ -70,7 +68,58 @@ SET(SRC rna_userdef.c rna_vfont.c rna_wm.c - rna_world.c + rna_world.c) + +SET(GENSRC + rna_action_gen.c + rna_actuator_gen.c + rna_armature_gen.c + rna_brush_gen.c + rna_camera_gen.c + rna_cloth_gen.c + rna_color_gen.c + rna_constraint_gen.c + rna_controller_gen.c + rna_curve_gen.c + rna_fluidsim_gen.c + rna_group_gen.c + rna_ID_gen.c + rna_image_gen.c + rna_ipo_gen.c + rna_key_gen.c + rna_lamp_gen.c + rna_lattice_gen.c + rna_main_gen.c + rna_material_gen.c + rna_mesh_gen.c + rna_meta_gen.c + rna_modifier_gen.c + rna_nodetree_gen.c + rna_object_gen.c + rna_object_force_gen.c + rna_packedfile_gen.c + rna_particle_gen.c + rna_pose_gen.c + rna_property_gen.c + rna_radio_gen.c + rna_rna_gen.c + rna_scene_gen.c + rna_screen_gen.c + rna_scriptlink_gen.c + rna_sensor_gen.c + rna_sequence_gen.c + rna_sound_gen.c + rna_text_gen.c + rna_texture_gen.c + rna_userdef_gen.c + rna_vfont_gen.c + rna_wm_gen.c + rna_world_gen.c) + +SET(SRC + makesrna.c + rna_define.c + ${DEFSRC} ../../../../intern/guardedalloc/intern/mallocn.c ../../../../intern/guardedalloc/intern/mmap_win.c) @@ -81,15 +130,16 @@ FILE(GLOB INC_FILES ../*.h ../../makesdna/*.h) ADD_EXECUTABLE(makesrna ${SRC} ${INC_FILES}) TARGET_LINK_LIBRARIES(makesrna bf_dna) -# Output rna.c +# Output rna_*_gen.c ADD_CUSTOM_COMMAND( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/rna.c - COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/makesrna ${CMAKE_CURRENT_BINARY_DIR}/rna.c ${CMAKE_SOURCE_DIR}/source/blender/makesrna/ + OUTPUT ${GENSRC} + COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/makesrna ${CMAKE_CURRENT_BINARY_DIR}/ ${CMAKE_SOURCE_DIR}/source/blender/makesrna/ DEPENDS makesrna ) # Build bf_rna -SET(SRC rna_access.c rna_dependency.c rna.c) +SET(SRC rna_access.c rna_dependency.c ${GENSRC}) BLENDERLIB(bf_rna "${SRC}" "${INC}") MESSAGE(STATUS "Configuring makesrna") + diff --git a/source/blender/makesrna/intern/Makefile b/source/blender/makesrna/intern/Makefile index e844d74decf..aad4acdbf38 100644 --- a/source/blender/makesrna/intern/Makefile +++ b/source/blender/makesrna/intern/Makefile @@ -24,7 +24,17 @@ LIBNAME = rna DIR = $(OCGDIR)/blender/makesrna -CSRCS = RNA.c $(wildcard rna_*.c) + +ALLRNA = $(wildcard rna_*.c) +DEFRNA = $(filter-out %rna_define.c, $(filter-out %rna_dependency.c, $(filter-out %rna_access.c, $(ALLRNA)))) + +GENSRCS = $(patsubst rna_%.c, rna_%_gen.c, $(DEFRNA)) +GENTARGET = $(patsubst %.c, $(DIR)/$(DEBUG_DIR)%.c, $(GENSRCS)) + +MAKESRCS = $(DEFRNA) makesrna.c rna_define.c +MAKEOBJS = $(patsubst %.c, $(DIR)/$(DEBUG_DIR)%.o, $(MAKESRCS)) + +CSRCS = $(GENSRCS) rna_access.c rna_dependency.c include nan_compile.mk @@ -53,8 +63,8 @@ ifeq ($(OS),windows) endif clean:: - @$(RM) $(DIR)/makesrna* $(DIR)/RNA.c - @$(RM) $(DIR)/debug/makesrna* $(DIR)/debug/RNA.c + @$(RM) $(DIR)/makesrna* $(DIR)/rna* + @$(RM) $(DIR)/debug/makesrna* $(DIR)/debug/rna* # TODO include right .mk for ldflags @@ -62,18 +72,19 @@ clean:: # is done quite intentionally. If there is a bug in that lib, it needs # to be fixed by the module maintainer. -RNAOBJS = $(filter-out %rna_dependency.o, $(filter-out %rna_access.o, $(filter-out %RNA.o, $(OBJS)))) - -$(DIR)/$(DEBUG_DIR)makesrna: $(RNAOBJS) $(DIR)/$(DEBUG_DIR)makesrna.o $(OCGDIR)/blender/makesdna/$(DEBUG_DIR)libdna.a $(NAN_GUARDEDALLOC)/lib/libguardedalloc.a +$(DIR)/$(DEBUG_DIR)makesrna: $(MAKEOBJS) $(OCGDIR)/blender/makesdna/$(DEBUG_DIR)libdna.a $(NAN_GUARDEDALLOC)/lib/libguardedalloc.a $(CC) $(LDFLAGS) -o $@ $(WINLIBS) $^ -$(DIR)/$(DEBUG_DIR)RNA.c: $(DIR)/$(DEBUG_DIR)makesrna +$(DIR)/$(DEBUG_DIR)rna_phony_gen.c: $(DIR)/$(DEBUG_DIR)makesrna ifeq ($(OS),windows) $(SRCHOME)/tools/cygwin/cl_wrapper.pl - $(DIR)/$(DEBUG_DIR)makesrna \ - $(DIR)/$(DEBUG_DIR)RNA.c + $(DIR)/$(DEBUG_DIR) else - $(DIR)/$(DEBUG_DIR)makesrna $(DIR)/$(DEBUG_DIR)RNA.c + $(DIR)/$(DEBUG_DIR)makesrna $(DIR)/$(DEBUG_DIR) endif + @touch $@ + +$(GENTARGET): $(DIR)/$(DEBUG_DIR)rna_phony_gen.c $(DIR)/$(DEBUG_DIR)makesrna.o: makesrna.c $(wildcard rna_*.c) $(CC) -c $(CFLAGS) $(CPPFLAGS) makesrna.c -o $@ diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index af0d67a0b9e..661f9b91a34 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -14,6 +14,12 @@ source_files = env.Glob('*.c') source_files.remove('rna_access.c') source_files.remove('rna_dependency.c') +generated_files = source_files[:] +generated_files.remove('rna_define.c') +generated_files.remove('makesrna.c') + +generated_files = [filename[:-2] + '_gen.c' for filename in generated_files] + makesrna_tool = env.Clone() rna = env.Clone() makesrna_tool.Append(CCFLAGS = '-DBASE_HEADER="\\"source/blender/makesrna/\\"" ') @@ -59,11 +65,19 @@ else: makesrna = makesrna_tool.Program (target = targetpath, source = source_files, LIBS=['bf_guardedalloc', 'bf_dna']) rna_dict = rna.Dictionary() -rna.Depends ('rna.c', makesrna) +rna.Depends (generated_files, makesrna) + +# this seems bad, how to retrieve it from scons? +build_dir = root_build_dir + '/source/blender/makesrna/intern/' + if env['OURPLATFORM'] != 'linuxcross': - rna.Command ('rna.c', '', root_build_dir+os.sep+"makesrna $TARGET") + rna.Command (generated_files, '', root_build_dir+os.sep+"makesrna " + build_dir) else: - rna.Command ('rna.c', '', root_build_dir+os.sep+"makesrna.exe $TARGET") -obj = ['intern/rna.c', 'intern/rna_access.c', 'intern/rna_dependency.c'] + rna.Command (generated_files, '', root_build_dir+os.sep+"makesrna.exe " + build_dir) + +obj = ['intern/rna_access.c', 'intern/rna_dependency.c'] +for generated_file in generated_files: + obj += ['intern/' + generated_file] + Return ('obj') diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index b0af27bde9a..32024ceefdf 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -167,6 +167,15 @@ static int rna_enum_bitmask(PropertyRNA *prop) return mask; } +static int rna_color_quantize(PropertyRNA *prop, PropertyDefRNA *dp) +{ + if(prop->type == PROP_FLOAT && prop->subtype == PROP_COLOR) + if(strcmp(dp->dnatype, "float") != 0 && strcmp(dp->dnatype, "double") != 0) + return 1; + + return 0; +} + static char *rna_def_property_get_func(FILE *f, StructRNA *srna, PropertyRNA *prop, PropertyDefRNA *dp) { char *func; @@ -212,6 +221,8 @@ static char *rna_def_property_get_func(FILE *f, StructRNA *srna, PropertyRNA *pr else { if(prop->type == PROP_BOOLEAN && dp->booleanbit) fprintf(f, " return (%s(data->%s[index] & %d) != 0);\n", (dp->booleannegative)? "!": "", dp->dnaname, dp->booleanbit); + else if(rna_color_quantize(prop, dp)) + fprintf(f, " return (%s)(data->%s[index]/255.0f);\n", rna_type_type(prop), dp->dnaname); else fprintf(f, " return (%s)%s(data->%s[index]);\n", rna_type_type(prop), (dp->booleannegative)? "!": "", dp->dnaname); } @@ -326,6 +337,9 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr fprintf(f, " if(%svalue) data->%s[index] |= %d;\n", (dp->booleannegative)? "!": "", dp->dnaname, dp->booleanbit); fprintf(f, " else data->%s[index] &= ~%d;\n", dp->dnaname, dp->booleanbit); } + else if(rna_color_quantize(prop, dp)) { + fprintf(f, " data->%s[index]= FTOCHAR(value);\n", dp->dnaname); + } else { rna_clamp_value(f, prop); fprintf(f, " data->%s[index]= %svalue;\n", dp->dnaname, (dp->booleannegative)? "!": ""); @@ -584,18 +598,6 @@ static void rna_auto_types() } } -static void rna_auto_functions(FILE *f) -{ - StructDefRNA *ds; - PropertyDefRNA *dp; - - fprintf(f, "/* Autogenerated Functions */\n\n"); - - for(ds=DefRNA.structs.first; ds; ds=ds->next) - for(dp=ds->properties.first; dp; dp=dp->next) - rna_def_property_funcs(f, dp); -} - static void rna_sort(BlenderRNA *brna) { StructRNA *srna; @@ -654,8 +656,13 @@ static void rna_generate_prototypes(BlenderRNA *brna, FILE *f) StructRNA *srna; for(srna=brna->structs.first; srna; srna=srna->next) - fprintf(f, "StructRNA RNA_%s;\n", srna->identifier); + fprintf(f, "extern StructRNA RNA_%s;\n", srna->identifier); fprintf(f, "\n"); +} + +static void rna_generate_blender(BlenderRNA *brna, FILE *f) +{ + StructRNA *srna; fprintf(f, "BlenderRNA BLENDER_RNA = {"); @@ -876,6 +883,9 @@ static void rna_generate_struct(BlenderRNA *brna, StructRNA *srna, FILE *f) if(srna->from) fprintf(f, "\t&RNA_%s,\n", (char*)srna->from); else fprintf(f, "\tNULL,\n"); + if(srna->parent) fprintf(f, "\t&RNA_%s,\n", (char*)srna->parent); + else fprintf(f, "\tNULL,\n"); + fprintf(f, "\t%s,\n", rna_function_string(srna->refine)); prop= srna->properties.first; @@ -943,18 +953,15 @@ RNAProcessItem PROCESS_ITEMS[]= { {"rna_world.c", RNA_def_world}, {NULL, NULL}}; -static int rna_preprocess(char *basedirectory, FILE *f) +static void rna_generate(BlenderRNA *brna, char *basedirectory, FILE *f, char *filename) { - BlenderRNA *brna; - StructRNA *srna; - int i, status; + StructDefRNA *ds; + PropertyDefRNA *dp; fprintf(f, "\n/* Automatically generated struct definitions for the Data API.\n" " Do not edit manually, changes will be overwritten */\n\n" "#define RNA_RUNTIME\n\n"); - brna= RNA_create(); - fprintf(f, "#include <float.h>\n"); fprintf(f, "#include <limits.h>\n"); fprintf(f, "#include <string.h>\n\n"); @@ -967,29 +974,89 @@ static int rna_preprocess(char *basedirectory, FILE *f) fprintf(f, "#include \"RNA_types.h\"\n"); fprintf(f, "#include \"rna_internal.h\"\n\n"); - /* this is ugly, but we cannot have c files compiled for both - * makesrna and blender with some build systems at the moment */ - fprintf(f, "#include \"rna_define.c\"\n\n"); + rna_generate_prototypes(brna, f); + + fprintf(f, "#include \"%s\"\n\n", filename); + + fprintf(f, "/* Autogenerated Functions */\n\n"); + + for(ds=DefRNA.structs.first; ds; ds=ds->next) + if(!filename || ds->filename == filename) + for(dp=ds->properties.first; dp; dp=dp->next) + rna_def_property_funcs(f, dp); - for(i=0; PROCESS_ITEMS[i].filename; i++) - if(PROCESS_ITEMS[i].define) + for(ds=DefRNA.structs.first; ds; ds=ds->next) + if(!filename || ds->filename == filename) + rna_generate_struct(brna, ds->srna, f); + + if(strcmp(filename, "rna_ID.c") == 0) { + /* this is ugly, but we cannot have c files compiled for both + * makesrna and blender with some build systems at the moment */ + fprintf(f, "#include \"rna_define.c\"\n\n"); + + rna_generate_blender(brna, f); + } +} + +static void make_bad_file(char *file) +{ + FILE *fp= fopen(file, "w"); + fprintf(fp, "ERROR! Cannot make correct RNA file, STUPID!\n"); + fclose(fp); +} + +static int rna_preprocess(char *basedirectory, char *outfile) +{ + BlenderRNA *brna; + StructDefRNA *ds; + FILE *file; + char deffile[4096]; + int i, status, len; + + /* define rna */ + brna= RNA_create(); + + for(i=0; PROCESS_ITEMS[i].filename; i++) { + if(PROCESS_ITEMS[i].define) { PROCESS_ITEMS[i].define(brna); + for(ds=DefRNA.structs.first; ds; ds=ds->next) + if(!ds->filename) + ds->filename= PROCESS_ITEMS[i].filename; + } + } + rna_sort(brna); rna_auto_types(); - - rna_generate_prototypes(brna, f); - for(i=0; PROCESS_ITEMS[i].filename; i++) - fprintf(f, "#include \"%s\"\n", PROCESS_ITEMS[i].filename); - fprintf(f, "\n"); + status= (DefRNA.error != 0); - rna_auto_functions(f); + len= strlen(outfile); - for(srna=brna->structs.first; srna; srna=srna->next) - rna_generate_struct(brna, srna, f); - - status= DefRNA.error; + for(i=0; PROCESS_ITEMS[i].filename; i++) { + strcpy(deffile, outfile); + strcat(deffile, PROCESS_ITEMS[i].filename); + deffile[strlen(deffile)-2] = '\0'; + strcat(deffile, "_gen.c"); + + if(status) { + make_bad_file(deffile); + } + else { + file = fopen(deffile, "w"); + + if(!file) { + printf ("Unable to open file: %s\n", deffile); + status = 1; + } + else { + rna_generate(brna, basedirectory, file, PROCESS_ITEMS[i].filename); + fclose(file); + + status= (DefRNA.error != 0); + } + } + } RNA_define_free(brna); RNA_free(brna); @@ -997,52 +1064,29 @@ static int rna_preprocess(char *basedirectory, FILE *f) return status; } -static void make_bad_file(char *file) -{ - FILE *fp= fopen(file, "w"); - fprintf(fp, "ERROR! Cannot make correct RNA.c file, STUPID!\n"); - fclose(fp); -} - #ifndef BASE_HEADER #define BASE_HEADER "../" #endif int main(int argc, char **argv) { - FILE *file; int totblock, return_status = 0; if (argc!=2 && argc!=3) { - printf("Usage: %s outfile.c [base directory]\n", argv[0]); + printf("Usage: %s outdirectory/ [base directory]\n", argv[0]); return_status = 1; } else { - file = fopen(argv[1], "w"); - - if (!file) { - printf ("Unable to open file: %s\n", argv[1]); - return_status = 1; - } - else { - char baseDirectory[256]; - - printf("Running makesrna, program versions %s\n", RNA_VERSION_DATE); + char baseDirectory[256]; - if (argc==3) - strcpy(baseDirectory, argv[2]); - else - strcpy(baseDirectory, BASE_HEADER); + printf("Running makesrna, program versions %s\n", RNA_VERSION_DATE); - return_status= (rna_preprocess(baseDirectory, file)); - fclose(file); + if (argc==3) + strcpy(baseDirectory, argv[2]); + else + strcpy(baseDirectory, BASE_HEADER); - if(return_status) { - /* error */ - make_bad_file(argv[1]); - return_status = 1; - } - } + return_status= rna_preprocess(baseDirectory, argv[1]); } totblock= MEM_get_memory_blocks_in_use(); diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index bb7fe7be526..7ea2952d9fc 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -35,25 +35,25 @@ #include "BKE_idprop.h" /* name functions that ignore the first two ID characters */ -static void rna_ID_name_get(PointerRNA *ptr, char *value) +void rna_ID_name_get(PointerRNA *ptr, char *value) { ID *id= (ID*)ptr->data; BLI_strncpy(value, id->name+2, sizeof(id->name)-2); } -static int rna_ID_name_length(PointerRNA *ptr) +int rna_ID_name_length(PointerRNA *ptr) { ID *id= (ID*)ptr->data; return strlen(id->name+2); } -static void rna_ID_name_set(PointerRNA *ptr, const char *value) +void rna_ID_name_set(PointerRNA *ptr, const char *value) { ID *id= (ID*)ptr->data; BLI_strncpy(id->name+2, value, sizeof(id->name)-2); } -static StructRNA *rna_ID_refine(PointerRNA *ptr) +StructRNA *rna_ID_refine(PointerRNA *ptr) { ID *id= (ID*)ptr->data; @@ -87,7 +87,7 @@ static StructRNA *rna_ID_refine(PointerRNA *ptr) } } -static void rna_ID_fake_user_set(PointerRNA *ptr, int value) +void rna_ID_fake_user_set(PointerRNA *ptr, int value) { ID *id= (ID*)ptr->data; diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 55d3cde4af7..a56980c96b2 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -61,16 +61,34 @@ void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr) r_ptr->data= main; } -void RNA_id_pointer_create(StructRNA *idtype, ID *id, PointerRNA *r_ptr) +void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr) { + PointerRNA tmp; + StructRNA *idtype= NULL; + + if(id) { + memset(&tmp, 0, sizeof(tmp)); + tmp.data= id; + idtype= rna_ID_refine(&tmp); + } + r_ptr->id.type= idtype; r_ptr->id.data= id; r_ptr->type= idtype; r_ptr->data= id; } -void RNA_pointer_create(StructRNA *idtype, ID *id, StructRNA *type, void *data, PointerRNA *r_ptr) +void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr) { + PointerRNA tmp; + StructRNA *idtype= NULL; + + if(id) { + memset(&tmp, 0, sizeof(tmp)); + tmp.data= id; + idtype= rna_ID_refine(&tmp); + } + r_ptr->id.type= idtype; r_ptr->id.data= id; r_ptr->type= type; diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index b412d5f073b..84c6af0a509 100755 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -157,39 +157,10 @@ void RNA_def_action(BlenderRNA *brna) RNA_def_property_struct_type(prop, "ActionGroup"); RNA_def_property_ui_text(prop, "Action Groups", "Convenient groupings of Action Channels."); - prop= RNA_def_property(srna, "timeline_markers", PROP_COLLECTION, PROP_NONE); + prop= RNA_def_property(srna, "pose_markers", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "markers", NULL); RNA_def_property_struct_type(prop, "UnknownType"); /* implement when timeline rna is wrapped */ - RNA_def_property_ui_text(prop, "Timeline Markers", "Markers specific to this Action, for labeling poses."); - - prop= RNA_def_property(srna, "action_show_sliders", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SLIDERS); - RNA_def_property_ui_text(prop, "Show Sliders", "Show Shape Key sliders."); - - prop= RNA_def_property(srna, "action_time_units", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_DRAWTIME); - RNA_def_property_ui_text(prop, "Time Units", "Show seconds or frames in the timeline."); - - prop= RNA_def_property(srna, "action_show_all", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_NOHIDE); - RNA_def_property_ui_text(prop, "Show All", "Show all channels regardless of hidden status."); - - prop= RNA_def_property(srna, "action_kill_overlapping_keys", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_NOTRANSKEYCULL); - RNA_def_property_ui_text(prop, "Kill Overlapping Keys", "Remove overlapping keys after a transform."); - - prop= RNA_def_property(srna, "action_key_cull_to_view", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_HORIZOPTIMISEON); - RNA_def_property_ui_text(prop, "Cull Keys to View", "Only consider keys that are within the view."); - - prop= RNA_def_property(srna, "action_group_colors", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_NODRAWGCOLORS); - RNA_def_property_ui_text(prop, "Group Color", "Use custom color grouping and instead of default color scheme."); - - prop= RNA_def_property(srna, "action_current_frame_number", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_NODRAWCFRANUM); - RNA_def_property_ui_text(prop, "Current Frame Number", "Draw the frame number beside the current frame indicator."); - + RNA_def_property_ui_text(prop, "Pose Markers", "Markers specific to this Action, for labeling poses."); } #endif diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 761e2b89a62..6e32bd7ac44 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -84,7 +84,7 @@ void rna_def_constraint_basedata(BlenderRNA *brna) /* data */ srna= RNA_def_struct(brna, "Constraint", NULL ); RNA_def_struct_ui_text(srna, "Constraint", "alter the transformation of 'Objects' or 'Bones' from a number of predefined constraints"); - //RNA_def_struct_refine_func(srna, "rna_Constraint_refine"); // XXX or should this go down below with the data? + RNA_def_struct_refine_func(srna, "rna_Constraint_refine"); RNA_def_struct_sdna(srna, "bConstraint"); /* strings */ diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 8623987bfc9..36b62f5030b 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -516,6 +516,15 @@ void RNA_def_struct_name_property(struct StructRNA *srna, struct PropertyRNA *pr srna->nameproperty= prop; } +void RNA_def_struct_parent(StructRNA *srna, StructRNA *parent) +{ + + if(DefRNA.preprocess) + srna->parent= (StructRNA*)parent->identifier; + else + srna->parent= parent; +} + void RNA_def_struct_flag(StructRNA *srna, int flag) { srna->flag= flag; diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index cc8d9b6ac04..32c545131ba 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -64,6 +64,7 @@ typedef struct StructDefRNA { struct StructDefRNA *next, *prev; struct StructRNA *srna; + const char *filename; const char *dnaname; @@ -142,6 +143,12 @@ void RNA_def_world(struct BlenderRNA *brna); void rna_def_ipo_common(struct StructRNA *srna); void rna_def_texmat_common(struct StructRNA *srna, const char *texspace_editable); +void rna_ID_name_get(struct PointerRNA *ptr, char *value); +int rna_ID_name_length(struct PointerRNA *ptr); +void rna_ID_name_set(struct PointerRNA *ptr, const char *value); +struct StructRNA *rna_ID_refine(struct PointerRNA *ptr); +void rna_ID_fake_user_set(struct PointerRNA *ptr, int value); + void rna_object_vgroup_name_index_get(struct PointerRNA *ptr, char *value, int index); int rna_object_vgroup_name_index_length(struct PointerRNA *ptr, int index); void rna_object_vgroup_name_index_set(struct PointerRNA *ptr, const char *value, short *index); diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index 89b0503239b..45b122b2ae5 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -205,6 +205,8 @@ typedef struct CollectionPropertyRNA { struct StructRNA *structtype; } CollectionPropertyRNA; + +/* changes to this struct require updating rna_generate_struct in makesrna.c */ struct StructRNA { struct StructRNA *next, *prev; @@ -227,6 +229,12 @@ struct StructRNA { /* struct this is derivedfrom */ struct StructRNA *from; + /* only use for nested structs, where both the parent and child access + * the same C Struct but nesting is used for grouping properties. + * The parent property is used so we know NULL checks are not needed, + * and that this struct will never exist without its parent */ + struct StructRNA *parent; + /* function to give the more specific type */ StructRefineFunc refine; diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c index e48a462b69a..6610cf895b4 100644 --- a/source/blender/makesrna/intern/rna_lattice.c +++ b/source/blender/makesrna/intern/rna_lattice.c @@ -29,6 +29,7 @@ #include "rna_internal.h" +#include "DNA_curve_types.h" #include "DNA_key_types.h" #include "DNA_lattice_types.h" #include "DNA_meshdata_types.h" diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 20bac170554..6ace02710b7 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -168,6 +168,7 @@ static void rna_def_material_raymirror(BlenderRNA *brna, StructRNA *parent) srna= RNA_def_struct(brna, "MaterialRaytraceMirror", NULL); RNA_def_struct_sdna(srna, "Material"); + RNA_def_struct_parent(srna, parent); RNA_def_struct_ui_text(srna, "Raytrace Mirror", ""); prop= RNA_def_property(parent, "raytrace_mirror", PROP_POINTER, PROP_NONE); @@ -248,6 +249,7 @@ static void rna_def_material_raytra(BlenderRNA *brna, StructRNA *parent) srna= RNA_def_struct(brna, "MaterialRaytraceTransparency", NULL); RNA_def_struct_sdna(srna, "Material"); + RNA_def_struct_parent(srna, parent); RNA_def_struct_ui_text(srna, "Raytrace Transparency", ""); prop= RNA_def_property(parent, "raytrace_transparency", PROP_POINTER, PROP_NONE); @@ -334,6 +336,7 @@ static void rna_def_material_halo(BlenderRNA *brna, StructRNA *parent) srna= RNA_def_struct(brna, "MaterialHalo", NULL); RNA_def_struct_sdna(srna, "Material"); + RNA_def_struct_parent(srna, parent); RNA_def_struct_ui_text(srna, "Halo", ""); prop= RNA_def_property(parent, "halo", PROP_POINTER, PROP_NONE); @@ -472,6 +475,7 @@ static void rna_def_material_sss(BlenderRNA *brna, StructRNA *parent) srna= RNA_def_struct(brna, "MaterialSubsurfaceScattering", NULL); RNA_def_struct_sdna(srna, "Material"); + RNA_def_struct_parent(srna, parent); RNA_def_struct_ui_text(srna, "Subsurface Scattering", ""); prop= RNA_def_property(parent, "subsurface_scattering", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c index 043f9932622..7da77897921 100644 --- a/source/blender/makesrna/intern/rna_meta.c +++ b/source/blender/makesrna/intern/rna_meta.c @@ -29,6 +29,7 @@ #include "rna_internal.h" +#include "DNA_mesh_types.h" #include "DNA_meta_types.h" #ifdef RNA_RUNTIME diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index b079262d549..a5ba31e2280 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -33,6 +33,7 @@ #include "DNA_armature_types.h" #include "DNA_modifier_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "BKE_bmesh.h" /* For BevelModifierData */ @@ -284,7 +285,6 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna) static void rna_def_modifier_multires(BlenderRNA *brna) { StructRNA *srna; - PropertyRNA *prop; srna= RNA_def_struct(brna, "MultiresModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Multires Modifier", ""); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 3e4474dba8e..0ae76a20972 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -29,6 +29,8 @@ #include "rna_internal.h" +#include "DNA_customdata_types.h" +#include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_property_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index aead0ca54c0..60faf0c8e07 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -24,6 +24,9 @@ #include <stdlib.h> +#include "DNA_ID.h" + +#include "RNA_access.h" #include "RNA_define.h" #include "RNA_types.h" @@ -66,6 +69,11 @@ static void *rna_Struct_base_get(PointerRNA *ptr) return ((StructRNA*)ptr->data)->from; } +static void *rna_Struct_parent_get(PointerRNA *ptr) +{ + return ((StructRNA*)ptr->data)->parent; +} + static void *rna_Struct_name_property_get(PointerRNA *ptr) { return ((StructRNA*)ptr->data)->nameproperty; @@ -427,6 +435,12 @@ static void rna_def_struct(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, "rna_Struct_base_get", NULL, NULL); RNA_def_property_ui_text(prop, "Base", "Struct definition this is derived from."); + prop= RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NOT_EDITABLE); + RNA_def_property_struct_type(prop, "Struct"); + RNA_def_property_pointer_funcs(prop, "rna_Struct_parent_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Parent", "Parent struct, used only for nested structs."); + prop= RNA_def_property(srna, "name_property", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NOT_EDITABLE); RNA_def_property_struct_type(prop, "StringProperty"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 353db5248d9..f87636bf4e1 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -35,6 +35,7 @@ #ifdef RNA_RUNTIME +#include "BKE_context.h" #include "BKE_global.h" void *rna_Scene_objects_get(CollectionPropertyIterator *iter) diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c index 77cff4f8d15..af04b396584 100644 --- a/source/blender/makesrna/intern/rna_text.c +++ b/source/blender/makesrna/intern/rna_text.c @@ -25,6 +25,8 @@ #include <stdlib.h> #include <limits.h> +#include "MEM_guardedalloc.h" + #include "BKE_text.h" #include "RNA_define.h" @@ -36,18 +38,6 @@ #ifdef RNA_RUNTIME -static float rna_TextMarker_color_get(PointerRNA *ptr, int index) -{ - TextMarker *marker= (TextMarker*)ptr->data; - return marker->color[index]/255.0f; -} - -static void rna_TextMarker_color_set(PointerRNA *ptr, int index, float value) -{ - TextMarker *marker= (TextMarker*)ptr->data; - marker->color[index] = (char)(CLAMPIS(value*255.0f, 0, 255)); -} - static void rna_Text_filename_get(PointerRNA *ptr, char *value) { Text *text= (Text*)ptr->data; @@ -163,7 +153,6 @@ static void rna_def_text_marker(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Edit All", "Edit all markers of the same group as one."); prop= RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); - RNA_def_property_float_funcs(prop, "rna_TextMarker_color_get", "rna_TextMarker_color_set", NULL); RNA_def_property_ui_text(prop, "Color", "Color to display the marker with."); } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index a26c3e566cd..54bc5d21cd9 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -30,28 +30,1671 @@ #include "rna_internal.h" #include "DNA_userdef_types.h" +#include "DNA_ipo_types.h" #ifdef RNA_RUNTIME +static void rna_userdef_lmb_select_set(struct PointerRNA *ptr,int value) +{ + UserDef *userdef = (UserDef*)ptr->data; + + if(value) { + userdef->flag |= USER_LMOUSESELECT; + userdef->flag &= ~USER_TWOBUTTONMOUSE; + } + else + userdef->flag &= ~USER_LMOUSESELECT; +} + +static void rna_userdef_rmb_select_set(struct PointerRNA *ptr,int value) +{ + rna_userdef_lmb_select_set(ptr, !value); +} + +static void rna_userdef_emulate_set(struct PointerRNA *ptr,int value) +{ + UserDef *userdef = (UserDef*)ptr->data; + + if(userdef->flag & USER_LMOUSESELECT) + userdef->flag &= ~USER_TWOBUTTONMOUSE; + else + userdef->flag ^= USER_TWOBUTTONMOUSE; +} + +static int rna_userdef_autokeymode_get(struct PointerRNA *ptr) +{ + UserDef *userdef = (UserDef*)ptr->data; + short retval = userdef->autokey_mode; + + if(!(userdef->autokey_mode & AUTOKEY_ON)) + retval |= AUTOKEY_ON; + + return retval; +} + +static void rna_userdef_autokeymode_set(struct PointerRNA *ptr,int value) +{ + UserDef *userdef = (UserDef*)ptr->data; + + if(value == AUTOKEY_MODE_NORMAL) { + userdef->autokey_mode |= (AUTOKEY_MODE_NORMAL - AUTOKEY_ON); + userdef->autokey_mode &= ~(AUTOKEY_MODE_EDITKEYS - AUTOKEY_ON); + } + else if(value == AUTOKEY_MODE_EDITKEYS) { + userdef->autokey_mode |= (AUTOKEY_MODE_EDITKEYS - AUTOKEY_ON); + userdef->autokey_mode &= ~(AUTOKEY_MODE_NORMAL - AUTOKEY_ON); + } +} + #else -static void rna_def_userdef(BlenderRNA *brna) +static void rna_def_userdef_theme_ui(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - srna= RNA_def_struct(brna, "UserPreferences", NULL); - RNA_def_struct_sdna(srna, "UserDef"); - RNA_def_struct_ui_text(srna, "User Preferences", ""); + static EnumPropertyItem button_theme_styles[] = { + {TH_MINIMAL, "MINIMAL", "Minimal", ""}, + {TH_SHADED, "SHADED", "Shaded", ""}, + {TH_ROUNDED, "ROUNDED", "Rounded", ""}, + {TH_ROUNDSHADED, "ROUNDSHADED", "Round Shaded", ""}, + {TH_OLDSKOOL, "OLDSKOOL", "Old Skool", ""}, + {0, NULL, NULL, NULL}}; + + srna= RNA_def_struct(brna, "ThemeUserInterface", NULL); + RNA_def_struct_sdna(srna, "ThemeUI"); + RNA_def_struct_ui_text(srna, "Theme User Interface", "Theme settings for user interface elements."); + + prop= RNA_def_property(srna, "outline", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Outline", ""); + + prop= RNA_def_property(srna, "neutral", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Neutral", ""); + + prop= RNA_def_property(srna, "action", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Action", ""); + + prop= RNA_def_property(srna, "setting", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Setting", ""); + + prop= RNA_def_property(srna, "special_setting_1", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "setting1"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Special Setting 1", ""); + + prop= RNA_def_property(srna, "special_setting_2", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "setting2"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Special Setting 2", ""); + + prop= RNA_def_property(srna, "number_input", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "num"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Number Input", ""); + + prop= RNA_def_property(srna, "text_field", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "textfield"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Text Field", ""); + + prop= RNA_def_property(srna, "textfield_highlight", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "textfield_hi"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Text Field Highlight", ""); + + prop= RNA_def_property(srna, "popup", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Popup", ""); + + prop= RNA_def_property(srna, "text", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Text", ""); + + prop= RNA_def_property(srna, "text_highlight", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "text_hi"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Text highlight", ""); + + prop= RNA_def_property(srna, "menu_background", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "menu_back"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Menu Background", ""); + + prop= RNA_def_property(srna, "menu_item", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Menu Item", ""); + + prop= RNA_def_property(srna, "menu_highlight", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "menu_hilite"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Menu Highlight", ""); + + prop= RNA_def_property(srna, "menu_text", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Menu Text", ""); + + prop= RNA_def_property(srna, "menu_text_highlight", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "menu_text_hi"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Menu Text Highlight", ""); + + prop= RNA_def_property(srna, "button_draw_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "but_drawtype"); + RNA_def_property_enum_items(prop, button_theme_styles); + RNA_def_property_ui_text(prop, "Button Draw Type", ""); + + prop= RNA_def_property(srna, "icon_file", PROP_STRING, PROP_FILEPATH); + RNA_def_property_string_sdna(prop, NULL, "iconfile"); + RNA_def_property_ui_text(prop, "Icon File", ""); +} + +static void rna_def_userdef_theme_spaces_main(StructRNA *srna) +{ + PropertyRNA *prop; + + prop= RNA_def_property(srna, "back", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Back", ""); + + prop= RNA_def_property(srna, "text", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Text", ""); + + prop= RNA_def_property(srna, "text_highlight", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "text_hi"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Text Highlight", ""); + + prop= RNA_def_property(srna, "header", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Header", ""); +} + +static void rna_def_userdef_theme_spaces_vertex(StructRNA *srna) +{ + PropertyRNA *prop; + + prop= RNA_def_property(srna, "vertex", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Vertex", ""); + + prop= RNA_def_property(srna, "vertex_select", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Vertex Select", ""); + + prop= RNA_def_property(srna, "vertex_size", PROP_INT, PROP_NONE); + RNA_def_property_range(prop, 0, 255); + RNA_def_property_ui_text(prop, "Vertex Size", ""); +} + +static void rna_def_userdef_theme_spaces_edge(StructRNA *srna) +{ + PropertyRNA *prop; + + prop= RNA_def_property(srna, "edge_select", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "edge Select", ""); + + prop= RNA_def_property(srna, "edge_seam", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Edge Seam", ""); + + prop= RNA_def_property(srna, "edge_sharp", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Edge Sharp", ""); + + prop= RNA_def_property(srna, "edge_facesel", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Edge UV Face Select", ""); +} + +static void rna_def_userdef_theme_spaces_face(StructRNA *srna) +{ + PropertyRNA *prop; + + prop= RNA_def_property(srna, "face", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Face", ""); + + prop= RNA_def_property(srna, "face_select", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Face Selected", ""); + + prop= RNA_def_property(srna, "face_dot", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Face Dot Selected", ""); + + prop= RNA_def_property(srna, "facedot_size", PROP_INT, PROP_NONE); + RNA_def_property_range(prop, 0, 255); + RNA_def_property_ui_text(prop, "Face Dot Size", ""); +} + +static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_view3d */ + + srna= RNA_def_struct(brna, "ThemeView3D", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme 3D View", ""); + + rna_def_userdef_theme_spaces_main(srna); + + prop= RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Grid", ""); + + prop= RNA_def_property(srna, "panel", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Panel", ""); + + prop= RNA_def_property(srna, "wire", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Wire", ""); + + prop= RNA_def_property(srna, "lamp", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Lamp", ""); + + prop= RNA_def_property(srna, "object_selected", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "select"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Object Selected", ""); + + prop= RNA_def_property(srna, "object_active", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "active"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Active Object", ""); + + prop= RNA_def_property(srna, "object_grouped", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "group"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Object Grouped", ""); + + prop= RNA_def_property(srna, "object_grouped_active", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "group_active"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Object Grouped Active", ""); + + prop= RNA_def_property(srna, "transform", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Transform", ""); + + rna_def_userdef_theme_spaces_vertex(srna); + rna_def_userdef_theme_spaces_edge(srna); + rna_def_userdef_theme_spaces_face(srna); + + prop= RNA_def_property(srna, "editmesh_active", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Active Vert/Edge/Face", ""); + + prop= RNA_def_property(srna, "normal", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Normal", ""); + + prop= RNA_def_property(srna, "bone_solid", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Bone Solid", ""); + + prop= RNA_def_property(srna, "bone_pose", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Bone Pose", ""); + + prop= RNA_def_property(srna, "current_frame", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "cframe"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Current Frame", ""); +} + +static void rna_def_userdef_theme_space_ipo(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_ipo */ + + srna= RNA_def_struct(brna, "ThemeIpoEditor", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme Ipo Editor", ""); + + rna_def_userdef_theme_spaces_main(srna); + + prop= RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Grid", ""); + + prop= RNA_def_property(srna, "panel", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Panel", ""); + + prop= RNA_def_property(srna, "window_sliders", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade1"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Window Sliders", ""); + + prop= RNA_def_property(srna, "ipo_channels", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade2"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Ipo Channels", ""); + + rna_def_userdef_theme_spaces_vertex(srna); + + prop= RNA_def_property(srna, "current_frame", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "cframe"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Current Frame", ""); + + prop= RNA_def_property(srna, "handle_vertex", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Handle Vertex", ""); + + prop= RNA_def_property(srna, "handle_vertex_select", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Handle Vertex Select", ""); + + prop= RNA_def_property(srna, "handle_vertex_size", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Handle Vertex Size", ""); +} + +static void rna_def_userdef_theme_space_file(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_file */ + + srna= RNA_def_struct(brna, "ThemeFileBrowser", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme File Browser", ""); + + rna_def_userdef_theme_spaces_main(srna); + + prop= RNA_def_property(srna, "selected_file", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "hilite"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Selected File", ""); + + prop= RNA_def_property(srna, "tiles", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "panel"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Tiles", ""); + + prop= RNA_def_property(srna, "scrollbar", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade1"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Scrollbar", ""); + + prop= RNA_def_property(srna, "scroll_handle", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade2"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Scroll Handle", ""); + + prop= RNA_def_property(srna, "active_file", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "active"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Active File", ""); + + prop= RNA_def_property(srna, "active_file_text", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "grid"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Active File Text", ""); +} + +static void rna_def_userdef_theme_space_oops(BlenderRNA *brna) +{ + StructRNA *srna; + + /* space_oops */ + + srna= RNA_def_struct(brna, "ThemeOutliner", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme Outliner", ""); + + rna_def_userdef_theme_spaces_main(srna); +} + +static void rna_def_userdef_theme_space_info(BlenderRNA *brna) +{ + StructRNA *srna; + + /* space_info */ + + srna= RNA_def_struct(brna, "ThemeUserPreferences", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme User Preferences", ""); + + rna_def_userdef_theme_spaces_main(srna); +} + +static void rna_def_userdef_theme_space_text(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_text */ + + srna= RNA_def_struct(brna, "ThemeTextEditor", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme Text Editor", ""); + + rna_def_userdef_theme_spaces_main(srna); + + prop= RNA_def_property(srna, "line_numbers_background", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "grid"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Line Numbers Background", ""); + + prop= RNA_def_property(srna, "scroll_bar", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade1"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Scroll Bar", ""); + + prop= RNA_def_property(srna, "selected_text", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade2"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Selected Text", ""); + + prop= RNA_def_property(srna, "cursor", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "hilite"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Cursor", ""); + + prop= RNA_def_property(srna, "syntax_builtin", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "syntaxb"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Syntax Builtin", ""); + + prop= RNA_def_property(srna, "syntax_special", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "syntaxv"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Syntax Special", ""); + + prop= RNA_def_property(srna, "syntax_Comment", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "syntaxc"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Syntax Comment", ""); + + prop= RNA_def_property(srna, "syntax_string", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "syntaxl"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Syntax String", ""); + + prop= RNA_def_property(srna, "syntax_numbers", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "syntaxn"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Syntax Numbers", ""); +} + +static void rna_def_userdef_theme_space_node(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_node */ + + srna= RNA_def_struct(brna, "ThemeNodeEditor", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme Node Editor", ""); + + rna_def_userdef_theme_spaces_main(srna); + + prop= RNA_def_property(srna, "wires", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "wire"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Wires", ""); + + prop= RNA_def_property(srna, "wire_select", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "edge_select"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Wire Select", ""); + + prop= RNA_def_property(srna, "selected_text", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade2"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Selected Text", ""); + + prop= RNA_def_property(srna, "node_backdrop", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "syntaxl"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Node Backdrop", ""); + + prop= RNA_def_property(srna, "in_out_node", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "syntaxn"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "In/Out Node", ""); + + prop= RNA_def_property(srna, "converter_node", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "syntaxv"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Converter Node", ""); + + prop= RNA_def_property(srna, "operator_node", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "syntaxb"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Operator Node", ""); + + prop= RNA_def_property(srna, "group_node", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "syntaxc"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Group Node", ""); +} + +static void rna_def_userdef_theme_space_buts(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_buts */ + + srna= RNA_def_struct(brna, "ThemeButtonsWindow", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme Buttons Window", ""); + + rna_def_userdef_theme_spaces_main(srna); + + prop= RNA_def_property(srna, "panel", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Panel", ""); +} + +static void rna_def_userdef_theme_space_time(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_time */ + + srna= RNA_def_struct(brna, "ThemeTimeline", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme Timeline", ""); + + rna_def_userdef_theme_spaces_main(srna); + + prop= RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Grid", ""); + + prop= RNA_def_property(srna, "current_frame", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "cframe"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Current Frame", ""); +} + +static void rna_def_userdef_theme_space_sound(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_sound */ + + srna= RNA_def_struct(brna, "ThemeAudioWindow", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme Audio Window", ""); + + rna_def_userdef_theme_spaces_main(srna); + + prop= RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Grid", ""); + + prop= RNA_def_property(srna, "window_sliders", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade1"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Window Sliders", ""); + + prop= RNA_def_property(srna, "current_frame", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "cframe"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Current Frame", ""); +} + +static void rna_def_userdef_theme_space_image(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_image */ + + srna= RNA_def_struct(brna, "ThemeImageEditor", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme Image Editor", ""); + + rna_def_userdef_theme_spaces_main(srna); + rna_def_userdef_theme_spaces_vertex(srna); + rna_def_userdef_theme_spaces_face(srna); + + prop= RNA_def_property(srna, "editmesh_active", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Active Vert/Edge/Face", ""); +} + +static void rna_def_userdef_theme_space_seq(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_seq */ + + srna= RNA_def_struct(brna, "ThemeSequenceEditor", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme Sequence Editor", ""); + + prop= RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Grid", ""); + + prop= RNA_def_property(srna, "window_sliders", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade1"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Window Sliders", ""); + + prop= RNA_def_property(srna, "movie_strip", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "movie"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Movie Strip", ""); + + prop= RNA_def_property(srna, "image_strip", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "image"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Image Strip", ""); + + prop= RNA_def_property(srna, "scene_strip", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "scene"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Scene Strip", ""); + + prop= RNA_def_property(srna, "audio_strip", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "audio"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Audio Strip", ""); + + prop= RNA_def_property(srna, "effect_strip", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "effect"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Effect Strip", ""); + + prop= RNA_def_property(srna, "plugin_strip", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "plugin"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Plugin Strip", ""); + + prop= RNA_def_property(srna, "transition_strip", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "transition"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Transition Strip", ""); + + prop= RNA_def_property(srna, "meta_strip", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "meta"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Meta Strip", ""); + + prop= RNA_def_property(srna, "current_frame", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "cframe"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Current Frame", ""); + + prop= RNA_def_property(srna, "keyframe", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "vertex_select"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Keyframe", ""); + + prop= RNA_def_property(srna, "draw_action", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "bone_pose"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Draw Action", ""); +} + +static void rna_def_userdef_theme_space_action(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_action */ + + srna= RNA_def_struct(brna, "ThemeActionEditor", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme Action Editor", ""); + + rna_def_userdef_theme_spaces_main(srna); + + prop= RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Grid", ""); + + prop= RNA_def_property(srna, "rvk_sliders", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "face"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "RVK Sliders", ""); + + prop= RNA_def_property(srna, "view_sliders", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade1"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "View Sliders", ""); + + prop= RNA_def_property(srna, "channels", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade2"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Channels", ""); + + prop= RNA_def_property(srna, "channels_selected", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "hilite"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Channels Selected", ""); + + prop= RNA_def_property(srna, "channel_group", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "group"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Channel Group", ""); + + prop= RNA_def_property(srna, "active_channels_group", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "group_active"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Active Channel Group", ""); + + prop= RNA_def_property(srna, "long_key", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "strip"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Long Key", ""); + + prop= RNA_def_property(srna, "long_key_selected", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "strip_select"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Long Key Selected", ""); + + prop= RNA_def_property(srna, "current_frame", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "cframe"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Current Frame", ""); +} + +static void rna_def_userdef_theme_space_nla(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* space_nla */ + + srna= RNA_def_struct(brna, "ThemeNLAEditor", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_ui_text(srna, "Theme NLA Editor", ""); + + rna_def_userdef_theme_spaces_main(srna); + + prop= RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Grid", ""); + + prop= RNA_def_property(srna, "view_sliders", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade1"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "View Sliders", ""); + + prop= RNA_def_property(srna, "bars", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "shade2"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Bars", ""); + + prop= RNA_def_property(srna, "bars_selected", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "hilite"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Bars Selected", ""); + + prop= RNA_def_property(srna, "strips", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "strip"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "strips", ""); + + prop= RNA_def_property(srna, "strips_selected", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "strip_select"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Strips Selected", ""); + + prop= RNA_def_property(srna, "current_frame", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "cframe"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Current Frame", ""); +} + +static void rna_def_userdef_theme_colorset(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "ThemeBoneColorSet", NULL); + RNA_def_struct_sdna(srna, "ThemeWireColor"); + RNA_def_struct_ui_text(srna, "Theme Bone Color Set", "Bone color sets."); + + prop= RNA_def_property(srna, "normal", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "solid"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Normal", "Color used for the surface of bones."); + + prop= RNA_def_property(srna, "selected", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "select"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Selected", "Color used for selected bones."); + + prop= RNA_def_property(srna, "active", PROP_FLOAT, PROP_COLOR); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Active", "Color used for active bones."); + + prop= RNA_def_property(srna, "colored_constraints", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", TH_WIRECOLOR_CONSTCOLS); + RNA_def_property_ui_text(prop, "Colored Constraints", "Allow the use of colors indicating constraints/keyed status."); +} + +static void rna_def_userdef_themes(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "Theme", NULL); + RNA_def_struct_sdna(srna, "bTheme"); + RNA_def_struct_ui_text(srna, "Theme", ""); + + prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Name of the theme."); + RNA_def_struct_name_property(srna, prop); + + prop= RNA_def_property(srna, "user_interface", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tui"); + RNA_def_property_struct_type(prop, "ThemeUserInterface"); + RNA_def_property_ui_text(prop, "User Interface", ""); + + prop= RNA_def_property(srna, "view_3d", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tv3d"); + RNA_def_property_struct_type(prop, "ThemeView3D"); + RNA_def_property_ui_text(prop, "3D View", ""); + + prop= RNA_def_property(srna, "ipo_curve_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tipo"); + RNA_def_property_struct_type(prop, "ThemeIpoEditor"); + RNA_def_property_ui_text(prop, "Ipo Curve Editor", ""); + + prop= RNA_def_property(srna, "file_browser", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tfile"); + RNA_def_property_struct_type(prop, "ThemeFileBrowser"); + RNA_def_property_ui_text(prop, "File Browser", ""); + + prop= RNA_def_property(srna, "nla_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tnla"); + RNA_def_property_struct_type(prop, "ThemeNLAEditor"); + RNA_def_property_ui_text(prop, "NLA Editor", ""); + + prop= RNA_def_property(srna, "action_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tact"); + RNA_def_property_struct_type(prop, "ThemeActionEditor"); + RNA_def_property_ui_text(prop, "Action Editor", ""); + + prop= RNA_def_property(srna, "image_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tima"); + RNA_def_property_struct_type(prop, "ThemeImageEditor"); + RNA_def_property_ui_text(prop, "Image Editor", ""); + + prop= RNA_def_property(srna, "sequence_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tseq"); + RNA_def_property_struct_type(prop, "ThemeSequenceEditor"); + RNA_def_property_ui_text(prop, "Sequence Editor", ""); + + prop= RNA_def_property(srna, "buttons_window", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tbuts"); + RNA_def_property_struct_type(prop, "ThemeButtonsWindow"); + RNA_def_property_ui_text(prop, "Buttons Window", ""); + + prop= RNA_def_property(srna, "text_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "text"); + RNA_def_property_struct_type(prop, "ThemeTextEditor"); + RNA_def_property_ui_text(prop, "Text Editor", ""); + + prop= RNA_def_property(srna, "timeline", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "ttime"); + RNA_def_property_struct_type(prop, "ThemeTimeline"); + RNA_def_property_ui_text(prop, "Timeline", ""); + + prop= RNA_def_property(srna, "node_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tnode"); + RNA_def_property_struct_type(prop, "ThemeNodeEditor"); + RNA_def_property_ui_text(prop, "Node Editor", ""); + + prop= RNA_def_property(srna, "outliner", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "toops"); + RNA_def_property_struct_type(prop, "ThemeOutliner"); + RNA_def_property_ui_text(prop, "Outliner", ""); + + prop= RNA_def_property(srna, "user_preferences", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "tinfo"); + RNA_def_property_struct_type(prop, "ThemeUserPreferences"); + RNA_def_property_ui_text(prop, "User Preferences", ""); + + prop= RNA_def_property(srna, "bone_color_sets", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "tarm", ""); + RNA_def_property_struct_type(prop, "ThemeBoneColorSet"); + RNA_def_property_ui_text(prop, "Bone Color Sets", ""); +} + +static void rna_def_userdef_dothemes(BlenderRNA *brna) +{ + rna_def_userdef_theme_ui(brna); + rna_def_userdef_theme_space_view3d(brna); + rna_def_userdef_theme_space_ipo(brna); + rna_def_userdef_theme_space_file(brna); + rna_def_userdef_theme_space_nla(brna); + rna_def_userdef_theme_space_action(brna); + rna_def_userdef_theme_space_image(brna); + rna_def_userdef_theme_space_seq(brna); + rna_def_userdef_theme_space_buts(brna); + rna_def_userdef_theme_space_text(brna); + rna_def_userdef_theme_space_time(brna); + rna_def_userdef_theme_space_node(brna); + rna_def_userdef_theme_space_oops(brna); + rna_def_userdef_theme_space_info(brna); + rna_def_userdef_theme_space_sound(brna); + rna_def_userdef_theme_colorset(brna); + rna_def_userdef_themes(brna); +} + +static void rna_def_userdef_solidlight(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "UserSolidLight", NULL); + RNA_def_struct_sdna(srna, "SolidLight"); + RNA_def_struct_ui_text(srna, "Solid Light", "Light used for OpenGL lighting in solid draw mode."); + + prop= RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", 1); + RNA_def_property_ui_text(prop, "Enabled", "Enable this OpenGL light in solid draw mode."); + + prop= RNA_def_property(srna, "direction", PROP_FLOAT, PROP_VECTOR); + RNA_def_property_float_sdna(prop, NULL, "vec"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Direction", "The direction that the OpenGL light is shining."); + + prop= RNA_def_property(srna, "diffuse_color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "col"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Diffuse Color", "The diffuse color of the OpenGL light."); + + prop= RNA_def_property(srna, "specular_color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "spec"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Specular Color", "The color of the lights specular highlight."); +} + +static void rna_def_userdef_view(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem view_zoom_styles[] = { + {USER_ZOOM_CONT, "CONTINUE", "Continue", "Old style zoom, continues while moving mouse up or down."}, + {USER_ZOOM_DOLLY, "DOLLY", "Dolly", "Zooms in and out based on vertical mouse movement."}, + {USER_ZOOM_SCALE, "SCALE", "Scale", "Zooms in and out like scaling the view, mouse movements relative to center."}, + {0, NULL, NULL, NULL}}; + + static EnumPropertyItem view_rotation_items[] = { + {0, "TURNTABLE", "Turntable", "Use turntable style rotation in the viewport."}, + {USER_TRACKBALL, "TRACKBALL", "Trackball", "Use trackball style rotation in the viewport."}, + {0, NULL, NULL, NULL}}; + + + /* View and Controls */ + + /* display */ + prop= RNA_def_property(srna, "tooltips", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_TOOLTIPS); + RNA_def_property_ui_text(prop, "Tooltips", "Display tooltips."); + + prop= RNA_def_property(srna, "display_object_info", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_DRAWVIEWINFO); + RNA_def_property_ui_text(prop, "Display Object Info", "Display and objects name and frame number in 3d view."); + + prop= RNA_def_property(srna, "global_scene", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_SCENEGLOBAL); + RNA_def_property_ui_text(prop, "Global Scene", "Forces the current Scene to be displayed in all Screens."); + + prop= RNA_def_property(srna, "use_large_cursors", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "curssize", 0); + RNA_def_property_ui_text(prop, "Use Large Cursors", "Use large mouse cursors when available."); + + prop= RNA_def_property(srna, "show_view_name", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_SHOW_VIEWPORTNAME); + RNA_def_property_ui_text(prop, "Show View Name", "Show the name of the view's direction in each 3D View."); + + prop= RNA_def_property(srna, "show_playback_fps", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_SHOW_FPS); + RNA_def_property_ui_text(prop, "Show Playback FPS", "Show the frames per second screen refresh rate, while animation is played back."); + + /* menus */ + prop= RNA_def_property(srna, "open_mouse_over", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_MENUOPENAUTO); + RNA_def_property_ui_text(prop, "Open On Mouse Over", "Open menu buttons and pulldowns automatically when the mouse is hovering."); + + prop= RNA_def_property(srna, "open_toplevel_delay", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "menuthreshold1"); + RNA_def_property_range(prop, 1, 40); + RNA_def_property_ui_text(prop, "Top Level Menu Open Delay", "Time delay in 1/10 seconds before automatically opening top level menus."); + + prop= RNA_def_property(srna, "open_sublevel_delay", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "menuthreshold2"); + RNA_def_property_range(prop, 1, 40); + RNA_def_property_ui_text(prop, "Sub Level Menu Open Delay", "Time delay in 1/10 seconds before automatically opening sub level menus."); + + /* Toolbox click-hold delay */ + prop= RNA_def_property(srna, "open_left_mouse_delay", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "tb_leftmouse"); + RNA_def_property_range(prop, 1, 40); + RNA_def_property_ui_text(prop, "Hold LMB Open Toolbox Delay", "Time in 1/10 seconds to hold the Left Mouse Button before opening the toolbox."); + + prop= RNA_def_property(srna, "open_right_mouse_delay", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "tb_rightmouse"); + RNA_def_property_range(prop, 1, 40); + RNA_def_property_ui_text(prop, "Hold RMB Open Toolbox Delay", "Time in 1/10 seconds to hold the Right Mouse Button before opening the toolbox."); + + prop= RNA_def_property(srna, "pin_floating_panels", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_PANELPINNED); + RNA_def_property_ui_text(prop, "Pin Floating Panels", "Make floating panels invoked by a hotkey (eg. N Key) open at the previous location."); + + prop= RNA_def_property(srna, "use_column_layout", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_PLAINMENUS); + RNA_def_property_ui_text(prop, "Use Column Layout", "Use a column layout for toolbox and do not flip the contents of any menu."); + + /* snap to grid */ + prop= RNA_def_property(srna, "snap_translate", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_AUTOGRABGRID); + RNA_def_property_ui_text(prop, "Enable Translation Snap", "Snap objects and sub-objects to grid units when moving."); + + prop= RNA_def_property(srna, "snap_rotate", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_AUTOROTGRID); + RNA_def_property_ui_text(prop, "Enable Rotation Snap", "Snap objects and sub-objects to grid units when rotating."); + + prop= RNA_def_property(srna, "snap_scale", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_AUTOSIZEGRID); + RNA_def_property_ui_text(prop, "Enable Scaling Snap", "Snap objects and sub-objects to grid units when scaling."); + + prop= RNA_def_property(srna, "auto_depth", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ORBIT_ZBUF); + RNA_def_property_ui_text(prop, "Use Auto Depth", "Use the depth under the mouse to improve view pan/rotate/zoom functionality."); + + prop= RNA_def_property(srna, "global_pivot", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_LOCKAROUND); + RNA_def_property_ui_text(prop, "Use Global Pivot", "Lock the same rotation/scaling pivot in all 3D Views."); + + /* view zoom */ + prop= RNA_def_property(srna, "viewport_zoom_style", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "viewzoom"); + RNA_def_property_enum_items(prop, view_zoom_styles); + RNA_def_property_ui_text(prop, "Viewport Zoom Style", "Which style to use for viewport scaling."); + + prop= RNA_def_property(srna, "zoom_to_mouse", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ZOOM_TO_MOUSEPOS); + RNA_def_property_ui_text(prop, "Zoom To Mouse Position", "Zoom in towards the mouse pointer's position in the 3D view, rather than the 2D window center."); + + /* view rotation */ + prop= RNA_def_property(srna, "view_rotation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, view_rotation_items); + RNA_def_property_ui_text(prop, "View Rotation", "Rotation style in the viewport."); + + prop= RNA_def_property(srna, "perspective_orthographic_switch", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_AUTOPERSP); + RNA_def_property_ui_text(prop, "Perspective/Orthographic Switch", "Automatically switch between orthographic and perspective when changing from top/front/side views."); + + prop= RNA_def_property(srna, "rotate_around_selection", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ORBIT_SELECTION); + RNA_def_property_ui_text(prop, "Rotate Around Selection", "Use selection as the orbiting center."); + + /* select with */ + prop= RNA_def_property(srna, "left_mouse_button_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_LMOUSESELECT); + RNA_def_property_boolean_funcs(prop, NULL, "rna_userdef_lmb_select_set"); + RNA_def_property_ui_text(prop, "Left Mouse Button Select", "Use left Mouse Button for selection."); + + prop= RNA_def_property(srna, "right_mouse_button_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_LMOUSESELECT); + RNA_def_property_boolean_funcs(prop, NULL, "rna_userdef_rmb_select_set"); + RNA_def_property_ui_text(prop, "Right Mouse Button Select", "Use Right Mouse Button for selection."); + + prop= RNA_def_property(srna, "emulate_3_button_mouse", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_TWOBUTTONMOUSE); + RNA_def_property_boolean_funcs(prop, NULL, "rna_userdef_emulate_set"); + RNA_def_property_ui_text(prop, "Emulate 3 Button Mouse", "Emulates Middle Mouse with Alt+LeftMouse (doesnt work with Left Mouse Select option.)"); + + prop= RNA_def_property(srna, "use_middle_mouse_paste", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_MMB_PASTE); + RNA_def_property_ui_text(prop, "Use Middle Mouse Paste", "In text window, paste with middle mouse button instead of panning."); + + prop= RNA_def_property(srna, "show_mini_axis", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_SHOW_ROTVIEWICON); + RNA_def_property_ui_text(prop, "Show Mini Axis", "Show a small rotating 3D axis in the bottom left corner of the 3D View."); + + prop= RNA_def_property(srna, "mini_axis_size", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "rvisize"); + RNA_def_property_range(prop, 10, 64); + RNA_def_property_ui_text(prop, "Mini Axis Size", "The axis icon's size."); + + prop= RNA_def_property(srna, "mini_axis_brightness", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "rvibright"); + RNA_def_property_range(prop, 0, 10); + RNA_def_property_ui_text(prop, "Mini Axis Brightness", "The brightness of the icon."); + + /* middle mouse button */ + prop= RNA_def_property(srna, "middle_mouse_rotate", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_VIEWMOVE); + RNA_def_property_ui_text(prop, "Use Middle Mouse Rotate", "Use the middle mouse button for rotation the viewport."); + + prop= RNA_def_property(srna, "middle_mouse_pan", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_VIEWMOVE); + RNA_def_property_ui_text(prop, "Use Middle Mouse Pan", "Use the middle mouse button for panning the viewport."); + + prop= RNA_def_property(srna, "wheel_invert_zoom", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_WHEELZOOMDIR); + RNA_def_property_ui_text(prop, "Wheel Invert Zoom", "Swap the Mouse Wheel zoom direction."); + + prop= RNA_def_property(srna, "wheel_scroll_lines", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "wheellinescroll"); + RNA_def_property_range(prop, 0, 32); + RNA_def_property_ui_text(prop, "Wheel Scroll Lines", "The number of lines scrolled at a time with the mouse wheel."); + + prop= RNA_def_property(srna, "smooth_view", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "smooth_viewtx"); + RNA_def_property_range(prop, 0, 1000); + RNA_def_property_ui_text(prop, "Smooth View", "The time to animate the view in miliseconds, zero to disable."); + + prop= RNA_def_property(srna, "rotation_angle", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "pad_rot_angle"); + RNA_def_property_range(prop, 0, 90); + RNA_def_property_ui_text(prop, "Rotation Angle", "The rotation step for numerical pad keys (2 4 6 8)."); + + /* 3D transform widget */ + prop= RNA_def_property(srna, "use_transform_widget", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "tw_flag", 1); + RNA_def_property_ui_text(prop, "Use Transform Widget", "Use 3d transform manipulator."); + + prop= RNA_def_property(srna, "transform_widget_size", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "tw_size"); + RNA_def_property_range(prop, 2, 40); + RNA_def_property_ui_text(prop, "Transform Widget Size", "Diameter of widget, in 10 pixel units."); + + prop= RNA_def_property(srna, "transform_widget_handle_size", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "tw_handlesize"); + RNA_def_property_range(prop, 2, 40); + RNA_def_property_ui_text(prop, "Transform Widget Handle Size", "Size of widget handles as percentage of widget radius."); + + prop= RNA_def_property(srna, "transform_widget_hotspot", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "tw_hotspot"); + RNA_def_property_range(prop, 4, 40); + RNA_def_property_ui_text(prop, "Transform Widget Hotspot", "Hotspot in pixels for clicking widget handles."); + + prop= RNA_def_property(srna, "object_center_size", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "obcenter_dia"); + RNA_def_property_range(prop, 4, 10); + RNA_def_property_ui_text(prop, "Object Center Size", "Diameter in Pixels for Object/Lamp center display."); + + prop= RNA_def_property(srna, "ndof_pan_speed", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "ndof_pan"); + RNA_def_property_range(prop, 4, 10); + RNA_def_property_ui_text(prop, "NDof Pan Speed", "The overall panning speed of an NDOF device, as percent of standard."); + + prop= RNA_def_property(srna, "ndof_rotate_speed", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "ndof_rotate"); + RNA_def_property_range(prop, 4, 10); + RNA_def_property_ui_text(prop, "NDof Rotation Speed", "The overall rotation speed of an NDOF device, as percent of standard."); +} + +static void rna_def_userdef_edit(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem auto_key_modes[] = { + {AUTOKEY_MODE_NORMAL, "ADD_REPLACE_KEYS", "Add/Replace Keys", ""}, + {AUTOKEY_MODE_EDITKEYS, "REPLACE_KEYS", "Replace Keys", ""}, + {0, NULL, NULL, NULL}}; + + static EnumPropertyItem new_ipo_curve_types[] = { + {IPO_CONST, "CONSTANT", "Constant", ""}, + {IPO_LIN, "LINEAR", "Linear", ""}, + {IPO_BEZ, "BEZIER", "Bezier", ""}, + {0, NULL, NULL, NULL}}; + + /* Edit Methods */ + prop= RNA_def_property(srna, "material_linked_object", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_MAT_ON_OB); + RNA_def_property_ui_text(prop, "Material Linked Object", "Toggle whether the material is linked to object data or the object block."); + + prop= RNA_def_property(srna, "material_linked_obdata", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_MAT_ON_OB); + RNA_def_property_ui_text(prop, "Material Linked ObData", "Toggle whether the material is linked to object data or the object block."); + + prop= RNA_def_property(srna, "enter_edit_mode", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_ADD_EDITMODE); + RNA_def_property_ui_text(prop, "Enter Edit Mode", "Enter Edit Mode automatically after adding a new object."); + + prop= RNA_def_property(srna, "align_to_view", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_ADD_VIEWALIGNED); + RNA_def_property_ui_text(prop, "Align To View", "Align newly added objects facing the 3D View direction."); + + prop= RNA_def_property(srna, "drag_immediately", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_DRAGIMMEDIATE); + RNA_def_property_ui_text(prop, "Drag Immediately", "Moving things with a mouse drag doesn't require a click to confirm (Best for tablet users)."); + + prop= RNA_def_property(srna, "undo_steps", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "undosteps"); + RNA_def_property_range(prop, 0, 64); + RNA_def_property_ui_text(prop, "Undo Steps", "Number of undo steps available (smaller values conserve memory)."); + + prop= RNA_def_property(srna, "undo_memory_limit", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "undomemory"); + RNA_def_property_range(prop, 0, 32767); + RNA_def_property_ui_text(prop, "Undo Memory Size", "Maximum memory usage in megabytes (0 means unlimited)."); + + prop= RNA_def_property(srna, "global_undo", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_GLOBALUNDO); + RNA_def_property_ui_text(prop, "Global Undo", "Global undo works by keeping a full copy of the file itself in memory, so takes extra memory."); + + prop= RNA_def_property(srna, "auto_keying_enable", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "autokey_mode", AUTOKEY_ON); + RNA_def_property_ui_text(prop, "Auto Keying Enable", "Automatic keyframe insertion for Objects and Bones."); + + prop= RNA_def_property(srna, "auto_keying_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, auto_key_modes); + RNA_def_property_enum_funcs(prop, "rna_userdef_autokeymode_get", "rna_userdef_autokeymode_set"); + RNA_def_property_ui_text(prop, "Auto Keying Mode", "Mode of automatic keyframe insertion for Objects and Bones."); + + prop= RNA_def_property(srna, "auto_keyframe_insert_available", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_INSERTAVAIL); + RNA_def_property_ui_text(prop, "Auto Keyframe Insert Available", "Automatic keyframe insertion in available curves."); + + prop= RNA_def_property(srna, "auto_keyframe_insert_needed", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_INSERTNEEDED); + RNA_def_property_ui_text(prop, "Auto Keyframe Insert Needed", "Automatic keyframe insertion only when keyframe needed."); + + prop= RNA_def_property(srna, "use_visual_keying", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_AUTOMATKEY); + RNA_def_property_ui_text(prop, "Use Visual Keying", "Use Visual keying automatically for constrained objects."); + + prop= RNA_def_property(srna, "new_ipo_curve_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, new_ipo_curve_types); + RNA_def_property_enum_sdna(prop, NULL, "ipo_new"); + RNA_def_property_ui_text(prop, "New Ipo Curve Type", ""); + + prop= RNA_def_property(srna, "grease_pencil_manhattan_distance", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "gp_manhattendist"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Grease Pencil Manhattan Distance", "Pixels moved by mouse per axis when drawing stroke."); + + prop= RNA_def_property(srna, "grease_pencil_euclidean_distance", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "gp_euclideandist"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Grease Pencil Euclidean Distance", "Distance moved by mouse when drawing stroke (in pixels) to include."); + + prop= RNA_def_property(srna, "grease_pencil_smooth_stroke", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "gp_settings", GP_PAINT_DOSMOOTH); + RNA_def_property_ui_text(prop, "Grease Pencil Smooth Stroke", "Smooth the final stroke."); + +#if 0 + prop= RNA_def_property(srna, "grease_pencil_simplify_stroke", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "gp_settings", GP_PAINT_DOSIMPLIFY); + RNA_def_property_ui_text(prop, "Grease Pencil Simplify Stroke", "Simplify the final stroke."); +#endif + + prop= RNA_def_property(srna, "grease_pencil_eraser_radius", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "gp_eraser"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Grease Pencil Eraser Radius", "Radius of eraser 'brush'."); + + prop= RNA_def_property(srna, "duplicate_mesh", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_MESH); + RNA_def_property_ui_text(prop, "Duplicate Mesh", "Causes mesh data to be duplicated with Shift+D."); + + prop= RNA_def_property(srna, "duplicate_surface", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_SURF); + RNA_def_property_ui_text(prop, "Duplicate Surface", "Causes surface data to be duplicated with Shift+D."); + + prop= RNA_def_property(srna, "duplicate_curve", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_CURVE); + RNA_def_property_ui_text(prop, "Duplicate Curve", "Causes curve data to be duplicated with Shift+D."); + + prop= RNA_def_property(srna, "duplicate_text", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_FONT); + RNA_def_property_ui_text(prop, "Duplicate Text", "Causes text data to be duplicated with Shift+D."); + + prop= RNA_def_property(srna, "duplicate_metaball", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_MBALL); + RNA_def_property_ui_text(prop, "Duplicate Metaball", "Causes metaball data to be duplicated with Shift+D."); + + prop= RNA_def_property(srna, "duplicate_armature", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_ARM); + RNA_def_property_ui_text(prop, "Duplicate Armature", "Causes armature data to be duplicated with Shift+D."); + + prop= RNA_def_property(srna, "duplicate_lamp", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_LAMP); + RNA_def_property_ui_text(prop, "Duplicate Lamp", "Causes lamp data to be duplicated with Shift+D."); + + prop= RNA_def_property(srna, "duplicate_Material", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_MAT); + RNA_def_property_ui_text(prop, "Duplicate Material", "Causes material data to be duplicated with Shift+D."); + + prop= RNA_def_property(srna, "duplicate_texture", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_TEX); + RNA_def_property_ui_text(prop, "Duplicate Texture", "Causes texture data to be duplicated with Shift+D."); + + prop= RNA_def_property(srna, "duplicate_ipo", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_IPO); + RNA_def_property_ui_text(prop, "Duplicate Ipo", "Causes ipo data to be duplicated with Shift+D."); + + prop= RNA_def_property(srna, "duplicate_action", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_ACT); + RNA_def_property_ui_text(prop, "Duplicate Action", "Causes actions to be duplicated with Shift+D."); +} + +static void rna_def_userdef_language(StructRNA *srna) +{ + PropertyRNA *prop; + + /* hardcoded here, could become dynamic somehow */ + static EnumPropertyItem language_items[] = { + {0, "ENGLISH", "English", ""}, + {1, "JAPANESE", "Japanese", ""}, + {2, "DUTCH", "Dutch", ""}, + {3, "ITALIAN", "Italian", ""}, + {4, "GERMAN", "German", ""}, + {5, "FINNISH", "Finnish", ""}, + {6, "SWEDISH", "Swedish", ""}, + {7, "FRENCH", "French", ""}, + {8, "SPANISH", "Spanish", ""}, + {9, "CATALAN", "Catalan", ""}, + {10, "CZECH", "Czech", ""}, + {11, "BRAZILIAN_PORTUGUESE", "Brazilian Portuguese", ""}, + {12, "SIMPLIFIED_CHINESE", "Simplified Chinese", ""}, + {13, "RUSSIAN", "Russian", ""}, + {14, "CROATIAN", "Croatian", ""}, + {15, "SERBIAN", "Serbian", ""}, + {16, "UKRAINIAN", "Ukrainian", ""}, + {17, "POLISH", "Polish", ""}, + {18, "ROMANIAN", "Romanian", ""}, + {19, "ARABIC", "Arabic", ""}, + {20, "BULGARIAN", "Bulgarian", ""}, + {21, "GREEK", "Greek", ""}, + {22, "KOREAN", "Korean", ""}, + {0, NULL, NULL, NULL}}; + + prop= RNA_def_property(srna, "international_fonts", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_DOTRANSLATE); + RNA_def_property_ui_text(prop, "International Fonts", "Use international fonts."); + + prop= RNA_def_property(srna, "font_size", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "fontsize"); + RNA_def_property_range(prop, 8, 16); + RNA_def_property_ui_text(prop, "Font Size", "International font size (points)."); + + prop= RNA_def_property(srna, "font_filename", PROP_STRING, PROP_FILEPATH); + RNA_def_property_string_sdna(prop, NULL, "fontname"); + RNA_def_property_ui_text(prop, "Font Filename", "International font filename."); + + /* Language Selection */ + + prop= RNA_def_property(srna, "language", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, language_items); + RNA_def_property_ui_text(prop, "Language", "Language use for translation."); + + prop= RNA_def_property(srna, "translate_tooltips", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_TOOLTIPS); + RNA_def_property_ui_text(prop, "Translate Tooltips", "Translate Tooltips."); + + prop= RNA_def_property(srna, "translate_buttons", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_BUTTONS); + RNA_def_property_ui_text(prop, "Translate Buttons", "Translate button labels."); + + prop= RNA_def_property(srna, "translate_toolbox", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_MENUS); + RNA_def_property_ui_text(prop, "Translate Toolbox", "Translate toolbox menu."); + + prop= RNA_def_property(srna, "use_textured_fonts", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_USETEXTUREFONT); + RNA_def_property_ui_text(prop, "Use Textured Fonts", "Use textures for drawing international fonts."); +} + +static void rna_def_userdef_autosave(StructRNA *srna) +{ + PropertyRNA *prop; + + /* Autosave */ + + prop= RNA_def_property(srna, "save_version", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "versions"); + RNA_def_property_range(prop, 0, 32); + RNA_def_property_ui_text(prop, "Save Versions", "The number of old versions to maintain in the current directory, when manually saving."); prop= RNA_def_property(srna, "auto_save_temporary_files", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_AUTOSAVE); RNA_def_property_ui_text(prop, "Auto Save Temporary Files", "Automatic saving of temporary files."); + + prop= RNA_def_property(srna, "auto_save_time", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "savetime"); + RNA_def_property_range(prop, 0, 32); + RNA_def_property_ui_text(prop, "Auto Save Time", "The time (in minutes) to wait between automatic temporary saves."); + + prop= RNA_def_property(srna, "recent_files", PROP_INT, PROP_NONE); + RNA_def_property_range(prop, 0, 30); + RNA_def_property_ui_text(prop, "Recent Files", "Maximum number of recently opened files to remember."); + + prop= RNA_def_property(srna, "save_preview_images", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_SAVE_PREVIEWS); + RNA_def_property_ui_text(prop, "Save Preview Images", "Enables automatic saving of preview images in the .blend file."); +} + +static void rna_def_userdef_system(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem gl_texture_clamp_items[] = { + {0, "GL_CLAMP_OFF", "GL Texture Clamp Off", ""}, + {8192, "GL_CLAMP_8192", "GL Texture Clamp 8192", ""}, + {4096, "GL_CLAMP_4096", "GL Texture Clamp 4096", ""}, + {2048, "GL_CLAMP_2048", "GL Texture Clamp 2048", ""}, + {1024, "GL_CLAMP_1024", "GL Texture Clamp 1024", ""}, + {512, "GL_CLAMP_512", "GL Texture Clamp 512", ""}, + {256, "GL_CLAMP_256", "GL Texture Clamp 256", ""}, + {128, "GL_CLAMP_128", "GL Texture Clamp 128", ""}, + {0, NULL, NULL, NULL}}; + + static EnumPropertyItem audio_mixing_samples_items[] = { + {256, "AUDIO_SAMPLES_256", "256", "Set audio mixing buffer size to 256 samples"}, + {512, "AUDIO_SAMPLES_512", "512", "Set audio mixing buffer size to 512 samples"}, + {1024, "AUDIO_SAMPLES_1024", "1024", "Set audio mixing buffer size to 1024 samples"}, + {2048, "AUDIO_SAMPLES_2048", "2048", "Set audio mixing buffer size to 2048 samples"}, + {0, NULL, NULL, NULL}}; + + /* System & OpenGL */ + + prop= RNA_def_property(srna, "solid_lights", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "light", ""); + RNA_def_property_struct_type(prop, "UserSolidLight"); + RNA_def_property_ui_text(prop, "Solid Lights", "Lights user to display objects in solid draw mode."); + + prop= RNA_def_property(srna, "use_weight_color_range", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_CUSTOM_RANGE); + RNA_def_property_ui_text(prop, "Use Weight Color Range", "Enable color range used for weight visualization in weight painting mode."); + + prop= RNA_def_property(srna, "weight_color_range", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "coba_weight"); + RNA_def_property_struct_type(prop, "ColorRamp"); + RNA_def_property_ui_text(prop, "Weight Color Range", "Color range used for weight visualization in weight painting mode."); + + prop= RNA_def_property(srna, "enable_all_codecs", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ALLWINCODECS); + RNA_def_property_ui_text(prop, "Enable All Codecs", "Enables automatic saving of preview images in the .blend file (Windows only)."); + + prop= RNA_def_property(srna, "auto_run_python_scripts", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_DONT_DOSCRIPTLINKS); + RNA_def_property_ui_text(prop, "Auto Run Python Scripts", "Allow any .blend file to run scripts automatically (unsafe with blend files from an untrusted source)."); + + prop= RNA_def_property(srna, "emulate_numpad", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_NONUMPAD); + RNA_def_property_ui_text(prop, "Emulate Numpad", "Causes the 1 to 0 keys to act as the numpad (useful for laptops)."); + + prop= RNA_def_property(srna, "prefetch_frames", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "prefetchframes"); + RNA_def_property_range(prop, 0, 500); + RNA_def_property_ui_text(prop, "Prefetch Frames", "Number of frames to render ahead during playback."); + + prop= RNA_def_property(srna, "memory_cache_limit", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "memcachelimit"); + RNA_def_property_range(prop, 0, (sizeof(void *) ==8)? 1024*16: 1024); /* 32 bit 2 GB, 64 bit 16 GB */ + RNA_def_property_ui_text(prop, "Memory Cache Limit", "Memory cache limit in sequencer (megabytes)."); + + prop= RNA_def_property(srna, "frame_server_port", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "frameserverport"); + RNA_def_property_range(prop, 0, 32727); + RNA_def_property_ui_text(prop, "Frame Server Port", "Frameserver Port for Framserver-Rendering."); + + prop= RNA_def_property(srna, "game_sound", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_SOUND); + RNA_def_property_ui_text(prop, "Game Sound", "Enables sounds to be played in games."); + + prop= RNA_def_property(srna, "filter_file_extensions", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_FILTERFILEEXTS); + RNA_def_property_ui_text(prop, "Filter File Extensions", "Display only files with extensions in the image select window."); + + prop= RNA_def_property(srna, "hide_dot_files_datablocks", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_HIDE_DOT); + RNA_def_property_ui_text(prop, "Hide Dot Files/Datablocks", "Hide files/datablocks that start with a dot(.*)"); + + prop= RNA_def_property(srna, "clip_alpha", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "glalphaclip"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Clip Alpha", "Clip alpha below this threshold in the 3d textured view."); + + prop= RNA_def_property(srna, "use_mipmaps", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_MIPMAP); + RNA_def_property_ui_text(prop, "Use Mipmaps", "Scale textures for the 3d View (looks nicer but uses more memory and slows image reloading.)"); + + prop= RNA_def_property(srna, "gl_texture_limit", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "glreslimit"); + RNA_def_property_enum_items(prop, gl_texture_clamp_items); + RNA_def_property_ui_text(prop, "GL Texture Limit", "Limit the texture size to save graphics memory."); + + prop= RNA_def_property(srna, "texture_time_out", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "textimeout"); + RNA_def_property_range(prop, 0, 3600); + RNA_def_property_ui_text(prop, "Texture Time Out", "Time since last access of a GL texture in seconds after which it is freed. (Set to 0 to keep textures allocated.)"); + + prop= RNA_def_property(srna, "texture_collection_rate", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "texcollectrate"); + RNA_def_property_range(prop, 1, 3600); + RNA_def_property_ui_text(prop, "Texture Collection Rate", "Number of seconds between each run of the GL texture garbage collector."); + + prop= RNA_def_property(srna, "audio_mixing_buffer", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mixbufsize"); + RNA_def_property_enum_items(prop, audio_mixing_samples_items); + RNA_def_property_ui_text(prop, "Audio Mixing Buffer", "Sets the number of samples used by the audio mixing buffer."); + +#if 0 + prop= RNA_def_property(srna, "verse_master", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "versemaster"); + RNA_def_property_ui_text(prop, "Verse Master", "The Verse Master-server IP"); + + prop= RNA_def_property(srna, "verse_username", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "verseuser"); + RNA_def_property_ui_text(prop, "Verse Username", "The Verse user name"); +#endif +} + +static void rna_def_userdef_filepaths(StructRNA *srna) +{ + PropertyRNA *prop; + + prop= RNA_def_property(srna, "use_relative_paths", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_RELPATHS); + RNA_def_property_ui_text(prop, "Use Relative Paths", "Default relative path option for the file selector."); + + prop= RNA_def_property(srna, "compress_file", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_FILECOMPRESS); + RNA_def_property_ui_text(prop, "Compress File", "Enable file compression when saving .blend files."); + + prop= RNA_def_property(srna, "yafray_export_directory", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "yfexportdir"); + RNA_def_property_ui_text(prop, "Yafray Export Directory", "The default directory for yafray xml export (must exist!)."); + + prop= RNA_def_property(srna, "fonts_directory", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "fontdir"); + RNA_def_property_ui_text(prop, "Fonts Directory", "The default directory to search for loading fonts."); + + prop= RNA_def_property(srna, "textures_directory", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "textudir"); + RNA_def_property_ui_text(prop, "Textures Directory", "The default directory to search for textures."); + + prop= RNA_def_property(srna, "texture_plugin_directory", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "plugtexdir"); + RNA_def_property_ui_text(prop, "Texture Plugin Directory", "The default directory to search for texture plugins."); + + prop= RNA_def_property(srna, "sequence_plugin_directory", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "plugseqdir"); + RNA_def_property_ui_text(prop, "Sequence Plugin Directory", "The default directory to search for sequence plugins."); + + prop= RNA_def_property(srna, "render_output_directory", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "renderdir"); + RNA_def_property_ui_text(prop, "Render Output Directory", "The default directory for rendering output."); + + prop= RNA_def_property(srna, "python_scripts_directory", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "pythondir"); + RNA_def_property_ui_text(prop, "Python Scripts Directory", "The default directory to search for Python scripts (resets python module search path: sys.path)."); + + prop= RNA_def_property(srna, "sounds_directory", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "sounddir"); + RNA_def_property_ui_text(prop, "Sounds Directory", "The default directory to search for sounds."); + + prop= RNA_def_property(srna, "temporary_directory", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "tempdir"); + RNA_def_property_ui_text(prop, "Temporary Directory", "The directory for storing temporary save files."); } void RNA_def_userdef(BlenderRNA *brna) { - rna_def_userdef(brna); + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem user_pref_sections[] = { + {0, "VIEW_CONTROLS", "View & Controls", ""}, + {1, "EDIT_METHODS", "Edit Methods", ""}, + {2, "LANGUAGE_COLORS", "Language & Colors", ""}, + {3, "AUTO_SAVE", "Auto Save", ""}, + {4, "SYSTEM_OPENGL", "System & OpenGL", ""}, + {5, "FILE_PATHS", "File Paths", ""}, + {6, "THEMES", "Themes", ""}, + {0, NULL, NULL, NULL}}; + + rna_def_userdef_dothemes(brna); + rna_def_userdef_solidlight(brna); + + srna= RNA_def_struct(brna, "UserPreferences", NULL); + RNA_def_struct_sdna(srna, "UserDef"); + RNA_def_struct_ui_text(srna, "User Preferences", "Global user preferences."); + + prop= RNA_def_property(srna, "active_section", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "userpref"); + RNA_def_property_enum_items(prop, user_pref_sections); + RNA_def_property_ui_text(prop, "Active Section", "Active section of the user preferences shown in the user interface."); + + prop= RNA_def_property(srna, "themes", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "themes", NULL); + RNA_def_property_struct_type(prop, "Theme"); + RNA_def_property_ui_text(prop, "Themes", ""); + + rna_def_userdef_view(srna); + rna_def_userdef_edit(srna); + rna_def_userdef_language(srna); + rna_def_userdef_autosave(srna); + rna_def_userdef_system(srna); + rna_def_userdef_filepaths(srna); } #endif diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index c125c587be8..d09776adfa4 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -71,6 +71,7 @@ void rna_def_ambient_occlusion(BlenderRNA *brna, StructRNA *parent) srna= RNA_def_struct(brna, "WorldAmbientOcclusion", NULL); RNA_def_struct_sdna(srna, "World"); + RNA_def_struct_parent(srna, parent); RNA_def_struct_ui_text(srna, "Ambient Occlusion", "DOC_BROKEN"); prop= RNA_def_property(parent, "ambient_occlusion", PROP_POINTER, PROP_NONE); diff --git a/source/blender/python/epy_doc_gen.py b/source/blender/python/epy_doc_gen.py index 9e0c6127a4c..99faf57a1bd 100644 --- a/source/blender/python/epy_doc_gen.py +++ b/source/blender/python/epy_doc_gen.py @@ -43,23 +43,23 @@ def rna2epy(target_path): - def write_struct(rna_struct): + def write_struct(rna_struct, structs, ident): identifier = rna_struct.identifier rna_base = rna_struct.base if rna_base: - out.write('class %s(%s):\n' % (identifier, rna_base.identifier)) + out.write(ident+ 'class %s(%s):\n' % (identifier, rna_base.identifier)) else: - out.write('class %s:\n' % identifier) + out.write(ident+ 'class %s:\n' % identifier) - out.write('\t"""\n') + out.write(ident+ '\t"""\n') title = 'The %s Object' % rna_struct.name - out.write('\t%s\n' % title) - out.write('\t%s\n' % ('=' * len(title))) - out.write('\t\t%s\n' % rna_struct.description) + out.write(ident+ '\t%s\n' % title) + out.write(ident+ '\t%s\n' % ('=' * len(title))) + out.write(ident+ '\t\t%s\n' % rna_struct.description) for rna_prop_identifier, rna_prop in rna_struct.properties.items(): @@ -90,25 +90,30 @@ def rna2epy(target_path): else: readonly_str = ' (readonly)' if rna_prop_ptr: # Use the pointer type - out.write('\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc)) - out.write('\t@type %s: %sL{%s}%s%s\n' % (rna_prop_identifier, collection_str, rna_prop_ptr.identifier, array_str, readonly_str)) + out.write(ident+ '\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc)) + out.write(ident+ '\t@type %s: %sL{%s}%s%s\n' % (rna_prop_identifier, collection_str, rna_prop_ptr.identifier, array_str, readonly_str)) else: if rna_prop_type == 'enum': - out.write('\t@ivar %s: %s in (%s)\n' % (rna_prop_identifier, rna_desc, ', '.join(rna_prop.items.keys()))) - out.write('\t@type %s: %s%s%s\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str)) + out.write(ident+ '\t@ivar %s: %s in (%s)\n' % (rna_prop_identifier, rna_desc, ', '.join(rna_prop.items.keys()))) + out.write(ident+ '\t@type %s: %s%s%s\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str)) elif rna_prop_type == 'int' or rna_prop_type == 'float': - out.write('\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc)) - out.write('\t@type %s: %s%s%s in [%s, %s]\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str, range_str(rna_prop.hard_min), range_str(rna_prop.hard_max) )) + out.write(ident+ '\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc)) + out.write(ident+ '\t@type %s: %s%s%s in [%s, %s]\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str, range_str(rna_prop.hard_min), range_str(rna_prop.hard_max) )) elif rna_prop_type == 'string': - out.write('\t@ivar %s: %s (maximum length of %s)\n' % (rna_prop_identifier, rna_desc, rna_prop.max_length)) - out.write('\t@type %s: %s%s%s\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str)) + out.write(ident+ '\t@ivar %s: %s (maximum length of %s)\n' % (rna_prop_identifier, rna_desc, rna_prop.max_length)) + out.write(ident+ '\t@type %s: %s%s%s\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str)) else: - out.write('\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc)) - out.write('\t@type %s: %s%s%s\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str)) + out.write(ident+ '\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc)) + out.write(ident+ '\t@type %s: %s%s%s\n' % (rna_prop_identifier, rna_prop_type, array_str, readonly_str)) - out.write('\t"""\n\n') - + out.write(ident+ '\t"""\n\n') + + # Now write children recursively + for child in structs: + if rna_struct == child.parent: + write_struct(child, structs, ident + '\t') + out = open(target_path, 'w') @@ -150,7 +155,11 @@ def rna2epy(target_path): for rna_struct in structs: - write_struct(rna_struct) + if rna_struct.parent: + continue + + write_struct(rna_struct, structs, '') + out.write('\n') out.close() diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 061c43c4773..f800b7d0d04 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -164,7 +164,9 @@ PyObject *pyop_func_get_rna(BPy_OperatorFunc *self) pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); /* were not really using &ptr, overwite next */ /* XXX POINTER - if this 'ot' is python generated, it could be free'd */ - RNA_pointer_create(NULL, NULL, ot->srna, &pyrna->properties, &pyrna->ptr); + RNA_pointer_create(NULL, ot->srna, NULL, &pyrna->ptr); + pyrna->freeptr= 1; + return (PyObject *)pyrna; } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index a8409976b73..7ad40d3dcd3 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -63,10 +63,10 @@ static long pyrna_struct_hash( BPy_StructRNA * self ) static void pyrna_struct_dealloc( BPy_StructRNA * self ) { /* Note!! for some weired reason calling PyObject_DEL() directly crashes blender! */ - if (self->properties) { - IDP_FreeProperty(self->properties); - MEM_freeN(self->properties); - self->properties= NULL; + if (self->freeptr && self->ptr.data) { + IDP_FreeProperty(self->ptr.data); + MEM_freeN(self->ptr.data); + self->ptr.data= NULL; } ((PyObject *)self)->ob_type->tp_free(self); @@ -1135,7 +1135,7 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr ) } pyrna->ptr= *ptr; - pyrna->properties= NULL; + pyrna->freeptr= 0; return ( PyObject * ) pyrna; } diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 8f21e6d80c8..73272eac6e8 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -36,7 +36,7 @@ extern PyTypeObject pyrna_prop_Type; typedef struct { PyObject_VAR_HEAD /* required python macro */ PointerRNA ptr; - IDProperty *properties; /* needed in some cases for RNA_pointer_create(), free when deallocing */ + int freeptr; /* needed in some cases if ptr.data is created on the fly, free when deallocing */ } BPy_StructRNA; typedef struct { diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 3149b711a27..4de6c770cdc 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2043,8 +2043,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem psys->flag &= ~PSYS_DRAWING; if(psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } if(path && (ma->mode_l & MA_TANGENT_STR)==0) diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 40a67c3c67a..c4cd6d655a3 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -63,6 +63,9 @@ void WM_cursor_restore (struct wmWindow *win); void WM_cursor_wait (struct wmWindow *win, int val); void WM_timecursor (struct wmWindow *win, int nr); +void *WM_paint_cursor_activate(struct wmWindowManager *wm, int (*poll)(struct bContext *C), void (*draw)(struct bContext *C, int, int)); +void WM_paint_cursor_end(struct wmWindowManager *wm, void *handle); + /* keymap */ wmKeymapItem *WM_keymap_set_item (ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier); diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 1533cc636db..f76bfb511b3 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -168,6 +168,8 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) BLI_freelistN(&wm->queue); + BLI_freelistN(&wm->paintcursors); + if(C && CTX_wm_manager(C)==wm) CTX_wm_manager_set(C, NULL); } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index eb5a1449f36..161ab66f3fd 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -277,6 +277,23 @@ static int wm_draw_update_test_window(wmWindow *win) return 0; } +static void wm_paintcursor_draw(bContext *C) +{ + wmWindowManager *wm= CTX_wm_manager(C); + + if(wm->paintcursors.first) { + wmWindow *win= CTX_wm_window(C); + wmPaintCursor *pc; + + for(pc= wm->paintcursors.first; pc; pc= pc->next) { + if(pc->poll(C)) { + ARegion *ar= CTX_wm_region(C); + pc->draw(C, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin); + } + } + } +} + void wm_draw_update(bContext *C) { wmWindowManager *wm= CTX_wm_manager(C); @@ -304,12 +321,16 @@ void wm_draw_update(bContext *C) CTX_wm_area_set(C, sa); for(ar=sa->regionbase.first; ar; ar= ar->next) { - CTX_wm_region_set(C, ar); - if(ar->swinid && ar->do_draw) + if(ar->swinid && ar->do_draw) { + CTX_wm_region_set(C, ar); + ED_region_do_draw(C, ar); - - CTX_wm_region_set(C, NULL); + if(win->screen->subwinactive==ar->swinid) + wm_paintcursor_draw(C); + + CTX_wm_region_set(C, NULL); + } } CTX_wm_area_set(C, NULL); @@ -392,7 +413,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P IDPropertyTemplate val = {0}; op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties"); } - RNA_pointer_create(&RNA_WindowManager, &wm->id, ot->srna, op->properties, op->ptr); + RNA_pointer_create(&wm->id, ot->srna, op->properties, op->ptr); /* initialize error reports */ if (reports) { @@ -509,7 +530,6 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe /* ********************* handlers *************** */ - /* not handler itself, is called by UI to move handlers to other queues, so don't close modal ones */ static void wm_event_free_handler(wmEventHandler *handler) { @@ -799,11 +819,6 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) static int wm_event_inside_i(wmEvent *event, rcti *rect) { - return BLI_in_rcti(rect, event->x, event->y); -} - -static int wm_event_prev_inside_i(wmEvent *event, rcti *rect) -{ if(BLI_in_rcti(rect, event->x, event->y)) return 1; if(event->type==MOUSEMOVE) { @@ -815,19 +830,19 @@ static int wm_event_prev_inside_i(wmEvent *event, rcti *rect) return 0; } -static ScrArea *area_event_inside(bContext *C, wmEvent *event) +static ScrArea *area_event_inside(bContext *C, int x, int y) { bScreen *screen= CTX_wm_screen(C); ScrArea *sa; if(screen) for(sa= screen->areabase.first; sa; sa= sa->next) - if(BLI_in_rcti(&sa->totrct, event->x, event->y)) + if(BLI_in_rcti(&sa->totrct, x, y)) return sa; return NULL; } -static ARegion *region_event_inside(bContext *C, wmEvent *event) +static ARegion *region_event_inside(bContext *C, int x, int y) { bScreen *screen= CTX_wm_screen(C); ScrArea *area= CTX_wm_area(C); @@ -835,11 +850,44 @@ static ARegion *region_event_inside(bContext *C, wmEvent *event) if(screen && area) for(ar= area->regionbase.first; ar; ar= ar->next) - if(BLI_in_rcti(&ar->winrct, event->x, event->y)) + if(BLI_in_rcti(&ar->winrct, x, y)) return ar; return NULL; } +static void wm_paintcursor_tag(bContext *C, wmPaintCursor *pc, ARegion *ar) +{ + if(ar) + for(; pc; pc= pc->next) + if(pc->poll(C)) + ED_region_tag_redraw(ar); +} + +/* called on mousemove, check updates for paintcursors */ +/* context was set on active area and region */ +static void wm_paintcursor_test(bContext *C, wmEvent *event) +{ + wmWindowManager *wm= CTX_wm_manager(C); + + if(wm->paintcursors.first) { + ARegion *ar= CTX_wm_region(C); + if(ar) + wm_paintcursor_tag(C, wm->paintcursors.first, ar); + + /* if previous position was not in current region, we have to set a temp new context */ + if(ar==NULL || !BLI_in_rcti(&ar->winrct, event->prevx, event->prevy)) { + ScrArea *sa= CTX_wm_area(C); + + CTX_wm_area_set(C, area_event_inside(C, event->prevx, event->prevy)); + CTX_wm_region_set(C, region_event_inside(C, event->prevx, event->prevy)); + + wm_paintcursor_tag(C, wm->paintcursors.first, CTX_wm_region(C)); + + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + } + } +} /* called in main loop */ /* goes over entire hierarchy: events -> window -> screen -> area -> region */ @@ -857,8 +905,9 @@ void wm_event_do_handlers(bContext *C) int action; CTX_wm_window_set(C, win); - CTX_wm_area_set(C, area_event_inside(C, event)); - CTX_wm_region_set(C, region_event_inside(C, event)); + /* we let modal handlers get active area/region, also wm_paintcursor_test needs it */ + CTX_wm_area_set(C, area_event_inside(C, event->x, event->y)); + CTX_wm_region_set(C, region_event_inside(C, event->x, event->y)); /* MVC demands to not draw in event handlers... but we need to leave it for ogl selecting etc */ wm_window_make_drawable(C, win); @@ -871,22 +920,26 @@ void wm_event_do_handlers(bContext *C) int doit= 0; /* XXX to solve, here screen handlers? */ - if(!wm_event_always_pass(event)) + if(event->type==MOUSEMOVE) { ED_screen_set_subwinactive(win, event); /* state variables in screen, cursors */ + wm_paintcursor_test(C, event); + } for(sa= win->screen->areabase.first; sa; sa= sa->next) { - if(wm_event_always_pass(event) || wm_event_prev_inside_i(event, &sa->totrct)) { - doit= 1; + if(wm_event_always_pass(event) || wm_event_inside_i(event, &sa->totrct)) { + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, NULL); action= wm_handlers_do(C, event, &sa->handlers); if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) { for(ar=sa->regionbase.first; ar; ar= ar->next) { - if(wm_event_always_pass(event) || wm_event_inside_i(event, &ar->winrct) || wm_event_prev_inside_i(event, &ar->winrct)) { + if(wm_event_always_pass(event) || wm_event_inside_i(event, &ar->winrct)) { CTX_wm_region_set(C, ar); action= wm_handlers_do(C, event, &ar->handlers); - CTX_wm_region_set(C, NULL); + doit |= (BLI_in_rcti(&ar->winrct, event->x, event->y)); + if(!wm_event_always_pass(event)) { if(action==WM_HANDLER_BREAK) break; @@ -894,21 +947,21 @@ void wm_event_do_handlers(bContext *C) } } } - - CTX_wm_area_set(C, NULL); /* NOTE: do not escape on WM_HANDLER_BREAK, mousemove needs handled for previous area */ } } /* XXX hrmf, this gives reliable previous mouse coord for area change, feels bad? doing it on ghost queue gives errors when mousemoves go over area borders */ - if(doit) { - CTX_wm_window(C)->eventstate->prevx= event->x; - CTX_wm_window(C)->eventstate->prevy= event->y; + if(doit && win->screen->subwinactive != win->screen->mainwin) { + win->eventstate->prevx= event->x; + win->eventstate->prevy= event->y; } } wm_event_free(event); CTX_wm_window_set(C, NULL); + CTX_wm_area_set(C, NULL); + CTX_wm_region_set(C, NULL); } } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index f79b5a2955d..a2eefad05a5 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -172,7 +172,7 @@ void WM_operator_properties_create(PointerRNA *ptr, const char *opstring) wmOperatorType *ot= WM_operatortype_find(opstring); if(ot) - RNA_pointer_create(NULL, NULL, ot->srna, NULL, ptr); + RNA_pointer_create(NULL, ot->srna, NULL, ptr); else memset(ptr, 0, sizeof(*ptr)); } @@ -335,12 +335,10 @@ static int wm_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event) /* settings for filebrowser */ sfile= (SpaceFile*)CTX_wm_space_data(C); sfile->op = op; + ED_fileselect_set_params(sfile, FILE_BLENDER, "Load", "C:\\", 0, 0, 0); - ED_fileselect_set_params(sfile->params, FILE_BLENDER, "Load", "C:\\", 0, 0, 0); + /* screen and area have been reset already in ED_screen_full_newspace */ - /* screen, areas init */ - WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); - return OPERATOR_RUNNING_MODAL; } @@ -393,6 +391,38 @@ static void WM_OT_exit_blender(wmOperatorType *ot) ot->poll= WM_operator_winactive; } +/* ************ default paint cursors, draw always around cursor *********** */ +/* + - returns handler to free + - poll(bContext): returns 1 if draw should happen + - draw(bContext): drawing callback for paint cursor +*/ + +void *WM_paint_cursor_activate(wmWindowManager *wm, int (*poll)(bContext *C), void (*draw)(bContext *C, int, int)) +{ + wmPaintCursor *pc= MEM_callocN(sizeof(wmPaintCursor), "paint cursor"); + + BLI_addtail(&wm->paintcursors, pc); + + pc->poll= poll; + pc->draw= draw; + + return pc; +} + +void WM_paint_cursor_end(wmWindowManager *wm, void *handle) +{ + wmPaintCursor *pc; + + for(pc= wm->paintcursors.first; pc; pc= pc->next) { + if(pc == (wmPaintCursor *)handle) { + BLI_remlink(&wm->paintcursors, pc); + MEM_freeN(pc); + return; + } + } +} + /* ************ window gesture operator-callback definitions ************** */ /* * These are default callbacks for use in operators requiring gesture input @@ -498,7 +528,7 @@ int WM_border_select_modal(bContext *C, wmOperator *op, wmEvent *event) } /* **************** circle gesture *************** */ -/* works now only for selection or modal paint stuff, calls exec while hold mouse */ +/* works now only for selection or modal paint stuff, calls exec while hold mouse, exit on release */ int WM_gesture_circle_invoke(bContext *C, wmOperator *op, wmEvent *event) { diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index 1835a475323..c063226b96f 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -30,6 +30,13 @@ struct wmWindow; +typedef struct wmPaintCursor { + struct wmPaintCursor *next, *prev; + + int (*poll)(struct bContext *C); + void (*draw)(bContext *C, int, int); +} wmPaintCursor; + extern void wm_close_and_free(bContext *C, wmWindowManager *); extern void wm_close_and_free_all(bContext *C, ListBase *); |