commit before doing some hefty shapekey change, will break compilation

This commit is contained in:
Joseph Eagar 2009-11-01 00:06:53 +00:00
parent 672c8926d7
commit 2d0d4e7de4
226 changed files with 9805 additions and 6758 deletions

View File

@ -67,6 +67,7 @@ struct KeyingSet *BKE_keyingset_add(struct ListBase *list, const char name[], sh
/* Add a destination to a KeyingSet */
void BKE_keyingset_add_destination(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode);
/* Find the destination matching the criteria given */
struct KS_Path *BKE_keyingset_find_destination(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode);
/* Copy all KeyingSets in the given list */
@ -78,6 +79,15 @@ void BKE_keyingset_free(struct KeyingSet *ks);
/* Free all the KeyingSets in the given list */
void BKE_keyingsets_free(struct ListBase *list);
/* ************************************* */
/* Path Fixing API */
/* Fix all the paths for the given ID+AnimData */
void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, char *prefix, char *oldName, char *newName);
/* Fix all the paths for the entire database... */
void BKE_all_animdata_fix_paths_rename(char *prefix, char *oldName, char *newName);
/* ************************************* */
// TODO: overrides, remapping, and path-finding api's

View File

@ -43,7 +43,7 @@ struct bContext;
struct ReportList;
#define BLENDER_VERSION 250
#define BLENDER_SUBVERSION 6
#define BLENDER_SUBVERSION 7
#define BLENDER_MINVERSION 250
#define BLENDER_MINSUBVERSION 0

View File

@ -92,6 +92,9 @@ void switchdirectionNurb( struct Nurb *nu);
float (*curve_getVertexCos(struct Curve *cu, struct ListBase *lb, int *numVerts_r))[3];
void curve_applyVertexCos(struct Curve *cu, struct ListBase *lb, float (*vertexCos)[3]);
float (*curve_getKeyVertexCos(struct Curve *cu, struct ListBase *lb, float *key))[3];
void curve_applyKeyVertexTilts(struct Curve *cu, struct ListBase *lb, float *key);
/* nurb checks if they can be drawn, also clamp order func */
int check_valid_nurb_u( struct Nurb *nu);
int check_valid_nurb_v( struct Nurb *nu);

View File

@ -110,7 +110,7 @@ typedef struct Global {
#define G_BACKBUFSEL (1 << 4)
#define G_PICKSEL (1 << 5)
#define G_FACESELECT (1 << 8)
/* #define G_FACESELECT (1 << 8) use (mesh->editflag & ME_EDIT_PAINT_MASK) */
#define G_DEBUG (1 << 12)
#define G_DOSCRIPTLINKS (1 << 13)
@ -145,6 +145,7 @@ typedef struct Global {
#define G_FILE_GLSL_NO_NODES (1 << 20) /* deprecated */
#define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21) /* deprecated */
#define G_FILE_IGNORE_DEPRECATION_WARNINGS (1 << 22) /* deprecated */
#define G_FILE_RECOVER (1 << 23)
/* G.windowstate */
#define G_WINDOWSTATE_USERDEF 0

View File

@ -56,17 +56,15 @@ void key_curve_position_weights(float t, float *data, int type);
void key_curve_tangent_weights(float t, float *data, int type);
void key_curve_normal_weights(float t, float *data, int type);
/* only exported to curve.c! */
void cp_cu_key(struct Curve *cu, struct KeyBlock *kb, int start, int end);
int do_ob_key(struct Scene *scene, struct Object *ob);
float *do_ob_key(struct Scene *scene, struct Object *ob);
struct Key *ob_get_key(struct Object *ob);
struct KeyBlock *ob_get_keyblock(struct Object *ob);
struct KeyBlock *key_get_keyblock(struct Key *key, int index);
struct KeyBlock *key_get_named_keyblock(struct Key *key, const char name[]);
char *key_get_curValue_rnaPath(struct Key *key, struct KeyBlock *kb);
// needed for the GE
void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, int mode);
void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, int mode);
#ifdef __cplusplus
};

View File

@ -47,6 +47,7 @@ void test_object_materials(struct ID *id);
void init_material(struct Material *ma);
struct Material *add_material(char *name);
struct Material *copy_material(struct Material *ma);
struct Material *give_node_material(struct Material *ma); /* returns node material or self */
void make_local_material(struct Material *ma);
void automatname(struct Material *);

View File

@ -55,7 +55,7 @@ extern "C" {
struct EditMesh *BKE_mesh_get_editmesh(struct Mesh *me);
void BKE_mesh_end_editmesh(struct Mesh *me, struct EditMesh *em);
struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me);
struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob);
/*
this function recreates a tesselation.
@ -111,7 +111,6 @@ void mesh_calc_normals(struct MVert *mverts, int numVerts, struct MFace *mfaces,
/* Return a newly MEM_malloc'd array of all the mesh vertex locations
* (_numVerts_r_ may be NULL) */
float (*mesh_getVertexCos(struct Mesh *me, int *numVerts_r))[3];
float (*mesh_getRefKeyCos(struct Mesh *me, int *numVerts_r))[3];
/* map from uv vertex to face (for select linked, stitch, uv suburf) */

View File

@ -294,7 +294,7 @@ void modifiers_foreachIDLink(struct Object *ob,
struct ModifierData *modifiers_findByType(struct Object *ob, ModifierType type);
void modifiers_clearErrors(struct Object *ob);
int modifiers_getCageIndex(struct Object *ob,
int *lastPossibleCageIndex_r);
int *lastPossibleCageIndex_r, int virtual_);
int modifiers_isSoftbodyEnabled(struct Object *ob);
int modifiers_isClothEnabled(struct Object *ob);

View File

@ -135,6 +135,7 @@ struct SeqEffectHandle {
/* ********************* prototypes *************** */
/* sequence.c */
void printf_strip(struct Sequence *seq);
// extern
void seq_free_sequence(struct Scene *scene, struct Sequence *seq);
@ -181,6 +182,7 @@ int check_single_seq(struct Sequence *seq);
void fix_single_seq(struct Sequence *seq);
int seq_test_overlap(struct ListBase * seqbasep, struct Sequence *test);
int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test);
int shuffle_seq_time(ListBase * seqbasep);
void free_imbuf_seq(struct ListBase * seqbasep, int check_mem_usage);
void seq_update_sound(struct Sequence *seq);

View File

@ -1990,9 +1990,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
*final_r = NULL;
if(useDeform) {
if(useDeform > 0 && do_ob_key(scene, ob)) /* shape key makes deform verts */
deformedVerts = mesh_getVertexCos(me, &numVerts);
else if(inputVertexCos)
if(inputVertexCos)
deformedVerts = inputVertexCos;
/* Apply all leading deforming modifiers */
@ -2035,7 +2033,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
if(inputVertexCos)
deformedVerts = inputVertexCos;
else
deformedVerts = mesh_getRefKeyCos(me, &numVerts);
deformedVerts = mesh_getVertexCos(me, &numVerts);
}
@ -2248,7 +2246,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
float (*deformedVerts)[3] = NULL;
CustomDataMask mask;
DerivedMesh *dm, *orcodm = NULL;
int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL, 1);
LinkNode *datamasks, *curr;
int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
@ -2259,7 +2257,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
}
dm = NULL;
md = ob->modifiers.first;
md = modifiers_getVirtualModifierList(ob);
/* we always want to keep original indices */
dataMask |= CD_MASK_ORIGINDEX;
@ -2695,13 +2693,13 @@ int editbmesh_get_first_deform_matrices(Object *ob, BMEditMesh *em, float (**def
ModifierData *md;
DerivedMesh *dm;
int i, a, numleft = 0, numVerts = 0;
int cageIndex = modifiers_getCageIndex(ob, NULL);
int cageIndex = modifiers_getCageIndex(ob, NULL, 1);
float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
modifiers_clearErrors(ob);
dm = NULL;
md = ob->modifiers.first;
md = modifiers_getVirtualModifierList(ob);
/* compute the deformation matrices and coordinates for the first
modifiers with on cage editing that are enabled and support computing

View File

@ -238,24 +238,88 @@ void BKE_animdata_make_local(AnimData *adt)
/* Path Validation -------------------------------------------- */
#if 0
/* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate */
static char *rna_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, char *oldpath)
/* Check if a given RNA Path is valid, by tracing it from the given ID, and seeing if we can resolve it */
static short check_rna_path_is_valid (ID *owner_id, char *path)
{
PointerRNA id_ptr, ptr;
PropertyRNA *prop=NULL;
/* make initial RNA pointer to start resolving from */
RNA_id_pointer_create(owner_id, &id_ptr);
return oldpath; // FIXME!!!
/* try to resolve */
return RNA_path_resolve(&id_ptr, path, &ptr, &prop);
}
/* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate
* NOTE: we assume that oldName and newName have [" "] padding around them
*/
static char *rna_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, char *oldpath)
{
char *prefixPtr= strstr(oldpath, prefix);
char *oldNamePtr= strstr(oldpath, oldName);
int prefixLen= strlen(prefix);
int oldNameLen= strlen(oldName);
/* only start fixing the path if the prefix and oldName feature in the path,
* and prefix occurs immediately before oldName
*/
if ( (prefixPtr && oldNamePtr) && (prefixPtr+prefixLen == oldNamePtr) ) {
/* if we haven't aren't able to resolve the path now, try again after fixing it */
if (check_rna_path_is_valid(owner_id, oldpath) == 0) {
DynStr *ds= BLI_dynstr_new();
char *postfixPtr= oldNamePtr+oldNameLen;
char *newPath = NULL;
char oldChar;
/* add the part of the string that goes up to the start of the prefix */
if (prefixPtr > oldpath) {
oldChar= prefixPtr[0];
prefixPtr[0]= 0;
BLI_dynstr_append(ds, oldpath);
prefixPtr[0]= oldChar;
}
/* add the prefix */
BLI_dynstr_append(ds, prefix);
/* add the new name (complete with brackets) */
BLI_dynstr_append(ds, newName);
/* add the postfix */
BLI_dynstr_append(ds, postfixPtr);
/* create new path, and cleanup old data */
newPath= BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
/* check if the new path will solve our problems */
// TODO: will need to check whether this step really helps in practice
if (check_rna_path_is_valid(owner_id, newPath)) {
/* free the old path, and return the new one, since we've solved the issues */
MEM_freeN(oldpath);
return newPath;
}
else {
/* still couldn't resolve the path... so, might as well just leave it alone */
MEM_freeN(newPath);
}
}
}
/* the old path doesn't need to be changed */
return oldpath;
}
/* Check RNA-Paths for a list of F-Curves */
static void fcurves_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, ListBase *curves)
static void fcurves_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *curves)
{
FCurve *fcu;
/* we need to check every curve... */
for (fcu= curves->first; fcu; fcu= fcu->next) {
/* firstly, handle the F-Curve's own path */
fcu->rna_path= rna_path_rename_fix(owner_id, modPtr, newName, fcu->rna_path);
fcu->rna_path= rna_path_rename_fix(owner_id, prefix, oldName, newName, fcu->rna_path);
/* driver? */
if (fcu->driver) {
@ -264,14 +328,14 @@ static void fcurves_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *new
/* driver targets */
for (dtar= driver->targets.first; dtar; dtar=dtar->next) {
dtat->rna_path= rna_path_rename_fix(dtar->id, modPtr, newName, dtar->rna_path);
dtar->rna_path= rna_path_rename_fix(dtar->id, prefix, oldName, newName, dtar->rna_path);
}
}
}
}
/* Fix all RNA-Paths for Actions linked to NLA Strips */
static void nlastrips_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, ListBase *strips)
static void nlastrips_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *strips)
{
NlaStrip *strip;
@ -279,42 +343,122 @@ static void nlastrips_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *n
for (strip= strips->first; strip; strip= strip->next) {
/* fix strip's action */
if (strip->act)
fcurves_path_rename_fix(owner_id, modPtr, newName, &strip->act->curves);
fcurves_path_rename_fix(owner_id, prefix, oldName, newName, &strip->act->curves);
/* ignore own F-Curves, since those are local... */
/* check sub-strips (if metas) */
nlastrips_path_rename_fix(owner_id, modPtr, newName, &strip->strips);
nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, &strip->strips);
}
}
/* Fix all RNA-Paths in the AnimData block used by the given ID block
* - the pointer of interest must not have had its new name assigned already, otherwise
* path matching for this will never work
* NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
* i.e. pose.pose_channels["Bone"]
*/
void BKE_animdata_fix_paths_rename (ID *owner_id, PointerRNA *modPtr, char *newName)
void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, char *prefix, char *oldName, char *newName)
{
AnimData *adt= BKE_animdata_from_id(owner_id);
NlaTrack *nlt;
char *oldN, *newN;
/* if no AnimData, no need to proceed */
if (ELEM4(NULL, owner_id, adt, modPtr, newName))
if (ELEM4(NULL, owner_id, adt, oldName, newName))
return;
/* pad the names with [" "] so that only exact matches are made */
oldN= BLI_sprintfN("[\"%s\"]", oldName);
newN= BLI_sprintfN("[\"%s\"]", newName);
/* Active action and temp action */
if (adt->action)
fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->action->curves);
fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->action->curves);
if (adt->tmpact)
fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->tmpact->curves);
fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->tmpact->curves);
/* Drivers - Drivers are really F-Curves */
fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->drivers);
fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->drivers);
/* NLA Data - Animation Data for Strips */
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
nlastrips_path_rename_fix(owner_id, prefix, oldN, newN, &nlt->strips);
/* free the temp names */
MEM_freeN(oldN);
MEM_freeN(newN);
}
/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
* NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
* i.e. pose.pose_channels["Bone"]
*/
void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newName)
{
Main *mainptr= G.main;
ID *id;
/* macro for less typing
* - whether animdata exists is checked for by the main renaming callback, though taking
* this outside of the function may make things slightly faster?
*/
#define RENAMEFIX_ANIM_IDS(first) \
for (id= first; id; id= id->next) { \
AnimData *adt= BKE_animdata_from_id(id); \
BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName);\
}
/* nodes */
RENAMEFIX_ANIM_IDS(mainptr->nodetree.first);
/* textures */
RENAMEFIX_ANIM_IDS(mainptr->tex.first);
/* lamps */
RENAMEFIX_ANIM_IDS(mainptr->lamp.first);
/* materials */
RENAMEFIX_ANIM_IDS(mainptr->mat.first);
/* cameras */
RENAMEFIX_ANIM_IDS(mainptr->camera.first);
/* shapekeys */
RENAMEFIX_ANIM_IDS(mainptr->key.first);
/* metaballs */
RENAMEFIX_ANIM_IDS(mainptr->mball.first);
/* curves */
RENAMEFIX_ANIM_IDS(mainptr->curve.first);
/* armatures */
RENAMEFIX_ANIM_IDS(mainptr->armature.first);
/* meshes */
// TODO...
/* particles */
RENAMEFIX_ANIM_IDS(mainptr->particle.first);
/* objects */
RENAMEFIX_ANIM_IDS(mainptr->object.first);
/* worlds */
RENAMEFIX_ANIM_IDS(mainptr->world.first);
/* scenes */
for (id= mainptr->scene.first; id; id= id->next) {
AnimData *adt= BKE_animdata_from_id(id);
Scene *scene= (Scene *)id;
/* do compositing nodes first (since these aren't included in main tree) */
if (scene->nodetree) {
AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree);
BKE_animdata_fix_paths_rename((ID *)scene->nodetree, adt2, prefix, oldName, newName);
}
/* now fix scene animation data as per normal */
BKE_animdata_fix_paths_rename((ID *)id, adt, prefix, oldName, newName);
}
}
#endif
/* *********************************** */
/* KeyingSet API */

View File

@ -1287,7 +1287,7 @@ void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float
* - the result should be that the rotations given in the provided pointers have had conversions
* applied (as appropriate), such that the rotation of the element hasn't 'visually' changed
*/
void BKE_rotMode_change_values (float quat[4], float eul[3], float *axis, float angle[3], short oldMode, short newMode)
void BKE_rotMode_change_values (float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode)
{
/* check if any change - if so, need to convert data */
if (newMode > 0) { /* to euler */

View File

@ -226,8 +226,6 @@ static void clear_global(void)
// free_vertexpaint();
G.main= NULL;
G.f &= ~(G_FACESELECT);
}
/* make sure path names are correct for OS */
@ -281,12 +279,15 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
Object *ob;
bScreen *curscreen= NULL;
Scene *curscene= NULL;
int recover;
char mode;
/* 'u' = undo save, 'n' = no UI load */
if(bfd->main->screen.first==NULL) mode= 'u';
else if(G.fileflags & G_FILE_NO_UI) mode= 'n';
else mode= 0;
recover= (G.fileflags & G_FILE_RECOVER);
clean_paths(bfd->main);
@ -371,6 +372,16 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
if(G.main->versionfile < 250)
do_versions_ipos_to_animato(G.main); // XXX fixme... complicated versionpatching
/* in case of autosave or quit.blend, use original filename instead */
if(recover && bfd->filename[0])
filename= bfd->filename;
/* these are the same at times, should never copy to the same location */
if(G.sce != filename)
BLI_strncpy(G.sce, filename, FILE_MAX);
BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */
/* baseflags, groups, make depsgraph, etc */
set_scene_bg(CTX_data_scene(C));
@ -383,11 +394,6 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
/* now tag update flags, to ensure deformers get calculated on redraw */
DAG_scene_update_flags(CTX_data_scene(C), CTX_data_scene(C)->lay);
if (G.sce != filename) /* these are the same at times, should never copy to the same location */
strcpy(G.sce, filename);
BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */
MEM_freeN(bfd);
}

View File

@ -1099,8 +1099,7 @@ float *make_orco_curve(Scene *scene, Object *ob)
float *fp, *coord_array;
int remakeDisp = 0;
if (!(cu->flag&CU_UV_ORCO) && cu->key && cu->key->refkey) {
cp_cu_key(cu, cu->key->refkey, 0, count_curveverts(&cu->nurb));
if (!(cu->flag&CU_UV_ORCO) && cu->key && cu->key->block.first) {
makeDispListCurveTypes(scene, ob, 1);
remakeDisp = 1;
}
@ -1922,7 +1921,7 @@ void makeBevelList(Object *ob)
BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
float min, inp, x1, x2, y1, y2;
struct bevelsort *sortdata, *sd, *sd1;
int a, b, nr, poly, resolu, len=0;
int a, b, nr, poly, resolu = 0, len = 0;
int do_tilt, do_radius;
/* this function needs an object, because of tflag and upflag */
@ -2905,6 +2904,64 @@ void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3])
}
}
float (*curve_getKeyVertexCos(Curve *cu, ListBase *lb, float *key))[3]
{
int i, numVerts;
float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "cu_vcos");
Nurb *nu;
co = cos[0];
for (nu=lb->first; nu; nu=nu->next) {
if (nu->type == CU_BEZIER) {
BezTriple *bezt = nu->bezt;
for (i=0; i<nu->pntsu; i++,bezt++) {
VECCOPY(co, key); co+=3; key+=3;
VECCOPY(co, key); co+=3; key+=3;
VECCOPY(co, key); co+=3; key+=3;
key++; /* skip tilt */
}
}
else {
BPoint *bp = nu->bp;
for(i=0; i<nu->pntsu*nu->pntsv; i++,bp++) {
VECCOPY(co, key); co+=3; key+=3;
key++; /* skip tilt */
}
}
}
return cos;
}
void curve_applyKeyVertexTilts(Curve *cu, ListBase *lb, float *key)
{
Nurb *nu;
int i;
for(nu=lb->first; nu; nu=nu->next) {
if(nu->type == CU_BEZIER) {
BezTriple *bezt = nu->bezt;
for(i=0; i<nu->pntsu; i++,bezt++) {
key+=3*3;
bezt->alfa= *key;
key++;
}
}
else {
BPoint *bp = nu->bp;
for(i=0; i<nu->pntsu*nu->pntsv; i++,bp++) {
key+=3;
bp->alfa= *key;
key++;
}
}
}
}
int check_valid_nurb_u( struct Nurb *nu )
{
if (nu==NULL) return 0;

View File

@ -829,7 +829,27 @@ static void layerDefault_mcol(void *data, int count)
mcol[i] = default_mcol;
}
static void layerInterp_shapekey(void **sources, float *weights,
float *sub_weights, int count, void *dest)
{
float *co = dest, *src;
float **in = sources;
int i, j, k;
if(count <= 0) return;
memset(co, 0, sizeof(float)*3);
sub_weight = sub_weights;
for(i = 0; i < count; ++i) {
float weight = weights ? weights[i] : 1.0f;
src = in[i];
co[0] += src[0] * weight;
co[1] += src[1] * weight;
co[2] += src[2] * weight;
}
}
const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
@ -875,13 +895,16 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
layerSwap_mcol, layerDefault_mcol},
{sizeof(MCol)*4, "MCol", 4, "TextureCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
{sizeof(float), "", 3, "ShapeKey", layerInterp_shapekey},
};
const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace",
"CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty",
"CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV",
"CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol"};
"CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol", "CDMPoly",
"CDMLoop", "CDMLoopCol", "CDIDCol", "CDTextureCol", "CDShapeKeyIndex"};
const CustomDataMask CD_MASK_BAREMESH =
CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MLOOP | CD_MASK_MPOLY;
@ -893,15 +916,17 @@ const CustomDataMask CD_MASK_MESH =
CD_MASK_MTEXPOLY;
const CustomDataMask CD_MASK_EDITMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS;
CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX |
CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR |
CD_MASK_MDISPS | CD_MASK_SHAPEKEY;
const CustomDataMask CD_MASK_DERIVEDMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_WEIGHT_MLOOPCOL |
CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_WEIGHT_MCOL;
const CustomDataMask CD_MASK_BMESH = CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX;
const CustomDataMask CD_MASK_FACECORNERS =
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL;

View File

@ -2235,7 +2235,18 @@ void DAG_id_flush_update(ID *id, short flag)
}
}
}
/* set flags based on ShapeKey */
if(idtype == ID_KE) {
for(obt=bmain->object.first; obt; obt= obt->id.next) {
Key *key= ob_get_key(obt);
if(!(ob && obt == ob) && ((ID *)key == id)) {
obt->flag |= (OB_RECALC|OB_RECALC_DATA);
BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
}
}
}
/* set flags based on particle settings */
if(idtype == ID_PA) {
ParticleSystem *psys;

View File

@ -1245,6 +1245,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
int editmode = (!forRender && cu->editnurb);
float (*originalVerts)[3] = NULL;
float (*deformedVerts)[3] = NULL;
float *keyVerts= NULL;
int required_mode;
if(forRender) required_mode = eModifierMode_Render;
@ -1254,9 +1255,17 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
if(editmode) required_mode |= eModifierMode_Editmode;
if(cu->editnurb==NULL && do_ob_key(scene, ob)) {
deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts);
originalVerts = MEM_dupallocN(deformedVerts);
if(cu->editnurb==NULL) {
keyVerts= do_ob_key(scene, ob);
if(keyVerts) {
/* split coords from key data, the latter also includes
tilts, which is passed through in the modifier stack.
this is also the reason curves do not use a virtual
shape key modifier yet. */
deformedVerts= curve_getKeyVertexCos(cu, nurb, keyVerts);
originalVerts= MEM_dupallocN(deformedVerts);
}
}
if (preTesselatePoint) {
@ -1270,7 +1279,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
if (mti->type!=eModifierTypeType_OnlyDeform) continue;
if (!deformedVerts) {
deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts);
deformedVerts = curve_getVertexCos(cu, nurb, &numVerts);
originalVerts = MEM_dupallocN(deformedVerts);
}
@ -1281,9 +1290,13 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
}
}
if (deformedVerts) {
curve_applyVertexCos(ob->data, nurb, deformedVerts);
}
if (deformedVerts)
curve_applyVertexCos(cu, nurb, deformedVerts);
if (keyVerts) /* these are not passed through modifier stack */
curve_applyKeyVertexTilts(cu, nurb, keyVerts);
if(keyVerts)
MEM_freeN(keyVerts);
*originalVerts_r = originalVerts;
*deformedVerts_r = deformedVerts;

View File

