diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2010-02-28 06:44:15 +0300 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2010-02-28 06:44:15 +0300 |
commit | b21a994076e12804efe49dc35fb698a81f5a33a3 (patch) | |
tree | c6630190078ff969b5bbc8eca48235c9833eb73a /source/blender | |
parent | 07fdcb1f1b919f1359c6b77d8ae2fe08d7506a48 (diff) | |
parent | e51bcbae6230882eb2c5b16974b86a906b398408 (diff) |
Merged changes in the trunk up to revision 27178.
Diffstat (limited to 'source/blender')
98 files changed, 1846 insertions, 974 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 2f2fcfcc531..f6950ba07b8 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -70,11 +70,11 @@ void BKE_animdata_make_local(struct AnimData *adt); /* Used to create a new 'custom' KeyingSet for the user, that will be automatically added to the stack */ struct KeyingSet *BKE_keyingset_add(struct ListBase *list, const char name[], short flag, short keyingflag); -/* 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); +/* Add a path to a KeyingSet */ +void BKE_keyingset_add_path(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); +struct KS_Path *BKE_keyingset_find_path(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 */ void BKE_keyingsets_copy(struct ListBase *newlist, struct ListBase *list); diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 3aad5a8c1e4..6084b0cfb73 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -113,7 +113,7 @@ typedef struct Global { /* #define G_FACESELECT (1 << 8) use (mesh->editflag & ME_EDIT_PAINT_MASK) */ #define G_DEBUG (1 << 12) -#define G_DOSCRIPTLINKS (1 << 13) +#define G_SCRIPT_AUTOEXEC (1 << 13) /* #define G_NOFROZEN (1 << 17) also removed */ #define G_GREASEPENCIL (1 << 17) diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 153cf3f300e..6b22b10cf24 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -130,9 +130,6 @@ void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf); /* called on frame change or before render */ void BKE_image_user_calc_frame(struct ImageUser *iuser, int cfra, int fieldnr); -/* produce image export path */ -int BKE_get_image_export_path(struct Image *im, const char *dest_dir, char *abs, int abs_size, char *rel, int rel_size); - /* fix things in ImageUser when new image gets assigned */ void BKE_image_user_new_image(struct Image *ima, struct ImageUser *iuser); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 703ed118a58..a6a641a3219 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -112,10 +112,13 @@ void boundbox_set_from_min_max(struct BoundBox *bb, float min[3], float max[3]); struct BoundBox *object_get_boundbox(struct Object *ob); void object_boundbox_flag(struct Object *ob, int flag, int set); void minmax_object(struct Object *ob, float *min, float *max); -void minmax_object_duplis(struct Scene *scene, struct Object *ob, float *min, float *max); +int minmax_object_duplis(struct Scene *scene, struct Object *ob, float *min, float *max); void solve_tracking (struct Object *ob, float targetmat[][4]); int ray_hit_boundbox(struct BoundBox *bb, float ray_start[3], float ray_normal[3]); +void *object_tfm_backup(struct Object *ob); +void object_tfm_restore(struct Object *ob, void *obtfm_pt); + void object_handle_update(struct Scene *scene, struct Object *ob); float give_timeoffset(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index b291d9126ee..10550ccdc05 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -55,6 +55,7 @@ /* File open options, for BKE_ptcache_file_open */ #define PTCACHE_FILE_READ 0 #define PTCACHE_FILE_WRITE 1 +#define PTCACHE_FILE_UPDATE 2 /* PTCacheID types */ #define PTCACHE_TYPE_SOFTBODY 0 diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 7b2eea141f2..a880417a111 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -547,7 +547,7 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa /* Find the first path that matches the given criteria */ // TODO: do we want some method to perform partial matches too? -KS_Path *BKE_keyingset_find_destination (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode) +KS_Path *BKE_keyingset_find_path (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode) { KS_Path *ksp; @@ -624,7 +624,7 @@ KeyingSet *BKE_keyingset_add (ListBase *list, const char name[], short flag, sho /* Add a destination to a KeyingSet. Nothing is returned for now... * Checks are performed to ensure that destination is appropriate for the KeyingSet in question */ -void BKE_keyingset_add_destination (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode) +void BKE_keyingset_add_path (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode) { KS_Path *ksp; @@ -643,7 +643,7 @@ void BKE_keyingset_add_destination (KeyingSet *ks, ID *id, const char group_name } /* don't add if there is already a matching KS_Path in the KeyingSet */ - if (BKE_keyingset_find_destination(ks, id, group_name, rna_path, array_index, groupmode)) { + if (BKE_keyingset_find_path(ks, id, group_name, rna_path, array_index, groupmode)) { if (G.f & G_DEBUG) printf("ERROR: destination already exists in Keying Set \n"); return; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 9c1e15b0f77..4903ea84b3d 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1502,7 +1502,8 @@ void where_is_armature (bArmature *arm) } } -/* if bone layer is protected, copy the data from from->pose */ +/* if bone layer is protected, copy the data from from->pose + * when used with linked libraries this copies from the linked pose into the local pose */ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected) { bPose *pose= ob->pose, *frompose= from->pose; diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 1567ed0f986..171b48af974 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -291,8 +291,6 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename) if (G.f & G_SWAP_EXCHANGE) bfd->globalf |= G_SWAP_EXCHANGE; else bfd->globalf &= ~G_SWAP_EXCHANGE; - if ((U.flag & USER_DONT_DOSCRIPTLINKS)) bfd->globalf &= ~G_DOSCRIPTLINKS; - G.f= bfd->globalf; if (!G.background) { @@ -358,7 +356,7 @@ void BKE_userdef_free(void) BLI_freelistN(&U.uifonts); BLI_freelistN(&U.themes); BLI_freelistN(&U.keymaps); - BLI_freelistN(&U.extensions); + BLI_freelistN(&U.addons); } /* returns: diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 89c3da9b3e9..b521ec41cba 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -162,8 +162,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, else if(rule->type == eBoidRuleType_Avoid && bpa->data.mode == eBoidMode_Climbing && priority > 2.0f * gabr->fear_factor) { /* detach from surface and try to fly away from danger */ - VECCOPY(efd.vec_to_point, bpa->gravity); - mul_v3_fl(efd.vec_to_point, -1.0f); + negate_v3_v3(efd.vec_to_point, bpa->gravity); } VECCOPY(bbd->wanted_co, efd.vec_to_point); @@ -689,7 +688,7 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti if(bpa->data.health/bbd->part->boids->health * bbd->part->boids->aggression < e_strength / f_strength) { /* decide to flee */ if(closest_dist < fbr->flee_distance * fbr->distance) { - mul_v3_fl(bbd->wanted_co, -1.0f); + negate_v3(bbd->wanted_co); bbd->wanted_speed = val->max_speed; } else { /* wait for better odds */ @@ -1342,9 +1341,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) float grav[3]; /* Don't take gravity's strength in to account, */ /* otherwise amount of banking is hard to control. */ - VECCOPY(grav, ground_nor); - mul_v3_fl(grav, -1.0f); - + negate_v3_v3(grav, ground_nor); + project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel); sub_v3_v3v3(dvec, bpa->data.acc, dvec); @@ -1387,7 +1385,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) VECCOPY(mat[2], bpa->gravity); } - mul_v3_fl(mat[2], -1.0f); + negate_v3(mat[2]); cross_v3_v3v3(mat[1], mat[2], mat[0]); /* apply rotation */ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 86591fe784d..855de95572a 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -545,7 +545,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, implicit_set_positions(clmd); cache->flag |= PTCACHE_SIMULATION_VALID; } - else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { + else if( /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED)) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */ /* if baked and nothing in cache, do nothing */ cache->flag &= ~PTCACHE_SIMULATION_VALID; cache->simframe= 0; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index b726437a874..b024ba5f4e1 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1550,8 +1550,8 @@ static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, Collision // cloth - object collisions int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, float dt ) { - Cloth *cloth=NULL; - BVHTree *cloth_bvh=NULL; + Cloth *cloth= clmd->clothObject; + BVHTree *cloth_bvh= cloth->bvhtree; int i=0, numfaces = 0, numverts = 0, k, l, j; int rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; @@ -1559,16 +1559,12 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl Object **collobjs = NULL; int numcollobj = 0; - if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) ) - { + if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || cloth_bvh==NULL) return 0; - } - cloth = clmd->clothObject; verts = cloth->verts; - cloth_bvh = ( BVHTree * ) cloth->bvhtree; - numfaces = clmd->clothObject->numfaces; - numverts = clmd->clothObject->numverts; + numfaces = cloth->numfaces; + numverts = cloth->numverts; //////////////////////////////////////////////////////////// // static collisions @@ -1672,8 +1668,8 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl // collisions = 1; verts = cloth->verts; // needed for openMP - numfaces = clmd->clothObject->numfaces; - numverts = clmd->clothObject->numverts; + numfaces = cloth->numfaces; + numverts = cloth->numverts; verts = cloth->verts; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index c22510a2527..53a07193aa6 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1947,7 +1947,7 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT /* only execute target calculation if allowed */ #ifndef DISABLE_PYTHON - if (G.f & G_DOSCRIPTLINKS) + if (G.f & G_SCRIPT_AUTOEXEC) BPY_pyconstraint_target(data, ct); #endif } @@ -1963,7 +1963,7 @@ static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targ bPythonConstraint *data= con->data; /* only evaluate in python if we're allowed to do so */ - if ((G.f & G_DOSCRIPTLINKS)==0) return; + if ((G.f & G_SCRIPT_AUTOEXEC)==0) return; /* currently removed, until I this can be re-implemented for multiple targets */ #if 0 diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 9d33bc5ae11..fb27327c3be 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -191,6 +191,7 @@ Curve *copy_curve(Curve *cu) cun->path= 0; cun->editnurb= NULL; + cun->editfont= NULL; #if 0 // XXX old animation system /* single user ipo too */ diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 552c7d0767d..bd29bd55428 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -326,7 +326,7 @@ FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction } /* threshold for binary-searching keyframes - threshold here should be good enough for now, but should become userpref */ -#define BEZT_BINARYSEARCH_THRESH 0.00001f +#define BEZT_BINARYSEARCH_THRESH 0.01f /* was 0.00001, but giving errors */ /* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_fcurve) * Returns the index to insert at (data already at that index will be offset if replace is 0) @@ -801,13 +801,19 @@ typedef struct DriverVarTypeInfo { /* ......... */ +static ID *dtar_id_ensure_proxy_from(ID *id) +{ + if (id && GS(id->name)==ID_OB && ((Object *)id)->proxy_from) + return (ID *)(((Object *)id)->proxy_from); + return id; +} + /* Helper function to obtain a value using RNA from the specified source (for evaluating drivers) */ static float dtar_get_prop_val (ChannelDriver *driver, DriverTarget *dtar) { PointerRNA id_ptr, ptr; PropertyRNA *prop; ID *id; - char *path; int index; float value= 0.0f; @@ -815,22 +821,22 @@ static float dtar_get_prop_val (ChannelDriver *driver, DriverTarget *dtar) if ELEM(NULL, driver, dtar) return 0.0f; - /* get RNA-pointer for the ID-block given in target */ - RNA_id_pointer_create(dtar->id, &id_ptr); - id= dtar->id; - path= dtar->rna_path; + id= dtar_id_ensure_proxy_from(dtar->id); /* error check for missing pointer... */ // TODO: tag the specific target too as having issues if (id == NULL) { printf("Error: driver has an invalid target to use \n"); - if (G.f & G_DEBUG) printf("\tpath = %s\n", path); + if (G.f & G_DEBUG) printf("\tpath = %s\n", dtar->rna_path); driver->flag |= DRIVER_FLAG_INVALID; return 0.0f; } + /* get RNA-pointer for the ID-block given in target */ + RNA_id_pointer_create(id, &id_ptr); + /* get property to read from, and get value as appropriate */ - if (RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) { + if (RNA_path_resolve_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { switch (RNA_property_type(prop)) { case PROP_BOOLEAN: if (RNA_property_array_length(&ptr, prop)) @@ -859,7 +865,7 @@ static float dtar_get_prop_val (ChannelDriver *driver, DriverTarget *dtar) } else { if (G.f & G_DEBUG) - printf("Driver Evaluation Error: cannot resolve target for %s -> %s \n", id->name, path); + printf("Driver Evaluation Error: cannot resolve target for %s -> %s \n", id->name, dtar->rna_path); driver->flag |= DRIVER_FLAG_INVALID; return 0.0f; @@ -871,13 +877,16 @@ static float dtar_get_prop_val (ChannelDriver *driver, DriverTarget *dtar) /* Helper function to obtain a pointer to a Pose Channel (for evaluating drivers) */ static bPoseChannel *dtar_get_pchan_ptr (ChannelDriver *driver, DriverTarget *dtar) { + ID *id; /* sanity check */ if ELEM(NULL, driver, dtar) return NULL; - + + id= dtar_id_ensure_proxy_from(dtar->id); + /* check if the ID here is a valid object */ - if ((dtar->id) && GS(dtar->id->name)) { - Object *ob= (Object *)dtar->id; + if (id && GS(id->name)) { + Object *ob= (Object *)id; /* get pose, and subsequently, posechannel */ return get_pose_channel(ob->pose, dtar->pchan_name); @@ -947,12 +956,12 @@ static float dvar_eval_locDiff (ChannelDriver *driver, DriverVar *dvar) DRIVER_TARGETS_USED_LOOPER(dvar) { /* get pointer to loc values to store in */ - Object *ob= (Object *)dtar->id; + Object *ob= (Object *)dtar_id_ensure_proxy_from(dtar->id); bPoseChannel *pchan; float tmp_loc[3]; /* check if this target has valid data */ - if ((ob == NULL) || (GS(dtar->id->name) != ID_OB)) { + if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { /* invalid target, so will not have enough targets */ driver->flag |= DRIVER_FLAG_INVALID; return 0.0f; @@ -1007,14 +1016,14 @@ static float dvar_eval_locDiff (ChannelDriver *driver, DriverVar *dvar) static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar) { DriverTarget *dtar= &dvar->targets[0]; - Object *ob= (Object *)dtar->id; + Object *ob= (Object *)dtar_id_ensure_proxy_from(dtar->id); bPoseChannel *pchan; float mat[4][4]; float eul[3] = {0.0f,0.0f,0.0f}; short useEulers=0, rotOrder=ROT_MODE_EUL; /* check if this target has valid data */ - if ((ob == NULL) || (GS(dtar->id->name) != ID_OB)) { + if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { /* invalid target, so will not have enough targets */ driver->flag |= DRIVER_FLAG_INVALID; return 0.0f; @@ -1281,7 +1290,7 @@ ChannelDriver *fcurve_copy_driver (ChannelDriver *driver) float driver_get_variable_value (ChannelDriver *driver, DriverVar *dvar) { DriverVarTypeInfo *dvti; - + /* sanity check */ if (ELEM(NULL, driver, dvar)) return 0.0f; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index d6edb068fa0..accadb3d434 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2260,104 +2260,3 @@ void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr) if(iuser->ok==0) iuser->ok= 1; } } - -/* - Produce image export path. - - Fails returning 0 if image filename is empty or if destination path - matches image path (i.e. both are the same file). - - Trailing slash in dest_dir is optional. - - Logic: - - - if an image is "below" current .blend file directory, rebuild the - same dir structure in dest_dir - - For example //textures/foo/bar.png becomes - [dest_dir]/textures/foo/bar.png. - - - if an image is not "below" current .blend file directory, - disregard it's path and copy it in the same directory where 3D file - goes. - - For example //../foo/bar.png becomes [dest_dir]/bar.png. - - This logic will help ensure that all image paths are relative and - that a user gets his images in one place. It'll also provide - consistent behaviour across exporters. - */ -int BKE_get_image_export_path(struct Image *im, const char *dest_dir, char *abs, int abs_size, char *rel, int rel_size) -{ - char path[FILE_MAX]; - char dir[FILE_MAX]; - char base[FILE_MAX]; - char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */ - char dest_path[FILE_MAX]; - char rel_dir[FILE_MAX]; - int len; - - if (abs) - abs[0]= 0; - - if (rel) - rel[0]= 0; - - BLI_split_dirfile_basic(G.sce, blend_dir, NULL); - - if (!strlen(im->name)) { - if (G.f & G_DEBUG) printf("Invalid image type.\n"); - return 0; - } - - BLI_strncpy(path, im->name, sizeof(path)); - - /* expand "//" in filename and get absolute path */ - BLI_convertstringcode(path, G.sce); - - /* get the directory part */ - BLI_split_dirfile_basic(path, dir, base); - - len= strlen(blend_dir); - - rel_dir[0] = 0; - - /* if image is "below" current .blend file directory */ - if (!strncmp(path, blend_dir, len)) { - - /* if image is _in_ current .blend file directory */ - if (!strcmp(dir, blend_dir)) { - BLI_join_dirfile(dest_path, dest_dir, base); - } - /* "below" */ - else { - /* rel = image_path_dir - blend_dir */ - BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir)); - - BLI_join_dirfile(dest_path, dest_dir, rel_dir); - BLI_join_dirfile(dest_path, dest_path, base); - } - - } - /* image is out of current directory */ - else { - BLI_join_dirfile(dest_path, dest_dir, base); - } - - if (abs) - BLI_strncpy(abs, dest_path, abs_size); - - if (rel) { - strncat(rel, rel_dir, rel_size); - strncat(rel, base, rel_size); - } - - /* return 2 if src=dest */ - if (!strcmp(path, dest_path)) { - if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path); - return 2; - } - - return 1; -} - diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index ed3e7348d7e..6912a65886a 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1408,19 +1408,29 @@ typedef struct HairGridVert { float velocity[3]; float density; } HairGridVert; +#define HAIR_GRID_INDEX(vec, min, max, axis) (int)( (vec[axis] - min[axis]) / (max[axis] - min[axis]) * 9.99f ); /* Smoothing of hair velocities: * adapted from Volumetric Methods for Simulation and Rendering of Hair by Lena Petrovic, Mark Henne and John Anderson * Pixar Technical Memo #06-08, Pixar Animation Studios */ -static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX, lfVector *lV, int numverts) +static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, int numverts) { - /* TODO: this is an initial implementation and should be made much better in due time */ + /* TODO: This is an initial implementation and should be made much better in due time. + * What should at least be implemented is a grid size parameter and a smoothing kernel + * for bigger grids. + */ /* 10x10x10 grid gives nice initial results */ HairGridVert grid[10][10][10]; + HairGridVert colg[10][10][10]; + ListBase *colliders = get_collider_cache(clmd->scene, NULL); + ColliderCache *col = NULL; float gmin[3], gmax[3], density; + /* 2.0f is an experimental value that seems to give good results */ + float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth; + float collfac = 2.0f * clmd->sim_parms->collider_friction; int v = 0; int i = 0; int j = 0; @@ -1439,15 +1449,20 @@ static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX, grid[i][j][k].velocity[1] = 0.0f; grid[i][j][k].velocity[2] = 0.0f; grid[i][j][k].density = 0.0f; + + colg[i][j][k].velocity[0] = 0.0f; + colg[i][j][k].velocity[1] = 0.0f; + colg[i][j][k].velocity[2] = 0.0f; + colg[i][j][k].density = 0.0f; } } } /* gather velocities & density */ - for(v = 0; v < numverts; v++) { - i = (int)( (lX[v][0] - gmin[0]) / (gmax[0] - gmin[0]) * 9.99f ); - j = (int)( (lX[v][1] - gmin[1]) / (gmax[1] - gmin[1]) * 9.99f ); - k = (int)( (lX[v][2] - gmin[2]) / (gmax[2] - gmin[2]) * 9.99f ); + if(smoothfac > 0.0f) for(v = 0; v < numverts; v++) { + i = HAIR_GRID_INDEX(lX[v], gmin, gmax, 0); + j = HAIR_GRID_INDEX(lX[v], gmin, gmax, 1); + k = HAIR_GRID_INDEX(lX[v], gmin, gmax, 2); grid[i][j][k].velocity[0] += lV[v][0]; grid[i][j][k].velocity[1] += lV[v][1]; @@ -1455,6 +1470,36 @@ static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX, grid[i][j][k].density += 1.0f; } + /* gather colliders */ + if(colliders && collfac > 0.0f) for(col = colliders->first; col; col = col->next) + { + MVert *loc0 = col->collmd->x; + MVert *loc1 = col->collmd->xnew; + float vel[3]; + + for(v=0; v<col->collmd->numverts; v++, loc0++, loc1++) { + i = HAIR_GRID_INDEX(loc1->co, gmin, gmax, 0); + + if(i>=0 && i<10) { + j = HAIR_GRID_INDEX(loc1->co, gmin, gmax, 1); + + if(j>=0 && j<10) { + k = HAIR_GRID_INDEX(loc1->co, gmin, gmax, 2); + + if(k>=0 && k<10) { + VECSUB(vel, loc1->co, loc0->co); + + colg[i][j][k].velocity[0] += vel[0]; + colg[i][j][k].velocity[1] += vel[1]; + colg[i][j][k].velocity[2] += vel[2]; + colg[i][j][k].density += 1.0; + } + } + } + } + } + + /* divide velocity with density */ for(i = 0; i < 10; i++) { for(j = 0; j < 10; j++) { @@ -1465,21 +1510,35 @@ static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX, grid[i][j][k].velocity[1] /= density; grid[i][j][k].velocity[2] /= density; } + + density = colg[i][j][k].density; + if(density > 0.0f) { + colg[i][j][k].velocity[0] /= density; + colg[i][j][k].velocity[1] /= density; + colg[i][j][k].velocity[2] /= density; + } } } } /* calculate forces */ for(v = 0; v < numverts; v++) { - i = (int)( (lX[v][0] - gmin[0]) / (gmax[0] - gmin[0]) * 9.99f ); - j = (int)( (lX[v][1] - gmin[1]) / (gmax[1] - gmin[1]) * 9.99f ); - k = (int)( (lX[v][2] - gmin[2]) / (gmax[2] - gmin[2]) * 9.99f ); - - /* 2.0f is an experimental value that seems to give good results */ - lF[v][0] += 2.0f * smoothfac * (grid[i][j][k].velocity[0] - lV[v][0]); - lF[v][1] += 2.0f * smoothfac * (grid[i][j][k].velocity[1] - lV[v][1]); - lF[v][2] += 2.0f * smoothfac * (grid[i][j][k].velocity[2] - lV[v][2]); + i = HAIR_GRID_INDEX(lX[v], gmin, gmax, 0); + j = HAIR_GRID_INDEX(lX[v], gmin, gmax, 1); + k = HAIR_GRID_INDEX(lX[v], gmin, gmax, 2); + + lF[v][0] += smoothfac * (grid[i][j][k].velocity[0] - lV[v][0]); + lF[v][1] += smoothfac * (grid[i][j][k].velocity[1] - lV[v][1]); + lF[v][2] += smoothfac * (grid[i][j][k].velocity[2] - lV[v][2]); + + if(colg[i][j][k].density > 0.0f) { + lF[v][0] += collfac * (colg[i][j][k].velocity[0] - lV[v][0]); + lF[v][1] += collfac * (colg[i][j][k].velocity[1] - lV[v][1]); + lF[v][2] += collfac * (colg[i][j][k].velocity[2] - lV[v][2]); + } } + + free_collider_cache(&colliders); } static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M) { @@ -1508,8 +1567,8 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, init_lfvector(lF, gravity, numverts); - if(clmd->sim_parms->velocity_smooth > 0.0f) - hair_velocity_smoothing(clmd->sim_parms->velocity_smooth, lF, lX, lV, numverts); + if(clmd->sim_parms->velocity_smooth > 0.0f || clmd->sim_parms->collider_friction > 0.0f) + hair_velocity_smoothing(clmd, lF, lX, lV, numverts); /* multiply lF with mass matrix // force = mass * acceleration (in this case: gravity) @@ -1579,6 +1638,36 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, VECADDS(lF[mfaces[i].v4], lF[mfaces[i].v4], tmp, factor); } } + + /* Hair has only edges */ + if(cloth->numfaces == 0) { + ClothSpring *spring; + float edgevec[3]={0,0,0}; //edge vector + float edgeunnormal[3]={0,0,0}; // not-normalized-edge normal + float tmp[3]={0,0,0}; + float factor = 0.01; + + search = cloth->springs; + while(search) { + spring = search->link; + + if(spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) { + VECSUB(edgevec, (float*)lX[spring->ij], (float*)lX[spring->kl]); + + project_v3_v3v3(tmp, winvec[spring->ij], edgevec); + VECSUB(edgeunnormal, winvec[spring->ij], tmp); + /* hair doesn't stretch too much so we can use restlen pretty safely */ + VECADDS(lF[spring->ij], lF[spring->ij], edgeunnormal, spring->restlen * factor); + + project_v3_v3v3(tmp, winvec[spring->kl], edgevec); + VECSUB(edgeunnormal, winvec[spring->kl], tmp); + VECADDS(lF[spring->kl], lF[spring->kl], edgeunnormal, spring->restlen * factor); + } + + search = search->next; + } + } + del_lfvector(winvec); } @@ -1689,8 +1778,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase VECCOPY(verts[i].txold, id->X[i]); } - - if(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) + + if(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED && clmd->clothObject->bvhtree) { float temp = clmd->sim_parms->stepsPerFrame; /* not too nice hack, but collisions need this correction -jahka */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index ff00dc9dc3c..146701f2976 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -353,15 +353,14 @@ static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest, static void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3]) { - md= md->next; - if(md) { - if(md->type==eModifierType_Armature) { - ArmatureModifierData *amd = (ArmatureModifierData*) md; - if(amd->multi) - amd->prevCos= MEM_dupallocN(vertexCos); - } - /* lattice/mesh modifier too */ + while((md=md->next) && md->type==eModifierType_Armature) { + ArmatureModifierData *amd = (ArmatureModifierData*) md; + if(amd->multi && amd->prevCos==NULL) + amd->prevCos= MEM_dupallocN(vertexCos); + else + break; } + /* lattice/mesh modifier too */ } @@ -4826,9 +4825,15 @@ static void castModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { - DerivedMesh *dm = get_dm(md->scene, ob, NULL, derivedData, NULL, 0); + DerivedMesh *dm = NULL; CastModifierData *cmd = (CastModifierData *)md; + if (ob->type == OB_MESH) { + /* DerivedMesh is used only in case object is MESH */ + /* so we could optimize modifier applying by skipping DM creation */ + dm = get_dm(md->scene, ob, NULL, derivedData, NULL, 0); + } + if (cmd->type == MOD_CAST_TYPE_CUBOID) { castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts); } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 88aaf054aec..46c26524f47 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2373,27 +2373,97 @@ void minmax_object(Object *ob, float *min, float *max) } } -/* TODO - use dupli objects bounding boxes */ -void minmax_object_duplis(Scene *scene, Object *ob, float *min, float *max) +int minmax_object_duplis(Scene *scene, Object *ob, float *min, float *max) { + int ok= 0; if ((ob->transflag & OB_DUPLI)==0) { - return; + return ok; } else { ListBase *lb; DupliObject *dob; lb= object_duplilist(scene, ob); for(dob= lb->first; dob; dob= dob->next) { - if(dob->no_draw); - else { - /* should really use bound box of dup object */ - DO_MINMAX(dob->mat[3], min, max); + if(dob->no_draw == 0) { + BoundBox *bb= object_get_boundbox(dob->ob); + + if(bb) { + int i; + for(i=0; i<8; i++) { + float vec[3]; + mul_v3_m4v3(vec, dob->mat, bb->vec[i]); + DO_MINMAX(vec, min, max); + } + + ok= 1; + } } } free_object_duplilist(lb); /* does restore */ } -} + return ok; +} + +/* copied from DNA_object_types.h */ +typedef struct ObTfmBack { + float loc[3], dloc[3], orig[3]; + float size[3], dsize[3]; /* scale and delta scale */ + float rot[3], drot[3]; /* euler rotation */ + float quat[4], dquat[4]; /* quaternion rotation */ + float rotAxis[3], drotAxis[3]; /* axis angle rotation - axis part */ + float rotAngle, drotAngle; /* axis angle rotation - angle part */ + float obmat[4][4]; /* final worldspace matrix with constraints & animsys applied */ + float parentinv[4][4]; /* inverse result of parent, so that object doesn't 'stick' to parent */ + float constinv[4][4]; /* inverse result of constraints. doesn't include effect of parent or object local transform */ + float imat[4][4]; /* inverse matrix of 'obmat' for during render, old game engine, temporally: ipokeys of transform */ +} ObTfmBack; + +void *object_tfm_backup(Object *ob) +{ + ObTfmBack *obtfm= MEM_mallocN(sizeof(ObTfmBack), "ObTfmBack"); + copy_v3_v3(obtfm->loc, ob->loc); + copy_v3_v3(obtfm->dloc, ob->dloc); + copy_v3_v3(obtfm->orig, ob->orig); + copy_v3_v3(obtfm->size, ob->size); + copy_v3_v3(obtfm->dsize, ob->dsize); + copy_v3_v3(obtfm->rot, ob->rot); + copy_v3_v3(obtfm->drot, ob->drot); + copy_qt_qt(obtfm->quat, ob->quat); + copy_qt_qt(obtfm->dquat, ob->dquat); + copy_v3_v3(obtfm->rotAxis, ob->rotAxis); + copy_v3_v3(obtfm->drotAxis, ob->drotAxis); + obtfm->rotAngle= ob->rotAngle; + obtfm->drotAngle= ob->drotAngle; + copy_m4_m4(obtfm->obmat, ob->obmat); + copy_m4_m4(obtfm->parentinv, ob->parentinv); + copy_m4_m4(obtfm->constinv, ob->constinv); + copy_m4_m4(obtfm->imat, ob->imat); + + return (void *)obtfm; +} + +void object_tfm_restore(Object *ob, void *obtfm_pt) +{ + ObTfmBack *obtfm= (ObTfmBack *)obtfm_pt; + copy_v3_v3(ob->loc, obtfm->loc); + copy_v3_v3(ob->dloc, obtfm->dloc); + copy_v3_v3(ob->orig, obtfm->orig); + copy_v3_v3(ob->size, obtfm->size); + copy_v3_v3(ob->dsize, obtfm->dsize); + copy_v3_v3(ob->rot, obtfm->rot); + copy_v3_v3(ob->drot, obtfm->drot); + copy_qt_qt(ob->quat, obtfm->quat); + copy_qt_qt(ob->dquat, obtfm->dquat); + copy_v3_v3(ob->rotAxis, obtfm->rotAxis); + copy_v3_v3(ob->drotAxis, obtfm->drotAxis); + ob->rotAngle= obtfm->rotAngle; + ob->drotAngle= obtfm->drotAngle; + copy_m4_m4(ob->obmat, obtfm->obmat); + copy_m4_m4(ob->parentinv, obtfm->parentinv); + copy_m4_m4(ob->constinv, obtfm->constinv); + copy_m4_m4(ob->imat, obtfm->imat); +} /* proxy rule: lib_object->proxy_from == the one we borrow from, only set temporal and cleared here */ /* local_object->proxy == pointer to library object, saved in files and read */ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index a4784fc606d..9b1d48ac8c3 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1056,6 +1056,8 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, cpa->num=-1; } } + /* dmcache must be updated for parent particles if children from faces is used */ + psys_calc_dmcache(ob, finaldm, psys); return 0; } @@ -1820,8 +1822,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, project_v3_v3v3(dvec, r_vel, pa->state.ave); sub_v3_v3v3(mat[0], pa->state.ave, dvec); normalize_v3(mat[0]); - VECCOPY(mat[2], r_vel); - mul_v3_fl(mat[2], -1.0f); + negate_v3_v3(mat[2], r_vel); normalize_v3(mat[2]); cross_v3_v3v3(mat[1], mat[2], mat[0]); @@ -3313,6 +3314,8 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) if(pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN || cfra + psys->pointcache->step > pa->time)) reset_particle(sim, pa, dtime, cfra); + else if(part->phystype == PART_PHYS_NO) + reset_particle(sim, pa, dtime, cfra); if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ switch(part->phystype){ @@ -3805,7 +3808,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) pa->alive = PARS_ALIVE; } } - else if(cfra != startframe && (sim->ob->id.lib || (cache->flag & PTCACHE_BAKED))) { + else if(cfra != startframe && ( /*sim->ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED))) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */ psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra=cfra; psys->recalc = 0; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 6859aba57c9..b1319a81f5d 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -203,9 +203,9 @@ static int ptcache_write_particle(int index, void *psys_v, void **data) ParticleData *pa = psys->particles + index; BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; float times[3] = {pa->time, pa->dietime, pa->lifetime}; + int step = psys->pointcache->step; if(data[BPHYS_DATA_INDEX]) { - int step = psys->pointcache->step; /* No need to store unborn or died particles */ if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time) return 0; @@ -222,7 +222,8 @@ static int ptcache_write_particle(int index, void *psys_v, void **data) if(boid) PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); - return 1; + /* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */ + return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time); } void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time) { @@ -249,6 +250,10 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); + /* set frames cached before birth to birth time */ + if(cfra < pa->time) + pa->state.time = pa->time; + if(data[BPHYS_DATA_SIZE]) PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); @@ -1148,6 +1153,9 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) } else if (mode==PTCACHE_FILE_WRITE) { BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */ fp = fopen(filename, "wb"); + } else if (mode==PTCACHE_FILE_UPDATE) { + BLI_make_existing_file(filename); + fp = fopen(filename, "rb+"); } if (!fp) @@ -1253,6 +1261,18 @@ static void ptcache_file_init_pointers(PTCacheFile *pf) pf->cur[BPHYS_DATA_BOIDS] = data_types & (1<<BPHYS_DATA_BOIDS) ? &pf->data.boids : NULL; } +static void ptcache_file_seek_pointers(int index, PTCacheFile *pf) +{ + int i, size=0; + int data_types = pf->data_types; + + for(i=0; i<BPHYS_TOT_DATA; i++) + size += pf->data_types & (1<<i) ? ptcache_data_size[i] : 0; + + ptcache_file_init_pointers(pf); + /* size of default header + data up to index */ + fseek(pf->fp, 8 + 3*sizeof(int) + index * size, SEEK_SET); +} void BKE_ptcache_mem_init_pointers(PTCacheMem *pm) { int data_types = pm->data_types; @@ -1271,6 +1291,14 @@ void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm) pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i]; } } +void BKE_ptcache_mem_seek_pointers(int index, PTCacheMem *pm) +{ + int data_types = pm->data_types; + int i; + + for(i=0; i<BPHYS_TOT_DATA; i++) + pm->cur[i] = data_types & (1<<i) ? (char*)pm->data[i] + index * ptcache_data_size[i] : NULL; +} static void ptcache_alloc_data(PTCacheMem *pm) { int data_types = pm->data_types; @@ -1453,7 +1481,7 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) else if(pid->read_header(pf2)) { ptcache_file_init_pointers(pf2); totpoint2 = pf2->totpoint; - index2 = pf->data_types & BPHYS_DATA_INDEX ? &pf2->data.index : &i; + index2 = pf2->data_types & BPHYS_DATA_INDEX ? &pf2->data.index : &i; } } else { @@ -1615,7 +1643,7 @@ int BKE_ptcache_read_cache(PTCacheID *pid, float cfra, float frs_sec) int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) { PointCache *cache = pid->cache; - PTCacheFile *pf= NULL; + PTCacheFile *pf= NULL, *pf2= NULL; int i; int totpoint = pid->totpoint(pid->calldata); int add = 0, overwrite = 0; @@ -1625,7 +1653,7 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) return 0; if(cache->flag & PTCACHE_DISK_CACHE) { - int efra = cache->endframe; + int ofra, efra = cache->endframe; if(cfra==0) add = 1; @@ -1636,7 +1664,6 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) add = 1; } else { - int ofra; /* find last cached frame */ while(efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) efra--; @@ -1679,11 +1706,36 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) } else for(i=0; i<totpoint; i++) { - if(pid->write_elem && pid->write_elem(i, pid->calldata, pf->cur)) - if(!ptcache_file_write_data(pf)) { - ptcache_file_close(pf); - return 0; + if(pid->write_elem) { + int write = pid->write_elem(i, pid->calldata, pf->cur); + if(write) { + if(!ptcache_file_write_data(pf)) { + ptcache_file_close(pf); + if(pf2) ptcache_file_close(pf2); + return 0; + } + /* newly born particles have to be copied to previous cached frame */ + else if(overwrite && write == 2) { + if(!pf2) { + pf2 = ptcache_file_open(pid, PTCACHE_FILE_UPDATE, ofra); + if(!pf2) { + ptcache_file_close(pf); + return 0; + } + pf2->type = pid->type; + pf2->totpoint = totpoint; + pf2->data_types = pid->data_types; + } + ptcache_file_seek_pointers(i, pf2); + pid->write_elem(i, pid->calldata, pf2->cur); + if(!ptcache_file_write_data(pf2)) { + ptcache_file_close(pf); + ptcache_file_close(pf2); + return 0; + } + } } + } } } } @@ -1728,8 +1780,19 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) BKE_ptcache_mem_init_pointers(pm); for(i=0; i<totpoint; i++) { - if(pid->write_elem && pid->write_elem(i, pid->calldata, pm->cur)) - BKE_ptcache_mem_incr_pointers(pm); + if(pid->write_elem) { + int write = pid->write_elem(i, pid->calldata, pm->cur); + if(write) { + BKE_ptcache_mem_incr_pointers(pm); + + /* newly born particles have to be copied to previous cached frame */ + if(overwrite && write == 2) { + pm2 = cache->mem_cache.last; + BKE_ptcache_mem_seek_pointers(i, pm2); + pid->write_elem(i, pid->calldata, pm2->cur); + } + } + } } //ptcache_make_index_array(pm, pid->totpoint(pid->calldata)); @@ -1748,8 +1811,9 @@ int BKE_ptcache_write_cache(PTCacheID *pid, int cfra) cache->flag |= PTCACHE_FRAMES_SKIPPED; } - if(pf) - ptcache_file_close(pf); + if(pf) ptcache_file_close(pf); + + if(pf2) ptcache_file_close(pf2); BKE_ptcache_update_info(pid); diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 22dc5a15650..a16c1956cc4 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -170,7 +170,8 @@ static void unit_dual_convert(double value, bUnitCollection *usys, { bUnitDef *unit= unit_best_fit(value, usys, NULL, 1); - *value_a= floor(value/unit->scalar) * unit->scalar; + if(value < 0.0) *value_a= -floor(-value/unit->scalar) * unit->scalar; + else *value_a= floor( value/unit->scalar) * unit->scalar; *value_b= value - (*value_a); *unit_a= unit; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 917ecd044ea..6e94602c0c9 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -880,7 +880,7 @@ int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, } } - write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base)); + write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / rd->frs_sec_base)); return success; } diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h index 8544b451b65..c5158264e72 100644 --- a/source/blender/blenlib/BLI_dynstr.h +++ b/source/blender/blenlib/BLI_dynstr.h @@ -60,6 +60,15 @@ DynStr* BLI_dynstr_new (void); */ void BLI_dynstr_append (DynStr *ds, const char *cstr); +/** + * Append a length clamped c-string to a DynStr. + * + * @param ds The DynStr to append to. + * @param cstr The c-string to append. + * @param len The maximum length of the c-string to copy. + */ +void BLI_dynstr_nappend (DynStr *ds, const char *cstr, int len); + /** * Append a c-string to a DynStr, but with formatting like printf. * diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 9e494de5379..9b4084aa172 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -59,6 +59,7 @@ void BLI_make_existing_file(char *name); void BLI_split_dirfile(char *string, char *dir, char *file); void BLI_split_dirfile_basic(const char *string, char *dir, char *file); void BLI_join_dirfile(char *string, const char *dir, const char *file); +int BKE_rebase_path(char *abs, int abs_size, char *rel, int rel_size, const char *base_dir, const char *src_dir, const char *dest_dir); void BLI_getlastdir(const char* dir, char *last, int maxlen); int BLI_testextensie(const char *str, const char *ext); void BLI_uniquename(struct ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short len); diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index b534087f32c..fec5f1803eb 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -28,7 +28,7 @@ FILE(GLOB SRC intern/*.c) SET(INC . ../makesdna ../blenkernel ../../../intern/guardedalloc ../include - ../gpu + ../gpu ../../../intern/ghost ${FREETYPE_INCLUDE_DIRS} ${ZLIB_INC} ) diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript index df1a096cb99..090094a834d 100644 --- a/source/blender/blenlib/SConscript +++ b/source/blender/blenlib/SConscript @@ -4,7 +4,7 @@ Import ('env') sources = env.Glob('intern/*.c') cflags='' -incs = '. ../makesdna ../blenkernel #/intern/guardedalloc ../editors/include ../gpu' +incs = '. ../makesdna ../blenkernel #/intern/guardedalloc #/intern/ghost ../editors/include ../gpu' incs += ' ' + env['BF_FREETYPE_INC'] incs += ' ' + env['BF_ZLIB_INC'] defs = '' diff --git a/source/blender/blenlib/intern/BLI_bfile.c b/source/blender/blenlib/intern/BLI_bfile.c index 9540b16d2f4..3306283ad3f 100644 --- a/source/blender/blenlib/intern/BLI_bfile.c +++ b/source/blender/blenlib/intern/BLI_bfile.c @@ -46,6 +46,8 @@ #include "BLI_storage.h" #include "BLI_bfile.h" +#include "GHOST_C-api.h" + /* Internal bfile classification flags */ #define BCF_OPEN (0) #define BCF_FOPEN (1<<0) @@ -54,6 +56,11 @@ #define BCF_AT_END (1<<3) #define BCF_DISCARD (1<<4) +/* Standard files names */ +#define LAST_SESSION_FILE "last-session" +#define ENVIRONMENT_FILE "environment" + + /* Declaration of internal functions */ void chomp(char* line); void expand_envvars(char* src, char* dst); @@ -221,19 +228,6 @@ void BLI_bfile_set_error(BFILE *bfile, int 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]; @@ -249,10 +243,12 @@ void BLI_bfile_init_vars() { if(BLI_exist(temp)) { BLI_setenv_if_new("BLENDER_SHARE", dirname(bprogname)); } else { - BLI_setenv_if_new("BLENDER_SHARE", SHARED_DIRECTORY); + BLI_setenv_if_new("BLENDER_SHARE", (const char*)GHOST_getSystemDir()); } - expand_envvars(LAST_SESSION_FILE, file); + strcpy(file, (const char*)GHOST_getUserDir()); + BLI_add_slash(file); + strcat(file, LAST_SESSION_FILE); fp = fopen(file, "r"); /* 1st line, read previous version */ if (fp && (fscanf(fp, "%3c\n", temp) == 1)) { @@ -283,7 +279,9 @@ void BLI_bfile_init_vars() { } /* Load vars from user and system files */ - expand_envvars(ENVIRONMENT_FILE, file); + strcpy(file, (const char *)GHOST_getUserDir()); + BLI_add_slash(file); + strcat(file, ENVIRONMENT_FILE); init_vars_from_file(file); sprintf(temp, "/%d/environment", BLENDER_VERSION); BLI_make_file_string("/", file, getenv("BLENDER_SHARE"), temp); diff --git a/source/blender/blenlib/intern/BLI_dynstr.c b/source/blender/blenlib/intern/BLI_dynstr.c index 02c7ff2e9e5..4b7b61e64d9 100644 --- a/source/blender/blenlib/intern/BLI_dynstr.c +++ b/source/blender/blenlib/intern/BLI_dynstr.c @@ -83,6 +83,23 @@ void BLI_dynstr_append(DynStr *ds, const char *cstr) { ds->curlen+= cstrlen; } +void BLI_dynstr_nappend(DynStr *ds, const char *cstr, int len) { + DynStrElem *dse= malloc(sizeof(*dse)); + int cstrlen= BLI_strnlen(cstr, len); + + dse->str= malloc(cstrlen+1); + memcpy(dse->str, cstr, cstrlen); + dse->str[cstrlen] = '\0'; + dse->next= NULL; + + if (!ds->last) + ds->last= ds->elems= dse; + else + ds->last= ds->last->next= dse; + + ds->curlen+= cstrlen; +} + void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args) { char *message, fixedmessage[256]; diff --git a/source/blender/blenlib/intern/Makefile b/source/blender/blenlib/intern/Makefile index d8aed3ac0ed..7ef44aff881 100644 --- a/source/blender/blenlib/intern/Makefile +++ b/source/blender/blenlib/intern/Makefile @@ -52,6 +52,8 @@ CPPFLAGS += -I$(NAN_ZLIB)/include CPPFLAGS += -I../../gpu +CPPFLAGS += -I$(NAN_GHOST)/include + ifdef NAN_PTHREADS CPPFLAGS += -I$(NAN_PTHREADS)/include endif diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 8d5684a3ac8..a92f80e35c7 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -1333,8 +1333,14 @@ void mat4_to_dquat(DualQuat *dq,float basemat[][4], float mat[][4]) if((determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4) { /* extract R and S */ - mat4_to_quat(basequat,baseRS); - quat_to_mat4(baseR,basequat); + float tmp[4][4]; + + /* extra orthogonalize, to avoid flipping with stretched bones */ + copy_m4_m4(tmp, baseRS); + orthogonalize_m4(tmp, 1); + mat4_to_quat(basequat, tmp); + + quat_to_mat4(baseR, basequat); copy_v3_v3(baseR[3], baseRS[3]); invert_m4_m4(baseinv, basemat); diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 1bf321ec1bc..fe43960b770 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1320,6 +1320,106 @@ void BLI_join_dirfile(char *string, const char *dir, const char *file) } } + +/* + Produce image export path. + + Fails returning 0 if image filename is empty or if destination path + matches image path (i.e. both are the same file). + + Trailing slash in dest_dir is optional. + + Logic: + + - if an image is "below" current .blend file directory, rebuild the + same dir structure in dest_dir + + For example //textures/foo/bar.png becomes + [dest_dir]/textures/foo/bar.png. + + - if an image is not "below" current .blend file directory, + disregard it's path and copy it in the same directory where 3D file + goes. + + For example //../foo/bar.png becomes [dest_dir]/bar.png. + + This logic will help ensure that all image paths are relative and + that a user gets his images in one place. It'll also provide + consistent behaviour across exporters. + */ +int BKE_rebase_path(char *abs, int abs_size, char *rel, int rel_size, const char *base_dir, const char *src_dir, const char *dest_dir) +{ + char path[FILE_MAX]; + char dir[FILE_MAX]; + char base[FILE_MAX]; + char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */ + char dest_path[FILE_MAX]; + char rel_dir[FILE_MAX]; + int len; + + if (abs) + abs[0]= 0; + + if (rel) + rel[0]= 0; + + BLI_split_dirfile_basic(base_dir, blend_dir, NULL); + + if (src_dir[0]=='\0') + return 0; + + BLI_strncpy(path, src_dir, sizeof(path)); + + /* expand "//" in filename and get absolute path */ + BLI_convertstringcode(path, base_dir); + + /* get the directory part */ + BLI_split_dirfile_basic(path, dir, base); + + len= strlen(blend_dir); + + rel_dir[0] = 0; + + /* if image is "below" current .blend file directory */ + if (!strncmp(path, blend_dir, len)) { + + /* if image is _in_ current .blend file directory */ + if (!strcmp(dir, blend_dir)) { + BLI_join_dirfile(dest_path, dest_dir, base); + } + /* "below" */ + else { + /* rel = image_path_dir - blend_dir */ + BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir)); + + BLI_join_dirfile(dest_path, dest_dir, rel_dir); + BLI_join_dirfile(dest_path, dest_path, base); + } + + } + /* image is out of current directory */ + else { + BLI_join_dirfile(dest_path, dest_dir, base); + } + + if (abs) + BLI_strncpy(abs, dest_path, abs_size); + + if (rel) { + strncat(rel, rel_dir, rel_size); + strncat(rel, base, rel_size); + } + + /* return 2 if src=dest */ + if (!strcmp(path, dest_path)) { + // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path); + return 2; + } + + return 1; +} + + static int add_win32_extension(char *name) { int retval = 0; diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index bf2e1d28b3a..dd1d0a3bd4f 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -342,3 +342,10 @@ void BLI_timestr(double _time, char *str) str[11]=0; } + +/* determine the length of a fixed-size string */ +size_t BLI_strnlen(const char *str, size_t maxlen) +{ + const char *end = memchr(str, '\0', maxlen); + return end ? (size_t) (end - str) : maxlen; +} diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a34507d85f2..2c8a8869ddd 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -32,6 +32,7 @@ #include <limits.h> #include <stdio.h> // for printf fopen fwrite fclose sprintf FILE #include <stdlib.h> // for getenv atoi +#include <stddef.h> // for offsetof #include <fcntl.h> // for open #include <string.h> // for strrchr strncmp strstr #include <math.h> // for fabs @@ -10694,7 +10695,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) link_list(fd, &user->themes); link_list(fd, &user->keymaps); - link_list(fd, &user->extensions); + link_list(fd, &user->addons); for(keymap=user->keymaps.first; keymap; keymap=keymap->next) { keymap->modal_items= NULL; @@ -10887,20 +10888,9 @@ char *bhead_id_name(FileData *fd, BHead *bhead) static ID *is_yet_read(FileData *fd, Main *mainvar, BHead *bhead) { - ListBase *lb; - char *idname= bhead_id_name(fd, bhead); - - lb= wich_libbase(mainvar, GS(idname)); - - if(lb) { - ID *id= lb->first; - while(id) { - if( strcmp(id->name, idname)==0 ) - return id; - id= id->next; - } - } - return NULL; + const char *idname= bhead_id_name(fd, bhead); + /* wich_libbase can be NULL, intentionally not using idname+2 */ + return BLI_findstring(wich_libbase(mainvar, GS(idname)), idname, offsetof(ID, name)); } static void expand_doit(FileData *fd, Main *mainvar, void *old) diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 1cd68ec6f04..66815f5316f 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -542,7 +542,7 @@ static void write_userdef(WriteData *wd) bTheme *btheme; wmKeyMap *keymap; wmKeyMapItem *kmi; - bExtension *bext; + bAddon *bext; writestruct(wd, USER, "UserDef", 1, &U); @@ -560,8 +560,8 @@ static void write_userdef(WriteData *wd) } } - for(bext= U.extensions.first; bext; bext=bext->next) - writestruct(wd, DATA, "bExtension", 1, bext); + for(bext= U.addons.first; bext; bext=bext->next) + writestruct(wd, DATA, "bAddon", 1, bext); } static void write_boid_state(WriteData *wd, BoidState *state) diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 4b35499fb62..3e1898a64d9 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -1435,9 +1435,9 @@ public: BLI_split_dirfile_basic(mfilename, dir, NULL); - BKE_get_image_export_path(image, dir, abs, sizeof(abs), rel, sizeof(rel)); + BKE_rebase_path(abs, sizeof(abs), rel, sizeof(rel), G.sce, image->name, dir); - if (strlen(abs)) { + if (abs[0] != '\0') { // make absolute source path BLI_strncpy(src, image->name, sizeof(src)); diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index e6280a2556c..efdb9008014 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -436,6 +436,7 @@ static int ed_marker_move_init(bContext *C, wmOperator *op) initNumInput(&mm->num); mm->num.idx_max = 0; /* one axis */ mm->num.flag |= NUM_NO_FRACTION; + mm->num.increment = 1.0f; for (a=0, marker= markers->first; marker; marker= marker->next) { if (marker->flag & SELECT) { @@ -617,7 +618,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) float vec[3]; char str_tx[256]; - if (handleNumInput(&mm->num, evt, 1.0)) + if (handleNumInput(&mm->num, evt)) { applyNumInput(&mm->num, vec); outputNumInput(&mm->num, str_tx); diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index f1d84fb1066..63323a8519d 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -355,7 +355,7 @@ static int add_keyingset_button_exec (bContext *C, wmOperator *op) } /* add path to this setting */ - BKE_keyingset_add_destination(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME); + BKE_keyingset_add_path(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME); ks->active_path= BLI_countlist(&ks->paths); success= 1; @@ -426,7 +426,7 @@ static int remove_keyingset_button_exec (bContext *C, wmOperator *op) KS_Path *ksp; /* try to find a path matching this description */ - ksp= BKE_keyingset_find_destination(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME); + ksp= BKE_keyingset_find_path(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME); if (ksp) { /* just free it... */ @@ -1162,31 +1162,13 @@ static int keyingset_relative_get_templates (KeyingSet *ks) return templates; } -/* Check if context data is suitable for the given absolute Keying Set */ +/* Check if context data is suitable for the given Keying Set */ short keyingset_context_ok_poll (bContext *C, KeyingSet *ks) { - ScrArea *sa= CTX_wm_area(C); - - /* data retrieved from context depends on active editor */ - if (sa == NULL) return 0; - - switch (sa->spacetype) { - case SPACE_VIEW3D: - { - Object *obact= CTX_data_active_object(C); - - /* if in posemode, check if 'pose-channels' requested for in KeyingSet */ - if ((obact && obact->pose) && (obact->mode & OB_MODE_POSE)) { - /* check for posechannels */ - - } - else { - /* check for selected object */ - - } - } - break; - } + // TODO: + // For 'relative' keyingsets (i.e. py-keyingsets), add a call here + // which basically gets a listing of all the paths to be used for this + // set. return 1; diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c index a9be4b346f0..b3960c3cfd5 100644 --- a/source/blender/editors/armature/editarmature_retarget.c +++ b/source/blender/editors/armature/editarmature_retarget.c @@ -186,12 +186,12 @@ float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float qrot[4], if (dot_v3v3(new_up_axis, x_axis) < 0) { - mul_v3_fl(x_axis, -1); + negate_v3(x_axis); } if (dot_v3v3(new_up_axis, z_axis) < 0) { - mul_v3_fl(z_axis, -1); + negate_v3(z_axis); } if (angle_normalized_v3v3(x_axis, new_up_axis) < angle_normalized_v3v3(z_axis, new_up_axis)) diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index c49ad2a768a..0170241c6c2 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -52,6 +52,7 @@ #include "DNA_userdef_types.h" #include "BKE_anim.h" +#include "BKE_idprop.h" #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_armature.h" @@ -840,6 +841,15 @@ static bPose *g_posebuf = NULL; void free_posebuf(void) { if (g_posebuf) { + bPoseChannel *pchan; + + for (pchan= g_posebuf->chanbase.first; pchan; pchan= pchan->next) { + if(pchan->prop) { + IDP_FreeProperty(pchan->prop); + MEM_freeN(pchan->prop); + } + } + /* was copied without constraints */ BLI_freelistN(&g_posebuf->chanbase); MEM_freeN(g_posebuf); @@ -891,7 +901,8 @@ void POSE_OT_copy (wmOperatorType *ot) /* Pointers to the builtin KeyingSets that we want to use */ static KeyingSet *posePaste_ks_locrotscale = NULL; /* the only keyingset we'll need */ -/* ---- */ +/* transform.h */ +extern void autokeyframe_pose_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode, short targetless_ik); static int pose_paste_exec (bContext *C, wmOperator *op) { @@ -1002,33 +1013,55 @@ static int pose_paste_exec (bContext *C, wmOperator *op) } } - if (autokeyframe_cfra_can_key(scene, &ob->id)) { - /* Set keys on pose - * - KeyingSet to use depends on rotation mode - * (but that's handled by the templates code) - */ - // TODO: for getting the KeyingSet used, we should really check which channels were affected - if (posePaste_ks_locrotscale == NULL) - posePaste_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale"); - - /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */ - cks.pchan= pchan; - - modify_keyframes(scene, &dsources, NULL, posePaste_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA); - - /* clear any unkeyed tags */ - if (chan->bone) - chan->bone->flag &= ~BONE_UNKEYED; + /* ID property */ + if(pchan->prop) { + IDP_FreeProperty(pchan->prop); + MEM_freeN(pchan->prop); + pchan->prop= NULL; } - else { - /* add unkeyed tags */ - if (chan->bone) - chan->bone->flag |= BONE_UNKEYED; + + if(chan->prop) { + pchan->prop= IDP_CopyProperty(chan->prop); + } + + /* auto key, TODO, fix up this INSERTAVAIL vs all other cases */ + if (IS_AUTOKEY_FLAG(INSERTAVAIL) == 0) { /* deal with this case later */ + if (autokeyframe_cfra_can_key(scene, &ob->id)) { + + /* Set keys on pose + * - KeyingSet to use depends on rotation mode + * (but that's handled by the templates code) + */ + // TODO: for getting the KeyingSet used, we should really check which channels were affected + if (posePaste_ks_locrotscale == NULL) + posePaste_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale"); + + /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */ + cks.pchan= pchan; + + modify_keyframes(scene, &dsources, NULL, posePaste_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA); + + /* clear any unkeyed tags */ + if (chan->bone) + chan->bone->flag &= ~BONE_UNKEYED; + } + else { + /* add unkeyed tags */ + if (chan->bone) + chan->bone->flag |= BONE_UNKEYED; + } } } } } + if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { + View3D *v3d= CTX_wm_view3d(C); + autokeyframe_pose_cb_func(C, scene, v3d, ob, TFM_TRANSLATION, 0); + autokeyframe_pose_cb_func(C, scene, v3d, ob, TFM_ROTATION, 0); + autokeyframe_pose_cb_func(C, scene, v3d, ob, TFM_TIME_SCALE, 0); + } + /* Update event for pose and deformation children */ DAG_id_flush_update(&ob->id, OB_RECALC_DATA); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 886da0820a2..cc875e5156f 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -178,6 +178,7 @@ 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, int extend); void selectall_tface(struct Object *ob, int action); void select_linked_tfaces(struct bContext *C, struct Object *ob, short mval[2], int mode); +int minmax_tface(struct Object *ob, float *min, float *max); /* object_vgroup.c */ diff --git a/source/blender/editors/include/ED_numinput.h b/source/blender/editors/include/ED_numinput.h index 381131c8b2d..ca5dc4797de 100644 --- a/source/blender/editors/include/ED_numinput.h +++ b/source/blender/editors/include/ED_numinput.h @@ -33,6 +33,7 @@ typedef struct NumInput { char inv[3]; /* If the value is inverted or not */ float val[3]; /* Direct value of the input */ int ctrl[3]; /* Control to indicate what to do with the numbers that are typed */ + float increment; } NumInput ; /* NUMINPUT FLAGS */ @@ -48,7 +49,7 @@ void initNumInput(NumInput *n); void outputNumInput(NumInput *n, char *str); short hasNumInput(NumInput *n); void applyNumInput(NumInput *n, float *vec); -char handleNumInput(NumInput *n, struct wmEvent *event, float increment); +char handleNumInput(NumInput *n, struct wmEvent *event); #define NUM_MODAL_INCREMENT_UP 18 #define NUM_MODAL_INCREMENT_DOWN 19 diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h index 7f2effdd975..3529eddd6d9 100644 --- a/source/blender/editors/include/ED_space_api.h +++ b/source/blender/editors/include/ED_space_api.h @@ -69,6 +69,7 @@ void *ED_region_draw_cb_activate(struct ARegionType *, void *custumdata, int type); void ED_region_draw_cb_draw(const struct bContext *, struct ARegion *, int); void ED_region_draw_cb_exit(struct ARegionType *, void *); +void *ED_region_draw_cb_customdata(void *handle); #endif /* ED_SPACE_API_H */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 9624adf4879..0dd8e3d412d 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4015,7 +4015,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) if(event->alt) ui_but_anim_remove_keyingset(C); else - ui_but_anim_remove_keyingset(C); + ui_but_anim_add_keyingset(C); ED_region_tag_redraw(CTX_wm_region(C)); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 4c818f9d0ac..e2804efe040 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -157,16 +157,19 @@ static void id_search_cb(const bContext *C, void *arg_template, char *str, uiSea { TemplateID *template= (TemplateID*)arg_template; ListBase *lb= template->idlb; - ID *id; + ID *id, *id_from= template->ptr.id.data; int iconid; + int flag= RNA_property_flag(template->prop); /* ID listbase */ for(id= lb->first; id; id= id->next) { - if(BLI_strcasestr(id->name+2, str)) { - iconid= ui_id_icon_get((bContext*)C, id, 0); + if(!((flag & PROP_ID_SELF_CHECK) && id == id_from)) { + if(BLI_strcasestr(id->name+2, str)) { + iconid= ui_id_icon_get((bContext*)C, id, 0); - if(!uiSearchItemAdd(items, id->name+2, id, iconid)) - break; + if(!uiSearchItemAdd(items, id->name+2, id, iconid)) + break; + } } } } @@ -281,6 +284,10 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) memset(&idptr, 0, sizeof(idptr)); RNA_property_pointer_set(&template->ptr, template->prop, idptr); RNA_property_update(C, &template->ptr, template->prop); + + if(id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */ + id->us= 0; + break; case UI_ID_FAKE_USER: if(id) { @@ -447,8 +454,11 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); } else { - but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Unlink datablock, Shift + Click to force removal on save"); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE)); + + if(RNA_property_flag(template->prop) & PROP_NEVER_NULL) + uiButSetFlag(but, UI_BUT_DISABLED); } if((idfrom && idfrom->lib)) diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 19eb782884d..e83be1f4f1d 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -450,52 +450,28 @@ void selectswap_tface(Scene *scene) // XXX notifier! object_tface_flags_changed(OBACT, 0); } -int minmax_tface(Scene *scene, float *min, float *max) +int minmax_tface(Object *ob, float *min, float *max) { - Object *ob; - Mesh *me; + Mesh *me= get_mesh(ob); MFace *mf; - MTFace *tf; MVert *mv; int a, ok=0; - float vec[3], bmat[3][3]; - - ob = OBACT; - if (ob==0) return ok; - me= get_mesh(ob); - if(me==0 || me->mtface==0) return ok; - - copy_m3_m4(bmat, ob->obmat); + float vec[3]; + + if(me==NULL) + return ok; mv= me->mvert; mf= me->mface; - tf= me->mtface; - for (a=me->totface; a>0; a--, mf++, tf++) { - if (mf->flag & ME_HIDE || !(mf->flag & ME_FACE_SEL)) - continue; - - VECCOPY(vec, (mv+mf->v1)->co); - mul_m3_v3(bmat, vec); - add_v3_v3v3(vec, vec, ob->obmat[3]); - DO_MINMAX(vec, min, max); - - VECCOPY(vec, (mv+mf->v2)->co); - mul_m3_v3(bmat, vec); - add_v3_v3v3(vec, vec, ob->obmat[3]); - DO_MINMAX(vec, min, max); - - VECCOPY(vec, (mv+mf->v3)->co); - mul_m3_v3(bmat, vec); - add_v3_v3v3(vec, vec, ob->obmat[3]); - DO_MINMAX(vec, min, max); - - if (mf->v4) { - VECCOPY(vec, (mv+mf->v4)->co); - mul_m3_v3(bmat, vec); - add_v3_v3v3(vec, vec, ob->obmat[3]); - DO_MINMAX(vec, min, max); + for (a=me->totface; a>0; a--, mf++) { + if ((mf->flag & ME_HIDE || !(mf->flag & ME_FACE_SEL)) == 0) { + int i= mf->v4 ? 3:2; + do { + mul_v3_m4v3(vec, ob->obmat, (mv + (*(&mf->v1 + i)))->co); + DO_MINMAX(vec, min, max); + } while (i--); + ok= 1; } - ok= 1; } return ok; } diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index d7ffa1d983b..ab50bd4c37c 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -289,6 +289,18 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OBJECT_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "OBJECT_OT_select_mirror", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + kmi= WM_keymap_add_item(keymap, "OBJECT_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, 0, 0); + RNA_enum_set_identifier(kmi->ptr, "direction", "PARENT"); + kmi= WM_keymap_add_item(keymap, "OBJECT_OT_select_hierarchy", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0); + RNA_enum_set_identifier(kmi->ptr, "direction", "PARENT"); + RNA_boolean_set(kmi->ptr, "extend", 1); + + kmi= WM_keymap_add_item(keymap, "OBJECT_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, 0, 0); + RNA_enum_set_identifier(kmi->ptr, "direction", "CHILD"); + kmi= WM_keymap_add_item(keymap, "OBJECT_OT_select_hierarchy", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0); + RNA_enum_set_identifier(kmi->ptr, "direction", "CHILD"); + RNA_boolean_set(kmi->ptr, "extend", 1); + WM_keymap_verify_item(keymap, "OBJECT_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_verify_item(keymap, "OBJECT_OT_parent_no_inverse_set", PKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); WM_keymap_verify_item(keymap, "OBJECT_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/render/Makefile b/source/blender/editors/render/Makefile index ed25f0be02a..85b70172e0a 100644 --- a/source/blender/editors/render/Makefile +++ b/source/blender/editors/render/Makefile @@ -54,3 +54,9 @@ CPPFLAGS += -I../../render/extern/include # own include CPPFLAGS += -I../include + +ifeq ($(OS), darwin) + ifeq ($(WITH_BF_OPENMP), true) + CPPFLAGS += -DPARALLEL=1 + endif +endif diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript index cb901be2494..5526194eab4 100644 --- a/source/blender/editors/render/SConscript +++ b/source/blender/editors/render/SConscript @@ -24,4 +24,8 @@ if env['WITH_BF_QUICKTIME']: if env['USE_QTKIT']: env.Append(CFLAGS=['-DUSE_QTKIT']) +if env['OURPLATFORM'] == 'darwin': + if env['WITH_BF_OPENMP']: + env.Append(CFLAGS=['-DPARALLEL=1']) + env.BlenderLib ( 'bf_editors_render', sources, Split(incs), [], libtype=['core'], priority=[45]) diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 1563c5a8e1d..aca13fbd66d 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -100,6 +100,13 @@ #define PR_XMAX 200 #define PR_YMAX 195 +#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) +/* ************** libgomp (Apple gcc 4.2.1) TLS bug workaround *************** */ +#include <pthread.h> +extern pthread_key_t gomp_tls_key; +static void *thread_tls_data; +#endif + /* XXX */ static int qtest() {return 0;} /* XXX */ @@ -1098,6 +1105,11 @@ static void common_preview_startjob(void *customdata, short *stop, short *do_upd { ShaderPreview *sp= customdata; +#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) + // Workaround for Apple gcc 4.2.1 omp vs background thread bug + pthread_setspecific (gomp_tls_key, thread_tls_data); +#endif + if(sp->pr_method == PR_ICON_RENDER) icon_preview_startjob(customdata, stop, do_update); else @@ -1127,7 +1139,12 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r WM_jobs_customdata(steve, sp, shader_preview_free); WM_jobs_timer(steve, 0.1, NC_MATERIAL, NC_MATERIAL); WM_jobs_callbacks(steve, common_preview_startjob, NULL, NULL); - + +#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) + // Workaround for Apple gcc 4.2.1 omp vs background thread bug + thread_tls_data = pthread_getspecific(gomp_tls_key); +#endif + WM_jobs_start(CTX_wm_manager(C), steve); } @@ -1154,6 +1171,11 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M WM_jobs_timer(steve, 0.1, NC_MATERIAL, NC_MATERIAL); WM_jobs_callbacks(steve, common_preview_startjob, NULL, shader_preview_updatejob); +#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) + // Workaround for Apple gcc 4.2.1 omp vs background thread bug + thread_tls_data = pthread_getspecific(gomp_tls_key); +#endif + WM_jobs_start(CTX_wm_manager(C), steve); } diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 9bfe3213587..a3fe29536a3 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -204,6 +204,11 @@ void ED_region_draw_cb_exit(ARegionType *art, void *handle) } } +void *ED_region_draw_cb_customdata(void *handle) +{ + return ((RegionDrawCB *)handle)->customdata; +} + void ED_region_draw_cb_draw(const bContext *C, ARegion *ar, int type) { RegionDrawCB *rdc; diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 3ebb4c61f7b..7b59f6aafa9 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -38,6 +38,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "ED_screen.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -75,6 +77,7 @@ void BUTTONS_OT_toolbox(wmOperatorType *ot) /* api callbacks */ ot->invoke= toolbox_invoke; + ot->poll= ED_operator_buttons_active; } /********************** filebrowse operator *********************/ diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index 16f5f47075e..708089f8f4c 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -140,9 +140,23 @@ typedef struct ConsoleDrawContext { static void console_draw_sel(int sel[2], int xy[2], int str_len, int cwidth, int console_width, int lheight) { - if(sel[0] < str_len && sel[1] > 0) { + if(sel[0] <= str_len && sel[1] >= 0) { int sta = MAX2(sel[0], 0); int end = MIN2(sel[1], str_len); + + /* highly confusing but draws correctly */ + if(sel[0] < 0 || sel[1] > str_len) { + if(sel[0] > 0) { + end= sta; + sta= 0; + } + if (sel[1] <= str_len) { + sta= end; + end= str_len; + } + } + /* end confusement */ + { glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(stipple_halftone); @@ -157,8 +171,8 @@ static void console_draw_sel(int sel[2], int xy[2], int str_len, int cwidth, int } } - sel[0] -= str_len; - sel[1] -= str_len; + sel[0] -= str_len + 1; + sel[1] -= str_len + 1; } @@ -179,7 +193,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, char *str, int str_len, int ofs = (int)floor(((float)cdc->mval[0] / (float)cdc->cwidth)); *cdc->pos_pick += MIN2(ofs, str_len); } else - *cdc->pos_pick += str_len; + *cdc->pos_pick += str_len + 1; } } @@ -190,6 +204,13 @@ static int console_draw_string(ConsoleDrawContext *cdc, char *str, int str_len, else if (y_next-cdc->lheight < cdc->ymin) { /* have not reached the drawable area so don't break */ cdc->xy[1]= y_next; + + /* adjust selection even if not drawing */ + if(cdc->sel[0] != cdc->sel[1]) { + cdc->sel[0] -= str_len + 1; + cdc->sel[1] -= str_len + 1; + } + return 1; } @@ -314,6 +335,7 @@ static int console_text_main__internal(struct SpaceConsole *sc, struct ARegion * if(sc->sel_start != sc->sel_end) { sel[0]= sc->sel_start; sel[1]= sc->sel_end; + // printf("%d %d\n", sel[0], sel[1]); } /* text */ diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 44c0b2159d7..763436dd05f 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -681,23 +681,71 @@ static int copy_exec(bContext *C, wmOperator *op) char *buf_str; ConsoleLine *cl; - + int sel[2]; + int offset= 0; + +#if 0 + /* copy whole file */ for(cl= sc->scrollback.first; cl; cl= cl->next) { BLI_dynstr_append(buf_dyn, cl->line); BLI_dynstr_append(buf_dyn, "\n"); } +#endif + + if(sc->sel_start == sc->sel_end) + return OPERATOR_CANCELLED; + + + for(cl= sc->scrollback.first; cl; cl= cl->next) { + offset += cl->len + 1; + } + + if(offset==0) + return OPERATOR_CANCELLED; + + + offset -= 1; + sel[0]= offset - sc->sel_end; + sel[1]= offset - sc->sel_start; + + for(cl= sc->scrollback.first; cl; cl= cl->next) { + + int sta= MAX2(0, sel[0]); + int end= MIN2(cl->len, sel[1]); + + if(sel[0] <= cl->len && sel[1] >= 0) { + int str_len= cl->len; + + /* highly confusing but draws correctly */ + if(sel[0] < 0 || sel[1] > str_len) { + if(sel[0] > 0) { + end= sta; + sta= 0; + } + if (sel[1] <= str_len) { + sta= end; + end= str_len; + } + } + /* end confusement */ + + SWAP(int, sta, end); + end= cl->len - end; + sta= cl->len - sta; + + if(BLI_dynstr_get_len(buf_dyn)) + BLI_dynstr_append(buf_dyn, "\n"); + + BLI_dynstr_nappend(buf_dyn, cl->line + sta, end - sta); + } + + sel[0] -= cl->len + 1; + sel[1] -= cl->len + 1; + } buf_str= BLI_dynstr_get_cstring(buf_dyn); buf_len= BLI_dynstr_get_len(buf_dyn); BLI_dynstr_free(buf_dyn); - - /* hack for selection */ -#if 0 - if(sc->sel_start != sc->sel_end) { - buf_str[buf_len - sc->sel_start]= '\0'; - WM_clipboard_text_set(buf_str+(buf_len - sc->sel_end), 0); - } -#endif WM_clipboard_text_set(buf_str, 0); MEM_freeN(buf_str); @@ -723,11 +771,28 @@ static int paste_exec(bContext *C, wmOperator *op) ConsoleLine *ci= console_history_verify(C); char *buf_str= WM_clipboard_text_get(0); + char *buf_step, *buf_next; if(buf_str==NULL) return OPERATOR_CANCELLED; - console_line_insert(ci, buf_str); /* TODO - Multiline copy?? */ + buf_next= buf_str; + buf_step= buf_str; + + while((buf_next=buf_step) && buf_next[0] != '\0') { + buf_step= strchr(buf_next, '\n'); + if(buf_step) { + *buf_step= '\0'; + buf_step++; + } + + if(buf_next != buf_str) { + WM_operator_name_call(C, "CONSOLE_OT_execute", WM_OP_EXEC_DEFAULT, NULL); + ci= console_history_verify(C); + } + + console_line_insert(ci, buf_next); + } MEM_freeN(buf_str); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 1cc8fc37e77..543fa1dfed7 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -246,27 +246,6 @@ void NLA_OT_tweakmode_exit (wmOperatorType *ot) /* ******************** Add Action-Clip Operator ***************************** */ /* Add a new Action-Clip strip to the active track (or the active block if no space in the track) */ -/* pop up menu allowing user to choose the action to use */ -// TODO: at some point, we may have to migrate to a search menu to manage the case where there are many actions -static int nlaedit_add_actionclip_invoke (bContext *C, wmOperator *op, wmEvent *evt) -{ - Main *m= CTX_data_main(C); - bAction *act; - uiPopupMenu *pup; - uiLayout *layout; - - pup= uiPupMenuBegin(C, "Add Action Clip", 0); - layout= uiPupMenuLayout(pup); - - /* loop through Actions in Main database, adding as items in the menu */ - for (act= m->action.first; act; act= act->id.next) - uiItemStringO(layout, act->id.name+2, 0, "NLA_OT_actionclip_add", "action", act->id.name+2); - uiItemS(layout); - - uiPupMenuEnd(C, pup); - - return OPERATOR_CANCELLED; -} /* add the specified action as new strip */ static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op) @@ -277,9 +256,9 @@ static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op) ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter, items; - - bAction *act = NULL; - char actname[20]; + + bAction *act; + float cfra; /* get editor data */ @@ -290,8 +269,7 @@ static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op) cfra= (float)CFRA; /* get action to use */ - RNA_string_get(op->ptr, "action", actname); - act= (bAction *)find_id("AC", actname); + act= BLI_findlink(&CTX_data_main(C)->action, RNA_enum_get(op->ptr, "type")); if (act == NULL) { BKE_report(op->reports, RPT_ERROR, "No valid Action to add."); @@ -350,13 +328,15 @@ static int nlaedit_add_actionclip_exec (bContext *C, wmOperator *op) void NLA_OT_actionclip_add (wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name= "Add Action Strip"; ot->idname= "NLA_OT_actionclip_add"; ot->description= "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track"; /* api callbacks */ - ot->invoke= nlaedit_add_actionclip_invoke; + ot->invoke= WM_enum_search_invoke; ot->exec= nlaedit_add_actionclip_exec; ot->poll= nlaop_poll_tweakmode_off; @@ -365,7 +345,9 @@ void NLA_OT_actionclip_add (wmOperatorType *ot) /* props */ // TODO: this would be nicer as an ID-pointer... - ot->prop = RNA_def_string(ot->srna, "action", "", 19, "Action", "Name of Action to add as a new Action-Clip Strip."); + prop= RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Type", ""); + RNA_def_enum_funcs(prop, RNA_action_itemf); + ot->prop= prop; } /* ******************** Add Transition Operator ***************************** */ diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index 09b5e3a80e2..4618f7a8873 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -3977,14 +3977,14 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa { /* add a new path with the information obtained (only if valid) */ // TODO: what do we do with group name? for now, we don't supply one, and just let this use the KeyingSet name - BKE_keyingset_add_destination(ks, id, NULL, path, array_index, flag, groupmode); + BKE_keyingset_add_path(ks, id, NULL, path, array_index, flag, groupmode); ks->active_path= BLI_countlist(&ks->paths); } break; case KEYINGSET_EDITMODE_REMOVE: { /* find the relevant path, then remove it from the KeyingSet */ - KS_Path *ksp= BKE_keyingset_find_destination(ks, id, NULL, path, array_index, groupmode); + KS_Path *ksp= BKE_keyingset_find_path(ks, id, NULL, path, array_index, groupmode); if (ksp) { /* free path's data */ diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 1c04667e501..fc67881367f 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -751,6 +751,10 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) if(wmn->action == NA_RENAME) ED_region_tag_redraw(ar); break; + case NC_SCREEN: + if(wmn->data == ND_GPENCIL) + ED_region_tag_redraw(ar); + break; } } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 81a508de139..51e8f9e43b2 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -76,6 +76,7 @@ #include "ED_screen.h" #include "ED_transform.h" #include "ED_types.h" +#include "ED_mesh.h" #include "UI_interface.h" #include "UI_resources.h" @@ -109,9 +110,7 @@ static void view3d_boxview_clip(ScrArea *sa) if(ar->winx>ar->winy) y1= ar->winy*rv3d->dist/ar->winx; else y1= rv3d->dist; - - ofs[0]= rv3d->ofs[0]; - ofs[1]= rv3d->ofs[1]; + copy_v2_v2(ofs, rv3d->ofs); } else if(ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) { ofs[2]= rv3d->ofs[2]; @@ -335,8 +334,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) VECCOPY(vod->ofs, rv3d->ofs); /* If there's no selection, lastofs is unmodified and last value since static */ calculateTransformCenter(C, V3D_CENTROID, lastofs); - VECCOPY(vod->dyn_ofs, lastofs); - mul_v3_fl(vod->dyn_ofs, -1.0f); + negate_v3_v3(vod->dyn_ofs, lastofs); } else if (U.uiflag & USER_ORBIT_ZBUF) { @@ -371,8 +369,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin); vod->dist0 = rv3d->dist = len_v3v3(my_pivot, dvec); - negate_v3(dvec); - VECCOPY(rv3d->ofs, dvec); + negate_v3_v3(rv3d->ofs, dvec); } negate_v3(vod->dyn_ofs); VECCOPY(vod->ofs, rv3d->ofs); @@ -547,11 +544,8 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) * dragged. */ phi = si * M_PI / 2.0; - si= sin(phi); q1[0]= cos(phi); - q1[1]*= si; - q1[2]*= si; - q1[3]*= si; + mul_v3_fl(q1+1, sin(phi)); mul_qt_qtqt(rv3d->viewquat, q1, vod->oldquat); if (vod->use_dyn_ofs) { @@ -569,7 +563,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) } else { /* New turntable view code by John Aughey */ - float si, phi, q1[4]; + float phi, q1[4]; float m[3][3]; float m_inv[3][3]; float xvec[3] = {1,0,0}; @@ -589,11 +583,8 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) /* Perform the up/down rotation */ phi = sensitivity * -(y - vod->oldy); - si = sin(phi); q1[0] = cos(phi); - q1[1] = si * xvec[0]; - q1[2] = si * xvec[1]; - q1[3] = si * xvec[2]; + mul_v3_v3fl(q1+1, xvec, sin(phi)); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); if (vod->use_dyn_ofs) { @@ -634,12 +625,10 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) if ((dot_v3v3(snapmat[0], viewmat[0]) > thres) && (dot_v3v3(snapmat[1], viewmat[1]) > thres) && - (dot_v3v3(snapmat[2], viewmat[2]) > thres)){ - - QUATCOPY(rv3d->viewquat, snapquats[i]); - - rv3d->view = view; - + (dot_v3v3(snapmat[2], viewmat[2]) > thres) + ) { + copy_qt_qt(rv3d->viewquat, snapquats[i]); + rv3d->view= view; break; } } @@ -968,18 +957,15 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) vb[0] = ar->winx; vb[1] = ar->winy; - tpos[0] = -rv3d->ofs[0]; - tpos[1] = -rv3d->ofs[1]; - tpos[2] = -rv3d->ofs[2]; + negate_v3_v3(tpos, rv3d->ofs); /* Project cursor position into 3D space */ initgrabz(rv3d, tpos[0], tpos[1], tpos[2]); window_to_3d_delta(ar, dvec, mouseloc[0]-vb[0]/2, mouseloc[1]-vb[1]/2); /* Calculate view target position for dolly */ - tvec[0] = -(tpos[0] + dvec[0]); - tvec[1] = -(tpos[1] + dvec[1]); - tvec[2] = -(tpos[2] + dvec[2]); + add_v3_v3v3(tvec, tpos, dvec); + negate_v3(tvec); /* Offset to target position and dolly */ new_dist = rv3d->dist * dfac; @@ -988,11 +974,7 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) rv3d->dist = new_dist; /* Calculate final offset */ - dvec[0] = tvec[0] + dvec[0] * dfac; - dvec[1] = tvec[1] + dvec[1] * dfac; - dvec[2] = tvec[2] + dvec[2] * dfac; - - VECCOPY(rv3d->ofs, dvec); + madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac); } else { rv3d->dist *= dfac; } @@ -1384,7 +1366,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) /* like a localview wi } } else if (paint_facesel_test(ob)) { -// XXX ok= minmax_tface(min, max); + ok= minmax_tface(ob, min, max); } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { ok= PE_minmax(scene, min, max); @@ -1393,9 +1375,10 @@ static int viewselected_exec(bContext *C, wmOperator *op) /* like a localview wi Base *base= FIRSTBASE; while(base) { if(TESTBASE(v3d, base)) { - minmax_object(base->object, min, max); + /* account for duplis */ - minmax_object_duplis(scene, base->object, min, max); + if (minmax_object_duplis(scene, base->object, min, max)==0) + minmax_object(base->object, min, max); /* use if duplis not found */ ok= 1; } @@ -1405,9 +1388,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) /* like a localview wi if(ok==0) return OPERATOR_FINISHED; - afm[0]= (max[0]-min[0]); - afm[1]= (max[1]-min[1]); - afm[2]= (max[2]-min[2]); + sub_v3_v3v3(afm, max, min); size= MAX3(afm[0], afm[1], afm[2]); if(rv3d->persp==RV3D_ORTHO) { @@ -1425,9 +1406,8 @@ static int viewselected_exec(bContext *C, wmOperator *op) /* like a localview wi } } - new_ofs[0]= -(min[0]+max[0])/2.0f; - new_ofs[1]= -(min[1]+max[1])/2.0f; - new_ofs[2]= -(min[2]+max[2])/2.0f; + add_v3_v3v3(new_ofs, min, max); + mul_v3_fl(new_ofs, -0.5f); new_dist = size; @@ -1482,13 +1462,8 @@ static int viewcenter_cursor_exec(bContext *C, wmOperator *op) } else { /* non camera center */ - float *curs= give_cursor(scene, v3d); float new_ofs[3]; - - new_ofs[0]= -curs[0]; - new_ofs[1]= -curs[1]; - new_ofs[2]= -curs[2]; - + negate_v3_v3(new_ofs, give_cursor(scene, v3d)); smooth_view(C, NULL, NULL, new_ofs, NULL, NULL, NULL); } @@ -1706,9 +1681,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) new_ofs[2] = -p[2]; } else { /* We cant use the depth, fallback to the old way that dosnt set the center depth */ - new_ofs[0] = rv3d->ofs[0]; - new_ofs[1] = rv3d->ofs[1]; - new_ofs[2] = rv3d->ofs[2]; + copy_v3_v3(new_ofs, rv3d->ofs); initgrabz(rv3d, -new_ofs[0], -new_ofs[1], -new_ofs[2]); @@ -1982,7 +1955,7 @@ static EnumPropertyItem prop_view_orbit_items[] = { static int vieworbit_exec(bContext *C, wmOperator *op) { RegionView3D *rv3d= CTX_wm_region_view3d(C); - float phi, si, q1[4], new_quat[4]; + float phi, q1[4], new_quat[4]; int orbitdir; orbitdir = RNA_enum_get(op->ptr, "type"); @@ -1991,6 +1964,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op) if(rv3d->persp != RV3D_CAMOB) { if(orbitdir == V3D_VIEW_STEPLEFT || orbitdir == V3D_VIEW_STEPRIGHT) { + float si; /* z-axis */ phi= (float)(M_PI/360.0)*U.pad_rot_angle; if(orbitdir == V3D_VIEW_STEPRIGHT) phi= -phi; @@ -2008,11 +1982,8 @@ static int vieworbit_exec(bContext *C, wmOperator *op) normalize_v3(q1+1); phi= (float)(M_PI/360.0)*U.pad_rot_angle; if(orbitdir == V3D_VIEW_STEPDOWN) phi= -phi; - si= (float)sin(phi); q1[0]= (float)cos(phi); - q1[1]*= si; - q1[2]*= si; - q1[3]*= si; + mul_v3_fl(q1+1, sin(phi)); mul_qt_qtqt(new_quat, rv3d->viewquat, q1); rv3d->view= 0; } @@ -2815,7 +2786,7 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode) float xvec[3] = {1,0,0}; float yvec[3] = {0,-1,0}; float zvec[3] = {0,0,1}; - float phi, si; + float phi; float q1[4]; float obofs[3]; float reverse; @@ -2964,11 +2935,8 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode) /* Perform the up/down rotation */ phi = sbadjust * rsens * /*0.5f * */ fval[3]; /* spin vertically half as fast as horizontally */ - si = sin(phi); q1[0] = cos(phi); - q1[1] = si * xvec[0]; - q1[2] = si * xvec[1]; - q1[3] = si * xvec[2]; + mul_v3_v3fl(q1+1, xvec, sin(phi)); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); if (use_sel) { diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 59051c7a894..1674c135008 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -161,11 +161,9 @@ static void view_settings_from_ob(Object *ob, float *ofs, float *quat, float *di if (!ob) return; /* Offset */ - if (ofs) { - VECCOPY(ofs, ob->obmat[3]); - mul_v3_fl(ofs, -1.0f); /*flip the vector*/ - } - + if (ofs) + negate_v3_v3(ofs, ob->obmat[3]); + /* Quat */ if (quat) { copy_m4_m4(bmat, ob->obmat); @@ -404,13 +402,9 @@ static void setcameratoview3d(View3D *v3d, RegionView3D *rv3d, Object *ob) { float dvec[3]; float mat3[3][3]; - - dvec[0]= rv3d->dist*rv3d->viewinv[2][0]; - dvec[1]= rv3d->dist*rv3d->viewinv[2][1]; - dvec[2]= rv3d->dist*rv3d->viewinv[2][2]; - - VECCOPY(ob->loc, dvec); - sub_v3_v3v3(ob->loc, ob->loc, rv3d->ofs); + + mul_v3_v3fl(dvec, rv3d->viewinv[2], rv3d->dist); + sub_v3_v3v3(ob->loc, dvec, rv3d->ofs); rv3d->viewquat[0]= -rv3d->viewquat[0]; // quat_to_eul( ob->rot,rv3d->viewquat); // in 2.4x for xyz eulers only @@ -602,9 +596,7 @@ void viewvector(RegionView3D *rv3d, float coord[3], float vec[3]) p2[3] = 1.0f; mul_m4_v4(rv3d->viewmat, p2); - p2[0] = 2.0f * p2[0]; - p2[1] = 2.0f * p2[1]; - p2[2] = 2.0f * p2[2]; + mul_v3_fl(p2, 2.0f); mul_m4_v4(rv3d->viewinv, p2); @@ -1154,6 +1146,25 @@ static void view3d_viewlock(RegionView3D *rv3d) } } +/* give a 4x4 matrix from a perspective view, only needs viewquat, ofs and dist + * basically the same as... + * rv3d->persp= RV3D_PERSP + * setviewmatrixview3d(scene, v3d, rv3d); + * setcameratoview3d(v3d, rv3d, v3d->camera); + * ...but less of a hassle + * */ +static void view3d_persp_mat4(RegionView3D *rv3d, float mat[][4]) +{ + float qt[4], dvec[3]; + copy_qt_qt(qt, rv3d->viewquat); + qt[0]= -qt[0]; + quat_to_mat4(mat, qt); + mat[3][2] -= rv3d->dist; + translate_m4(mat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]); + mul_v3_v3fl(dvec, mat[2], -rv3d->dist); + sub_v3_v3v3(mat[3], dvec, rv3d->ofs); +} + /* dont set windows active in in here, is used by renderwin too */ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d) { @@ -1690,8 +1701,8 @@ void game_set_commmandline_options(GameData *gm) test= (gm->flag & GAME_ENABLE_ALL_FRAMES); SYS_WriteCommandLineInt(syshandle, "fixedtime", test); -// a= (G.fileflags & G_FILE_GAME_TO_IPO); -// SYS_WriteCommandLineInt(syshandle, "game2ipo", a); + test= (gm->flag & GAME_ENABLE_ANIMATION_RECORD); + SYS_WriteCommandLineInt(syshandle, "animation_record", test); test= (gm->flag & GAME_IGNORE_DEPRECATION_WARNINGS); SYS_WriteCommandLineInt(syshandle, "ignore_deprecation_warnings", test); @@ -1940,12 +1951,17 @@ typedef struct FlyInfo { float xlock_momentum, zlock_momentum; /* nicer dynamics */ float grid; /* world scale 1.0 default */ + /* root most parent */ + Object *root_parent; + /* backup values */ float dist_backup; /* backup the views distance since we use a zero dist for fly mode */ float ofs_backup[3]; /* backup the views offset incase the user cancels flying in non camera mode */ float rot_backup[4]; /* backup the views quat incase the user cancels flying in non camera mode. (quat for view, eul for camera) */ short persp_backup; /* remember if were ortho or not, only used for restoring the view if it was a ortho view */ + void *obtfm; /* backup the objects transform */ + /* compare between last state */ double time_lastwheel; /* used to accelerate when using the mousewheel a lot */ double time_lastdraw; /* time between draws */ @@ -2019,13 +2035,23 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even fly->persp_backup= fly->rv3d->persp; fly->dist_backup= fly->rv3d->dist; if (fly->rv3d->persp==RV3D_CAMOB) { - /* store the origoinal camera loc and rot */ - VECCOPY(fly->ofs_backup, fly->v3d->camera->loc); - VECCOPY(fly->rot_backup, fly->v3d->camera->rot); + Object *ob_back; + if((fly->root_parent=fly->v3d->camera->parent)) { + while(fly->root_parent->parent) + fly->root_parent= fly->root_parent->parent; + ob_back= fly->root_parent; + } + else { + ob_back= fly->v3d->camera; + } + + /* store the original camera loc and rot */ + /* TODO. axis angle etc */ + + fly->obtfm= object_tfm_backup(ob_back); where_is_object(fly->scene, fly->v3d->camera); - VECCOPY(fly->rv3d->ofs, fly->v3d->camera->obmat[3]); - mul_v3_fl(fly->rv3d->ofs, -1.0f); /*flip the vector*/ + negate_v3_v3(fly->rv3d->ofs, fly->v3d->camera->obmat[3]); fly->rv3d->dist=0.0; } else { @@ -2066,10 +2092,14 @@ static int flyEnd(bContext *C, FlyInfo *fly) if (fly->state == FLY_CANCEL) { /* Revert to original view? */ if (fly->persp_backup==RV3D_CAMOB) { /* a camera view */ + Object *ob_back; + if(fly->root_parent)ob_back= fly->root_parent; + else ob_back= fly->v3d->camera; - VECCOPY(v3d->camera->loc, fly->ofs_backup); - VECCOPY(v3d->camera->rot, fly->rot_backup); - DAG_id_flush_update(&v3d->camera->id, OB_RECALC_OB); + /* store the original camera loc and rot */ + object_tfm_restore(ob_back, fly->obtfm); + + DAG_id_flush_update(&ob_back->id, OB_RECALC_OB); } else { /* Non Camera we need to reset the view back to the original location bacause the user canceled*/ QUATCOPY(rv3d->viewquat, fly->rot_backup); @@ -2079,10 +2109,15 @@ static int flyEnd(bContext *C, FlyInfo *fly) } else if (fly->persp_backup==RV3D_CAMOB) { /* camera */ float mat3[3][3]; - copy_m3_m4(mat3, v3d->camera->obmat); - object_mat3_to_rot(v3d->camera, mat3, TRUE); + if(fly->root_parent) { + DAG_id_flush_update(&fly->root_parent->id, OB_RECALC_OB); + } + else { + copy_m3_m4(mat3, v3d->camera->obmat); + object_mat3_to_rot(v3d->camera, mat3, TRUE); + DAG_id_flush_update(&v3d->camera->id, OB_RECALC_OB); + } - DAG_id_flush_update(&v3d->camera->id, OB_RECALC_OB); #if 0 //XXX2.5 if (IS_AUTOKEY_MODE(NORMAL)) { allqueue(REDRAWIPO, 0); @@ -2107,6 +2142,8 @@ static int flyEnd(bContext *C, FlyInfo *fly) rv3d->rflag &= ~(RV3D_FLYMODE|RV3D_NAVIGATING); //XXX2.5 BIF_view3d_previewrender_signal(fly->sa, PR_DBASE|PR_DISPRECT); /* not working at the moment not sure why */ + if(fly->obtfm) + MEM_freeN(fly->obtfm); if(fly->state == FLY_CONFIRM) { MEM_freeN(fly); @@ -2250,6 +2287,8 @@ static int flyApply(FlyInfo *fly) ARegion *ar = fly->ar; Scene *scene= fly->scene; + float prev_view_mat[4][4]; + float mat[3][3], /* 3x3 copy of the view matrix so we can move allong the view axis */ dvec[3]={0,0,0}, /* this is the direction thast added to the view offset per redraw */ @@ -2265,7 +2304,9 @@ static int flyApply(FlyInfo *fly) unsigned char apply_rotation= 1; /* if the user presses shift they can look about without movinf the direction there looking*/ - + if(fly->root_parent) + view3d_persp_mat4(rv3d, prev_view_mat); + /* the dist defines a vector that is infront of the offset to rotate the view about. this is no good for fly mode because we @@ -2458,42 +2499,73 @@ static int flyApply(FlyInfo *fly) interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f/(1.0f+(time_redraw*5.0f)))); if (rv3d->persp==RV3D_CAMOB) { - if (v3d->camera->protectflag & OB_LOCK_LOCX) - dvec[0] = 0.0; - if (v3d->camera->protectflag & OB_LOCK_LOCY) - dvec[1] = 0.0; - if (v3d->camera->protectflag & OB_LOCK_LOCZ) - dvec[2] = 0.0; + Object *lock_ob= fly->root_parent ? fly->root_parent : fly->v3d->camera; + if (lock_ob->protectflag & OB_LOCK_LOCX) dvec[0] = 0.0; + if (lock_ob->protectflag & OB_LOCK_LOCY) dvec[1] = 0.0; + if (lock_ob->protectflag & OB_LOCK_LOCZ) dvec[2] = 0.0; } add_v3_v3v3(rv3d->ofs, rv3d->ofs, dvec); -#if 0 //XXX2.5 + + /* todo, dynamic keys */ +#if 0 if (fly->zlock && fly->xlock) - headerprint("FlyKeys Speed:(+/- | Wheel), Upright Axis:X on/Z on, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); + ED_area_headerprint(fly->ar, "FlyKeys Speed:(+/- | Wheel), Upright Axis:X on/Z on, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); else if (fly->zlock) - headerprint("FlyKeys Speed:(+/- | Wheel), Upright Axis:X off/Z on, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); + ED_area_headerprint(fly->ar, "FlyKeys Speed:(+/- | Wheel), Upright Axis:X off/Z on, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); else if (fly->xlock) - headerprint("FlyKeys Speed:(+/- | Wheel), Upright Axis:X on/Z off, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); + ED_area_headerprint(fly->ar, "FlyKeys Speed:(+/- | Wheel), Upright Axis:X on/Z off, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); else - headerprint("FlyKeys Speed:(+/- | Wheel), Upright Axis:X off/Z off, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); + ED_area_headerprint(fly->ar, "FlyKeys Speed:(+/- | Wheel), Upright Axis:X off/Z off, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); #endif /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */ if (rv3d->persp==RV3D_CAMOB) { - rv3d->persp= RV3D_PERSP; /*set this so setviewmatrixview3d uses the ofs and quat instead of the camera */ - setviewmatrixview3d(scene, v3d, rv3d); - setcameratoview3d(v3d, rv3d, v3d->camera); - rv3d->persp= RV3D_CAMOB; - + ID *id_key; + /* transform the parent or the camera? */ + if(fly->root_parent) { + Object *ob_update; + + float view_mat[4][4]; + float prev_view_imat[4][4]; + float diff_mat[4][4]; + float parent_mat[4][4]; + + invert_m4_m4(prev_view_imat, prev_view_mat); + view3d_persp_mat4(rv3d, view_mat); + mul_m4_m4m4(diff_mat, prev_view_imat, view_mat); + mul_m4_m4m4(parent_mat, fly->root_parent->obmat, diff_mat); + object_apply_mat4(fly->root_parent, parent_mat); + + // where_is_object(scene, fly->root_parent); + + ob_update= v3d->camera->parent; + while(ob_update) { + DAG_id_flush_update(&ob_update->id, OB_RECALC_OB); + ob_update= ob_update->parent; + } + + copy_m4_m4(prev_view_mat, view_mat); + + id_key= &fly->root_parent->id; + + } + else { + float view_mat[4][4]; + view3d_persp_mat4(rv3d, view_mat); + object_apply_mat4(v3d->camera, view_mat); + id_key= &v3d->camera->id; + } + /* record the motion */ - if (autokeyframe_cfra_can_key(scene, &v3d->camera->id)) { + if (autokeyframe_cfra_can_key(scene, id_key)) { bCommonKeySrc cks; ListBase dsources = {&cks, &cks}; int cfra = CFRA; /* init common-key-source for use by KeyingSets */ memset(&cks, 0, sizeof(bCommonKeySrc)); - cks.id= &v3d->camera->id; + cks.id= id_key; /* insert keyframes * 1) on the first frame @@ -2612,10 +2684,9 @@ void view3d_align_axis_to_vector(View3D *v3d, RegionView3D *rv3d, int axisidx, f if(axisidx > 0) alignaxis[axisidx-1]= 1.0; else alignaxis[-axisidx-1]= -1.0; - - VECCOPY(norm, vec); - normalize_v3(norm); - + + normalize_v3_v3(norm, vec); + angle= (float)acos(dot_v3v3(alignaxis, norm)); cross_v3_v3v3(axis, alignaxis, norm); axis_angle_to_quat( new_quat,axis, -angle); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index d63054756d9..09c99a47a46 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -718,7 +718,7 @@ int transformEvent(TransInfo *t, wmEvent *event) } // Modal numinput events - t->redraw |= handleNumInput(&(t->num), event, t->snap[1]); + t->redraw |= handleNumInput(&(t->num), event); } /* else do non-mapped events */ else if (event->val==KM_PRESS) { @@ -971,7 +971,7 @@ int transformEvent(TransInfo *t, wmEvent *event) } // Numerical input events - t->redraw |= handleNumInput(&(t->num), event, t->snap[1]); + t->redraw |= handleNumInput(&(t->num), event); // NDof input events switch(handleNDofInput(&(t->ndof), event)) @@ -2081,6 +2081,8 @@ void initWarp(TransInfo *t) t->snap[1] = 5.0f; t->snap[2] = 1.0f; + t->num.increment = 1.0f; + t->flag |= T_NO_CONSTRAINT; /* we need min/max in view space */ @@ -2237,6 +2239,8 @@ void initShear(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; + t->num.increment = 0.1f; + t->flag |= T_NO_CONSTRAINT; } @@ -2363,6 +2367,8 @@ void initResize(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; + + t->num.increment = t->snap[1]; } static void headerResize(TransInfo *t, float vec[3], char *str) { @@ -2614,6 +2620,8 @@ void initToSphere(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; + t->num.increment = t->snap[1]; + t->num.flag |= NUM_NULL_ONE | NUM_NO_NEGATIVE; t->flag |= T_NO_CONSTRAINT; @@ -2705,11 +2713,12 @@ void initRotation(TransInfo *t) t->snap[1] = (float)((5.0/180)*M_PI); t->snap[2] = t->snap[1] * 0.2f; + t->num.increment = 1.0f; + if (t->flag & T_2D_EDIT) t->flag |= T_NO_CONSTRAINT; - VECCOPY(t->axis, t->viewinv[2]); - mul_v3_fl(t->axis, -1.0f); + negate_v3_v3(t->axis, t->viewinv[2]); normalize_v3(t->axis); } @@ -2967,8 +2976,7 @@ int Rotation(TransInfo *t, short mval[2]) t->con.applyRot(t, NULL, t->axis, &final); } else { /* reset axis if constraint is not set */ - VECCOPY(t->axis, t->viewinv[2]); - mul_v3_fl(t->axis, -1.0f); + negate_v3_v3(t->axis, t->viewinv[2]); normalize_v3(t->axis); } @@ -3032,6 +3040,8 @@ void initTrackball(TransInfo *t) t->snap[1] = (float)((5.0/180)*M_PI); t->snap[2] = t->snap[1] * 0.2f; + t->num.increment = 1.0f; + t->flag |= T_NO_CONSTRAINT; } @@ -3149,6 +3159,8 @@ void initTranslation(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = t->snap[2] = 1.0f; } + + t->num.increment = t->snap[1]; } static void headerTranslation(TransInfo *t, float vec[3], char *str) { @@ -3339,6 +3351,8 @@ void initShrinkFatten(TransInfo *t) t->snap[1] = 1.0f; t->snap[2] = t->snap[1] * 0.1f; + t->num.increment = t->snap[1]; + t->flag |= T_NO_CONSTRAINT; } } @@ -3413,6 +3427,8 @@ void initTilt(TransInfo *t) t->snap[1] = (float)((5.0/180)*M_PI); t->snap[2] = t->snap[1] * 0.2f; + t->num.increment = t->snap[1]; + t->flag |= T_NO_CONSTRAINT; } @@ -3482,6 +3498,8 @@ void initCurveShrinkFatten(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; + t->num.increment = t->snap[1]; + t->flag |= T_NO_ZERO; t->num.flag |= NUM_NO_ZERO; @@ -3551,6 +3569,8 @@ void initPushPull(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = 1.0f; t->snap[2] = t->snap[1] * 0.1f; + + t->num.increment = t->snap[1]; } @@ -3639,6 +3659,8 @@ void initBevel(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; + t->num.increment = t->snap[1]; + /* DON'T KNOW WHY THIS IS NEEDED */ if (G.editBMesh->imval[0] == 0 && G.editBMesh->imval[1] == 0) { /* save the initial mouse co */ @@ -3748,6 +3770,8 @@ void initBevelWeight(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; + t->num.increment = t->snap[1]; + t->flag |= T_NO_CONSTRAINT; } @@ -3819,6 +3843,8 @@ void initCrease(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; + t->num.increment = t->snap[1]; + t->flag |= T_NO_CONSTRAINT; } @@ -3893,6 +3919,8 @@ void initBoneSize(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; + + t->num.increment = t->snap[1]; } static void headerBoneSize(TransInfo *t, float vec[3], char *str) { @@ -4009,6 +4037,8 @@ void initBoneEnvelope(TransInfo *t) t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; + t->num.increment = t->snap[1]; + t->flag |= T_NO_CONSTRAINT; } @@ -4586,6 +4616,8 @@ void initEdgeSlide(TransInfo *t) t->snap[1] = (float)((5.0/180)*M_PI); t->snap[2] = t->snap[1] * 0.2f; + t->num.increment = t->snap[1]; + t->flag |= T_NO_CONSTRAINT; } @@ -4754,6 +4786,8 @@ void initBoneRoll(TransInfo *t) t->snap[1] = (float)((5.0/180)*M_PI); t->snap[2] = t->snap[1] * 0.2f; + t->num.increment = 1.0f; + t->flag |= T_NO_CONSTRAINT; } @@ -4814,6 +4848,8 @@ void initBakeTime(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = 1.0f; t->snap[2] = t->snap[1] * 0.1f; + + t->num.increment = t->snap[1]; } int BakeTime(TransInfo *t, short mval[2]) @@ -5031,6 +5067,8 @@ void initSeqSlide(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = floor(t->scene->r.frs_sec / t->scene->r.frs_sec_base); t->snap[2] = 10.0f; + + t->num.increment = t->snap[1]; } static void headerSeqSlide(TransInfo *t, float val[2], char *str) @@ -5246,6 +5284,8 @@ void initTimeTranslate(TransInfo *t) /* initialise snap like for everything else */ t->snap[0] = 0.0f; t->snap[1] = t->snap[2] = 1.0f; + + t->num.increment = t->snap[1]; } static void headerTimeTranslate(TransInfo *t, char *str) @@ -5392,6 +5432,8 @@ void initTimeSlide(TransInfo *t) /* initialise snap like for everything else */ t->snap[0] = 0.0f; t->snap[1] = t->snap[2] = 1.0f; + + t->num.increment = t->snap[1]; } static void headerTimeSlide(TransInfo *t, float sval, char *str) @@ -5524,6 +5566,8 @@ void initTimeScale(TransInfo *t) /* initialise snap like for everything else */ t->snap[0] = 0.0f; t->snap[1] = t->snap[2] = 1.0f; + + t->num.increment = t->snap[1]; } static void headerTimeScale(TransInfo *t, char *str) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 9d0cfdc5ac0..9d236bd47db 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1116,6 +1116,7 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td->loc = NULL; td->ext = NULL; + td->ob = t->obedit; td++; } @@ -1131,6 +1132,7 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td->loc = NULL; td->ext = NULL; + td->ob = t->obedit; td++; } @@ -1165,6 +1167,7 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) normalize_m3(td->axismtx); td->ext = NULL; + td->ob = t->obedit; td++; } @@ -1181,6 +1184,7 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td->flag= TD_SELECTED; td->ext = NULL; + td->ob = t->obedit; td++; } @@ -1209,6 +1213,7 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td->ext = NULL; td->val = NULL; + td->ob = t->obedit; td++; } @@ -1231,6 +1236,7 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td->ext = NULL; td->val = NULL; + td->ob = t->obedit; td++; } @@ -4712,7 +4718,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) Object *ob; // short redrawipo=0, resetslowpar=1; int cancelled= (t->state == TRANS_CANCEL); - short duplicate= (t->undostr && strstr(t->undostr, "Duplicate")) ? 1 : 0; + short duplicate= (t->undostr && strstr(t->undostr, "Duplicate")) ? 1 : 0; /* see bugreport #21229 for reasons for this data */ /* early out when nothing happened */ if (t->total == 0 || t->mode == TFM_DUMMY) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 27eb48614d2..d358614b1eb 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -859,7 +859,8 @@ void drawLine(TransInfo *t, float *center, float *dir, char axis, short options) setlinestyle(0); glBegin(GL_LINE_STRIP); glVertex3fv(v1); - glVertex3fv(v2); + glVertex3fv(center); +// glVertex3fv(v2); glEnd(); glPopMatrix(); diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 4c0f192ed40..2e60db8048e 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -817,9 +817,8 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], quat_to_mat4( mat,ml_sel->quat); VECCOPY(normal, mat[2]); - VECCOPY(plane, mat[1]); - mul_v3_fl(plane, -1.0); + negate_v3_v3(plane, mat[1]); result = ORIENTATION_NORMAL; } @@ -887,7 +886,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], add_v3_v3v3(plane, plane, pchan->pose_mat[1]); } } - mul_v3_fl(plane, -1.0); + negate_v3(plane); /* we need the transpose of the inverse for a normal... */ copy_m3_m4(imat, ob->obmat); diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index d6e2621a235..fc193373327 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -159,7 +159,7 @@ void applyNumInput(NumInput *n, float *vec) } } -char handleNumInput(NumInput *n, wmEvent *event, float increment) +char handleNumInput(NumInput *n, wmEvent *event) { float Val = 0; short idx = n->idx, idx_max = n->idx_max; @@ -170,13 +170,13 @@ char handleNumInput(NumInput *n, wmEvent *event, float increment) if (!n->ctrl[idx]) n->ctrl[idx] = 1; - n->val[idx] += increment; + n->val[idx] += n->increment; break; case NUM_MODAL_INCREMENT_DOWN: if (!n->ctrl[idx]) n->ctrl[idx] = 1; - n->val[idx] -= increment; + n->val[idx] -= n->increment; break; default: return 0; @@ -300,6 +300,8 @@ char handleNumInput(NumInput *n, wmEvent *event, float increment) } } + printf("%f\n", n->val[idx]); + /* REDRAW SINCE NUMBERS HAVE CHANGED */ return 1; } diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index f6ad69c50eb..8ed70b5509f 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -270,7 +270,7 @@ void IMB_float_from_rect(struct ImBuf *ibuf) if(to==NULL) return; if(tof==NULL) { - imb_addrectfloatImBuf(ibuf); + if (imb_addrectfloatImBuf(ibuf) == 0) return; tof = ibuf->rect_float; } diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 06ace29dbfe..8e04107afe0 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -66,6 +66,8 @@ typedef struct ClothSimSettings float goalspring; float goalfrict; float velocity_smooth; /* smoothing of velocities for hair */ + float collider_friction; /* friction with colliders */ + int stepsPerFrame; /* Number of time steps per frame. */ int flags; /* flags, see CSIMSETT_FLAGS enum above. */ int preroll; /* How many frames of simulation to do before we start. */ @@ -76,7 +78,6 @@ typedef struct ClothSimSettings short vgroup_struct; /* vertex group for scaling structural stiffness */ short presets; /* used for presets on GUI */ short reset; - int pad; struct EffectorWeights *effector_weights; } ClothSimSettings; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index d35de0497d9..5af90e2db6d 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -492,6 +492,7 @@ typedef struct GameData { #define GAME_GLSL_NO_NODES (1 << 10) #define GAME_GLSL_NO_EXTRA_TEX (1 << 11) #define GAME_IGNORE_DEPRECATION_WARNINGS (1 << 12) +#define GAME_ENABLE_ANIMATION_RECORD (1 << 13) /* GameData.matmode */ #define GAME_MAT_TEXFACE 0 diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index a2d18ed5d0a..85c6e73a909 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -276,10 +276,10 @@ typedef struct bTheme { } bTheme; /* for the moment only the name. may want to store options with this later */ -typedef struct bExtension { - struct bExtension *next, *prev; +typedef struct bAddon { + struct bAddon *next, *prev; char module[64]; -} bExtension; +} bAddon; typedef struct SolidLight { int flag, pad; @@ -327,7 +327,7 @@ typedef struct UserDef { struct ListBase uifonts; struct ListBase uistyles; struct ListBase keymaps; - struct ListBase extensions; + struct ListBase addons; char keyconfigstr[64]; short undosteps; @@ -378,7 +378,7 @@ extern UserDef U; /* from blenkernel blender.c */ #define USER_SECTION_SYSTEM 3 #define USER_SECTION_THEME 4 #define USER_SECTION_INPUT 5 -#define USER_SECTION_EXTENSIONS 6 +#define USER_SECTION_ADDONS 6 /* flag */ #define USER_AUTOSAVE (1 << 0) @@ -403,7 +403,7 @@ extern UserDef U; /* from blenkernel blender.c */ #define USER_ADD_VIEWALIGNED (1 << 19) #define USER_RELPATHS (1 << 20) #define USER_DRAGIMMEDIATE (1 << 21) -#define USER_DONT_DOSCRIPTLINKS (1 << 22) +#define USER_SCRIPT_AUTOEXEC_DISABLE (1 << 22) #define USER_FILENOUI (1 << 23) #define USER_NONEGFRAMES (1 << 24) @@ -456,8 +456,10 @@ extern UserDef U; /* from blenkernel blender.c */ #define AUTOKEY_MODE_NORMAL 3 #define AUTOKEY_MODE_EDITKEYS 5 -/* Auto-Keying flag */ - /* U.autokey_flag (not strictly used when autokeying only - is also used when keyframing these days) */ +/* Auto-Keying flag + * U.autokey_flag (not strictly used when autokeying only - is also used when keyframing these days) + * note: AUTOKEY_FLAG_* is used with a macro, search for lines like IS_AUTOKEY_FLAG(INSERTAVAIL) + */ #define AUTOKEY_FLAG_INSERTAVAIL (1<<0) #define AUTOKEY_FLAG_INSERTNEEDED (1<<1) #define AUTOKEY_FLAG_AUTOMATKEY (1<<2) diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 9df3e053d9f..a53645e7442 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -271,8 +271,9 @@ typedef struct wmOperator { IDProperty *properties; /* saved, user-settable properties */ /* runtime */ - struct wmOperatorType *type; /* operator type definition from idname */ + struct wmOperatorType *type;/* operator type definition from idname */ void *customdata; /* custom storage, only while operator runs */ + void *py_instance; /* python stores the class instance here */ struct PointerRNA *ptr; /* rna pointer to access properties */ struct ReportList *reports; /* errors and warnings storage */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index bce449cc66a..eb92b23bd5d 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -49,6 +49,7 @@ extern StructRNA RNA_ActionConstraint; extern StructRNA RNA_ActionGroup; extern StructRNA RNA_Actuator; extern StructRNA RNA_ActuatorSensor; +extern StructRNA RNA_Addon; extern StructRNA RNA_AlwaysSensor; extern StructRNA RNA_AndController; extern StructRNA RNA_AnimData; @@ -196,7 +197,6 @@ extern StructRNA RNA_EnumPropertyItem; extern StructRNA RNA_EnvironmentMap; extern StructRNA RNA_EnvironmentMapTexture; extern StructRNA RNA_Event; -extern StructRNA RNA_Extension; extern StructRNA RNA_ExplodeModifier; extern StructRNA RNA_ExpressionController; extern StructRNA RNA_FCurve; @@ -374,11 +374,11 @@ extern StructRNA RNA_RenderEngine; extern StructRNA RNA_RenderLayer; extern StructRNA RNA_RenderPass; extern StructRNA RNA_RenderResult; +extern StructRNA RNA_RenderSettings; extern StructRNA RNA_RGBANodeSocket; extern StructRNA RNA_RigidBodyJointConstraint; extern StructRNA RNA_Scene; extern StructRNA RNA_SceneGameData; -extern StructRNA RNA_SceneRenderData; extern StructRNA RNA_SceneRenderLayer; extern StructRNA RNA_SceneSequence; extern StructRNA RNA_Screen; @@ -665,6 +665,7 @@ StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop); int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop); int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index); +int RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop); /* without lib check, only checks the flag */ int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop); int RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop); @@ -809,6 +810,7 @@ void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values) int RNA_enum_get(PointerRNA *ptr, const char *name); void RNA_enum_set(PointerRNA *ptr, const char *name, int value); +void RNA_enum_set_identifier(PointerRNA *ptr, const char *name, const char *id); int RNA_enum_is_equal(struct bContext *C, PointerRNA *ptr, const char *name, const char *enumname); /* lower level functions that donr use a PointerRNA */ diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index 2ed365ad79f..ddd6dfef653 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -88,6 +88,7 @@ EnumPropertyItem *rna_TransformOrientation_itemf(struct bContext *C, struct Poin /* Generic functions, return an enum from library data, index is the position * in the linked list can add more for different types as needed */ +EnumPropertyItem *RNA_action_itemf(struct bContext *C, struct PointerRNA *ptr, int *free); EnumPropertyItem *RNA_group_itemf(struct bContext *C, struct PointerRNA *ptr, int *free); EnumPropertyItem *RNA_scene_itemf(struct bContext *C, struct PointerRNA *ptr, int *free); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 81e34dad7c0..4a50be6f58b 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1135,19 +1135,21 @@ int RNA_property_ui_icon(PropertyRNA *prop) int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop) { - ID *id; + ID *id= ptr->id.data; int flag; prop= rna_ensure_property(prop); + flag= prop->editable ? prop->editable(ptr) : prop->flag; + return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION)); +} - if(prop->editable) - flag= prop->editable(ptr); - else - flag= prop->flag; - - id= ptr->id.data; +int RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop) +{ + int flag; - return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION)); + prop= rna_ensure_property(prop); + flag= prop->editable ? prop->editable(ptr) : prop->flag; + return (flag & PROP_EDITABLE); } /* same as RNA_property_editable(), except this checks individual items in an array */ @@ -1937,8 +1939,12 @@ void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr else { PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop; - if(pprop->set && !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL)) + if( pprop->set && + !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) && + !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data) + ) { pprop->set(ptr, ptr_value); + } } } @@ -3289,6 +3295,20 @@ void RNA_enum_set(PointerRNA *ptr, const char *name, int value) printf("RNA_enum_set: %s.%s not found.\n", ptr->type->identifier, name); } +void RNA_enum_set_identifier(PointerRNA *ptr, const char *name, const char *id) +{ + PropertyRNA *prop= RNA_struct_find_property(ptr, name); + + if(prop) { + int value; + if(RNA_property_enum_value(NULL, ptr, prop, id, &value)) + RNA_property_enum_set(ptr, prop, value); + else + printf("RNA_enum_set_identifier: %s.%s has no enum id '%s'.\n", ptr->type->identifier, name, id); + } else + printf("RNA_enum_set_identifier: %s.%s not found.\n", ptr->type->identifier, name); +} + int RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char *enumname) { PropertyRNA *prop= RNA_struct_find_property(ptr, name); diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 208f91a452f..453d9b9a844 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -249,6 +249,7 @@ static void rna_def_keyingset(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Active Path Index", "Current Keying Set index"); /* Flags */ + // XXX: depreceated prop= RNA_def_property(srna, "builtin", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYINGSET_BUILTIN); diff --git a/source/blender/makesrna/intern/rna_animation_api.c b/source/blender/makesrna/intern/rna_animation_api.c index 7ce93658789..208e3b9ca4c 100644 --- a/source/blender/makesrna/intern/rna_animation_api.c +++ b/source/blender/makesrna/intern/rna_animation_api.c @@ -41,7 +41,7 @@ #include "BKE_animsys.h" -static void rna_KeyingSet_add_destination(KeyingSet *keyingset, ReportList *reports, +static void rna_KeyingSet_add_path(KeyingSet *keyingset, ReportList *reports, ID *id, char rna_path[], int array_index, int entire_array, int grouping_method, char group_name[]) { @@ -53,11 +53,11 @@ static void rna_KeyingSet_add_destination(KeyingSet *keyingset, ReportList *repo /* if data is valid, call the API function for this */ if (keyingset) { - BKE_keyingset_add_destination(keyingset, id, group_name, rna_path, array_index, flag, grouping_method); + BKE_keyingset_add_path(keyingset, id, group_name, rna_path, array_index, flag, grouping_method); keyingset->active_path= BLI_countlist(&keyingset->paths); } else { - BKE_report(reports, RPT_ERROR, "Keying Set Destination could not be added."); + BKE_report(reports, RPT_ERROR, "Keying Set Path could not be added."); } } @@ -69,7 +69,7 @@ void RNA_api_keyingset(StructRNA *srna) PropertyRNA *parm; /* Add Destination */ - func= RNA_def_function(srna, "add_destination", "rna_KeyingSet_add_destination"); + func= RNA_def_function(srna, "add_destination", "rna_KeyingSet_add_path"); RNA_def_function_ui_description(func, "Add a new destination for the Keying Set."); RNA_def_function_flag(func, FUNC_USE_REPORTS); /* ID-block for target */ diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 961e0708adc..4ecb93eb1d6 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -225,6 +225,12 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Internal Friction", ""); RNA_def_property_update(prop, 0, "rna_cloth_update"); + prop= RNA_def_property(srna, "collider_friction", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "collider_friction"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Collider Friction", ""); + RNA_def_property_update(prop, 0, "rna_cloth_update"); + /* mass */ prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 02bfb9f9493..499423276ab 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -805,27 +805,27 @@ static void rna_def_curve(BlenderRNA *brna) prop= RNA_def_property(srna, "resolution_u", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolu"); - RNA_def_property_ui_range(prop, 1, 1024, 1, 0); RNA_def_property_range(prop, 1, INT_MAX); + RNA_def_property_ui_range(prop, 1, 64, 1, 0); RNA_def_property_ui_text(prop, "Resolution U", "Surface resolution in U direction"); RNA_def_property_update(prop, 0, "rna_Curve_resolution_u_update_data"); prop= RNA_def_property(srna, "resolution_v", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolv"); - RNA_def_property_ui_range(prop, 1, 1024, 1, 0); + RNA_def_property_ui_range(prop, 1, 64, 1, 0); RNA_def_property_range(prop, 1, INT_MAX); RNA_def_property_ui_text(prop, "Resolution V", "Surface resolution in V direction"); RNA_def_property_update(prop, 0, "rna_Curve_resolution_v_update_data"); prop= RNA_def_property(srna, "render_resolution_u", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolu_ren"); - RNA_def_property_ui_range(prop, 0, 1024, 1, 0); RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_range(prop, 1, 64, 1, 0); RNA_def_property_ui_text(prop, "Render Resolution U", "Surface resolution in U direction used while rendering. Zero skips this property"); prop= RNA_def_property(srna, "render_resolution_v", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolv_ren"); - RNA_def_property_ui_range(prop, 0, 1024, 1, 0); + RNA_def_property_ui_range(prop, 1, 64, 1, 0); RNA_def_property_range(prop, 0, INT_MAX); RNA_def_property_ui_text(prop, "Render Resolution V", "Surface resolution in V direction used while rendering. Zero skips this property"); @@ -965,13 +965,15 @@ static void rna_def_curve_nurb(BlenderRNA *brna) prop= RNA_def_property(srna, "resolution_u", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolu"); - RNA_def_property_range(prop, 1, 1024); + RNA_def_property_range(prop, 1, INT_MAX); + RNA_def_property_ui_range(prop, 1, 64, 1, 0); RNA_def_property_ui_text(prop, "Resolution U", "Curve or Surface subdivisions per segment"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); prop= RNA_def_property(srna, "resolution_v", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "resolv"); - RNA_def_property_range(prop, 1, 1024); + RNA_def_property_range(prop, 1, INT_MAX); + RNA_def_property_ui_range(prop, 1, 64, 1, 0); RNA_def_property_ui_text(prop, "Resolution V", "Surface subdivisions per segment"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index e394fd4f710..533d954871c 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -37,33 +37,18 @@ #ifdef RNA_RUNTIME #include "BKE_image.h" +#include "BKE_packedFile.h" #include "BKE_main.h" #include "BKE_utildefines.h" +#include "IMB_imbuf.h" + #include "DNA_image_types.h" #include "DNA_scene_types.h" #include "MEM_guardedalloc.h" -/* - User should check if returned path exists before copying a file there. - - TODO: it would be better to return a (abs, rel) tuple. -*/ -static char *rna_Image_get_export_path(Image *image, char *dest_dir, int rel) -{ - int length = FILE_MAX; - char *path= MEM_callocN(length, "image file path"); - - if (!BKE_get_image_export_path(image, dest_dir, rel ? NULL : path, length, rel ? path : NULL, length )) { - MEM_freeN(path); - return NULL; - } - - return path; -} - -static void rna_Image_save(Image *image, bContext *C, ReportList *reports, char *path, Scene *scene) +static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports, char *path, Scene *scene) { ImBuf *ibuf; @@ -92,15 +77,25 @@ static void rna_Image_save(Image *image, bContext *C, ReportList *reports, char } } -char *rna_Image_get_abs_filename(Image *image, bContext *C) +static void rna_Image_save(Image *image, ReportList *reports) { - char *filename= MEM_callocN(FILE_MAX, "Image.get_abs_filename()"); - - BLI_strncpy(filename, image->name, FILE_MAXDIR + FILE_MAXFILE); - BLI_convertstringcode(filename, CTX_data_main(C)->name); - BLI_convertstringframe(filename, CTX_data_scene(C)->r.cfra, 0); - - return filename; + ImBuf *ibuf= BKE_image_get_ibuf(image, NULL); + if(ibuf) { + if(image->packedfile) { + if (writePackedFile(reports, image->name, image->packedfile, 0) != RET_OK) { + BKE_reportf(reports, RPT_ERROR, "Image \"%s\" could saved packed file to \"%s\"", image->id.name+2, image->name); + } + } + else if (IMB_saveiff(ibuf, image->name, ibuf->flags)) { + ibuf->userflags &= ~IB_BITMAPDIRTY; + } + else { + BKE_reportf(reports, RPT_ERROR, "Image \"%s\" could not be saved to \"%s\"", image->id.name+2, image->name); + } + } + else { + BKE_reportf(reports, RPT_ERROR, "Image \"%s\" does not have any image data", image->id.name+2); + } } #else @@ -110,27 +105,16 @@ void RNA_api_image(StructRNA *srna) FunctionRNA *func; PropertyRNA *parm; - func= RNA_def_function(srna, "get_export_path", "rna_Image_get_export_path"); - RNA_def_function_ui_description(func, "Produce image export path."); - parm= RNA_def_string(func, "dest_dir", "", 0, "", "Destination directory."); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_boolean(func, "get_rel_path", 1, "", "Return relative path if True."); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_string(func, "path", "", 0, "", "Absolute export path."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "get_abs_filename", "rna_Image_get_abs_filename"); - RNA_def_function_ui_description(func, "Get absolute filename."); - RNA_def_function_flag(func, FUNC_USE_CONTEXT); - parm= RNA_def_string_file_path(func, "abs_filename", NULL, 0, "", "Image/movie absolute filename."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "save", "rna_Image_save"); - RNA_def_function_ui_description(func, "Save image to a specific path."); + func= RNA_def_function(srna, "save_render", "rna_Image_save_render"); + RNA_def_function_ui_description(func, "Save image to a specific path using a scenes render settings."); RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS); parm= RNA_def_string(func, "path", "", 0, "", "Save path."); RNA_def_property_flag(parm, PROP_REQUIRED); parm= RNA_def_pointer(func, "scene", "Scene", "", "Scene to take image parameters from."); + + func= RNA_def_function(srna, "save", "rna_Image_save"); + RNA_def_function_ui_description(func, "Save image to its source path."); + RNA_def_function_flag(func, FUNC_USE_REPORTS); } #endif diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index f6197a8da15..5b9913ad311 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -346,12 +346,13 @@ static void rna_def_lamp(BlenderRNA *brna) prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "dist"); - RNA_def_property_ui_range(prop, 0, 1000, 1.0, 2); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_range(prop, 0, 1000, 1, 3); RNA_def_property_ui_text(prop, "Distance", "Falloff distance - the light is at half the original intensity at this point"); RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); prop= RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE); - RNA_def_property_ui_range(prop, 0, 10.0, 10, 2); + RNA_def_property_ui_range(prop, 0, 10, 1, 3); RNA_def_property_ui_text(prop, "Energy", "Amount of light that the lamp emits"); RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index e937a3b10c2..56c0819680d 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -30,6 +30,7 @@ #include <stdio.h> #include "RNA_define.h" +#include "RNA_access.h" #include "RNA_types.h" #include "RNA_enum_types.h" @@ -38,6 +39,7 @@ #ifdef RNA_RUNTIME #include "BKE_main.h" +#include "BKE_curve.h" #include "BKE_mesh.h" #include "BKE_armature.h" #include "BKE_library.h" @@ -109,12 +111,54 @@ void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports, struc unlink_scene(bmain, scene, newscene); } -Object *rna_Main_objects_new(Main *bmain, char* name, int type) -{ - Object *ob= add_only_object(type, name); +Object *rna_Main_objects_new(Main *bmain, ReportList *reports, char* name, ID *data) +{ + Object *ob; + int type= OB_EMPTY; + if(data) { + switch(GS(data->name)) { + case ID_ME: + type= OB_MESH; + break; + case ID_CU: + type= curve_type((struct Curve *)data); + break; + case ID_MB: + type= OB_MBALL; + break; + case ID_LA: + type= OB_LAMP; + break; + case ID_CA: + type= OB_CAMERA; + break; + case ID_LT: + type= OB_LATTICE; + break; + case ID_AR: + type= OB_ARMATURE; + break; + default: + { + const char *idname; + if(RNA_enum_id_from_value(id_type_items, GS(data->name), &idname) == 0) + idname= "UNKNOWN"; + + BKE_reportf(reports, RPT_ERROR, "ID type '%s' is not valid for a object.", idname); + return NULL; + } + } + + data->us++; + } + + ob= add_only_object(type, name); ob->id.us--; + + ob->data= data; return ob; } + void rna_Main_objects_remove(Main *bmain, ReportList *reports, struct Object *object) { /* @@ -337,10 +381,11 @@ void RNA_def_main_objects(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_struct_ui_text(srna, "Main Objects", "Collection of objects"); func= RNA_def_function(srna, "new", "rna_Main_objects_new"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Add a new object to the main database"); parm= RNA_def_string(func, "name", "Object", 0, "", "New name for the datablock."); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_enum(func, "type", object_type_items, 0, "", "Type of Object."); + parm= RNA_def_pointer(func, "object_data", "ID", "", "Object data or None for an empty object."); RNA_def_property_flag(parm, PROP_REQUIRED); /* return type */ diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 295119bf8a2..117a1d5bc60 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1443,6 +1443,7 @@ static void rna_def_object(BlenderRNA *brna) static float default_quat[4] = {1,0,0,0}; /* default quaternion values */ static float default_axisAngle[4] = {0,0,1,0}; /* default axis-angle rotation values */ + static float default_scale[3] = {1,1,1}; /* default scale values */ int matrix_dimsize[]= {4, 4}; int boundbox_dimsize[]= {8, 3}; @@ -1603,6 +1604,7 @@ static void rna_def_object(BlenderRNA *brna) prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_editable_array_func(prop, "rna_Object_scale_editable"); + RNA_def_property_float_array_default(prop, default_scale); RNA_def_property_ui_text(prop, "Scale", "Scaling of the object"); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); @@ -1724,8 +1726,9 @@ static void rna_def_object(BlenderRNA *brna) prop= RNA_def_property(srna, "empty_draw_size", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "empty_drawsize"); - RNA_def_property_range(prop, 0.01, 10.0); - RNA_def_property_ui_text(prop, "Empty Display Size", "Size of of display for empties in the viewport"); + RNA_def_property_range(prop, 0.1f, 1000.0f); + RNA_def_property_ui_range(prop, 0.01, 100, 1, 1); + RNA_def_property_ui_text(prop, "Empty Display Size", "Size of display for empties in the viewport"); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); /* render */ diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 44bf85679c4..240d02f7f9e 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -663,6 +663,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) static float default_quat[4] = {1,0,0,0}; /* default quaternion values */ static float default_axisAngle[4] = {0,0,1,0}; /* default axis-angle rotation values */ + static float default_scale[3] = {1,1,1}; /* default scale values */ StructRNA *srna; PropertyRNA *prop; @@ -722,6 +723,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_editable_array_func(prop, "rna_PoseChannel_scale_editable"); + RNA_def_property_float_array_default(prop, default_scale); RNA_def_property_ui_text(prop, "Scale", ""); RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); // XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 6c6a5b2c0cb..c5f31590029 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -354,12 +354,12 @@ static void rna_Scene_active_keying_set_index_range(PointerRNA *ptr, int *min, i } -static char *rna_SceneRenderData_path(PointerRNA *ptr) +static char *rna_RenderSettings_path(PointerRNA *ptr) { - return BLI_sprintfN("render_data"); + return BLI_sprintfN("render"); } -static int rna_SceneRenderData_threads_get(PointerRNA *ptr) +static int rna_RenderSettings_threads_get(PointerRNA *ptr) { RenderData *rd= (RenderData*)ptr->data; @@ -369,7 +369,7 @@ static int rna_SceneRenderData_threads_get(PointerRNA *ptr) return BLI_system_thread_count(); } -static int rna_SceneRenderData_save_buffers_get(PointerRNA *ptr) +static int rna_RenderSettings_save_buffers_get(PointerRNA *ptr) { RenderData *rd= (RenderData*)ptr->data; if(rd->mode & R_BORDER) @@ -378,14 +378,14 @@ static int rna_SceneRenderData_save_buffers_get(PointerRNA *ptr) return (rd->scemode & (R_EXR_TILE_FILE|R_FULL_SAMPLE)) != 0; } -static int rna_SceneRenderData_full_sample_get(PointerRNA *ptr) +static int rna_RenderSettings_full_sample_get(PointerRNA *ptr) { RenderData *rd= (RenderData*)ptr->data; return (rd->scemode & R_FULL_SAMPLE) && !(rd->mode & R_BORDER); } -static void rna_SceneRenderData_file_format_set(PointerRNA *ptr, int value) +static void rna_RenderSettings_file_format_set(PointerRNA *ptr, int value) { RenderData *rd= (RenderData*)ptr->data; @@ -413,7 +413,7 @@ static void rna_SceneRender_file_ext_get(PointerRNA *ptr, char *str) BKE_add_image_extension(str, rd->imtype); } -void rna_SceneRenderData_jpeg2k_preset_update(RenderData *rd) +void rna_RenderSettings_jpeg2k_preset_update(RenderData *rd) { rd->subimtype &= ~(R_JPEG2K_12BIT|R_JPEG2K_16BIT | R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS); @@ -435,37 +435,37 @@ void rna_SceneRenderData_jpeg2k_preset_update(RenderData *rd) } #ifdef WITH_OPENJPEG -static void rna_SceneRenderData_jpeg2k_preset_set(PointerRNA *ptr, int value) +static void rna_RenderSettings_jpeg2k_preset_set(PointerRNA *ptr, int value) { RenderData *rd= (RenderData*)ptr->data; rd->jp2_preset= value; - rna_SceneRenderData_jpeg2k_preset_update(rd); + rna_RenderSettings_jpeg2k_preset_update(rd); } -static void rna_SceneRenderData_jpeg2k_depth_set(PointerRNA *ptr, int value) +static void rna_RenderSettings_jpeg2k_depth_set(PointerRNA *ptr, int value) { RenderData *rd= (RenderData*)ptr->data; rd->jp2_depth= value; - rna_SceneRenderData_jpeg2k_preset_update(rd); + rna_RenderSettings_jpeg2k_preset_update(rd); } #endif #ifdef WITH_QUICKTIME -static int rna_SceneRenderData_qtcodecsettings_codecType_get(PointerRNA *ptr) +static int rna_RenderSettings_qtcodecsettings_codecType_get(PointerRNA *ptr) { RenderData *rd= (RenderData*)ptr->data; return quicktime_rnatmpvalue_from_codectype(rd->qtcodecsettings.codecType); } -static void rna_SceneRenderData_qtcodecsettings_codecType_set(PointerRNA *ptr, int value) +static void rna_RenderSettings_qtcodecsettings_codecType_set(PointerRNA *ptr, int value) { RenderData *rd= (RenderData*)ptr->data; rd->qtcodecsettings.codecType = quicktime_codecType_from_rnatmpvalue(value); } -static EnumPropertyItem *rna_SceneRenderData_qtcodecsettings_codecType_itemf(bContext *C, PointerRNA *ptr, int *free) +static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bContext *C, PointerRNA *ptr, int *free) { EnumPropertyItem *item= NULL; EnumPropertyItem tmp = {0, "", 0, "", ""}; @@ -492,19 +492,19 @@ static EnumPropertyItem *rna_SceneRenderData_qtcodecsettings_codecType_itemf(bCo } #endif -static int rna_SceneRenderData_active_layer_index_get(PointerRNA *ptr) +static int rna_RenderSettings_active_layer_index_get(PointerRNA *ptr) { RenderData *rd= (RenderData*)ptr->data; return rd->actlay; } -static void rna_SceneRenderData_active_layer_index_set(PointerRNA *ptr, int value) +static void rna_RenderSettings_active_layer_index_set(PointerRNA *ptr, int value) { RenderData *rd= (RenderData*)ptr->data; rd->actlay= value; } -static void rna_SceneRenderData_active_layer_index_range(PointerRNA *ptr, int *min, int *max) +static void rna_RenderSettings_active_layer_index_range(PointerRNA *ptr, int *min, int *max) { RenderData *rd= (RenderData*)ptr->data; @@ -513,7 +513,7 @@ static void rna_SceneRenderData_active_layer_index_range(PointerRNA *ptr, int *m *max= MAX2(0, *max); } -static void rna_SceneRenderData_engine_set(PointerRNA *ptr, int value) +static void rna_RenderSettings_engine_set(PointerRNA *ptr, int value) { RenderData *rd= (RenderData*)ptr->data; RenderEngineType *type= BLI_findlink(&R_engines, value); @@ -522,7 +522,7 @@ static void rna_SceneRenderData_engine_set(PointerRNA *ptr, int value) BLI_strncpy(rd->engine, type->idname, sizeof(rd->engine)); } -static EnumPropertyItem *rna_SceneRenderData_engine_itemf(bContext *C, PointerRNA *ptr, int *free) +static EnumPropertyItem *rna_RenderSettings_engine_itemf(bContext *C, PointerRNA *ptr, int *free) { RenderEngineType *type; EnumPropertyItem *item= NULL; @@ -542,7 +542,7 @@ static EnumPropertyItem *rna_SceneRenderData_engine_itemf(bContext *C, PointerRN return item; } -static int rna_SceneRenderData_engine_get(PointerRNA *ptr) +static int rna_RenderSettings_engine_get(PointerRNA *ptr) { RenderData *rd= (RenderData*)ptr->data; RenderEngineType *type; @@ -555,7 +555,7 @@ static int rna_SceneRenderData_engine_get(PointerRNA *ptr) return 0; } -static void rna_SceneRenderData_color_management_update(Main *bmain, Scene *unused, PointerRNA *ptr) +static void rna_RenderSettings_color_management_update(Main *bmain, Scene *unused, PointerRNA *ptr) { /* reset image nodes */ Scene *scene= (Scene*)ptr->id.data; @@ -595,12 +595,12 @@ static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value) } } -static int rna_SceneRenderData_multiple_engines_get(PointerRNA *ptr) +static int rna_RenderSettings_multiple_engines_get(PointerRNA *ptr) { return (BLI_countlist(&R_engines) > 1); } -static int rna_SceneRenderData_use_game_engine_get(PointerRNA *ptr) +static int rna_RenderSettings_use_game_engine_get(PointerRNA *ptr) { RenderData *rd= (RenderData*)ptr->data; RenderEngineType *type; @@ -1563,51 +1563,46 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop= RNA_def_property(srna, "use_occlusion_culling", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", (1 << 5)); //XXX mode hardcoded // WO_DBVT_CULLING RNA_def_property_ui_text(prop, "DBVT culling", "Use optimized Bullet DBVT tree for view frustrum and occlusion culling"); - RNA_def_property_update(prop, NC_SCENE, NULL); // not used // deprecated !!!!!!!!!!!!! prop= RNA_def_property(srna, "activity_culling", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", (1 << 3)); //XXX mode hardcoded RNA_def_property_ui_text(prop, "Activity Culling", "Activity culling is enabled"); - RNA_def_property_update(prop, NC_SCENE, NULL); // not used // deprecated !!!!!!!!!!!!! prop= RNA_def_property(srna, "activity_culling_box_radius", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "activityBoxRadius"); RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "box radius", "Radius of the activity bubble, in Manhattan length. Objects outside the box are activity-culled"); - RNA_def_property_update(prop, NC_SCENE, NULL); /* booleans */ - prop= RNA_def_property(srna, "all_frames", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GAME_ENABLE_ALL_FRAMES); - RNA_def_property_ui_text(prop, "All Frames", "Render as many frames as possible, rather than respecting framerate"); - RNA_def_property_update(prop, NC_SCENE, NULL); - prop= RNA_def_property(srna, "show_debug_properties", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GAME_SHOW_DEBUG_PROPS); RNA_def_property_ui_text(prop, "Show Debug Properties", "Show properties marked for debugging while the game runs"); - RNA_def_property_update(prop, NC_SCENE, NULL); prop= RNA_def_property(srna, "show_framerate_profile", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GAME_SHOW_FRAMERATE); RNA_def_property_ui_text(prop, "Show Framerate and Profile", "Show framerate and profiling information while the game runs"); - RNA_def_property_update(prop, NC_SCENE, NULL); prop= RNA_def_property(srna, "show_physics_visualization", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GAME_SHOW_PHYSICS); RNA_def_property_ui_text(prop, "Show Physics Visualization", "Show a visualization of physics bounds and interactions"); - RNA_def_property_update(prop, NC_SCENE, NULL); - prop= RNA_def_property(srna, "display_lists", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_frame_rate", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GAME_ENABLE_ALL_FRAMES); + RNA_def_property_ui_text(prop, "Use Frame Rate", "Respect the frame rate rather then rendering as many frames as possible"); + + prop= RNA_def_property(srna, "use_display_lists", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GAME_DISPLAY_LISTS); RNA_def_property_ui_text(prop, "Display Lists", "Use display lists to speed up rendering by keeping geometry on the GPU"); - RNA_def_property_update(prop, NC_SCENE, NULL); - prop= RNA_def_property(srna, "deprecation_warnings", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_deprecation_warnings", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GAME_IGNORE_DEPRECATION_WARNINGS); RNA_def_property_ui_text(prop, "Deprecation Warnings", "Print warnings when using deprecated features in the python API"); - RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "use_animation_record", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GAME_ENABLE_ANIMATION_RECORD); + RNA_def_property_ui_text(prop, "Record Animation", "Record animation to fcurves"); /* materials */ prop= RNA_def_property(srna, "material_mode", PROP_ENUM, PROP_NONE); @@ -1894,10 +1889,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {0, "BLENDER_RENDER", 0, "Blender Render", ""}, {0, NULL, 0, NULL, NULL}}; - srna= RNA_def_struct(brna, "SceneRenderData", NULL); + srna= RNA_def_struct(brna, "RenderSettings", NULL); RNA_def_struct_sdna(srna, "RenderData"); RNA_def_struct_nested(brna, srna, "Scene"); - RNA_def_struct_path_func(srna, "rna_SceneRenderData_path"); + RNA_def_struct_path_func(srna, "rna_RenderSettings_path"); RNA_def_struct_ui_text(srna, "Render Data", "Rendering settings for a Scene datablock"); prop= RNA_def_property(srna, "color_mode", PROP_ENUM, PROP_NONE); @@ -2019,14 +2014,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "jpeg2k_preset", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "jp2_preset"); RNA_def_property_enum_items(prop, jp2_preset_items); - RNA_def_property_enum_funcs(prop, NULL, "rna_SceneRenderData_jpeg2k_preset_set", NULL); + RNA_def_property_enum_funcs(prop, NULL, "rna_RenderSettings_jpeg2k_preset_set", NULL); RNA_def_property_ui_text(prop, "Preset", "Use a DCI Standard preset for saving jpeg2000"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "jpeg2k_depth", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "jp2_depth"); RNA_def_property_enum_items(prop, jp2_depth_items); - RNA_def_property_enum_funcs(prop, NULL, "rna_SceneRenderData_jpeg2k_depth_set", NULL); + RNA_def_property_enum_funcs(prop, NULL, "rna_RenderSettings_jpeg2k_depth_set", NULL); RNA_def_property_ui_text(prop, "Depth", "Bit depth per channel"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); @@ -2042,9 +2037,9 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "quicktime_codec_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "qtcodecsettings.codecType"); RNA_def_property_enum_items(prop, quicktime_codec_type_items); - RNA_def_property_enum_funcs(prop, "rna_SceneRenderData_qtcodecsettings_codecType_get", - "rna_SceneRenderData_qtcodecsettings_codecType_set", - "rna_SceneRenderData_qtcodecsettings_codecType_itemf"); + RNA_def_property_enum_funcs(prop, "rna_RenderSettings_qtcodecsettings_codecType_get", + "rna_RenderSettings_qtcodecsettings_codecType_set", + "rna_RenderSettings_qtcodecsettings_codecType_itemf"); RNA_def_property_ui_text(prop, "Codec", "QuickTime codec type"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); @@ -2286,7 +2281,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "threads", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "threads"); RNA_def_property_range(prop, 1, BLENDER_MAX_THREADS); - RNA_def_property_int_funcs(prop, "rna_SceneRenderData_threads_get", NULL, NULL); + RNA_def_property_int_funcs(prop, "rna_RenderSettings_threads_get", NULL, NULL); RNA_def_property_ui_text(prop, "Threads", "Number of CPU threads to use simultaneously while rendering (for multi-core/CPU systems)"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); @@ -2364,7 +2359,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "color_management", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "color_mgt_flag", R_COLOR_MANAGEMENT); RNA_def_property_ui_text(prop, "Color Management", "Use color profiles and gamma corrected imaging pipeline"); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_MATERIAL|ND_SHADING, "rna_SceneRenderData_color_management_update"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_MATERIAL|ND_SHADING, "rna_RenderSettings_color_management_update"); prop= RNA_def_property(srna, "use_file_extension", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_EXTENSION); @@ -2374,7 +2369,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "file_format", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "imtype"); RNA_def_property_enum_items(prop, image_type_items); - RNA_def_property_enum_funcs(prop, NULL, "rna_SceneRenderData_file_format_set", NULL); + RNA_def_property_enum_funcs(prop, NULL, "rna_RenderSettings_file_format_set", NULL); RNA_def_property_ui_text(prop, "File Format", "File format to save the rendered images as"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); @@ -2396,13 +2391,13 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "save_buffers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_EXR_TILE_FILE); - RNA_def_property_boolean_funcs(prop, "rna_SceneRenderData_save_buffers_get", NULL); + RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_save_buffers_get", NULL); RNA_def_property_ui_text(prop, "Save Buffers","Save tiles for all RenderLayers and SceneNodes to files in the temp directory (saves memory, required for Full Sample)"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "full_sample", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_FULL_SAMPLE); - RNA_def_property_boolean_funcs(prop, "rna_SceneRenderData_full_sample_get", NULL); + RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_full_sample_get", NULL); RNA_def_property_ui_text(prop, "Full Sample","Save for every anti-aliasing sample the entire RenderLayer results. This solves anti-aliasing issues with compositing"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); @@ -2570,24 +2565,24 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "active_layer_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "actlay"); - RNA_def_property_int_funcs(prop, "rna_SceneRenderData_active_layer_index_get", "rna_SceneRenderData_active_layer_index_set", "rna_SceneRenderData_active_layer_index_range"); + RNA_def_property_int_funcs(prop, "rna_RenderSettings_active_layer_index_get", "rna_RenderSettings_active_layer_index_set", "rna_RenderSettings_active_layer_index_range"); RNA_def_property_ui_text(prop, "Active Layer Index", "Active index in render layer array"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); /* engine */ prop= RNA_def_property(srna, "engine", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, engine_items); - RNA_def_property_enum_funcs(prop, "rna_SceneRenderData_engine_get", "rna_SceneRenderData_engine_set", "rna_SceneRenderData_engine_itemf"); + RNA_def_property_enum_funcs(prop, "rna_RenderSettings_engine_get", "rna_RenderSettings_engine_set", "rna_RenderSettings_engine_itemf"); RNA_def_property_ui_text(prop, "Engine", "Engine to use for rendering"); RNA_def_property_update(prop, NC_WINDOW, NULL); prop= RNA_def_property(srna, "multiple_engines", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_funcs(prop, "rna_SceneRenderData_multiple_engines_get", NULL); + RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_multiple_engines_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Multiple Engines", "More than one rendering engine is available"); prop= RNA_def_property(srna, "use_game_engine", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_funcs(prop, "rna_SceneRenderData_use_game_engine_get", NULL); + RNA_def_property_boolean_funcs(prop, "rna_RenderSettings_use_game_engine_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Use Game Engine", "Current rendering engine is a game engine"); @@ -2779,7 +2774,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_int_funcs(prop, NULL, "rna_Scene_start_frame_set", NULL); RNA_def_property_range(prop, MINFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "Start Frame", "First frame of the playback/rendering range"); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_FRAME, NULL); prop= RNA_def_property(srna, "end_frame", PROP_INT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -2787,15 +2782,15 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_int_funcs(prop, NULL, "rna_Scene_end_frame_set", NULL); RNA_def_property_range(prop, MINFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "End Frame", "Final frame of the playback/rendering range"); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_FRAME, NULL); prop= RNA_def_property(srna, "frame_step", PROP_INT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "r.frame_step"); RNA_def_property_range(prop, 0, MAXFRAME); - RNA_def_property_ui_range(prop, 0, 100, 1, 0); + RNA_def_property_ui_range(prop, 1, 100, 1, 0); RNA_def_property_ui_text(prop, "Frame Step", "Number of frames to skip forward while rendering/playing back each frame"); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_FRAME, NULL); /* Preview Range (frame-range for UI playback) */ prop=RNA_def_property(srna, "use_preview_range", PROP_BOOLEAN, PROP_NONE); @@ -2803,21 +2798,21 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "r.flag", SCER_PRV_RANGE); RNA_def_property_boolean_funcs(prop, NULL, "rna_Scene_use_preview_range_set"); RNA_def_property_ui_text(prop, "Use Preview Range", ""); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_FRAME, NULL); prop= RNA_def_property(srna, "preview_range_start_frame", PROP_INT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "r.psfra"); RNA_def_property_int_funcs(prop, NULL, "rna_Scene_preview_range_start_frame_set", NULL); RNA_def_property_ui_text(prop, "Preview Range Start Frame", ""); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_FRAME, NULL); prop= RNA_def_property(srna, "preview_range_end_frame", PROP_INT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "r.pefra"); RNA_def_property_int_funcs(prop, NULL, "rna_Scene_preview_range_end_frame_set", NULL); RNA_def_property_ui_text(prop, "Preview Range End Frame", ""); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_FRAME, NULL); /* Stamp */ prop= RNA_def_property(srna, "stamp_note", PROP_STRING, PROP_NONE); @@ -2913,10 +2908,10 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Physics_update"); /* Render Data */ - prop= RNA_def_property(srna, "render_data", PROP_POINTER, PROP_NONE); + prop= RNA_def_property(srna, "render", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "r"); - RNA_def_property_struct_type(prop, "SceneRenderData"); + RNA_def_property_struct_type(prop, "RenderSettings"); RNA_def_property_ui_text(prop, "Render Data", ""); /* Markers */ diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index ee2c96bcbd2..6f6ee5216ae 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -47,6 +47,7 @@ #include "BKE_depsgraph.h" #include "DNA_object_types.h" #include "GPU_draw.h" +#include "BKE_global.h" #include "MEM_guardedalloc.h" @@ -55,6 +56,13 @@ static void rna_userdef_update(Main *bmain, Scene *scene, PointerRNA *ptr) WM_main_add_notifier(NC_WINDOW, NULL); } +static void rna_userdef_script_autoexec_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + UserDef *userdef = (UserDef*)ptr->data; + if (userdef->flag & USER_SCRIPT_AUTOEXEC_DISABLE) G.f &= ~G_SCRIPT_AUTOEXEC; + else G.f |= G_SCRIPT_AUTOEXEC; +} + static void rna_userdef_mipmap_update(Main *bmain, Scene *scene, PointerRNA *ptr) { GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); @@ -211,16 +219,16 @@ static void rna_userdef_autosave_update(Main *bmain, Scene *scene, PointerRNA *p rna_userdef_update(bmain, scene, ptr); } -static bExtension *rna_userdef_extension_new(void) +static bAddon *rna_userdef_addon_new(void) { - bExtension *bext= MEM_callocN(sizeof(bExtension), "bext"); - BLI_addtail(&U.extensions, bext); + bAddon *bext= MEM_callocN(sizeof(bAddon), "bAddon"); + BLI_addtail(&U.addons, bext); return bext; } -static void rna_userdef_extension_remove(bExtension *bext) +static void rna_userdef_addon_remove(bAddon *bext) { - BLI_freelinkN(&U.extensions, bext); + BLI_freelinkN(&U.addons, bext); } @@ -1687,14 +1695,14 @@ static void rna_def_userdef_themes(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Bone Color Sets", ""); } -static void rna_def_userdef_extensions(BlenderRNA *brna) +static void rna_def_userdef_addon(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - srna= RNA_def_struct(brna, "Extension", NULL); - RNA_def_struct_sdna(srna, "bExtension"); - RNA_def_struct_ui_text(srna, "Extension", "Python extensions to be loaded automatically"); + srna= RNA_def_struct(brna, "Addon", NULL); + RNA_def_struct_sdna(srna, "bAddon"); + RNA_def_struct_ui_text(srna, "Addon", "Python addons to be loaded automatically"); prop= RNA_def_property(srna, "module", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Module", "Module name"); @@ -1727,7 +1735,6 @@ static void rna_def_userdef_dothemes(BlenderRNA *brna) rna_def_userdef_theme_space_logic(brna); rna_def_userdef_theme_colorset(brna); rna_def_userdef_themes(brna); - rna_def_userdef_extensions(brna); } static void rna_def_userdef_solidlight(BlenderRNA *brna) @@ -2346,9 +2353,10 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ALLWINCODECS); RNA_def_property_ui_text(prop, "Enable All Codecs", "Enables automatic saving of preview images in the .blend file (Windows only)"); - prop= RNA_def_property(srna, "auto_run_python_scripts", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_DONT_DOSCRIPTLINKS); + prop= RNA_def_property(srna, "auto_execute_scripts", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_SCRIPT_AUTOEXEC_DISABLE); RNA_def_property_ui_text(prop, "Auto Run Python Scripts", "Allow any .blend file to run scripts automatically (unsafe with blend files from an untrusted source)"); + RNA_def_property_update(prop, 0, "rna_userdef_script_autoexec_update"); prop= RNA_def_property(srna, "prefetch_frames", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "prefetchframes"); @@ -2649,27 +2657,27 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Save Preview Images", "Enables automatic saving of preview images in the .blend file"); } -void rna_def_userdef_extension_collection(BlenderRNA *brna, PropertyRNA *cprop) +void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; FunctionRNA *func; PropertyRNA *parm; - RNA_def_property_srna(cprop, "UserExtensions"); - srna= RNA_def_struct(brna, "UserExtensions", NULL); - RNA_def_struct_ui_text(srna, "User Extensions", "Collection of extensions"); + RNA_def_property_srna(cprop, "Addons"); + srna= RNA_def_struct(brna, "Addons", NULL); + RNA_def_struct_ui_text(srna, "User Add-Ons", "Collection of add-ons"); - func= RNA_def_function(srna, "new", "rna_userdef_extension_new"); + func= RNA_def_function(srna, "new", "rna_userdef_addon_new"); RNA_def_function_flag(func, FUNC_NO_SELF); - RNA_def_function_ui_description(func, "Add a new camera to the main database"); + RNA_def_function_ui_description(func, "Add a new addon"); /* return type */ - parm= RNA_def_pointer(func, "extension", "Extension", "", "Extension datablock."); + parm= RNA_def_pointer(func, "addon", "Addon", "", "Addon datablock."); RNA_def_function_return(func, parm); - func= RNA_def_function(srna, "remove", "rna_userdef_extension_remove"); + func= RNA_def_function(srna, "remove", "rna_userdef_addon_remove"); RNA_def_function_flag(func, FUNC_NO_SELF); - RNA_def_function_ui_description(func, "Remove a camera from the current blendfile."); - parm= RNA_def_pointer(func, "extension", "Extension", "", "Extension to remove."); + RNA_def_function_ui_description(func, "Remove addon."); + parm= RNA_def_pointer(func, "addon", "Addon", "", "Addon to remove."); RNA_def_property_flag(parm, PROP_REQUIRED); } @@ -2682,7 +2690,7 @@ void RNA_def_userdef(BlenderRNA *brna) {USER_SECTION_INTERFACE, "INTERFACE", 0, "Interface", ""}, {USER_SECTION_EDIT, "EDITING", 0, "Editing", ""}, {USER_SECTION_INPUT, "INPUT", 0, "Input", ""}, - {USER_SECTION_EXTENSIONS, "EXTENSIONS", 0, "Extensions", ""}, + {USER_SECTION_ADDONS, "ADDONS", 0, "Add-Ons", ""}, {USER_SECTION_THEME, "THEMES", 0, "Themes", ""}, {USER_SECTION_FILE, "FILES", 0, "File", ""}, {USER_SECTION_SYSTEM, "SYSTEM", 0, "System", ""}, @@ -2711,11 +2719,11 @@ void RNA_def_userdef(BlenderRNA *brna) RNA_def_property_struct_type(prop, "ThemeStyle"); RNA_def_property_ui_text(prop, "Styles", ""); - prop= RNA_def_property(srna, "extensions", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "extensions", NULL); - RNA_def_property_struct_type(prop, "Extension"); - RNA_def_property_ui_text(prop, "Extension", ""); - rna_def_userdef_extension_collection(brna, prop); + prop= RNA_def_property(srna, "addons", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "addons", NULL); + RNA_def_property_struct_type(prop, "Addon"); + RNA_def_property_ui_text(prop, "Addon", ""); + rna_def_userdef_addon_collection(brna, prop); /* nested structs */ @@ -2754,6 +2762,7 @@ void RNA_def_userdef(BlenderRNA *brna) rna_def_userdef_input(brna); rna_def_userdef_filepaths(brna); rna_def_userdef_system(brna); + rna_def_userdef_addon(brna); } diff --git a/source/blender/python/generic/BGL.c b/source/blender/python/generic/BGL.c index 2318549f2ec..340ebbe3dcd 100644 --- a/source/blender/python/generic/BGL.c +++ b/source/blender/python/generic/BGL.c @@ -36,9 +36,6 @@ #include <GL/glew.h> #include "MEM_guardedalloc.h" -static int type_size( int type ); -static Buffer *make_buffer( int type, int ndimensions, int *dimensions ); - static char Method_Buffer_doc[] = "(type, dimensions, [template]) - Create a new Buffer object\n\n\ (type) - The format to store data in\n\ @@ -82,7 +79,7 @@ static PyObject *Buffer_dimensions( PyObject * self ); static PyObject *Buffer_getattr( PyObject * self, char *name ); static PyObject *Buffer_repr( PyObject * self ); -PyTypeObject buffer_Type = { +PyTypeObject BGL_bufferType = { PyVarObject_HEAD_INIT(NULL, 0) "buffer", /*tp_name */ sizeof( Buffer ), /*tp_basicsize */ @@ -120,7 +117,7 @@ static PyObject *Method_##funcname (PyObject *self, PyObject *args) {\ /* #endif */ /********/ -static int type_size(int type) +int BGL_typeSize(int type) { switch (type) { case GL_BYTE: @@ -137,7 +134,7 @@ static int type_size(int type) return -1; } -static Buffer *make_buffer(int type, int ndimensions, int *dimensions) +Buffer *BGL_MakeBuffer(int type, int ndimensions, int *dimensions, void *initbuffer) { Buffer *buffer; void *buf= NULL; @@ -147,39 +144,49 @@ static Buffer *make_buffer(int type, int ndimensions, int *dimensions) for (i=0; i<ndimensions; i++) length*= dimensions[i]; - size= type_size(type); + size= BGL_typeSize(type); buf= MEM_mallocN(length*size, "Buffer buffer"); - - buffer= (Buffer *) PyObject_NEW(Buffer, &buffer_Type); + + buffer= (Buffer *) PyObject_NEW(Buffer, &BGL_bufferType); buffer->parent= NULL; buffer->ndimensions= ndimensions; - buffer->dimensions= dimensions; + buffer->dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions"); + memcpy(buffer->dimensions, dimensions, ndimensions*sizeof(int)); buffer->type= type; buffer->buf.asvoid= buf; - for (i= 0; i<length; i++) { - if (type==GL_BYTE) - buffer->buf.asbyte[i]= 0; - else if (type==GL_SHORT) - buffer->buf.asshort[i]= 0; - else if (type==GL_INT) - buffer->buf.asint[i]= 0; - else if (type==GL_FLOAT) - buffer->buf.asfloat[i]= 0.0f; - else if (type==GL_DOUBLE) - buffer->buf.asdouble[i]= 0.0; + if (initbuffer) { + memcpy(buffer->buf.asvoid, initbuffer, length*size); + } else { + memset(buffer->buf.asvoid, 0, length*size); + /* + for (i= 0; i<length; i++) { + if (type==GL_BYTE) + buffer->buf.asbyte[i]= 0; + else if (type==GL_SHORT) + buffer->buf.asshort[i]= 0; + else if (type==GL_INT) + buffer->buf.asint[i]= 0; + else if (type==GL_FLOAT) + buffer->buf.asfloat[i]= 0.0f; + else if (type==GL_DOUBLE) + buffer->buf.asdouble[i]= 0.0; + } + */ } return buffer; } +#define MAX_DIMENSIONS 256 static PyObject *Method_Buffer (PyObject *self, PyObject *args) { PyObject *length_ob= NULL, *template= NULL; Buffer *buffer; + int dimensions[MAX_DIMENSIONS]; int i, type; - int *dimensions = 0, ndimensions = 0; + int ndimensions = 0; if (!PyArg_ParseTuple(args, "iO|O", &type, &length_ob, &template)) { PyErr_SetString(PyExc_AttributeError, "expected an int and one or two PyObjects"); @@ -192,11 +199,13 @@ static PyObject *Method_Buffer (PyObject *self, PyObject *args) if (PyNumber_Check(length_ob)) { ndimensions= 1; - dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions"); dimensions[0]= PyLong_AsLong(length_ob); } else if (PySequence_Check(length_ob)) { ndimensions= PySequence_Length(length_ob); - dimensions= MEM_mallocN(ndimensions*sizeof(int), "Buffer dimensions"); + if (ndimensions > MAX_DIMENSIONS) { + PyErr_SetString(PyExc_AttributeError, "too many dimensions, max is 256"); + return NULL; + } for (i=0; i<ndimensions; i++) { PyObject *ob= PySequence_GetItem(length_ob, i); @@ -206,7 +215,7 @@ static PyObject *Method_Buffer (PyObject *self, PyObject *args) } } - buffer= make_buffer(type, ndimensions, dimensions); + buffer= BGL_MakeBuffer(type, ndimensions, dimensions, NULL); if (template && ndimensions) { if (Buffer_ass_slice((PyObject *) buffer, 0, dimensions[0], template)) { Py_DECREF(buffer); @@ -250,9 +259,9 @@ static PyObject *Buffer_item(PyObject *self, int i) for (j=1; j<buf->ndimensions; j++) { length*= buf->dimensions[j]; } - size= type_size(buf->type); + size= BGL_typeSize(buf->type); - newbuf= (Buffer *) PyObject_NEW(Buffer, &buffer_Type); + newbuf= (Buffer *) PyObject_NEW(Buffer, &BGL_bufferType); Py_INCREF(self); newbuf->parent= self; @@ -1104,7 +1113,7 @@ PyObject *BGL_Init(void) PyDict_SetItemString(PySys_GetObject("modules"), BGL_module_def.m_name, mod); dict= PyModule_GetDict(mod); - if( PyType_Ready( &buffer_Type) < 0) + if( PyType_Ready( &BGL_bufferType) < 0) return NULL; /* should never happen */ #define EXPP_ADDCONST(x) PyDict_SetItemString(dict, #x, item=PyLong_FromLong((int)x)); Py_DECREF(item) diff --git a/source/blender/python/generic/BGL.h b/source/blender/python/generic/BGL.h index 32076f4fba8..89bade930ce 100644 --- a/source/blender/python/generic/BGL.h +++ b/source/blender/python/generic/BGL.h @@ -44,9 +44,16 @@ PyObject *BGL_Init(void); +/*@ Create a buffer object */ +/*@ dimensions is an array of ndimensions integers representing the size of each dimension */ +/*@ initbuffer if not NULL holds a contiguous buffer with the correct format from which the buffer will be initialized */ +struct _Buffer *BGL_MakeBuffer( int type, int ndimensions, int *dimensions, void *initbuffer ); +/*@ Return the size of buffer element, type must be one of GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT or GL_DOUBLE */ +/*@ returns -1 otherwise */ +int BGL_typeSize( int type ); + /*@ Buffer Object */ /*@ For Python access to OpenGL functions requiring a pointer. */ - typedef struct _Buffer { PyObject_VAR_HEAD PyObject * parent; @@ -66,6 +73,8 @@ typedef struct _Buffer { } buf; } Buffer; +/*@ The type object */ +extern PyTypeObject BGL_bufferType; /*@ By golly George! It looks like fancy pants macro time!!! */ @@ -93,7 +102,7 @@ typedef struct _Buffer { #define buffer_str "O!" #define buffer_var(number) (bgl_buffer##number)->buf.asvoid -#define buffer_ref(number) &buffer_Type, &bgl_buffer##number +#define buffer_ref(number) &BGL_bufferType, &bgl_buffer##number #define buffer_def(number) Buffer *bgl_buffer##number /* GL Pointer fields, handled by buffer type */ @@ -101,62 +110,62 @@ typedef struct _Buffer { #define GLbooleanP_str "O!" #define GLbooleanP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLbooleanP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLbooleanP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLbooleanP_def(number) Buffer *bgl_buffer##number #define GLbyteP_str "O!" #define GLbyteP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLbyteP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLbyteP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLbyteP_def(number) Buffer *bgl_buffer##number #define GLubyteP_str "O!" #define GLubyteP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLubyteP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLubyteP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLubyteP_def(number) Buffer *bgl_buffer##number #define GLintP_str "O!" #define GLintP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLintP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLintP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLintP_def(number) Buffer *bgl_buffer##number #define GLuintP_str "O!" #define GLuintP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLuintP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLuintP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLuintP_def(number) Buffer *bgl_buffer##number #define GLshortP_str "O!" #define GLshortP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLshortP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLshortP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLshortP_def(number) Buffer *bgl_buffer##number #define GLushortP_str "O!" #define GLushortP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLushortP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLushortP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLushortP_def(number) Buffer *bgl_buffer##number #define GLfloatP_str "O!" #define GLfloatP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLfloatP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLfloatP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLfloatP_def(number) Buffer *bgl_buffer##number #define GLdoubleP_str "O!" #define GLdoubleP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLdoubleP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLdoubleP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLdoubleP_def(number) Buffer *bgl_buffer##number #define GLclampfP_str "O!" #define GLclampfP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLclampfP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLclampfP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLclampfP_def(number) Buffer *bgl_buffer##number #define GLvoidP_str "O!" #define GLvoidP_var(number) (bgl_buffer##number)->buf.asvoid -#define GLvoidP_ref(number) &buffer_Type, &bgl_buffer##number +#define GLvoidP_ref(number) &BGL_bufferType, &bgl_buffer##number #define GLvoidP_def(number) Buffer *bgl_buffer##number #define buffer_str "O!" #define buffer_var(number) (bgl_buffer##number)->buf.asvoid -#define buffer_ref(number) &buffer_Type, &bgl_buffer##number +#define buffer_ref(number) &BGL_bufferType, &bgl_buffer##number #define buffer_def(number) Buffer *bgl_buffer##number /*@The standard GL typedefs are used as prototypes, we can't diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c index a20ed3e4f59..0b0b1470823 100644 --- a/source/blender/python/generic/matrix.c +++ b/source/blender/python/generic/matrix.c @@ -194,7 +194,7 @@ static float matrix_determinant(MatrixObject * self) self->matrix[2][0], self->matrix[2][1], self->matrix[2][2]); } else { - return determinant_m4((float (*)[4]) *self->matrix); + return determinant_m4((float (*)[4])self->contigPtr); } } @@ -221,9 +221,9 @@ static PyObject *Matrix_toQuat(MatrixObject * self) return NULL; } if(self->colSize == 3){ - mat3_to_quat( quat,(float (*)[3])*self->matrix); + mat3_to_quat( quat,(float (*)[3])self->contigPtr); }else{ - mat4_to_quat( quat,(float (*)[4])*self->matrix); + mat4_to_quat( quat,(float (*)[4])self->contigPtr); } return newQuaternionObject(quat, Py_NEW, NULL); @@ -267,9 +267,9 @@ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args) /*must be 3-4 cols, 3-4 rows, square matrix*/ if(self->colSize ==3 && self->rowSize ==3) { - mat= (float (*)[3]) *self->matrix; + mat= (float (*)[3])self->contigPtr; }else if (self->colSize ==4 && self->rowSize ==4) { - copy_m3_m4(tmat, (float (*)[4]) *self->matrix); + copy_m3_m4(tmat, (float (*)[4])self->contigPtr); mat= tmat; }else { PyErr_SetString(PyExc_AttributeError, "Matrix.to_euler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n"); @@ -301,7 +301,7 @@ static char Matrix_Resize4x4_doc[] = " Resize the matrix to 4x4.\n" "\n" " :return: an instance of itself.\n" -" :rtype: :class:`Vector`\n"; +" :rtype: :class:`Matrix`\n"; PyObject *Matrix_Resize4x4(MatrixObject * self) { @@ -359,6 +359,59 @@ PyObject *Matrix_Resize4x4(MatrixObject * self) Py_INCREF(self); return (PyObject *)self; } + +static char Matrix_to_4x4_doc[] = +".. method:: to_4x4()\n" +"\n" +" Return a 4x4 copy of this matrix.\n" +"\n" +" :return: a new matrix.\n" +" :rtype: :class:`Matrix`\n"; +PyObject *Matrix_to_4x4(MatrixObject * self) +{ + if(!BaseMath_ReadCallback(self)) + return NULL; + + if(self->colSize==4 && self->rowSize==4) { + return (PyObject *)newMatrixObject(self->contigPtr, 4, 4, Py_NEW, Py_TYPE(self)); + } + else if(self->colSize==3 && self->rowSize==3) { + float mat[4][4]; + copy_m4_m3(mat, (float (*)[3])self->contigPtr); + return (PyObject *)newMatrixObject((float *)mat, 4, 4, Py_NEW, Py_TYPE(self)); + } + /* TODO, 2x2 matrix */ + + PyErr_SetString(PyExc_TypeError, "Matrix.to_4x4(): inappropriate matrix size"); + return NULL; +} + +static char Matrix_to_3x3_doc[] = +".. method:: to_3x3()\n" +"\n" +" Return a 3x3 copy of this matrix.\n" +"\n" +" :return: a new matrix.\n" +" :rtype: :class:`Matrix`\n"; +PyObject *Matrix_to_3x3(MatrixObject * self) +{ + if(!BaseMath_ReadCallback(self)) + return NULL; + + if(self->colSize==3 && self->rowSize==3) { + return (PyObject *)newMatrixObject(self->contigPtr, 3, 3, Py_NEW, Py_TYPE(self)); + } + else if(self->colSize==4 && self->rowSize==4) { + float mat[3][3]; + copy_m3_m4(mat, (float (*)[4])self->contigPtr); + return (PyObject *)newMatrixObject((float *)mat, 3, 3, Py_NEW, Py_TYPE(self)); + } + /* TODO, 2x2 matrix */ + + PyErr_SetString(PyExc_TypeError, "Matrix.to_3x3(): inappropriate matrix size"); + return NULL; +} + /*---------------------------Matrix.translationPart() ------------*/ static char Matrix_TranslationPart_doc[] = ".. method:: translation_part()\n" @@ -439,9 +492,9 @@ PyObject *Matrix_scalePart(MatrixObject * self) /*must be 3-4 cols, 3-4 rows, square matrix*/ if(self->colSize == 4 && self->rowSize == 4) - copy_m3_m4(mat, (float (*)[4])*self->matrix); + copy_m3_m4(mat, (float (*)[4])self->contigPtr); else if(self->colSize == 3 && self->rowSize == 3) - copy_m3_m3(mat, (float (*)[3])*self->matrix); + copy_m3_m3(mat, (float (*)[3])self->contigPtr); else { PyErr_SetString(PyExc_AttributeError, "Matrix.scale_part(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n"); return NULL; @@ -497,9 +550,9 @@ PyObject *Matrix_Invert(MatrixObject * self) mat[2] = -self->matrix[1][0]; mat[3] = self->matrix[0][0]; } else if(self->rowSize == 3) { - adjoint_m3_m3((float (*)[3]) mat,(float (*)[3]) *self->matrix); + adjoint_m3_m3((float (*)[3]) mat,(float (*)[3])self->contigPtr); } else if(self->rowSize == 4) { - adjoint_m4_m4((float (*)[4]) mat, (float (*)[4]) *self->matrix); + adjoint_m4_m4((float (*)[4]) mat, (float (*)[4])self->contigPtr); } /*divide by determinate*/ for(x = 0; x < (self->rowSize * self->colSize); x++) { @@ -576,9 +629,9 @@ PyObject *Matrix_Transpose(MatrixObject * self) self->matrix[1][0] = self->matrix[0][1]; self->matrix[0][1] = t; } else if(self->rowSize == 3) { - transpose_m3((float (*)[3])*self->matrix); + transpose_m3((float (*)[3])self->contigPtr); } else { - transpose_m4((float (*)[4])*self->matrix); + transpose_m4((float (*)[4])self->contigPtr); } BaseMath_WriteCallback(self); @@ -641,9 +694,9 @@ PyObject *Matrix_Identity(MatrixObject * self) self->matrix[1][0] = 0.0f; self->matrix[1][1] = 1.0f; } else if(self->rowSize == 3) { - unit_m3((float (*)[3]) *self->matrix); + unit_m3((float (*)[3])self->contigPtr); } else { - unit_m4((float (*)[4]) *self->matrix); + unit_m4((float (*)[4])self->contigPtr); } if(!BaseMath_WriteCallback(self)) @@ -667,7 +720,7 @@ PyObject *Matrix_copy(MatrixObject * self) if(!BaseMath_ReadCallback(self)) return NULL; - return (PyObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW, Py_TYPE(self)); + return (PyObject*)newMatrixObject((float (*))self->contigPtr, self->rowSize, self->colSize, Py_NEW, Py_TYPE(self)); } /*----------------------------print object (internal)-------------*/ @@ -1219,9 +1272,9 @@ static PyObject *Matrix_getMedianScale( MatrixObject * self, void *type ) /*must be 3-4 cols, 3-4 rows, square matrix*/ if(self->colSize == 4 && self->rowSize == 4) - copy_m3_m4(mat, (float (*)[4])*self->matrix); + copy_m3_m4(mat, (float (*)[4])self->contigPtr); else if(self->colSize == 3 && self->rowSize == 3) - copy_m3_m3(mat, (float (*)[3])*self->matrix); + copy_m3_m3(mat, (float (*)[3])self->contigPtr); else { PyErr_SetString(PyExc_AttributeError, "Matrix.median_scale: inappropriate matrix size - expects 3x3 or 4x4 matrix\n"); return NULL; @@ -1237,9 +1290,9 @@ static PyObject *Matrix_getIsNegative( MatrixObject * self, void *type ) /*must be 3-4 cols, 3-4 rows, square matrix*/ if(self->colSize == 4 && self->rowSize == 4) - return PyBool_FromLong(is_negative_m4((float (*)[4])*self->matrix)); + return PyBool_FromLong(is_negative_m4((float (*)[4])self->contigPtr)); else if(self->colSize == 3 && self->rowSize == 3) - return PyBool_FromLong(is_negative_m3((float (*)[3])*self->matrix)); + return PyBool_FromLong(is_negative_m3((float (*)[3])self->contigPtr)); else { PyErr_SetString(PyExc_AttributeError, "Matrix.is_negative: inappropriate matrix size - expects 3x3 or 4x4 matrix\n"); return NULL; @@ -1271,6 +1324,8 @@ static struct PyMethodDef Matrix_methods[] = { {"rotation_part", (PyCFunction) Matrix_RotationPart, METH_NOARGS, Matrix_RotationPart_doc}, {"scale_part", (PyCFunction) Matrix_scalePart, METH_NOARGS, Matrix_scalePart_doc}, {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, Matrix_Resize4x4_doc}, + {"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc}, + {"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc}, {"to_euler", (PyCFunction) Matrix_toEuler, METH_VARARGS, Matrix_toEuler_doc}, {"to_quat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc}, {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 356abeeb40f..f628e7e8569 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -30,6 +30,7 @@ #include "BPY_extern.h" #include "BKE_fcurve.h" +#include "BKE_global.h" #include <Python.h> @@ -86,7 +87,7 @@ static int bpy_pydriver_create_dict(void) /* If there's a Blender text called pydrivers.py, import it. * Users can add their own functions to this module. */ - if (G.f & G_DOSCRIPTLINKS) { + if (G.f & G_SCRIPT_AUTOEXEC) { mod = importText("pydrivers"); /* can also use PyImport_Import() */ if (mod) { PyDict_SetItemString(d, "pydrivers", mod); @@ -158,14 +159,18 @@ float BPY_pydriver_eval (ChannelDriver *driver) int i; /* sanity checks - should driver be executed? */ - if ((driver == NULL) /*|| (G.f & G_DOSCRIPTLINKS)==0*/) - return result; + /*if (G.f & G_SCRIPT_AUTOEXEC)==0) return result; */ /* get the py expression to be evaluated */ expr = driver->expression; if ((expr == NULL) || (expr[0]=='\0')) return result; + if(!(G.f & G_SCRIPT_AUTOEXEC)) { + printf("skipping driver '%s', automatic scripts are disabled\n", driver->expression); + return result; + } + gilstate = PyGILState_Ensure(); /* init global dictionary for py-driver evaluation settings */ @@ -207,6 +212,8 @@ float BPY_pydriver_eval (ChannelDriver *driver) for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) { PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_InternFromString(dvar->name)); } + + driver->flag &= ~DRIVER_FLAG_RENAMEVAR; } else { expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1); @@ -253,24 +260,20 @@ float BPY_pydriver_eval (ChannelDriver *driver) /* process the result */ if (retval == NULL) { - result = pydriver_error(driver); - PyGILState_Release(gilstate); - return result; - } + pydriver_error(driver); + result = 0.0f; + } else if((result= (float)PyFloat_AsDouble(retval)) == -1.0f && PyErr_Occurred()) { + pydriver_error(driver); + Py_DECREF(retval); + result = 0.0f; - result = (float)PyFloat_AsDouble(retval); - Py_DECREF(retval); - - if ((result == -1) && PyErr_Occurred()) { - result = pydriver_error(driver); - PyGILState_Release(gilstate); - return result; } - - /* all fine, make sure the "invalid expression" flag is cleared */ - driver->flag &= ~DRIVER_FLAG_INVALID; + else { + /* all fine, make sure the "invalid expression" flag is cleared */ + driver->flag &= ~DRIVER_FLAG_INVALID; + Py_DECREF(retval); + } PyGILState_Release(gilstate); - return result; } diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 0b7c8759b5c..4160d56ba25 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -62,6 +62,7 @@ #include "BKE_text.h" #include "BKE_context.h" #include "BKE_main.h" +#include "BKE_global.h" /* only for script checking */ #include "BPY_extern.h" @@ -556,24 +557,26 @@ int BPY_button_eval(bContext *C, char *expr, double *value) PyObject *dict, *mod, *retval; int error_ret = 0; - if (!value || !expr || expr[0]=='\0') return -1; - + if (!value || !expr) return -1; + + if(expr[0]=='\0') { + *value= 0.0; + return error_ret; + } + bpy_context_set(C, &gilstate); dict= CreateGlobalDictionary(C, NULL); - - /* import some modules: builtins,math*/ - PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()); mod = PyImport_ImportModule("math"); if (mod) { PyDict_Merge(dict, PyModule_GetDict(mod), 0); /* 0 - dont overwrite existing values */ - - /* Only keep for backwards compat! - just import all math into root, they are standard */ - PyDict_SetItemString(dict, "math", mod); - PyDict_SetItemString(dict, "m", mod); Py_DECREF(mod); - } + } + else { /* highly unlikely but possibly */ + PyErr_Print(); + PyErr_Clear(); + } retval = PyRun_String(expr, Py_eval_input, dict, dict); @@ -630,14 +633,19 @@ void BPY_load_user_modules(bContext *C) for(text=CTX_data_main(C)->text.first; text; text= text->id.next) { if(text->flags & TXT_ISSCRIPT && BLI_testextensie(text->id.name+2, ".py")) { - PyObject *module= bpy_text_import(text); - - if (module==NULL) { - PyErr_Print(); - PyErr_Clear(); + if(!(G.f & G_SCRIPT_AUTOEXEC)) { + printf("scripts disabled for \"%s\", skipping '%s'\n", bmain->name, text->id.name+2); } else { - Py_DECREF(module); + PyObject *module= bpy_text_import(text); + + if (module==NULL) { + PyErr_Print(); + PyErr_Clear(); + } + else { + Py_DECREF(module); + } } } } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 691010ade0d..2b31f06f51b 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -26,6 +26,7 @@ #include "bpy_rna.h" #include "bpy_props.h" #include "bpy_util.h" +#include "bpy_rna_callback.h" //#include "blendef.h" #include "BLI_dynstr.h" #include "BLI_listbase.h" @@ -154,6 +155,19 @@ Mathutils_Callback mathutils_rna_matrix_cb = { (BaseMathSetIndexFunc) NULL }; +/* same as RNA_enum_value_from_id but raises an exception */ +int pyrna_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value, const char *error_prefix) +{ + if(RNA_enum_value_from_id(item, identifier, value) == 0) { + char *enum_str= BPy_enum_as_string(item); + PyErr_Format(PyExc_TypeError, "%s: '%.200s' not found in (%s)", error_prefix, identifier, enum_str); + MEM_freeN(enum_str); + return -1; + } + + return 0; +} + #define PROP_ALL_VECTOR_SUBTYPES PROP_TRANSLATION: case PROP_DIRECTION: case PROP_VELOCITY: case PROP_ACCELERATION: case PROP_XYZ: case PROP_XYZ|PROP_UNIT_LENGTH PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) @@ -474,16 +488,11 @@ int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_ char *param= _PyUnicode_AsString(key); if(param==NULL) { - PyErr_Format(PyExc_TypeError, "%s expected a string. found a %.200s", error_prefix, Py_TYPE(key)->tp_name); + PyErr_Format(PyExc_TypeError, "%.200s expected a string. found a %.200s", error_prefix, Py_TYPE(key)->tp_name); return -1; } - - if(RNA_enum_value_from_id(items, param, &ret) == 0) { - char *enum_str= BPy_enum_as_string(items); - PyErr_Format(PyExc_TypeError, "%s \"%.200s\" not found in (%.200s)", error_prefix, param, enum_str); - MEM_freeN(enum_str); + if(pyrna_enum_value_from_id(items, param, &ret, error_prefix) < 0) return -1; - } flag |= ret; } @@ -507,7 +516,7 @@ static int pyrna_prop_to_enum_bitfield(PointerRNA *ptr, PropertyRNA *prop, PyObj } else { if(PySet_GET_SIZE(value)) { - PyErr_Format(PyExc_TypeError, "%s: empty enum \"%.200s\" could not have any values assigned.", error_prefix, RNA_property_identifier(prop)); + PyErr_Format(PyExc_TypeError, "%.200s: empty enum \"%.200s\" could not have any values assigned.", error_prefix, RNA_property_identifier(prop)); ret= -1; } else { @@ -651,7 +660,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) ret = pyrna_prop_CreatePyObject(ptr, prop); break; default: - PyErr_Format(PyExc_TypeError, "RNA Error: unknown type \"%d\" (pyrna_prop_to_py)", type); + PyErr_Format(PyExc_TypeError, "bpy_struct internal error: unknown type \"%d\" (pyrna_prop_to_py)", type); ret = NULL; break; } @@ -886,6 +895,9 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, v } else if((flag & PROP_NEVER_NULL) && value == Py_None) { PyErr_Format(PyExc_TypeError, "%.200s does not support a 'None' assignment %.200s type", error_prefix, RNA_struct_identifier(ptype)); return -1; + } else if(value != Py_None && ((flag & PROP_ID_SELF_CHECK) && ptr->id.data == ((BPy_StructRNA*)value)->ptr.id.data)) { + PyErr_Format(PyExc_TypeError, "%.200s ID type does not support assignment to its self", error_prefix); + return -1; } else { BPy_StructRNA *param= (BPy_StructRNA*)value; int raise_error= FALSE; @@ -1084,7 +1096,7 @@ static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_s if(RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr)) return pyrna_struct_CreatePyObject(&newptr); - PyErr_Format(PyExc_IndexError, "index %d out of range", keynum); + PyErr_Format(PyExc_IndexError, "bpy_prop_collection[index]: index %d out of range", keynum); return NULL; } @@ -1097,7 +1109,7 @@ static PyObject *pyrna_prop_array_subscript_int(BPy_PropertyRNA *self, int keynu if(keynum >= 0 && keynum < len) return pyrna_prop_to_py_index(self, keynum); - PyErr_Format(PyExc_IndexError, "index %d out of range", keynum); + PyErr_Format(PyExc_IndexError, "bpy_prop_array[index]: index %d out of range", keynum); return NULL; } @@ -1107,7 +1119,7 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, char if(RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) return pyrna_struct_CreatePyObject(&newptr); - PyErr_Format(PyExc_KeyError, "key \"%.200s\" not found", keyname); + PyErr_Format(PyExc_KeyError, "bpy_prop_collection[key]: key \"%.200s\" not found", keyname); return NULL; } /* static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) */ @@ -1237,12 +1249,12 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject return pyrna_prop_collection_subscript_slice(&self->ptr, self->prop, start, stop, len); } else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported with rna"); return NULL; } } else { - PyErr_Format(PyExc_TypeError, "invalid rna key, key must be a string or an int instead of %.200s instance.", Py_TYPE(key)->tp_name); + PyErr_Format(PyExc_TypeError, "bpy_prop_collection[key]: invalid key, must be a string or an int instead of %.200s instance.", Py_TYPE(key)->tp_name); return NULL; } } @@ -1272,12 +1284,12 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyRNA *self, PyObject *key return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, start, stop, len); } else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); + PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]: slice steps not supported with rna"); return NULL; } } else { - PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int"); + PyErr_SetString(PyExc_AttributeError, "bpy_prop_array[key]: invalid key, key must be an int"); return NULL; } } @@ -1291,17 +1303,17 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, in int ret= 0; if(value_orig == NULL) { - PyErr_SetString(PyExc_TypeError, "invalid slice assignment, deleting with list types is not supported by StructRNA."); + PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice] = value: deleting with list types is not supported by bpy_struct."); return -1; } - if(!(value=PySequence_Fast(value_orig, "invalid slice assignment, type is not a sequence"))) { + if(!(value=PySequence_Fast(value_orig, "bpy_prop_array[slice] = value: type is not a sequence"))) { return -1; } if(PySequence_Fast_GET_SIZE(value) != stop-start) { Py_DECREF(value); - PyErr_SetString(PyExc_TypeError, "invalid slice assignment, resizing StructRNA arrays isn't supported."); + PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice] = value: resizing bpy_struct arrays isn't supported."); return -1; } @@ -1394,7 +1406,7 @@ static int prop_subscript_ass_array_int(BPy_PropertyRNA *self, Py_ssize_t keynum if(keynum >= 0 && keynum < len) return pyrna_py_to_prop_index(self, keynum, value); - PyErr_SetString(PyExc_IndexError, "out of range"); + PyErr_SetString(PyExc_IndexError, "bpy_prop_array[index] = value: index out of range"); return -1; } @@ -1402,8 +1414,8 @@ static int pyrna_prop_array_ass_subscript( BPy_PropertyRNA *self, PyObject *key, { /* char *keyname = NULL; */ /* not supported yet */ - if (!RNA_property_editable(&self->ptr, self->prop)) { - PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%.200s\" from \"%.200s\" is read-only", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) ); + if (!RNA_property_editable_flag(&self->ptr, self->prop)) { + PyErr_Format(PyExc_AttributeError, "bpy_prop_collection: attribute \"%.200s\" from \"%.200s\" is read-only", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) ); return -1; } @@ -1467,7 +1479,7 @@ static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *value char *keyname = _PyUnicode_AsString(value); if(keyname==NULL) { - PyErr_SetString(PyExc_TypeError, "PropertyRNA - key in prop, key must be a string type"); + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.__contains__: expected a string"); return -1; } @@ -1483,12 +1495,12 @@ static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value) char *name = _PyUnicode_AsString(value); if (!name) { - PyErr_SetString( PyExc_TypeError, "expected a string"); + PyErr_SetString( PyExc_TypeError, "bpy_struct.__contains__: expected a string"); return -1; } if(RNA_struct_idproperties_check(self->ptr.type)==0) { - PyErr_SetString( PyExc_TypeError, "this type doesnt support IDProperties"); + PyErr_SetString( PyExc_TypeError, "bpy_struct: this type doesnt support IDProperties"); return -1; } @@ -1545,21 +1557,21 @@ static PyObject *pyrna_struct_subscript( BPy_StructRNA *self, PyObject *key ) } if(name==NULL) { - PyErr_SetString( PyExc_TypeError, "only strings are allowed as keys of ID properties"); + PyErr_SetString( PyExc_TypeError, "bpy_struct[key]: only strings are allowed as keys of ID properties"); return NULL; } group= RNA_struct_idproperties(&self->ptr, 0); if(group==NULL) { - PyErr_Format( PyExc_KeyError, "key \"%s\" not found", name); + PyErr_Format( PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); return NULL; } idprop= IDP_GetPropertyFromGroup(group, name); if(idprop==NULL) { - PyErr_Format( PyExc_KeyError, "key \"%s\" not found", name); + PyErr_Format( PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); return NULL; } @@ -1571,7 +1583,7 @@ static int pyrna_struct_ass_subscript( BPy_StructRNA *self, PyObject *key, PyObj IDProperty *group= RNA_struct_idproperties(&self->ptr, 1); if(group==NULL) { - PyErr_SetString(PyExc_TypeError, "id properties not supported for this type"); + PyErr_SetString(PyExc_TypeError, "bpy_struct[key] = val: id properties not supported for this type"); return -1; } @@ -1589,7 +1601,7 @@ static PyObject *pyrna_struct_keys(BPy_PropertyRNA *self) IDProperty *group; if(RNA_struct_idproperties_check(self->ptr.type)==0) { - PyErr_SetString( PyExc_TypeError, "this type doesnt support IDProperties"); + PyErr_SetString( PyExc_TypeError, "bpy_struct.keys(): this type doesn't support IDProperties"); return NULL; } @@ -1606,7 +1618,7 @@ static PyObject *pyrna_struct_items(BPy_PropertyRNA *self) IDProperty *group; if(RNA_struct_idproperties_check(self->ptr.type)==0) { - PyErr_SetString( PyExc_TypeError, "this type doesnt support IDProperties"); + PyErr_SetString( PyExc_TypeError, "bpy_struct.items(): this type doesn't support IDProperties"); return NULL; } @@ -1624,7 +1636,7 @@ static PyObject *pyrna_struct_values(BPy_PropertyRNA *self) IDProperty *group; if(RNA_struct_idproperties_check(self->ptr.type)==0) { - PyErr_SetString( PyExc_TypeError, "this type doesnt support IDProperties"); + PyErr_SetString( PyExc_TypeError, "bpy_struct.values(): this type doesn't support IDProperties"); return NULL; } @@ -1636,47 +1648,81 @@ static PyObject *pyrna_struct_values(BPy_PropertyRNA *self) return BPy_Wrap_GetValues(self->ptr.id.data, group); } -static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args) +/* internal use for insert and delete */ +int pyrna_struct_keyframe_parse(PointerRNA *ptr, PyObject *args, char *error_prefix, + char **path_full, int *index, float *cfra) /* return values */ { - char *path, *path_full; - int index= -1; /* default to all */ - float cfra = CTX_data_scene(BPy_GetContext())->r.cfra; + char *path; PropertyRNA *prop; - PyObject *result; - if (!PyArg_ParseTuple(args, "s|if:keyframe_insert", &path, &index, &cfra)) - return NULL; + if (!PyArg_ParseTuple(args, "s|if", &path, &index, &cfra)) { + PyErr_Format(PyExc_TypeError, "%.200s expected a string and optionally an int and float arguments", error_prefix); + return -1; + } - if (self->ptr.data==NULL) { - PyErr_Format( PyExc_TypeError, "keyframe_insert, this struct has no data, cant be animated", path); - return NULL; + if (ptr->data==NULL) { + PyErr_Format(PyExc_TypeError, "%.200s this struct has no data, can't be animated", error_prefix); + return -1; } - prop = RNA_struct_find_property(&self->ptr, path); + prop = RNA_struct_find_property(ptr, path); if (prop==NULL) { - PyErr_Format( PyExc_TypeError, "keyframe_insert, property \"%s\" not found", path); - return NULL; + PyErr_Format( PyExc_TypeError, "%.200s property \"%s\" not found", error_prefix, path); + return -1; } - if (!RNA_property_animateable(&self->ptr, prop)) { - PyErr_Format( PyExc_TypeError, "keyframe_insert, property \"%s\" not animatable", path); - return NULL; + if (!RNA_property_animateable(ptr, prop)) { + PyErr_Format( PyExc_TypeError, "%.200s property \"%s\" not animatable", error_prefix, path); + return -1; } - path_full= RNA_path_from_ID_to_property(&self->ptr, prop); + *path_full= RNA_path_from_ID_to_property(ptr, prop); - if (path_full==NULL) { - PyErr_Format( PyExc_TypeError, "keyframe_insert, could not make path to \"%s\"", path); - return NULL; + if (*path_full==NULL) { + PyErr_Format( PyExc_TypeError, "%.200s could not make path to \"%s\"", error_prefix, path); + return -1; } - result= PyBool_FromLong( insert_keyframe((ID *)self->ptr.id.data, NULL, NULL, path_full, index, cfra, 0)); + if(*cfra==FLT_MAX) + *cfra= CTX_data_scene(BPy_GetContext())->r.cfra; + + return 0; /* success */ +} + +static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args) +{ + PyObject *result; + /* args, pyrna_struct_keyframe_parse handles these */ + char *path_full= NULL; + int index= -1; + float cfra= FLT_MAX; + + if(pyrna_struct_keyframe_parse(&self->ptr, args, "bpy_struct.keyframe_insert():", &path_full, &index, &cfra) == -1) + return NULL; + + result= PyBool_FromLong(insert_keyframe((ID *)self->ptr.id.data, NULL, NULL, path_full, index, cfra, 0)); MEM_freeN(path_full); return result; } +static PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args) +{ + PyObject *result; + /* args, pyrna_struct_keyframe_parse handles these */ + char *path_full= NULL; + int index= -1; + float cfra= FLT_MAX; + + if(pyrna_struct_keyframe_parse(&self->ptr, args, "bpy_struct.keyframe_delete():", &path_full, &index, &cfra) == -1) + return NULL; + + result= PyBool_FromLong(delete_keyframe((ID *)self->ptr.id.data, NULL, NULL, path_full, index, cfra, 0)); + MEM_freeN(path_full); + + return result; +} static PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) { @@ -1689,26 +1735,26 @@ static PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) return NULL; if (self->ptr.data==NULL) { - PyErr_Format( PyExc_TypeError, "driver_add, this struct has no data, cant be animated", path); + PyErr_Format( PyExc_TypeError, "bpy_struct.driver_add(): this struct has no data, cant be animated", path); return NULL; } prop = RNA_struct_find_property(&self->ptr, path); if (prop==NULL) { - PyErr_Format( PyExc_TypeError, "driver_add, property \"%s\" not found", path); + PyErr_Format( PyExc_TypeError, "bpy_struct.driver_add(): property \"%s\" not found", path); return NULL; } if (!RNA_property_animateable(&self->ptr, prop)) { - PyErr_Format( PyExc_TypeError, "driver_add, property \"%s\" not animatable", path); + PyErr_Format( PyExc_TypeError, "bpy_struct.driver_add(): property \"%s\" not animatable", path); return NULL; } path_full= RNA_path_from_ID_to_property(&self->ptr, prop); if (path_full==NULL) { - PyErr_Format( PyExc_TypeError, "driver_add, could not make path to \"%s\"", path); + PyErr_Format( PyExc_TypeError, "bpy_struct.driver_add(): could not make path to \"%s\"", path); return NULL; } @@ -1778,7 +1824,7 @@ static PyObject *pyrna_struct_path_resolve(BPy_StructRNA *self, PyObject *value) PropertyRNA *r_prop; if(path==NULL) { - PyErr_SetString( PyExc_TypeError, "items() is only valid for collection types" ); + PyErr_SetString( PyExc_TypeError, "bpy_struct.items(): is only valid for collection types" ); return NULL; } @@ -1801,7 +1847,7 @@ static PyObject *pyrna_struct_path_to_id(BPy_StructRNA *self, PyObject *args) if(name) { prop= RNA_struct_find_property(&self->ptr, name); if(prop==NULL) { - PyErr_Format(PyExc_TypeError, "path_to_id(\"%.200s\") not found", name); + PyErr_Format(PyExc_TypeError, "%.200s.path_to_id(\"%.200s\") not found", RNA_struct_identifier(self->ptr.type), name); return NULL; } @@ -1960,7 +2006,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname ) if(name[0]=='_') { // rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups /* annoying exception, maybe we need to have different types for this... */ if((strcmp(name, "__getitem__")==0 || strcmp(name, "__setitem__")==0) && !RNA_struct_idproperties_check(self->ptr.type)) { - PyErr_SetString(PyExc_AttributeError, "StructRNA - no __getitem__ support for this type"); + PyErr_SetString(PyExc_AttributeError, "bpy_struct: no __getitem__ support for this type"); ret = NULL; } else { @@ -1977,7 +2023,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname ) else if (self->ptr.type == &RNA_Context) { bContext *C = self->ptr.data; if(C==NULL) { - PyErr_Format( PyExc_AttributeError, "StructRNA Context is 'NULL', can't get \"%.200s\" from context", name); + PyErr_Format( PyExc_AttributeError, "bpy_struct: Context is 'NULL', can't get \"%.200s\" from context", name); ret= NULL; } else { @@ -2021,7 +2067,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname ) } else { #if 0 - PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%.200s\" not found", name); + PyErr_Format( PyExc_AttributeError, "bpy_struct: attribute \"%.200s\" not found", name); ret = NULL; #endif /* Include this incase this instance is a subtype of a python class @@ -2056,30 +2102,13 @@ static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObjec if (prop==NULL) { return PyObject_GenericSetAttr((PyObject *)self, pyname, value); -#if 0 - // XXX - This currently allows anything to be assigned to an rna prop, need to see how this should be used - // but for now it makes porting scripts confusing since it fails silently. - // edit: allowing this for setting classes internal attributes. - // edit: allow this for any attribute that alredy exists as a python attr - if ( (name[0]=='_' /* || pyrna_struct_pydict_contains(self, pyname) */ ) && - !BPy_StructRNA_CheckExact(self) && - - return 0; - } else - { - PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%.200s\" not found", name); - return -1; - } -#endif - } - - if (!RNA_property_editable(&self->ptr, prop)) { - PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%.200s\" from \"%.200s\" is read-only", RNA_property_identifier(prop), RNA_struct_identifier(self->ptr.type) ); + } else if (!RNA_property_editable_flag(&self->ptr, prop)) { + PyErr_Format( PyExc_AttributeError, "bpy_struct: attribute \"%.200s\" from \"%.200s\" is read-only", RNA_property_identifier(prop), RNA_struct_identifier(self->ptr.type) ); return -1; } /* pyrna_py_to_prop sets its own exceptions */ - return pyrna_py_to_prop(&self->ptr, prop, NULL, NULL, value, "StructRNA - item.attr = val:"); + return pyrna_py_to_prop(&self->ptr, prop, NULL, NULL, value, "bpy_struct: item.attr = val:"); } static PyObject *pyrna_prop_dir(BPy_PropertyRNA *self) @@ -2151,7 +2180,7 @@ static int pyrna_prop_collection_setattro( BPy_PropertyRNA *self, PyObject *pyna } } - PyErr_Format( PyExc_AttributeError, "BPy_PropertyRNA - Attribute \"%.200s\" not found", name); + PyErr_Format( PyExc_AttributeError, "bpy_prop_collection: attribute \"%.200s\" not found", name); return -1; } @@ -2162,7 +2191,7 @@ static PyObject *pyrna_prop_add(BPy_PropertyRNA *self) RNA_property_collection_add(&self->ptr, self->prop, &r_ptr); if(!r_ptr.data) { - PyErr_SetString( PyExc_TypeError, "add() not supported for this collection"); + PyErr_SetString( PyExc_TypeError, "bpy_prop_collection.add(): not supported for this collection"); return NULL; } else { @@ -2176,12 +2205,12 @@ static PyObject *pyrna_prop_remove(BPy_PropertyRNA *self, PyObject *value) int key= PyLong_AsSsize_t(value); if (key==-1 && PyErr_Occurred()) { - PyErr_SetString( PyExc_TypeError, "remove() expected one int argument"); + PyErr_SetString( PyExc_TypeError, "bpy_prop_collection.remove(): expected one int argument"); return NULL; } if(!RNA_property_collection_remove(&self->ptr, self->prop, key)) { - PyErr_SetString( PyExc_TypeError, "remove() not supported for this collection"); + PyErr_SetString( PyExc_TypeError, "bpy_prop_collection.remove() not supported for this collection"); return NULL; } @@ -2219,96 +2248,74 @@ static PyGetSetDef pyrna_struct_getseters[] = { static PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) { - PyObject *ret; - if (RNA_property_type(self->prop) != PROP_COLLECTION) { - PyErr_SetString( PyExc_TypeError, "keys() is only valid for collection types" ); - ret = NULL; - } else { - PyObject *item; - char name[256], *nameptr; + PyObject *ret= PyList_New(0); + PyObject *item; + char name[256], *nameptr; - ret = PyList_New(0); - - RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { - nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name)); + RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { + nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name)); - if(nameptr) { - /* add to python list */ - item = PyUnicode_FromString( nameptr ); - PyList_Append(ret, item); - Py_DECREF(item); - /* done */ - - if(name != nameptr) - MEM_freeN(nameptr); - } + if(nameptr) { + /* add to python list */ + item = PyUnicode_FromString( nameptr ); + PyList_Append(ret, item); + Py_DECREF(item); + /* done */ + + if(name != nameptr) + MEM_freeN(nameptr); } - RNA_PROP_END; } + RNA_PROP_END; return ret; } static PyObject *pyrna_prop_items(BPy_PropertyRNA *self) { - PyObject *ret; - if (RNA_property_type(self->prop) != PROP_COLLECTION) { - PyErr_SetString( PyExc_TypeError, "items() is only valid for collection types" ); - ret = NULL; - } else { - PyObject *item; - char name[256], *nameptr; - int i= 0; + PyObject *ret= PyList_New(0); + PyObject *item; + char name[256], *nameptr; + int i= 0; - ret = PyList_New(0); - - RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { - if(itemptr.data) { - /* add to python list */ - item= PyTuple_New(2); - nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name)); - if(nameptr) { - PyTuple_SET_ITEM(item, 0, PyUnicode_FromString( nameptr )); - if(name != nameptr) - MEM_freeN(nameptr); - } - else { - PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); /* a bit strange but better then returning an empty list */ - } - PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); - - PyList_Append(ret, item); - Py_DECREF(item); - - i++; + RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { + if(itemptr.data) { + /* add to python list */ + item= PyTuple_New(2); + nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name)); + if(nameptr) { + PyTuple_SET_ITEM(item, 0, PyUnicode_FromString( nameptr )); + if(name != nameptr) + MEM_freeN(nameptr); + } + else { + PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); /* a bit strange but better then returning an empty list */ } + PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); + + PyList_Append(ret, item); + Py_DECREF(item); + + i++; } - RNA_PROP_END; } + RNA_PROP_END; return ret; } - static PyObject *pyrna_prop_values(BPy_PropertyRNA *self) { - PyObject *ret; + PyObject *ret= PyList_New(0); + PyObject *item; - if (RNA_property_type(self->prop) != PROP_COLLECTION) { - PyErr_SetString( PyExc_TypeError, "values() is only valid for collection types" ); - ret = NULL; - } else { - PyObject *item; - ret = PyList_New(0); - - RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { - item = pyrna_struct_CreatePyObject(&itemptr); - PyList_Append(ret, item); - Py_DECREF(item); - } - RNA_PROP_END; + RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { + item = pyrna_struct_CreatePyObject(&itemptr); + PyList_Append(ret, item); + Py_DECREF(item); } - + RNA_PROP_END; + return ret; } @@ -2656,6 +2663,7 @@ static struct PyMethodDef pyrna_struct_methods[] = { /* maybe this become and ID function */ {"keyframe_insert", (PyCFunction)pyrna_struct_keyframe_insert, METH_VARARGS, NULL}, +// {"keyframe_delete", (PyCFunction)pyrna_struct_keyframe_delete, METH_VARARGS, NULL}, // WIP {"driver_add", (PyCFunction)pyrna_struct_driver_add, METH_VARARGS, NULL}, {"is_property_set", (PyCFunction)pyrna_struct_is_property_set, METH_VARARGS, NULL}, {"is_property_hidden", (PyCFunction)pyrna_struct_is_property_hidden, METH_VARARGS, NULL}, @@ -2663,6 +2671,11 @@ static struct PyMethodDef pyrna_struct_methods[] = { {"path_to_id", (PyCFunction)pyrna_struct_path_to_id, METH_VARARGS, NULL}, {"recast_type", (PyCFunction)pyrna_struct_recast_type, METH_NOARGS, NULL}, {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL}, + + /* experemental */ + {"callback_add", (PyCFunction)pyrna_callback_add, METH_VARARGS, NULL}, + {"callback_remove", (PyCFunction)pyrna_callback_remove, METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL} }; @@ -2700,7 +2713,7 @@ static PyObject * pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject BPy_StructRNA *base = NULL; - if (!PyArg_ParseTuple(args, "O!:Base BPy_StructRNA", &pyrna_struct_Type, &base)) + if (!PyArg_ParseTuple(args, "O!:bpy_struct.__new__", &pyrna_struct_Type, &base)) return NULL; if (type == &pyrna_struct_Type) { @@ -2883,7 +2896,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) ParameterIterator iter; PropertyRNA *parm; PyObject *ret, *item; - int i, args_len, parms_len, ret_len, flag, err= 0, kw_tot= 0, kw_arg; + int i, pyargs_len, pykw_len, parms_len, ret_len, flag, err= 0, kw_tot= 0, kw_arg; const char *parm_id; PropertyRNA *pret_single= NULL; @@ -2905,16 +2918,17 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) * the same ID as the functions. */ RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr); - args_len= PyTuple_GET_SIZE(args); + pyargs_len= PyTuple_GET_SIZE(args); + pykw_len= kw ? PyDict_Size(kw) : 0; RNA_parameter_list_create(&parms, self_ptr, self_func); RNA_parameter_list_begin(&parms, &iter); parms_len= RNA_parameter_list_size(&parms); ret_len= 0; - if(args_len + (kw ? PyDict_Size(kw):0) > parms_len) { + if(pyargs_len + pykw_len > parms_len) { RNA_parameter_list_end(&iter); - PyErr_Format(PyExc_TypeError, "%.200s.%.200s(): takes at most %d arguments, got %d", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), parms_len, args_len); + PyErr_Format(PyExc_TypeError, "%.200s.%.200s(): takes at most %d arguments, got %d", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), parms_len, pyargs_len + pykw_len); err= -1; } @@ -2937,7 +2951,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) parm_id= RNA_property_identifier(parm); item= NULL; - if ((i < args_len) && (flag & PROP_REQUIRED)) { + if ((i < pyargs_len) && (flag & PROP_REQUIRED)) { item= PyTuple_GET_ITEM(args, i); i++; @@ -2988,7 +3002,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) * the if below is quick, checking if it passed less keyword args then we gave. * (Dont overwrite the error if we have one, otherwise can skip important messages and confuse with args) */ - if(err == 0 && kw && (PyDict_Size(kw) > kw_tot)) { + if(err == 0 && kw && (pykw_len > kw_tot)) { PyObject *key, *value; Py_ssize_t pos = 0; @@ -3111,7 +3125,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) /*-----------------------BPy_StructRNA method def------------------------------*/ PyTypeObject pyrna_struct_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "StructRNA", /* tp_name */ + "bpy_struct", /* tp_name */ sizeof( BPy_StructRNA ), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -3190,7 +3204,7 @@ PyTypeObject pyrna_struct_Type = { /*-----------------------BPy_PropertyRNA method def------------------------------*/ PyTypeObject pyrna_prop_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "PropertyRNA", /* tp_name */ + "bpy_prop", /* tp_name */ sizeof( BPy_PropertyRNA ), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -3270,7 +3284,7 @@ PyTypeObject pyrna_prop_Type = { PyTypeObject pyrna_prop_array_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "PropertyArrayRNA", /* tp_name */ + "bpy_prop_array", /* tp_name */ sizeof( BPy_PropertyRNA ), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -3350,7 +3364,7 @@ PyTypeObject pyrna_prop_array_Type = { PyTypeObject pyrna_prop_collection_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "PropertyCollectionRNA", /* tp_name */ + "bpy_prop_collection", /* tp_name */ sizeof( BPy_PropertyRNA ), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -3669,7 +3683,7 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr ) } if( !pyrna ) { - PyErr_SetString( PyExc_MemoryError, "couldn't create BPy_StructRNA object" ); + PyErr_SetString( PyExc_MemoryError, "couldn't create bpy_struct object" ); return NULL; } @@ -3915,7 +3929,7 @@ static int deferred_register_prop(StructRNA *srna, PyObject *item, PyObject *key if(PyArg_ParseTuple(item, "O!O!", &PyCapsule_Type, &py_func_ptr, &PyDict_Type, &py_kw)) { if(*_PyUnicode_AsString(key)=='_') { - PyErr_Format(PyExc_ValueError, "StructRNA \"%.200s\" registration error: %.200s could not register because the property starts with an '_'\n", RNA_struct_identifier(srna), _PyUnicode_AsString(key)); + PyErr_Format(PyExc_ValueError, "bpy_struct \"%.200s\" registration error: %.200s could not register because the property starts with an '_'\n", RNA_struct_identifier(srna), _PyUnicode_AsString(key)); Py_DECREF(dummy_args); return -1; } @@ -3936,7 +3950,7 @@ static int deferred_register_prop(StructRNA *srna, PyObject *item, PyObject *key PyErr_Clear(); // PyLineSpit(); - PyErr_Format(PyExc_ValueError, "StructRNA \"%.200s\" registration error: %.200s could not register\n", RNA_struct_identifier(srna), _PyUnicode_AsString(key)); + PyErr_Format(PyExc_ValueError, "bpy_struct \"%.200s\" registration error: %.200s could not register\n", RNA_struct_identifier(srna), _PyUnicode_AsString(key)); Py_DECREF(dummy_args); return -1; @@ -4143,7 +4157,8 @@ extern void BPY_update_modules( void ); //XXX temp solution static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *parms) { PyObject *args; - PyObject *ret= NULL, *py_class, *py_class_instance, *item, *parmitem; + PyObject *ret= NULL, *py_srna= NULL, *py_class, *py_class_instance= NULL, *parmitem; + void **py_class_instance_store= NULL; PropertyRNA *parm; ParameterIterator iter; PointerRNA funcptr; @@ -4159,23 +4174,49 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par py_class= RNA_struct_py_type_get(ptr->type); - item = pyrna_struct_CreatePyObject(ptr); - if(item == NULL) { + /* exception, operators store their PyObjects for re-use */ + if(ptr->data) { + if(RNA_struct_is_a(ptr->type, &RNA_Operator)) { + wmOperator *op= ptr->data; + if(op->py_instance) { + py_class_instance= op->py_instance; + Py_INCREF(py_class_instance); + } + else { + /* store the instance here once its created */ + py_class_instance_store= &op->py_instance; + } + } + } + /* end exception */ + + if(py_class_instance==NULL) + py_srna= pyrna_struct_CreatePyObject(ptr); + + if(py_class_instance) { + /* special case, instance is cached */ + } + else if(py_srna == NULL) { py_class_instance = NULL; } - else if(item == Py_None) { /* probably wont ever happen but possible */ - Py_DECREF(item); + else if(py_srna == Py_None) { /* probably wont ever happen but possible */ + Py_DECREF(py_srna); py_class_instance = NULL; } else { args = PyTuple_New(1); - PyTuple_SET_ITEM(args, 0, item); + PyTuple_SET_ITEM(args, 0, py_srna); py_class_instance = PyObject_Call(py_class, args, NULL); Py_DECREF(args); + + if(py_class_instance_store) { + *py_class_instance_store = py_class_instance; + Py_INCREF(py_class_instance); + } } if (py_class_instance) { /* Initializing the class worked, now run its invoke function */ - item= PyObject_GetAttrString(py_class, RNA_function_identifier(func)); + PyObject *item= PyObject_GetAttrString(py_class, RNA_function_identifier(func)); // flag= RNA_function_flag(func); if(item) { diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 77f6ec00d48..770e88e1a1d 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -84,6 +84,8 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop); PyObject *pyrna_enum_bitfield_to_py(struct EnumPropertyItem *items, int value); int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix); +int pyrna_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value, const char *error_prefix); + /* function for registering types */ PyObject *pyrna_basetype_register(PyObject *self, PyObject *args); PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *args); diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c new file mode 100644 index 00000000000..ee0c5cb143b --- /dev/null +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -0,0 +1,111 @@ +/** + * $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "Python.h" + +#include "bpy_rna.h" +#include "bpy_util.h" + +#include "BLI_path_util.h" +#include "DNA_screen_types.h" +#include "BKE_context.h" +#include "ED_space_api.h" + +EnumPropertyItem region_draw_mode_items[] = { + {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Pose View", ""}, + {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""}, + {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""}, + {0, NULL, 0, NULL, NULL}}; + + +void cb_region_draw(const bContext *C, ARegion *ar, void *customdata) +{ + PyObject *cb_func, *cb_args, *result; + PyGILState_STATE gilstate; + + bpy_context_set((bContext *)C, &gilstate); + + cb_func= PyTuple_GET_ITEM((PyObject *)customdata, 0); + cb_args= PyTuple_GET_ITEM((PyObject *)customdata, 1); + result = PyObject_CallObject(cb_func, cb_args); + + if(result) { + Py_DECREF(result); + } + else { + PyErr_Print(); + PyErr_Clear(); + } + + bpy_context_clear((bContext *)C, &gilstate); +} + +PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args) +{ + void *handle; + + PyObject *cb_func, *cb_args; + char *cb_event_str= NULL; + int cb_event; + + if (!PyArg_ParseTuple(args, "OO|s:bpy_struct.callback_add", &cb_func, &cb_args, &cb_event_str)) + return NULL; + + if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) { + + if(pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") < 0) + return NULL; + + handle= ED_region_draw_cb_activate(((ARegion *)self->ptr.data)->type, cb_region_draw, (void *)args, cb_event); + Py_INCREF(args); + } + else { + PyErr_SetString(PyExc_TypeError, "callbcak_add(): type does not suppport cllbacks"); + return NULL; + } + + return PyCapsule_New((void *)handle, NULL, NULL); +} + +PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args) +{ + PyObject *py_handle; + PyObject *py_args; + void *handle; + void *customdata; + + if (!PyArg_ParseTuple(args, "O!:callback_remove", &PyCapsule_Type, &py_handle)) + return NULL; + + handle= PyCapsule_GetPointer(py_handle, NULL); + + if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) { + customdata= ED_region_draw_cb_customdata(handle); + Py_DECREF((PyObject *)customdata); + + ED_region_draw_cb_exit(((ARegion *)self->ptr.data)->type, handle); + } + + Py_RETURN_NONE; +} diff --git a/source/blender/python/intern/bpy_rna_callback.h b/source/blender/python/intern/bpy_rna_callback.h new file mode 100644 index 00000000000..b6d771b23b2 --- /dev/null +++ b/source/blender/python/intern/bpy_rna_callback.h @@ -0,0 +1,29 @@ +/** + * $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +struct BPy_StructRNA; +struct PyObject; + +struct PyObject *pyrna_callback_add(struct BPy_StructRNA *self, struct PyObject *args); +struct PyObject *pyrna_callback_remove(struct BPy_StructRNA *self, struct PyObject *args); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index c44d83f4f06..0a292c7acd5 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2405,7 +2405,7 @@ static void init_render_mball(Render *re, ObjectRen *obr) ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; normalize_v3(ver->n); - //if(ob->transflag & OB_NEG_SCALE) mul_v3_fl(ver->n. -1.0); + //if(ob->transflag & OB_NEG_SCALE) negate_v3(ver->n); if(need_orco) ver->orco= orco; } diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index 10cbd82fb1b..954ff373c89 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -986,8 +986,9 @@ static float readdeepvisibility(DeepSample *dsample, int tot, int z, int bias, f if(a == 0) return 1.0f; /* completely in front of all samples */ + /* converting to float early here because ds->z - prevds->z can overflow */ prevds= ds-1; - t= (float)(z-bias - prevds->z)/(float)(ds->z - prevds->z); + t= ((float)(z-bias) - (float)prevds->z)/((float)ds->z - (float)prevds->z); return t*ds->v + (1.0f-t)*prevds->v; } diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index 1622ee2bf4c..70e0fd41b7d 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -488,7 +488,7 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float * if (ELEM(lar->type, LA_SUN, LA_HEMI)) VECCOPY(lv, lar->vec); - mul_v3_fl(lv, -1.0f); + negate_v3(lv); if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADOWED) { mul_v3_fl(lacol, vol_get_shadow(shi, lar, co)); diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index e2b2c17beee..048487fcd68 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -54,6 +54,7 @@ #include "wm.h" #include "ED_screen.h" +#include "BPY_extern.h" #include "RNA_types.h" @@ -63,6 +64,12 @@ void WM_operator_free(wmOperator *op) { + if(op->py_instance) { + /* do this first incase there are any __del__ functions or + * similar that use properties */ + BPY_DECREF(op->py_instance); + } + if(op->ptr) { op->properties= op->ptr->data; MEM_freeN(op->ptr); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 74679ce89a6..b72bc02aca6 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -28,6 +28,7 @@ #include <stdlib.h> #include <string.h> +#include <math.h> #include "DNA_listBase.h" #include "DNA_screen_types.h" @@ -1533,23 +1534,32 @@ void wm_event_do_handlers(bContext *C) wm_event_free_all(win); else { - if(win->screen->scene) + Scene* scene = win->screen->scene; + if(scene) { int playing = sound_scene_playing(win->screen->scene); if(playing != -1) { + CTX_wm_window_set(C, win); + CTX_wm_screen_set(C, win->screen); + CTX_data_scene_set(C, scene); if(((playing == 1) && (!win->screen->animtimer)) || ((playing == 0) && (win->screen->animtimer))) { - CTX_wm_window_set(C, win); - CTX_wm_screen_set(C, win->screen); - CTX_data_scene_set(C, win->screen->scene); - ED_screen_animation_play(C, -1, 1); - - CTX_data_scene_set(C, NULL); - CTX_wm_screen_set(C, NULL); - CTX_wm_window_set(C, NULL); } + if(playing == 0) + { + int ncfra = floor(sound_sync_scene(scene) * FPS); + if(ncfra != scene->r.cfra) + { + scene->r.cfra = ncfra; + ED_update_for_newframe(C, 1); + WM_event_add_notifier(C, NC_WINDOW, NULL); + } + } + CTX_data_scene_set(C, NULL); + CTX_wm_screen_set(C, NULL); + CTX_wm_window_set(C, NULL); } } } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 16776517e40..2ab6f78daa5 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -241,6 +241,10 @@ static void wm_init_userdef(bContext *C) UI_init_userdef(); MEM_CacheLimiter_set_maximum(U.memcachelimit * 1024 * 1024); sound_init(CTX_data_main(C)); + + /* set the python auto-execute setting from user prefs */ + if (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) G.f &= ~G_SCRIPT_AUTOEXEC; + else G.f |= G_SCRIPT_AUTOEXEC; } void WM_read_file(bContext *C, char *name, ReportList *reports) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index b52588f2e75..29359b1ddb9 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1120,7 +1120,10 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *arg_unuse else display_name= recent->filename; uiItemStringO(col, display_name, ICON_FILE_BLEND, "WM_OT_open_mainfile", "path", recent->filename); } - + uiItemL(col, "Recovery", 0); + uiItemO(col, NULL, ICON_FILE_BLEND, "WM_OT_recover_last_session"); + uiItemO(col, NULL, ICON_FILE_BLEND, "WM_OT_recover_auto_save"); + uiItemL(col, "", 0); uiCenteredBoundsBlock(block, 0.0f); @@ -1323,10 +1326,17 @@ static void open_set_load_ui(wmOperator *op) RNA_boolean_set(op->ptr, "load_ui", !(U.flag & USER_FILENOUI)); } +static void open_set_use_scripts(wmOperator *op) +{ + if(!RNA_property_is_set(op->ptr, "use_scripts")) + RNA_boolean_set(op->ptr, "use_scripts", !(U.flag & USER_SCRIPT_AUTOEXEC_DISABLE)); +} + static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event) { RNA_string_set(op->ptr, "path", G.sce); open_set_load_ui(op); + open_set_use_scripts(op); WM_event_add_fileselect(C, op); @@ -1339,11 +1349,17 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "path", path); open_set_load_ui(op); + open_set_use_scripts(op); if(RNA_boolean_get(op->ptr, "load_ui")) G.fileflags &= ~G_FILE_NO_UI; else G.fileflags |= G_FILE_NO_UI; + + if(RNA_boolean_get(op->ptr, "use_scripts")) + G.f |= G_SCRIPT_AUTOEXEC; + else + G.f &= ~G_SCRIPT_AUTOEXEC; // XXX wm in context is not set correctly after WM_read_file -> crash // do it before for now, but is this correct with multiple windows? @@ -1367,6 +1383,7 @@ static void WM_OT_open_mainfile(wmOperatorType *ot) WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER, FILE_OPENFILE); RNA_def_boolean(ot->srna, "load_ui", 1, "Load UI", "Load user interface setup in the .blend file"); + RNA_def_boolean(ot->srna, "use_scripts", 1, "Trusted Source", "Allow blend file execute scripts automatically, default available from system preferences"); } /* **************** link/append *************** */ @@ -2997,7 +3014,11 @@ static EnumPropertyItem *rna_id_itemf(bContext *C, PointerRNA *ptr, int *free, I return item; } -/* can add more */ +/* can add more as needed */ +EnumPropertyItem *RNA_action_itemf(bContext *C, PointerRNA *ptr, int *free) +{ + return rna_id_itemf(C, ptr, free, C ? (ID *)CTX_data_main(C)->action.first : NULL); +} EnumPropertyItem *RNA_group_itemf(bContext *C, PointerRNA *ptr, int *free) { return rna_id_itemf(C, ptr, free, C ? (ID *)CTX_data_main(C)->group.first : NULL); |