@ -35,6 +35,9 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
#include "DNA_anim_types.h"
#include "DNA_curve_types.h"
#include "DNA_key_types.h"
@ -53,11 +56,12 @@
#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_mesh.h"
#include "BKE_tessmesh.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_utildefines.h"
#include "BLI_blenlib.h"
#include "RNA_access.h"
#include "BLI_cellalloc.h"
@ -167,7 +171,7 @@ Key *copy_key(Key *key)
while(kbn) {
if(kbn->data) kbn->data= MEM_dupallocN(kbn->data);
if( kb==key->refkey ) keyn->refkey= kbn;
if(kb==key->refkey) keyn->refkey= kbn;
kbn= kbn->next;
kb= kb->next;
@ -496,48 +500,80 @@ static void rel_flerp(int aantal, float *in, float *ref, float *out, float fac)
}
}
static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *k, float *weights, int mode)
static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **freedata)
{
if(kb == actkb) {
/* this hack makes it possible to edit shape keys in
edit mode with shape keys blending applied */
if(GS(key->from->name) == ID_ME) {
Mesh *me;
BMVert *eve;
BMIter iter;
float (*co)[3];
int a;
me= (Mesh*)key->from;
if(me->edit_btmesh && me->edit_btmesh->bm->totvert == kb->totelem) {
a= 0;
co= MEM_callocN(sizeof(float)*3*me->edit_btmesh->bm->totvert, "key_block_get_data");
BM_ITER(eve, &iter, me->edit_btmesh->bm, BM_VERTS_OF_MESH, NULL) {
VECCOPY(co[a], eve->co);
a++;
}
*freedata= (char*)co;
return (char*)co;
}
}
}
*freedata= NULL;
return kb->data;
}
static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, int mode)
{
float ktot = 0.0, kd = 0.0;
int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo=0;
char *k1, *kref;
char *k1, *kref, *freek1, *freekref;
char *cp, elemstr[8];
if(key->from==NULL) return;
if( GS(key->from->name)==ID_ME ) {
ofs[0]= sizeof(MVert);
ofs[0]= sizeof(float)*3;
ofs[1]= 0;
poinsize= ofs[0];
}
else if( GS(key->from->name)==ID_LT ) {
ofs[0]= sizeof(BPoint);
ofs[0]= sizeof(float)*3;
ofs[1]= 0;
poinsize= ofs[0];
}
else if( GS(key->from->name)==ID_CU ) {
if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
else ofs[0]= sizeof(BezTriple);
if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
else ofs[0]= sizeof(float)*10;
ofs[1]= 0;
poinsize= ofs[0];
}
if(end>tot) end= tot;
k1= k->data;
kref= key->refkey->data;
if(tot != k->totelem) {
if(tot != kb->totelem) {
ktot= 0.0;
flagflo= 1;
if(k->totelem) {
kd= k->totelem/(float)tot;
if(kb->totelem) {
kd= kb->totelem/(float)tot;
}
else return;
}
k1= key_block_get_data(key, actkb, kb, &freek1);
kref= key_block_get_data(key, actkb, key->refkey, &freekref);
/* this exception is needed for slurphing */
if(start!=0) {
@ -574,33 +610,24 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
switch(cp[1]) {
case IPO_FLOAT:
if(weights) {
memcpy(poin, kref, sizeof(float)*cp[0]);
memcpy(poin, kref, sizeof(float)*3);
if(*weights!=0.0f)
rel_flerp(cp[0], (float *)poin, (float *)kref, (float *)k1, *weights);
weights++;
}
else
memcpy(poin, k1, sizeof(float)*cp[0]);
poin+= ofsp[0];
memcpy(poin, k1, sizeof(float)*3);
break;
case IPO_BPOINT:
memcpy(poin, k1, 3*sizeof(float));
memcpy(poin+4*sizeof(float), k1+3*sizeof(float), sizeof(float));
poin+= ofsp[0];
memcpy(poin, k1, sizeof(float)*4);
break;
case IPO_BEZTRIPLE:
memcpy(poin, k1, sizeof(float)*10);
poin+= ofsp[0];
break;
}
poin+= ofsp[0];
cp+= 2; ofsp++;
}
@ -620,71 +647,63 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
if(mode==KEY_BEZTRIPLE) a+=2;
}
if(freek1) MEM_freeN(freek1);
if(freekref) MEM_freeN(freekref);
}
void cp_cu_key(Curve *cu, KeyBlock *kb, int start, int end)
static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int start, int end, char *out, int tot)
{
Nurb *nu;
int a, step = 0, tot, a1, a2;
char *poin;
int a, step, a1, a2;
tot= count_curveverts(&cu->nurb);
nu= cu->nurb.first;
a= 0;
while(nu) {
for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
if(nu->bp) {
step= nu->pntsu*nu->pntsv;
/* exception because keys prefer to work with complete blocks */
poin= (char *)nu->bp->vec;
poin -= a*sizeof(BPoint);
poin= out - a*sizeof(float)*4;
a1= MAX2(a, start);
a2= MIN2(a+step, end);
if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, NULL, KEY_BPOINT);
if(a1<a2) cp_key(a1, a2, tot, poin, key, actkb, kb, NULL, KEY_BPOINT);
}
else if(nu->bezt) {
step= 3*nu->pntsu;
poin= (char *)nu->bezt->vec;
poin -= a*sizeof(BezTriple);
poin= out - a*sizeof(float)*10;
a1= MAX2(a, start);
a2= MIN2(a+step, end);
if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, NULL, KEY_BEZTRIPLE);
if(a1<a2) cp_key(a1, a2, tot, poin, key, actkb, kb, NULL, KEY_BEZTRIPLE);
}
a+= step;
nu=nu->next;
else
step= 0;
}
}
void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode)
void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock *actkb, int mode)
{
KeyBlock *kb;
int *ofsp, ofs[3], elemsize, b;
char *cp, *poin, *reffrom, *from, elemstr[8];
char *freefrom, *freereffrom;
if(key->from==NULL) return;
if (G.f & G_DEBUG) printf("do_rel_key() \n");
if( GS(key->from->name)==ID_ME ) {
ofs[0]= sizeof(MVert);
ofs[0]= sizeof(float)*3;
ofs[1]= 0;
}
else if( GS(key->from->name)==ID_LT ) {
ofs[0]= sizeof(BPoint);
ofs[0]= sizeof(float)*3;
ofs[1]= 0;
}
else if( GS(key->from->name)==ID_CU ) {
if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
else ofs[0]= sizeof(BezTriple);
if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
else ofs[0]= sizeof(float)*10;
ofs[1]= 0;
}
@ -701,7 +720,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
if(mode==KEY_BEZTRIPLE) elemsize*= 3;
/* step 1 init */
cp_key(start, end, tot, basispoin, key, key->refkey, NULL, mode);
cp_key(start, end, tot, basispoin, key, actkb, key->refkey, NULL, mode);
/* step 2: do it */
@ -709,21 +728,18 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
if(kb!=key->refkey) {
float icuval= kb->curval;
if (G.f & G_DEBUG) printf("\tdo rel key %s : %s = %f \n", key->id.name+2, kb->name, icuval);
/* only with value, and no difference allowed */
if(!(kb->flag & KEYBLOCK_MUTE) && icuval!=0.0f && kb->totelem==tot) {
KeyBlock *refb;
float weight, *weights= kb->weights;
if (G.f & G_DEBUG) printf("\t\tnot skipped \n");
poin= basispoin;
from= kb->data;
/* reference now can be any block */
refb= BLI_findlink(&key->block, kb->relative);
if(refb==NULL) continue;
reffrom= refb->data;
poin= basispoin;
from= key_block_get_data(key, actkb, kb, &freefrom);
reffrom= key_block_get_data(key, actkb, refb, &freereffrom);
poin+= start*ofs[0];
reffrom+= key->elemsize*start; // key elemsize yes!
@ -745,17 +761,13 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
switch(cp[1]) {
case IPO_FLOAT:
rel_flerp(cp[0], (float *)poin, (float *)reffrom, (float *)from, weight);
rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, weight);
break;
case IPO_BPOINT:
rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, icuval);
rel_flerp(1, (float *)(poin+16), (float *)(reffrom+16), (float *)(from+16), icuval);
rel_flerp(4, (float *)poin, (float *)reffrom, (float *)from, weight);
break;
case IPO_BEZTRIPLE:
rel_flerp(9, (float *)poin, (float *)reffrom, (float *)from, icuval);
rel_flerp(10, (float *)poin, (float *)reffrom, (float *)from, weight);
break;
}
@ -771,38 +783,39 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
if(mode==KEY_BEZTRIPLE) b+= 2;
if(weights) weights++;
}
if(freefrom) MEM_freeN(freefrom);
if(freereffrom) MEM_freeN(freereffrom);
}
}
}
}
static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock **k, float *t, int mode)
static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, int mode)
{
float k1tot = 0.0, k2tot = 0.0, k3tot = 0.0, k4tot = 0.0;
float k1d = 0.0, k2d = 0.0, k3d = 0.0, k4d = 0.0;
int a, ofs[32], *ofsp;
int flagdo= 15, flagflo=0, elemsize, poinsize=0;
char *k1, *k2, *k3, *k4;
char *k1, *k2, *k3, *k4, *freek1, *freek2, *freek3, *freek4;
char *cp, elemstr[8];;
if(key->from==0) return;
if (G.f & G_DEBUG) printf("do_key() \n");
if( GS(key->from->name)==ID_ME ) {
ofs[0]= sizeof(MVert);
ofs[0]= sizeof(float)*3;
ofs[1]= 0;
poinsize= ofs[0];
}
else if( GS(key->from->name)==ID_LT ) {
ofs[0]= sizeof(BPoint);
ofs[0]= sizeof(float)*3;
ofs[1]= 0;
poinsize= ofs[0];
}
else if( GS(key->from->name)==ID_CU ) {
if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
else ofs[0]= sizeof(BezTriple);
if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
else ofs[0]= sizeof(float)*10;
ofs[1]= 0;
poinsize= ofs[0];
@ -810,10 +823,10 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
if(end>tot) end= tot;
k1= k[0]->data;
k2= k[1]->data;
k3= k[2]->data;
k4= k[3]->data;
k1= key_block_get_data(key, actkb, k[0], &freek1);
k2= key_block_get_data(key, actkb, k[1], &freek2);
k3= key_block_get_data(key, actkb, k[2], &freek3);
k4= key_block_get_data(key, actkb, k[3], &freek4);
/* test for more or less points (per key!) */
if(tot != k[0]->totelem) {
@ -921,26 +934,17 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
switch(cp[1]) {
case IPO_FLOAT:
flerp(cp[0], (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
poin+= ofsp[0];
flerp(3, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
break;
case IPO_BPOINT:
flerp(3, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
flerp(1, (float *)(poin+16), (float *)(k1+12), (float *)(k2+12), (float *)(k3+12), (float *)(k4+12), t);
poin+= ofsp[0];
flerp(4, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
break;
case IPO_BEZTRIPLE:
flerp(9, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
flerp(1, (float *)(poin+36), (float *)(k1+36), (float *)(k2+36), (float *)(k3+36), (float *)(k4+36), t);
poin+= ofsp[0];
flerp(10, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
break;
}
poin+= ofsp[0];
cp+= 2;
ofsp++;
}
@ -988,6 +992,11 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
if(mode==KEY_BEZTRIPLE) a+= 2;
}
if(freek1) MEM_freeN(freek1);
if(freek2) MEM_freeN(freek2);
if(freek3) MEM_freeN(freek3);
if(freek4) MEM_freeN(freek4);
}
static float *get_weights_array(Object *ob, char *vgroup)
@ -1037,41 +1046,30 @@ static float *get_weights_array(Object *ob, char *vgroup)
return NULL;
}
static int do_mesh_key(Scene *scene, Object *ob, Mesh *me)
static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
{
KeyBlock *k[4];
float cfra, ctime, t[4], delta, loc[3], size[3];
KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
float cfra, ctime, t[4], delta;
int a, flag = 0, step;
if(me->totvert==0) return 0;
if(me->key==NULL) return 0;
if(me->key->block.first==NULL) return 0;
/* prevent python from screwing this up? anyhoo, the from pointer could be dropped */
me->key->from= (ID *)me;
if (G.f & G_DEBUG) printf("do mesh key ob:%s me:%s ke:%s \n", ob->id.name+2, me->id.name+2, me->key->id.name+2);
if(me->key->slurph && me->key->type!=KEY_RELATIVE ) {
if (G.f & G_DEBUG) printf("\tslurph key\n");
delta= me->key->slurph;
delta/= me->totvert;
if(key->slurph && key->type!=KEY_RELATIVE ) {
delta= key->slurph;
delta/= tot;
step= 1;
if(me->totvert>100 && slurph_opt) {
step= me->totvert/50;
if(tot>100 && slurph_opt) {
step= tot/50;
delta*= step;
/* in do_key and cp_key the case a>tot is handled */
}
cfra= (float)scene->r.cfra;
for(a=0; a<me->totvert; a+=step, cfra+= delta) {
for(a=0; a<tot; a+=step, cfra+= delta) {
ctime= bsystem_time(scene, 0, cfra, 0.0); // xxx ugly cruft!
#if 0 // XXX old animation system
if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
}
@ -1080,42 +1078,33 @@ static int do_mesh_key(Scene *scene, Object *ob, Mesh *me)
ctime /= 100.0f;
CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing
flag= setkeys(ctime, &me->key->block, k, t, 0);
if(flag==0) {
do_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k, t, 0);
}
else {
cp_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k[2], NULL, 0);
}
flag= setkeys(ctime, &key->block, k, t, 0);
if(flag==0)
do_key(a, a+step, tot, (char *)out, key, actkb, k, t, 0);
else
cp_key(a, a+step, tot, (char *)out, key, actkb, k[2], NULL, 0);
}
if(flag && k[2]==me->key->refkey) tex_space_mesh(me);
else boundbox_mesh(me, loc, size);
}
else {
if(me->key->type==KEY_RELATIVE) {
if(key->type==KEY_RELATIVE) {
KeyBlock *kb;
if (G.f & G_DEBUG) printf("\tdo relative \n");
for(kb= me->key->block.first; kb; kb= kb->next)
for(kb= key->block.first; kb; kb= kb->next)
kb->weights= get_weights_array(ob, kb->vgroup);
do_rel_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, 0);
do_rel_key(0, tot, tot, (char *)out, key, actkb, 0);
for(kb= me->key->block.first; kb; kb= kb->next) {
for(kb= key->block.first; kb; kb= kb->next) {
if(kb->weights) MEM_freeN(kb->weights);
kb->weights= NULL;
}
}
else {
if (G.f & G_DEBUG) printf("\tdo absolute \n");
ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0f); // xxx old cruft
#if 0 // XXX old animation system
if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
}
@ -1124,106 +1113,69 @@ static int do_mesh_key(Scene *scene, Object *ob, Mesh *me)
ctime /= 100.0f;
CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing
flag= setkeys(ctime, &me->key->block, k, t, 0);
if(flag==0) {
do_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k, t, 0);
}
else {
cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k[2], NULL, 0);
}
if(flag && k[2]==me->key->refkey) tex_space_mesh(me);
else boundbox_mesh(me, loc, size);
flag= setkeys(ctime, &key->block, k, t, 0);
if(flag==0)
do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0);
else
cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0);
}
}
return 1;
}
static void do_cu_key(Curve *cu, KeyBlock **k, float *t)
static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, int tot)
{
Nurb *nu;
int a, step = 0, tot;
char *poin;
int a, step;
tot= count_curveverts(&cu->nurb);
nu= cu->nurb.first;
a= 0;
while(nu) {
for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
if(nu->bp) {
step= nu->pntsu*nu->pntsv;
/* exception because keys prefer to work with complete blocks */
poin= (char *)nu->bp->vec;
poin -= a*sizeof(BPoint);
do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BPOINT);
poin= out - a*sizeof(float)*4;
do_key(a, a+step, tot, poin, key, actkb, k, t, KEY_BPOINT);
}
else if(nu->bezt) {
step= 3*nu->pntsu;
poin= (char *)nu->bezt->vec;
poin -= a*sizeof(BezTriple);
do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BEZTRIPLE);
poin= out - a*sizeof(float)*10;
do_key(a, a+step, tot, poin, key, actkb, k, t, KEY_BEZTRIPLE);
}
a+= step;
nu=nu->next;
else
step= 0;
}
}
static void do_rel_cu_key(Curve *cu, float ctime)
static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float ctime, char *out, int tot)
{
Nurb *nu;
int a, step = 0, tot;
char *poin;
int a, step;
tot= count_curveverts(&cu->nurb);
nu= cu->nurb.first;
a= 0;
while(nu) {
for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
if(nu->bp) {
step= nu->pntsu*nu->pntsv;
/* exception because keys prefer to work with complete blocks */
poin= (char *)nu->bp->vec;
poin -= a*sizeof(BPoint);
do_rel_key(a, a+step, tot, poin, cu->key, KEY_BPOINT);
poin= out - a*sizeof(float)*3;
do_rel_key(a, a+step, tot, out, key, actkb, KEY_BPOINT);
}
else if(nu->bezt) {
step= 3*nu->pntsu;
poin= (char *)nu->bezt->vec;
poin -= a*sizeof(BezTriple);
do_rel_key(a, a+step, tot, poin, cu->key, KEY_BEZTRIPLE);
poin= out - a*sizeof(float)*10;
do_rel_key(a, a+step, tot, poin, key, actkb, KEY_BEZTRIPLE);
}
a+= step;
nu=nu->next;
else
step= 0;
}
}
static int do_curve_key(Scene *scene, Curve *cu)
static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
{
KeyBlock *k[4];
Curve *cu= ob->data;
KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
float cfra, ctime, t[4], delta;
int a, flag = 0, step = 0, tot;
int a, flag = 0, step = 0;
tot= count_curveverts(&cu->nurb);
if(tot==0) return 0;
if(cu->key==NULL) return 0;
if(cu->key->block.first==NULL) return 0;
if(cu->key->slurph) {
delta= cu->key->slurph;
if(key->slurph) {
delta= key->slurph;
delta/= tot;
step= 1;
@ -1238,66 +1190,52 @@ static int do_curve_key(Scene *scene, Curve *cu)
for(a=0; a<tot; a+=step, cfra+= delta) {
ctime= bsystem_time(scene, 0, cfra, 0.0f); // XXX old cruft
#if 0 // XXX old animation system
if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) {
if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
}
#endif // XXX old animation system
flag= setkeys(ctime, &cu->key->block, k, t, 0);
if(flag==0) {
/* do_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k, t, 0); */
}
else {
/* cp_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k[2],0); */
}
}
flag= setkeys(ctime, &key->block, k, t, 0);
if(flag && k[2]==cu->key->refkey) tex_space_curve(cu);
if(flag==0)
; /* do_key(a, a+step, tot, (char *)out, key, k, t, 0); */
else
; /* cp_key(a, a+step, tot, (char *)out, key, k[2],0); */
}
}
else {
ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0);
if(cu->key->type==KEY_RELATIVE) {
do_rel_cu_key(cu, ctime);
if(key->type==KEY_RELATIVE) {
do_rel_cu_key(cu, cu->key, actkb, ctime, out, tot);
}
else {
#if 0 // XXX old animation system
if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) {
if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
}
#endif // XXX old animation system
flag= setkeys(ctime, &cu->key->block, k, t, 0);
flag= setkeys(ctime, &key->block, k, t, 0);
if(flag==0) do_cu_key(cu, k, t);
else cp_cu_key(cu, k[2], 0, tot);
if(flag && k[2]==cu->key->refkey) tex_space_curve(cu);
if(flag==0) do_cu_key(cu, key, actkb, k, t, out, tot);
else cp_cu_key(cu, key, actkb, k[2], 0, tot, out, tot);
}
}
return 1;
}
static int do_latt_key(Scene *scene, Object *ob, Lattice *lt)
static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
{
KeyBlock *k[4];
Lattice *lt= ob->data;
KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
float delta, cfra, ctime, t[4];
int a, tot, flag;
int a, flag;
if(lt->key==NULL) return 0;
if(lt->key->block.first==NULL) return 0;
tot= lt->pntsu*lt->pntsv*lt->pntsw;
if(lt->key->slurph) {
delta= lt->key->slurph;
if(key->slurph) {
delta= key->slurph;
delta/= (float)tot;
cfra= (float)scene->r.cfra;
@ -1306,74 +1244,110 @@ static int do_latt_key(Scene *scene, Object *ob, Lattice *lt)
ctime= bsystem_time(scene, 0, cfra, 0.0); // XXX old cruft
#if 0 // XXX old animation system
if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
}
#endif // XXX old animation system
flag= setkeys(ctime, &lt->key->block, k, t, 0);
if(flag==0) {
do_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k, t, 0);
}
else {
cp_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k[2], NULL, 0);
}
flag= setkeys(ctime, &key->block, k, t, 0);
if(flag==0)
do_key(a, a+1, tot, (char *)out, key, actkb, k, t, 0);
else
cp_key(a, a+1, tot, (char *)out, key, actkb, k[2], NULL, 0);
}
}
else {
ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0);
if(lt->key->type==KEY_RELATIVE) {
if(key->type==KEY_RELATIVE) {
KeyBlock *kb;
for(kb= lt->key->block.first; kb; kb= kb->next)
for(kb= key->block.first; kb; kb= kb->next)
kb->weights= get_weights_array(ob, kb->vgroup);
do_rel_key(0, tot, tot, (char *)lt->def->vec, lt->key, 0);
do_rel_key(0, tot, tot, (char *)out, key, actkb, 0);
for(kb= lt->key->block.first; kb; kb= kb->next) {
for(kb= key->block.first; kb; kb= kb->next) {
if(kb->weights) MEM_freeN(kb->weights);
kb->weights= NULL;
}
}
else {
ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0);
#if 0 // XXX old animation system
if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
}
#endif // XXX old animation system
flag= setkeys(ctime, &lt->key->block, k, t, 0);
if(flag==0) {
do_key(0, tot, tot, (char *)lt->def->vec, lt->key, k, t, 0);
}
else {
cp_key(0, tot, tot, (char *)lt->def->vec, lt->key, k[2], NULL, 0);
}
flag= setkeys(ctime, &key->block, k, t, 0);
if(flag==0)
do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0);
else
cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0);
}
}
if(lt->flag & LT_OUTSIDE) outside_lattice(lt);
return 1;
}
/* returns 1 when key applied */
int do_ob_key(Scene *scene, Object *ob)
/* returns key coordinates (+ tilt) when key applied, NULL otherwise */
float *do_ob_key(Scene *scene, Object *ob)
{
Key *key= ob_get_key(ob);
KeyBlock *actkb= ob_get_keyblock(ob);
char *out;
int tot= 0, size= 0;
if(key==NULL)
return 0;
if(key==NULL || key->block.first==NULL)
return NULL;
/* compute size of output array */
if(ob->type == OB_MESH) {
Mesh *me= ob->data;
tot= me->totvert;
size= tot*3*sizeof(float);
}
else if(ob->type == OB_LATTICE) {
Lattice *lt= ob->data;
tot= lt->pntsu*lt->pntsv*lt->pntsw;
size= tot*3*sizeof(float);
}
else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu= ob->data;
Nurb *nu;
for(nu=cu->nurb.first; nu; nu=nu->next) {
if(nu->bezt) {
tot += 3*nu->pntsu;
size += nu->pntsu*10*sizeof(float);
}
else if(nu->bp) {
tot += nu->pntsu*nu->pntsv;
size += nu->pntsu*nu->pntsv*10*sizeof(float);
}
}
}
/* if nothing to interpolate, cancel */
if(tot == 0 || size == 0)
return NULL;
/* allocate array */
out= MEM_callocN(size, "do_ob_key out");
/* prevent python from screwing this up? anyhoo, the from pointer could be dropped */
key->from= (ID *)ob->data;
if(ob->shapeflag & OB_SHAPE_LOCK) {
/* shape locked, copy the locked shape instead of blending */
KeyBlock *kb= BLI_findlink(&key->block, ob->shapenr-1);
if (G.f & G_DEBUG) printf("ob %s, key %s locked \n", ob->id.name+2, key->id.name+2);
if(kb && (kb->flag & KEYBLOCK_MUTE))
kb= key->refkey;
@ -1382,46 +1356,29 @@ int do_ob_key(Scene *scene, Object *ob)
ob->shapenr= 1;
}
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
if(ELEM(ob->type, OB_MESH, OB_LATTICE)) {
float *weights= get_weights_array(ob, kb->vgroup);
cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, key, kb, weights, 0);
cp_key(0, tot, tot, (char*)out, key, actkb, kb, weights, 0);
if(weights) MEM_freeN(weights);
}
else if(ob->type==OB_LATTICE) {
Lattice *lt= ob->data;
float *weights= get_weights_array(ob, kb->vgroup);
int tot= lt->pntsu*lt->pntsv*lt->pntsw;
cp_key(0, tot, tot, (char *)lt->def->vec, key, kb, weights, 0);
if(weights) MEM_freeN(weights);
}
else if ELEM(ob->type, OB_CURVE, OB_SURF) {
Curve *cu= ob->data;
int tot= count_curveverts(&cu->nurb);
cp_cu_key(cu, kb, 0, tot);
}
return 1;
else if(ELEM(ob->type, OB_CURVE, OB_SURF))
cp_cu_key(ob->data, key, actkb, kb, 0, tot, out, tot);
}
else {
/* do shapekey local drivers */
float ctime= (float)scene->r.cfra; // XXX this needs to be checked
if (G.f & G_DEBUG)
printf("ob %s - do shapekey (%s) drivers \n", ob->id.name+2, key->id.name+2);
BKE_animsys_evaluate_animdata(&key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
if(ob->type==OB_MESH) return do_mesh_key(scene, ob, ob->data);
else if(ob->type==OB_CURVE) return do_curve_key(scene, ob->data);
else if(ob->type==OB_SURF) return do_curve_key(scene, ob->data);
else if(ob->type==OB_LATTICE) return do_latt_key(scene, ob, ob->data);
if(ob->type==OB_MESH) do_mesh_key(scene, ob, key, out, tot);
else if(ob->type==OB_LATTICE) do_latt_key(scene, ob, key, out, tot);
else if(ob->type==OB_CURVE) do_curve_key(scene, ob, key, out, tot);
else if(ob->type==OB_SURF) do_curve_key(scene, ob, key, out, tot);
}
return 0;
return (float*)out;
}
Key *ob_get_key(Object *ob)
@ -1490,3 +1447,24 @@ KeyBlock *key_get_named_keyblock(Key *key, const char name[])
return NULL;
}
/* Get RNA-Path for 'value' setting of the given ShapeKey
* NOTE: the user needs to free the returned string once they're finishe with it
*/
char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb)
{
PointerRNA ptr;
PropertyRNA *prop;
/* sanity checks */
if ELEM(NULL, key, kb)
return NULL;
/* create the RNA pointer */
RNA_pointer_create(&key->id, &RNA_ShapeKey, kb, &ptr);
/* get pointer to the property too */
prop= RNA_struct_find_property(&ptr, "value");
/* return the path */
return RNA_path_from_ID_to_property(&ptr, prop);
}

View File

@ -996,10 +996,6 @@ void lattice_calc_modifiers(Scene *scene, Object *ob)
freedisplist(&ob->disp);
if (!editmode) {
do_ob_key(scene, ob);
}
for (; md; md=md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);

View File

@ -485,6 +485,18 @@ ID *material_from(Object *ob, int act)
else return ob->data;
}
Material *give_node_material(Material *ma)
{
if(ma && ma->use_nodes && ma->nodetree) {
bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
if(node)
return (Material *)node->id;
}
return NULL;
}
/* GS reads the memory pointed at in a specific ordering. There are,
* however two definitions for it. I have jotted them down here, both,
* but I think the first one is actually used. The thing is that
@ -982,7 +994,7 @@ int object_remove_material_slot(Object *ob)
/* if g==NULL, it only does r channel */
void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
{
float tmp, facm= 1.0-fac;
float tmp, facm= 1.0f-fac;
switch (type) {
case MA_RAMP_BLEND:
@ -1007,26 +1019,26 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
}
break;
case MA_RAMP_SCREEN:
*r = 1.0 - (facm + fac*(1.0 - col[0])) * (1.0 - *r);
*r = 1.0f - (facm + fac*(1.0f - col[0])) * (1.0f - *r);
if(g) {
*g = 1.0 - (facm + fac*(1.0 - col[1])) * (1.0 - *g);
*b = 1.0 - (facm + fac*(1.0 - col[2])) * (1.0 - *b);
*g = 1.0f - (facm + fac*(1.0f - col[1])) * (1.0f - *g);
*b = 1.0f - (facm + fac*(1.0f - col[2])) * (1.0f - *b);
}
break;
case MA_RAMP_OVERLAY:
if(*r < 0.5f)
*r *= (facm + 2.0f*fac*col[0]);
else
*r = 1.0 - (facm + 2.0f*fac*(1.0 - col[0])) * (1.0 - *r);
*r = 1.0f - (facm + 2.0f*fac*(1.0f - col[0])) * (1.0f - *r);
if(g) {
if(*g < 0.5f)
*g *= (facm + 2.0f*fac*col[1]);
else
*g = 1.0 - (facm + 2.0f*fac*(1.0 - col[1])) * (1.0 - *g);
*g = 1.0f - (facm + 2.0f*fac*(1.0f - col[1])) * (1.0f - *g);
if(*b < 0.5f)
*b *= (facm + 2.0f*fac*col[2]);
else
*b = 1.0 - (facm + 2.0f*fac*(1.0 - col[2])) * (1.0 - *b);
*b = 1.0f - (facm + 2.0f*fac*(1.0f - col[2])) * (1.0f - *b);
}
break;
case MA_RAMP_SUB:
@ -1037,12 +1049,12 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
}
break;
case MA_RAMP_DIV:
if(col[0]!=0.0)
if(col[0]!=0.0f)
*r = facm*(*r) + fac*(*r)/col[0];
if(g) {
if(col[1]!=0.0)
if(col[1]!=0.0f)
*g = facm*(*g) + fac*(*g)/col[1];
if(col[2]!=0.0)
if(col[2]!=0.0f)
*b = facm*(*b) + fac*(*b)/col[2];
}
break;
@ -1076,31 +1088,31 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
case MA_RAMP_DODGE:
if(*r !=0.0){
tmp = 1.0 - fac*col[0];
if(tmp <= 0.0)
*r = 1.0;
else if ((tmp = (*r) / tmp)> 1.0)
*r = 1.0;
if(*r !=0.0f){
tmp = 1.0f - fac*col[0];
if(tmp <= 0.0f)
*r = 1.0f;
else if ((tmp = (*r) / tmp)> 1.0f)
*r = 1.0f;
else
*r = tmp;
}
if(g) {
if(*g !=0.0){
tmp = 1.0 - fac*col[1];
if(tmp <= 0.0 )
*g = 1.0;
else if ((tmp = (*g) / tmp) > 1.0 )
*g = 1.0;
if(*g !=0.0f){
tmp = 1.0f - fac*col[1];
if(tmp <= 0.0f )
*g = 1.0f;
else if ((tmp = (*g) / tmp) > 1.0f )
*g = 1.0f;
else
*g = tmp;
}
if(*b !=0.0){
tmp = 1.0 - fac*col[2];
if(tmp <= 0.0)
*b = 1.0;
else if ((tmp = (*b) / tmp) > 1.0 )
*b = 1.0;
if(*b !=0.0f){
tmp = 1.0f - fac*col[2];
if(tmp <= 0.0f)
*b = 1.0f;
else if ((tmp = (*b) / tmp) > 1.0f )
*b = 1.0f;
else
*b = tmp;
}
@ -1111,33 +1123,33 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
tmp = facm + fac*col[0];
if(tmp <= 0.0)
*r = 0.0;
else if (( tmp = (1.0 - (1.0 - (*r)) / tmp )) < 0.0)
*r = 0.0;
else if (tmp > 1.0)
*r=1.0;
if(tmp <= 0.0f)
*r = 0.0f;
else if (( tmp = (1.0f - (1.0f - (*r)) / tmp )) < 0.0f)
*r = 0.0f;
else if (tmp > 1.0f)
*r=1.0f;
else
*r = tmp;
if(g) {
tmp = facm + fac*col[1];
if(tmp <= 0.0)
*g = 0.0;
else if (( tmp = (1.0 - (1.0 - (*g)) / tmp )) < 0.0 )
*g = 0.0;
else if(tmp >1.0)
*g=1.0;
if(tmp <= 0.0f)
*g = 0.0f;
else if (( tmp = (1.0f - (1.0f - (*g)) / tmp )) < 0.0f )
*g = 0.0f;
else if(tmp >1.0f)
*g=1.0f;
else
*g = tmp;
tmp = facm + fac*col[2];
if(tmp <= 0.0)
*b = 0.0;
else if (( tmp = (1.0 - (1.0 - (*b)) / tmp )) < 0.0 )
*b = 0.0;
else if(tmp >1.0)
*b= 1.0;
if(tmp <= 0.0f)
*b = 0.0f;
else if (( tmp = (1.0f - (1.0f - (*b)) / tmp )) < 0.0f )
*b = 0.0f;
else if(tmp >1.0f)
*b= 1.0f;
else
*b = tmp;
}
@ -1197,29 +1209,29 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
float scr, scg, scb;
/* first calculate non-fac based Screen mix */
scr = 1.0 - ((1.0 - col[0])) * (1.0 - *r);
scg = 1.0 - ((1.0 - col[1])) * (1.0 - *g);
scb = 1.0 - ((1.0 - col[2])) * (1.0 - *b);
scr = 1.0f - (1.0f - col[0]) * (1.0f - *r);
scg = 1.0f - (1.0f - col[1]) * (1.0f - *g);
scb = 1.0f - (1.0f - col[2]) * (1.0f - *b);
*r = facm*(*r) + fac*(((1.0 - *r) * col[0] * (*r)) + (*r * scr));
*g = facm*(*g) + fac*(((1.0 - *g) * col[1] * (*g)) + (*g * scg));
*b = facm*(*b) + fac*(((1.0 - *b) * col[2] * (*b)) + (*b * scb));
*r = facm*(*r) + fac*(((1.0f - *r) * col[0] * (*r)) + (*r * scr));
*g = facm*(*g) + fac*(((1.0f - *g) * col[1] * (*g)) + (*g * scg));
*b = facm*(*b) + fac*(((1.0f - *b) * col[2] * (*b)) + (*b * scb));
}
break;
case MA_RAMP_LINEAR:
if (col[0] > 0.5)
*r = *r + fac*(2*(col[0]-0.5));
if (col[0] > 0.5f)
*r = *r + fac*(2.0f*(col[0]-0.5f));
else
*r = *r + fac*(2*(col[0]) - 1);
*r = *r + fac*(2.0f*(col[0]) - 1.0f);
if (g){
if (col[1] > 0.5)
*g = *g + fac*(2*(col[1]-0.5));
if (col[1] > 0.5f)
*g = *g + fac*(2.0f*(col[1]-0.5f));
else
*g = *g + fac*(2*(col[1]) -1);
if (col[2] > 0.5)
*b = *b + fac*(2*(col[2]-0.5));
*g = *g + fac*(2.0f*(col[1]) -1.0f);
if (col[2] > 0.5f)
*b = *b + fac*(2.0f*(col[2]-0.5f));
else
*b = *b + fac*(2*(col[2]) - 1);
*b = *b + fac*(2.0f*(col[2]) - 1.0f);
}
break;
}

View File

@ -345,14 +345,14 @@ Mesh *copy_mesh(Mesh *me)
return men;
}
BMesh *BKE_mesh_to_bmesh(Mesh *me)
BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob)
{
BMesh *bm;
int allocsize[4] = {512,512,2048,512};
bm = BM_Make_Mesh(allocsize);
BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p", me);
BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p object=%p", me, ob);
return bm;
}
@ -496,35 +496,12 @@ void boundbox_mesh(Mesh *me, float *loc, float *size)
void tex_space_mesh(Mesh *me)
{
KeyBlock *kb;
float *fp, loc[3], size[3], min[3], max[3];
float loc[3], size[3];
int a;
boundbox_mesh(me, loc, size);
if(me->texflag & AUTOSPACE) {
if(me->key) {
kb= me->key->refkey;
if (kb) {
INIT_MINMAX(min, max);
fp= kb->data;
for(a=0; a<kb->totelem; a++, fp+=3) {
DO_MINMAX(fp, min, max);
}
if(kb->totelem) {
loc[0]= (min[0]+max[0])/2.0f; loc[1]= (min[1]+max[1])/2.0f; loc[2]= (min[2]+max[2])/2.0f;
size[0]= (max[0]-min[0])/2.0f; size[1]= (max[1]-min[1])/2.0f; size[2]= (max[2]-min[2])/2.0f;
}
else {
loc[0]= loc[1]= loc[2]= 0.0;
size[0]= size[1]= size[2]= 0.0;
}
}
}
for (a=0; a<3; a++) {
if(size[a]==0.0) size[a]= 1.0;
else if(size[a]>0.0 && size[a]<0.00001) size[a]= 0.00001;
@ -564,26 +541,20 @@ void mesh_get_texspace(Mesh *me, float *loc_r, float *rot_r, float *size_r)
float *get_mesh_orco_verts(Object *ob)
{
Mesh *me = ob->data;
MVert *mvert = NULL;
Mesh *tme = me->texcomesh?me->texcomesh:me;
int a, totvert;
float (*vcos)[3] = NULL;
/* Get appropriate vertex coordinates */
if(me->key && me->texcomesh==0 && me->key->refkey) {
vcos= mesh_getRefKeyCos(me, &totvert);
}
else {
MVert *mvert = NULL;
Mesh *tme = me->texcomesh?me->texcomesh:me;
vcos = MEM_callocN(sizeof(*vcos)*me->totvert, "orco mesh");
mvert = tme->mvert;
totvert = MIN2(tme->totvert, me->totvert);
vcos = MEM_callocN(sizeof(*vcos)*me->totvert, "orco mesh");
mvert = tme->mvert;
totvert = MIN2(tme->totvert, me->totvert);
for(a=0; a<totvert; a++, mvert++) {
vcos[a][0]= mvert->co[0];
vcos[a][1]= mvert->co[1];
vcos[a][2]= mvert->co[2];
}
for(a=0; a<totvert; a++, mvert++) {
vcos[a][0]= mvert->co[0];
vcos[a][1]= mvert->co[1];
vcos[a][2]= mvert->co[2];
}
return (float*)vcos;
@ -1354,29 +1325,6 @@ float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3]
return cos;
}
float (*mesh_getRefKeyCos(Mesh *me, int *numVerts_r))[3]
{
KeyBlock *kb;
float (*cos)[3] = NULL;
int totvert;
if(me->key && me->key->refkey) {
if(numVerts_r) *numVerts_r= me->totvert;
kb= me->key->refkey;
/* prevent accessing invalid memory */
if (me->totvert > kb->totelem) cos= MEM_callocN(sizeof(*cos)*me->totvert, "vertexcos1");
else cos= MEM_mallocN(sizeof(*cos)*me->totvert, "vertexcos1");
totvert= MIN2(kb->totelem, me->totvert);
memcpy(cos, kb->data, sizeof(*cos)*totvert);
}
return cos;
}
UvVertMap *make_uv_vert_map(struct MFace *mface, struct MTFace *tface, unsigned int totface, unsigned int totvert, int selected, float *limit)
{
UvVertMap *vmap;

View File

@ -64,6 +64,7 @@
#include "DNA_curve_types.h"
#include "DNA_effect_types.h"
#include "DNA_group_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@ -96,6 +97,7 @@
#include "BKE_fluidsim.h"
#include "BKE_global.h"
#include "BKE_multires.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_material.h"
@ -1196,9 +1198,9 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
/* need to avoid infinite recursion here */
if(amd->start_cap && amd->start_cap != ob)
start_cap = mesh_get_derived_final(scene, amd->start_cap, CD_MASK_MESH);
start_cap = amd->start_cap->derivedFinal;
if(amd->end_cap && amd->end_cap != ob)
end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH);
end_cap = amd->end_cap->derivedFinal;
Mat4One(offset);
@ -5549,7 +5551,7 @@ static DerivedMesh *booleanModifier_applyModifier(
{
// XXX doesn't handle derived data
BooleanModifierData *bmd = (BooleanModifierData*) md;
DerivedMesh *dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_BAREMESH);
DerivedMesh *dm = bmd->object->derivedFinal;
/* we do a quick sanity check */
if(dm && (derivedData->getNumTessFaces(derivedData) > 3)
@ -7536,6 +7538,52 @@ static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, BME
dm->release(dm);
}
/* Shape Key */
static void shapekeyModifier_deformVerts(
ModifierData *md, Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
{
KeyBlock *kb= ob_get_keyblock(ob);
float (*deformedVerts)[3];
if(kb && kb->totelem == numVerts) {
deformedVerts= (float(*)[3])do_ob_key(md->scene, ob);
if(deformedVerts) {
memcpy(vertexCos, deformedVerts, sizeof(float)*3*numVerts);
MEM_freeN(deformedVerts);
}
}
}
static void shapekeyModifier_deformVertsEM(
ModifierData *md, Object *ob, EditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
Key *key= ob_get_key(ob);
if(key && key->type == KEY_RELATIVE)
shapekeyModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0);
}
static void shapekeyModifier_deformMatricesEM(
ModifierData *md, Object *ob, EditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3],
float (*defMats)[3][3], int numVerts)
{
Key *key= ob_get_key(ob);
KeyBlock *kb= ob_get_keyblock(ob);
float scale[3][3];
int a;
if(kb && kb->totelem==numVerts && kb!=key->refkey) {
Mat3Scale(scale, kb->curval);
for(a=0; a<numVerts; a++)
Mat3CpyMat3(defMats[a], scale);
}
}
/***/
static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES];
@ -7940,6 +7988,14 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->copyData = multiresModifier_copyData;
mti->applyModifier = multiresModifier_applyModifier;
mti = INIT_TYPE(ShapeKey);
mti->type = eModifierTypeType_OnlyDeform;
mti->flags = eModifierTypeFlag_AcceptsCVs
| eModifierTypeFlag_SupportsEditmode;
mti->deformVerts = shapekeyModifier_deformVerts;
mti->deformVertsEM = shapekeyModifier_deformVertsEM;
mti->deformMatricesEM = shapekeyModifier_deformMatricesEM;
typeArrInit = 0;
#undef INIT_TYPE
}
@ -8104,9 +8160,9 @@ void modifier_setError(ModifierData *md, char *format, ...)
* also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg
* then is NULL)
*/
int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r)
int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r, int virtual_)
{
ModifierData *md = ob->modifiers.first;
ModifierData *md = (virtual_)? modifiers_getVirtualModifierList(ob): ob->modifiers.first;
int i, cageIndex = -1;
/* Find the last modifier acting on the cage. */
@ -8215,11 +8271,11 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
static ArmatureModifierData amd;
static CurveModifierData cmd;
static LatticeModifierData lmd;
static ShapeKeyModifierData smd;
static int init = 1;
ModifierData *md;
if (init) {
ModifierData *md;
md = modifier_new(eModifierType_Armature);
amd = *((ArmatureModifierData*) md);
modifier_free(md);
@ -8232,32 +8288,50 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
lmd = *((LatticeModifierData*) md);
modifier_free(md);
md = modifier_new(eModifierType_ShapeKey);
smd = *((ShapeKeyModifierData*) md);
modifier_free(md);
amd.modifier.mode |= eModifierMode_Virtual;
cmd.modifier.mode |= eModifierMode_Virtual;
lmd.modifier.mode |= eModifierMode_Virtual;
smd.modifier.mode |= eModifierMode_Virtual;
init = 0;
}
if (ob->parent) {
md = ob->modifiers.first;
if(ob->parent) {
if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) {
amd.object = ob->parent;
amd.modifier.next = ob->modifiers.first;
amd.modifier.next = md;
amd.deformflag= ((bArmature *)(ob->parent->data))->deformflag;
return &amd.modifier;
md = &amd.modifier;
} else if(ob->parent->type==OB_CURVE && ob->partype==PARSKEL) {
cmd.object = ob->parent;
cmd.defaxis = ob->trackflag + 1;
cmd.modifier.next = ob->modifiers.first;
return &cmd.modifier;
cmd.modifier.next = md;
md = &cmd.modifier;
} else if(ob->parent->type==OB_LATTICE && ob->partype==PARSKEL) {
lmd.object = ob->parent;
lmd.modifier.next = ob->modifiers.first;
return &lmd.modifier;
lmd.modifier.next = md;
md = &lmd.modifier;
}
}
return ob->modifiers.first;
/* shape key modifier, not yet for curves */
if(ELEM(ob->type, OB_MESH, OB_LATTICE) && ob_get_key(ob)) {
if(ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
smd.modifier.mode |= eModifierMode_Editmode|eModifierMode_OnCage;
else
smd.modifier.mode &= ~eModifierMode_Editmode|eModifierMode_OnCage;
smd.modifier.next = md;
md = &smd.modifier;
}
return md;
}
/* Takes an object and returns its first selected armature, else just its
* armature
@ -8334,6 +8408,8 @@ int modifier_isDeformer(ModifierData *md)
return 1;
if (md->type==eModifierType_Lattice)
return 1;
if (md->type==eModifierType_ShapeKey)
return 1;
return 0;
}

View File

@ -1198,6 +1198,8 @@ static void node_init_preview(bNode *node, int xsize, int ysize)
node->preview->xsize= xsize;
node->preview->ysize= ysize;
}
else
memset(node->preview->rect, 0, 4*xsize + xsize*ysize*sizeof(float)*4);
}
void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize)

View File

@ -1134,6 +1134,8 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
psysn->pathcache= NULL;
psysn->childcache= NULL;
psysn->edit= NULL;
psysn->frand= NULL;
psysn->pdd= NULL;
psysn->pathcachebufs.first = psysn->pathcachebufs.last = NULL;
psysn->childcachebufs.first = psysn->childcachebufs.last = NULL;

View File

@ -29,6 +29,7 @@
#include "DNA_brush_types.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_scene_types.h"
#include "BKE_brush.h"
@ -160,8 +161,7 @@ void paint_brush_slot_remove(Paint *p)
int paint_facesel_test(Object *ob)
{
return (G.f&G_FACESELECT) && (ob && (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT)));
return (ob && ob->data && (((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_MASK) && (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT)));
}
void paint_init(Paint *p, const char col[3])

View File

@ -2278,15 +2278,20 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
ParticleSettings *part = psys->part;
ParticleEditSettings *pset = &scene->toolsettings->particle;
int totparent=0, between=0;
int steps = (int)pow(2.0,(double)part->draw_step);
int steps = (int)pow(2.0, (double)part->draw_step);
int totchild = psys->totchild;
int i, seed, totthread= threads[0].tot;
/*---start figuring out what is actually wanted---*/
if(psys_in_edit_mode(scene, psys))
if(psys_in_edit_mode(scene, psys)) {
ParticleEditSettings *pset = &scene->toolsettings->particle;
if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0)
totchild=0;
steps = (int)pow(2.0, (double)pset->draw_step);
}
if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
totparent=(int)(totchild*part->parents*0.3);
@ -2361,7 +2366,7 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
ParticleSystem *psys = ctx->sim.psys;
ParticleSettings *part = psys->part;
ParticleCacheKey **cache= psys->childcache;
ParticleCacheKey **pcache= psys->pathcache;
ParticleCacheKey **pcache= psys_in_edit_mode(ctx->sim.scene, psys) ? psys->edit->pathcache : psys->pathcache;
ParticleCacheKey *state, *par = NULL, *key[4];
ParticleData *pa=NULL;
ParticleTexture ptex;
@ -2373,6 +2378,9 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
int k, cpa_num;
short cpa_from;
if(!pcache)
return;
if(part->flag & PART_BRANCHING) {
branch_begin=rng_getFloat(thread->rng_path);
branch_end=branch_begin+(1.0f-branch_begin)*rng_getFloat(thread->rng_path);
@ -2955,7 +2963,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
float birthtime = 0.0, dietime = 0.0;
float t, time = 0.0, keytime = 0.0, frs_sec;
float hairmat[4][4];
float hairmat[4][4], rotmat[3][3], prev_tangent[3];
int k,i;
int steps = (int)pow(2.0, (double)pset->draw_step);
int totpart = edit->totpoint;
@ -2999,8 +3007,12 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
/*--get the first data points--*/
init_particle_interpolation(ob, psys, pa, &pind);
if(psys)
if(psys) {
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
VECCOPY(rotmat[0], hairmat[2]);
VECCOPY(rotmat[1], hairmat[1]);
VECCOPY(rotmat[2], hairmat[0]);
}
birthtime = pind.birthtime;
dietime = pind.dietime;
@ -3021,9 +3033,55 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result);
/* non-hair points are allready in global space */
if(psys && !(psys->flag & PSYS_GLOBAL_HAIR))
if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
Mat4MulVecfl(hairmat, result.co);
/* create rotations for proper creation of children */
if(k) {
float cosangle, angle, tangent[3], normal[3], q[4];
if(k == 1) {
/* calculate initial tangent for incremental rotations */
VECSUB(tangent, ca->co, (ca - 1)->co);
VECCOPY(prev_tangent, tangent);
Normalize(prev_tangent);
/* First rotation is based on emitting face orientation. */
/* This is way better than having flipping rotations resulting */
/* from using a global axis as a rotation pole (vec_to_quat()). */
/* It's not an ideal solution though since it disregards the */
/* initial tangent, but taking that in to account will allow */
/* the possibility of flipping again. -jahka */
Mat3ToQuat_is_ok(rotmat, (ca-1)->rot);
}
else {
VECSUB(tangent, ca->co, (ca - 1)->co);
Normalize(tangent);
cosangle= Inpf(tangent, prev_tangent);
/* note we do the comparison on cosangle instead of
* angle, since floating point accuracy makes it give
* different results across platforms */
if(cosangle > 0.999999f) {
QUATCOPY((ca - 1)->rot, (ca - 2)->rot);
}
else {
angle= saacos(cosangle);
Crossf(normal, prev_tangent, tangent);
VecRotToQuat(normal, angle, q);
QuatMul((ca - 1)->rot, q, (ca - 2)->rot);
}
VECCOPY(prev_tangent, tangent);
}
if(k == steps)
QUATCOPY(ca->rot, (ca - 1)->rot);
}
}
VECCOPY(ca->co, result.co);
ca->vel[0] = ca->vel[1] = 0.0f;
@ -3054,6 +3112,11 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
}
edit->totcached = totpart;
if(psys && psys->part->type == PART_HAIR) {
ParticleSimulationData sim = {scene, ob, psys, psys_get_modifier(ob, psys), NULL};
psys_cache_child_paths(&sim, cfra, 1);
}
}
/************************************************/
/* Particle Key handling */
@ -3766,6 +3829,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
pind.keyed = keyed;
pind.cache = cached ? psys->pointcache : NULL;
pind.epoint = NULL;
pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
pind.dm = psys->hair_out_dm;
init_particle_interpolation(sim->ob, psys, pa, &pind);
do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state);

View File

@ -3504,8 +3504,6 @@ static void psys_changed_physics(ParticleSimulationData *sim)
if(part->phystype == PART_PHYS_BOIDS && part->boids == NULL) {
BoidState *state;
psys_check_boid_data(sim->psys);
part->boids = MEM_callocN(sizeof(BoidSettings), "Boid Settings");
boid_default_settings(part->boids);
@ -3518,6 +3516,8 @@ static void psys_changed_physics(ParticleSimulationData *sim)
state->flag |= BOIDSTATE_CURRENT;
BLI_addtail(&part->boids->states, state);
}
psys_check_boid_data(sim->psys);
}
static void particles_fluid_step(ParticleSimulationData *sim, int cfra)
{

View File

@ -69,6 +69,13 @@ static int blender_test_break() {return 0;}
/* **** XXX ******** */
void printf_strip(Sequence *seq)
{
fprintf(stderr, "name: '%s', len:%d, start:%d, (startofs:%d, endofs:%d), (startstill:%d, endstill:%d), machine:%d, (startdisp:%d, enddisp:%d)\n",
seq->name, seq->len, seq->start, seq->startofs, seq->endofs, seq->startstill, seq->endstill, seq->machine, seq->startdisp, seq->enddisp);
fprintf(stderr, "\tseq_tx_set_final_left: %d %d\n\n", seq_tx_get_final_left(seq, 0), seq_tx_get_final_right(seq, 0));
}
/* **********************************************************************
alloc / free functions
********************************************************************** */
@ -3238,7 +3245,7 @@ void seq_tx_set_final_left(Sequence *seq, int val)
{
if (val < (seq)->start) {
seq->startstill = abs(val - (seq)->start);
(seq)->startofs = 0;
seq->startofs = 0;
} else {
seq->startofs = abs(val - (seq)->start);
seq->startstill = 0;
@ -3249,7 +3256,7 @@ void seq_tx_set_final_right(Sequence *seq, int val)
{
if (val > (seq)->start + (seq)->len) {
seq->endstill = abs(val - (seq->start + (seq)->len));
(seq)->endofs = 0;
seq->endofs = 0;
} else {
seq->endofs = abs(val - ((seq)->start + (seq)->len));
seq->endstill = 0;
@ -3334,18 +3341,25 @@ int seq_tx_test(Sequence * seq)
return (seq->type < SEQ_EFFECT) || (get_sequence_effect_num_inputs(seq->type) == 0);
}
static int seq_overlap(Sequence *seq1, Sequence *seq2)
{
if(seq1 != seq2)
if(seq1->machine==seq2->machine)
if(((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0)
return 1;
return 0;
}
int seq_test_overlap(ListBase * seqbasep, Sequence *test)
{
Sequence *seq;
seq= seqbasep->first;
while(seq) {
if(seq!=test) {
if(test->machine==seq->machine) {
if( (test->enddisp <= seq->startdisp) || (test->startdisp >= seq->enddisp) );
else return 1;
}
}
if(seq_overlap(test, seq))
return 1;
seq= seq->next;
}
return 0;
@ -3403,6 +3417,76 @@ int shuffle_seq(ListBase * seqbasep, Sequence *test)
}
}
static int shuffle_seq_time_offset_test(ListBase * seqbasep, char dir)
{
int offset= 0;
Sequence *seq, *seq_other;
for(seq= seqbasep->first; seq; seq= seq->next) {
if(seq->tmp) {
for(seq_other= seqbasep->first; seq_other; seq_other= seq_other->next) {
if(seq_overlap(seq, seq_other)) {
if(dir=='L') {
offset= MIN2(offset, seq_other->startdisp - seq->enddisp);
}
else {
offset= MAX2(offset, seq_other->enddisp - seq->startdisp);
}
}
}
}
}
return offset;
}
static int shuffle_seq_time_offset(ListBase * seqbasep, char dir)
{
int ofs= 0;
int tot_ofs= 0;
Sequence *seq;
while( (ofs= shuffle_seq_time_offset_test(seqbasep, dir)) ) {
for(seq= seqbasep->first; seq; seq= seq->next) {
if(seq->tmp) {
/* seq_test_overlap only tests display values */
seq->startdisp += ofs;
seq->enddisp += ofs;
}
}
tot_ofs+= ofs;
}
for(seq= seqbasep->first; seq; seq= seq->next) {
if(seq->tmp)
calc_sequence_disp(seq); /* corrects dummy startdisp/enddisp values */
}
return tot_ofs;
}
int shuffle_seq_time(ListBase * seqbasep)
{
/* note: seq->tmp is used to tag strips to move */
Sequence *seq;
int offset_l = shuffle_seq_time_offset(seqbasep, 'L');
int offset_r = shuffle_seq_time_offset(seqbasep, 'R');
int offset = (-offset_l < offset_r) ? offset_l:offset_r;
if(offset) {
for(seq= seqbasep->first; seq; seq= seq->next) {
if(seq->tmp) {
seq_translate(seq, offset);
seq->flag &= ~SEQ_OVERLAP;
}
}
}
return offset? 0:1;
}
void seq_update_sound(struct Sequence *seq)
{
if(seq->type == SEQ_SOUND)

View File

@ -1027,7 +1027,7 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
{
SmokeModifierData *smd2 = (SmokeModifierData *)md;
if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll)
if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points)
{
// we got nice collision object
SmokeCollSettings *scs = smd2->coll;

View File

@ -1706,7 +1706,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
GHash *hash;
GHashIterator *ihash;
float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], dv1[3],ve[3],avel[3]={0.0,0.0,0.0},
vv1[3], vv2[3], vv3[3], vv4[3], coledge[3], mindistedge = 1000.0f,
vv1[3], vv2[3], vv3[3], vv4[3], coledge[3]={0.0f, 0.0f, 0.0f}, mindistedge = 1000.0f,
outerforceaccu[3],innerforceaccu[3],
facedist,n_mag,force_mag_norm,minx,miny,minz,maxx,maxy,maxz,
innerfacethickness = -0.5f, outerfacethickness = 0.2f,

View File

@ -454,6 +454,7 @@ void i_window(
#define BLI_CS_CIE 2
#define RAD2DEG(_rad) ((_rad)*(180.0/M_PI))
#define DEG2RAD(_deg) ((_deg)*(M_PI/180.0))
void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b);
void hex_to_rgb(char *hexcol, float *r, float *g, float *b);

View File

@ -38,9 +38,9 @@
#define BFILE_NORMAL (0)
/* No supervision, just translate // if needed, RISKY */
#define BFILE_RAW (1<<0)
/* Path is relative to config dirs */
/* Path is based in env vars specified by "envvars" */
#define BFILE_CONFIG (1<<1)
/* Path is for current session temp file */
/* Path is for current session temp files */
#define BFILE_TEMP (1<<2)
/* Config handling, special cases: */
@ -50,6 +50,17 @@
/* Compression to apply on close: */
#define BFILE_GZIP (1<<5)
/**
For the envvars param.
*/
typedef enum BEnvVarFamilies {
BENV_NONE,
BENV_BASE,
BENV_DATAFILES,
BENV_PYTHON,
BENV_PLUGINS
} BEnvVarFam;
/**
File descriptor for Blender abstracted file access.
*/
@ -58,22 +69,23 @@ typedef struct {
int fd;
/* Anything below should not be touched directly */
int uflags; /* Special options requested by upper level, copy of bflags */
char *fpath; /* Final/requested path name */
char *tpath; /* Temp path name if applicable */
int type; /* Own flags, common classification of open and fopen */
int error; /* An op caused an error, unsafe to replace older files */
int uflags; /* Special options requested by upper level, copy of bflags */
BEnvVarFam evars; /* What kind of file, describe the env vars to use */
char *fpath; /* Final/requested path name */
char *tpath; /* Temp path name if applicable */
int classf; /* Own flags, common classification of open and fopen */
int error; /* An op caused an error, unsafe to replace older files */
} BFILE;
/**
Open a BFILE* with fopen()-like syntax.
*/
BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags);
BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags, BEnvVarFam envvars);
/**
Open a BFILE* with open()-like syntax.
*/
BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags);
BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags, BEnvVarFam envvars);
/**
Get the FILE* associated with the BFILE*.

View File

@ -176,6 +176,8 @@ typedef struct EditMesh
short mat_nr;
/* stats */
int totvert, totedge, totface, totvertsel, totedgesel, totfacesel;
/* shape key being edited */
int shapenr;
struct DerivedMesh *derivedCage, *derivedFinal;
/* the custom data layer mask that was last used to calculate

View File

@ -178,7 +178,7 @@ extern unsigned int hashsizes[];
/*---------inlined functions---------*/
BM_INLINE void BLI_ghash_insert(GHash *gh, void *key, void *val) {
unsigned int hash= gh->hashfp(key)%gh->nbuckets;
Entry *e= BLI_mempool_alloc(gh->entrypool);
Entry *e= (Entry*) BLI_mempool_alloc(gh->entrypool);
e->key= key;
e->val= val;

View File

@ -66,6 +66,9 @@ int BLI_exist(char *name);
* @param name The name of the file to read.
* @retval A list of strings representing the file lines.
*/
int BLI_is_dir(char *file);
struct LinkNode *BLI_read_file_as_lines(char *name);
/**

View File

@ -51,6 +51,7 @@ char *BLI_gethome_folder(char *folder_name, int flag);
#define BLI_GETHOME_ALL (BLI_GETHOME_SYSTEM|BLI_GETHOME_LOCAL|BLI_GETHOME_USER)
void BLI_setenv(const char *env, const char *val);
void BLI_setenv_if_new(const char *env, const char* val);
void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file);
void BLI_make_exist(char *dir);

View File

@ -129,6 +129,7 @@ struct dirent *readdir(DIR *dp);
int closedir (DIR *dp);
void get_default_root(char *root);
int check_file_chars(char *filename);
char *dirname(char *path);
#ifdef WIN32
int BLI_getInstallationDir(char *str);

View File

@ -25,89 +25,70 @@
*/
#include <string.h>
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#include <unistd.h>
#include <sys/param.h>
// #include <libgen.h>
#else
#include <io.h>
#include "BLI_winstuff.h"
#include <io.h>
#include "BLI_winstuff.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "MEM_guardedalloc.h"
#include "BKE_utildefines.h"
#include "BKE_blender.h"
#include "BLI_util.h"
#include "BLI_fileops.h"
#include "BLI_storage.h"
#include "BLI_bfile.h"
// This would provide config paths and their oldest viable version
// so if there is an uncompatible change, user's old versions are not loaded
//#include "bfile_tables.h"
/* Internal bfile classification flags */
#define BCF_OPEN (0)
#define BCF_FOPEN (1<<0)
#define BCF_READ (1<<1)
#define BCF_WRITE (1<<2)
#define BCF_AT_END (1<<3)
#define BCF_DISCARD (1<<4)
/* Internal bfile type flags */
#define BTF_OPEN (0)
#define BTF_FOPEN (1<<0)
#define BTF_READ (1<<1)
#define BTF_WRITE (1<<2)
#define BTF_AT_END (1<<3)
#define BTF_DISCARD (1<<4)
/* Declaration of internal functions */
void chomp(char* line);
void expand_envvars(char* src, char* dst);
void fill_paths(BFILE *bfile, const char *path);
char* find_in_pathlist(char* filename, char* pathlist);
void init_vars_from_file(const char* path);
void setup_temp();
/*** Exported functions ***/
void fill_paths(BFILE *bfile, const char *path) {
char* source_path = NULL;
int bflags = bfile->uflags;
if(bflags & BFILE_NORMAL || bflags & BFILE_RAW) {
// bfile->fpath is path with // replaced
}
if(bflags & BFILE_TEMP) {
// bfile->fpath is tempdir+path
}
if(bflags & BFILE_CONFIG) {
// bfile->fpath is userdir+version+path
// source_path is first hit in (if using fallback to older versions)
// userdir+curversion+path (... userdir+limitversion+path) sysdir+path
// (limitversion is based in path, using some kind of regex or "tables")
}
if(bfile->type & BTF_WRITE && !(bflags & BFILE_RAW)) {
/* Generate temp path */
// bfile->tpath is fpath+randstring
if(!(bfile->type & BTF_DISCARD)) {
/* Copy data to tpath */
if(source_path) {
// copy it from older version or sys version
}
}
} else {
bfile->tpath = bfile->fpath;
}
}
BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags) {
BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags,
BEnvVarFam envvars)
{
BFILE *bfile;
bfile = MEM_mallocN(sizeof(BFILE), "bfile-fopen");
bfile->type = BTF_FOPEN;
bfile->classf = BCF_FOPEN;
bfile->uflags = bflags;
/* From fopen() doc, we can guess some logic:
r BTF_READ
r+ BTF_READ | BTF_WRITE
w BTF_DISCARD | BTF_WRITE
w+ BTF_DISCARD | BTF_WRITE | BTF_READ
a BTF_AT_END | BTF_WRITE
a+ BTF_AT_END | BTF_WRITE | BTF_READ
r BCF_READ
r+ BCF_READ | BCF_WRITE
w BCF_DISCARD | BCF_WRITE
w+ BCF_DISCARD | BCF_WRITE | BCF_READ
a BCF_AT_END | BCF_WRITE
a+ BCF_AT_END | BCF_WRITE | BCF_READ
*/
if(strchr(mode, 'r'))
bfile->type |= BTF_READ;
bfile->classf |= BCF_READ;
if(strchr(mode, 'w'))
bfile->type |= (BTF_DISCARD | BTF_WRITE);
bfile->classf |= (BCF_DISCARD | BCF_WRITE);
if(strchr(mode, 'a'))
bfile->type |= (BTF_AT_END | BTF_WRITE);
bfile->classf |= (BCF_AT_END | BCF_WRITE);
if(strchr(mode, '+'))
bfile->type |= (BTF_READ | BTF_WRITE);
bfile->classf |= (BCF_READ | BCF_WRITE);
fill_paths(bfile, path);
@ -118,24 +99,26 @@ BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags) {
}
BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags) {
BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags,
BEnvVarFam envvars)
{
BFILE *bfile;
bfile = MEM_mallocN(sizeof(BFILE), "bfile-open");
bfile->type = BTF_OPEN;
bfile->classf = BCF_OPEN;
bfile->uflags = bflags;
/* Easy mapping for open() */
if(flags & O_RDONLY)
bfile->type |= BTF_READ;
bfile->classf |= BCF_READ;
if(flags & O_WRONLY)
bfile->type |= BTF_WRITE;
bfile->classf |= BCF_WRITE;
if(flags & O_RDWR)
bfile->type |= (BTF_READ | BTF_WRITE);
bfile->classf |= (BCF_READ | BCF_WRITE);
if(flags & O_APPEND)
bfile->type |= BTF_AT_END;
bfile->classf |= BCF_AT_END;
if(flags & O_TRUNC)
bfile->type |= BTF_DISCARD;
bfile->classf |= BCF_DISCARD;
fill_paths(bfile, pathname);
@ -180,7 +163,9 @@ ssize_t BLI_bfile_read(BFILE *f, void *buf, size_t count) {
}
size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb, BFILE *f) {
size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb,
BFILE *f)
{
size_t ret;
ret = fwrite(ptr, size, nmemb, f->stream);
@ -205,7 +190,7 @@ size_t BLI_bfile_fread(void *ptr, size_t size, size_t nmemb, BFILE *f) {
void BLI_bfile_close(BFILE *bfile) {
if((bfile->type | BTF_WRITE) &&
if((bfile->classf | BCF_WRITE) &&
!(bfile->uflags | BFILE_RAW)) {
/* Make sure data is on disk */
/* Move to final name if no errors */
@ -234,3 +219,301 @@ void BLI_bfile_set_error(BFILE *bfile, int error) {
bfile->error = error;
}
}
#if defined(WIN32)
#define LAST_SESSION_FILE "%HOME%\\Blender\\last-session FIXME FIXME FIXME"
#define ENVIRONMENT_FILE "FIXME"
#define SHARED_DIRECTORY "FIXME TOO"
#elif defined(OSX)
#define LAST_SESSION_FILE "${HOME}/Library/Application Support/Blender/last-session"
#define ENVIRONMENT_FILE "${HOME}/Library/Application Support/Blender/${BLENDER_VERSION}/environment"
#define SHARED_DIRECTORY "/Library/Application Support/Blender"
#else
#define LAST_SESSION_FILE "${HOME}/.blender/last-session"
#define ENVIRONMENT_FILE "${HOME}/.blender/${BLENDER_VERSION}/environment"
#define SHARED_DIRECTORY "/usr/share/blender"
#endif
void BLI_bfile_init_vars() {
char file[MAXPATHLEN];
char temp[MAXPATHLEN];
extern char bprogname[];
FILE* fp;
/* This one is unconditional */
sprintf(temp, "%d", BLENDER_VERSION);
BLI_setenv("BLENDER_VERSION", temp);
/* Is this unpack&run? */
sprintf(temp, "%s/%d/environment", dirname(bprogname), BLENDER_VERSION);
if(BLI_exist(temp)) {
BLI_setenv_if_new("BLENDER_SHARE", dirname(bprogname));
} else {
BLI_setenv_if_new("BLENDER_SHARE", SHARED_DIRECTORY);
}
expand_envvars(LAST_SESSION_FILE, file);
fp = fopen(file, "r");
/* 1st line, read previous version */
if (fp && (fscanf(fp, "%3c\n", temp) == 1)) {
temp[3] = '\0';
BLI_setenv("BLENDER_VERSION_PREV", temp);
/* 2nd line, read previous session path if needed */
if(!getenv("BLENDER_TEMP")) {
if ((fgets(temp, MAXPATHLEN, fp) != NULL)) {
/* Clean any \n */
chomp(temp);
/* Check the dir is still there or generate new one */
if(!BLI_exist(temp)) {
setup_temp();
}
} else {
/* We have to generate it for sure */
setup_temp();
}
}
} else {
/* Probably new user, or only <=249 before */
BLI_setenv("BLENDER_VERSION_PREV", "0");
setup_temp();
}
if(fp) {
fclose(fp);
}
/* Load vars from user and system files */
expand_envvars(ENVIRONMENT_FILE, file);
init_vars_from_file(file);
sprintf(temp, "/%d/environment", BLENDER_VERSION);
BLI_make_file_string("/", file, getenv("BLENDER_SHARE"), temp);
init_vars_from_file(file);
}
/*** Internal functions ***/
/**
Eliminate trailing EOL by writing a \0 over it.
Name taken from Perl.
*/
void chomp(char* line) {
int len = strlen(line);
#ifndef WIN32
if (line[len - 1] == '\n') {
line[len - 1] = '\0';
}
#else
if ((line[len - 2] == '\r' ) && ((line[len - 1] == '\n'))) {
line[len - 2] = '\0';
}
#endif /* WIN32 */
}
/**
Parse a file with lines like FOO=bar (comment lines have # as first
character) assigning to envvar FOO the value bar if FOO does not
exist yet.
Any white space before FOO, around the = or trailing will be used,
so beware.
*/
#define MAX_LINE 4096
#define ENV_VAR 256
#define VAR_LEN 8192
void init_vars_from_file(const char* path) {
char line[MAX_LINE];
char name[ENV_VAR];
FILE *fp;
char* separator;
char expanded[VAR_LEN];
fp = fopen(path, "r");
if (!fp) return;
while (fgets(line, MAX_LINE, fp) != NULL) {
/* Ignore comment lines */
if (line[0] == '#')
continue;
/* Split into envvar name and contents */
separator = strchr(line, '=');
if(separator && ((separator - line) < ENV_VAR)) {
/* First remove EOL */
chomp(line);
strncpy(name, line, separator - line);
name[separator - line] = '\0';
expand_envvars(separator + 1, expanded);
BLI_setenv_if_new(name, expanded);
}
}
fclose(fp);
}
/**
Look for ${} (or %%) env vars in src and expand if the var
exists (even if empty value). If not exist, the name is left as is.
The process is done all over src, and nested ${${}} is not supported.
src must be \0 terminated, and dst must be big enough.
*/
#ifndef WIN32
#define ENVVAR_PREFFIX "${"
#define ENVVAR_P_SIZE 2
#define ENVVAR_SUFFIX "}"
#define ENVVAR_S_SIZE 1
#else
#define ENVVAR_PREFFIX "%"
#define ENVVAR_P_SIZE 1
#define ENVVAR_SUFFIX "%"
#define ENVVAR_S_SIZE 1
#endif /* WIN32 */
void expand_envvars(char* src, char* dst) {
char* hit1;
char* hit2;
char name[ENV_VAR];
char* value;
int prevlen;
int done = 0;
char* source = src;
dst[0] = '\0';
while (!done) {
hit1 = strstr(source, ENVVAR_PREFFIX);
if (hit1) {
hit2 = strstr(hit1 + ENVVAR_P_SIZE, ENVVAR_SUFFIX);
if (hit2) {
/* "Copy" the leading part, if any */
if (hit1 != source) {
prevlen = strlen(dst);
strncat(dst, source, hit1 - source);
dst[prevlen + (hit1 - source)] = '\0';
}
/* Figure the name of the env var we just found */
strncpy(name, hit1 + ENVVAR_P_SIZE,
hit2 - (hit1 + ENVVAR_P_SIZE));
name[hit2 - (hit1 + ENVVAR_P_SIZE)] = '\0';
/* See if we can get something with that name */
value = getenv(name);
if (value) {
/* Push the var value */
strcat(dst, value);
} else {
/* Leave the var name, so it is clear that it failed */
strcat(dst, ENVVAR_PREFFIX);
strcat(dst, name);
strcat(dst, ENVVAR_SUFFIX);
}
/* Continue after closing mark, like a new string */
source = hit2 + ENVVAR_S_SIZE;
} else {
/* Non terminated var so "copy as is" and finish */
strcat(dst, source);
done = 1;
}
} else {
/* "Copy" whatever is left */
strcat(dst, source);
done = 1;
}
}
}
/**
Return a full path if the filename exists when combined
with any item from pathlist. Or NULL otherwise.
*/
#ifdef WIN32
#define SEPARATOR ';'
#else
#define SEPARATOR ':'
#endif
char* find_in_pathlist(char* filename, char* pathlist) {
char first[FILE_MAX + 10];
char* rest = NULL;
/* Separate first path from rest, use typical separator for current OS */
rest = strchr(pathlist, SEPARATOR);
if (rest) {
strncpy(first, pathlist, rest - pathlist);
first[rest - pathlist] = '\0';
/* Skip the separator so it becomes a valid new pathlist */
rest++;
} else {
strcpy(first, pathlist);
}
/* Check if combination exists */
BLI_add_slash(first);
strcat(first, filename);
if(BLI_exist(first)) {
return strdup(first);
}
/* First path failed, try with rest of paths if possible */
if(rest) {
return find_in_pathlist(filename, rest);
} else {
return NULL;
}
}
/**
Setup fpath and tpath based in the needs of the bfile.
*/
void fill_paths(BFILE *bfile, const char *path) {
char* source_path = NULL;
char* temp_path = NULL;
int bflags = bfile->uflags;
if(bflags & BFILE_NORMAL || bflags & BFILE_RAW) {
// bfile->fpath is path with // replaced
}
if(bflags & BFILE_TEMP) {
temp_path = MEM_mallocN(MAXPATHLEN, "bfile-fpath-1");
snprintf(temp_path, MAXPATHLEN, "%s/%s", getenv("BLENDER_TEMP"), path);
bfile->fpath = temp_path;
}
if(bflags & BFILE_CONFIG) {
// bfile->fpath is userdir+version+path
// source_path is first hit in (if using fallback to older versions)
// userdir+curversion+path (... userdir+limitversion+path) sysdir+path
// (limitversion is based in path, using some kind of regex or "tables")
}
if(bfile->classf & BCF_WRITE && !(bflags & BFILE_RAW)) {
/* Generate temp path */
temp_path = MEM_mallocN(MAXPATHLEN, "bfile-fpath-2");
snprintf(temp_path, MAXPATHLEN, "%s.XXXXXX", path);
bfile->tpath = mkdtemp(temp_path);
if(!(bfile->classf & BCF_DISCARD)) {
/* Copy data to tpath */
if(source_path) {
// copy it from older version or sys version
}
}
} else {
bfile->tpath = bfile->fpath;
}
}
/**
Create a temp directory in safe and multiuser way.
*/
void setup_temp() {
char template[MAXPATHLEN];
char* tempdir;
if(getenv("TMPDIR")) {
sprintf(template, "%s/blender-XXXXXX", getenv("TMPDIR"));
} else {
sprintf(template, "/tmp/blender-XXXXXX");
// MacOSX NSTemporaryDirectory and WIN32 ???
}
tempdir = mkdtemp(template);
BLI_setenv("BLENDER_TEMP", tempdir);
}

View File

@ -468,6 +468,11 @@ int BLI_exist(char *name)
return(st.st_mode);
}
/* would be better in fileops.c except that it needs stat.h so add here */
int BLI_is_dir(char *file) {
return S_ISDIR(BLI_exist(file));
}
LinkNode *BLI_read_file_as_lines(char *name)
{
FILE *fp= fopen(name, "r");

View File

@ -992,6 +992,18 @@ void BLI_setenv(const char *env, const char*val)
#endif
}
/**
Only set an env var if already not there.
Like Unix setenv(env, val, 0);
*/
void BLI_setenv_if_new(const char *env, const char* val)
{
if(getenv(env) == NULL)
BLI_setenv(env, val);
}
void BLI_clean(char *path)
{
if(path==0) return;
@ -1374,10 +1386,10 @@ void BLI_where_am_i(char *fullname, const char *name)
char *path = NULL, *temp;
#ifdef _WIN32
char *seperator = ";";
char *separator = ";";
char slash = '\\';
#else
char *seperator = ":";
char *separator = ":";
char slash = '/';
#endif
@ -1415,7 +1427,7 @@ void BLI_where_am_i(char *fullname, const char *name)
path = getenv("PATH");
if (path) {
do {
temp = strstr(path, seperator);
temp = strstr(path, separator);
if (temp) {
strncpy(filename, path, temp - path);
filename[temp - path] = 0;

View File

@ -217,6 +217,32 @@ int check_file_chars(char *filename)
return 1;
}
/* Copied from http://sourceware.org/ml/newlib/2005/msg00248.html */
/* Copyright 2005 Shaun Jackman
* Permission to use, copy, modify, and distribute this software
* is freely granted, provided that this notice is preserved.
*/
#include <string.h>
char* dirname(char *path)
{
char *p;
if( path == NULL || *path == '\0' )
return ".";
p = path + strlen(path) - 1;
while( *p == '/' ) {
if( p == path )
return path;
*p-- = '\0';
}
while( p >= path && *p != '/' )
p--;
return
p < path ? "." :
p == path ? "/" :
(*p = '\0', path);
}
/* End of copied part */
#else
/* intentionally empty for UNIX */

View File

@ -62,6 +62,7 @@ typedef struct BlendFileData {
int fileflags;
int displaymode;
int globalf;
char filename[240]; /* 240 = FILE_MAX */
struct bScreen* curscreen;
struct Scene* curscene;

View File

@ -364,7 +364,7 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
fd = blo_openblendermemfile(memfile, reports);
if (fd) {
fd->reports= reports;
strcpy(fd->filename, filename);
strcpy(fd->relabase, filename);
/* clear ob->proxy_from pointers in old main */
blo_clear_proxy_pointers_from_lib(fd, oldmain);

View File

@ -978,7 +978,7 @@ FileData *blo_openblenderfile(char *name, ReportList *reports)
fd->read = fd_read_gzip_from_file;
/* needed for library_append and read_libraries */
BLI_strncpy(fd->filename, name, sizeof(fd->filename));
BLI_strncpy(fd->relabase, name, sizeof(fd->relabase));
return blo_decode_and_check(fd, reports);
}
@ -4287,7 +4287,7 @@ static void composite_patch(bNodeTree *ntree, Scene *scene)
bNode *node;
for(node= ntree->nodes.first; node; node= node->next)
if(node->id==NULL && ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE))
if(node->id==NULL && ELEM3(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS))
node->id= &scene->id;
}
@ -4400,8 +4400,10 @@ static void link_recurs_seq(FileData *fd, ListBase *lb)
static void direct_link_paint(FileData *fd, Paint **paint)
{
(*paint)= newdataadr(fd, (*paint));
if(*paint)
if(*paint) {
(*paint)->paint_cursor= NULL;
(*paint)->brushes= newdataadr(fd, (*paint)->brushes);
}
}
static void direct_link_scene(FileData *fd, Scene *sce)
@ -4600,7 +4602,6 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->curswin= NULL;
win->tweak= NULL;
win->timers.first= win->timers.last= NULL;
win->queue.first= win->queue.last= NULL;
win->handlers.first= win->handlers.last= NULL;
win->modalhandlers.first= win->modalhandlers.last= NULL;
@ -4612,6 +4613,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->drawfail= 0;
}
wm->timers.first= wm->timers.last= NULL;
wm->operators.first= wm->operators.last= NULL;
wm->paintcursors.first= wm->paintcursors.last= NULL;
wm->queue.first= wm->queue.last= NULL;
@ -5302,7 +5304,7 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
}
/* make sure we have full path in lib->filename */
BLI_strncpy(lib->filename, lib->name, sizeof(lib->name));
cleanup_path(fd->filename, lib->filename);
cleanup_path(fd->relabase, lib->filename);
// printf("direct_link_library: name %s\n", lib->name);
// printf("direct_link_library: filename %s\n", lib->filename);
@ -5636,6 +5638,9 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
bfd->fileflags= fg->fileflags;
bfd->displaymode= fg->displaymode;
bfd->globalf= fg->globalf;
BLI_strncpy(bfd->filename, fg->filename, sizeof(bfd->filename));
if(G.fileflags & G_FILE_RECOVER)
BLI_strncpy(fd->relabase, fg->filename, sizeof(fd->relabase));
bfd->curscreen= fg->curscreen;
bfd->curscene= fg->curscene;
@ -6451,7 +6456,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* WATCH IT!!!: pointers from libdata have not been converted */
if(G.f & G_DEBUG)
printf("read file %s\n Version %d sub %d\n", fd->filename, main->versionfile, main->subversionfile);
printf("read file %s\n Version %d sub %d\n", fd->relabase, main->versionfile, main->subversionfile);
if(main->versionfile == 100) {
/* tex->extend and tex->imageflag have changed: */
@ -6598,7 +6603,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
if(main->versionfile <= 140) {
/* r-g-b-fac in texure */
/* r-g-b-fac in texture */
Tex *tex = main->tex.first;
while (tex) {
if ((tex->rfac == 0.0) &&
@ -10087,7 +10092,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
/* put 2.50 compatibility code here until next subversion bump */
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 6)) {
Object *ob;
Lamp *la;
@ -10113,6 +10117,71 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
la->compressthresh= 0.05f;
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 7)) {
Mesh *me;
Nurb *nu;
Lattice *lt;
Curve *cu;
Key *key;
float *data;
int a, tot;
/* shape keys are no longer applied to the mesh itself, but rather
to the derivedmesh/displist, so here we ensure that the basis
shape key is always set in the mesh coordinates. */
for(me= main->mesh.first; me; me= me->id.next) {
if((key = newlibadr(fd, lib, me->key)) && key->refkey) {
data= key->refkey->data;
tot= MIN2(me->totvert, key->refkey->totelem);
for(a=0; a<tot; a++, data+=3)
VECCOPY(me->mvert[a].co, data)
}
}
for(lt= main->latt.first; lt; lt= lt->id.next) {
if((key = newlibadr(fd, lib, lt->key)) && key->refkey) {
data= key->refkey->data;
tot= MIN2(lt->pntsu*lt->pntsv*lt->pntsw, key->refkey->totelem);
for(a=0; a<tot; a++, data+=3)
VECCOPY(lt->def[a].vec, data)
}
}
for(cu= main->curve.first; cu; cu= cu->id.next) {
if((key = newlibadr(fd, lib, cu->key)) && key->refkey) {
data= key->refkey->data;
for(nu=cu->nurb.first; nu; nu=nu->next) {
if(nu->bezt) {
BezTriple *bezt = nu->bezt;
for(a=0; a<nu->pntsu; a++, bezt++) {
VECCOPY(bezt->vec[0], data); data+=3;
VECCOPY(bezt->vec[1], data); data+=3;
VECCOPY(bezt->vec[2], data); data+=3;
bezt->alfa= *data; data++;
}
}
else if(nu->bp) {
BPoint *bp = nu->bp;
for(a=0; a<nu->pntsu*nu->pntsv; a++, bp++) {
VECCOPY(bp->vec, data); data+=3;
bp->alfa= *data; data++;
}
}
}
}
}
}
/* put 2.50 compatibility code here until next subversion bump */
{
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
@ -10225,14 +10294,25 @@ BlendFileData *blo_read_file_internal(FileData *fd, char *file)
break;
case ID_LI:
bhead = read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
/* skip library datablocks in undo, this works together with
BLO_read_from_memfile, where the old main->library is restored
overwriting the libraries from the memory file. previously
it did not save ID_LI/ID_ID blocks in this case, but they are
needed to make quit.blend recover them correctly. */
if(fd->memfile)
bhead= blo_nextbhead(fd, bhead);
else
bhead= read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
break;
case ID_ID:
/* same as above */
if(fd->memfile)
bhead= blo_nextbhead(fd, bhead);
else
/* always adds to the most recently loaded
* ID_LI block, see direct_link_library.
* this is part of the file format definition.
*/
bhead = read_libblock(fd, fd->mainlist.last, bhead, LIB_READ+LIB_EXTERN, NULL);
* this is part of the file format definition. */
bhead = read_libblock(fd, fd->mainlist.last, bhead, LIB_READ+LIB_EXTERN, NULL);
break;
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
@ -10254,7 +10334,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, char *file)
lib_link_all(fd, bfd->main);
lib_verify_nodetree(bfd->main, 1);
fix_relpaths_library(fd->filename, bfd->main); /* make all relative paths, relative to the open blend file */
fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */
link_global(fd, bfd); /* as last */
@ -10302,6 +10382,10 @@ static void sort_bhead_old_map(FileData *fd)
static BHead *find_previous_lib(FileData *fd, BHead *bhead)
{
/* skip library datablocks in undo, see comment in read_libblock */
if(fd->memfile)
return NULL;
for (; bhead; bhead= blo_prevbhead(fd, bhead))
if (bhead->code==ID_LI)
break;
@ -10373,7 +10457,7 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
if(bheadlib) {
Library *lib= read_struct(fd, bheadlib, "Library");
Main *ptr= blo_find_main(fd, &fd->mainlist, lib->name, fd->filename);
Main *ptr= blo_find_main(fd, &fd->mainlist, lib->name, fd->relabase);
id= is_yet_read(fd, ptr, bhead);
@ -11631,7 +11715,7 @@ BlendFileData *blo_read_blendafterruntime(int file, char *name, int actualsize,
fd->read = fd_read_from_file;
/* needed for library_append and read_libraries */
BLI_strncpy(fd->filename, name, sizeof(fd->filename));
BLI_strncpy(fd->relabase, name, sizeof(fd->relabase));
fd = blo_decode_and_check(fd, reports);
if (!fd)

View File

@ -56,7 +56,7 @@ typedef struct FileData {
gzFile gzfiledes;
// now only in use for library appending
char filename[FILE_MAXDIR+FILE_MAXFILE];
char relabase[FILE_MAXDIR+FILE_MAXFILE];
// variables needed for reading from stream
char headerdone;

View File

@ -2310,7 +2310,7 @@ static void write_scripts(WriteData *wd, ListBase *idbase)
/* context is usually defined by WM, two cases where no WM is available:
* - for forward compatibility, curscreen has to be saved
* - for undofile, curscene needs to be saved */
static void write_global(WriteData *wd, Main *mainvar)
static void write_global(WriteData *wd, int fileflags, Main *mainvar)
{
FileGlobal fg;
bScreen *screen;
@ -2323,8 +2323,9 @@ static void write_global(WriteData *wd, Main *mainvar)
fg.curscene= screen->scene;
fg.displaymode= G.displaymode;
fg.winpos= G.winpos;
fg.fileflags= (G.fileflags & ~G_FILE_NO_UI); // prevent to save this, is not good convention, and feature with concerns...
fg.fileflags= (fileflags & ~G_FILE_NO_UI); // prevent to save this, is not good convention, and feature with concerns...
fg.globalf= G.f;
BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename));
sprintf(subvstr, "%4d", BLENDER_SUBVERSION);
memcpy(fg.subvstr, subvstr, 4);
@ -2353,7 +2354,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
mywrite(wd, buf, 12);
write_renderinfo(wd, mainvar);
write_global(wd, mainvar);
write_global(wd, write_flags, mainvar);
/* no UI save in undo */
if(current==NULL) {
@ -2384,8 +2385,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
write_brushes (wd, &mainvar->brush);
write_scripts (wd, &mainvar->script);
write_gpencils (wd, &mainvar->gpencil);
if(current==NULL)
write_libraries(wd, mainvar->next); /* no library save in undo */
write_libraries(wd, mainvar->next);
if (write_user_block) {
write_userdef(wd);

View File

@ -177,6 +177,9 @@ typedef struct BMesh {
/*active face pointer*/
struct BMFace *act_face;
/*active shape key number, should really be in BMEditMesh, not here*/
int shapenr;
} BMesh;
typedef struct BMVert {

View File

@ -468,11 +468,12 @@ BMOpDefine def_object_load_bmesh = {
/*
BMesh to Mesh
Converts a bmesh to a Mesh
Converts a bmesh to a Mesh. This is reserved for exiting editmode.
*/
BMOpDefine def_bmesh_to_mesh = {
"bmesh_to_mesh",
{{BMOP_OPSLOT_PNT, "meshptr"}, //pointer to a mesh structure to fill in
{{BMOP_OPSLOT_PNT, "mesh"}, //pointer to a mesh structure to fill in
{BMOP_OPSLOT_PNT, "object"}, //pointer to an object structure
{BMOP_OPSLOT_INT, "notesselation"}, //don't calculate mfaces
{0, /*null-terminating sentinel*/}},
bmesh_to_mesh_exec,
@ -482,11 +483,13 @@ BMOpDefine def_bmesh_to_mesh = {
/*
Mesh to BMesh
Load the contents of a mesh into the bmesh.
Load the contents of a mesh into the bmesh. this bmop is private, it's
reserved exclusively for entering editmode.
*/
BMOpDefine def_mesh_to_bmesh = {
"mesh_to_bmesh",
{{BMOP_OPSLOT_PNT, "mesh"}, //pointer to a Mesh structure
{BMOP_OPSLOT_PNT, "object"}, //pointer to an Object structure
{0, /*null-terminating sentinel*/}},
mesh_to_bmesh_exec,
0

View File

@ -6,6 +6,8 @@
#include "DNA_customdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@ -15,6 +17,8 @@
#include "BKE_global.h"
#include "BKE_DerivedMesh.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_key.h"
#include "BKE_main.h"
#include "BLI_blenlib.h"
#include "BLI_edgehash.h"
@ -27,6 +31,15 @@
#include "mesh_intern.h"
#include "bmesh.h"
/*
HACK: we're using the old keyindex shape key hack for now, where each
vertex is assigned an index on entering editmode, which is used to retrieve
the original shapekey coordinates on exiting editmode.
this should be replaced by proper use of customdata layers, but I'm not
sure if that's such a good idea before merging with trunk or not.
*/
/*
* MESH CONV.C
*
@ -37,21 +50,24 @@
*/
void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
Object *ob = BMO_Get_Pnt(op, "object");
Mesh *me = BMO_Get_Pnt(op, "mesh");
MVert *mvert;
MEdge *medge;
MLoop *ml;
MPoly *mpoly;
KeyBlock *actkey;
BMVert *v, **vt=NULL;
BMEdge *e, **fedges=NULL, **et = NULL;
BLI_array_declare(fedges);
BMFace *f;
BLI_array_declare(fedges);
float (*keyco)[3]= NULL;
int *keyi;
int i, j, li, allocsize[4] = {512, 512, 2048, 512};
if (!me || !me->totvert) return; /*sanity check*/
mvert = me->mvert;
vt = MEM_mallocN(sizeof(void**)*me->totvert, "mesh to bmesh vtable");
CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
@ -59,13 +75,23 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);
CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
actkey = ob_get_keyblock(ob);
if(actkey && actkey->totelem == me->totvert) {
keyco= actkey->data;
bm->shapenr= ob->shapenr;
} else if (actkey) {
printf("shapekey<->mesh mismatch!\n");
}
for (i=0; i<me->totvert; i++, mvert++) {
v = BM_Make_Vert(bm, mvert->co, NULL);
v = BM_Make_Vert(bm, keyco ? keyco[i] : mvert->co, NULL);
VECCOPY(v->no, mvert->no);
vt[i] = v;
@ -80,6 +106,10 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
/*Copy Custom Data*/
CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data);
/*set shape key original index*/
keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
*keyi = i;
}
if (!me->totedge) {
@ -223,24 +253,25 @@ void object_load_bmesh_exec(BMesh *bm, BMOperator *op) {
Scene *scene = BMO_Get_Pnt(op, "scene");
Mesh *me = ob->data;
BMO_CallOpf(bm, "bmesh_to_mesh meshptr=%p", me);
BMO_CallOpf(bm, "bmesh_to_mesh mesh=%p object=%p", me, ob);
/*BMESH_TODO eventually we'll have to handle shapekeys here*/
}
void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) {
Mesh *me = BMO_Get_Pnt(op, "meshptr");
Mesh *me = BMO_Get_Pnt(op, "mesh");
Object *ob = BMO_Get_Pnt(op, "object");
MLoop *mloop;
MPoly *mpoly;
MVert *mvert, *oldverts;
MEdge *medge;
MFace *mface;
BMVert *v;
BMVert *v, *eve;
BMEdge *e;
BMLoop *l;
BMFace *f;
BMIter iter, liter;
int i, j, ototvert, totloop, totface, numTex, numCol;
int i, j, *keyi, ototvert, totloop, totface, numTex, numCol;
int dotess = !BMO_Get_Int(op, "notesselation");
numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
@ -459,5 +490,129 @@ void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) {
mpoly++;
}
/* patch hook indices and vertex parents */
{
Object *ob;
ModifierData *md;
BMVert **vertMap = NULL;
int i,j;
for (ob=G.main->object.first; ob; ob=ob->id.next) {
if (ob->parent==ob && ELEM(ob->partype, PARVERT1,PARVERT3)) {
/* duplicate code from below, make it function later...? */
if (!vertMap) {
vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
if (*keyi != ORIGINDEX_NONE)
vertMap[*keyi] = eve;
}
}
if(ob->par1 < ototvert) {
eve = vertMap[ob->par1];
if(eve) ob->par1= BMINDEX_GET(eve);
}
if(ob->par2 < ototvert) {
eve = vertMap[ob->par2];
if(eve) ob->par2= BMINDEX_GET(eve);
}
if(ob->par3 < ototvert) {
eve = vertMap[ob->par3];
if(eve) ob->par3= BMINDEX_GET(eve);
}
}
if (ob->data==me) {
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type==eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData*) md;
if (!vertMap) {
vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
if (*keyi != ORIGINDEX_NONE)
vertMap[*keyi] = eve;
}
}
for (i=j=0; i<hmd->totindex; i++) {
if(hmd->indexar[i] < ototvert) {
eve = vertMap[hmd->indexar[i]];
if (eve) {
hmd->indexar[j++] = BMINDEX_GET(eve);
}
}
else j++;
}
hmd->totindex = j;
}
}
}
}
if (vertMap) MEM_freeN(vertMap);
}
mesh_update_customdata_pointers(me);
/* are there keys? */
if(me->key) {
float *fp, *newkey, *oldkey;
KeyBlock *currkey;
KeyBlock *actkey= BLI_findlink(&me->key->block, bm->shapenr-1);
/* Lets reorder the key data so that things line up roughly
* with the way things were before editmode */
currkey = me->key->block.first;
while(currkey) {
fp= newkey= MEM_callocN(me->key->elemsize*bm->totvert, "currkey->data");
oldkey = currkey->data;
eve= BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
i = 0;
mvert = me->mvert;
while(eve) {
keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
if (*keyi >= 0 && *keyi < currkey->totelem) { // valid old vertex
if(currkey == actkey) {
if(actkey == me->key->refkey) {
VECCOPY(fp, mvert->co);
}
else {
VECCOPY(fp, mvert->co);
if(oldverts) {
VECCOPY(mvert->co, oldverts[*keyi].co);
}
}
}
else {
if(oldkey) {
VECCOPY(fp, oldkey + 3 * *keyi);
}
}
}
else {
VECCOPY(fp, mvert->co);
}
fp+= 3;
++i;
++mvert;
eve= BMIter_Step(&iter);
}
currkey->totelem= bm->totvert;
if(currkey->data) MEM_freeN(currkey->data);
currkey->data = newkey;
currkey= currkey->next;
}
}
if(oldverts) MEM_freeN(oldverts);
}

View File

@ -1386,7 +1386,7 @@ static int acf_dsskey_setting_flag(int setting, short *neg)
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
return KEYBLOCK_DS_EXPAND;
return KEY_DS_EXPAND;
case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
return ADT_NLA_EVAL_OFF;
@ -1737,28 +1737,91 @@ static bAnimChannelType ACF_DSARM=
/* ShapeKey Entry ------------------------------------------- */
// XXX ... this is currently obsolete...
#if 0
static void dummy_olddraw_shapekeys ()
/* name for ShapeKey */
static void acf_shapekey_name(bAnimListElem *ale, char *name)
{
case ANIMTYPE_SHAPEKEY: /* shapekey channel */
{
KeyBlock *kb = (KeyBlock *)ale->data;
indent = 0;
special = -1;
offset= (ale->id) ? 21 : 0;
if (kb->name[0] == '\0')
sprintf(name, "Key %d", ale->index);
else
KeyBlock *kb= (KeyBlock *)ale->data;
/* just copy the name... */
if (kb && name) {
/* if the KeyBlock had a name, use it, otherwise use the index */
if (kb->name[0])
strcpy(name, kb->name);
else
sprintf(name, "Key %d", ale->index);
}
break;
}
#endif
/* check if some setting exists for this channel */
static short acf_shapekey_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
{
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted */
case ACHANNEL_SETTING_PROTECT: /* protected */
return 1;
/* nothing else is supported */
default:
return 0;
}
}
/* get the appropriate flag(s) for the setting when it is valid */
static int acf_shapekey_setting_flag(int setting, short *neg)
{
/* clear extra return data first */
*neg= 0;
switch (setting) {
case ACHANNEL_SETTING_MUTE: /* mute */
return KEYBLOCK_MUTE;
case ACHANNEL_SETTING_SELECT: /* selected */
return KEYBLOCK_SEL;
case ACHANNEL_SETTING_PROTECT: /* locked */
return KEYBLOCK_LOCKED;
default: /* unsupported */
return 0;
}
}
/* get pointer to the setting */
static void *acf_shapekey_setting_ptr(bAnimListElem *ale, int setting, short *type)
{
KeyBlock *kb= (KeyBlock *)ale->data;
/* clear extra return data first */
*type= 0;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted */
case ACHANNEL_SETTING_PROTECT: /* protected */
GET_ACF_FLAG_PTR(kb->flag)
default: /* unsupported */
return NULL;
}
}
/* shapekey expander type define */
static bAnimChannelType ACF_SHAPEKEY=
{
acf_generic_channel_backdrop, /* backdrop */
acf_generic_indention_0, /* indent level */
acf_generic_basic_offset, /* offset */
acf_shapekey_name, /* name */
NULL, /* icon */
acf_shapekey_setting_valid, /* has setting */
acf_shapekey_setting_flag, /* flag for setting */
acf_shapekey_setting_ptr /* pointer for setting */
};
/* Grease Pencil entries ------------------------------------------- */
// XXX ... this is currently not restored yet
@ -1923,7 +1986,7 @@ void ANIM_init_channel_typeinfo_data (void)
animchannelTypeInfo[type++]= &ACF_DSMBALL; /* MetaBall Channel */
animchannelTypeInfo[type++]= &ACF_DSARM; /* Armature Channel */
animchannelTypeInfo[type++]= NULL; /* ShapeKey */ // XXX this is no longer used for now...
animchannelTypeInfo[type++]= &ACF_SHAPEKEY; /* ShapeKey */
// XXX not restored yet
animchannelTypeInfo[type++]= NULL; /* Grease Pencil Datablock */
@ -2084,7 +2147,7 @@ void ANIM_channel_setting_set (bAnimContext *ac, bAnimListElem *ale, int setting
// XXX hardcoded size of icons
#define ICON_WIDTH 17
// XXX hardcoded width of sliders
#define SLIDER_WIDTH 70
#define SLIDER_WIDTH 80
/* Draw the given channel */
// TODO: make this use UI controls for the buttons
@ -2195,6 +2258,134 @@ static void achannel_setting_widget_cb(bContext *C, void *poin, void *poin2)
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
}
/* callback for visiblility-toggle widget settings - perform value flushing (Graph Editor only) */
static void achannel_setting_visible_widget_cb(bContext *C, void *ale_npoin, void *dummy_poin)
{
bAnimListElem *ale_setting= (bAnimListElem *)ale_npoin;
int prevLevel=0, matchLevel=0;
short vizOn = 0;
bAnimContext ac;
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale, *match=NULL;
int filter;
/* send notifiers before doing anything else... */
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
/* verify animation context */
if (ANIM_animdata_get_context(C, &ac) == 0)
return;
/* verify that we have a channel to operate on, and that it has all we need */
if (ale_setting) {
/* check if the setting is on... */
vizOn= ANIM_channel_setting_get(&ac, ale_setting, ACHANNEL_SETTING_VISIBLE);
/* vizOn == -1 means setting not found... */
if (vizOn == -1)
return;
}
else
return;
/* get all channels that can possibly be chosen
* - therefore, the filter is simply ANIMFILTER_CHANNELS, since if we took VISIBLE too,
* then the channels under closed expanders get ignored...
*/
filter= ANIMFILTER_CHANNELS;
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* find the channel that got changed */
for (ale= anim_data.first; ale; ale= ale->next) {
/* compare data, and type as main way of identifying the channel */
if ((ale->data == ale_setting->data) && (ale->type == ale_setting->type)) {
/* we also have to check the ID, this is assigned to, since a block may have multiple users */
// TODO: is the owner-data more revealing?
if (ale->id == ale_setting->id) {
match= ale;
break;
}
}
}
if (match == NULL) {
printf("ERROR: no channel matching the one changed was found \n");
BLI_freelistN(&anim_data);
return;
}
else {
bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale_setting);
/* get the level of the channel that was affected
* - we define the level as simply being the offset for the start of the channel
*/
matchLevel= (acf->get_offset)? acf->get_offset(&ac, ale_setting) : 0;
}
/* flush up?
* - only flush up if the current state is now enabled
* (otherwise, it's too much work to force the parents to be inactive too)
*/
if (vizOn) {
/* go backwards in the list, until the highest-ranking element (by indention has been covered) */
for (ale= match->prev; ale; ale= ale->prev) {
bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
int level;
/* get the level of the current channel traversed
* - we define the level as simply being the offset for the start of the channel
*/
level= (acf->get_offset)? acf->get_offset(&ac, ale) : 0;
/* if the level is 'less than' (i.e. more important) the previous channel,
* flush the new status...
*/
if (level < matchLevel)
ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vizOn);
/* however, if the level is 'greater than' (i.e. less important than the previous channel,
* stop searching, since we've already reached the bottom of another hierarchy
*/
else if (level > matchLevel)
break;
/* store this level as the 'old' level now */
prevLevel= level;
}
}
/* flush down (always) */
{
/* go forwards in the list, until the lowest-ranking element (by indention has been covered) */
for (ale= match->next; ale; ale= ale->next) {
bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
int level;
/* get the level of the current channel traversed
* - we define the level as simply being the offset for the start of the channel
*/
level= (acf->get_offset)? acf->get_offset(&ac, ale) : 0;
/* if the level is 'greater than' (i.e. less important) the channel that was changed,
* flush the new status...
*/
if (level > matchLevel)
ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vizOn);
/* however, if the level is 'less than or equal to' the channel that was changed,
* (i.e. the current channel is as important if not more important than the changed channel)
* then we should stop, since we've found the last one of the children we should flush
*/
else
break;
/* store this level as the 'old' level now */
prevLevel= level;
}
}
/* free temp data */
BLI_freelistN(&anim_data);
}
/* callback for widget sliders - insert keyframes */
static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin)
{
@ -2237,7 +2428,57 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
}
}
/* callback for shapekey widget sliders - insert keyframes */
static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, void *kb_poin)
{
Key *key= (Key *)key_poin;
KeyBlock *kb= (KeyBlock *)kb_poin;
char *rna_path= key_get_curValue_rnaPath(key, kb);
Scene *scene= CTX_data_scene(C);
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
short flag=0, done=0;
float cfra;
/* get current frame */
// NOTE: this will do for now...
cfra= (float)CFRA;
/* get flags for keyframing */
if (IS_AUTOKEY_FLAG(INSERTNEEDED))
flag |= INSERTKEY_NEEDED;
if (IS_AUTOKEY_FLAG(AUTOMATKEY))
flag |= INSERTKEY_MATRIX;
if (IS_AUTOKEY_MODE(scene, EDITKEYS))
flag |= INSERTKEY_REPLACE;
/* get RNA pointer, and resolve the path */
RNA_id_pointer_create((ID *)key, &id_ptr);
/* try to resolve the path stored in the F-Curve */
if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) {
/* find or create new F-Curve */
// XXX is the group name for this ok?
bAction *act= verify_adt_action((ID *)key, 1);
FCurve *fcu= verify_fcurve(act, NULL, rna_path, 0, 1);
/* set the special 'replace' flag if on a keyframe */
if (fcurve_frame_has_keyframe(fcu, cfra, 0))
flag |= INSERTKEY_REPLACE;
/* insert a keyframe for this F-Curve */
done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
if (done)
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
}
/* free the path */
if (rna_path)
MEM_freeN(rna_path);
}
/* Draw a widget for some setting */
static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf, uiBlock *block, int xpos, int ypos, int setting)
@ -2260,9 +2501,9 @@ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChan
icon= ICON_CHECKBOX_DEHLT;
if (ale->type == ANIMTYPE_FCURVE)
tooltip= "F-Curve is visible in Graph Editor for editing.";
tooltip= "Channel is visible in Graph Editor for editing.";
else
tooltip= "F-Curve(s) are visible in Graph Editor for editing.";
tooltip= "Channel(s) are visible in Graph Editor for editing.";
break;
case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
@ -2327,10 +2568,14 @@ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChan
break;
}
/* set call to send relevant notifiers */
// NOTE: for now, we only need to send 'edited'
if (but)
uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL);
/* set call to send relevant notifiers and/or perform type-specific updates */
if (but) {
/* 'visibility' toggles for Graph Editor need special flushing */
if (setting == ACHANNEL_SETTING_VISIBLE)
uiButSetNFunc(but, achannel_setting_visible_widget_cb, MEM_dupallocN(ale), 0);
else
uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL);
}
}
}
@ -2445,7 +2690,7 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
* and wouldn't be able to auto-keyframe...
* - slider should start before the toggles (if they're visible) to keep a clean line down the side
*/
if ((draw_sliders) && (ale->type == ANIMTYPE_FCURVE)) {
if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) {
/* adjust offset */
offset += SLIDER_WIDTH;
@ -2453,20 +2698,49 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
uiBlockSetEmboss(block, UI_EMBOSS);
if (ale->id) { /* Slider using RNA Access -------------------- */
FCurve *fcu= (FCurve *)ale->data;
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
char *rna_path = NULL;
int array_index = 0;
short free_path = 0;
/* get RNA pointer, and resolve the path */
RNA_id_pointer_create(ale->id, &id_ptr);
/* try to resolve the path */
if (RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) {
uiBut *but;
/* get destination info */
if (ale->type == ANIMTYPE_FCURVE) {
FCurve *fcu= (FCurve *)ale->data;
/* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
but= uiDefAutoButR(block, &ptr, prop, fcu->array_index, "", 0, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc);
uiButSetFunc(but, achannel_setting_slider_cb, ale->id, fcu);
rna_path= fcu->rna_path;
array_index= fcu->array_index;
}
else if (ale->type == ANIMTYPE_SHAPEKEY) {
KeyBlock *kb= (KeyBlock *)ale->data;
Key *key= (Key *)ale->id;
rna_path= key_get_curValue_rnaPath(key, kb);
free_path= 1;
}
/* only if RNA-Path found */
if (rna_path) {
/* get RNA pointer, and resolve the path */
RNA_id_pointer_create(ale->id, &id_ptr);
/* try to resolve the path */
if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) {
uiBut *but;
/* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
but= uiDefAutoButR(block, &ptr, prop, array_index, "", 0, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc);
/* assign keyframing function according to slider type */
if (ale->type == ANIMTYPE_SHAPEKEY)
uiButSetFunc(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data);
else
uiButSetFunc(but, achannel_setting_slider_cb, ale->id, ale->data);
}
/* free the path if necessary */
if (free_path)
MEM_freeN(rna_path);
}
}
else { /* Special Slider for stuff without RNA Access ---------- */

View File

@ -238,6 +238,10 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
if (ale->flag & FCURVE_SELECTED)
sel= ACHANNEL_SETFLAG_CLEAR;
break;
case ANIMTYPE_SHAPEKEY:
if (ale->flag & KEYBLOCK_SEL)
sel= ACHANNEL_SETFLAG_CLEAR;
break;
case ANIMTYPE_NLATRACK:
if (ale->flag & NLATRACK_SELECTED)
sel= ACHANNEL_SETFLAG_CLEAR;
@ -307,6 +311,13 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
fcu->flag &= ~FCURVE_ACTIVE;
}
break;
case ANIMTYPE_SHAPEKEY:
{
KeyBlock *kb= (KeyBlock *)ale->data;
ACHANNEL_SET_FLAG(kb, sel, KEYBLOCK_SEL);
}
break;
case ANIMTYPE_NLATRACK:
{
NlaTrack *nlt= (NlaTrack *)ale->data;
@ -904,28 +915,14 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
if (vis == ACHANNEL_SETFLAG_CLEAR)
break;
if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_VISIBLE))
vis= ACHANNEL_SETFLAG_CLEAR;
else if ((ale->type == ANIMTYPE_GROUP) && !(ale->flag & AGRP_NOTVISIBLE))
/* set the setting in the appropriate way (if available) */
if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE))
vis= ACHANNEL_SETFLAG_CLEAR;
}
/* Now set the flags */
for (ale= anim_data.first; ale; ale= ale->next) {
switch (ale->type) {
case ANIMTYPE_FCURVE: /* F-Curve */
{
FCurve *fcu= (FCurve *)ale->data;
ACHANNEL_SET_FLAG(fcu, vis, FCURVE_VISIBLE);
}
break;
case ANIMTYPE_GROUP: /* Group */
{
bActionGroup *agrp= (bActionGroup *)ale->data;
ACHANNEL_SET_FLAG_NEG(agrp, vis, AGRP_NOTVISIBLE);
}
break;
}
ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vis);
}
/* cleanup */
@ -1361,7 +1358,7 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
/* get the channel that was clicked on */
/* filter channels */
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
filter= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* get channel from index */
ale= BLI_findlink(&anim_data, channel_index);
@ -1531,6 +1528,24 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
if (fcu->flag & FCURVE_SELECTED)
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
notifierFlags |= ND_ANIMCHAN_SELECT;
}
break;
case ANIMTYPE_SHAPEKEY:
{
KeyBlock *kb= (KeyBlock *)ale->data;
/* select/deselect */
if (selectmode == SELECT_INVERT) {
/* inverse selection status of this ShapeKey only */
kb->flag ^= KEYBLOCK_SEL;
}
else {
/* select ShapeKey by itself */
ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
kb->flag |= KEYBLOCK_SEL;
}
notifierFlags |= ND_ANIMCHAN_SELECT;
}
break;
@ -1571,9 +1586,6 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
#endif // XXX future of this is unclear
}
break;
case ANIMTYPE_SHAPEKEY:
/* TODO: shapekey channels cannot be selected atm... */
break;
default:
printf("Error: Invalid channel type in mouse_anim_channels() \n");
}

View File

@ -156,7 +156,7 @@ static void draw_cfra_number (Scene *scene, View2D *v2d, float cfra, short time)
glScalef(xscale, 1.0, 1.0);
}
/* General call for drawing current frame indicator in a */
/* General call for drawing current frame indicator in animation editor */
void ANIM_draw_cfra (const bContext *C, View2D *v2d, short flag)
{
Scene *scene= CTX_data_scene(C);

View File

@ -78,6 +78,7 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_key.h"
@ -207,8 +208,10 @@ static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
{
/* init dopesheet data if non-existant (i.e. for old files) */
if (sipo->ads == NULL)
if (sipo->ads == NULL) {
sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
sipo->ads->source= (ID *)ac->scene;
}
/* set settings for Graph Editor - "Selected = Editable" */
if (sipo->flag & SIPO_SELCUVERTSONLY)
@ -370,9 +373,18 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
*
* - id: ID block which should have an AnimData pointer following it immediately, to use
* - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
* - nlaOk: line or block of code to execute for NLA case
* - nlaOk: line or block of code to execute for NLA tracks+strips case
* - driversOk: line or block of code to execute for Drivers case
* - keysOk: line or block of code for Keyframes case
*
* The checks for the various cases are as follows:
* 0) top level: checks for animdata and also that all the F-Curves for the block will be visible
* 1) animdata check: for filtering animdata blocks only
* 2A) nla tracks: include animdata block's data as there are NLA tracks+strips there
* 2B) actions to convert to nla: include animdata block's data as there is an action that can be
* converted to a new NLA strip, and the filtering options allow this
* 3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor)
* 4) normal keyframes: only when there is an active action
*/
#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
{\
@ -647,6 +659,36 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
ale->datatype= ALE_FCURVE;
}
break;
case ANIMTYPE_SHAPEKEY:
{
KeyBlock *kb= (KeyBlock *)data;
Key *key= (Key *)ale->id;
ale->flag= kb->flag;
/* whether we have keyframes depends on whether there is a Key block to find it from */
if (key) {
/* index of shapekey is defined by place in key's list */
ale->index= BLI_findindex(&key->block, kb);
/* the corresponding keyframes are from the animdata */
if (ale->adt && ale->adt->action) {
bAction *act= ale->adt->action;
char *rna_path = key_get_curValue_rnaPath(key, kb);
/* try to find the F-Curve which corresponds to this exactly,
* then free the MEM_alloc'd string
*/
if (rna_path) {
ale->key_data= (void *)list_find_fcurve(&act->curves, rna_path, 0);
MEM_freeN(rna_path);
}
}
ale->datatype= (ale->key_data)? ALE_FCURVE : ALE_NONE;
}
}
break;
case ANIMTYPE_GPLAYER:
{
@ -892,7 +934,55 @@ static int animdata_filter_nla (ListBase *anim_data, bDopeSheet *ads, AnimData *
/* return the number of items added to the list */
return items;
}
/* Include ShapeKey Data for ShapeKey Editor */
static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode)
{
bAnimListElem *ale;
int items = 0;
/* check if channels or only F-Curves */
if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
KeyBlock *kb;
/* loop through the channels adding ShapeKeys as appropriate */
for (kb= key->block.first; kb; kb= kb->next) {
/* skip the first one, since that's the non-animateable basis */
// XXX maybe in future this may become handy?
if (kb == key->block.first) continue;
/* only work with this channel and its subchannels if it is editable */
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_SHAPEKEY(kb)) {
/* only include this track if selected in a way consistent with the filtering requirements */
if ( ANIMCHANNEL_SELOK(SEL_SHAPEKEY(kb)) ) {
// TODO: consider 'active' too?
/* owner-id here must be key so that the F-Curve can be resolved... */
ale= make_new_animlistelem(kb, ANIMTYPE_SHAPEKEY, NULL, ANIMTYPE_NONE, (ID *)key);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
}
}
else {
/* just use the action associated with the shapekey */
// FIXME: is owner-id and having no owner/dopesheet really fine?
if (key->adt) {
if (filter_mode & ANIMFILTER_ANIMDATA)
ANIMDATA_ADD_ANIMDATA(key)
else if (key->adt->action)
items= animdata_filter_action(anim_data, NULL, key->adt->action, filter_mode, NULL, ANIMTYPE_NONE, (ID *)key);
}
}
/* return the number of items added to the list */
return items;
}
#if 0
// FIXME: switch this to use the bDopeSheet...
static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode)
@ -1023,7 +1113,7 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
}
/* add material's animation data */
if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
ANIMDATA_FILTER_CASES(ma,
{ /* AnimData blocks - do nothing... */ },
items += animdata_filter_nla(anim_data, ads, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);,
@ -1083,7 +1173,7 @@ static int animdata_filter_dopesheet_particles (ListBase *anim_data, bDopeSheet
}
}
if (FILTER_PART_OBJD(psys->part) || (filter_mode & ANIMFILTER_CURVESONLY)) {
if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_PART_OBJD(psys->part) || (filter_mode & ANIMFILTER_CURVESONLY)) {
ANIMDATA_FILTER_CASES(psys->part,
{ /* AnimData blocks - do nothing... */ },
items += animdata_filter_nla(anim_data, ads, psys->part->adt, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);,
@ -1164,7 +1254,7 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad
}
/* add object-data animation channels? */
if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
if (!(filter_mode & ANIMFILTER_VISIBLE) || (expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
/* filtering for channels - nla, drivers, keyframes */
ANIMDATA_FILTER_CASES(iat,
{ /* AnimData blocks - do nothing... */ },
@ -1202,7 +1292,8 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
}
/* if collapsed, don't go any further (unless adding keyframes only) */
if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
if ( ((filter_mode & ANIMFILTER_VISIBLE) && EXPANDED_OBJC(ob) == 0) &&
!(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
return items;
/* Action, Drivers, or NLA */
@ -1225,7 +1316,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
}
/* add F-Curve channels (drivers are F-Curves) */
if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
// need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
}
@ -1241,7 +1332,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
}
/* add F-Curve channels? */
if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
// need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
}
@ -1269,7 +1360,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
}
/* add NLA tracks - only if expanded or so */
if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY))
if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY))
items += animdata_filter_nla(anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
},
{ /* drivers */
@ -1283,7 +1374,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
}
/* add channels */
if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, key, ANIMTYPE_DSSKEY, filter_mode, (ID *)key);
}
},
@ -1301,7 +1392,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
}
/* add channels */
if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
items += animdata_filter_action(anim_data, ads, adt->action, filter_mode, key, ANIMTYPE_DSSKEY, (ID *)key);
}
}
@ -1516,7 +1607,9 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bAnimContext *ac, bDo
/* check that we do indeed have a scene */
if ((ads->source == NULL) || (GS(ads->source->name)!=ID_SCE)) {
printf("DopeSheet Error: Not scene! \n");
printf("DopeSheet Error: Not scene!\n");
if (G.f & G_DEBUG)
printf("\tPointer = %p, Name = '%s' \n", ads->source, (ads->source)?ads->source->name:NULL);
return 0;
}
@ -1944,9 +2037,11 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode
}
break;
case ANIMCONT_SHAPEKEY:
case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
{
//items= animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
/* the check for the DopeSheet summary is included here since the summary works here too */
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
items= animdata_filter_shapekey(anim_data, data, filter_mode);
}
break;

View File

@ -62,6 +62,18 @@
/* ********************** frame change operator ***************************/
/* Check if the operator can be run from the current context */
static int change_frame_poll(bContext *C)
{
ScrArea *curarea= CTX_wm_area(C);
/* as long as there is an active area, and it isn't a Graph Editor
* (since the Graph Editor has its own version which does extra stuff),
* we're fine
*/
return ((curarea) && (curarea->spacetype != SPACE_IPO));
}
/* Set any flags that are necessary to indicate modal time-changing operation */
static int change_frame_init(bContext *C, wmOperator *op)
{
@ -85,18 +97,12 @@ static int change_frame_init(bContext *C, wmOperator *op)
static void change_frame_apply(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
int cfra;
/* get frame, and clamp to MINAFRAME
* - not MINFRAME, since it's useful to be able to key a few-frames back
*/
cfra= RNA_int_get(op->ptr, "frame");
if (cfra < MINAFRAME) cfra= MINAFRAME;
CFRA= cfra;
/* set the new frame number */
CFRA= RNA_int_get(op->ptr, "frame");
/* do updates */
sound_scrub(C);
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
}
@ -210,12 +216,14 @@ void ANIM_OT_change_frame(wmOperatorType *ot)
/* identifiers */
ot->name= "Change frame";
ot->idname= "ANIM_OT_change_frame";
ot->description= "Interactively change the current frame number.";
/* api callbacks */
ot->exec= change_frame_exec;
ot->invoke= change_frame_invoke;
ot->cancel= change_frame_cancel;
ot->modal= change_frame_modal;
ot->poll= change_frame_poll;
/* flags */
ot->flag= OPTYPE_BLOCKING;

View File

@ -521,9 +521,14 @@ short bezt_calc_average(BeztEditData *bed, BezTriple *bezt)
{
/* only if selected */
if (bezt->f2 & SELECT) {
/* store average time in float (only do rounding at last step */
/* store average time in float 1 (only do rounding at last step) */
bed->f1 += bezt->vec[1][0];
/* store average value in float 2 (only do rounding at last step)
* - this isn't always needed, but some operators may also require this
*/
bed->f2 += bezt->vec[1][1];
/* increment number of items */
bed->i1++;
}
@ -669,7 +674,20 @@ static short mirror_bezier_marker(BeztEditData *bed, BezTriple *bezt)
return 0;
}
/* Note: for markers case, need to set global vars (eww...) */
static short mirror_bezier_value(BeztEditData *bed, BezTriple *bezt)
{
float diff;
/* value to mirror over is stored in the custom data -> first float value slot */
if (bezt->f2 & SELECT) {
diff= (bed->f1 - bezt->vec[1][1]);
bezt->vec[1][1]= (bed->f1 + diff);
}
return 0;
}
/* Note: for markers and 'value', the values to use must be supplied as the first float value */
// calchandles_fcurve
BeztEditFunc ANIM_editkeyframes_mirror(short type)
{
@ -682,6 +700,8 @@ BeztEditFunc ANIM_editkeyframes_mirror(short type)
return mirror_bezier_xaxis;
case MIRROR_KEYS_MARKER: /* mirror over marker */
return mirror_bezier_marker;
case MIRROR_KEYS_VALUE: /* mirror over given value */
return mirror_bezier_value;
default: /* just in case */
return mirror_bezier_yaxis;
break;

View File

@ -1430,7 +1430,7 @@ int autokeyframe_cfra_can_key(Scene *scene, ID *id)
short fcurve_frame_has_keyframe (FCurve *fcu, float frame, short filter)
{
/* quick sanity check */
if (fcu == NULL)
if (ELEM(NULL, fcu, fcu->bezt))
return 0;
/* we either include all regardless of muting, or only non-muted */

View File

@ -142,6 +142,9 @@ static int add_default_keyingset_exec (bContext *C, wmOperator *op)
scene->active_keyingset= BLI_countlist(&scene->keyingsets);
/* send notifiers */
WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
return OPERATOR_FINISHED;
}
@ -182,6 +185,9 @@ static int remove_active_keyingset_exec (bContext *C, wmOperator *op)
/* the active one should now be the previously second-to-last one */
scene->active_keyingset--;
/* send notifiers */
WM_event_add_notifier(C, NC_SCENE|ND_KEYINGSET, NULL);
return OPERATOR_FINISHED;
}

View File

@ -214,6 +214,22 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
keymap= WM_keymap_find(keyconf, "Armature", 0, 0);
keymap->poll= ED_operator_editarmature;
/* Armature -> Etch-A-Ton ------------------------ */
WM_keymap_add_item(keymap, "SKETCH_OT_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_finish_stroke", SELECTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_cancel_stroke", ESCKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
/* sketch poll checks mode */
WM_keymap_add_item(keymap, "SKETCH_OT_gesture", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "snap", 1);
WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, 0, 0);
kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "snap", 1);
/* only set in editmode armature, by space_view3d listener */
// WM_keymap_add_item(keymap, "ARMATURE_OT_hide", HKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ARMATURE_OT_align", AKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
@ -278,22 +294,6 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
/* 2) set roll */
kmi= WM_keymap_add_item(keymap, "TFM_OT_transform", RKEY, KM_PRESS, KM_CTRL, 0);
RNA_enum_set(kmi->ptr, "mode", TFM_BONE_ROLL);
/* Armature -> Etch-A-Ton ------------------------ */
WM_keymap_add_item(keymap, "SKETCH_OT_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_delete", DELKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_finish_stroke", SELECTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_cancel_stroke", ESCKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
/* sketch poll checks mode */
WM_keymap_add_item(keymap, "SKETCH_OT_gesture", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "snap", 1);
WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, 0, 0);
kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "snap", 1);
/* Pose ------------------------ */
/* only set in posemode, by space_view3d listener */

View File

@ -55,6 +55,7 @@
#include "BLI_editVert.h"
#include "BLI_ghash.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
@ -5036,11 +5037,11 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
/* Set the flags */
CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) {
/* select pchan, only if selectable */
if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
if (sel==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
else pchan->bone->flag |= BONE_SELECTED;
}
/* select pchan only if selectable, but deselect works always */
if (sel==0)
pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE);
else if ((pchan->bone->flag & BONE_UNSELECTABLE)==0)
pchan->bone->flag |= BONE_SELECTED;
}
CTX_DATA_END;
@ -5289,9 +5290,8 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
/* now check if we're in editmode, we need to find the unique name */
if (arm->edbo) {
EditBone *eBone;
EditBone *eBone= editbone_name_exists(arm->edbo, oldname);
eBone= editbone_name_exists(arm->edbo, oldname);
if (eBone) {
unique_editbone_name(arm->edbo, newname, NULL);
BLI_strncpy(eBone->name, newname, MAXBONENAME);
@ -5302,7 +5302,7 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
Bone *bone= get_named_bone(arm, oldname);
if (bone) {
unique_bone_name (arm, newname);
unique_bone_name(arm, newname);
BLI_strncpy(bone->name, newname, MAXBONENAME);
}
else return;
@ -5313,21 +5313,7 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
/* we have the object using the armature */
if (arm==ob->data) {
Object *cob;
//bAction *act;
//bActionChannel *achan;
//bActionStrip *strip;
/* Rename action channel if necessary */
#if 0 // XXX old animation system
act = ob->action;
if (act && !act->id.lib) {
/* Find the appropriate channel */
achan= get_action_channel(act, oldname);
if (achan)
BLI_strncpy(achan->name, newname, MAXBONENAME);
}
#endif // XXX old animation system
/* Rename the pose channel, if it exists */
if (ob->pose) {
bPoseChannel *pchan = get_pose_channel(ob->pose, oldname);
@ -5335,20 +5321,6 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
BLI_strncpy(pchan->name, newname, MAXBONENAME);
}
/* check all nla-strips too */
#if 0 // XXX old animation system
for (strip= ob->nlastrips.first; strip; strip= strip->next) {
/* Rename action channel if necessary */
act = strip->act;
if (act && !act->id.lib) {
/* Find the appropriate channel */
achan= get_action_channel(act, oldname);
if (achan)
BLI_strncpy(achan->name, newname, MAXBONENAME);
}
}
#endif // XXX old animation system
/* Update any object constraints to use the new bone name */
for (cob= G.main->object.first; cob; cob= cob->id.next) {
if (cob->constraints.first)
@ -5379,31 +5351,14 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
BLI_strncpy(dg->name, newname, MAXBONENAME);
}
}
}
/* do entire db - ipo's for the drivers */
#if 0 // XXX old animation system
for (ipo= G.main->ipo.first; ipo; ipo= ipo->id.next) {
IpoCurve *icu;
/* check each curve's driver */
for (icu= ipo->curve.first; icu; icu= icu->next) {
IpoDriver *icd= icu->driver;
if ((icd) && (icd->ob)) {
ob= icd->ob;
if (icu->driver->type == IPO_DRIVER_TYPE_NORMAL) {
if (!strcmp(oldname, icd->name))
BLI_strncpy(icd->name, newname, MAXBONENAME);
}
else {
/* TODO: pydrivers need to be treated differently */
}
}
}
/* Fix animation data attached to this object */
// TODO: should we be using the database wide version instead (since drivers may break)
if (ob->adt) {
/* posechannels only... */
BKE_animdata_fix_paths_rename(&ob->id, ob->adt, "pose.pose_channels", oldname, newname);
}
}
#endif // XXX old animation system
}
}

View File

@ -1154,7 +1154,7 @@ void pose_adds_vgroups(Scene *scene, Object *meshobj, int heatweights)
return;
}
// XXX add_verts_to_dgroups(meshobj, poseobj, heatweights, (Gwp.flag & VP_MIRROR_X));
// XXX add_verts_to_dgroups(meshobj, poseobj, heatweights, ((Mesh *)(meshobj->data))->editflag & ME_EDIT_MIRROR_X);
if(heatweights)
BIF_undo_push("Apply Bone Heat Weights to Vertex Groups");

File diff suppressed because it is too large Load Diff

View File

@ -99,7 +99,7 @@ typedef struct bAnimListElem {
void *data; /* source data this elem represents */
int type; /* one of the ANIMTYPE_* values */
int flag; /* copy of elem's flags for quick access */
int index; /* copy of adrcode where applicable */
int index; /* for un-named data, the index of the data in it's collection */
void *key_data; /* motion data - mostly F-Curves, but can be other types too */
short datatype; /* type of motion data to expect */
@ -144,7 +144,7 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_DSMBALL,
ANIMTYPE_DSARM,
ANIMTYPE_SHAPEKEY, // XXX probably can become depreceated???
ANIMTYPE_SHAPEKEY,
ANIMTYPE_GPDATABLOCK,
ANIMTYPE_GPLAYER,
@ -209,7 +209,7 @@ typedef enum eAnimFilter_Flags {
#define FILTER_MAT_OBJC(ob) ((ob->nlaflag & OB_ADS_SHOWMATS))
#define FILTER_PART_OBJC(ob) ((ob->nlaflag & OB_ADS_SHOWPARTS))
/* 'Sub-object' channels (flags stored in Data block) */
#define FILTER_SKE_OBJD(key) ((key->flag & KEYBLOCK_DS_EXPAND))
#define FILTER_SKE_OBJD(key) ((key->flag & KEY_DS_EXPAND))
#define FILTER_MAT_OBJD(ma) ((ma->flag & MA_DS_EXPAND))
#define FILTER_LAM_OBJD(la) ((la->flag & LA_DS_EXPAND))
#define FILTER_CAM_OBJD(ca) ((ca->flag & CAM_DS_EXPAND))
@ -232,6 +232,10 @@ typedef enum eAnimFilter_Flags {
#define EDITABLE_FCU(fcu) ((fcu->flag & FCURVE_PROTECTED)==0)
#define SEL_FCU(fcu) (fcu->flag & (FCURVE_ACTIVE|FCURVE_SELECTED))
/* ShapeKey mode only */
#define EDITABLE_SHAPEKEY(kb) ((kb->flag & KEYBLOCK_LOCKED)==0)
#define SEL_SHAPEKEY(kb) (kb->flag & KEYBLOCK_SEL)
/* Grease Pencil only */
/* Grease Pencil datablock settings */
#define EXPANDED_GPD(gpd) (gpd->flag & GP_DATA_EXPAND)

View File

@ -82,6 +82,7 @@ typedef enum eEditKeyframes_Mirror {
MIRROR_KEYS_YAXIS,
MIRROR_KEYS_XAXIS,
MIRROR_KEYS_MARKER,
MIRROR_KEYS_VALUE,
} eEditKeyframes_Mirror;
/* ************************************************ */

View File

@ -59,6 +59,7 @@ struct UvVertMap;
struct UvMapVert;
struct Material;
struct Object;
struct recti;
// edge and face flag both
#define EM_FGON 2
@ -212,6 +213,7 @@ void EM_free_uv_vert_map(struct UvVertMap *vmap);
/* editmesh_mods.c */
extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs;
void EM_cache_x_mirror_vert(struct Object *ob, struct EditMesh *em);
void mouse_mesh(struct bContext *C, short mval[2], short extend);
int EM_check_backbuf(unsigned int index);
int EM_mask_init_backbuf_border(struct ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax);
@ -226,6 +228,10 @@ void EM_automerge(struct Scene *scene, struct Object *obedit, int update);
/* editface.c */
struct MTFace *EM_get_active_mtface(struct EditMesh *em, struct EditFace **act_efa, struct MCol **mcol, int sloppy);
int face_select(struct bContext *C, struct Object *ob, short mval[2], int extend);
void face_borderselect(struct bContext *C, struct Object *ob, struct rcti *rect, int select);
void deselectall_tface(struct Object *ob);
void select_linked_tfaces(struct bContext *C, struct Object *ob, short mval[2], int mode);
/* object_vgroup.c */
@ -237,6 +243,7 @@ struct bDeformGroup *ED_vgroup_add(struct Object *ob);
struct bDeformGroup *ED_vgroup_add_name(struct Object *ob, char *name);
void ED_vgroup_select_by_name(struct Object *ob, char *name);
void ED_vgroup_data_create(struct ID *id);
int ED_vgroup_give_array(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
void ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *dg, int vertnum, float weight, int assignmode);
void ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum);

View File

@ -102,8 +102,6 @@ void mouse_lattice(struct bContext *C, short mval[2], int extend);
void undo_push_lattice(struct bContext *C, char *name);
/* object_shapekey.c */
void insert_shapekey(struct Scene *scene, struct Object *ob);
void delete_key(struct Scene *scene, struct Object *ob);
void key_to_mesh(struct KeyBlock *kb, struct Mesh *me);
void mesh_to_key(struct Mesh *me, struct KeyBlock *kb);
void key_to_latt(struct KeyBlock *kb, struct Lattice *lt);

View File

@ -32,6 +32,11 @@
struct wmKeyConfig;
/* particle_edit.c */
int PE_poll(struct bContext *C);
int PE_hair_poll(struct bContext *C);
int PE_poll_3dview(struct bContext *C);
/* operators */
void ED_operatortypes_physics(void);
void ED_keymap_physics(struct wmKeyConfig *keyconf);

View File

@ -60,8 +60,8 @@ void ED_spacetype_userpref(void);
void ED_file_init(void);
void ED_file_exit(void);
#define REGION_DRAW_PRE 1
#define REGION_DRAW_POST 0
#define REGION_DRAW_POST_VIEW 0
#define REGION_DRAW_POST_PIXEL 1
void *ED_region_draw_cb_activate(struct ARegionType *,
void (*draw)(const struct bContext *, struct ARegion *, void *),

View File

@ -523,7 +523,7 @@ DEF_ICON(ICON_MOD_UVPROJECT)
DEF_ICON(ICON_MOD_DISPLACE)
DEF_ICON(ICON_MOD_CURVE)
DEF_ICON(ICON_MOD_LATTICE)
DEF_ICON(ICON_BLANK143)
DEF_ICON(ICON_CONSTRAINT_DATA)
DEF_ICON(ICON_MOD_ARMATURE)
DEF_ICON(ICON_MOD_SHRINKWRAP)
DEF_ICON(ICON_MOD_CAST)

View File

@ -148,6 +148,7 @@ typedef struct uiLayout uiLayout;
#define UI_BUT_LAST_ACTIVE (1<<24)
#define UI_BUT_UNDO (1<<25)
#define UI_BUT_IMMEDIATE (1<<26)
#define UI_BUT_NO_TOOLTIP (1<<27)
#define UI_PANEL_WIDTH 340
#define UI_COMPACT_PANEL_WIDTH 160
@ -603,16 +604,17 @@ int uiLayoutGetKeepAspect(uiLayout *layout);
int uiLayoutGetWidth(uiLayout *layout);
float uiLayoutGetScaleX(uiLayout *layout);
float uiLayoutGetScaleY(uiLayout *layout);
ListBase *uiLayoutBoxGetList(uiLayout *layout);
/* layout specifiers */
uiLayout *uiLayoutRow(uiLayout *layout, int align);
uiLayout *uiLayoutColumn(uiLayout *layout, int align);
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align);
uiLayout *uiLayoutBox(uiLayout *layout);
uiLayout *uiLayoutListBox(uiLayout *layout);
uiLayout *uiLayoutFree(uiLayout *layout, int align);
uiLayout *uiLayoutListBox(uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop,
struct PointerRNA *actptr, struct PropertyRNA *actprop);
uiLayout *uiLayoutAbsolute(uiLayout *layout, int align);
uiLayout *uiLayoutSplit(uiLayout *layout, float percentage);
uiLayout *uiLayoutOverlap(uiLayout *layout);
uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout);
@ -639,14 +641,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C);
void uiTemplate_view3d_select_faceselmenu(uiLayout *layout, struct bContext *C);
void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *tex);
typedef struct uiListItem {
struct uiListItem *next, *prev;
struct PointerRNA data;
uiLayout *layout;
} uiListItem;
ListBase uiTemplateList(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *activeptr, char *activeprop, int rows, int type);
void uiTemplateList(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *activeptr, char *activeprop, int rows, int type);
/* items */
void uiItemO(uiLayout *layout, char *name, int icon, char *opname);
@ -683,6 +678,7 @@ void uiIDContextProperty(struct bContext *C, struct PointerRNA *ptr, struct Prop
/* Styled text draw */
void uiStyleFontSet(struct uiFontStyle *fs);
void uiStyleFontDraw(struct uiFontStyle *fs, struct rcti *rect, char *str);
void uiStyleFontDrawRotated(struct uiFontStyle *fs, struct rcti *rect, char *str);
int UI_GetStringWidth(char *str); // XXX temp
void UI_DrawString(float x, float y, char *str); // XXX temp

View File

@ -49,6 +49,7 @@ CPPFLAGS += -I../../makesrna
CPPFLAGS += -I../../imbuf
CPPFLAGS += -I../../blenfont
CPPFLAGS += -I../../python
CPPFLAGS += -I../../gpu
# own include

View File

@ -7,7 +7,7 @@ for source in env.Glob('*_api.c'):
sources.remove(source)
incs = '../include ../../blenlib ../../blenfont ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc'
incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc ../../gpu'
incs += ' #/extern/glew/include'
incs += ' ../../python/' # python button eval

View File

@ -92,6 +92,7 @@ typedef enum uiHandleButtonState {
} uiHandleButtonState;
typedef struct uiHandleButtonData {
wmWindowManager *wm;
wmWindow *window;
ARegion *region;
@ -1943,8 +1944,11 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
{
if(data->state == BUTTON_STATE_HIGHLIGHT) {
if(ELEM4(event->type, LEFTMOUSE, PADENTER, RETKEY, EVT_BUT_OPEN) && event->val==KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
return WM_UI_HANDLER_BREAK;
if(but->dt == UI_EMBOSSN && !event->ctrl);
else {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
return WM_UI_HANDLER_BREAK;
}
}
}
else if(data->state == BUTTON_STATE_TEXT_EDITING) {
@ -2056,9 +2060,21 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
/* Mouse location isn't screen clamped to the screen so use a linear mapping
* 2px == 1-int, or 1px == 1-ClickStep */
if(ui_is_but_float(but)) {
tempf = data->startvalue + ((mx - data->dragstartx) * fac * 0.01*but->a1);
fac *= 0.01*but->a1;
tempf = data->startvalue + ((mx - data->dragstartx) * fac);
tempf= ui_numedit_apply_snapf(tempf, softmin, softmax, softrange, snap);
#if 1 /* fake moving the click start, nicer for dragging back after passing the limit */
if(tempf < softmin) {
data->dragstartx -= (softmin-tempf) / fac;
tempf= softmin;
} else if (tempf > softmax) {
data->dragstartx += (tempf-softmax) / fac;
tempf= softmax;
}
#else
CLAMP(tempf, softmin, softmax);
#endif
if(tempf != data->value) {
data->dragchange= 1;
@ -2067,9 +2083,22 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
}
}
else {
temp= data->startvalue + (mx - data->dragstartx)/2; /* simple 2px == 1 */
fac = 0.5; /* simple 2px == 1 */
temp= data->startvalue + ((mx - data->dragstartx) * fac);
temp= ui_numedit_apply_snap(temp, softmin, softmax, snap);
#if 1 /* fake moving the click start, nicer for dragging back after passing the limit */
if(temp < softmin) {
data->dragstartx -= (softmin-temp) / fac;
temp= softmin;
} else if (temp > softmax) {
data->dragstartx += (temp-softmax) / fac;
temp= softmax;
}
#else
CLAMP(temp, softmin, softmax);
#endif
if(temp != data->value) {
data->dragchange= 1;
@ -2077,6 +2106,8 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
changed= 1;
}
}
data->draglastx= mx;
}
else {
/* Use a non-linear mapping of the mouse drag especially for large floats (normal behavior) */
@ -3625,15 +3656,35 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
if(but->flag & UI_HIDDEN)
continue;
if(ui_but_contains_pt(but, mx, my))
/* give precedence to already activated buttons */
if(!butover || (!butover->active && but->active))
butover= but;
butover= but;
}
}
return butover;
}
static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
{
uiBlock *block;
uiBut *but;
int mx, my;
if(!ui_mouse_inside_region(ar, x, y))
return NULL;
for(block=ar->uiblocks.first; block; block=block->next) {
mx= x;
my= y;
ui_window_to_block(ar, block, &mx, &my);
for(but=block->buttons.last; but; but= but->prev)
if(but->type == LISTBOX && ui_but_contains_pt(but, mx, my))
return but;
}
return NULL;
}
/* ****************** button state handling **************************/
static int button_modal_state(uiHandleButtonState state)
@ -3650,7 +3701,7 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but)
data= but->active;
if(data->tooltiptimer) {
WM_event_remove_window_timer(data->window, data->tooltiptimer);
WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
data->tooltiptimer= NULL;
}
if(data->tooltip) {
@ -3659,7 +3710,7 @@ static void button_timers_tooltip_remove(bContext *C, uiBut *but)
}
if(data->autoopentimer) {
WM_event_remove_window_timer(data->window, data->autoopentimer);
WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
data->autoopentimer= NULL;
}
}
@ -3671,13 +3722,13 @@ static void button_tooltip_timer_reset(uiBut *but)
data= but->active;
if(data->tooltiptimer) {
WM_event_remove_window_timer(data->window, data->tooltiptimer);
WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
data->tooltiptimer= NULL;
}
if(U.flag & USER_TOOLTIPS)
if(!but->block->tooltipdisabled)
data->tooltiptimer= WM_event_add_window_timer(data->window, TIMER, BUTTON_TOOLTIP_DELAY);
data->tooltiptimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY);
}
static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state)
@ -3705,7 +3756,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
else time= -1;
if(time >= 0)
data->autoopentimer= WM_event_add_window_timer(data->window, TIMER, 0.02*(double)time);
data->autoopentimer= WM_event_add_timer(data->wm, data->window, TIMER, 0.02*(double)time);
}
}
}
@ -3723,12 +3774,12 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
/* number editing */
if(state == BUTTON_STATE_NUM_EDITING) {
if(ui_is_a_warp_but(but))
WM_cursor_grab(CTX_wm_window(C), TRUE);
WM_cursor_grab(CTX_wm_window(C), TRUE, TRUE, NULL);
ui_numedit_begin(but, data);
} else if(data->state == BUTTON_STATE_NUM_EDITING) {
ui_numedit_end(but, data);
if(ui_is_a_warp_but(but))
WM_cursor_ungrab(CTX_wm_window(C), FALSE);
WM_cursor_ungrab(CTX_wm_window(C));
}
/* menu open */
if(state == BUTTON_STATE_MENU_OPEN)
@ -3738,10 +3789,10 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
/* add a short delay before exiting, to ensure there is some feedback */
if(state == BUTTON_STATE_WAIT_FLASH) {
data->flashtimer= WM_event_add_window_timer(data->window, TIMER, BUTTON_FLASH_DELAY);
data->flashtimer= WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_FLASH_DELAY);
}
else if(data->flashtimer) {
WM_event_remove_window_timer(data->window, data->flashtimer);
WM_event_remove_timer(data->wm, data->window, data->flashtimer);
data->flashtimer= NULL;
}
@ -3772,6 +3823,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
/* setup struct */
data= MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData");
data->wm= CTX_wm_manager(C);
data->window= CTX_wm_window(C);
data->region= ar;
if( ELEM(but->type, BUT_CURVE, SEARCH_MENU) ); // XXX curve is temp
@ -3999,6 +4051,10 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
data->cancel= 1;
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
else if(ui_but_find_mouse_over(ar, event->x, event->y) != but) {
data->cancel= 1;
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
else if(event->x!=event->prevx || event->y!=event->prevy) {
/* re-enable tooltip on mouse move */
ui_blocks_set_tooltips(ar, 1);
@ -4009,7 +4065,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
case TIMER: {
/* handle tooltip timer */
if(event->customdata == data->tooltiptimer) {
WM_event_remove_window_timer(data->window, data->tooltiptimer);
WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
data->tooltiptimer= NULL;
if(!data->tooltip)
@ -4017,7 +4073,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
}
/* handle menu auto open timer */
else if(event->customdata == data->autoopentimer) {
WM_event_remove_window_timer(data->window, data->autoopentimer);
WM_event_remove_timer(data->wm, data->window, data->autoopentimer);
data->autoopentimer= NULL;
if(ui_mouse_inside_button(ar, but, event->x, event->y))
@ -4031,7 +4087,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
case MIDDLEMOUSE:
/* XXX hardcoded keymap check... but anyway, while view changes, tooltips should be removed */
if(data->tooltiptimer) {
WM_event_remove_window_timer(data->window, data->tooltiptimer);
WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
data->tooltiptimer= NULL;
}
/* pass on purposedly */
@ -4122,6 +4178,71 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
return retval;
}
static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
{
uiBut *but= ui_list_find_mouse_over(ar, event->x, event->y);
int retval= WM_UI_HANDLER_CONTINUE;
int value, min, max;
if(but && (event->val == KM_PRESS)) {
Panel *pa= but->block->panel;
if(ELEM(event->type, UPARROWKEY, DOWNARROWKEY) ||
((ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt))) {
/* activate up/down the list */
value= RNA_property_int_get(&but->rnapoin, but->rnaprop);
if(ELEM(event->type, UPARROWKEY, WHEELUPMOUSE))
value--;
else
value++;
if(value < pa->list_scroll)
pa->list_scroll= value;
else if(value >= pa->list_scroll+pa->list_size)
pa->list_scroll= value - pa->list_size + 1;
RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
value= CLAMPIS(value, min, max);
RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
RNA_property_update(C, &but->rnapoin, but->rnaprop);
ED_region_tag_redraw(ar);
retval= WM_UI_HANDLER_BREAK;
}
else if(ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
/* silly replacement for proper grip */
if(pa->list_grip_size == 0)
pa->list_grip_size= pa->list_size;
if(event->type == WHEELUPMOUSE)
pa->list_grip_size--;
else
pa->list_grip_size++;
pa->list_grip_size= MAX2(pa->list_grip_size, 1);
ED_region_tag_redraw(ar);
retval= WM_UI_HANDLER_BREAK;
}
else if(ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
/* list template will clamp */
if(event->type == WHEELUPMOUSE)
pa->list_scroll--;
else
pa->list_scroll++;
ED_region_tag_redraw(ar);
retval= WM_UI_HANDLER_BREAK;
}
}
return retval;
}
static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *but)
{
uiHandleButtonData *data;
@ -4586,6 +4707,9 @@ static int ui_handler_region(bContext *C, wmEvent *event, void *userdata)
if(!but || !button_modal_state(but->active->state))
retval= ui_handler_panel_region(C, event);
if(retval == WM_UI_HANDLER_CONTINUE)
retval= ui_handle_list_event(C, event, ar);
if(retval == WM_UI_HANDLER_CONTINUE) {
if(but)
retval= ui_handle_button_event(C, event, but);

View File

@ -38,6 +38,8 @@
#endif
#include "MEM_guardedalloc.h"
#include "GPU_extensions.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BLI_storage_types.h"
@ -489,7 +491,7 @@ static void init_internal_icons()
}
/* we only use a texture for cards with non-power of two */
if(GLEW_ARB_texture_non_power_of_two) {
if(GPU_non_power_of_two_support()) {
glGenTextures(1, &icongltex.id);
if(icongltex.id) {

View File

@ -98,6 +98,7 @@ typedef enum uiItemType {
ITEM_LAYOUT_BOX,
ITEM_LAYOUT_ABSOLUTE,
ITEM_LAYOUT_SPLIT,
ITEM_LAYOUT_OVERLAP,
ITEM_LAYOUT_ROOT
#if 0
@ -148,7 +149,6 @@ typedef struct uiLayoutItemFlow {
typedef struct uiLayoutItemBx {
uiLayout litem;
uiBut *roundbox;
ListBase items;
} uiLayoutItemBx;
typedef struct uiLayoutItemSplt {
@ -286,6 +286,7 @@ static int ui_layout_local_dir(uiLayout *layout)
switch(layout->item.type) {
case ITEM_LAYOUT_ROW:
case ITEM_LAYOUT_ROOT:
case ITEM_LAYOUT_OVERLAP:
return UI_LAYOUT_HORIZONTAL;
case ITEM_LAYOUT_COLUMN:
case ITEM_LAYOUT_COLUMN_FLOW:
@ -362,7 +363,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, char *name, int icon
int cols= (len >= 20)? 2: 1;
int colbuts= len/(2*cols);
uiBlockSetCurLayout(block, uiLayoutFree(layout, 0));
uiBlockSetCurLayout(block, uiLayoutAbsolute(layout, 0));
unit= UI_UNIT_X*0.75;
butw= unit;
@ -390,7 +391,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, char *name, int icon
/* matrix layout */
int row, col;
uiBlockSetCurLayout(block, uiLayoutFree(layout, 1));
uiBlockSetCurLayout(block, uiLayoutAbsolute(layout, 1));
len= ceil(sqrt(len));
@ -892,10 +893,13 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper
name= ui_item_name_add_colon(name, namestr);
if(layout->root->type == UI_LAYOUT_MENU) {
if(type == PROP_BOOLEAN)
icon= (RNA_property_boolean_get(ptr, prop))? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
else if(type == PROP_ENUM && index == RNA_ENUM_VALUE)
icon= (RNA_property_enum_get(ptr, prop) == value)? ICON_CHECKBOX_HLT: ICON_CHECKBOX_DEHLT;
/* whether the property is actually enabled doesn't matter,
* since the widget code for drawing toggles takes care of the
* rest (i.e. given the deactivated icon, it finds the active one
* based on the state of the setting)
*/
if ( (type == PROP_BOOLEAN) || (type==PROP_ENUM && index==RNA_ENUM_VALUE) )
icon= ICON_CHECKBOX_DEHLT; /* ICON_CHECKBOX_HLT when on... */
}
slider= (flag & UI_ITEM_R_SLIDER);
@ -1051,10 +1055,14 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, ui
{
uiBut *but= arg_but;
char *name;
int i, iconid;
int i, iconid, flag= RNA_property_flag(but->rnaprop);
i = 0;
RNA_PROP_BEGIN(&but->rnasearchpoin, itemptr, but->rnasearchprop) {
if(flag & PROP_ID_SELF_CHECK)
if(itemptr.data == but->rnapoin.id.data)
continue;
iconid= 0;
if(RNA_struct_is_ID(itemptr.type))
iconid= ui_id_icon_get((bContext*)C, itemptr.data);
@ -1495,11 +1503,11 @@ static void ui_litem_layout_row(uiLayout *litem)
/* align right/center */
offset= 0;
if(litem->alignment == UI_LAYOUT_ALIGN_RIGHT) {
if(fixedw == 0 && freew < w-fixedw)
if(freew > 0 && freew < w-fixedw)
offset= (w - fixedw) - freew;
}
else if(litem->alignment == UI_LAYOUT_ALIGN_CENTER) {
if(fixedw == 0 && freew < w-fixedw)
if(freew > 0 && freew < w-fixedw)
offset= ((w - fixedw) - freew)/2;
}
@ -1862,6 +1870,42 @@ static void ui_litem_layout_split(uiLayout *litem)
litem->y= y;
}
/* overlap layout */
static void ui_litem_estimate_overlap(uiLayout *litem)
{
uiItem *item;
int itemw, itemh;
litem->w= 0;
litem->h= 0;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, &itemw, &itemh);
litem->w= MAX2(itemw, litem->w);
litem->h= MAX2(itemh, litem->h);
}
}
static void ui_litem_layout_overlap(uiLayout *litem)
{
uiItem *item;
int itemw, itemh, x, y;
x= litem->x;
y= litem->y;
for(item=litem->items.first; item; item=item->next) {
ui_item_size(item, &itemw, &itemh);
ui_item_position(item, x, y-itemh, litem->w, itemh);
litem->h= MAX2(litem->h, itemh);
}
litem->x= x;
litem->y= y - litem->h;
}
/* layout create functions */
uiLayout *uiLayoutRow(uiLayout *layout, int align)
{
@ -1921,7 +1965,7 @@ uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align)
return &flow->litem;
}
static uiLayout *ui_layout_box(uiLayout *layout, int type)
static uiLayoutItemBx *ui_layout_box(uiLayout *layout, int type)
{
uiLayoutItemBx *box;
@ -1938,30 +1982,32 @@ static uiLayout *ui_layout_box(uiLayout *layout, int type)
box->roundbox= uiDefBut(layout->root->block, type, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
return &box->litem;
return box;
}
uiLayout *uiLayoutBox(uiLayout *layout)
{
return ui_layout_box(layout, ROUNDBOX);
return (uiLayout*)ui_layout_box(layout, ROUNDBOX);
}
uiLayout *uiLayoutListBox(uiLayout *layout)
uiLayout *uiLayoutListBox(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr, PropertyRNA *actprop)
{
return ui_layout_box(layout, LISTBOX);
uiLayoutItemBx *box= ui_layout_box(layout, LISTBOX);
uiBut *but= box->roundbox;
but->rnasearchpoin= *ptr;
but->rnasearchprop= prop;
but->rnapoin= *actptr;
but->rnaprop= actprop;
return (uiLayout*)box;
}
ListBase *uiLayoutBoxGetList(uiLayout *layout)
{
uiLayoutItemBx *box= (uiLayoutItemBx*)layout;
return &box->items;
}
uiLayout *uiLayoutFree(uiLayout *layout, int align)
uiLayout *uiLayoutAbsolute(uiLayout *layout, int align)
{
uiLayout *litem;
litem= MEM_callocN(sizeof(uiLayout), "uiLayoutFree");
litem= MEM_callocN(sizeof(uiLayout), "uiLayoutAbsolute");
litem->item.type= ITEM_LAYOUT_ABSOLUTE;
litem->root= layout->root;
litem->align= align;
@ -1980,11 +2026,28 @@ uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout)
uiBlock *block;
block= uiLayoutGetBlock(layout);
uiLayoutFree(layout, 0);
uiLayoutAbsolute(layout, 0);
return block;
}
uiLayout *uiLayoutOverlap(uiLayout *layout)
{
uiLayout *litem;
litem= MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap");
litem->item.type= ITEM_LAYOUT_OVERLAP;
litem->root= layout->root;
litem->active= 1;
litem->enabled= 1;
litem->context= layout->context;
BLI_addtail(&layout->items, litem);
uiBlockSetCurLayout(layout->root->block, litem);
return litem;
}
uiLayout *uiLayoutSplit(uiLayout *layout, float percentage)
{
uiLayoutItemSplt *split;
@ -2142,6 +2205,9 @@ static void ui_item_estimate(uiItem *item)
case ITEM_LAYOUT_SPLIT:
ui_litem_estimate_split(litem);
break;
case ITEM_LAYOUT_OVERLAP:
ui_litem_estimate_overlap(litem);
break;
default:
break;
}
@ -2162,6 +2228,7 @@ static void ui_item_align(uiLayout *litem, int nr)
bitem->but->alignnr= nr;
}
else if(item->type == ITEM_LAYOUT_ABSOLUTE);
else if(item->type == ITEM_LAYOUT_OVERLAP);
else if(item->type == ITEM_LAYOUT_BOX) {
box= (uiLayoutItemBx*)item;
box->roundbox->alignnr= nr;
@ -2227,6 +2294,9 @@ static void ui_item_layout(uiItem *item)
case ITEM_LAYOUT_SPLIT:
ui_litem_layout_split(litem);
break;
case ITEM_LAYOUT_OVERLAP:
ui_litem_layout_overlap(litem);
break;
default:
break;
}
@ -2261,9 +2331,6 @@ static void ui_layout_free(uiLayout *layout)
ui_layout_free((uiLayout*)item);
}
if(layout->item.type == ITEM_LAYOUT_BOX)
BLI_freelistN(&((uiLayoutItemBx*)layout)->items);
MEM_freeN(layout);
}

View File

@ -309,20 +309,6 @@ void uiPanelToMouse(const bContext *C, Panel *pa)
}
#endif
static int panel_has_tabs(ARegion *ar, Panel *panel)
{
Panel *pa= ar->panels.first;
if(panel==NULL) return 0;
while(pa) {
if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==panel) {
return 1;
}
pa= pa->next;
}
return 0;
}
static void ui_offset_panel_block(uiBlock *block)
{
@ -465,62 +451,32 @@ static void ui_draw_panel_dragwidget(rctf *rect)
}
static void ui_draw_aligned_panel_header(ARegion *ar, uiStyle *style, uiBlock *block, rcti *rect)
static void ui_draw_aligned_panel_header(ARegion *ar, uiStyle *style, uiBlock *block, rcti *rect, char dir)
{
Panel *panel= block->panel;
Panel *pa;
rcti hrect;
float width;
int a, nr= 1, pnl_icons;
int pnl_icons;
char *activename= panel->drawname[0]?panel->drawname:panel->panelname;
char *panelname;
/* count */
for(pa= ar->panels.first; pa; pa=pa->next)
if(pa->runtime_flag & PNL_ACTIVE)
if(pa->paneltab==panel)
nr++;
/* + 0.001f to avoid flirting with float inaccuracy */
if(panel->control & UI_PNL_CLOSE) pnl_icons=(panel->labelofs+2*PNL_ICON+5)/block->aspect + 0.001f;
else pnl_icons= (panel->labelofs+PNL_ICON+5)/block->aspect + 0.001f;
if(nr==1) {
/* active tab */
/* draw text label */
UI_ThemeColor(TH_TITLE);
hrect= *rect;
/* active tab */
/* draw text label */
UI_ThemeColor(TH_TITLE);
hrect= *rect;
if(dir == 'h') {
hrect.xmin= rect->xmin+pnl_icons;
uiStyleFontDraw(&style->paneltitle, &hrect, activename);
return;
}
a= 0;
width= (rect->xmax-rect->xmin - 3 - pnl_icons - PNL_ICON)/nr;
for(pa= ar->panels.first; pa; pa=pa->next) {
panelname= pa->drawname[0]?pa->drawname:pa->panelname;
if((pa->runtime_flag & PNL_ACTIVE) && (pa==panel || pa->paneltab==panel)) {
float col[3];
UI_GetThemeColor3fv(TH_TITLE, col);
/* active tab */
if(pa==panel)
glColor4f(col[0], col[1], col[2], 1.0f);
else
glColor4f(col[0], col[1], col[2], 0.5f);
hrect= *rect;
hrect.xmin= rect->xmin+pnl_icons + a*width;
hrect.xmax= hrect.xmin + width;
uiStyleFontDraw(&style->paneltitle, &hrect, panelname);
a++;
}
else {
/* ignore 'pnl_icons', otherwise the text gets offset horizontally
* + 0.001f to avoid flirting with float inaccuracy
*/
hrect.xmin= rect->xmin + (PNL_ICON+5)/block->aspect + 0.001f;
uiStyleFontDrawRotated(&style->paneltitle, &hrect, activename);
}
}
@ -567,9 +523,9 @@ void ui_draw_aligned_panel(ARegion *ar, uiStyle *style, uiBlock *block, rcti *re
glDisable(GL_BLEND);
}
/* title */
/* horizontal title */
if(!(panel->flag & PNL_CLOSEDX)) {
ui_draw_aligned_panel_header(ar, style, block, &headrect);
ui_draw_aligned_panel_header(ar, style, block, &headrect, 'h');
/* itemrect smaller */
itemrect.xmax= headrect.xmax - 5.0f/block->aspect;
@ -585,16 +541,10 @@ void ui_draw_aligned_panel(ARegion *ar, uiStyle *style, uiBlock *block, rcti *re
*/
if(panel->flag & PNL_CLOSEDY) {
/* if it's being overlapped by a panel being dragged */
if(panel->flag & PNL_OVERLAP) {
UI_ThemeColor(TH_TEXT_HI);
uiRoundRect(rect->xmin, rect->ymax, rect->xmax, rect->ymax+PNL_HEADER, 8);
}
}
else if(panel->flag & PNL_CLOSEDX) {
/* draw vertical title */
ui_draw_aligned_panel_header(ar, style, block, &headrect, 'v');
}
/* an open panel */
else {
@ -607,13 +557,6 @@ void ui_draw_aligned_panel(ARegion *ar, uiStyle *style, uiBlock *block, rcti *re
UI_ThemeColorShade(TH_BACK, -120);
uiRoundRect(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax+1, 8);
}
if(panel->flag & PNL_OVERLAP) {
if(panel->control & UI_PNL_SOLID) uiSetRoundBox(15);
else uiSetRoundBox(3);
UI_ThemeColor(TH_TEXT_HI);
uiRoundRect(rect->xmin, rect->ymin, rect->xmax, headrect.ymax+1, 8);
}
if(panel->control & UI_PNL_SCALE)
ui_draw_panel_scalewidget(rect);
@ -963,62 +906,6 @@ static void check_panel_overlap(ARegion *ar, Panel *panel)
}
}
#if 0 // XXX panel docking/tabbing code that's no longer used
static void test_add_new_tabs(ARegion *ar)
{
Panel *pa, *pasel=NULL, *palap=NULL;
/* search selected and overlapped panel */
pa= ar->panels.first;
while(pa) {
if(pa->runtime_flag & PNL_ACTIVE) {
if(pa->flag & PNL_SELECT) pasel= pa;
if(pa->flag & PNL_OVERLAP) palap= pa;
}
pa= pa->next;
}
if(pasel && palap==NULL) {
/* copy locations */
pa= ar->panels.first;
while(pa) {
if(pa->paneltab==pasel) {
ui_panel_copy_offset(pa, pasel);
}
pa= pa->next;
}
}
if(pasel==NULL || palap==NULL) return;
if(palap->type && palap->type->flag & PNL_NO_HEADER) return;
/* the overlapped panel becomes a tab */
palap->paneltab= pasel;
/* the selected panel gets coords of overlapped one */
ui_panel_copy_offset(pasel, palap);
/* and its tabs */
pa= ar->panels.first;
while(pa) {
if(pa->paneltab == pasel) {
ui_panel_copy_offset(pa, palap);
}
pa= pa->next;
}
/* but, the overlapped panel already can have tabs too! */
pa= ar->panels.first;
while(pa) {
if(pa->paneltab == palap) {
pa->paneltab = pasel;
}
pa= pa->next;
}
}
#endif
/************************ panel dragging ****************************/
static void ui_do_drag(const bContext *C, wmEvent *event, Panel *panel)
@ -1061,99 +948,8 @@ static void ui_do_drag(const bContext *C, wmEvent *event, Panel *panel)
ED_region_tag_redraw(ar);
}
static void ui_do_untab(const bContext *C, wmEvent *event, Panel *panel)
{
uiHandlePanelData *data= panel->activedata;
ARegion *ar= CTX_wm_region(C);
Panel *pa, *panew= NULL;
int nr;
/* wait until a threshold is passed to untab */
if(abs(event->x-data->startx) + abs(event->y-data->starty) > 6) {
/* find new parent panel */
nr= 0;
for(pa= ar->panels.first; pa; pa=pa->next) {
if(pa->paneltab==panel) {
panew= pa;
nr++;
}
}
/* make old tabs point to panew */
panew->paneltab= NULL;
for(pa= ar->panels.first; pa; pa=pa->next)
if(pa->paneltab==panel)
pa->paneltab= panew;
panel_activate_state(C, panel, PANEL_STATE_DRAG);
}
}
/******************* region level panel interaction *****************/
static void panel_clicked_tabs(const bContext *C, ScrArea *sa, ARegion *ar, uiBlock *block, int mousex)
{
Panel *pa, *tabsel=NULL, *panel= block->panel;
int nr= 1, a, width, ofsx;
ofsx= PNL_ICON;
if(block->panel->type && (block->panel->control & UI_PNL_CLOSE)) ofsx+= PNL_ICON;
/* count */
for(pa= ar->panels.first; pa; pa=pa->next)
if(pa!=panel)
if((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==panel)
nr++;
if(nr==1) return;
/* find clicked tab, mouse in panel coords */
a= 0;
width= (int)((float)(panel->sizex - ofsx-10)/nr);
pa= ar->panels.first;
while(pa) {
if(pa==panel || ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab==panel)) {
if((mousex > ofsx+a*width) && (mousex < ofsx+(a+1)*width)) {
tabsel= pa;
break;
}
a++;
}
pa= pa->next;
}
if(tabsel) {
if(tabsel == panel) {
panel_activate_state(C, panel, PANEL_STATE_WAIT_UNTAB);
}
else {
/* tabsel now becomes parent for all others */
panel->paneltab= tabsel;
tabsel->paneltab= NULL;
pa= ar->panels.first;
while(pa) {
if(pa->paneltab == panel) pa->paneltab = tabsel;
pa= pa->next;
}
/* copy locations to tabs */
for(pa= ar->panels.first; pa; pa= pa->next) {
if(pa->paneltab && pa->runtime_flag & PNL_ACTIVE) {
ui_panel_copy_offset(pa, pa->paneltab);
}
}
/* panels now differ size.. */
if(panel_aligned(sa, ar))
panel_activate_state(C, tabsel, PANEL_STATE_ANIMATION);
ED_region_tag_redraw(ar);
}
}
}
/* this function is supposed to call general window drawing too */
/* also it supposes a block has panel, and isnt a menu */
@ -1217,10 +1013,6 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
else if(block->panel->flag & PNL_CLOSED) {
panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
}
/* check if clicked in tabbed area */
else if(mx < block->maxx-PNL_ICON-3 && panel_has_tabs(ar, block->panel)) {
panel_clicked_tabs(C, sa, ar, block, mx);
}
else {
panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
}
@ -1346,9 +1138,7 @@ static int ui_handler_panel(bContext *C, wmEvent *event, void *userdata)
panel_activate_state(C, panel, PANEL_STATE_EXIT);
}
else if(event->type == MOUSEMOVE) {
if(data->state == PANEL_STATE_WAIT_UNTAB)
ui_do_untab(C, event, panel);
else if(data->state == PANEL_STATE_DRAG)
if(data->state == PANEL_STATE_DRAG)
ui_do_drag(C, event, panel);
}
else if(event->type == TIMER && event->customdata == data->animtimer) {
@ -1399,7 +1189,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
pa->flag |= PNL_SELECT;
if(data && data->animtimer) {
WM_event_remove_window_timer(win, data->animtimer);
WM_event_remove_timer(CTX_wm_manager(C), win, data->animtimer);
data->animtimer= NULL;
}
@ -1418,7 +1208,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat
}
if(ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG))
data->animtimer= WM_event_add_window_timer(win, TIMER, ANIMATION_INTERVAL);
data->animtimer= WM_event_add_timer(CTX_wm_manager(C), win, TIMER, ANIMATION_INTERVAL);
data->state= state;
data->startx= win->eventstate->x;

View File

@ -357,6 +357,9 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
float x1f, x2f, y1f, y2f;
int x1, x2, y1, y2, winx, winy, ofsx, ofsy, w, h, a;
if(but->flag & UI_BUT_NO_TOOLTIP)
return NULL;
/* create tooltip data */
data= MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");

View File

@ -184,6 +184,60 @@ void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, char *str)
BLF_disable(BLF_KERNING_DEFAULT);
}
/* drawn same as above, but at 90 degree angle */
void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, char *str)
{
float height;
int xofs, yofs;
float angle;
rcti txtrect;
uiStyleFontSet(fs);
height= BLF_height("2"); /* correct offset is on baseline, the j is below that */
/* becomes x-offset when rotated */
xofs= floor( 0.5f*(rect->ymax - rect->ymin - height)) + 1;
/* ignore UI_STYLE, always aligned to top */
/* rotate counter-clockwise for now (assumes left-to-right language)*/
xofs+= height;
yofs= BLF_width(str) + 5;
angle= 90.0f;
/* translate rect to vertical */
txtrect.xmin= rect->xmin - (rect->ymax - rect->ymin);
txtrect.ymin= rect->ymin - (rect->xmax - rect->xmin);
txtrect.xmax= rect->xmin;
txtrect.ymax= rect->ymin;
/* clip is very strict, so we give it some space */
/* clipping is done without rotation, so make rect big enough to contain both positions */
BLF_clipping(txtrect.xmin-1, txtrect.ymin-yofs-xofs-4, rect->xmax+1, rect->ymax+4);
BLF_enable(BLF_CLIPPING);
BLF_position(txtrect.xmin+xofs, txtrect.ymax-yofs, 0.0f);
BLF_enable(BLF_ROTATION);
BLF_rotation(angle);
if (fs->shadow) {
BLF_enable(BLF_SHADOW);
BLF_shadow(fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
BLF_shadow_offset(fs->shadx, fs->shady);
}
if (fs->kerning == 1)
BLF_enable(BLF_KERNING_DEFAULT);
BLF_draw(str);
BLF_disable(BLF_ROTATION);
BLF_disable(BLF_CLIPPING);
if (fs->shadow)
BLF_disable(BLF_SHADOW);
if (fs->kerning == 1)
BLF_disable(BLF_KERNING_DEFAULT);
}
/* ************** helpers ************************ */
/* temporarily, does widget font */

View File

@ -506,7 +506,7 @@ static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
{
Object *ob = ob_v;
ModifierData *md= md_v;
int i, cageIndex = modifiers_getCageIndex(ob, NULL );
int i, cageIndex = modifiers_getCageIndex(ob, NULL, 0);
/* undo button operation */
md->mode ^= eModifierMode_OnCage;
@ -715,7 +715,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, PointerRNA *ptr)
uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
/* find modifier and draw it */
cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
cageIndex = modifiers_getCageIndex(ob, &lastCageIndex, 0);
// XXX virtual modifiers are not accesible for python
vmd = modifiers_getVirtualModifierList(ob);
@ -1925,25 +1925,6 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname)
/************************* List Template **************************/
#if 0
static void list_item_add(ListBase *lb, ListBase *itemlb, uiLayout *layout, PointerRNA *data)
{
CollectionPointerLink *link;
uiListItem *item;
/* add to list to store in box */
item= MEM_callocN(sizeof(uiListItem), "uiListItem");
item->layout= layout;
item->data= *data;
BLI_addtail(itemlb, item);
/* add to list to return from function */
link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return");
RNA_pointer_create(NULL, &RNA_UIListItem, item, &link->ptr);
BLI_addtail(lb, link);
}
#endif
static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon)
{
ID *id= NULL;
@ -1974,60 +1955,126 @@ static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon)
return rnaicon;
}
ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *activeptr, char *activepropname, int rows, int listtype)
static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, char *activepropname)
{
Object *ob;
uiBlock *block= uiLayoutGetBlock(layout);
uiBut *but;
uiLayout *split, *overlap, *sub, *row;
char *name, *namebuf;
int icon;
overlap= uiLayoutOverlap(layout);
/* list item behind label & other buttons */
sub= uiLayoutRow(overlap, 0);
if(itemptr->type == &RNA_ShapeKey) {
ob= (Object*)activeptr->data;
if(ob->mode == OB_MODE_EDIT && !(ob->type == OB_MESH))
uiLayoutSetEnabled(sub, 0);
}
but= uiDefButR(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
sub= uiLayoutRow(overlap, 0);
/* retrieve icon and name */
icon= list_item_icon_get(C, itemptr, rnaicon);
if(!icon || icon == ICON_DOT)
icon= 0;
namebuf= RNA_struct_name_get_alloc(itemptr, NULL, 0);
name= (namebuf)? namebuf: "";
/* hardcoded types */
uiBlockSetEmboss(block, UI_EMBOSSN);
if(itemptr->type == &RNA_MeshTextureFaceLayer || itemptr->type == &RNA_MeshColorLayer) {
uiItemL(sub, name, icon);
uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
}
else if(itemptr->type == &RNA_MaterialTextureSlot) {
uiItemL(sub, name, icon);
uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
}
else if(itemptr->type == &RNA_ShapeKey) {
ob= (Object*)activeptr->data;
split= uiLayoutSplit(sub, 0.75f);
uiItemL(split, name, icon);
row= uiLayoutRow(split, 1);
if(i == 0) uiItemL(row, "", 0);
else uiItemR(row, "", 0, itemptr, "value", 0);
if(ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH))
uiLayoutSetActive(row, 0);
//uiItemR(row, "", ICON_MUTE_IPO_OFF, itemptr, "mute", 0);
}
else
uiItemL(sub, name, icon);
uiBlockSetEmboss(block, UI_EMBOSS);
/* free name */
if(namebuf)
MEM_freeN(namebuf);
}
void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *activeptr, char *activepropname, int rows, int listtype)
{
//Scene *scene= CTX_data_scene(C);
PropertyRNA *prop= NULL, *activeprop;
PropertyType type, activetype;
StructRNA *ptype;
uiLayout *box, *row, *col, *subrow;
uiLayout *box, *row, *col;
uiBlock *block;
uiBut *but;
Panel *pa;
ListBase lb, *itemlb;
char *name, str[32];
int rnaicon=0, icon=0, i= 0, activei= 0, len= 0, items, found, min, max;
lb.first= lb.last= NULL;
/* validate arguments */
block= uiLayoutGetBlock(layout);
pa= block->panel;
if(!pa) {
printf("uiTemplateList: only works inside a panel.\n");
return lb;
return;
}
if(!activeptr->data)
return lb;
return;
if(ptr->data) {
prop= RNA_struct_find_property(ptr, propname);
if(!prop) {
printf("uiTemplateList: property not found: %s\n", propname);
return lb;
return;
}
}
activeprop= RNA_struct_find_property(activeptr, activepropname);
if(!activeprop) {
printf("uiTemplateList: property not found: %s\n", activepropname);
return lb;
return;
}
if(prop) {
type= RNA_property_type(prop);
if(type != PROP_COLLECTION) {
printf("uiTemplateList: expected collection property.\n");
return lb;
return;
}
}
activetype= RNA_property_type(activeprop);
if(activetype != PROP_INT) {
printf("uiTemplateList: expected integer property.\n");
return lb;
return;
}
/* get icon */
@ -2040,12 +2087,10 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr
activei= RNA_property_int_get(activeptr, activeprop);
if(listtype == 'i') {
box= uiLayoutListBox(layout);
box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
col= uiLayoutColumn(box, 1);
row= uiLayoutRow(col, 0);
itemlb= uiLayoutBoxGetList(box);
if(ptr->data && prop) {
/* create list items */
RNA_PROP_BEGIN(ptr, itemptr, prop) {
@ -2054,9 +2099,8 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr
row= uiLayoutRow(col, 0);
icon= list_item_icon_get(C, &itemptr, rnaicon);
uiDefIconButR(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
//list_item_add(&lb, itemlb, uiLayoutRow(row, 1), &itemptr);
but= uiDefIconButR(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
i++;
}
@ -2082,9 +2126,6 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr
if(name)
MEM_freeN(name);
/* add to list to return */
//list_item_add(&lb, itemlb, uiLayoutRow(row, 1), &itemptr);
}
i++;
@ -2106,9 +2147,11 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr
/* default rows */
if(rows == 0)
rows= 5;
if(pa->list_grip_size != 0)
rows= pa->list_grip_size;
/* layout */
box= uiLayoutListBox(layout);
box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
row= uiLayoutRow(box, 0);
col = uiLayoutColumn(row, 1);
@ -2117,47 +2160,23 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr
if(prop)
len= RNA_property_collection_length(ptr, prop);
items= CLAMPIS(len, rows, 5);
items= CLAMPIS(len, rows, MAX2(rows, 5));
/* if list length changes and active is out of view, scroll to it */
if(pa->list_last_len != len)
if((activei < pa->list_scroll || activei >= pa->list_scroll+items))
pa->list_scroll= activei;
pa->list_scroll= MIN2(pa->list_scroll, len-items);
pa->list_scroll= MAX2(pa->list_scroll, 0);
itemlb= uiLayoutBoxGetList(box);
pa->list_size= items;
pa->list_last_len= len;
if(ptr->data && prop) {
/* create list items */
RNA_PROP_BEGIN(ptr, itemptr, prop) {
if(i >= pa->list_scroll && i<pa->list_scroll+items) {
name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
subrow= uiLayoutRow(col, 0);
icon= list_item_icon_get(C, &itemptr, rnaicon);
/* create button */
if(!icon || icon == ICON_DOT)
but= uiDefButR(block, LISTROW, 0, (name)? name: "", 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
else
but= uiDefIconTextButR(block, LISTROW, 0, icon, (name)? name: "", 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
uiButSetFlag(but, UI_ICON_LEFT|UI_TEXT_LEFT);
/* XXX hardcoded */
if(itemptr.type == &RNA_MeshTextureFaceLayer || itemptr.type == &RNA_MeshColorLayer) {
uiBlockSetEmboss(block, UI_EMBOSSN);
uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, &itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
uiBlockSetEmboss(block, UI_EMBOSS);
}
else if (itemptr.type == &RNA_MaterialTextureSlot) {
uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
}
/* XXX - end hardcoded cruft */
if(name)
MEM_freeN(name);
/* add to list to return */
//list_item_add(&lb, itemlb, subrow, &itemptr);
}
if(i >= pa->list_scroll && i<pa->list_scroll+items)
list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activepropname);
i++;
}
@ -2177,9 +2196,6 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr
uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
}
}
/* return items in list */
return lb;
}
/************************* Operator Search Template **************************/

View File

@ -255,12 +255,14 @@ void EDBM_MakeEditBMesh(ToolSettings *ts, Scene *scene, Object *ob)
BMesh *bm;
if (!me->mpoly && me->totface) {
printf("yeek!! bmesh conversion issue! may lose shapekeys!\n");
em = make_editMesh(scene, ob);
bm = editmesh_to_bmesh(em);
free_editMesh(em);
} else {
bm = BKE_mesh_to_bmesh(me);
bm = BKE_mesh_to_bmesh(me, ob);
}
me->edit_btmesh = BMEdit_Create(bm);

View File

@ -60,6 +60,7 @@
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_customdata.h"
#include "BKE_context.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@ -72,6 +73,7 @@
#endif
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_object.h"
#include "ED_view3d.h"
@ -82,9 +84,6 @@
#include "mesh_intern.h"
/* ***************** XXX **************** */
static int sample_backbuf_rect() {return 0;}
static int sample_backbuf() {return 0;}
static void error() {}
static int pupmenu() {return 0;}
/* ***************** XXX **************** */
@ -118,25 +117,30 @@ void object_facesel_flush_dm(Object *ob)
}
/* returns 0 if not found, otherwise 1 */
int facesel_face_pick(View3D *v3d, Mesh *me, short *mval, unsigned int *index, short rect)
int facesel_face_pick(struct bContext *C, Mesh *me, short *mval, unsigned int *index, short rect)
{
ViewContext vc;
view3d_set_viewcontext(C, &vc);
if (!me || me->totface==0)
return 0;
if (v3d->flag & V3D_NEEDBACKBUFDRAW) {
// XXX if (v3d->flag & V3D_NEEDBACKBUFDRAW) {
// XXX drawview.c! check_backbuf();
// XXX persp(PERSP_VIEW);
}
// XXX }
if (rect) {
/* sample rect to increase changes of selecting, so that when clicking
on an edge in the backbuf, we can still select a face */
int dist;
*index = sample_backbuf_rect(mval, 3, 1, me->totface+1, &dist,0,NULL);
*index = view3d_sample_backbuf_rect(&vc, mval, 3, 1, me->totface+1, &dist,0,NULL, NULL);
}
else
else {
/* sample only on the exact position */
*index = sample_backbuf(mval[0], mval[1]);
*index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
}
if ((*index)<=0 || (*index)>(unsigned int)me->totface)
return 0;
@ -231,35 +235,156 @@ void hide_tface(Scene *scene)
// XXX notifier! object_tface_flags_changed(OBACT, 0);
}
void select_linked_tfaces(Scene *scene, View3D *v3d, int mode)
/* Set tface seams based on edge data, uses hash table to find seam edges. */
static void hash_add_face(EdgeHash *ehash, MFace *mf)
{
BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL);
BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL);
if(mf->v4) {
BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL);
BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL);
}
else
BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL);
}
void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
{
MFace *mf;
int a, doit=1, mark=0;
char *linkflag;
EdgeHash *ehash, *seamhash;
MEdge *med;
ehash= BLI_edgehash_new();
seamhash = BLI_edgehash_new();
linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
for(med=me->medge, a=0; a < me->totedge; a++, med++)
if(med->flag & ME_SEAM)
BLI_edgehash_insert(seamhash, med->v1, med->v2, NULL);
if (mode==0 || mode==1) {
/* only put face under cursor in array */
mf= ((MFace*)me->mface) + index;
hash_add_face(ehash, mf);
linkflag[index]= 1;
}
else {
/* fill array by selection */
mf= me->mface;
for(a=0; a<me->totface; a++, mf++) {
if(mf->flag & ME_HIDE);
else if(mf->flag & ME_FACE_SEL) {
hash_add_face(ehash, mf);
linkflag[a]= 1;
}
}
}
while(doit) {
doit= 0;
/* expand selection */
mf= me->mface;
for(a=0; a<me->totface; a++, mf++) {
if(mf->flag & ME_HIDE)
continue;
if(!linkflag[a]) {
mark= 0;
if(!BLI_edgehash_haskey(seamhash, mf->v1, mf->v2))
if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2))
mark= 1;
if(!BLI_edgehash_haskey(seamhash, mf->v2, mf->v3))
if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3))
mark= 1;
if(mf->v4) {
if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v4))
if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4))
mark= 1;
if(!BLI_edgehash_haskey(seamhash, mf->v4, mf->v1))
if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1))
mark= 1;
}
else if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v1))
if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1))
mark = 1;
if(mark) {
linkflag[a]= 1;
hash_add_face(ehash, mf);
doit= 1;
}
}
}
}
BLI_edgehash_free(ehash, NULL);
BLI_edgehash_free(seamhash, NULL);
if(mode==0 || mode==2) {
for(a=0, mf=me->mface; a<me->totface; a++, mf++)
if(linkflag[a])
mf->flag |= ME_FACE_SEL;
else
mf->flag &= ~ME_FACE_SEL;
}
else if(mode==1) {
for(a=0, mf=me->mface; a<me->totface; a++, mf++)
if(linkflag[a] && (mf->flag & ME_FACE_SEL))
break;
if (a<me->totface) {
for(a=0, mf=me->mface; a<me->totface; a++, mf++)
if(linkflag[a])
mf->flag &= ~ME_FACE_SEL;
}
else {
for(a=0, mf=me->mface; a<me->totface; a++, mf++)
if(linkflag[a])
mf->flag |= ME_FACE_SEL;
}
}
MEM_freeN(linkflag);
// BIF_undo_push("Select linked UV face");
// object_tface_flags_changed(OBACT, 0);
}
void select_linked_tfaces(bContext *C, Object *ob, short mval[2], int mode)
{
Object *ob;
Mesh *me;
short mval[2];
unsigned int index=0;
ob = OBACT;
me = get_mesh(ob);
if(me==0 || me->totface==0) return;
if (mode==0 || mode==1) {
if (!(ob->lay & v3d->lay))
error("The active object is not in this layer");
// XXX getmouseco_areawin(mval);
if (!facesel_face_pick(v3d, me, mval, &index, 1)) return;
// XXX - Causes glitches, not sure why
/*
if (!facesel_face_pick(C, me, mval, &index, 1))
return;
*/
}
// XXX unwrapper.c select_linked_tfaces_with_seams(mode, me, index);
select_linked_tfaces_with_seams(mode, me, index);
object_facesel_flush_dm(ob);
}
void deselectall_tface(Scene *scene)
void deselectall_tface(Object *ob)
{
Mesh *me;
MFace *mface;
int a, sel;
me= get_mesh(OBACT);
me= get_mesh(ob);
if(me==0) return;
mface= me->mface;
@ -285,7 +410,7 @@ void deselectall_tface(Scene *scene)
mface++;
}
object_facesel_flush_dm(OBACT);
object_facesel_flush_dm(ob);
// XXX notifier! object_tface_flags_changed(OBACT, 0);
}
@ -646,32 +771,25 @@ void seam_mark_clear_tface(Scene *scene, short mode)
// XXX notifier! object_tface_flags_changed(OBACT, 1);
}
void face_select(Scene *scene, View3D *v3d)
int face_select(struct bContext *C, Object *ob, short mval[2], int extend)
{
Object *ob;
Mesh *me;
MFace *mface, *msel;
short mval[2];
unsigned int a, index;
int shift= 0; // XXX
/* Get the face under the cursor */
ob = OBACT;
if (!(ob->lay & v3d->lay)) {
error("The active object is not in this layer");
}
me = get_mesh(ob);
// XXX getmouseco_areawin(mval);
if (!facesel_face_pick(v3d, me, mval, &index, 1)) return;
if (!facesel_face_pick(C, me, mval, &index, 1))
return 0;
msel= (((MFace*)me->mface)+index);
if (msel->flag & ME_HIDE) return;
if (msel->flag & ME_HIDE) return 0;
/* clear flags */
mface = me->mface;
a = me->totface;
if ((shift)==0) {
if (!extend) {
while (a--) {
mface->flag &= ~ME_FACE_SEL;
mface++;
@ -680,7 +798,7 @@ void face_select(Scene *scene, View3D *v3d)
me->act_face = (int)index;
if (shift) {
if (extend) {
if (msel->flag & ME_FACE_SEL)
msel->flag &= ~ME_FACE_SEL;
else
@ -690,77 +808,70 @@ void face_select(Scene *scene, View3D *v3d)
/* image window redraw */
object_facesel_flush_dm(OBACT);
object_facesel_flush_dm(ob);
// XXX notifier! object_tface_flags_changed(OBACT, 1);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
return 1;
}
void face_borderselect(Scene *scene, ScrArea *sa, ARegion *ar)
void face_borderselect(struct bContext *C, Object *ob, rcti *rect, int select)
{
Mesh *me;
MFace *mface;
rcti rect;
struct ImBuf *ibuf;
unsigned int *rt;
int a, sx, sy, index, val= 0;
int a, sx, sy, index;
char *selar;
me= get_mesh(OBACT);
ViewContext vc;
view3d_set_viewcontext(C, &vc);
me= get_mesh(ob);
if(me==0) return;
if(me->totface==0) return;
// XXX val= get_border(&rect, 3);
if(val) {
/* without this border select often fails */
#if 0 /* XXX untested in 2.5 */
if (v3d->flag & V3D_NEEDBACKBUFDRAW) {
check_backbuf();
persp(PERSP_VIEW);
}
#endif
selar= MEM_callocN(me->totface+1, "selar");
sx= (rect.xmax-rect.xmin+1);
sy= (rect.ymax-rect.ymin+1);
if(sx*sy<=0) return;
ibuf = IMB_allocImBuf(sx,sy,32,IB_rect,0);
rt = ibuf->rect;
glReadPixels(rect.xmin+ar->winrct.xmin, rect.ymin+ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
selar= MEM_callocN(me->totface+1, "selar");
a= sx*sy;
while(a--) {
if(*rt) {
index= WM_framebuffer_to_index(*rt);
if(index<=me->totface) selar[index]= 1;
}
rt++;
sx= (rect->xmax-rect->xmin+1);
sy= (rect->ymax-rect->ymin+1);
if(sx*sy<=0) return;
view3d_validate_backbuf(&vc);
ibuf = IMB_allocImBuf(sx,sy,32,IB_rect,0);
rt = ibuf->rect;
glReadPixels(rect->xmin+vc.ar->winrct.xmin, rect->ymin+vc.ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
a= sx*sy;
while(a--) {
if(*rt) {
index= WM_framebuffer_to_index(*rt);
if(index<=me->totface) selar[index]= 1;
}
mface= me->mface;
for(a=1; a<=me->totface; a++, mface++) {
if(selar[a]) {
if(mface->flag & ME_HIDE);
else {
if(val==LEFTMOUSE) mface->flag |= ME_FACE_SEL;
else mface->flag &= ~ME_FACE_SEL;
}
rt++;
}
mface= me->mface;
for(a=1; a<=me->totface; a++, mface++) {
if(selar[a]) {
if(mface->flag & ME_HIDE);
else {
if(select) mface->flag |= ME_FACE_SEL;
else mface->flag &= ~ME_FACE_SEL;
}
}
IMB_freeImBuf(ibuf);
MEM_freeN(selar);
}
IMB_freeImBuf(ibuf);
MEM_freeN(selar);
// XXX notifier! object_tface_flags_changed(OBACT, 0);
}
#ifdef __APPLE__
glReadBuffer(GL_BACK);
#endif
object_facesel_flush_dm(OBACT);
object_facesel_flush_dm(ob);
}

View File

@ -719,7 +719,7 @@ EditMesh *make_editMesh(Scene *scene, Object *ob)
EditFace *efa;
EditEdge *eed;
EditSelection *ese;
float *co;
float *co, (*keyco)[3]= NULL;
int tot, a, eekadoodle= 0;
em= MEM_callocN(sizeof(EditMesh), "editmesh");
@ -732,7 +732,8 @@ EditMesh *make_editMesh(Scene *scene, Object *ob)
actkey = ob_get_keyblock(ob);
if(actkey) {
tot= actkey->totelem;
keyco= actkey->data;
em->shapenr= ob->shapenr;
}
/* make editverts */
@ -745,8 +746,8 @@ EditMesh *make_editMesh(Scene *scene, Object *ob)
co= mvert->co;
/* edit the shape key coordinate if available */
if(actkey && a < actkey->totelem)
co= (float*)actkey->data + 3*a;
if(keyco && a < actkey->totelem)
co= keyco[a];
eve= addvertlist(em, co, NULL);
evlist[a]= eve;
@ -1129,7 +1130,8 @@ void load_editMesh(Scene *scene, Object *ob, EditMesh *em)
/* are there keys? */
if(me->key) {
KeyBlock *currkey, *actkey = ob_get_keyblock(ob);
KeyBlock *currkey;
KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1);
/* Lets reorder the key data so that things line up roughly
* with the way things were before editmode */
@ -1146,7 +1148,7 @@ void load_editMesh(Scene *scene, Object *ob, EditMesh *em)
while(eve) {
if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex
if(currkey == actkey) {
if (actkey == me->key->refkey) {
if(actkey == me->key->refkey) {
VECCOPY(fp, mvert->co);
}
else {

View File

@ -1208,7 +1208,7 @@ static void make_prim_ext(bContext *C, int type, int tot, int seg,
int subdiv, float dia, float depth, int ext, int fill)
{
Object *obedit= CTX_data_edit_object(C);
int newob;
int newob = 0;
float mat[4][4];
if(obedit==NULL || obedit->type!=OB_MESH) {
@ -1308,49 +1308,21 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "fill", 0, "Fill", "");
}
static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
{
make_prim_ext(C, PRIM_CYLINDER, RNA_int_get(op->ptr, "vertices"), 0, 0,
RNA_float_get(op->ptr,"radius"),
RNA_float_get(op->ptr, "depth"), 1, 1);
return OPERATOR_FINISHED;
}
void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Add Cylinder";
ot->description= "Construct a cylindrical mesh (ends filled).";
ot->idname= "MESH_OT_primitive_cylinder_add";
/* api callbacks */
ot->exec= add_primitive_cylinder_exec;
ot->poll= ED_operator_scene_editable;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* props */
RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
RNA_def_float(ot->srna, "depth", 1.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
}
static int add_primitive_tube_exec(bContext *C, wmOperator *op)
{
make_prim_ext(C, PRIM_CYLINDER, RNA_int_get(op->ptr, "vertices"), 0, 0,
RNA_float_get(op->ptr,"radius"),
RNA_float_get(op->ptr, "depth"), 1, 0);
RNA_float_get(op->ptr, "depth"), 1,
RNA_boolean_get(op->ptr, "cap_ends"));
return OPERATOR_FINISHED;
return OPERATOR_FINISHED;
}
void MESH_OT_primitive_tube_add(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Add Tube";
ot->description= "Construct a cylindrical mesh (ends not filled).";
ot->description= "Construct a tube mesh.";
ot->idname= "MESH_OT_primitive_tube_add";
/* api callbacks */
@ -1364,6 +1336,7 @@ void MESH_OT_primitive_tube_add(wmOperatorType *ot)
RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500);
RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00);
RNA_def_float(ot->srna, "depth", 1.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00);
RNA_def_boolean(ot->srna, "cap_ends", 1, "Cap Ends", "");
}
static int add_primitive_cone_exec(bContext *C, wmOperator *op)

View File

@ -210,7 +210,7 @@ void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts)
EditEdge *nearest=NULL, *eed;
float fac;
int keys = 0, holdnum=0, selectmode, dist;
short mvalo[2] = {0,0}, mval[2];
short mvalo[2] = {0, 0}, mval[2] = {0, 0};
short event=0, val, choosing=1, cancel=0, cuthalf = 0, smooth=0;
short hasHidden = 0;
char msg[128];
@ -254,7 +254,7 @@ void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts)
// }
#endif
}
else PIL_sleep_ms(10); // idle
else PIL_sleep_ms(10); // idle
while(qtest())

View File

@ -99,41 +99,43 @@ static int pupmenu() {return 0;}
/* ****************************** MIRROR **************** */
void EM_select_mirrored(Object *obedit, EditMesh *em)
void EM_cache_x_mirror_vert(struct Object *ob, struct EditMesh *em)
{
#if 0
if(em->selectmode & SCE_SELECT_VERTEX) {
EditVert *eve, *v1;
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->f & SELECT) {
v1= editmesh_get_x_mirror_vert(obedit, em, eve->co);
if(v1) {
eve->f &= ~SELECT;
v1->f |= SELECT;
}
EditVert *eve, *eve_mirror;
for(eve= em->verts.first; eve; eve= eve->next) {
eve->tmp.v= NULL;
}
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->tmp.v==NULL) {
eve_mirror = editmesh_get_x_mirror_vert(ob, em, eve->co);
if(eve_mirror) {
eve->tmp.v= eve_mirror;
eve_mirror->tmp.v = eve;
}
}
}
#endif
}
void EM_automerge(int update)
void EM_select_mirrored(Object *obedit, EditMesh *em, int extend)
{
// XXX int len;
// if ((scene->automerge) &&
// (obedit && obedit->type==OB_MESH) &&
// (((Mesh*)obedit->data)->mr==NULL)
// ) {
// len = removedoublesflag(1, 1, scene->toolsettings->doublimit);
// if (len) {
// em->totvert -= len; /* saves doing a countall */
// if (update) {
// DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
// }
// }
// }
EditVert *eve;
EM_cache_x_mirror_vert(obedit, em);
for(eve= em->verts.first; eve; eve= eve->next) {
if(eve->f & SELECT && eve->tmp.v) {
eve->tmp.v->f |= SELECT;
if(extend==FALSE)
eve->f &= ~SELECT;
/* remove the interference */
eve->tmp.v->tmp.v= eve->tmp.v= NULL;
}
}
}
/* ****************************** SELECTION ROUTINES **************** */
@ -1247,6 +1249,39 @@ void MESH_OT_select_by_number_vertices(wmOperatorType *ot)
RNA_def_enum(ot->srna, "type", type_items, 3, "Type", "Type of elements to select.");
}
int select_mirror_exec(bContext *C, wmOperator *op)
{
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
int extend= RNA_boolean_get(op->ptr, "extend");
EM_select_mirrored(obedit, em, extend);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
void MESH_OT_select_mirror(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Select Mirror";
ot->description= "Select mesh items at mirrored locations.";
ot->idname= "MESH_OT_select_mirror";
/* api callbacks */
ot->exec= select_mirror_exec;
ot->poll= ED_operator_editmesh;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* props */
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection");
}
static int select_sharp_edges_exec(bContext *C, wmOperator *op)
{
/* Find edges that have exactly two neighboring faces,
@ -2295,99 +2330,6 @@ void vertexnoise(Object *obedit, EditMesh *em)
}
static void vertices_to_sphere(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, float perc)
{
EditVert *eve;
float *curs, len, vec[3], cent[3], fac, facm, imat[3][3], bmat[3][3];
int tot;
// XXX if(button(&perc, 1, 100, "Percentage:")==0) return;
fac= perc/100.0f;
facm= 1.0f-fac;
Mat3CpyMat4(bmat, obedit->obmat);
Mat3Inv(imat, bmat);
/* center */
curs= give_cursor(scene, v3d);
cent[0]= curs[0]-obedit->obmat[3][0];
cent[1]= curs[1]-obedit->obmat[3][1];
cent[2]= curs[2]-obedit->obmat[3][2];
Mat3MulVecfl(imat, cent);
len= 0.0;
tot= 0;
eve= em->verts.first;
while(eve) {
if(eve->f & SELECT) {
tot++;
len+= VecLenf(cent, eve->co);
}
eve= eve->next;
}
len/=tot;
if(len==0.0) len= 10.0;
eve= em->verts.first;
while(eve) {
if(eve->f & SELECT) {
vec[0]= eve->co[0]-cent[0];
vec[1]= eve->co[1]-cent[1];
vec[2]= eve->co[2]-cent[2];
Normalize(vec);
eve->co[0]= fac*(cent[0]+vec[0]*len) + facm*eve->co[0];
eve->co[1]= fac*(cent[1]+vec[1]*len) + facm*eve->co[1];
eve->co[2]= fac*(cent[2]+vec[2]*len) + facm*eve->co[2];
}
eve= eve->next;
}
recalc_editnormals(em);
// DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
}
static int vertices_to_sphere_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
View3D *v3d = CTX_wm_view3d(C);
EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
vertices_to_sphere(scene, v3d, obedit, em, RNA_float_get(op->ptr,"percent"));
BKE_mesh_end_editmesh(obedit->data, em);
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
return OPERATOR_FINISHED;
}
void MESH_OT_vertices_transform_to_sphere(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Vertices to Sphere";
//added "around cursor" to differentiate between "TFM_OT_tosphere()"
ot->description= "Move selected vertices outward in a spherical shape around cursor.";
ot->idname= "MESH_OT_vertices_transform_to_sphere";
/* api callbacks */
ot->exec= vertices_to_sphere_exec;
ot->poll= ED_operator_editmesh;
/* flags */
ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
/* props */
RNA_def_float(ot->srna, "percent", 100.0f, 0.0f, 100.0f, "Percent", "DOC_BROKEN", 0.01f, 100.0f);
}
void flipface(EditMesh *em, EditFace *efa)
{
if(efa->v4) {

View File

@ -69,6 +69,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_library.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
@ -96,10 +97,8 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
#include "bmesh.h"
/* XXX */
static int extern_qread() {return 0;}
static void waitcursor(int val) {}
static int pupmenu() {return 0;}
static int qtest() {return 0;}
#define add_numbut(a, b, c, d, e, f, g) {}
/* XXX */
@ -4245,6 +4244,7 @@ void mesh_set_face_flags(EditMesh *em, short mode)
/************************ Shape Operators *************************/
#if 0
void shape_propagate(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op)
{
EditVert *ev = NULL;
@ -4286,8 +4286,9 @@ void shape_propagate(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op)
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
return;
}
#endif
void shape_copy_from_lerp(EditMesh *em, KeyBlock* thisBlock, KeyBlock* fromBlock)
static int blend_from_shape_exec(bContext *C, wmOperator *op)
{
#if 0 //BMESH_TODO
EditVert *ev = NULL;
@ -4295,65 +4296,34 @@ void shape_copy_from_lerp(EditMesh *em, KeyBlock* thisBlock, KeyBlock* fromBlock
float perc = 0;
char str[64];
float *data, *odata;
Object *obedit= CTX_data_edit_object(C);
Mesh *me= obedit->data;
Key *key= me->key;
EditMesh *em= BKE_mesh_get_editmesh(me);
EditVert *eve;
KeyBlock *kb;
float *data, co[3];
float blend= RNA_float_get(op->ptr, "blend");
int shape= RNA_enum_get(op->ptr, "shape");
int add= RNA_int_get(op->ptr, "add");
int blended= 0;
data = fromBlock->data;
odata = thisBlock->data;
if(key && (kb= BLI_findlink(&key->block, shape))) {
data= kb->data;
// XXX getmouseco_areawin(mval);
curval[0] = mval[0] + 1; curval[1] = mval[1] + 1;
for(eve=em->verts.first; eve; eve=eve->next){
if(eve->f & SELECT) {
if(eve->keyindex >= 0 && eve->keyindex < kb->totelem) {
VECCOPY(co, data + eve->keyindex*3);
while (finished == 0)
{
// XXX getmouseco_areawin(mval);
if (mval[0] != curval[0] || mval[1] != curval[1])
{
if(add) {
VecMulf(co, blend);
VecAddf(eve->co, eve->co, co);
}
else
VecLerpf(eve->co, eve->co, co, blend);
if(mval[0] > curval[0])
perc += 0.1;
else if(mval[0] < curval[0])
perc -= 0.1;
if(perc < 0) perc = 0;
if(perc > 1) perc = 1;
curval[0] = mval[0];
curval[1] = mval[1];
if(fullcopy == 1){
perc = 1;
}
for(ev = em->verts.first; ev ; ev = ev->next){
if(ev->f & SELECT){
VecLerpf(ev->co,odata+(ev->keyindex*3),data+(ev->keyindex*3),perc);
}
}
sprintf(str,"Blending at %d%c MMB to Copy at 100%c",(int)(perc*100),'%','%');
// DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
// headerprint(str);
// force_draw(0);
if(fullcopy == 1){
break;
}
} else {
PIL_sleep_ms(10);
}
while(qtest()) {
short val=0;
event= extern_qread(&val);
if(val){
if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)){
finished = 1;
}
else if (event == MIDDLEMOUSE){
fullcopy = 1;
}
else if (ELEM3(event,ESCKEY,RIGHTMOUSE,RIGHTMOUSE)){
canceled = 1;
finished = 1;
blended= 1;
}
}
}
@ -4367,73 +4337,63 @@ void shape_copy_from_lerp(EditMesh *em, KeyBlock* thisBlock, KeyBlock* fromBlock
}
return;
#endif
return OPERATOR_CANCELLED;
}
static EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *ptr, int *free)
{
Object *obedit= CTX_data_edit_object(C);
Mesh *me= (obedit) ? obedit->data : NULL;
Key *key;
KeyBlock *kb, *actkb;
EnumPropertyItem tmp= {0, "", 0, "", ""}, *item= NULL;
int totitem= 0, a;
if(obedit && obedit->type == OB_MESH) {
key= me->key;
actkb= ob_get_keyblock(obedit);
void shape_copy_select_from(Object *obedit, EditMesh *em, wmOperator *op)
if(key && actkb) {
for(kb=key->block.first, a=0; kb; kb=kb->next, a++) {
if(kb != actkb) {
tmp.value= a;
tmp.identifier= kb->name;
tmp.name= kb->name;
RNA_enum_item_add(&item, &totitem, &tmp);
}
}
}
}
RNA_enum_item_end(&item, &totitem);
*free= 1;
return item;
}
void MESH_OT_blend_from_shape(wmOperatorType *ot)
{
Mesh* me = (Mesh*)obedit->data;
EditVert *ev = NULL;
int totverts = 0,curshape = obedit->shapenr;
PropertyRNA *prop;
static EnumPropertyItem shape_items[]= {{0, NULL, 0, NULL, NULL}};
Key* ky = NULL;
KeyBlock *kb = NULL,*thisBlock = NULL;
int maxlen=32, nr=0, a=0;
char *menu;
/* identifiers */
ot->name= "Blend From Shape";
ot->description= "Blend in shape from a shape key.";
ot->idname= "MESH_OT_blend_from_shape";
if(me->key){
ky = me->key;
} else {
BKE_report(op->reports, RPT_ERROR, "Object Has No Key");
return;
}
/* api callbacks */
ot->exec= blend_from_shape_exec;
ot->invoke= WM_operator_props_popup;
ot->poll= ED_operator_editmesh;
if(ky->block.first){
for(kb=ky->block.first;kb;kb = kb->next){
maxlen += 40; // Size of a block name
if(a == curshape-1){
thisBlock = kb;
}
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
a++;
}
a=0;
menu = MEM_callocN(maxlen, "Copy Shape Menu Text");
strcpy(menu, "Copy Vert Positions from Shape %t|");
for(kb=ky->block.first;kb;kb = kb->next){
if(a != curshape-1){
sprintf(menu,"%s %s %cx%d|",menu,kb->name,'%',a);
}
a++;
}
// XXX nr = pupmenu_col(menu, 20);
MEM_freeN(menu);
} else {
BKE_report(op->reports, RPT_ERROR, "Object Has No Blendshapes");
return;
}
a = 0;
for(kb=ky->block.first;kb;kb = kb->next){
if(a == nr){
for(ev = em->verts.first;ev;ev = ev->next){
totverts++;
}
if(me->totvert != totverts){
BKE_report(op->reports, RPT_ERROR, "Shape Has had Verts Added/Removed, please cycle editmode before copying");
return;
}
shape_copy_from_lerp(em, thisBlock,kb);
return;
}
a++;
}
return;
/* properties */
prop= RNA_def_enum(ot->srna, "shape", shape_items, 0, "Shape", "Shape key to use for blending.");
RNA_def_enum_funcs(prop, shape_itemf);
RNA_def_float(ot->srna, "blend", 1.0f, -FLT_MAX, FLT_MAX, "Blend", "Blending factor.", -2.0f, 2.0f);
RNA_def_boolean(ot->srna, "add", 1, "Add", "Add rather then blend between shapes.");
}
/************************ Merge Operator *************************/

View File

@ -301,7 +301,7 @@ static int ringsel_init (bContext *C, wmOperator *op, int do_cut)
/* assign the drawing handle for drawing preview line... */
lcd->ar= CTX_wm_region(C);
lcd->draw_handle= ED_region_draw_cb_activate(lcd->ar->type, ringsel_draw, lcd, REGION_DRAW_POST);
lcd->draw_handle= ED_region_draw_cb_activate(lcd->ar->type, ringsel_draw, lcd, REGION_DRAW_POST_VIEW);
lcd->ob = CTX_data_edit_object(C);
lcd->em= ((Mesh *)lcd->ob->data)->edit_btmesh;
lcd->extend = do_cut ? 0 : RNA_boolean_get(op->ptr, "extend");
@ -480,5 +480,5 @@ void MESH_OT_loopcut (wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
/* properties */
RNA_def_int(ot->srna, "number_cuts", 1, 1, 10, "Number of Cuts", "", 1, INT_MAX);
RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10);
}

View File

@ -118,7 +118,6 @@ void MESH_OT_separate(struct wmOperatorType *ot);
void MESH_OT_primitive_plane_add(struct wmOperatorType *ot);
void MESH_OT_primitive_cube_add(struct wmOperatorType *ot);
void MESH_OT_primitive_circle_add(struct wmOperatorType *ot);
void MESH_OT_primitive_cylinder_add(struct wmOperatorType *ot);
void MESH_OT_primitive_tube_add(struct wmOperatorType *ot);
void MESH_OT_primitive_cone_add(struct wmOperatorType *ot);
void MESH_OT_primitive_grid_add(struct wmOperatorType *ot);
@ -204,13 +203,13 @@ void MESH_OT_unpin(struct wmOperatorType *ot);
void MESH_OT_hide(struct wmOperatorType *ot);
void MESH_OT_reveal(struct wmOperatorType *ot);
void MESH_OT_select_by_number_vertices(struct wmOperatorType *ot);
void MESH_OT_select_mirror(struct wmOperatorType *ot);
void MESH_OT_normals_make_consistent(struct wmOperatorType *ot);
void MESH_OT_faces_select_linked_flat(struct wmOperatorType *ot);
void MESH_OT_edges_select_sharp(struct wmOperatorType *ot);
void MESH_OT_select_shortest_path(struct wmOperatorType *ot);
void MESH_OT_select_similar(struct wmOperatorType *ot);
void MESH_OT_select_random(struct wmOperatorType *ot);
void MESH_OT_vertices_transform_to_sphere(struct wmOperatorType *ot);
void MESH_OT_selection_type(struct wmOperatorType *ot);
void MESH_OT_loop_multi_select(struct wmOperatorType *ot);
void MESH_OT_mark_seam(struct wmOperatorType *ot);
@ -282,6 +281,8 @@ void MESH_OT_colors_reverse(struct wmOperatorType *ot);
void MESH_OT_delete(struct wmOperatorType *ot);
void MESH_OT_rip(struct wmOperatorType *ot);
void MESH_OT_blend_from_shape(struct wmOperatorType *ot);
/* ******************* mesh_layers.c */
void MESH_OT_uv_texture_add(struct wmOperatorType *ot);

View File

@ -82,6 +82,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_hide);
WM_operatortype_append(MESH_OT_reveal);
WM_operatortype_append(MESH_OT_select_by_number_vertices);
WM_operatortype_append(MESH_OT_select_mirror);
WM_operatortype_append(MESH_OT_normals_make_consistent);
WM_operatortype_append(MESH_OT_merge);
WM_operatortype_append(MESH_OT_subdivide);
@ -90,7 +91,6 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_primitive_plane_add);
WM_operatortype_append(MESH_OT_primitive_cube_add);
WM_operatortype_append(MESH_OT_primitive_circle_add);
WM_operatortype_append(MESH_OT_primitive_cylinder_add);
WM_operatortype_append(MESH_OT_primitive_tube_add);
WM_operatortype_append(MESH_OT_primitive_cone_add);
WM_operatortype_append(MESH_OT_primitive_grid_add);
@ -105,7 +105,6 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_spin);
WM_operatortype_append(MESH_OT_screw);
WM_operatortype_append(MESH_OT_vertices_transform_to_sphere);
WM_operatortype_append(MESH_OT_split);
WM_operatortype_append(MESH_OT_extrude_repeat);
WM_operatortype_append(MESH_OT_edge_rotate);
@ -143,6 +142,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_flip_normals);
WM_operatortype_append(MESH_OT_knife_cut);
WM_operatortype_append(MESH_OT_rip);
WM_operatortype_append(MESH_OT_blend_from_shape);
WM_operatortype_append(MESH_OT_uv_texture_add);
WM_operatortype_append(MESH_OT_uv_texture_remove);
@ -236,8 +236,6 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
RNA_float_set(WM_keymap_add_item(keymap, "MESH_OT_faces_select_linked_flat", FKEY, KM_PRESS, (KM_CTRL|KM_SHIFT|KM_ALT), 0)->ptr,"sharpness",135.0);
RNA_float_set(WM_keymap_add_item(keymap, "MESH_OT_edges_select_sharp", SKEY, KM_PRESS, (KM_CTRL|KM_SHIFT|KM_ALT), 0)->ptr,"sharpness",135.0);
WM_keymap_add_item(keymap, "MESH_OT_vertices_transform_to_sphere", SKEY, KM_PRESS, KM_CTRL|KM_SHIFT , 0);
WM_keymap_add_item(keymap, "MESH_OT_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "MESH_OT_edge_split", MKEY, KM_PRESS, 0, 0);
@ -299,8 +297,10 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
RNA_string_set(kmi->ptr, "name", "INFO_MT_mesh_add");
WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, 0, 0);
/* use KM_RELEASE because same key is used for tweaks */
WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", LEFTMOUSE, KM_RELEASE, KM_CTRL, 0);
/* use KM_RELEASE because same key is used for tweaks
* TEMPORARY REMAP TO ALT+CTRL TO AVOID CONFLICT
* */
WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", LEFTMOUSE, KM_RELEASE, KM_CTRL|KM_ALT, 0);
WM_keymap_add_item(keymap, "MESH_OT_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "MESH_OT_delete", DELKEY, KM_PRESS, 0, 0);

View File

@ -850,7 +850,7 @@ static void mesh_octree_add_nodes(MocNode **basetable, float *co, float *offs, f
}
static intptr_t mesh_octree_find_index(MocNode **bt, float (*orco)[3], MVert *mvert, float *co)
static intptr_t mesh_octree_find_index(MocNode **bt, MVert *mvert, float *co)
{
float *vec;
int a;
@ -861,12 +861,7 @@ static intptr_t mesh_octree_find_index(MocNode **bt, float (*orco)[3], MVert *mv
for(a=0; a<MOC_NODE_RES; a++) {
if((*bt)->index[a]) {
/* does mesh verts and editmode, code looks potential dangerous, octree should really be filled OK! */
if(orco) {
vec= orco[(*bt)->index[a]-1];
if(FloatCompare(vec, co, MOC_THRESH))
return (*bt)->index[a]-1;
}
else if(mvert) {
if(mvert) {
vec= (mvert+(*bt)->index[a]-1)->co;
if(FloatCompare(vec, co, MOC_THRESH))
return (*bt)->index[a]-1;
@ -880,7 +875,7 @@ static intptr_t mesh_octree_find_index(MocNode **bt, float (*orco)[3], MVert *mv
else return -1;
}
if( (*bt)->next)
return mesh_octree_find_index(&(*bt)->next, orco, mvert, co);
return mesh_octree_find_index(&(*bt)->next, mvert, co);
return -1;
}
@ -888,9 +883,7 @@ static intptr_t mesh_octree_find_index(MocNode **bt, float (*orco)[3], MVert *mv
static struct {
MocNode **table;
float offs[3], div[3];
float (*orco)[3];
float orcoloc[3];
} MeshOctree = {NULL, {0, 0, 0}, {0, 0, 0}, NULL};
} MeshOctree = {NULL, {0, 0, 0}, {0, 0, 0}};
/* mode is 's' start, or 'e' end, or 'u' use */
/* if end, ob can be NULL */
@ -906,9 +899,9 @@ intptr_t mesh_octree_table(Object *ob, BMEditMesh *em, float *co, char mode)
Mesh *me= ob->data;
bt= MeshOctree.table + mesh_octree_get_base_offs(co, MeshOctree.offs, MeshOctree.div);
if(em)
return mesh_octree_find_index(bt, NULL, NULL, co);
return mesh_octree_find_index(bt, NULL, co);
else
return mesh_octree_find_index(bt, MeshOctree.orco, me->mvert, co);
return mesh_octree_find_index(bt, me->mvert, co);
}
return -1;
}
@ -930,16 +923,10 @@ intptr_t mesh_octree_table(Object *ob, BMEditMesh *em, float *co, char mode)
}
else {
MVert *mvert;
float *vco;
int a, totvert;
int a;
MeshOctree.orco= mesh_getRefKeyCos(me, &totvert);
mesh_get_texspace(me, MeshOctree.orcoloc, NULL, NULL);
for(a=0, mvert= me->mvert; a<me->totvert; a++, mvert++) {
vco= (MeshOctree.orco)? MeshOctree.orco[a]: mvert->co;
DO_MINMAX(vco, min, max);
}
for(a=0, mvert= me->mvert; a<me->totvert; a++, mvert++)
DO_MINMAX(mvert->co, min, max);
}
/* for quick unit coordinate calculus */
@ -974,13 +961,10 @@ intptr_t mesh_octree_table(Object *ob, BMEditMesh *em, float *co, char mode)
}
else {
MVert *mvert;
float *vco;
int a;
for(a=0, mvert= me->mvert; a<me->totvert; a++, mvert++) {
vco= (MeshOctree.orco)? MeshOctree.orco[a]: mvert->co;
mesh_octree_add_nodes(MeshOctree.table, vco, MeshOctree.offs, MeshOctree.div, a+1);
}
for(a=0, mvert= me->mvert; a<me->totvert; a++, mvert++)
mesh_octree_add_nodes(MeshOctree.table, mvert->co, MeshOctree.offs, MeshOctree.div, a+1);
}
}
else if(mode=='e') { /* end table */
@ -993,10 +977,6 @@ intptr_t mesh_octree_table(Object *ob, BMEditMesh *em, float *co, char mode)
MEM_freeN(MeshOctree.table);
MeshOctree.table= NULL;
}
if(MeshOctree.orco) {
MEM_freeN(MeshOctree.orco);
MeshOctree.orco= NULL;
}
}
return 0;
}
@ -1007,19 +987,10 @@ int mesh_get_x_mirror_vert(Object *ob, int index)
MVert *mvert;
float vec[3];
if(MeshOctree.orco) {
float *loc= MeshOctree.orcoloc;
vec[0]= -(MeshOctree.orco[index][0] + loc[0]) - loc[0];
vec[1]= MeshOctree.orco[index][1];
vec[2]= MeshOctree.orco[index][2];
}
else {
mvert= me->mvert+index;
vec[0]= -mvert->co[0];
vec[1]= mvert->co[1];
vec[2]= mvert->co[2];
}
mvert= me->mvert+index;
vec[0]= -mvert->co[0];
vec[1]= mvert->co[1];
vec[2]= mvert->co[2];
return mesh_octree_table(ob, NULL, vec, 'u');
}

View File

@ -293,17 +293,20 @@ static int object_add_curve_exec(bContext *C, wmOperator *op)
Object *obedit= CTX_data_edit_object(C);
ListBase *editnurb;
Nurb *nu;
int newob= 0;
int newob= 0, type= RNA_enum_get(op->ptr, "type");
if(obedit==NULL || obedit->type!=OB_CURVE) {
ED_object_add_type(C, OB_CURVE);
ED_object_enter_editmode(C, 0);
newob = 1;
obedit= CTX_data_edit_object(C);
if(type & CU_PRIM_PATH)
((Curve*)obedit->data)->flag |= CU_PATH|CU_3D;
}
else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
obedit= CTX_data_edit_object(C);
nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
nu= add_nurbs_primitive(C, type, newob);
editnurb= curve_get_editcurve(obedit);
BLI_addtail(editnurb, nu);

View File

@ -471,7 +471,6 @@ void ED_object_enter_editmode(bContext *C, int flag)
static int editmode_toggle_exec(bContext *C, wmOperator *op)
{
if(!CTX_data_edit_object(C))
ED_object_enter_editmode(C, EM_WAITCURSOR);
else

View File

@ -58,6 +58,7 @@ void OBJECT_OT_track_clear(struct wmOperatorType *ot);
void OBJECT_OT_slow_parent_set(struct wmOperatorType *ot);
void OBJECT_OT_slow_parent_clear(struct wmOperatorType *ot);
void OBJECT_OT_make_local(struct wmOperatorType *ot);
void OBJECT_OT_make_single_user(struct wmOperatorType *ot);
void OBJECT_OT_move_to_layer(struct wmOperatorType *ot);
/* object_edit.c */
@ -165,6 +166,11 @@ void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_normalize_all(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_invert(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_blend(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_clean(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_menu(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_set_active(struct wmOperatorType *ot);
@ -174,6 +180,9 @@ void OBJECT_OT_game_property_remove(struct wmOperatorType *ot);
/* object_shapekey.c */
void OBJECT_OT_shape_key_add(struct wmOperatorType *ot);
void OBJECT_OT_shape_key_remove(struct wmOperatorType *ot);
void OBJECT_OT_shape_key_clear(struct wmOperatorType *ot);
void OBJECT_OT_shape_key_mirror(struct wmOperatorType *ot);
void OBJECT_OT_shape_key_move(struct wmOperatorType *ot);
/* object_group.c */
void OBJECT_OT_group_add(struct wmOperatorType *ot);

View File

@ -349,10 +349,10 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi
mesh_pmv_off(ob, me);
/* Multires: ensure that recent sculpting is applied */
if(md->type == eModifierType_Multires)
multires_force_update(ob);
/* Multires: ensure that recent sculpting is applied */
if(md->type == eModifierType_Multires)
multires_force_update(ob);
dm = mesh_create_derived_for_modifier(scene, ob, md);
if (!dm) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");

View File

@ -90,6 +90,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_slow_parent_set);
WM_operatortype_append(OBJECT_OT_slow_parent_clear);
WM_operatortype_append(OBJECT_OT_make_local);
WM_operatortype_append(OBJECT_OT_make_single_user);
WM_operatortype_append(OBJECT_OT_move_to_layer);
WM_operatortype_append(OBJECT_OT_select_inverse);
@ -162,6 +163,11 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_group_deselect);
WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked);
WM_operatortype_append(OBJECT_OT_vertex_group_copy);
WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
WM_operatortype_append(OBJECT_OT_vertex_group_normalize_all);
WM_operatortype_append(OBJECT_OT_vertex_group_invert);
WM_operatortype_append(OBJECT_OT_vertex_group_blend);
WM_operatortype_append(OBJECT_OT_vertex_group_clean);
WM_operatortype_append(OBJECT_OT_vertex_group_menu);
WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
@ -170,6 +176,9 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_shape_key_add);
WM_operatortype_append(OBJECT_OT_shape_key_remove);
WM_operatortype_append(OBJECT_OT_shape_key_clear);
WM_operatortype_append(OBJECT_OT_shape_key_mirror);
WM_operatortype_append(OBJECT_OT_shape_key_move);
WM_operatortype_append(LATTICE_OT_select_all_toggle);
WM_operatortype_append(LATTICE_OT_make_regular);
@ -181,12 +190,21 @@ void ED_operatortypes_object(void)
void ED_operatormacros_object(void)
{
wmOperatorType *ot;
wmOperatorTypeMacro *otmacro;
ot= WM_operatortype_append_macro("OBJECT_OT_duplicate_move", "Duplicate", OPTYPE_UNDO|OPTYPE_REGISTER);
if(ot) {
WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
WM_operatortype_macro_define(ot, "TFM_OT_translate");
}
/* grr, should be able to pass options on... */
ot= WM_operatortype_append_macro("OBJECT_OT_duplicate_move_linked", "Duplicate", OPTYPE_UNDO|OPTYPE_REGISTER);
if(ot) {
otmacro= WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
RNA_boolean_set(otmacro->ptr, "linked", 1);
WM_operatortype_macro_define(ot, "TFM_OT_translate");
}
}
static int object_mode_poll(bContext *C)
@ -249,15 +267,22 @@ void ED_keymap_object(wmKeyConfig *keyconf)
kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", AKEY, KM_PRESS, KM_SHIFT, 0);
RNA_string_set(kmi->ptr, "name", "INFO_MT_add");
WM_keymap_add_item(keymap, "OBJECT_OT_duplicates_make_real", AKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", AKEY, KM_PRESS, KM_CTRL, 0);
RNA_string_set(kmi->ptr, "name", "VIEW3D_MT_object_apply");
kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", UKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "name", "VIEW3D_MT_make_single_user");
WM_keymap_add_item(keymap, "OBJECT_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "OBJECT_OT_duplicate", DKEY, KM_PRESS, KM_ALT, 0)->ptr, "linked", 1);
WM_keymap_add_item(keymap, "OBJECT_OT_duplicate_move_linked", DKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_join", JKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_convert", CKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_proxy_make", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_make_local", LKEY, KM_PRESS, 0, 0);
// XXX this should probably be in screen instead... here for testing purposes in the meantime... - Aligorith
WM_keymap_verify_item(keymap, "ANIM_OT_insert_keyframe_menu", IKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "ANIM_OT_delete_keyframe_v3d", IKEY, KM_PRESS, KM_ALT, 0);
@ -272,6 +297,8 @@ void ED_keymap_object(wmKeyConfig *keyconf)
keymap->poll= ED_operator_editlattice;
WM_keymap_add_item(keymap, "LATTICE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
ED_object_generic_keymap(keyconf, keymap, TRUE);
}
void ED_object_generic_keymap(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, int do_pet)

View File

@ -1456,7 +1456,7 @@ void single_ipo_users(Scene *scene, int flag)
#endif // XXX old animation system
}
void single_mat_users(Scene *scene, int flag)
static void single_mat_users(Scene *scene, int flag, int do_textures)
{
Object *ob;
Base *base;
@ -1486,17 +1486,17 @@ void single_mat_users(Scene *scene, int flag)
ipo_idnew(ma->ipo); /* drivers */
}
#endif // XXX old animation system
for(b=0; b<MAX_MTEX; b++) {
if(ma->mtex[b] && ma->mtex[b]->tex) {
tex= ma->mtex[b]->tex;
if(tex->id.us>1) {
ma->mtex[b]->tex= copy_texture(tex);
tex->id.us--;
if(do_textures) {
for(b=0; b<MAX_MTEX; b++) {
if(ma->mtex[b] && ma->mtex[b]->tex) {
tex= ma->mtex[b]->tex;
if(tex->id.us>1) {
ma->mtex[b]->tex= copy_texture(tex);
tex->id.us--;
}
}
}
}
}
}
}
@ -1599,42 +1599,6 @@ static void single_mat_users_expand(void)
ID_NEW(ma->mtex[a]->object);
}
void single_user(Scene *scene, View3D *v3d)
{
int nr;
if(scene->id.lib) return;
clear_id_newpoins();
nr= pupmenu("Make Single User%t|Object|Object & ObData|Object & ObData & Materials+Tex|Materials+Tex|Ipos");
if(nr>0) {
if(nr==1) single_object_users(scene, v3d, 1);
else if(nr==2) {
single_object_users(scene, v3d, 1);
single_obdata_users(scene, 1);
}
else if(nr==3) {
single_object_users(scene, v3d, 1);
single_obdata_users(scene, 1);
single_mat_users(scene, 1); /* also tex */
}
else if(nr==4) {
single_mat_users(scene, 1);
}
else if(nr==5) {
single_ipo_users(scene, 1);
}
clear_id_newpoins();
}
}
/* used for copying scenes */
void ED_object_single_users(Scene *scene, int full)
{
@ -1676,7 +1640,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
Material *ma, ***matarar;
Lamp *la;
ID *id;
int a, b, mode= RNA_boolean_get(op->ptr, "type");
int a, b, mode= RNA_enum_get(op->ptr, "type");;
if(mode==3) {
all_local(NULL, 0); /* NULL is all libs */
@ -1777,3 +1741,59 @@ void OBJECT_OT_make_local(wmOperatorType *ot)
RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
static int make_single_user_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
View3D *v3d= CTX_wm_view3d(C); /* ok if this is NULL */
int flag= RNA_enum_get(op->ptr, "type"); /* 0==ALL, SELECTED==selected objecs */
if(RNA_boolean_get(op->ptr, "object"))
single_object_users(scene, v3d, flag);
if(RNA_boolean_get(op->ptr, "obdata"))
single_obdata_users(scene, flag);
if(RNA_boolean_get(op->ptr, "material"))
single_mat_users(scene, flag, FALSE);
if(RNA_boolean_get(op->ptr, "texture"))
single_mat_users(scene, flag, TRUE);
if(RNA_boolean_get(op->ptr, "animation"))
single_ipo_users(scene, flag);
clear_id_newpoins();
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
}
void OBJECT_OT_make_single_user(wmOperatorType *ot)
{
static EnumPropertyItem type_items[]= {
{SELECT, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
{0, "ALL", 0, "All", ""},
{0, NULL, 0, NULL, NULL}};
/* identifiers */
ot->name= "Make Single User";
ot->description = "Make linked data local to each object.";
ot->idname= "OBJECT_OT_make_single_user";
/* api callbacks */
ot->invoke= WM_menu_invoke;
ot->exec= make_single_user_exec;
ot->poll= ED_operator_scene_editable;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects");
RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data");
RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each datablock");
RNA_def_boolean(ot->srna, "texture", 0, "Textures", "Make textures local to each material");
RNA_def_boolean(ot->srna, "animation", 0, "Animation Data", "Make animation data local to each object");
}

View File

@ -95,7 +95,6 @@ void ED_base_object_select(Base *base, short mode)
void ED_base_object_activate(bContext *C, Base *base)
{
Scene *scene= CTX_data_scene(C);
Base *tbase;
/* sets scene->basact */
BASACT= base;

View File

@ -70,49 +70,16 @@
#include "BLO_sys_types.h" // for intptr_t support
#include "ED_object.h"
#include "ED_mesh.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
#include "object_intern.h"
#if 0 // XXX old animation system
static void default_key_ipo(Scene *scene, Key *key)
{
IpoCurve *icu;
BezTriple *bezt;
key->ipo= add_ipo(scene, "KeyIpo", ID_KE);
icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
icu->blocktype= ID_KE;
icu->adrcode= KEY_SPEED;
icu->flag= IPO_VISIBLE|IPO_SELECT|IPO_AUTO_HORIZ;
set_icu_vars(icu);
BLI_addtail( &(key->ipo->curve), icu);
icu->bezt= bezt= MEM_callocN(2*sizeof(BezTriple), "defaultipo");
icu->totvert= 2;
bezt->hide= IPO_BEZ;
bezt->f1=bezt->f2= bezt->f3= SELECT;
bezt->h1= bezt->h2= HD_AUTO;
bezt++;
bezt->vec[1][0]= 100.0;
bezt->vec[1][1]= 1.0;
bezt->hide= IPO_BEZ;
bezt->f1=bezt->f2= bezt->f3= SELECT;
bezt->h1= bezt->h2= HD_AUTO;
calchandles_ipocurve(icu);
}
#endif // XXX old animation system
/************************* Mesh ************************/
void mesh_to_key(Mesh *me, KeyBlock *kb)
@ -195,24 +162,30 @@ static KeyBlock *add_keyblock(Scene *scene, Key *key)
return kb;
}
void insert_meshkey(Scene *scene, Mesh *me, short rel)
static void insert_meshkey(Scene *scene, Object *ob)
{
Key *key;
Mesh *me= ob->data;
Key *key= me->key;
KeyBlock *kb;
int newkey= 0;
if(me->key==NULL) {
me->key= add_key( (ID *)me);
if(rel)
me->key->type = KEY_RELATIVE;
// else
// default_key_ipo(scene, me->key); // XXX old animation system
if(key == NULL) {
key= me->key= add_key((ID *)me);
key->type= KEY_RELATIVE;
newkey= 1;
}
key= me->key;
kb= add_keyblock(scene, key);
mesh_to_key(me, kb);
if(newkey) {
/* create from mesh */
mesh_to_key(me, kb);
}
else {
/* copy from current values */
kb->data= do_ob_key(scene, ob);
kb->totelem= me->totvert;
}
}
/************************* Lattice ************************/
@ -253,24 +226,31 @@ void key_to_latt(KeyBlock *kb, Lattice *lt)
for(a=0; a<tot; a++, fp+=3, bp++) {
VECCOPY(bp->vec, fp);
}
}
/* exported to python... hrms, should not, use object levels! (ton) */
void insert_lattkey(Scene *scene, Lattice *lt, short rel)
static void insert_lattkey(Scene *scene, Object *ob)
{
Key *key;
Lattice *lt= ob->data;
Key *key= lt->key;
KeyBlock *kb;
int newkey= 0;
if(lt->key==NULL) {
lt->key= add_key( (ID *)lt);
// default_key_ipo(scene, lt->key); // XXX old animation system
if(key==NULL) {
key= lt->key= add_key( (ID *)lt);
key->type= KEY_RELATIVE;
}
key= lt->key;
kb= add_keyblock(scene, key);
latt_to_key(lt, kb);
if(newkey) {
/* create from lattice */
latt_to_key(lt, kb);
}
else {
/* copy from current values */
kb->totelem= lt->pntsu*lt->pntsv*lt->pntsw;
kb->data= do_ob_key(scene, ob);
}
}
/************************* Curve ************************/
@ -377,36 +357,43 @@ void key_to_curve(KeyBlock *kb, Curve *cu, ListBase *nurb)
}
void insert_curvekey(Scene *scene, Curve *cu, short rel)
static void insert_curvekey(Scene *scene, Object *ob)
{
Key *key;
Curve *cu= ob->data;
Key *key= cu->key;
KeyBlock *kb;
ListBase *lb= (cu->editnurb)? cu->editnurb: &cu->nurb;
int newkey= 0;
if(cu->key==NULL) {
cu->key= add_key( (ID *)cu);
if(rel)
cu->key->type = KEY_RELATIVE;
// else
// default_key_ipo(scene, cu->key); // XXX old animation system
if(key==NULL) {
key= cu->key= add_key( (ID *)cu);
key->type = KEY_RELATIVE;
newkey= 1;
}
key= cu->key;
kb= add_keyblock(scene, key);
if(cu->editnurb->first) curve_to_key(cu, kb, cu->editnurb);
else curve_to_key(cu, kb, &cu->nurb);
if(newkey) {
/* create from curve */
curve_to_key(cu, kb, lb);
}
else {
/* copy from current values */
kb->totelem= count_curveverts(lb);
kb->data= do_ob_key(scene, ob);
}
}
/*********************** add shape key ***********************/
void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob)
static void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob)
{
Key *key;
if(ob->type==OB_MESH) insert_meshkey(scene, ob->data, 1);
else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(scene, ob->data, 1);
else if(ob->type==OB_LATTICE) insert_lattkey(scene, ob->data, 1);
if(ob->type==OB_MESH) insert_meshkey(scene, ob);
else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(scene, ob);
else if(ob->type==OB_LATTICE) insert_lattkey(scene, ob);
key= ob_get_key(ob);
ob->shapenr= BLI_countlist(&key->block);
@ -416,7 +403,7 @@ void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob)
/*********************** remove shape key ***********************/
int ED_object_shape_key_remove(bContext *C, Scene *scene, Object *ob)
static int ED_object_shape_key_remove(bContext *C, Object *ob)
{
Main *bmain= CTX_data_main(C);
KeyBlock *kb, *rkb;
@ -479,8 +466,76 @@ int ED_object_shape_key_remove(bContext *C, Scene *scene, Object *ob)
return 1;
}
static int ED_object_shape_key_mirror(bContext *C, Scene *scene, Object *ob)
{
KeyBlock *kb;
Key *key;
key= ob_get_key(ob);
if(key==NULL)
return 0;
kb= BLI_findlink(&key->block, ob->shapenr-1);
if(kb) {
int i1, i2;
float *fp1, *fp2;
float tvec[3];
char *tag_elem= MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");
if(ob->type==OB_MESH) {
Mesh *me= ob->data;
MVert *mv;
mesh_octree_table(ob, NULL, NULL, 's');
for(i1=0, mv=me->mvert; i1<me->totvert; i1++, mv++) {
i2= mesh_get_x_mirror_vert(ob, i1);
if(i2==i1) {
fp1= ((float *)kb->data) + i1*3;
fp1[0] = -fp1[0];
tag_elem[i1]= 1;
}
else if(i2 != -1) {
if(tag_elem[i1]==0 && tag_elem[i2]==0) {
fp1= ((float *)kb->data) + i1*3;
fp2= ((float *)kb->data) + i2*3;
VECCOPY(tvec, fp1);
VECCOPY(fp1, fp2);
VECCOPY(fp2, tvec);
/* flip x axis */
fp1[0] = -fp1[0];
fp2[0] = -fp2[0];
}
tag_elem[i1]= tag_elem[i2]= 1;
}
}
mesh_octree_table(ob, NULL, NULL, 'e');
}
/* todo, other types? */
MEM_freeN(tag_elem);
}
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
return 1;
}
/********************** shape key operators *********************/
static int shape_key_mode_poll(bContext *C)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
ID *data= (ob)? ob->data: NULL;
return (ob && !ob->id.lib && data && !data->lib && ob->mode != OB_MODE_EDIT);
}
static int shape_key_poll(bContext *C)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
@ -502,10 +557,11 @@ void OBJECT_OT_shape_key_add(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Add Shape Key";
ot->name= "Add shape key to the object.";
ot->idname= "OBJECT_OT_shape_key_add";
/* api callbacks */
ot->poll= shape_key_poll;
ot->poll= shape_key_mode_poll;
ot->exec= shape_key_add_exec;
/* flags */
@ -514,10 +570,9 @@ void OBJECT_OT_shape_key_add(wmOperatorType *ot)
static int shape_key_remove_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
if(!ED_object_shape_key_remove(C, scene, ob))
if(!ED_object_shape_key_remove(C, ob))
return OPERATOR_CANCELLED;
return OPERATOR_FINISHED;
@ -527,13 +582,132 @@ void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Remove Shape Key";
ot->name= "Remove shape key from the object.";
ot->idname= "OBJECT_OT_shape_key_remove";
/* api callbacks */
ot->poll= shape_key_poll;
ot->poll= shape_key_mode_poll;
ot->exec= shape_key_remove_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int shape_key_clear_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
Key *key= ob_get_key(ob);
KeyBlock *kb= ob_get_keyblock(ob);
if(!key || !kb)
return OPERATOR_CANCELLED;
for(kb=key->block.first; kb; kb=kb->next)
kb->curval= 0.0f;
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Clear Shape Keys";
ot->description= "Clear weights for all shape keys.";
ot->idname= "OBJECT_OT_shape_key_clear";
/* api callbacks */
ot->poll= shape_key_poll;
ot->exec= shape_key_clear_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int shape_key_mirror_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
if(!ED_object_shape_key_mirror(C, scene, ob))
return OPERATOR_CANCELLED;
return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Mirror Shape Key";
ot->idname= "OBJECT_OT_shape_key_mirror";
/* api callbacks */
ot->poll= shape_key_mode_poll;
ot->exec= shape_key_mirror_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int shape_key_move_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
int type= RNA_enum_get(op->ptr, "type");
Key *key= ob_get_key(ob);
if(key) {
KeyBlock *kb, *kb_other;
kb= BLI_findlink(&key->block, ob->shapenr-1);
if(type==-1) {
/* move back */
if(kb->prev) {
kb_other= kb->prev;
BLI_remlink(&key->block, kb);
BLI_insertlinkbefore(&key->block, kb_other, kb);
ob->shapenr--;
}
}
else {
/* move next */
if(kb->next) {
kb_other= kb->next;
BLI_remlink(&key->block, kb);
BLI_insertlinkafter(&key->block, kb_other, kb);
ob->shapenr++;
}
}
}
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_move(wmOperatorType *ot)
{
static EnumPropertyItem slot_move[] = {
{-1, "UP", 0, "Up", ""},
{1, "DOWN", 0, "Down", ""},
{0, NULL, 0, NULL, NULL}
};
/* identifiers */
ot->name= "Move Shape Key";
ot->idname= "OBJECT_OT_shape_key_move";
/* api callbacks */
ot->poll= shape_key_mode_poll;
ot->exec= shape_key_move_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
}

View File

@ -167,6 +167,33 @@ void ED_vgroup_data_create(ID *id)
}
}
/* returns true if the id type supports weights */
int ED_vgroup_give_array(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
{
if(id) {
switch(GS(id->name)) {
case ID_ME:
{
Mesh *me = (Mesh *)id;
*dvert_arr= me->dvert;
*dvert_tot= me->totvert;
return TRUE;
}
case ID_LT:
{
Lattice *lt= (Lattice *)id;
lt= (lt->editlatt)? lt->editlatt: lt;
*dvert_arr= lt->dvert;
*dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
return TRUE;
}
}
}
*dvert_arr= NULL;
*dvert_tot= 0;
return FALSE;
}
/* for mesh in object mode
lattice can be in editmode */
void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum)
@ -183,25 +210,18 @@ void ED_vgroup_nr_vert_remove(Object *ob, int def_nr, int vertnum)
MDeformWeight *newdw;
MDeformVert *dvert= NULL;
int i;
int i, tot;
/* 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= vgroup_edit_lattice(ob);
if(lt->dvert)
dvert = lt->dvert + vertnum;
}
ED_vgroup_give_array(ob->data, &dvert, &tot);
if(dvert==NULL)
return;
dvert+= vertnum;
/* for all of the deform weights in the
* deform vert
*/
@ -251,23 +271,16 @@ void ED_vgroup_nr_vert_add(Object *ob, int def_nr, int vertnum, float weight, in
*/
MDeformVert *dv= NULL;
MDeformWeight *newdw;
int i;
int i, tot;
/* 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= vgroup_edit_lattice(ob);
if(lt->dvert)
dv = lt->dvert + vertnum;
}
ED_vgroup_give_array(ob->data, &dv, &tot);
if(dv==NULL)
return;
dv+= vertnum;
/* Lets first check to see if this vert is
* already in the weight group -- if so
* lets update it
@ -342,23 +355,19 @@ void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight,
*/
int def_nr;
MDeformVert *dv= NULL;
int tot;
/* 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 there's no deform verts then create some,
*/
if(ob->type==OB_MESH) {
if(!((Mesh*)ob->data)->dvert)
ED_vgroup_data_create(ob->data);
}
else if(ob->type==OB_LATTICE) {
if(!((Lattice*)ob->data)->dvert)
ED_vgroup_data_create(ob->data);
}
if(ED_vgroup_give_array(ob->data, &dv, &tot) && dv==NULL)
ED_vgroup_data_create(ob->data);
/* call another function to do the work
*/
@ -549,16 +558,7 @@ static void vgroup_duplicate(Object *ob)
ob->actdef = BLI_countlist(&ob->defbase);
icdg = (ob->actdef-1);
if(ob->type == OB_MESH) {
Mesh *me = get_mesh(ob);
dvert_array= me->dvert;
dvert_tot= me->totvert;
}
else if(ob->type == OB_LATTICE) {
Lattice *lt= (Lattice *)ob->data;
dvert_array= lt->dvert;
dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
}
ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
if(!dvert_array)
return;
@ -575,6 +575,306 @@ static void vgroup_duplicate(Object *ob)
}
}
static void vgroup_normalize(Object *ob)
{
bDeformGroup *dg;
MDeformWeight *dw;
MDeformVert *dvert, *dvert_array=NULL;
int i, def_nr, dvert_tot=0;
ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
if(dg) {
float weight_max;
def_nr= ob->actdef-1;
for(i = 0; i < dvert_tot; i++) {
dvert = dvert_array+i;
dw = ED_vgroup_weight_get(dvert, def_nr);
if(dw) {
weight_max = MAX2(dw->weight, weight_max);
}
}
if(weight_max > 0.0f) {
for(i = 0; i < dvert_tot; i++) {
dvert = dvert_array+i;
dw = ED_vgroup_weight_get(dvert, def_nr);
if(dw) {
dw->weight /= weight_max;
/* incase of division errors with very low weights */
CLAMP(dw->weight, 0.0f, 1.0f);
}
}
}
}
}
/* TODO - select between groups */
static void vgroup_normalize_all(Object *ob, int lock_active)
{
MDeformWeight *dw, *dw_act;
MDeformVert *dvert, *dvert_array=NULL;
int i, dvert_tot=0;
float tot_weight;
ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
if(dvert_array) {
if(lock_active) {
int def_nr= ob->actdef-1;
for(i = 0; i < dvert_tot; i++) {
float lock_iweight= 1.0f;
int j;
tot_weight= 0.0f;
dw_act= NULL;
dvert = dvert_array+i;
j= dvert->totweight;
while(j--) {
dw= dvert->dw + j;
if(dw->def_nr==def_nr) {
dw_act= dw;
lock_iweight = (1.0f - dw_act->weight);
}
else {
tot_weight += dw->weight;
}
}
if(tot_weight) {
j= dvert->totweight;
while(j--) {
dw= dvert->dw + j;
if(dw == dw_act) {
if (dvert->totweight==1) {
dw_act->weight= 1.0f; /* no other weights, set to 1.0 */
}
} else {
if(dw->weight > 0.0f)
dw->weight = (dw->weight / tot_weight) * lock_iweight;
}
/* incase of division errors with very low weights */
CLAMP(dw->weight, 0.0f, 1.0f);
}
}
}
}
else {
for(i = 0; i < dvert_tot; i++) {
int j;
tot_weight= 0.0f;
dvert = dvert_array+i;
j= dvert->totweight;
while(j--) {
dw= dvert->dw + j;
tot_weight += dw->weight;
}
if(tot_weight) {
j= dvert->totweight;
while(j--) {
dw= dvert->dw + j;
dw->weight /= tot_weight;
/* incase of division errors with very low weights */
CLAMP(dw->weight, 0.0f, 1.0f);
}
}
}
}
}
}
static void vgroup_invert(Object *ob, int auto_assign, int auto_remove)
{
bDeformGroup *dg;
MDeformWeight *dw;
MDeformVert *dvert, *dvert_array=NULL;
int i, def_nr, dvert_tot=0;
ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
if(dg) {
def_nr= ob->actdef-1;
for(i = 0; i < dvert_tot; i++) {
dvert = dvert_array+i;
if(auto_assign) {
dw= ED_vgroup_weight_verify(dvert, def_nr);
} else {
dw= ED_vgroup_weight_get(dvert, def_nr);
}
if(dw) {
dw->weight = 1.0f-dw->weight;
if(auto_remove && dw->weight <= 0.0f) {
/* could have a faster function for this */
ED_vgroup_nr_vert_remove(ob, def_nr, i);
}
}
}
}
}
static void vgroup_blend(Object *ob)
{
BMEditMesh *em= ((Mesh *)ob->data)->edit_btmesh;
bDeformGroup *dg;
MDeformWeight *dw;
MDeformVert *dvert_array=NULL, *dvert;
int i, def_nr, dvert_tot=0;
// ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
if(em==NULL)
return;
dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
if(dg) {
BMEdge *eed;
BMVert *eve;
BMIter iter;
float *vg_weights;
float *vg_users;
int sel1, sel2;
int i1, i2;
def_nr= ob->actdef-1;
i= 0;
BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
BMINDEX_SET(eve, i);
i++;
}
dvert_tot= i;
vg_weights= MEM_callocN(sizeof(float)*dvert_tot, "vgroup_blend_f");
vg_users= MEM_callocN(sizeof(int)*dvert_tot, "vgroup_blend_i");
BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
sel1= BM_TestHFlag(eed->v1, BM_SELECT);
sel2= BM_TestHFlag(eed->v2, BM_SELECT);
if(sel1 != sel2) {
/* i1 is always the selected one */
if(sel1==TRUE && sel2==FALSE) {
i1= BMINDEX_GET(eed->v1);
i2= BMINDEX_GET(eed->v2);
eve= eed->v2;
}
else {
i2= BMINDEX_GET(eed->v1);
i1= BMINDEX_GET(eed->v2);
eve= eed->v1;
}
vg_users[i1]++;
/* TODO, we may want object mode blending */
if(em) dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
else dvert= dvert_array+i2;
dw= ED_vgroup_weight_get(dvert, def_nr);
if(dw) {
vg_weights[i1] += dw->weight;
}
}
}
i= 0;
BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
if(BM_TestHFlag(eve, BM_SELECT) && vg_users[i] > 0) {
/* TODO, we may want object mode blending */
if(em) dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT);
else dvert= dvert_array+i;
dw= ED_vgroup_weight_verify(dvert, def_nr);
dw->weight= vg_weights[i] / (float)vg_users[i];
}
i++;
}
MEM_freeN(vg_weights);
MEM_freeN(vg_users);
}
}
static void vgroup_clean(Object *ob, float eul, int keep_single)
{
bDeformGroup *dg;
MDeformWeight *dw;
MDeformVert *dvert, *dvert_array=NULL;
int i, def_nr, dvert_tot=0;
ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
/* only the active group */
dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
if(dg) {
def_nr= ob->actdef-1;
for(i = 0; i < dvert_tot; i++) {
dvert = dvert_array+i;
dw= ED_vgroup_weight_get(dvert, def_nr);
if(dw) {
if(dw->weight <= eul)
if(keep_single==FALSE || dvert->totweight > 1)
ED_vgroup_nr_vert_remove(ob, def_nr, i);
}
}
}
}
static void vgroup_clean_all(Object *ob, float eul, int keep_single)
{
MDeformWeight *dw;
MDeformVert *dvert, *dvert_array=NULL;
int i, dvert_tot=0;
ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
if(dvert_array) {
for(i = 0; i < dvert_tot; i++) {
int j;
dvert = dvert_array+i;
j= dvert->totweight;
while(j--) {
if(keep_single && dvert->totweight == 1)
break;
dw= dvert->dw + j;
if(dw->weight <= eul)
ED_vgroup_nr_vert_remove(ob, dw->def_nr, i);
}
}
}
}
static void vgroup_delete_update_users(Object *ob, int id)
{
ExplodeModifierData *emd;
@ -640,22 +940,13 @@ static void vgroup_delete_object_mode(Object *ob)
bDeformGroup *dg;
MDeformVert *dvert, *dvert_array=NULL;
int i, e, dvert_tot=0;
if(ob->type == OB_MESH) {
Mesh *me = get_mesh(ob);
dvert_array= me->dvert;
dvert_tot= me->totvert;
}
else if(ob->type == OB_LATTICE) {
Lattice *lt= (Lattice *)ob->data;
dvert_array= lt->dvert;
dvert_tot= lt->pntsu*lt->pntsv*lt->pntsw;
}
dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
if(!dg)
return;
ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);
if(dvert_array) {
for(i = 0; i < dvert_tot; i++) {
dvert = dvert_array + i;
@ -874,6 +1165,8 @@ static void vgroup_assign_verts(Object *ob, float weight)
int i, done;
dg=BLI_findlink(&ob->defbase, ob->actdef-1);
if(!dg)
return;
if(ob->type == OB_MESH) {
Mesh *me= ob->data;
@ -1173,6 +1466,161 @@ void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int vertex_group_normalize_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
vgroup_normalize(ob);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Normalize Vertex Group";
ot->idname= "OBJECT_OT_vertex_group_normalize";
/* api callbacks */
ot->poll= vertex_group_poll;
ot->exec= vertex_group_normalize_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
int lock_active= RNA_boolean_get(op->ptr,"lock_active");
vgroup_normalize_all(ob, lock_active);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Normalize All Vertex Groups";
ot->idname= "OBJECT_OT_vertex_group_normalize_all";
/* api callbacks */
ot->poll= vertex_group_poll;
ot->exec= vertex_group_normalize_all_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "lock_active", TRUE, "Lock Active", "Keep the values of the active group while normalizing others.");
}
static int vertex_group_invert_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
int auto_assign= RNA_boolean_get(op->ptr,"auto_assign");
int auto_remove= RNA_boolean_get(op->ptr,"auto_remove");
vgroup_invert(ob, auto_assign, auto_remove);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Invert Vertex Group";
ot->idname= "OBJECT_OT_vertex_group_invert";
/* api callbacks */
ot->poll= vertex_group_poll;
ot->exec= vertex_group_invert_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "auto_assign", TRUE, "Add Weights", "Add verts from groups that have zero weight before inverting.");
RNA_def_boolean(ot->srna, "auto_remove", TRUE, "Remove Weights", "Remove verts from groups that have zero weight after inverting.");
}
static int vertex_group_blend_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
vgroup_blend(ob);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_blend(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Blend Vertex Group";
ot->idname= "OBJECT_OT_vertex_group_blend";
/* api callbacks */
ot->poll= vertex_group_poll;
ot->exec= vertex_group_blend_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int vertex_group_clean_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
float limit= RNA_float_get(op->ptr,"limit");
int all_groups= RNA_boolean_get(op->ptr,"all_groups");
int keep_single= RNA_boolean_get(op->ptr,"keep_single");
if(all_groups) vgroup_clean_all(ob, limit, keep_single);
else vgroup_clean(ob, limit, keep_single);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Clean Vertex Group";
ot->idname= "OBJECT_OT_vertex_group_clean";
/* api callbacks */
ot->poll= vertex_group_poll;
ot->exec= vertex_group_clean_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, 1.0, "Limit", "Remove weights under this limit.", 0.001f, 0.99f);
RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Clean all vertex groups.");
RNA_def_boolean(ot->srna, "keep_single", FALSE, "Keep Single", "Keep verts assigned to at least one group when cleaning.");
}
static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);

View File

@ -851,7 +851,7 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
ParticleSystemModifierData *psmd;
POINT_P; KEY_K;
int index;
float *vec, *nor, dvec[3], dot, dist_1st;
float *vec, *nor, dvec[3], dot, dist_1st=0.0f;
float hairimat[4][4], hairmat[4][4];
if(edit==NULL || edit->psys==NULL || (pset->flag & PE_DEFLECT_EMITTER)==0 || (edit->psys->flag & PSYS_GLOBAL_HAIR))
@ -2708,6 +2708,10 @@ static void brush_cut(PEData *data, int pa_index)
/* blunt scissors */
if(BLI_frand() > data->cutfac) return;
/* don't cut hidden */
if(edit->points[pa_index].flag & PEP_HIDE)
return;
rad2= data->rad * data->rad;
cut=0;
@ -2791,7 +2795,7 @@ static void brush_length(PEData *data, int point_index)
PTCacheEdit *edit= data->edit;
PTCacheEditPoint *point = edit->points + point_index;
KEY_K;
float dvec[3],pvec[3];
float dvec[3],pvec[3] = {0.0f, 0.0f, 0.0f};
LOOP_KEYS {
if(k==0) {
@ -2815,7 +2819,7 @@ static void brush_puff(PEData *data, int point_index)
PTCacheEditPoint *point = edit->points + point_index;
KEY_K;
float mat[4][4], imat[4][4];
float lastco[3], rootco[3], co[3], nor[3], kco[3], dco[3], fac, length;
float lastco[3], rootco[3] = {0.0f, 0.0f, 0.0f}, co[3], nor[3], kco[3], dco[3], fac=0.0f, length=0.0f;
if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, psys->particles + point_index, mat);
@ -2897,7 +2901,7 @@ static void brush_smooth_do(PEData *data, float mat[][4], float imat[][4], int p
(data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
}
static void brush_add(PEData *data, short number)
static int brush_add(PEData *data, short number)
{
Scene *scene= data->scene;
Object *ob= data->ob;
@ -2918,7 +2922,7 @@ static void brush_add(PEData *data, short number)
Mat4Invert(imat,ob->obmat);
if(psys->flag & PSYS_GLOBAL_HAIR)
return;
return 0;
BLI_srandom(psys->seed+data->mval[0]+data->mval[1]);
@ -3093,6 +3097,8 @@ static void brush_add(PEData *data, short number)
if(!psmd->dm->deformedOnly)
dm->release(dm);
return n;
}
/************************* brush edit operator ********************/
@ -3143,7 +3149,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
ARegion *ar= CTX_wm_region(C);
float vec[3], mousef[2];
short mval[2], mvalo[2];
int flip, mouse[2], dx, dy, removed= 0, selected= 0;
int flip, mouse[2], dx, dy, removed= 0, added=0, selected= 0;
int lock_root = pset->flag & PE_LOCK_FIRST;
if(!PE_start_edit(edit))
@ -3221,6 +3227,9 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if(pset->flag & PE_KEEP_LENGTHS)
recalc_lengths(edit);
}
else
removed= 0;
break;
}
case PE_BRUSH_LENGTH:
@ -3275,11 +3284,13 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
PE_set_view3d_data(C, &data);
data.mval= mval;
brush_add(&data, brush->strength);
added= brush_add(&data, brush->strength);
if(pset->flag & PE_KEEP_LENGTHS)
recalc_lengths(edit);
}
else
added= 0;
break;
}
case PE_BRUSH_SMOOTH:
@ -3310,13 +3321,15 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if((pset->flag & PE_KEEP_LENGTHS)==0)
recalc_lengths(edit);
if(pset->brushtype == PE_BRUSH_ADD || removed) {
if(pset->brushtype == PE_BRUSH_ADD && (pset->flag & PE_X_MIRROR))
PE_mirror_x(scene, ob, 1);
if(ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT)) {
if(added || removed) {
if(pset->brushtype == PE_BRUSH_ADD && (pset->flag & PE_X_MIRROR))
PE_mirror_x(scene, ob, 1);
update_world_cos(ob,edit);
psys_free_path_cache(NULL, edit);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
update_world_cos(ob,edit);
psys_free_path_cache(NULL, edit);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
}
}
else
PE_update_object(scene, ob, 1);

View File

@ -386,6 +386,90 @@ void PARTICLE_OT_dupliob_move_up(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/********************** particle dupliweight operators *********************/
static int copy_particle_dupliob_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
ParticleSettings *part;
ParticleDupliWeight *dw;
if(!psys)
return OPERATOR_CANCELLED;
part = psys->part;
for(dw=part->dupliweights.first; dw; dw=dw->next) {
if(dw->flag & PART_DUPLIW_CURRENT) {
dw->flag &= ~PART_DUPLIW_CURRENT;
dw = MEM_dupallocN(dw);
dw->flag |= PART_DUPLIW_CURRENT;
BLI_addhead(&part->dupliweights, dw);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
break;
}
}
return OPERATOR_FINISHED;
}
void PARTICLE_OT_dupliob_copy(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Copy Particle Dupliob";
ot->idname= "PARTICLE_OT_dupliob_copy";
ot->description="Duplicate the current dupliobject.";
/* api callbacks */
ot->exec= copy_particle_dupliob_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int remove_particle_dupliob_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
ParticleSettings *part;
ParticleDupliWeight *dw;
if(!psys)
return OPERATOR_CANCELLED;
part = psys->part;
for(dw=part->dupliweights.first; dw; dw=dw->next) {
if(dw->flag & PART_DUPLIW_CURRENT) {
BLI_remlink(&part->dupliweights, dw);
MEM_freeN(dw);
break;
}
}
dw = part->dupliweights.last;
if(dw)
dw->flag |= PART_DUPLIW_CURRENT;
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
return OPERATOR_FINISHED;
}
void PARTICLE_OT_dupliob_remove(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Remove Particle Dupliobject";
ot->idname= "PARTICLE_OT_dupliob_remove";
ot->description="Remove the selected dupliobject.";
/* api callbacks */
ot->exec= remove_particle_dupliob_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/************************ move down particle dupliweight operator *********************/
static int dupliob_move_down_exec(bContext *C, wmOperator *op)
@ -517,7 +601,7 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
ParticleData *pa;
PTCacheEdit *edit;
PTCacheEditPoint *point;
PTCacheEditKey *ekey;
PTCacheEditKey *ekey = NULL;
HairKey *key;
BVHTreeFromMesh bvhtree;
BVHTreeNearest nearest;

Some files were not shown because too many files have changed in this diff Show More