diff options
Diffstat (limited to 'source/blender')
379 files changed, 18849 insertions, 10077 deletions
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index 703c5acd8a2..99297714fd2 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -40,6 +40,7 @@ ADD_SUBDIRECTORY(makesrna) ADD_SUBDIRECTORY(readblenfile) ADD_SUBDIRECTORY(render) ADD_SUBDIRECTORY(blenfont) +ADD_SUBDIRECTORY(ikplugin) IF(WITH_OPENEXR) ADD_SUBDIRECTORY(imbuf/intern/openexr) diff --git a/source/blender/Makefile b/source/blender/Makefile index 31636f838c3..6bc874c3c93 100644 --- a/source/blender/Makefile +++ b/source/blender/Makefile @@ -34,7 +34,7 @@ DIRS = windowmanager editors blenloader readblenfile DIRS += avi imbuf render blenlib blenkernel blenpluginapi DIRS += makesdna makesrna DIRS += python nodes gpu -DIRS += blenfont +DIRS += blenfont ikplugin ifeq ($(WITH_QUICKTIME), true) DIRS += quicktime diff --git a/source/blender/SConscript b/source/blender/SConscript index a064850c170..3625678f610 100644 --- a/source/blender/SConscript +++ b/source/blender/SConscript @@ -16,8 +16,9 @@ SConscript(['avi/SConscript', 'readblenfile/SConscript', 'render/SConscript', 'nodes/SConscript', + 'ikplugin/SConscript', 'windowmanager/SConscript', - 'blenfont/SConscript']) + 'blenfont/SConscript']) diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index 844a6899bf5..9b7e950526d 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -32,6 +32,7 @@ SET(INC IF(WITH_INTERNATIONAL) SET(INC ${INC} ${GETTEXT_INC}) + ADD_DEFINITIONS(-DINTERNATIONAL) ENDIF(WITH_INTERNATIONAL) IF(WIN32) diff --git a/source/blender/blenfont/Makefile b/source/blender/blenfont/Makefile index 70dd2e5052b..43eda027855 100644 --- a/source/blender/blenfont/Makefile +++ b/source/blender/blenfont/Makefile @@ -28,3 +28,7 @@ SOURCEDIR = source/blender/blenfont DIRS = intern include nan_subdirs.mk + +ifeq ($(INTERNATIONAL), true) + CPPFLAGS += -DINTERNATIONAL +endif diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index d070d985247..91edc46ba8b 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -9,9 +9,13 @@ incs += ' #/extern/glew/include' incs += ' ' + env['BF_FREETYPE_INC'] incs += ' ' + env['BF_GETTEXT_INC'] -defs = '' +defs = [] if sys.platform == 'win32': - defs += ' _WIN32 USE_GETTEXT_DLL' + defs.append('_WIN32') + defs.append('USE_GETTEXT_DLL') + +if env['WITH_BF_INTERNATIONAL']: + defs.append('INTERNATIONAL') env.BlenderLib ( 'bf_blenfont', sources, Split(incs), Split(defs), libtype=['core','player'], priority=[210,210] ) diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 8cb237a19ac..db88d84d0b5 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -102,7 +102,7 @@ void BLF_exit(void) blf_font_exit(); } -int blf_search(char *name) +static int blf_search(char *name) { FontBLF *font; int i; diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c index b4d902ff428..aac6cd7d2fc 100644 --- a/source/blender/blenfont/intern/blf_dir.c +++ b/source/blender/blenfont/intern/blf_dir.c @@ -51,7 +51,7 @@ static ListBase global_font_dir= { NULL, NULL }; -DirBLF *blf_dir_find(const char *path) +static DirBLF *blf_dir_find(const char *path) { DirBLF *p; diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 2cd72809579..8721e49f06b 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -353,8 +353,8 @@ void blf_font_boundbox(FontBLF *font, char *str, rctf *box) pen_x += delta.x >> 6; } - gbox.xmin= g->box.xmin + pen_x; - gbox.xmax= g->box.xmax + pen_x; + gbox.xmin= pen_x; + gbox.xmax= pen_x + g->advance; gbox.ymin= g->box.ymin + pen_y; gbox.ymax= g->box.ymax + pen_y; @@ -453,7 +453,7 @@ void blf_font_free(FontBLF *font) MEM_freeN(font); } -void blf_font_fill(FontBLF *font) +static void blf_font_fill(FontBLF *font) { font->aspect= 1.0f; font->pos[0]= 0.0f; diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index f3db3ddc9a5..7d1e43a38df 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -136,7 +136,7 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc) MEM_freeN(gc); } -void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc) +static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc) { int tot_mem, i; unsigned char *buf; diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index 024172d6db4..ed684eda46f 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -60,17 +60,14 @@ char global_messagepath[1024]; char global_language[32]; char global_encoding_name[32]; - -void BLF_lang_init(void) +#if defined(__APPLE__) +void BLF_lang_init(void) /* Apple Only, todo - use BLI_gethome_folder */ { -#ifdef __APPLE__ char *bundlepath; -#endif strcpy(global_encoding_name, SYSTEM_ENCODING_DEFAULT); /* set messagepath directory */ - #ifndef LOCALEDIR #define LOCALEDIR "/usr/share/locale" #endif @@ -81,44 +78,52 @@ void BLF_lang_init(void) BLI_make_file_string("/", global_messagepath, BLI_gethome(), ".blender/locale"); if (!BLI_exist(global_messagepath)) { /* locale not in home dir */ -#ifdef WIN32 - BLI_make_file_string("/", global_messagepath, BLI_gethome(), "/locale"); - if (!BLI_exist(global_messagepath)) { -#endif -#ifdef __APPLE__ /* message catalogs are stored inside the application bundle */ bundlepath= BLI_getbundle(); strcpy(global_messagepath, bundlepath); strcat(global_messagepath, "/Contents/Resources/locale"); if (!BLI_exist(global_messagepath)) { /* locale not in bundle (now that's odd..) */ -#endif strcpy(global_messagepath, LOCALEDIR); if (!BLI_exist(global_messagepath)) { /* locale not in LOCALEDIR */ strcpy(global_messagepath, "message"); /* old compatibility as last */ } -#ifdef WIN32 } -#endif -#ifdef __APPLE__ - } -#endif } } } - -void BLF_lang_set(const char *str) +#elif defined(_WIN32) +void BLF_lang_init(void) /* Windows Only, todo - use BLI_gethome_folder */ { -#if defined (_WIN32) || defined(__APPLE__) - char envstr[12]; + strcpy(global_encoding_name, SYSTEM_ENCODING_DEFAULT); + + strcpy(global_messagepath, ".blender/locale"); + + if (!BLI_exist(global_messagepath)) { /* locale not in current dir */ + BLI_make_file_string("/", global_messagepath, BLI_gethome(), ".blender/locale"); - sprintf(envstr, "LANG=%s", str); - envstr[strlen(envstr)]= '\0'; -#ifdef _WIN32 - gettext_putenv(envstr); + if (!BLI_exist(global_messagepath)) { /* locale not in home dir */ + BLI_make_file_string("/", global_messagepath, BLI_gethome(), "/locale"); + } + } +} #else - putenv(envstr); +void BLF_lang_init(void) /* not win or mac */ +{ + char *messagepath= BLI_gethome_folder("locale", BLI_GETHOME_ALL); + + if(messagepath) + strncpy(global_messagepath, messagepath, sizeof(global_messagepath)); + else + global_messagepath[0]= '\0'; + +} #endif + +void BLF_lang_set(const char *str) +{ +#if defined (_WIN32) || defined(__APPLE__) + BLI_setenv("LANG", str); #else char *locreturn= setlocale(LC_ALL, str); if (locreturn == NULL) { diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 4724ee19aaa..17b56864d1e 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -41,6 +41,7 @@ struct bAction; struct bActionGroup; struct FCurve; struct bPose; +struct bItasc; struct bPoseChannel; struct Object; struct Scene; @@ -51,7 +52,7 @@ struct ID; extern "C" { #endif -/* Action API ----------------- */ +/* Action Lib Stuff ----------------- */ /* Allocate a new bAction with the given name */ struct bAction *add_empty_action(const char name[]); @@ -65,6 +66,31 @@ void free_action(struct bAction *act); // XXX is this needed? void make_local_action(struct bAction *act); + +/* Action API ----------------- */ + +/* types of transforms applied to the given item + * - these are the return falgs for action_get_item_transforms() + */ +typedef enum eAction_TransformFlags { + /* location */ + ACT_TRANS_LOC = (1<<0), + /* rotation */ + ACT_TRANS_ROT = (1<<1), + /* scaling */ + ACT_TRANS_SCALE = (1<<2), + + /* all flags */ + ACT_TRANS_ALL = (ACT_TRANS_LOC|ACT_TRANS_ROT|ACT_TRANS_SCALE), +} eAction_TransformFlags; + +/* Return flags indicating which transforms the given object/posechannel has + * - if 'curves' is provided, a list of links to these curves are also returned + * whose nodes WILL NEED FREEING + */ +short action_get_item_transforms(struct bAction *act, struct Object *ob, struct bPoseChannel *pchan, ListBase *curves); + + /* Some kind of bounding box operation on the action */ void calc_action_range(const struct bAction *act, float *start, float *end, short incl_modifiers); @@ -73,6 +99,9 @@ short action_has_motion(const struct bAction *act); /* Action Groups API ----------------- */ +/* Get the active action-group for an Action */ +struct bActionGroup *get_active_actiongroup(struct bAction *act); + /* Make the given Action Group the active one */ void set_active_action_group(struct bAction *act, struct bActionGroup *agrp, short select); @@ -126,11 +155,21 @@ struct bPoseChannel *get_active_posechannel(struct Object *ob); */ struct bPoseChannel *verify_pose_channel(struct bPose* pose, const char* name); - +/* Copy the data from the action-pose (src) into the pose */ +void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); /* sets constraint flags */ void update_pose_constraint_flags(struct bPose *pose); +/* return the name of structure pointed by pose->ikparam */ +const char *get_ikparam_name(struct bPose *pose); + +/* allocate and initialize pose->ikparam according to pose->iksolver */ +void init_pose_ikparam(struct bPose *pose); + +/* initialize a bItasc structure with default value */ +void init_pose_itasc(struct bItasc *itasc); + /* clears BONE_UNKEYED flags for frame changing */ // XXX to be depreceated for a more general solution in animsys... void framechange_poses_clear_unkeyed(void); @@ -153,16 +192,6 @@ void copy_pose_result(struct bPose *to, struct bPose *from); /* clear all transforms */ void rest_pose(struct bPose *pose); -/* Game Engine ------------------------- */ - -/* exported for game engine */ -void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */ -void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); - -/* functions used by the game engine */ -void game_copy_pose(struct bPose **dst, struct bPose *src); -void game_free_pose(struct bPose *pose); - #ifdef __cplusplus }; #endif diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index 4b1e758da54..32c5ff81740 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -39,14 +39,7 @@ struct PartEff; struct Scene; struct ListBase; -typedef struct DupliObject { - struct DupliObject *next, *prev; - struct Object *ob; - unsigned int origlay; - int index, no_draw, type, animated; - float mat[4][4], omat[4][4]; - float orco[3], uv[2]; -} DupliObject; +#include "DNA_object_types.h" void free_path(struct Path *path); void calc_curvepath(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 1cbb2331782..e5d0c4274b3 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -89,6 +89,7 @@ void where_is_armature (struct bArmature *arm); void where_is_armature_bone(struct Bone *bone, struct Bone *prevbone); void armature_rebuild_pose(struct Object *ob, struct bArmature *arm); void where_is_pose (struct Scene *scene, struct Object *ob); +void where_is_pose_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime); /* get_objectspace_bone_matrix has to be removed still */ void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed); @@ -102,10 +103,8 @@ void armature_mat_pose_to_bone(struct bPoseChannel *pchan, float inmat[][4], flo void armature_loc_pose_to_bone(struct bPoseChannel *pchan, float *inloc, float *outloc); void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float arm_mat[][4]); -/* Animation functions */ -struct PoseTree *ik_tree_to_posetree(struct Object *ob, struct Bone *bone); -void solve_posetree(PoseTree *tree); -void free_posetree(PoseTree *tree); +/* Rotation Mode Conversions - Used for PoseChannels + Objects... */ +void BKE_rotMode_change_values(float quat[4], float eul[3], short oldMode, short newMode); /* B-Bone support */ typedef struct Mat4 { diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h index acceff863b9..fb65c9c8920 100644 --- a/source/blender/blenkernel/BKE_boids.h +++ b/source/blender/blenkernel/BKE_boids.h @@ -35,9 +35,7 @@ #include "DNA_boid_types.h" typedef struct BoidBrainData { - Scene *scene; - struct Object *ob; - struct ParticleSystem *psys; + struct ParticleSimulationData *sim; struct ParticleSettings *part; float timestep, cfra, dfra; float wanted_co[3], wanted_speed; diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 4d24a2433b3..f302618e60d 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -60,10 +60,10 @@ typedef enum { BRUSH_PRESET_MAX } BrushCurvePreset; void brush_curve_preset(struct Brush *b, BrushCurvePreset preset); -float brush_curve_strength(struct Brush *br, float p, const float len); +float brush_curve_strength_clamp(struct Brush *br, float p, const float len); +float brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */ /* sampling */ -float brush_sample_falloff(struct Brush *brush, float dist); void brush_sample_tex(struct Brush *brush, float *xy, float *rgba); void brush_imbuf_new(struct Brush *brush, short flt, short texfalloff, int size, struct ImBuf **imbuf); diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index e4eed084a3d..e0df75f41b9 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -139,7 +139,7 @@ void interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], ///////////////////////////////////////////////// // used in effect.c ///////////////////////////////////////////////// -CollisionModifierData **get_collisionobjects(struct Scene *scene, Object *self, int *numcollobj); +Object **get_collisionobjects(struct Scene *scene, Object *self, int *numcollobj); ///////////////////////////////////////////////// diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index a0061173438..126816f5a95 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -38,6 +38,9 @@ struct Scene; struct bPoseChannel; /* ---------------------------------------------------------------------------- */ +#ifdef __cplusplus +extern "C" { +#endif /* special struct for use in constraint evaluation */ typedef struct bConstraintOb { @@ -131,6 +134,9 @@ void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, void get_constraint_target_matrix(struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime); void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime); +#ifdef __cplusplus +} +#endif #endif diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index e242ead3b87..17a4749f704 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -96,19 +96,24 @@ void draw_all_deps(void); /* ********** API *************** */ /* Note that the DAG never executes changes in Objects, only sets flags in Objects */ + /* (re)-create dependency graph for scene */ void DAG_scene_sort(struct Scene *sce); /* flag all objects that need recalc because they're animated */ void DAG_scene_update_flags(struct Scene *sce, unsigned int lay); - /* flag all objects that need recalc because they're animated, influencing this object only */ -void DAG_object_update_flags(struct Scene *sce, struct Object *ob, unsigned int lay); - /* flushes all recalc flags in objects down the dependency tree */ void DAG_scene_flush_update(struct Scene *sce, unsigned int lay, int time); + + /* flag all IDs that need recalc because they're animated, influencing + this ID only. only for objects currently */ +void DAG_id_update_flags(struct ID *id); /* flushes all recalc flags for this object down the dependency tree, - but not the DAG only supports objects and object data currently */ + but note the DAG only supports objects and object data currently */ void DAG_id_flush_update(struct ID *id, short flag); + /* when setting manual RECALC flags, call this afterwards */ +void DAG_ids_flush_update(int time); + /* (re)-create dependency graph for armature pose */ void DAG_pose_sort(struct Object *ob); #endif diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index cda64c6b241..94d0864024b 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -35,6 +35,8 @@ struct DriverTarget; struct BezTriple; +#include "DNA_curve_types.h" + /* ************** Keyframe Tools ***************** */ // XXX this stuff is defined in BKE_ipo.h too, so maybe skip for now? @@ -153,6 +155,11 @@ void copy_fcurves(ListBase *dst, ListBase *src); /* find matching F-Curve in the given list of F-Curves */ struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index); +/* Binary search algorithm for finding where to 'insert' BezTriple with given frame number. + * Returns the index to insert at (data already at that index will be offset if replace is 0) + */ +int binarysearch_bezt_index(struct BezTriple array[], float frame, int arraylen, short *replace); + /* get the time extents for F-Curve */ void calc_fcurve_range(struct FCurve *fcu, float *min, float *max); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 816baa20467..47ab6f324d3 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -125,6 +125,9 @@ void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf); /* called on frame change or before render */ void BKE_image_user_calc_imanr(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_node.h b/source/blender/blenkernel/BKE_node.h index cbb37918d04..ea1707c19bf 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -42,7 +42,7 @@ struct bNode; struct bNodeLink; struct bNodeSocket; struct bNodeStack; -struct uiBlock; +struct uiLayout; struct rctf; struct ListBase; struct RenderData; @@ -52,6 +52,7 @@ struct Tex; struct GPUMaterial; struct GPUNode; struct GPUNodeStack; +struct PointerRNA; /* ************** NODE TYPE DEFINITIONS ***** */ @@ -82,7 +83,7 @@ typedef struct bNodeType { void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **); /* this line is set on startup of blender */ - int (*butfunc)(struct uiBlock *, struct bNodeTree *, struct bNode *, struct rctf *); + void (*uifunc)(struct uiLayout *, struct PointerRNA *ptr); void (*initfunc)(struct bNode *); void (*freestoragefunc)(struct bNode *); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index c22778f5a30..5850ddaca08 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -61,6 +61,23 @@ struct BVHTreeRayHit; #define PARTICLE_P ParticleData *pa; int p #define LOOP_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) +#define LOOP_EXISTING_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) if(!(pa->flag & PARS_UNEXIST)) +#define LOOP_SHOWN_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) if(!(pa->flag & (PARS_UNEXIST|PARS_NO_DISP))) + +#define PSYS_FRAND_COUNT 1024 +#define PSYS_FRAND(seed) psys->frand[(seed) % PSYS_FRAND_COUNT] + +/* fast but sure way to get the modifier*/ +#define PARTICLE_PSMD ParticleSystemModifierData *psmd = sim->psmd ? sim->psmd : psys_get_modifier(sim->ob, sim->psys) + +/* common stuff that many particle functions need */ +typedef struct ParticleSimulationData { + struct Scene *scene; + struct Object *ob; + struct ParticleSystem *psys; + struct ParticleSystemModifierData *psmd; + float timestep; +} ParticleSimulationData; typedef struct ParticleEffectorCache { struct ParticleEffectorCache *next, *prev; @@ -118,11 +135,8 @@ typedef struct ParticleCacheKey{ typedef struct ParticleThreadContext { /* shared */ - struct Scene *scene; - struct Object *ob; + struct ParticleSimulationData sim; struct DerivedMesh *dm; - struct ParticleSystemModifierData *psmd; - struct ParticleSystem *psys; struct Material *ma; /* distribution */ @@ -166,8 +180,7 @@ typedef struct ParticleBillboardData int lock, num; int totnum; short align, uv_split, anim, split_offset; -} -ParticleBillboardData; +} ParticleBillboardData; /* container for moving data between deflet_particle and particle_intersect_face */ typedef struct ParticleCollision @@ -179,40 +192,40 @@ typedef struct ParticleCollision float co1[3], co2[3]; // ray start and end points float ray_len; // original length of co2-co1, needed for collision time evaluation float t; // time of previous collision, needed for substracting face velocity -} -ParticleCollision; +} ParticleCollision; + +typedef struct ParticleDrawData { + float *vdata, *vd; /* vertice data */ + float *ndata, *nd; /* normal data */ + float *cdata, *cd; /* color data */ + float *vedata, *ved; /* velocity data */ + float *ma_r, *ma_g, *ma_b; + int tot_vec_size, flag; + int totpoint, totve; +} ParticleDrawData; + +#define PARTICLE_DRAW_DATA_UPDATED 1 /* ----------- functions needed outside particlesystem ---------------- */ /* particle.c */ int count_particles(struct ParticleSystem *psys); int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur); -int psys_count_keys(struct ParticleSystem *psys); -char *psys_menu_string(struct Object *ob, int for_sb); struct ParticleSystem *psys_get_current(struct Object *ob); +/* for rna */ short psys_get_current_num(struct Object *ob); void psys_set_current_num(Object *ob, int index); struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); -//struct ParticleSystem *psys_get(struct Object *ob, int index); -struct ParticleData *psys_get_selected_particle(struct ParticleSystem *psys, int *index); -struct ParticleKey *psys_get_selected_key(struct ParticleSystem *psys, int pa_index, int *key_index); -void psys_change_act(void *ob_v, void *act_v); -struct Object *psys_get_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); -void psys_disable_all(struct Object *ob); -void psys_enable_all(struct Object *ob); -int psys_ob_has_hair(struct Object *ob); + +struct Object *psys_get_lattice(struct ParticleSimulationData *sim); + int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys); int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys); -void psys_free_boid_rules(struct ListBase *list); +/* free */ void psys_free_settings(struct ParticleSettings *part); -void free_child_path_cache(struct ParticleSystem *psys); void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit); -void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics); -void free_keyed_keys(struct ParticleSystem *psys); -void psys_free_particles(struct ParticleSystem *psys); void psys_free(struct Object * ob, struct ParticleSystem * psys); -void psys_free_children(struct ParticleSystem *psys); void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset); void psys_render_restore(struct Object *ob, struct ParticleSystem *psys); @@ -234,45 +247,38 @@ struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc); void make_local_particlesettings(struct ParticleSettings *part); -struct LinkNode *psys_using_settings(struct Scene *scene, struct ParticleSettings *part, int flush_update); void psys_reset(struct ParticleSystem *psys, int mode); -void psys_find_parents(struct Object *ob, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys); +void psys_find_parents(struct ParticleSimulationData *sim); -void psys_cache_paths(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, float cfra); +void psys_cache_paths(struct ParticleSimulationData *sim, float cfra); void psys_cache_edit_paths(struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra); -void psys_cache_child_paths(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, float cfra, int editupdate); +void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, int editupdate); int do_guide(struct Scene *scene, struct ParticleKey *state, int pa_num, float time, struct ListBase *lb); -float psys_get_size(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct IpoCurve *icu_size, struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleData *pa, float *vg_size); -float psys_get_timestep(struct ParticleSettings *part); +float psys_get_timestep(struct ParticleSimulationData *sim); float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime); float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time); -void psys_get_particle_on_path(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel); -int psys_get_particle_state(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always); +void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, struct ParticleKey *state, int vel); +int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always); + +/* for anim.c */ void psys_get_dupli_texture(struct Object *ob, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco); -void psys_get_dupli_path_transform(struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale); +void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale); -ParticleThread *psys_threads_create(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); -int psys_threads_init_distribution(ParticleThread *threads, struct Scene *scene, struct DerivedMesh *dm, int from); -int psys_threads_init_path(ParticleThread *threads, struct Scene *scene, float cfra, int editupdate); +ParticleThread *psys_threads_create(struct ParticleSimulationData *sim); void psys_threads_free(ParticleThread *threads); -void psys_thread_distribute_particle(ParticleThread *thread, struct ParticleData *pa, struct ChildParticle *cpa, int p); -void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i); - void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]); /* particle_system.c */ struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt); -void psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys); -void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, struct Object **target_ob, struct ParticleSystem **target_psys); +void psys_count_keyed_targets(struct ParticleSimulationData *sim); +//void psys_get_reactor_target(struct ParticleSimulationData *sim, struct Object **target_ob, struct ParticleSystem **target_psys); -void psys_init_effectors(struct Scene *scene, struct Object *obsrc, struct Group *group, struct ParticleSystem *psys); -void psys_end_effectors(struct ParticleSystem *psys); +int psys_update_effectors(ParticleSimulationData *sim, float cfra, int precalc); void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys); -void psys_end_temp_pointcache(struct ParticleSystem *psys); -void psys_get_pointcache_start_end(struct Scene *scene, struct ParticleSystem *psys, int *sfra, int *efra); +void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, int *sfra, int *efra); void psys_check_boid_data(struct ParticleSystem *psys); @@ -280,39 +286,45 @@ void particle_system_update(struct Scene *scene, struct Object *ob, struct Parti /* ----------- functions needed only inside particlesystem ------------ */ /* particle.c */ +void psys_disable_all(struct Object *ob); +void psys_enable_all(struct Object *ob); + +void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics); +void free_keyed_keys(struct ParticleSystem *psys); +void psys_free_particles(struct ParticleSystem *psys); +void psys_free_children(struct ParticleSystem *psys); + void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, int velocity); -void psys_key_to_object(struct Object *ob, struct ParticleKey *key, float imat[][4]); -//void psys_key_to_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key); -//void psys_key_from_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key); -//void psys_face_mat(struct DerivedMesh *dm, struct ParticleData *pa, float mat[][4]); void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float *vec); -//void psys_vec_rot_from_face(struct DerivedMesh *dm, struct ParticleData *pa, float *vec); void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); +void psys_free_pdd(struct ParticleSystem *psys); + float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup); -void psys_get_texture(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys, struct ParticleData *pa, struct ParticleTexture *ptex, int event); +void psys_get_texture(struct ParticleSimulationData *sim, struct Material *ma, struct ParticleData *pa, struct ParticleTexture *ptex, int event); void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, float (*orcodata)[3], float *uv, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); float psys_particle_value_from_verts(struct DerivedMesh *dm, short from, struct ParticleData *pa, float *values); -float psys_interpolate_value_from_verts(struct DerivedMesh *dm, short from, int index, float *fw, float *values); void psys_get_from_key(struct ParticleKey *key, float *loc, float *vel, float *rot, float *time); +/* only in edisparticle.c*/ int psys_intersect_dm(struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float *vert_cos, float *co1, float* co2, float *min_d, int *min_face, float *min_uv, float *face_minmax, float *pa_minmax, float radius, float *ipoint); +/* BLI_bvhtree_ray_cast callback */ void particle_intersect_face(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit); void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); /* particle_system.c */ -void initialize_particle(struct ParticleData *pa, int p, struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd); +void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, int p); int effector_find_co(struct Scene *scene, float *pco, struct SurfaceModifierData *sur, struct Object *ob, struct PartDeflect *pd, float *co, float *nor, float *vel, int *index); -void do_effectors(int pa_no, struct ParticleData *pa, struct ParticleKey *state, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, float *texco, float *force_field, float *vel,float framestep, float cfra); +void do_effectors(struct ParticleSimulationData *sim, int pa_no, struct ParticleData *pa, struct ParticleKey *state, float *texco, float *force_field, float *vel,float framestep, float cfra); +void psys_end_effectors(struct ParticleSystem *psys); void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys); int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, float *fw, struct LinkNode *node); -void reset_particle(struct Scene *scene, struct ParticleData *pa, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct Object *ob, - float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot); +void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra); /* psys_reset */ diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 4fcb7c881be..ee04d4f47bc 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -230,11 +230,11 @@ void BKE_spacedata_copyfirst(ListBase *lb1, ListBase *lb2); /* area/regions */ struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar); void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar); +void BKE_screen_area_free(struct ScrArea *sa); -void BKE_screen_area_free(struct ScrArea *sa); - +/* screen */ void free_screen(struct bScreen *sc); - +unsigned int BKE_screen_visible_layers(struct bScreen *screen); #endif diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index e9f6eb21e36..cbce4663d6f 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -71,7 +71,7 @@ void sound_update_playing(struct bContext *C); void sound_scrub(struct bContext *C); #ifdef AUD_CAPI -AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end); +AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end, float volume); #endif void sound_stop_all(struct bContext *C); diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index bd14053d121..185e32ecdfa 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -48,6 +48,8 @@ int reopen_text (struct Text *text); struct Text* add_text (char *file, const char *relpath); struct Text* copy_text (struct Text *ta); void unlink_text (struct Main *bmain, struct Text *text); +void clear_text(struct Text *text); +void write_text(struct Text *text, char *str); char* txt_to_buf (struct Text *text); void txt_clean_text (struct Text *text); @@ -74,7 +76,7 @@ void txt_delete_selected (struct Text *text); void txt_sel_all (struct Text *text); void txt_sel_line (struct Text *text); char* txt_sel_to_buf (struct Text *text); -void txt_insert_buf (struct Text *text, char *in_buffer); +void txt_insert_buf (struct Text *text, const char *in_buffer); void txt_print_undo (struct Text *text); void txt_undo_add_toop (struct Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc); void txt_do_undo (struct Text *text); @@ -102,6 +104,14 @@ struct TextMarker *txt_next_marker (struct Text *text, struct TextMarker *marke struct TextMarker *txt_prev_marker_color (struct Text *text, struct TextMarker *marker); struct TextMarker *txt_next_marker_color (struct Text *text, struct TextMarker *marker); +/* utility functions, could be moved somewhere more generic but are python/text related */ +int text_check_bracket(char ch); +int text_check_delim(char ch); +int text_check_digit(char ch); +int text_check_identifier(char ch); +int text_check_whitespace(char ch); + + /* Undo opcodes */ /* Simple main cursor movement */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 68aed2b0184..f60cade61ed 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -30,12 +30,10 @@ SET(INC . ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna ../render/extern/include ../../../intern/decimation/extern ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern - ../../../intern/iksolver/extern ../blenloader + ../../../intern/iksolver/extern ../blenloader ../ikplugin ../nodes ../../../extern/glew/include ../gpu ../makesrna ../../../intern/smoke/extern ../../../intern/bsp/extern ../blenfont ../../../intern/audaspace/intern - ../../../extern/lzo/minilzo - ../../../extern/lzma ${ZLIB_INC} ) @@ -76,6 +74,16 @@ IF(NOT WITH_ELBEEM) ADD_DEFINITIONS(-DDISABLE_ELBEEM) ENDIF(NOT WITH_ELBEEM) +IF(WITH_LZO) + SET(INC ${INC} ../../../extern/lzo/minilzo) + ADD_DEFINITIONS(-DWITH_LZO) +ENDIF(WITH_LZO) + +IF(WITH_LZMA) + SET(INC ${INC} ../../../extern/lzma) + ADD_DEFINITIONS(-DWITH_LZMA) +ENDIF(WITH_LZMA) + IF(WIN32) SET(INC ${INC} ${PTHREADS_INC}) ENDIF(WIN32) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 1f42390504d..63631ddc40f 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -5,14 +5,12 @@ sources = env.Glob('intern/*.c') incs = '. #/intern/guardedalloc #/intern/memutil ../editors/include ../blenlib ../blenfont ../makesdna' incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna' -incs += ' ../imbuf ../avi #/intern/elbeem/extern ../nodes' +incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes' incs += ' #/intern/iksolver/extern ../blenloader' incs += ' #/extern/bullet2/src' incs += ' #/intern/opennl/extern #/intern/bsp/extern' incs += ' ../gpu #/extern/glew/include' incs += ' #/intern/smoke/extern' -incs += ' #/extern/lzo/minilzo' -incs += ' #/extern/lzma' incs += ' #/intern/audaspace/intern' incs += ' ' + env['BF_OPENGL_INC'] @@ -61,7 +59,15 @@ if env['BF_NO_ELBEEM']: if env['WITH_BF_LCMS']: defs.append('WITH_LCMS') - + +if env['WITH_BF_LZO']: + incs += ' #/extern/lzo/minilzo' + defs.append('WITH_LZO') + +if env['WITH_BF_LZMA']: + incs += ' #/extern/lzma' + defs.append('WITH_LZMA') + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 6c2edc9e25f..26b9b9ef0dd 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -47,6 +47,7 @@ CPPFLAGS += -I$(NAN_AUDASPACE)/include CPPFLAGS += -I../../makesdna CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../imbuf +CPPFLAGS += -I../../ikplugin # This mod uses the BLI and BLO module CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../blenloader @@ -85,14 +86,24 @@ CPPFLAGS += -I../../gpu # path to our own external headerfiles CPPFLAGS += -I.. -# path to bullet2, for cloth -CPPFLAGS += -I$(NAN_BULLET2)/include CPPFLAGS += -I$(NAN_FREETYPE)/include CPPFLAGS += -I$(NAN_FREETYPE)/include/freetype2 +# path to bullet2, for cloth +ifeq ($(NAN_USE_BULLET), true) + CPPFLAGS += -I$(NAN_BULLET2)/include +endif + # lzo and lzma, for pointcache -CPPFLAGS += -I$(NAN_LZO)/minilzo -CPPFLAGS += -I$(NAN_LZMA) +ifeq ($(WITH_LZO),true) + CPPFLAGS += -I$(NAN_LZO)/minilzo + CPPFLAGS += -DWITH_LZO +endif + +ifeq ($(WITH_LZO),true) + CPPFLAGS += -I$(NAN_LZMA) + CPPFLAGS += -DWITH_LZMA +endif ifeq ($(WITH_FFMPEG),true) CPPFLAGS += -DWITH_FFMPEG diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 47de044ea25..b8dc9fd049d 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -62,6 +62,7 @@ #include "BKE_main.h" #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BIK_api.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -212,6 +213,7 @@ bAction *copy_action (bAction *src) return dst; } +/* *************** Action Groups *************** */ /* Get the active action-group for an Action */ bActionGroup *get_active_actiongroup (bAction *act) @@ -404,7 +406,7 @@ bActionGroup *action_groups_find_named (bAction *act, const char name[]) return NULL; } -/* ************************ Pose channels *************** */ +/* *************** Pose channels *************** */ /* usually used within a loop, so we got a N^2 slowdown */ bPoseChannel *get_pose_channel(const bPose *pose, const char *name) @@ -450,7 +452,7 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name) chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f; chan->limitmax[0]= chan->limitmax[1]= chan->limitmax[2]= 180.0f; chan->stiffness[0]= chan->stiffness[1]= chan->stiffness[2]= 0.0f; - + chan->ikrotweight = chan->iklinweight = 0.0f; Mat4One(chan->constinv); BLI_addtail(&pose->chanbase, chan); @@ -476,7 +478,18 @@ bPoseChannel *get_active_posechannel (Object *ob) return NULL; } - +const char *get_ikparam_name(bPose *pose) +{ + if (pose) { + switch (pose->iksolver) { + case IKSOLVER_LEGACY: + return NULL; + case IKSOLVER_ITASC: + return "bItasc"; + } + } + return NULL; +} /* dst should be freed already, makes entire duplicate */ void copy_pose (bPose **dst, bPose *src, int copycon) { @@ -498,7 +511,10 @@ void copy_pose (bPose **dst, bPose *src, int copycon) outPose= MEM_callocN(sizeof(bPose), "pose"); BLI_duplicatelist(&outPose->chanbase, &src->chanbase); - + outPose->iksolver = src->iksolver; + outPose->ikdata = NULL; + outPose->ikparam = MEM_dupallocN(src->ikparam); + if (copycon) { for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) { copy_constraints(&listb, &pchan->constraints); // copy_constraints NULLs listb @@ -510,6 +526,39 @@ void copy_pose (bPose **dst, bPose *src, int copycon) *dst=outPose; } +void init_pose_itasc(bItasc *itasc) +{ + if (itasc) { + itasc->iksolver = IKSOLVER_ITASC; + itasc->minstep = 0.01f; + itasc->maxstep = 0.06f; + itasc->numiter = 100; + itasc->numstep = 4; + itasc->precision = 0.005f; + itasc->flag = ITASC_AUTO_STEP|ITASC_INITIAL_REITERATION|ITASC_SIMULATION; + itasc->feedback = 20.f; + itasc->maxvel = 50.f; + itasc->solver = ITASC_SOLVER_SDLS; + itasc->dampmax = 0.5; + itasc->dampeps = 0.15; + } +} +void init_pose_ikparam(bPose *pose) +{ + bItasc *itasc; + switch (pose->iksolver) { + case IKSOLVER_ITASC: + itasc = MEM_callocN(sizeof(bItasc), "itasc"); + init_pose_itasc(itasc); + pose->ikparam = itasc; + break; + case IKSOLVER_LEGACY: + default: + pose->ikparam = NULL; + break; + } +} + void free_pose_channels(bPose *pose) { bPoseChannel *pchan; @@ -533,133 +582,15 @@ void free_pose(bPose *pose) /* free pose-groups */ if (pose->agroups.first) BLI_freelistN(&pose->agroups); - - /* free pose */ - MEM_freeN(pose); - } -} - -void game_copy_pose(bPose **dst, bPose *src) -{ - bPose *out; - bPoseChannel *pchan, *outpchan; - GHash *ghash; - - /* the game engine copies the current armature pose and then swaps - * the object pose pointer. this makes it possible to change poses - * without affecting the original blender data. */ - - if (!src) { - *dst=NULL; - return; - } - else if (*dst==src) { - printf("copy_pose source and target are the same\n"); - *dst=NULL; - return; - } - - out= MEM_dupallocN(src); - out->agroups.first= out->agroups.last= NULL; - BLI_duplicatelist(&out->chanbase, &src->chanbase); - - /* remap pointers */ - ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - - pchan= src->chanbase.first; - outpchan= out->chanbase.first; - for (; pchan; pchan=pchan->next, outpchan=outpchan->next) - BLI_ghash_insert(ghash, pchan, outpchan); - - for (pchan=out->chanbase.first; pchan; pchan=pchan->next) { - pchan->parent= BLI_ghash_lookup(ghash, pchan->parent); - pchan->child= BLI_ghash_lookup(ghash, pchan->child); - pchan->path= NULL; - } - - BLI_ghash_free(ghash, NULL, NULL); - - *dst=out; -} + /* free IK solver state */ + BIK_clear_data(pose); -/* Only allowed for Poses with identical channels */ -void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/) -{ - short mode= ACTSTRIPMODE_BLEND; - - bPoseChannel *dchan; - const bPoseChannel *schan; - bConstraint *dcon, *scon; - float dstweight; - int i; + /* free IK solver param */ + if (pose->ikparam) + MEM_freeN(pose->ikparam); - switch (mode){ - case ACTSTRIPMODE_BLEND: - dstweight = 1.0F - srcweight; - break; - case ACTSTRIPMODE_ADD: - dstweight = 1.0F; - break; - default : - dstweight = 1.0F; - } - - schan= src->chanbase.first; - for (dchan = dst->chanbase.first; dchan; dchan=dchan->next, schan= schan->next){ - if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) { - /* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */ - - /* Do the transformation blend */ - if (schan->flag & POSE_ROT) { - /* quat interpolation done separate */ - if (schan->rotmode == PCHAN_ROT_QUAT) { - float dquat[4], squat[4]; - - QUATCOPY(dquat, dchan->quat); - QUATCOPY(squat, schan->quat); - if (mode==ACTSTRIPMODE_BLEND) - QuatInterpol(dchan->quat, dquat, squat, srcweight); - else { - QuatMulFac(squat, srcweight); - QuatMul(dchan->quat, dquat, squat); - } - - NormalQuat(dchan->quat); - } - } - - for (i=0; i<3; i++) { - /* blending for loc and scale are pretty self-explanatory... */ - if (schan->flag & POSE_LOC) - dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); - if (schan->flag & POSE_SIZE) - dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); - - /* euler-rotation interpolation done here instead... */ - // FIXME: are these results decent? - if ((schan->flag & POSE_ROT) && (schan->rotmode)) - dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight); - } - dchan->flag |= schan->flag; - } - for(dcon= dchan->constraints.first, scon= schan->constraints.first; dcon && scon; dcon= dcon->next, scon= scon->next) { - /* no 'add' option for constraint blending */ - dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight; - } - } - - /* this pose is now in src time */ - dst->ctime= src->ctime; -} - -void game_free_pose(bPose *pose) -{ - if (pose) { - /* we don't free constraints, those are owned by the original pose */ - if(pose->chanbase.first) - BLI_freelistN(&pose->chanbase); - + /* free pose */ MEM_freeN(pose); } } @@ -818,7 +749,7 @@ void pose_remove_group (Object *ob) } } -/* ************** time ****************** */ +/* ************** F-Curve Utilities for Actions ****************** */ /* Check if the given action has any keyframes */ short action_has_motion(const bAction *act) @@ -916,6 +847,98 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_ } } +/* Return flags indicating which transforms the given object/posechannel has + * - if 'curves' is provided, a list of links to these curves are also returned + */ +short action_get_item_transforms (bAction *act, Object *ob, bPoseChannel *pchan, ListBase *curves) +{ + PointerRNA ptr; + FCurve *fcu; + char *basePath=NULL; + short flags=0; + + /* build PointerRNA from provided data to obtain the paths to use */ + if (pchan) + RNA_pointer_create((ID *)ob, &RNA_PoseChannel, pchan, &ptr); + else if (ob) + RNA_id_pointer_create((ID *)ob, &ptr); + else + return 0; + + /* get the basic path to the properties of interest */ + basePath= RNA_path_from_ID_to_struct(&ptr); + if (basePath == NULL) + return 0; + + /* search F-Curves for the given properties + * - we cannot use the groups, since they may not be grouped in that way... + */ + for (fcu= act->curves.first; fcu; fcu= fcu->next) { + char *bPtr=NULL, *pPtr=NULL; + + /* if enough flags have been found, we can stop checking unless we're also getting the curves */ + if ((flags == ACT_TRANS_ALL) && (curves == NULL)) + break; + + /* just in case... */ + if (fcu->rna_path == NULL) + continue; + + /* step 1: check for matching base path */ + bPtr= strstr(fcu->rna_path, basePath); + + if (bPtr) { + /* step 2: check for some property with transforms + * - to speed things up, only check for the ones not yet found + * unless we're getting the curves too + * - if we're getting the curves, the BLI_genericNodeN() creates a LinkData + * node wrapping the F-Curve, which then gets added to the list + * - once a match has been found, the curve cannot possibly be any other one + */ + if ((curves) || (flags & ACT_TRANS_LOC) == 0) { + pPtr= strstr(fcu->rna_path, "location"); + if ((pPtr) && (pPtr >= bPtr)) { + flags |= ACT_TRANS_LOC; + + if (curves) + BLI_addtail(curves, BLI_genericNodeN(fcu)); + continue; + } + } + + if ((curves) || (flags & ACT_TRANS_SCALE) == 0) { + pPtr= strstr(fcu->rna_path, "scale"); + if ((pPtr) && (pPtr >= bPtr)) { + flags |= ACT_TRANS_SCALE; + + if (curves) + BLI_addtail(curves, BLI_genericNodeN(fcu)); + continue; + } + } + + if ((curves) || (flags & ACT_TRANS_ROT) == 0) { + pPtr= strstr(fcu->rna_path, "rotation"); + if ((pPtr) && (pPtr >= bPtr)) { + flags |= ACT_TRANS_ROT; + + if (curves) + BLI_addtail(curves, BLI_genericNodeN(fcu)); + continue; + } + } + } + } + + /* free basePath */ + MEM_freeN(basePath); + + /* return flags found */ + return flags; +} + +/* ************** Pose Management Tools ****************** */ + /* Copy the data from the action-pose (src) into the pose */ /* both args are assumed to be valid */ /* exported to game engine */ @@ -1158,138 +1181,6 @@ static void blend_pose_offset_bone(bActionStrip *strip, bPose *dst, bPose *src, VecAddf(dst->cyclic_offset, dst->cyclic_offset, src->cyclic_offset); } -typedef struct NlaIpoChannel { - struct NlaIpoChannel *next, *prev; - float val; - void *poin; - int type; -} NlaIpoChannel; - -void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, const char *name, float ctime) -{ - bActionChannel *achan= get_action_channel(act, name); - IpoCurve *icu; - NlaIpoChannel *nic; - - if(achan==NULL) return; - - if(achan->ipo) { - calc_ipo(achan->ipo, ctime); - - for(icu= achan->ipo->curve.first; icu; icu= icu->next) { - /* skip IPO_BITS, is for layers and cannot be blended */ - if(icu->vartype != IPO_BITS) { - nic= MEM_callocN(sizeof(NlaIpoChannel), "NlaIpoChannel"); - BLI_addtail(lb, nic); - nic->val= icu->curval; - nic->poin= get_ipo_poin(id, icu, &nic->type); - } - } - } - - /* constraint channels only for objects */ - if(GS(id->name)==ID_OB) { - Object *ob= (Object *)id; - bConstraint *con; - bConstraintChannel *conchan; - - for (con=ob->constraints.first; con; con=con->next) { - conchan = get_constraint_channel(&achan->constraintChannels, con->name); - - if(conchan && conchan->ipo) { - calc_ipo(conchan->ipo, ctime); - - icu= conchan->ipo->curve.first; // only one ipo now - if(icu) { - nic= MEM_callocN(sizeof(NlaIpoChannel), "NlaIpoChannel constr"); - BLI_addtail(lb, nic); - nic->val= icu->curval; - nic->poin= &con->enforce; - nic->type= IPO_FLOAT; - } - } - } - } -} - -static NlaIpoChannel *find_nla_ipochannel(ListBase *lb, void *poin) -{ - NlaIpoChannel *nic; - - if(poin) { - for(nic= lb->first; nic; nic= nic->next) { - if(nic->poin==poin) - return nic; - } - } - return NULL; -} - - -static void blend_ipochannels(ListBase *dst, ListBase *src, float srcweight, int mode) -{ - NlaIpoChannel *snic, *dnic, *next; - float dstweight; - - switch (mode){ - case ACTSTRIPMODE_BLEND: - dstweight = 1.0F - srcweight; - break; - case ACTSTRIPMODE_ADD: - dstweight = 1.0F; - break; - default : - dstweight = 1.0F; - } - - for(snic= src->first; snic; snic= next) { - next= snic->next; - - dnic= find_nla_ipochannel(dst, snic->poin); - if(dnic==NULL) { - /* remove from src list, and insert in dest */ - BLI_remlink(src, snic); - BLI_addtail(dst, snic); - } - else { - /* we do the blend */ - dnic->val= dstweight*dnic->val + srcweight*snic->val; - } - } -} - -int execute_ipochannels(ListBase *lb) -{ - NlaIpoChannel *nic; - int count = 0; - - for(nic= lb->first; nic; nic= nic->next) { - if(nic->poin) { - write_ipo_poin(nic->poin, nic->type, nic->val); - count++; - } - } - return count; -} - -/* nla timing */ - -/* this now only used for repeating cycles, to enable fields and blur. */ -/* the whole time control in blender needs serious thinking... */ -static float nla_time(Scene *scene, float cfra, float unit) -{ - extern float bluroffs; // bad construct, borrowed from object.c for now - extern float fieldoffs; - - /* motion blur & fields */ - cfra+= unit*(bluroffs+fieldoffs); - - /* global time */ - cfra*= scene->r.framelen; - - return cfra; -} - /* added "sizecorr" here, to allow armatures to be scaled and still have striding. Only works for uniform scaling. In general I'd advise against scaling armatures ever though! (ton) */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 8cb88cdb786..e943d92a0b5 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -766,12 +766,12 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p GroupObject *go; Object *ob=0, **oblist=0, obcopy, *obcopylist=0; DupliObject *dob; + ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)}; ParticleSettings *part; ParticleData *pa; ChildParticle *cpa=0; ParticleKey state; ParticleCacheKey *cache; - ParticleSystemModifierData *psmd; float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], size=0.0; float (*obmat)[4], (*oldobmat)[4]; @@ -784,7 +784,6 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if(level>MAX_DUPLI_RECUR) return; part=psys->part; - psmd= psys_get_modifier(par, psys); if(part==0) return; @@ -816,7 +815,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p totpart = psys->totcached; } - psys->lattice = psys_get_lattice(scene, par, psys); + psys->lattice = psys_get_lattice(&sim); /* gather list of objects or single object */ if(part->ren_as==PART_DRAW_GR) { @@ -887,11 +886,11 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p /* hair we handle separate and compute transform based on hair keys */ if(a < totpart) { cache = psys->pathcache[a]; - psys_get_dupli_path_transform(par, psys, psmd, pa, 0, cache, pamat, &scale); + psys_get_dupli_path_transform(&sim, pa, 0, cache, pamat, &scale); } else { cache = psys->childcache[a-totpart]; - psys_get_dupli_path_transform(par, psys, psmd, 0, cpa, cache, pamat, &scale); + psys_get_dupli_path_transform(&sim, 0, cpa, cache, pamat, &scale); } VECCOPY(pamat[3], cache->co); @@ -901,7 +900,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else { /* first key */ state.time = ctime; - if(psys_get_particle_state(scene, par, psys, a, &state, 0) == 0) + if(psys_get_particle_state(&sim, a, &state, 0) == 0) continue; QuatToMat4(state.rot, pamat); @@ -921,7 +920,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated); Mat4CpyMat4(dob->omat, obcopylist[b].obmat); if(G.rendering) - psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco); + psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { @@ -940,7 +939,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p dob= new_dupli_object(lb, ob, mat, ob->lay, counter, OB_DUPLIPARTS, animated); Mat4CpyMat4(dob->omat, oldobmat); if(G.rendering) - psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco); + psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 2d6a97c48ae..07b7b6dc30c 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -40,6 +40,7 @@ #include "BLI_dynstr.h" #include "DNA_anim_types.h" +#include "DNA_scene_types.h" #include "BKE_animsys.h" #include "BKE_action.h" @@ -71,7 +72,7 @@ static short id_has_animdata (ID *id) switch (GS(id->name)) { /* has AnimData */ case ID_OB: - case ID_MB: case ID_CU: + case ID_MB: case ID_CU: case ID_AR: case ID_KE: case ID_PA: case ID_MA: case ID_TE: case ID_NT: @@ -210,26 +211,113 @@ static void make_local_strips(ListBase *strips) { NlaStrip *strip; - for(strip=strips->first; strip; strip=strip->next) { - if(strip->act) make_local_action(strip->act); - if(strip->remap && strip->remap->target) make_local_action(strip->remap->target); - + for (strip=strips->first; strip; strip=strip->next) { + if (strip->act) make_local_action(strip->act); + //if (strip->remap && strip->remap->target) make_local_action(strip->remap->target); + make_local_strips(&strip->strips); } } +/* Use local copy instead of linked copy of various ID-blocks */ void BKE_animdata_make_local(AnimData *adt) { NlaTrack *nlt; + + /* Actions - Active and Temp */ + if (adt->action) make_local_action(adt->action); + if (adt->tmpact) make_local_action(adt->tmpact); + /* Remaps */ + if (adt->remap && adt->remap->target) make_local_action(adt->remap->target); + + /* Drivers */ + // TODO: need to remap the ID-targets too? + + /* NLA Data */ + for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next) + make_local_strips(&nlt->strips); +} - if(adt->action) make_local_action(adt->action); - if(adt->tmpact) make_local_action(adt->tmpact); - if(adt->remap && adt->remap->target) make_local_action(adt->remap->target); +/* Path Validation -------------------------------------------- */ - for(nlt=adt->nla_tracks.first; nlt; nlt=nlt->next) - make_local_strips(&nlt->strips); +#if 0 +/* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate */ +static char *rna_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, char *oldpath) +{ + + + return oldpath; // FIXME!!! +} + +/* Check RNA-Paths for a list of F-Curves */ +static void fcurves_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, ListBase *curves) +{ + FCurve *fcu; + + /* we need to check every curve... */ + for (fcu= curves->first; fcu; fcu= fcu->next) { + /* firstly, handle the F-Curve's own path */ + fcu->rna_path= rna_path_rename_fix(owner_id, modPtr, newName, fcu->rna_path); + + /* driver? */ + if (fcu->driver) { + ChannelDriver *driver= fcu->driver; + DriverTarget *dtar; + + /* driver targets */ + for (dtar= driver->targets.first; dtar; dtar=dtar->next) { + dtat->rna_path= rna_path_rename_fix(dtar->id, modPtr, newName, dtar->rna_path); + } + } + } +} + +/* Fix all RNA-Paths for Actions linked to NLA Strips */ +static void nlastrips_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, ListBase *strips) +{ + NlaStrip *strip; + + /* recursively check strips, fixing only actions... */ + for (strip= strips->first; strip; strip= strip->next) { + /* fix strip's action */ + if (strip->act) + fcurves_path_rename_fix(owner_id, modPtr, newName, &strip->act->curves); + /* ignore own F-Curves, since those are local... */ + + /* check sub-strips (if metas) */ + nlastrips_path_rename_fix(owner_id, modPtr, newName, &strip->strips); + } } +/* Fix all RNA-Paths in the AnimData block used by the given ID block + * - the pointer of interest must not have had its new name assigned already, otherwise + * path matching for this will never work + */ +void BKE_animdata_fix_paths_rename (ID *owner_id, PointerRNA *modPtr, char *newName) +{ + AnimData *adt= BKE_animdata_from_id(owner_id); + NlaTrack *nlt; + + /* if no AnimData, no need to proceed */ + if (ELEM4(NULL, owner_id, adt, modPtr, newName)) + return; + + /* Active action and temp action */ + if (adt->action) + fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->action->curves); + if (adt->tmpact) + fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->tmpact->curves); + + /* Drivers - Drivers are really F-Curves */ + fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->drivers); + + /* NLA Data - Animation Data for Strips */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + + } +} +#endif + /* *********************************** */ /* KeyingSet API */ @@ -438,7 +526,7 @@ void BKE_keyingsets_free (ListBase *list) * - path: original path string (as stored in F-Curve data) * - dst: destination string to write data to */ -short animsys_remap_path (AnimMapper *remap, char *path, char **dst) +static short animsys_remap_path (AnimMapper *remap, char *path, char **dst) { /* is there a valid remapping table to use? */ //if (remap) { @@ -1485,7 +1573,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) } /* nodes */ - // TODO... + EVAL_ANIM_IDS(main->nodetree.first, ADT_RECALC_ANIM); /* textures */ EVAL_ANIM_IDS(main->tex.first, ADT_RECALC_ANIM); @@ -1517,10 +1605,16 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) AnimData *adt= BKE_animdata_from_id(id); Curve *cu= (Curve *)id; + /* set ctime variable for curve */ cu->ctime= ctime; + + /* now execute animation data on top of this as per normal */ BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM); } + /* armatures */ + EVAL_ANIM_IDS(main->armature.first, ADT_RECALC_ANIM); + /* meshes */ // TODO... @@ -1537,7 +1631,19 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) EVAL_ANIM_IDS(main->world.first, ADT_RECALC_ANIM); /* scenes */ - EVAL_ANIM_IDS(main->scene.first, ADT_RECALC_ANIM); + for (id= main->scene.first; id; id= id->next) { + AnimData *adt= BKE_animdata_from_id(id); + Scene *scene= (Scene *)id; + + /* do compositing nodes first (since these aren't included in main tree) */ + if (scene->nodetree) { + AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree); + BKE_animsys_evaluate_animdata((ID *)scene->nodetree, adt2, ctime, ADT_RECALC_ANIM); + } + + /* now execute scene animation data as per normal */ + BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM); + } } /* ***************************************** */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index c880925aa94..6220835a620 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -66,10 +66,9 @@ #include "BKE_object.h" #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BIK_api.h" #include "BKE_sketch.h" -#include "IK_solver.h" - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -1280,6 +1279,65 @@ void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float Mat4MulMat4(delta_mat, pose_mat, imat); } +/* **************** Rotation Mode Conversions ****************************** */ +/* Used for Objects and Pose Channels, since both can have multiple rotation representations */ + +/* Called from RNA when rotation mode changes + * - the result should be that the rotations given in the provided pointers have had conversions + * applied (as appropriate), such that the rotation of the element hasn't 'visually' changed + * + * - as in SDNA data, quat is used to store quaternions AND axis-angle rotations... + */ +void BKE_rotMode_change_values (float quat[4], float eul[3], short oldMode, short newMode) +{ + /* check if any change - if so, need to convert data */ + if (newMode > 0) { /* to euler */ + if (oldMode == ROT_MODE_AXISANGLE) { + /* axis-angle to euler */ + AxisAngleToEulO(&quat[1], quat[0], eul, newMode); + } + else if (oldMode == ROT_MODE_QUAT) { + /* quat to euler */ + QuatToEulO(quat, eul, newMode); + } + /* else { no conversion needed } */ + } + else if (newMode == ROT_MODE_QUAT) { /* to quat */ + if (oldMode == ROT_MODE_AXISANGLE) { + /* axis angle to quat */ + float q[4]; + + /* copy to temp var first, since quats and axis-angle are stored in same place */ + QuatCopy(q, quat); + AxisAngleToQuat(q, &quat[1], quat[0]); + } + else if (oldMode > 0) { + /* euler to quat */ + EulOToQuat(eul, oldMode, quat); + } + /* else { no conversion needed } */ + } + else { /* to axis-angle */ + if (oldMode > 0) { + /* euler to axis angle */ + EulOToAxisAngle(eul, oldMode, &quat[1], &quat[0]); + } + else if (oldMode == ROT_MODE_QUAT) { + /* quat to axis angle */ + float q[4]; + + /* copy to temp var first, since quats and axis-angle are stored in same place */ + QuatCopy(q, quat); + QuatToAxisAngle(q, &quat[1], &quat[0]); + } + + /* when converting to axis-angle, we need a special exception for the case when there is no axis */ + if (IS_EQ(quat[1], quat[2]) && IS_EQ(quat[2], quat[3])) { + /* for now, rotate around y-axis then (so that it simply becomes the roll) */ + quat[2]= 1.0f; + } + } +} /* **************** The new & simple (but OK!) armature evaluation ********* */ @@ -1569,409 +1627,10 @@ void armature_rebuild_pose(Object *ob, bArmature *arm) DAG_pose_sort(ob); ob->pose->flag &= ~POSE_RECALC; + ob->pose->flag |= POSE_WAS_REBUILT; } -/* ********************** THE IK SOLVER ******************* */ - - - -/* allocates PoseTree, and links that to root bone/channel */ -/* Note: detecting the IK chain is duplicate code... in drawarmature.c and in transform_conversions.c */ -static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) -{ - bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256], **oldchan; - PoseTree *tree; - PoseTarget *target; - bConstraint *con; - bKinematicConstraint *data= NULL; - int a, segcount= 0, size, newsize, *oldparent, parent; - - /* find IK constraint, and validate it */ - for(con= pchan_tip->constraints.first; con; con= con->next) { - if(con->type==CONSTRAINT_TYPE_KINEMATIC) { - data=(bKinematicConstraint*)con->data; - if (data->flag & CONSTRAINT_IK_AUTO) break; - if (data->tar==NULL) continue; - if (data->tar->type==OB_ARMATURE && data->subtarget[0]==0) continue; - if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) break; - } - } - if(con==NULL) return; - - /* exclude tip from chain? */ - if(!(data->flag & CONSTRAINT_IK_TIP)) - pchan_tip= pchan_tip->parent; - - /* Find the chain's root & count the segments needed */ - for (curchan = pchan_tip; curchan; curchan=curchan->parent){ - pchan_root = curchan; - - curchan->flag |= POSE_CHAIN; // don't forget to clear this - chanlist[segcount]=curchan; - segcount++; - - if(segcount==data->rootbone || segcount>255) break; // 255 is weak - } - if (!segcount) return; - - /* setup the chain data */ - - /* we make tree-IK, unless all existing targets are in this chain */ - for(tree= pchan_root->iktree.first; tree; tree= tree->next) { - for(target= tree->targets.first; target; target= target->next) { - curchan= tree->pchan[target->tip]; - if(curchan->flag & POSE_CHAIN) - curchan->flag &= ~POSE_CHAIN; - else - break; - } - if(target) break; - } - - /* create a target */ - target= MEM_callocN(sizeof(PoseTarget), "posetarget"); - target->con= con; - pchan_tip->flag &= ~POSE_CHAIN; - - if(tree==NULL) { - /* make new tree */ - tree= MEM_callocN(sizeof(PoseTree), "posetree"); - - tree->iterations= data->iterations; - tree->totchannel= segcount; - tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH); - - tree->pchan= MEM_callocN(segcount*sizeof(void*), "ik tree pchan"); - tree->parent= MEM_callocN(segcount*sizeof(int), "ik tree parent"); - for(a=0; a<segcount; a++) { - tree->pchan[a]= chanlist[segcount-a-1]; - tree->parent[a]= a-1; - } - target->tip= segcount-1; - - /* AND! link the tree to the root */ - BLI_addtail(&pchan_root->iktree, tree); - } - else { - tree->iterations= MAX2(data->iterations, tree->iterations); - tree->stretch= tree->stretch && !(data->flag & CONSTRAINT_IK_STRETCH); - - /* skip common pose channels and add remaining*/ - size= MIN2(segcount, tree->totchannel); - for(a=0; a<size && tree->pchan[a]==chanlist[segcount-a-1]; a++); - parent= a-1; - - segcount= segcount-a; - target->tip= tree->totchannel + segcount - 1; - - if (segcount > 0) { - /* resize array */ - newsize= tree->totchannel + segcount; - oldchan= tree->pchan; - oldparent= tree->parent; - - tree->pchan= MEM_callocN(newsize*sizeof(void*), "ik tree pchan"); - tree->parent= MEM_callocN(newsize*sizeof(int), "ik tree parent"); - memcpy(tree->pchan, oldchan, sizeof(void*)*tree->totchannel); - memcpy(tree->parent, oldparent, sizeof(int)*tree->totchannel); - MEM_freeN(oldchan); - MEM_freeN(oldparent); - - /* add new pose channels at the end, in reverse order */ - for(a=0; a<segcount; a++) { - tree->pchan[tree->totchannel+a]= chanlist[segcount-a-1]; - tree->parent[tree->totchannel+a]= tree->totchannel+a-1; - } - tree->parent[tree->totchannel]= parent; - - tree->totchannel= newsize; - } - - /* move tree to end of list, for correct evaluation order */ - BLI_remlink(&pchan_root->iktree, tree); - BLI_addtail(&pchan_root->iktree, tree); - } - - /* add target to the tree */ - BLI_addtail(&tree->targets, target); -} - -/* called from within the core where_is_pose loop, all animsystems and constraints -were executed & assigned. Now as last we do an IK pass */ -static void execute_posetree(Object *ob, PoseTree *tree) -{ - float R_parmat[3][3], identity[3][3]; - float iR_parmat[3][3]; - float R_bonemat[3][3]; - float goalrot[3][3], goalpos[3]; - float rootmat[4][4], imat[4][4]; - float goal[4][4], goalinv[4][4]; - float irest_basis[3][3], full_basis[3][3]; - float end_pose[4][4], world_pose[4][4]; - float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL; - float resultinf=0.0f; - int a, flag, hasstretch=0, resultblend=0; - bPoseChannel *pchan; - IK_Segment *seg, *parent, **iktree, *iktarget; - IK_Solver *solver; - PoseTarget *target; - bKinematicConstraint *data, *poleangledata=NULL; - Bone *bone; - - if (tree->totchannel == 0) - return; - - iktree= MEM_mallocN(sizeof(void*)*tree->totchannel, "ik tree"); - - for(a=0; a<tree->totchannel; a++) { - pchan= tree->pchan[a]; - bone= pchan->bone; - - /* set DoF flag */ - flag= 0; - if(!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP)) - flag |= IK_XDOF; - if(!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP)) - flag |= IK_YDOF; - if(!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP)) - flag |= IK_ZDOF; - - if(tree->stretch && (pchan->ikstretch > 0.0)) { - flag |= IK_TRANS_YDOF; - hasstretch = 1; - } - - seg= iktree[a]= IK_CreateSegment(flag); - - /* find parent */ - if(a == 0) - parent= NULL; - else - parent= iktree[tree->parent[a]]; - - IK_SetParent(seg, parent); - - /* get the matrix that transforms from prevbone into this bone */ - Mat3CpyMat4(R_bonemat, pchan->pose_mat); - - /* gather transformations for this IK segment */ - - if (pchan->parent) - Mat3CpyMat4(R_parmat, pchan->parent->pose_mat); - else - Mat3One(R_parmat); - - /* bone offset */ - if (pchan->parent && (a > 0)) - VecSubf(start, pchan->pose_head, pchan->parent->pose_tail); - else - /* only root bone (a = 0) has no parent */ - start[0]= start[1]= start[2]= 0.0f; - - /* change length based on bone size */ - length= bone->length*VecLength(R_bonemat[1]); - - /* compute rest basis and its inverse */ - Mat3CpyMat3(rest_basis, bone->bone_mat); - Mat3CpyMat3(irest_basis, bone->bone_mat); - Mat3Transp(irest_basis); - - /* compute basis with rest_basis removed */ - Mat3Inv(iR_parmat, R_parmat); - Mat3MulMat3(full_basis, iR_parmat, R_bonemat); - Mat3MulMat3(basis, irest_basis, full_basis); - - /* basis must be pure rotation */ - Mat3Ortho(basis); - - /* transform offset into local bone space */ - Mat3Ortho(iR_parmat); - Mat3MulVecfl(iR_parmat, start); - - IK_SetTransform(seg, start, rest_basis, basis, length); - - if (pchan->ikflag & BONE_IK_XLIMIT) - IK_SetLimit(seg, IK_X, pchan->limitmin[0], pchan->limitmax[0]); - if (pchan->ikflag & BONE_IK_YLIMIT) - IK_SetLimit(seg, IK_Y, pchan->limitmin[1], pchan->limitmax[1]); - if (pchan->ikflag & BONE_IK_ZLIMIT) - IK_SetLimit(seg, IK_Z, pchan->limitmin[2], pchan->limitmax[2]); - - IK_SetStiffness(seg, IK_X, pchan->stiffness[0]); - IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]); - IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]); - - if(tree->stretch && (pchan->ikstretch > 0.0f)) { - float ikstretch = pchan->ikstretch*pchan->ikstretch; - IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0f-ikstretch, 0.99f)); - IK_SetLimit(seg, IK_TRANS_Y, 0.001f, 1e10); - } - } - - solver= IK_CreateSolver(iktree[0]); - - /* set solver goals */ - - /* first set the goal inverse transform, assuming the root of tree was done ok! */ - pchan= tree->pchan[0]; - if (pchan->parent) - /* transform goal by parent mat, so this rotation is not part of the - segment's basis. otherwise rotation limits do not work on the - local transform of the segment itself. */ - Mat4CpyMat4(rootmat, pchan->parent->pose_mat); - else - Mat4One(rootmat); - VECCOPY(rootmat[3], pchan->pose_head); - - Mat4MulMat4 (imat, rootmat, ob->obmat); - Mat4Invert (goalinv, imat); - - for (target=tree->targets.first; target; target=target->next) { - float polepos[3]; - int poleconstrain= 0; - - data= (bKinematicConstraint*)target->con->data; - - /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though - * strictly speaking, it is a posechannel) - */ - get_constraint_target_matrix(target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); - - /* and set and transform goal */ - Mat4MulMat4(goal, rootmat, goalinv); - - VECCOPY(goalpos, goal[3]); - Mat3CpyMat4(goalrot, goal); - - /* same for pole vector target */ - if(data->poletar) { - get_constraint_target_matrix(target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); - - if(data->flag & CONSTRAINT_IK_SETANGLE) { - /* don't solve IK when we are setting the pole angle */ - break; - } - else { - Mat4MulMat4(goal, rootmat, goalinv); - VECCOPY(polepos, goal[3]); - poleconstrain= 1; - - /* for pole targets, we blend the result of the ik solver - * instead of the target position, otherwise we can't get - * a smooth transition */ - resultblend= 1; - resultinf= target->con->enforce; - - if(data->flag & CONSTRAINT_IK_GETANGLE) { - poleangledata= data; - data->flag &= ~CONSTRAINT_IK_GETANGLE; - } - } - } - - /* do we need blending? */ - if (!resultblend && target->con->enforce!=1.0f) { - float q1[4], q2[4], q[4]; - float fac= target->con->enforce; - float mfac= 1.0f-fac; - - pchan= tree->pchan[target->tip]; - - /* end effector in world space */ - Mat4CpyMat4(end_pose, pchan->pose_mat); - VECCOPY(end_pose[3], pchan->pose_tail); - Mat4MulSerie(world_pose, goalinv, ob->obmat, end_pose, 0, 0, 0, 0, 0); - - /* blend position */ - goalpos[0]= fac*goalpos[0] + mfac*world_pose[3][0]; - goalpos[1]= fac*goalpos[1] + mfac*world_pose[3][1]; - goalpos[2]= fac*goalpos[2] + mfac*world_pose[3][2]; - - /* blend rotation */ - Mat3ToQuat(goalrot, q1); - Mat4ToQuat(world_pose, q2); - QuatInterpol(q, q1, q2, mfac); - QuatToMat3(q, goalrot); - } - - iktarget= iktree[target->tip]; - - if(data->weight != 0.0f) { - if(poleconstrain) - IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, - polepos, data->poleangle*(float)M_PI/180.0f, (poleangledata == data)); - IK_SolverAddGoal(solver, iktarget, goalpos, data->weight); - } - if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0f)) - if((data->flag & CONSTRAINT_IK_AUTO)==0) - IK_SolverAddGoalOrientation(solver, iktarget, goalrot, - data->orientweight); - } - - /* solve */ - IK_Solve(solver, 0.0f, tree->iterations); - - if(poleangledata) - poleangledata->poleangle= IK_SolverGetPoleAngle(solver)*180.0f/(float)M_PI; - - IK_FreeSolver(solver); - - /* gather basis changes */ - tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change"); - if(hasstretch) - ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch"); - - for(a=0; a<tree->totchannel; a++) { - IK_GetBasisChange(iktree[a], tree->basis_change[a]); - - if(hasstretch) { - /* have to compensate for scaling received from parent */ - float parentstretch, stretch; - - pchan= tree->pchan[a]; - parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0f; - - if(tree->stretch && (pchan->ikstretch > 0.0f)) { - float trans[3], length; - - IK_GetTranslationChange(iktree[a], trans); - length= pchan->bone->length*VecLength(pchan->pose_mat[1]); - - ikstretch[a]= (length == 0.0f)? 1.0f: (trans[1]+length)/length; - } - else - ikstretch[a] = 1.0f; - - stretch= (parentstretch == 0.0f)? 1.0f: ikstretch[a]/parentstretch; - - VecMulf(tree->basis_change[a][0], stretch); - VecMulf(tree->basis_change[a][1], stretch); - VecMulf(tree->basis_change[a][2], stretch); - } - - if(resultblend && resultinf!=1.0f) { - Mat3One(identity); - Mat3BlendMat3(tree->basis_change[a], identity, - tree->basis_change[a], resultinf); - } - - IK_FreeSegment(iktree[a]); - } - - MEM_freeN(iktree); - if(ikstretch) MEM_freeN(ikstretch); -} - -void free_posetree(PoseTree *tree) -{ - BLI_freelistN(&tree->targets); - if(tree->pchan) MEM_freeN(tree->pchan); - if(tree->parent) MEM_freeN(tree->parent); - if(tree->basis_change) MEM_freeN(tree->basis_change); - MEM_freeN(tree); -} - /* ********************** THE POSE SOLVER ******************* */ @@ -1991,7 +1650,7 @@ void chan_calc_mat(bPoseChannel *chan) /* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */ EulOToMat3(chan->eul, chan->rotmode, rmat); } - else if (chan->rotmode == PCHAN_ROT_AXISANGLE) { + else if (chan->rotmode == ROT_MODE_AXISANGLE) { /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ AxisAngleToMat3(&chan->quat[1], chan->quat[0], rmat); } @@ -2012,41 +1671,6 @@ void chan_calc_mat(bPoseChannel *chan) } } -/* transform from bone(b) to bone(b+1), store in chan_mat */ -static void make_dmats(bPoseChannel *pchan) -{ - if (pchan->parent) { - float iR_parmat[4][4]; - Mat4Invert(iR_parmat, pchan->parent->pose_mat); - Mat4MulMat4(pchan->chan_mat, pchan->pose_mat, iR_parmat); // delta mat - } - else Mat4CpyMat4(pchan->chan_mat, pchan->pose_mat); -} - -/* applies IK matrix to pchan, IK is done separated */ -/* formula: pose_mat(b) = pose_mat(b-1) * diffmat(b-1, b) * ik_mat(b) */ -/* to make this work, the diffmats have to be precalculated! Stored in chan_mat */ -static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = to detect if this is first bone -{ - float vec[3], ikmat[4][4]; - - Mat4CpyMat3(ikmat, ik_mat); - - if (pchan->parent) - Mat4MulSerie(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat, NULL, NULL, NULL, NULL, NULL); - else - Mat4MulMat4(pchan->pose_mat, ikmat, pchan->chan_mat); - - /* calculate head */ - VECCOPY(pchan->pose_head, pchan->pose_mat[3]); - /* calculate tail */ - VECCOPY(vec, pchan->pose_mat[1]); - VecMulf(vec, pchan->bone->length); - VecAddf(pchan->pose_tail, pchan->pose_head, vec); - - pchan->flag |= POSE_DONE; -} - /* NLA strip modifiers */ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseChannel *pchan) { @@ -2172,7 +1796,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha /* The main armature solver, does all constraints excluding IK */ /* pchan is validated, as having bone and parent pointer */ -static void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime) +void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime) { Bone *bone, *parbone; bPoseChannel *parchan; @@ -2312,48 +1936,27 @@ void where_is_pose (Scene *scene, Object *ob) else { Mat4Invert(ob->imat, ob->obmat); // imat is needed - /* 1. construct the PoseTrees, clear flags */ + /* 1. clear flags */ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - pchan->flag &= ~(POSE_DONE|POSE_CHAIN); - if(pchan->constflag & PCHAN_HAS_IK) // flag is set on editing constraints - initialize_posetree(ob, pchan); // will attach it to root! + pchan->flag &= ~(POSE_DONE|POSE_CHAIN|POSE_IKTREE); } - - /* 2. the main loop, channels are already hierarchical sorted from root to children */ + /* 2. construct the IK tree */ + BIK_initialize_tree(scene, ob, ctime); + + /* 3. the main loop, channels are already hierarchical sorted from root to children */ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - /* 3. if we find an IK root, we handle it separated */ - if(pchan->iktree.first) { - while(pchan->iktree.first) { - PoseTree *tree= pchan->iktree.first; - int a; - - /* 4. walk over the tree for regular solving */ - for(a=0; a<tree->totchannel; a++) { - if(!(tree->pchan[a]->flag & POSE_DONE)) // successive trees can set the flag - where_is_pose_bone(scene, ob, tree->pchan[a], ctime); - } - /* 5. execute the IK solver */ - execute_posetree(ob, tree); - - /* 6. apply the differences to the channels, - we need to calculate the original differences first */ - for(a=0; a<tree->totchannel; a++) - make_dmats(tree->pchan[a]); - - for(a=0; a<tree->totchannel; a++) - /* sets POSE_DONE */ - where_is_ik_bone(tree->pchan[a], tree->basis_change[a]); - - /* 7. and free */ - BLI_remlink(&pchan->iktree, tree); - free_posetree(tree); - } + /* 4. if we find an IK root, we handle it separated */ + if(pchan->flag & POSE_IKTREE) { + BIK_execute_tree(scene, ob, pchan, ctime); } + /* 5. otherwise just call the normal solver */ else if(!(pchan->flag & POSE_DONE)) { where_is_pose_bone(scene, ob, pchan, ctime); } } + /* 6. release the IK tree */ + BIK_release_tree(scene, ob, ctime); } /* calculating deform matrices */ diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 18f065b59d9..7c3f3a7876f 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -87,7 +87,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, float vec_to_part[3]; if(pd && pd->forcefield == PFIELD_BOID) { - effector_find_co(bbd->scene, pa->prev_state.co, NULL, gabr->ob, pd, loc, vec, NULL, NULL); + effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, gabr->ob, pd, loc, vec, NULL, NULL); VecSubf(vec_to_part, pa->prev_state.co, loc); @@ -99,7 +99,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, priority = 1.0; priority_ob = gabr->ob; } - else for(ec=bbd->psys->effectors.first; ec; ec=ec->next) { + else for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) { if(ec->type & PSYS_EC_EFFECTOR) { Object *eob = ec->ob; PartDeflect *pd = eob->pd; @@ -111,7 +111,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f) { float vec_to_part[3], temp; - effector_find_co(bbd->scene, pa->prev_state.co, NULL, eob, pd, loc, vec, NULL, NULL); + effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, vec, NULL, NULL); VecSubf(vec_to_part, pa->prev_state.co, loc); @@ -147,7 +147,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, if(gabr->options & BRULE_GOAL_AVOID_PREDICT) { /* estimate future location of target */ - surface = (float)effector_find_co(bbd->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, vec, NULL); + surface = (float)effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, vec, NULL); VecSubf(vec_to_part, pa->prev_state.co, loc); len = Normalize(vec_to_part); @@ -157,7 +157,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, VecSubf(vec_to_part, pa->prev_state.co, loc); } else { - surface = (float)effector_find_co(bbd->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, NULL, NULL); + surface = (float)effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, NULL, NULL); VecSubf(vec_to_part, pa->prev_state.co, loc); len = VecLength(vec_to_part); @@ -228,7 +228,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * hit.dist = col.ray_len = VecLength(ray_dir); /* find out closest deflector object */ - for(ec=bbd->psys->effectors.first; ec; ec=ec->next) { + for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) { if(ec->type & PSYS_EC_DEFLECT) { Object *eob = ec->ob; @@ -261,12 +261,12 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * //check boids in own system if(acbr->options & BRULE_ACOLL_WITH_BOIDS) { - neighbors = BLI_kdtree_range_search(bbd->psys->tree, acbr->look_ahead * VecLength(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); + neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, acbr->look_ahead * VecLength(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); if(neighbors > 1) for(n=1; n<neighbors; n++) { VECCOPY(co1, pa->prev_state.co); VECCOPY(vel1, pa->prev_state.vel); - VECCOPY(co2, (bbd->psys->particles + ptn[n].index)->prev_state.co); - VECCOPY(vel2, (bbd->psys->particles + ptn[n].index)->prev_state.vel); + VECCOPY(co2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.co); + VECCOPY(vel2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.vel); VecSubf(loc, co1, co2); @@ -303,8 +303,8 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * if(ptn){ MEM_freeN(ptn); ptn=NULL; } /* check boids in other systems */ - for(pt=bbd->psys->targets.first; pt; pt=pt->next) { - ParticleSystem *epsys = psys_get_target_system(bbd->ob, pt); + for(pt=bbd->sim->psys->targets.first; pt; pt=pt->next) { + ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if(epsys) { neighbors = BLI_kdtree_range_search(epsys->tree, acbr->look_ahead * VecLength(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); @@ -362,11 +362,11 @@ static int rule_separate(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Pa ParticleTarget *pt; float len = 2.0f * val->personal_space * pa->size + 1.0f; float vec[3] = {0.0f, 0.0f, 0.0f}; - int neighbors = BLI_kdtree_range_search(bbd->psys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); + int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); int ret = 0; if(neighbors > 1 && ptn[1].dist!=0.0f) { - VecSubf(vec, pa->prev_state.co, bbd->psys->particles[ptn[1].index].state.co); + VecSubf(vec, pa->prev_state.co, bbd->sim->psys->particles[ptn[1].index].state.co); VecMulf(vec, (2.0f * val->personal_space * pa->size - ptn[1].dist) / ptn[1].dist); VecAddf(bbd->wanted_co, bbd->wanted_co, vec); bbd->wanted_speed = val->max_speed; @@ -376,8 +376,8 @@ static int rule_separate(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Pa if(ptn){ MEM_freeN(ptn); ptn=NULL; } /* check other boid systems */ - for(pt=bbd->psys->targets.first; pt; pt=pt->next) { - ParticleSystem *epsys = psys_get_target_system(bbd->ob, pt); + for(pt=bbd->sim->psys->targets.first; pt; pt=pt->next) { + ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if(epsys) { neighbors = BLI_kdtree_range_search(epsys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); @@ -400,14 +400,14 @@ static int rule_flock(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti { KDTreeNearest ptn[11]; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; - int neighbors = BLI_kdtree_find_n_nearest(bbd->psys->tree, 11, pa->state.co, pa->prev_state.ave, ptn); + int neighbors = BLI_kdtree_find_n_nearest(bbd->sim->psys->tree, 11, pa->state.co, pa->prev_state.ave, ptn); int n; int ret = 0; if(neighbors > 1) { for(n=1; n<neighbors; n++) { - VecAddf(loc, loc, bbd->psys->particles[ptn[n].index].prev_state.co); - VecAddf(vec, vec, bbd->psys->particles[ptn[n].index].prev_state.vel); + VecAddf(loc, loc, bbd->sim->psys->particles[ptn[n].index].prev_state.co); + VecAddf(vec, vec, bbd->sim->psys->particles[ptn[n].index].prev_state.vel); } VecMulf(loc, 1.0f/((float)neighbors - 1.0f)); @@ -429,8 +429,8 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader*) rule; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; float mul, len; - int n = (flbr->queue_size <= 1) ? bbd->psys->totpart : flbr->queue_size; - int i, ret = 0, p = pa - bbd->psys->particles; + int n = (flbr->queue_size <= 1) ? bbd->sim->psys->totpart : flbr->queue_size; + int i, ret = 0, p = pa - bbd->sim->psys->particles; if(flbr->ob) { float vec2[3], t; @@ -475,8 +475,8 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* not blocking so try to follow leader */ if(p && flbr->options & BRULE_LEADER_IN_LINE) { - VECCOPY(vec, bbd->psys->particles[p-1].prev_state.vel); - VECCOPY(loc, bbd->psys->particles[p-1].prev_state.co); + VECCOPY(vec, bbd->sim->psys->particles[p-1].prev_state.vel); + VECCOPY(loc, bbd->sim->psys->particles[p-1].prev_state.co); } else { VECCOPY(loc, flbr->oloc); @@ -496,10 +496,10 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va float vec2[3], t, t_min = 3.0f; /* first check we're not blocking any leaders */ - for(i = 0; i< bbd->psys->totpart; i+=n){ - VECCOPY(vec, bbd->psys->particles[i].prev_state.vel); + for(i = 0; i< bbd->sim->psys->totpart; i+=n){ + VECCOPY(vec, bbd->sim->psys->particles[i].prev_state.vel); - VecSubf(loc, pa->prev_state.co, bbd->psys->particles[i].prev_state.co); + VecSubf(loc, pa->prev_state.co, bbd->sim->psys->particles[i].prev_state.co); mul = Inpf(vec, vec); @@ -539,12 +539,12 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* not blocking so try to follow leader */ if(flbr->options & BRULE_LEADER_IN_LINE) { - VECCOPY(vec, bbd->psys->particles[p-1].prev_state.vel); - VECCOPY(loc, bbd->psys->particles[p-1].prev_state.co); + VECCOPY(vec, bbd->sim->psys->particles[p-1].prev_state.vel); + VECCOPY(loc, bbd->sim->psys->particles[p-1].prev_state.co); } else { - VECCOPY(vec, bbd->psys->particles[p - p%n].prev_state.vel); - VECCOPY(loc, bbd->psys->particles[p - p%n].prev_state.co); + VECCOPY(vec, bbd->sim->psys->particles[p - p%n].prev_state.vel); + VECCOPY(loc, bbd->sim->psys->particles[p - p%n].prev_state.co); } /* fac is seconds behind leader */ @@ -584,7 +584,7 @@ static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* leveling */ if(asbr->level > 0.0f) { - Projf(vec, bbd->wanted_co, bbd->psys->part->acc); + Projf(vec, bbd->wanted_co, bbd->sim->psys->part->acc); VecMulf(vec, asbr->level); VecSubf(bbd->wanted_co, bbd->wanted_co, vec); } @@ -601,7 +601,7 @@ static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* leveling */ if(asbr->level > 0.0f) { - Projf(vec, bbd->wanted_co, bbd->psys->part->acc); + Projf(vec, bbd->wanted_co, bbd->sim->psys->part->acc); VecMulf(vec, asbr->level); VecSubf(bbd->wanted_co, bbd->wanted_co, vec); } @@ -627,9 +627,9 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti int n, ret = 0; /* calculate own group strength */ - int neighbors = BLI_kdtree_range_search(bbd->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn); + int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn); for(n=0; n<neighbors; n++) { - bpa = bbd->psys->particles[ptn[n].index].boid; + bpa = bbd->sim->psys->particles[ptn[n].index].boid; health += bpa->data.health; } @@ -638,8 +638,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti if(ptn){ MEM_freeN(ptn); ptn=NULL; } /* add other friendlies and calculate enemy strength and find closest enemy */ - for(pt=bbd->psys->targets.first; pt; pt=pt->next) { - ParticleSystem *epsys = psys_get_target_system(bbd->ob, pt); + for(pt=bbd->sim->psys->targets.first; pt; pt=pt->next) { + ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if(epsys) { epars = epsys->particles; @@ -760,11 +760,11 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro surmd = (SurfaceModifierData *)modifiers_findByType ( bpa->ground, eModifierType_Surface ); /* take surface velocity into account */ - effector_find_co(bbd->scene, pa->state.co, surmd, NULL, NULL, x, NULL, v, NULL); + effector_find_co(bbd->sim->scene, pa->state.co, surmd, NULL, NULL, x, NULL, v, NULL); VecAddf(x, x, v); /* get actual position on surface */ - effector_find_co(bbd->scene, x, surmd, NULL, NULL, ground_co, ground_nor, NULL, NULL); + effector_find_co(bbd->sim->scene, x, surmd, NULL, NULL, ground_co, ground_nor, NULL, NULL); return bpa->ground; } @@ -785,7 +785,7 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro hit.dist = col.ray_len = VecLength(ray_dir); /* find out upmost deflector object */ - for(ec=bbd->psys->effectors.first; ec; ec=ec->next) { + for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) { if(ec->type & PSYS_EC_DEFLECT) { Object *eob = ec->ob; @@ -941,7 +941,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) bbd->wanted_co[0]=bbd->wanted_co[1]=bbd->wanted_co[2]=bbd->wanted_speed=0.0f; /* create random seed for every particle & frame */ - BLI_srandom(bbd->psys->seed + p); + BLI_srandom(bbd->sim->psys->seed + p); rand = BLI_rand(); BLI_srandom((int)bbd->cfra + rand); @@ -1077,7 +1077,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f}; float force[3] = {0.0f, 0.0f, 0.0f}, tvel[3] = {0.0f, 0.0f, 1.0f}; float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep; - int p = pa - bbd->psys->particles; + int p = pa - bbd->sim->psys->particles; set_boid_values(&val, boids, pa); @@ -1208,7 +1208,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) } /* account for effectors */ - do_effectors(p, pa, &pa->state, bbd->scene, bbd->ob, bbd->psys, pa->state.co, force, tvel, bbd->dfra, bbd->cfra); + do_effectors(bbd->sim, p, pa, &pa->state, pa->state.co, force, tvel, bbd->dfra, bbd->cfra); if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) { float length = Normalize(force); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index bce4e1120be..115d31b587c 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -44,6 +44,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" +#include "BLI_rand.h" #include "BKE_brush.h" #include "BKE_colortools.h" @@ -78,7 +79,7 @@ Brush *add_brush(const char *name) brush->smooth_stroke_radius= 75; brush->smooth_stroke_factor= 0.9; brush->rate= 0.1f; - brush->innerradius= 0.5f; + brush->jitter= 0.0f; brush->clone.alpha= 0.5; brush->sculpt_tool = SCULPT_TOOL_DRAW; @@ -379,36 +380,6 @@ void brush_check_exists(Brush **brush, const char *name) } /* Brush Sampling */ - -/*static float taylor_approx_cos(float f) -{ - f = f*f; - f = 1.0f - f/2.0f + f*f/24.0f; - return f; -}*/ - -float brush_sample_falloff(Brush *brush, float dist) -{ - float a, outer, inner; - - outer = brush->size >> 1; - inner = outer*brush->innerradius; - - if (dist <= inner) { - return brush->alpha; - } - else if ((dist < outer) && (inner < outer)) { - a = sqrt((dist - inner)/(outer - inner)); - return (1 - a)*brush->alpha; - - /* formula used by sculpt, with taylor approx - a = 0.5f*(taylor_approx_cos(3.0f*(dist - inner)/(outer - inner)) + 1.0f); - return a*brush->alpha; */ - } - else - return 0.0f; -} - void brush_sample_tex(Brush *brush, float *xy, float *rgba) { MTex *mtex= brush->mtex[brush->texact]; @@ -446,6 +417,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o ImBuf *ibuf; float xy[2], dist, rgba[4], *dstf; int x, y, rowbytes, xoff, yoff, imbflag; + int maxsize = brush->size >> 1; char *dst, crgb[3]; imbflag= (flt)? IB_rectfloat: IB_rect; @@ -470,7 +442,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); VECCOPY(dstf, brush->rgb); - dstf[3]= brush_sample_falloff(brush, dist); + dstf[3]= brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize); } else if (texfall == 1) { brush_sample_tex(brush, xy, dstf); @@ -483,7 +455,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o dstf[0] = rgba[0]*brush->rgb[0]; dstf[1] = rgba[1]*brush->rgb[1]; dstf[2] = rgba[2]*brush->rgb[2]; - dstf[3] = rgba[3]*brush_sample_falloff(brush, dist); + dstf[3] = rgba[3]*brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize); } } } @@ -506,7 +478,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o dst[0]= crgb[0]; dst[1]= crgb[1]; dst[2]= crgb[2]; - dst[3]= FTOCHAR(brush_sample_falloff(brush, dist)); + dst[3]= FTOCHAR(brush->alpha*brush_curve_strength(brush, dist, maxsize)); } else if (texfall == 1) { brush_sample_tex(brush, xy, rgba); @@ -522,7 +494,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]); dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]); dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]); - dst[3] = FTOCHAR(rgba[3]*brush_sample_falloff(brush, dist)); + dst[3] = FTOCHAR(rgba[3]*brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize)); } } } @@ -542,7 +514,7 @@ typedef struct BrushPainterCache { int lastsize; float lastalpha; - float lastinnerradius; + float lastjitter; ImBuf *ibuf; ImBuf *texibuf; @@ -567,7 +539,7 @@ struct BrushPainter { float startsize; float startalpha; - float startinnerradius; + float startjitter; float startspacing; BrushPainterCache cache; @@ -583,7 +555,7 @@ BrushPainter *brush_painter_new(Brush *brush) painter->startsize = brush->size; painter->startalpha = brush->alpha; - painter->startinnerradius = brush->innerradius; + painter->startjitter = brush->jitter; painter->startspacing = brush->spacing; return painter; @@ -617,7 +589,7 @@ void brush_painter_free(BrushPainter *painter) brush->size = painter->startsize; brush->alpha = painter->startalpha; - brush->innerradius = painter->startinnerradius; + brush->jitter = painter->startjitter; brush->spacing = painter->startspacing; if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf); @@ -711,7 +683,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i } } -void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos) +static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float *pos) { Brush *brush= painter->brush; BrushPainterCache *cache= &painter->cache; @@ -773,7 +745,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos) short flt; if ((brush->size != cache->lastsize) || (brush->alpha != cache->lastalpha) - || (brush->innerradius != cache->lastinnerradius)) { + || (brush->jitter != cache->lastjitter)) { if (cache->ibuf) { IMB_freeImBuf(cache->ibuf); cache->ibuf= NULL; @@ -798,7 +770,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos) cache->lastsize= brush->size; cache->lastalpha= brush->alpha; - cache->lastinnerradius= brush->innerradius; + cache->lastjitter= brush->jitter; } else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) { int dx = (int)painter->lastpaintpos[0] - (int)pos[0]; @@ -820,20 +792,34 @@ static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pres brush->alpha = MAX2(0.0, painter->startalpha*pressure); if (brush->flag & BRUSH_SIZE_PRESSURE) brush->size = MAX2(1.0, painter->startsize*pressure); - if (brush->flag & BRUSH_RAD_PRESSURE) - brush->innerradius = MAX2(0.0, painter->startinnerradius*pressure); + if (brush->flag & BRUSH_JITTER_PRESSURE) + brush->jitter = MAX2(0.0, painter->startjitter*pressure); if (brush->flag & BRUSH_SPACING_PRESSURE) brush->spacing = MAX2(1.0, painter->startspacing*(1.5f-pressure)); } +static void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos) +{ + if(brush->jitter){ + jitterpos[0] = pos[0] + ((BLI_frand()-0.5f) * brush->size * brush->jitter * 2); + jitterpos[1] = pos[1] + ((BLI_frand()-0.5f) * brush->size * brush->jitter * 2); + } + else { + VECCOPY2D(jitterpos, pos); + } +} + int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user) { Brush *brush= painter->brush; int totpaintops= 0; - if (pressure == 0.0f) - pressure = 1.0f; /* zero pressure == not using tablet */ - + if (pressure == 0.0f) { + if(painter->lastpressure) // XXX - hack, operator misses + pressure= painter->lastpressure; + else + pressure = 1.0f; /* zero pressure == not using tablet */ + } if (painter->firsttouch) { /* paint exactly once on first touch */ painter->startpaintpos[0]= pos[0]; @@ -884,7 +870,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl } #endif else { - float startdistance, spacing, step, paintpos[2], dmousepos[2]; + float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2]; float t, len, press; /* compute brush spacing adapted to brush size, spacing may depend @@ -909,11 +895,13 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl brush_apply_pressure(painter, brush, press); spacing= MAX2(1.0f, brush->size)*brush->spacing*0.01f; + brush_jitter_pos(brush, paintpos, finalpos); + if (painter->cache.enabled) - brush_painter_refresh_cache(painter, paintpos); + brush_painter_refresh_cache(painter, finalpos); totpaintops += - func(user, painter->cache.ibuf, painter->lastpaintpos, paintpos); + func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos); painter->lastpaintpos[0]= paintpos[0]; painter->lastpaintpos[1]= paintpos[1]; @@ -936,10 +924,14 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl while (painter->accumtime >= brush->rate) { brush_apply_pressure(painter, brush, pressure); + + brush_jitter_pos(brush, pos, finalpos); + if (painter->cache.enabled) - brush_painter_refresh_cache(painter, paintpos); + brush_painter_refresh_cache(painter, finalpos); + totpaintops += - func(user, painter->cache.ibuf, painter->lastmousepos, pos); + func(user, painter->cache.ibuf, painter->lastmousepos, finalpos); painter->accumtime -= brush->rate; } @@ -953,17 +945,30 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl brush->alpha = painter->startalpha; brush->size = painter->startsize; - brush->innerradius = painter->startinnerradius; + brush->jitter = painter->startjitter; brush->spacing = painter->startspacing; return totpaintops; } /* Uses the brush curve control to find a strength value between 0 and 1 */ +float brush_curve_strength_clamp(Brush *br, float p, const float len) +{ + if(p >= len) p= 1.0f; + else p= p/len; + + p= curvemapping_evaluateF(br->curve, 0, p); + if(p < 0.0) p= 0.0f; + else if(p > 1.0f) p= 1.0f; + return p; +} +/* same as above but can return negative values if the curve enables + * used for sculpt only */ float brush_curve_strength(Brush *br, float p, const float len) { - if(p > len) p= len; - return curvemapping_evaluateF(br->curve, 0, p/len); + if(p >= len) p= 1.0f; + else p= p/len; + return curvemapping_evaluateF(br->curve, 0, p); } /* TODO: should probably be unified with BrushPainter stuff? */ @@ -1030,7 +1035,7 @@ static struct ImBuf *brush_gen_radial_control_imbuf(Brush *br) for(i=0; i<side; ++i) { for(j=0; j<side; ++j) { float magn= sqrt(pow(i - half, 2) + pow(j - half, 2)); - im->rect_float[i*side + j]= brush_curve_strength(br, magn, half); + im->rect_float[i*side + j]= brush_curve_strength_clamp(br, magn, half); } } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index d25c329f49f..5cfbd5c18dc 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -95,7 +95,7 @@ static CM_SOLVER_DEF solvers [] = static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first); -int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); +static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ); @@ -155,7 +155,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->goalfrict = 0.0f; } -BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) +static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) { unsigned int i; BVHTree *bvhtree; @@ -196,7 +196,7 @@ BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) return bvhtree; } -BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) +static BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) { unsigned int i; BVHTree *bvhtree; @@ -998,7 +998,7 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in return 0; } -void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist) +static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgelist) { unsigned int i = 0; @@ -1031,7 +1031,7 @@ void cloth_free_errorsprings(Cloth *cloth, EdgeHash *edgehash, LinkNode **edgeli BLI_edgehash_free ( cloth->edgehash, NULL ); } -int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) +static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) { Cloth *cloth = clmd->clothObject; ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; @@ -1160,25 +1160,66 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) BLI_linklist_prepend ( &cloth->springs, spring ); } - // bending springs - search2 = cloth->springs; - for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) - { - if ( !search2 ) - break; + if(numfaces) { + // bending springs + search2 = cloth->springs; + for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) + { + if ( !search2 ) + break; + + tspring2 = search2->link; + search = edgelist[tspring2->kl]; + while ( search ) + { + tspring = search->link; + index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) ); + + // check for existing spring + // check also if startpoint is equal to endpoint + if ( !BLI_edgehash_haskey ( edgehash, MIN2(tspring2->ij, index2), MAX2(tspring2->ij, index2) ) + && ( index2!=tspring2->ij ) ) + { + spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); + + if(!spring) + { + cloth_free_errorsprings(cloth, edgehash, edgelist); + return 0; + } - tspring2 = search2->link; - search = edgelist[tspring2->kl]; - while ( search ) + spring->ij = MIN2(tspring2->ij, index2); + spring->kl = MAX2(tspring2->ij, index2); + VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); + spring->restlen = sqrt ( INPR ( temp, temp ) ); + spring->type = CLOTH_SPRING_TYPE_BENDING; + spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0; + BLI_edgehash_insert ( edgehash, spring->ij, spring->kl, NULL ); + bend_springs++; + + BLI_linklist_prepend ( &cloth->springs, spring ); + } + search = search->next; + } + search2 = search2->next; + } + } + else if(struct_springs > 2) { + /* bending springs for hair strands */ + /* The current algorightm only goes through the edges in order of the mesh edges list */ + /* and makes springs between the outer vert of edges sharing a vertice. This works just */ + /* fine for hair, but not for user generated string meshes. This could/should be later */ + /* extended to work with non-ordered edges so that it can be used for general "rope */ + /* dynamics" without the need for the vertices or edges to be ordered through the length*/ + /* of the strands. -jahka */ + search = cloth->springs; + search2 = search->next; + while(search && search2) { tspring = search->link; - index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) ); - - // check for existing spring - // check also if startpoint is equal to endpoint - if ( !BLI_edgehash_haskey ( edgehash, MIN2(tspring2->ij, index2), MAX2(tspring2->ij, index2) ) - && ( index2!=tspring2->ij ) ) - { + tspring2 = search2->link; + + if(tspring->ij == tspring2->kl) { spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if(!spring) @@ -1187,20 +1228,20 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) return 0; } - spring->ij = MIN2(tspring2->ij, index2); - spring->kl = MAX2(tspring2->ij, index2); + spring->ij = tspring2->ij; + spring->kl = tspring->kl; VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_BENDING; spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0; - BLI_edgehash_insert ( edgehash, spring->ij, spring->kl, NULL ); bend_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); } + search = search->next; + search2 = search2->next; } - search2 = search2->next; } /* insert other near springs in edgehash AFTER bending springs are calculated (for selfcolls) */ diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 37e9c93a108..aa4aae2422c 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -313,7 +313,7 @@ gsl_poly_solve_quadratic (double a, double b, double c, * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation" * page 4, left column */ -int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] ) +static int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] ) { int num_sols = 0; @@ -427,7 +427,7 @@ int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3 // w3 is not perfect -void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) +static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) { double tempV1[3], tempV2[3], tempV4[3]; double a,b,c,d,e,f; @@ -726,7 +726,7 @@ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap return collpair; } -int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +static int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; Cloth *cloth1; @@ -891,7 +891,7 @@ static void findClosestPointsEE(float *x1, float *x2, float *x3, float *x4, floa } // calculates the distance of 2 edges -float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal) +static float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal) { float line1[3], line2[3], cross[3]; float length; @@ -1065,7 +1065,7 @@ float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3 return 0; } -int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) +static int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { EdgeCollPair edgecollpair; Cloth *cloth1=NULL; @@ -1275,7 +1275,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat return result; } -int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +static int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { Cloth *cloth1; cloth1 = clmd->clothObject; @@ -1296,15 +1296,15 @@ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *col // return all collision objects in scene // collision object will exclude self -CollisionModifierData **get_collisionobjects(Scene *scene, Object *self, int *numcollobj) +Object **get_collisionobjects(Scene *scene, Object *self, int *numcollobj) { Base *base=NULL; - CollisionModifierData **objs = NULL; + Object **objs = NULL; Object *coll_ob = NULL; CollisionModifierData *collmd = NULL; int numobj = 0, maxobj = 100; - objs = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); + objs = MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray"); // check all collision objects for ( base = scene->base.first; base; base = base->next ) { @@ -1330,16 +1330,16 @@ CollisionModifierData **get_collisionobjects(Scene *scene, Object *self, int *nu { // realloc int oldmax = maxobj; - CollisionModifierData **tmp; + Object **tmp; maxobj *= 2; - tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); - memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax); + tmp = MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray"); + memcpy(tmp, objs, sizeof(Object *)*oldmax); MEM_freeN(objs); objs = tmp; } - objs[numobj] = collmd; + objs[numobj] = coll_ob; numobj++; } else @@ -1374,15 +1374,15 @@ CollisionModifierData **get_collisionobjects(Scene *scene, Object *self, int *nu { // realloc int oldmax = maxobj; - CollisionModifierData **tmp; + Object **tmp; maxobj *= 2; - tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); - memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax); + tmp = MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray"); + memcpy(tmp, objs, sizeof(Object *)*oldmax); MEM_freeN(objs); objs = tmp; } - objs[numobj] = collmd; + objs[numobj] = coll_ob; numobj++; } } @@ -1392,7 +1392,7 @@ CollisionModifierData **get_collisionobjects(Scene *scene, Object *self, int *nu return objs; } -void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap) +static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap) { int i; @@ -1405,7 +1405,7 @@ void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModi } } -int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index) +static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index) { Cloth *cloth = clmd->clothObject; int i=0, j = 0, numfaces = 0, numverts = 0; @@ -1459,7 +1459,7 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl int rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0, ret2 = 0; - CollisionModifierData **collobjs = NULL; + Object **collobjs = NULL; int numcollobj = 0; if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) ) @@ -1498,7 +1498,8 @@ int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, fl // check all collision objects for(i = 0; i < numcollobj; i++) { - CollisionModifierData *collmd = collobjs[i]; + Object *collob= collobjs[i]; + CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision); BVHTreeOverlap *overlap = NULL; int result = 0; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index e5c0b3947de..8846fe77809 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -685,9 +685,19 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain ct->flag= CONSTRAINT_TAR_TEMP; \ \ if (ct->tar) { \ - if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) ct->type = CONSTRAINT_OBTYPE_BONE; \ - else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) ct->type = CONSTRAINT_OBTYPE_VERT; \ - else ct->type = CONSTRAINT_OBTYPE_OBJECT; \ + if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) { \ + bPoseChannel *pchan= get_pose_channel(ct->tar->pose, ct->subtarget); \ + ct->type = CONSTRAINT_OBTYPE_BONE; \ + ct->rotOrder= (pchan) ? (pchan->rotmode) : EULER_ORDER_DEFAULT; \ + }\ + else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { \ + ct->type = CONSTRAINT_OBTYPE_VERT; \ + ct->rotOrder = EULER_ORDER_DEFAULT; \ + } \ + else {\ + ct->type = CONSTRAINT_OBTYPE_OBJECT; \ + ct->rotOrder= ct->tar->rotmode; \ + } \ } \ \ BLI_addtail(list, ct); \ @@ -1045,6 +1055,7 @@ static void kinematic_new_data (void *cdata) data->weight= (float)1.0; data->orientweight= (float)1.0; data->iterations = 500; + data->dist= (float)1.0; data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS; } @@ -1180,7 +1191,10 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr if (cu->path && cu->path->data) { if ((data->followflag & FOLLOWPATH_STATIC) == 0) { /* animated position along curve depending on time */ - curvetime= bsystem_time(cob->scene, ct->tar, ctime, 0.0) - data->offset; + if (cob->scene) + curvetime= bsystem_time(cob->scene, ct->tar, ctime, 0.0) - data->offset; + else + curvetime= ctime - data->offset; /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated, * but this will only work if it actually is animated... @@ -1580,7 +1594,8 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta VECCOPY(loc, cob->matrix[3]); Mat4ToSize(cob->matrix, size); - Mat4ToEulO(ct->matrix, eul, ct->rotOrder); + /* to allow compatible rotations, must get both rotations in the order of the owner... */ + Mat4ToEulO(ct->matrix, eul, cob->rotOrder); Mat4ToEulO(cob->matrix, obeul, cob->rotOrder); if ((data->flag & ROTLIKE_X)==0) @@ -3631,7 +3646,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) /* these we can skip completely (invalid constraints...) */ if (cti == NULL) continue; - if (con->flag & CONSTRAINT_DISABLE) continue; + if (con->flag & (CONSTRAINT_DISABLE|CONSTRAINT_OFF)) continue; /* these constraints can't be evaluated anyway */ if (cti->evaluate_constraint == NULL) continue; /* influence == 0 should be ignored */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index eec3cb73d8a..2ce877bd847 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -68,7 +68,7 @@ /* globals */ /* local */ -int cu_isectLL(float *v1, float *v2, float *v3, float *v4, +static int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec); @@ -977,7 +977,7 @@ void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int i } } -void forward_diff_bezier_cotangent(float *p0, float *p1, float *p2, float *p3, float *p, int it, int stride) +static void forward_diff_bezier_cotangent(float *p0, float *p1, float *p2, float *p3, float *p, int it, int stride) { /* note that these are not purpendicular to the curve * they need to be rotated for this, @@ -1363,7 +1363,7 @@ void makebevelcurve(Scene *scene, Object *ob, ListBase *disp) } } -int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec) +static int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec) { /* return: -1: colliniar @@ -1616,7 +1616,7 @@ static void bevel_list_flip_tangents(BevList *bl) nr= bl->nr; while(nr--) { - if(VecAngle2(bevp0->tan, bevp1->tan) > 90) + if(RAD2DEG(VecAngle2(bevp0->tan, bevp1->tan)) > 90) VecNegf(bevp1->tan); bevp0= bevp1; @@ -1882,7 +1882,7 @@ static void make_bevel_list_3D_tangent(BevList *bl) } } -void make_bevel_list_3D(BevList *bl, int smooth_iter, int twist_mode) +static void make_bevel_list_3D(BevList *bl, int smooth_iter, int twist_mode) { switch(twist_mode) { case CU_TWIST_TANGENT: diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 6a14762e0ed..4c2b2f3ec12 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -78,6 +78,7 @@ #include "BKE_pointcache.h" #include "BKE_utildefines.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "MEM_guardedalloc.h" @@ -559,6 +560,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O for(; psys; psys=psys->next) { BoidRule *rule = NULL; BoidState *state = NULL; + ParticleSimulationData sim = {scene, ob, psys, NULL}; ParticleSettings *part= psys->part; dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation"); @@ -591,8 +593,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } } - psys_end_effectors(psys); - psys_init_effectors(scene, ob, psys->part->eff_group, psys); + psys_update_effectors(&sim, 0.0, 0); for(nec= psys->effectors.first; nec; nec= nec->next) { Object *ob1= nec->ob; @@ -2142,30 +2143,58 @@ void DAG_scene_update_flags(Scene *scene, unsigned int lay) } -void DAG_id_flush_update(ID *id, short flag) +static void dag_current_scene_layers(Main *bmain, Scene **sce, unsigned int *lay) { - Main *bmain= G.main; wmWindowManager *wm; wmWindow *win; - Scene *sce; - Object *obt, *ob= NULL; - short idtype; /* only one scene supported currently, making more scenes work correctly requires changes beyond just the dependency graph */ + *sce= NULL; + *lay= 0; + if((wm= bmain->wm.first)) { - /* if we have a windowmanager, use sce from first window */ + /* if we have a windowmanager, look into windows */ for(win=wm->windows.first; win; win=win->next) { - sce= (win->screen)? win->screen->scene: NULL; - - if(sce) - break; + if(win->screen) { + if(!*sce) *sce= win->screen->scene; + *lay |= BKE_screen_visible_layers(win->screen); + } } } - else + else { /* if not, use the first sce */ - sce= bmain->scene.first; + *sce= bmain->scene.first; + if(*sce) *lay= (*sce)->lay; + + /* XXX for background mode, we should get the scen + from somewhere, for the -S option, but it's in + the context, how to get it here? */ + } +} + +void DAG_ids_flush_update(int time) +{ + Main *bmain= G.main; + Scene *sce; + unsigned int lay; + + dag_current_scene_layers(bmain, &sce, &lay); + + if(sce) + DAG_scene_flush_update(sce, lay, time); +} + +void DAG_id_flush_update(ID *id, short flag) +{ + Main *bmain= G.main; + Scene *sce; + Object *obt, *ob= NULL; + short idtype; + unsigned int lay; + + dag_current_scene_layers(bmain, &sce, &lay); if(!id || !sce || !sce->theDag) return; @@ -2213,10 +2242,7 @@ void DAG_id_flush_update(ID *id, short flag) } /* flush to other objects that depend on this one */ -// XXX if(G.curscreen) -// DAG_scene_flush_update(sce, dag_screen_view3d_layers(), 0); -// else - DAG_scene_flush_update(sce, sce->lay, 0); + DAG_scene_flush_update(sce, lay, 0); } /* recursively descends tree, each node only checked once */ @@ -2251,10 +2277,25 @@ static int parent_check_node(DagNode *node, int curtime) /* all nodes that influence this object get tagged, for calculating the exact position of this object at a given timeframe */ -void DAG_object_update_flags(Scene *sce, Object *ob, unsigned int lay) +void DAG_id_update_flags(ID *id) { + Main *bmain= G.main; + Scene *sce; DagNode *node; DagAdjList *itA; + Object *ob; + unsigned int lay; + + dag_current_scene_layers(bmain, &sce, &lay); + + if(!id || !sce || !sce->theDag) + return; + + /* objects only currently */ + if(GS(id->name) != ID_OB) + return; + + ob= (Object*)id; /* tag nodes unchecked */ for(node = sce->theDag->DagNode.first; node; node= node->next) diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index d87dbc833c5..266a528dc57 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1131,7 +1131,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) } -void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase) +static void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase) { if(cu->flag & CU_3D) return; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index e3c4f12184e..acf906e3163 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -258,10 +258,10 @@ static void eff_tri_ray_hit(void *userdata, int index, const BVHTreeRay *ray, BV // get visibility of a wind ray static float eff_calc_visibility(Scene *scene, Object *ob, float *co, float *dir) { - CollisionModifierData **collobjs = NULL; + Object **collobjs = NULL; int numcollobj = 0, i; float norm[3], len = 0.0; - float visibility = 1.0; + float visibility = 1.0, absorption = 0.0; collobjs = get_collisionobjects(scene, ob, &numcollobj); @@ -275,7 +275,8 @@ static float eff_calc_visibility(Scene *scene, Object *ob, float *co, float *dir // check all collision objects for(i = 0; i < numcollobj; i++) { - CollisionModifierData *collmd = collobjs[i]; + Object *collob= collobjs[i]; + CollisionModifierData *collmd = (CollisionModifierData*)modifiers_findByType(collob, eModifierType_Collision); if(collmd->bvhtree) { @@ -287,8 +288,10 @@ static float eff_calc_visibility(Scene *scene, Object *ob, float *co, float *dir // check if the way is blocked if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0) { + absorption= (collob->pd)? collob->pd->absorption: 0.0f; + // visibility is only between 0 and 1, calculated from 1-absorption - visibility *= MAX2(0.0, MIN2(1.0, (1.0-((float)collmd->absorption)*0.01))); + visibility *= CLAMPIS(1.0f-absorption, 0.0f, 1.0f); if(visibility <= 0.0f) break; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 31f6e2c6067..0ecd1fe912b 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -200,6 +200,85 @@ FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array return NULL; } +/* threshold for binary-searching keyframes - threshold here should be good enough for now, but should become userpref */ +#define BEZT_BINARYSEARCH_THRESH 0.00001f + +/* 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) + */ +int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short *replace) +{ + int start=0, end=arraylen; + int loopbreaker= 0, maxloop= arraylen * 2; + + /* initialise replace-flag first */ + *replace= 0; + + /* sneaky optimisations (don't go through searching process if...): + * - keyframe to be added is to be added out of current bounds + * - keyframe to be added would replace one of the existing ones on bounds + */ + if ((arraylen <= 0) || (array == NULL)) { + printf("Warning: binarysearch_bezt_index() encountered invalid array \n"); + return 0; + } + else { + /* check whether to add before/after/on */ + float framenum; + + /* 'First' Keyframe (when only one keyframe, this case is used) */ + framenum= array[0].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_BINARYSEARCH_THRESH)) { + *replace = 1; + return 0; + } + else if (frame < framenum) + return 0; + + /* 'Last' Keyframe */ + framenum= array[(arraylen-1)].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_BINARYSEARCH_THRESH)) { + *replace= 1; + return (arraylen - 1); + } + else if (frame > framenum) + return arraylen; + } + + + /* most of the time, this loop is just to find where to put it + * 'loopbreaker' is just here to prevent infinite loops + */ + for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { + /* compute and get midpoint */ + int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */ + float midfra= array[mid].vec[1][0]; + + /* check if exactly equal to midpoint */ + if (IS_EQT(frame, midfra, BEZT_BINARYSEARCH_THRESH)) { + *replace = 1; + return mid; + } + + /* repeat in upper/lower half */ + if (frame > midfra) + start= mid + 1; + else if (frame < midfra) + end= mid - 1; + } + + /* print error if loop-limit exceeded */ + if (loopbreaker == (maxloop-1)) { + printf("Error: binarysearch_bezt_index() was taking too long \n"); + + // include debug info + printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); + } + + /* not found, so return where to place it */ + return start; +} + /* Calculate the extents of F-Curve's data */ void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax) { @@ -916,7 +995,7 @@ void correct_bezpart (float *v1, float *v2, float *v3, float *v4) } /* find root ('zero') */ -int findzero (float x, float q0, float q1, float q2, float q3, float *o) +static int findzero (float x, float q0, float q1, float q2, float q3, float *o) { double c0, c1, c2, c3, a, b, c, p, q, d, t, phi; int nr= 0; @@ -1010,7 +1089,7 @@ int findzero (float x, float q0, float q1, float q2, float q3, float *o) } } -void berekeny (float f1, float f2, float f3, float f4, float *o, int b) +static void berekeny (float f1, float f2, float f3, float f4, float *o, int b) { float t, c0, c1, c2, c3; int a; @@ -1026,7 +1105,8 @@ void berekeny (float f1, float f2, float f3, float f4, float *o, int b) } } -void berekenx (float *f, float *o, int b) +#if 0 +static void berekenx (float *f, float *o, int b) { float t, c0, c1, c2, c3; int a; @@ -1041,6 +1121,7 @@ void berekenx (float *f, float *o, int b) o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3; } } +#endif /* -------------------------- */ diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index ad9e481ffd2..aa163b821c8 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -80,6 +80,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd) if(!fss) return; + fss->fmd = fluidmd; fss->type = OB_FLUIDSIM_ENABLE; fss->show_advancedoptions = 0; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 411b2448dea..4e05bf45d3d 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -129,7 +129,7 @@ wcsleninu8(wchar_t *src) } int -utf8slen(char *src) +static utf8slen(char *src) { int size = 0, index = 0; unsigned char c; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index cdb175ed661..9953540bbcf 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -277,7 +277,7 @@ static Image *image_alloc(const char *name, short source, short type) ima->xrep= ima->yrep= 1; ima->aspx= ima->aspy= 1.0; - ima->gen_x= 256; ima->gen_y= 256; + ima->gen_x= 1024; ima->gen_y= 1024; ima->gen_type= 1; /* no defines yet? */ ima->source= source; @@ -1472,9 +1472,11 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) iuser->ok= 1; break; case IMA_SIGNAL_SRC_CHANGE: - if(ima->type==IMA_TYPE_MULTILAYER) - image_free_buffers(ima); - else if(ima->source==IMA_SRC_GENERATED) { + if(ima->type == IMA_TYPE_UV_TEST) + if(ima->source != IMA_SRC_GENERATED) + ima->type= IMA_TYPE_IMAGE; + + if(ima->source==IMA_SRC_GENERATED) { if(ima->gen_x==0 || ima->gen_y==0) { ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); if(ibuf) { @@ -1483,6 +1485,9 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) } } } + + image_free_buffers(ima); + ima->ok= 1; if(iuser) iuser->ok= 1; @@ -2090,8 +2095,8 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) else if(ima->source == IMA_SRC_GENERATED) { /* generated is: ibuf is allocated dynamically */ /* UV testgrid or black or solid etc */ - if(ima->gen_x==0) ima->gen_x= 256; - if(ima->gen_y==0) ima->gen_y= 256; + if(ima->gen_x==0) ima->gen_x= 1024; + if(ima->gen_y==0) ima->gen_y= 1024; ibuf= add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 0, ima->gen_type, color); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); ima->ok= IMA_OK_LOADED; @@ -2170,3 +2175,103 @@ void BKE_image_user_calc_imanr(ImageUser *iuser, int cfra, int fieldnr) } } +/* + 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 0bce71b57eb..ae2acd6aef7 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -43,7 +43,7 @@ #include <windows.h> static LARGE_INTEGER _itstart, _itend; static LARGE_INTEGER ifreq; -void itstart(void) +static void itstart(void) { static int first = 1; if(first) { @@ -52,7 +52,7 @@ void itstart(void) } QueryPerformanceCounter(&_itstart); } -void itend(void) +static void itend(void) { QueryPerformanceCounter(&_itend); } @@ -74,7 +74,7 @@ double itval() { gettimeofday(&_itstart, &itz); } -void itend(void) +static void itend(void) { gettimeofday(&_itend,&itz); } @@ -155,7 +155,7 @@ DO_INLINE void mul_fvectorT_fvectorS(float to[3][3], float vectorA[3], float vec /* printf vector[3] on console: for debug output */ -void print_fvector(float m3[3]) +static void print_fvector(float m3[3]) { printf("%f\n%f\n%f\n\n",m3[0],m3[1],m3[2]); } @@ -297,7 +297,7 @@ DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], f // 3x3 matrix /////////////////////////// /* printf 3x3 matrix on console: for debug output */ -void print_fmatrix(float m3[3][3]) +static void print_fmatrix(float m3[3][3]) { printf("%f\t%f\t%f\n",m3[0][0],m3[0][1],m3[0][2]); printf("%f\t%f\t%f\n",m3[1][0],m3[1][1],m3[1][2]); @@ -496,7 +496,8 @@ DO_INLINE void mulsub_fmatrix_fvector(float to[3], float matrix[3][3], float fro // SPARSE SYMMETRIC big matrix with 3x3 matrix entries /////////////////////////// /* printf a big matrix on console: for debug output */ -void print_bfmatrix(fmatrix3x3 *m3) +#if 0 +static void print_bfmatrix(fmatrix3x3 *m3) { unsigned int i = 0; @@ -505,6 +506,8 @@ void print_bfmatrix(fmatrix3x3 *m3) print_fmatrix(m3[i].m); } } +#endif + /* create big matrix */ DO_INLINE fmatrix3x3 *create_bfmatrix(unsigned int verts, unsigned int springs) { @@ -887,7 +890,7 @@ DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) } } -int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) +static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) { // Solves for unknown X in equation AX=B unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100; @@ -970,7 +973,7 @@ DO_INLINE void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv) } /* // version 1.3 -int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv) +static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv) { unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100; float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0; @@ -1038,7 +1041,7 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma } */ // version 1.4 -int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *bigI) +static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *bigI) { unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100; float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0, tol = 0; @@ -1391,7 +1394,7 @@ static void CalcFloat4( float *v1, float *v2, float *v3, float *v4, float *n) n[2]= n1[0]*n2[1]-n1[1]*n2[0]; } -float calculateVertexWindForce(float wind[3], float vertexnormal[3]) +static float calculateVertexWindForce(float wind[3], float vertexnormal[3]) { return (INPR(wind, vertexnormal)); } @@ -1417,7 +1420,6 @@ static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX, int i = 0; int j = 0; int k = 0; - lfVector temp; INIT_MINMAX(gmin, gmax); @@ -1595,7 +1597,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, // printf("\n"); } -void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *M, fmatrix3x3 *bigI) +static void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *M, fmatrix3x3 *bigI) { unsigned int numverts = dFdV[0].vcount; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 2f0e0931588..811a2658ae3 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -213,17 +213,17 @@ static char *ob_adrcodes_to_paths (int adrcode, int *array_index) *array_index= 2; return "delta_location"; case OB_ROT_X: - *array_index= 0; return "rotation"; + *array_index= 0; return "rotation_euler"; case OB_ROT_Y: - *array_index= 1; return "rotation"; + *array_index= 1; return "rotation_euler"; case OB_ROT_Z: - *array_index= 2; return "rotation"; + *array_index= 2; return "rotation_euler"; case OB_DROT_X: - *array_index= 0; return "delta_rotation"; + *array_index= 0; return "delta_rotation_euler"; case OB_DROT_Y: - *array_index= 1; return "delta_rotation"; + *array_index= 1; return "delta_rotation_euler"; case OB_DROT_Z: - *array_index= 2; return "delta_rotation"; + *array_index= 2; return "delta_rotation_euler"; case OB_SIZE_X: *array_index= 0; return "scale"; @@ -281,23 +281,23 @@ static char *pchan_adrcodes_to_paths (int adrcode, int *array_index) /* result depends on adrcode */ switch (adrcode) { case AC_QUAT_W: - *array_index= 0; return "rotation"; + *array_index= 0; return "rotation_quaternion"; case AC_QUAT_X: - *array_index= 1; return "rotation"; + *array_index= 1; return "rotation_quaternion"; case AC_QUAT_Y: - *array_index= 2; return "rotation"; + *array_index= 2; return "rotation_quaternion"; case AC_QUAT_Z: - *array_index= 3; return "rotation"; + *array_index= 3; return "rotation_quaternion"; case AC_EUL_X: - *array_index= 0; return "euler_rotation"; + *array_index= 0; return "rotation_euler"; case AC_EUL_Y: - *array_index= 1; return "euler_rotation"; + *array_index= 1; return "rotation_euler"; case AC_EUL_Z: - *array_index= 2; return "euler_rotation"; + *array_index= 2; return "rotation_euler"; case -1: /* special case for euler-rotations used by old drivers */ - *array_index= 0; return "euler_rotation"; + *array_index= 0; return "rotation_euler"; case AC_LOC_X: *array_index= 0; return "location"; @@ -820,7 +820,7 @@ static char *particle_adrcodes_to_paths (int adrcode, int *array_index) * - array_index - index in property's array (if applicable) to use * - return - the allocated path... */ -char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index) +static char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index) { DynStr *path= BLI_dynstr_new(); char *propname=NULL, *rpath=NULL; @@ -1214,6 +1214,9 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha /* interpolation can only be constant... */ dst->ipo= BEZT_IPO_CONST; + /* 'hide' flag is now used for keytype - only 'keyframes' existed before */ + dst->hide= BEZT_KEYTYPE_KEYFRAME; + /* correct values, by checking if the flag of interest is set */ if ( ((int)(dst->vec[1][1])) & (abp->bit) ) dst->vec[0][1]= dst->vec[1][1]= dst->vec[2][1] = 1.0f; @@ -1264,6 +1267,9 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha if (icu->ipo != IPO_MIXED) dst->ipo= icu->ipo; + /* 'hide' flag is now used for keytype - only 'keyframes' existed before */ + dst->hide= BEZT_KEYTYPE_KEYFRAME; + /* correct values for euler rotation curves - they were degrees/10 */ // XXX for now, just make them into radians as RNA sets/reads directly in that form if ( ((icu->blocktype == ID_OB) && ELEM3(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) || diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index da7692d0cdb..45869a317e8 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -455,16 +455,14 @@ void flag_all_listbases_ids(short flag, short value) while(a--) flag_listbase_ids(lbarray[a], flag, value); } -void recalc_all_library_objects(struct Main *main) +void recalc_all_library_objects(Main *main) { - /* DISPLISTS? */ - Object *ob= main->object.first; - while(ob) { - if(ob->id.lib) { + Object *ob; + + /* flag for full recalc */ + for(ob=main->object.first; ob; ob=ob->id.next) + if(ob->id.lib) ob->recalc |= OB_RECALC; - } - ob= ob->id.next; - } } /* note: MAX_LIBARRAY define should match this code */ diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index e6f9ac2f404..1667bd97102 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -159,9 +159,9 @@ void init_material(Material *ma) ma->sss_radius[0]= 1.0f; ma->sss_radius[1]= 1.0f; ma->sss_radius[2]= 1.0f; - ma->sss_col[0]= 0.8f; - ma->sss_col[1]= 0.8f; - ma->sss_col[2]= 0.8f; + ma->sss_col[0]= 1.0f; + ma->sss_col[1]= 1.0f; + ma->sss_col[2]= 1.0f; ma->sss_error= 0.05f; ma->sss_scale= 0.1f; ma->sss_ior= 1.3f; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index c92eda6d169..431543f8dbd 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -542,7 +542,8 @@ void set_mesh(Object *ob, Mesh *me) if(ob->type==OB_MESH) { old= ob->data; - old->id.us--; + if (old) + old->id.us--; ob->data= me; id_us_plus((ID *)me); } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index f06173264ee..b9b9ea6b4f3 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -214,7 +214,7 @@ static void curveModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tcmd->name, cmd->name, 32); } -CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *md) { CurveModifierData *cmd = (CurveModifierData *)md; CustomDataMask dataMask = 0; @@ -290,7 +290,7 @@ static void latticeModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tlmd->name, lmd->name, 32); } -CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData *md) { LatticeModifierData *lmd = (LatticeModifierData *)md; CustomDataMask dataMask = 0; @@ -1104,7 +1104,7 @@ static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest, Sc } } -float vertarray_size(MVert *mvert, int numVerts, int axis) +static float vertarray_size(MVert *mvert, int numVerts, int axis) { int i; float min_co, max_co; @@ -1771,7 +1771,7 @@ static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, S /* finds the best possible flipped name. For renaming; check for unique names afterwards */ /* if strip_number: removes number extensions */ -void vertgroup_flip_name (char *name, int strip_number) +static void vertgroup_flip_name (char *name, int strip_number) { int len; char prefix[128]={""}; /* The part before the facing */ @@ -3401,7 +3401,7 @@ static void bevelModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tbmd->defgrp_name, bmd->defgrp_name, 32); } -CustomDataMask bevelModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask bevelModifier_requiredDataMask(Object *ob, ModifierData *md) { BevelModifierData *bmd = (BevelModifierData *)md; CustomDataMask dataMask = 0; @@ -3481,7 +3481,7 @@ static void displaceModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tdmd->uvlayer_name, dmd->uvlayer_name, 32); } -CustomDataMask displaceModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask displaceModifier_requiredDataMask(Object *ob, ModifierData *md) { DisplaceModifierData *dmd = (DisplaceModifierData *)md; CustomDataMask dataMask = 0; @@ -3825,7 +3825,7 @@ static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target) tumd->aspecty = umd->aspecty; } -CustomDataMask uvprojectModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask uvprojectModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -4278,7 +4278,7 @@ static void smoothModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tsmd->defgrp_name, smd->defgrp_name, 32); } -int smoothModifier_isDisabled(ModifierData *md) +static int smoothModifier_isDisabled(ModifierData *md) { SmoothModifierData *smd = (SmoothModifierData*) md; short flag; @@ -4291,7 +4291,7 @@ int smoothModifier_isDisabled(ModifierData *md) return 0; } -CustomDataMask smoothModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask smoothModifier_requiredDataMask(Object *ob, ModifierData *md) { SmoothModifierData *smd = (SmoothModifierData *)md; CustomDataMask dataMask = 0; @@ -4508,7 +4508,7 @@ static void castModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32); } -int castModifier_isDisabled(ModifierData *md) +static int castModifier_isDisabled(ModifierData *md) { CastModifierData *cmd = (CastModifierData*) md; short flag; @@ -4520,7 +4520,7 @@ int castModifier_isDisabled(ModifierData *md) return 0; } -CustomDataMask castModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask castModifier_requiredDataMask(Object *ob, ModifierData *md) { CastModifierData *cmd = (CastModifierData *)md; CustomDataMask dataMask = 0; @@ -5151,7 +5151,7 @@ static void waveModifier_updateDepgraph( } } -CustomDataMask waveModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask waveModifier_requiredDataMask(Object *ob, ModifierData *md) { WaveModifierData *wmd = (WaveModifierData *)md; CustomDataMask dataMask = 0; @@ -5487,7 +5487,7 @@ static void armatureModifier_copyData(ModifierData *md, ModifierData *target) strncpy(tamd->defgrp_name, amd->defgrp_name, 32); } -CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -5602,7 +5602,7 @@ static void hookModifier_copyData(ModifierData *md, ModifierData *target) strncpy(thmd->subtarget, hmd->subtarget, 32); } -CustomDataMask hookModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask hookModifier_requiredDataMask(Object *ob, ModifierData *md) { HookModifierData *hmd = (HookModifierData *)md; CustomDataMask dataMask = 0; @@ -5947,7 +5947,7 @@ static void clothModifier_updateDepgraph( } } -CustomDataMask clothModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask clothModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = 0; @@ -6371,7 +6371,7 @@ static DerivedMesh *booleanModifier_applyModifier( return derivedData; } -CustomDataMask booleanModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask booleanModifier_requiredDataMask(Object *ob, ModifierData *md) { CustomDataMask dataMask = (1 << CD_MTFACE) + (1 << CD_MEDGE); @@ -6419,7 +6419,7 @@ static void particleSystemModifier_copyData(ModifierData *md, ModifierData *targ tpsmd->psys = psmd->psys; } -CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData *md) { ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md; CustomDataMask dataMask = 0; @@ -6601,6 +6601,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( { DerivedMesh *dm = derivedData, *result; ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md; + ParticleSimulationData sim; ParticleSystem * psys=0; ParticleData *pa=0, *pars=0; MFace *mface, *orig_mface; @@ -6635,6 +6636,11 @@ static DerivedMesh * particleInstanceModifier_applyModifier( if(totpart==0) return derivedData; + sim.scene = md->scene; + sim.ob = pimd->ob; + sim.psys = psys; + sim.psmd = psys_get_modifier(pimd->ob, psys); + if(pimd->flag & eParticleInstanceFlag_UseSize) { int p; float *si; @@ -6662,7 +6668,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( maxvert=totvert*totpart; maxface=totface*totpart; - psys->lattice=psys_get_lattice(md->scene, ob, psys); + psys->lattice=psys_get_lattice(&sim); if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){ @@ -6712,7 +6718,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( mv->co[axis] = 0.0; } - psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1); + psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1); Normalize(state.vel); @@ -6734,7 +6740,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( } else{ state.time=-1.0; - psys_get_particle_state(md->scene, pimd->ob, psys, first_particle + i/totvert, &state,1); + psys_get_particle_state(&sim, first_particle + i/totvert, &state,1); } QuatMulVecf(state.rot,mv->co); @@ -6832,7 +6838,7 @@ static int explodeModifier_dependsOnTime(ModifierData *md) { return 1; } -CustomDataMask explodeModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask explodeModifier_requiredDataMask(Object *ob, ModifierData *md) { ExplodeModifierData *emd= (ExplodeModifierData*) md; CustomDataMask dataMask = 0; @@ -7416,6 +7422,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, DerivedMesh *explode, *dm=to_explode; MFace *mf=0; ParticleSettings *part=psmd->psys->part; + ParticleSimulationData sim = {scene, ob, psmd->psys, psmd}; ParticleData *pa=NULL, *pars=psmd->psys->particles; ParticleKey state; EdgeHash *vertpahash; @@ -7431,7 +7438,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, totvert= dm->getNumVerts(dm); totpart= psmd->psys->totpart; - timestep= psys_get_timestep(part); + timestep= psys_get_timestep(&sim); //if(part->flag & PART_GLOB_TIME) cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0); @@ -7474,7 +7481,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, /* getting back to object space */ Mat4Invert(imat,ob->obmat); - psmd->psys->lattice = psys_get_lattice(scene, ob, psmd->psys); + psmd->psys->lattice = psys_get_lattice(&sim); /* duplicate & displace vertices */ ehi= BLI_edgehashIterator_new(vertpahash); @@ -7502,7 +7509,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, Mat4MulVecfl(ob->obmat,loc0); state.time=cfra; - psys_get_particle_state(scene, ob, psmd->psys, i, &state,1); + psys_get_particle_state(&sim, i, &state, 1); vertco=CDDM_get_vert(explode,v)->co; @@ -7591,7 +7598,7 @@ static DerivedMesh * explodeModifier_applyModifier( { DerivedMesh *dm = derivedData; ExplodeModifierData *emd= (ExplodeModifierData*) md; - ParticleSystemModifierData *psmd=explodeModifier_findPrecedingParticlesystem(ob,md);; + ParticleSystemModifierData *psmd=explodeModifier_findPrecedingParticlesystem(ob,md); if(psmd){ ParticleSystem * psys=psmd->psys; @@ -7746,7 +7753,7 @@ static void meshdeformModifier_copyData(ModifierData *md, ModifierData *target) tmmd->object = mmd->object; } -CustomDataMask meshdeformModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask meshdeformModifier_requiredDataMask(Object *ob, ModifierData *md) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; CustomDataMask dataMask = 0; @@ -8126,7 +8133,7 @@ static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target) tsmd->subsurfLevels = smd->subsurfLevels; } -CustomDataMask shrinkwrapModifier_requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask shrinkwrapModifier_requiredDataMask(Object *ob, ModifierData *md) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md; CustomDataMask dataMask = 0; @@ -8503,6 +8510,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->initData = smoothModifier_initData; mti->copyData = smoothModifier_copyData; mti->requiredDataMask = smoothModifier_requiredDataMask; + mti->isDisabled = smoothModifier_isDisabled; mti->deformVerts = smoothModifier_deformVerts; mti->deformVertsEM = smoothModifier_deformVertsEM; @@ -8513,6 +8521,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->initData = castModifier_initData; mti->copyData = castModifier_copyData; mti->requiredDataMask = castModifier_requiredDataMask; + mti->isDisabled = castModifier_isDisabled; mti->foreachObjectLink = castModifier_foreachObjectLink; mti->updateDepgraph = castModifier_updateDepgraph; mti->deformVerts = castModifier_deformVerts; @@ -9137,19 +9146,6 @@ int modifiers_indexInObject(Object *ob, ModifierData *md_seek) return i; } -int modifiers_usesPointCache(Object *ob) -{ - ModifierData *md = ob->modifiers.first; - - for (; md; md=md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if (mti->flags & eModifierTypeFlag_UsesPointCache) { - return 1; - } - } - return 0; -} - void modifier_freeTemporaryData(ModifierData *md) { if(md->type == eModifierType_Armature) { diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 37e7e55050a..e7159b82d49 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -596,7 +596,7 @@ static void find_displacer_edges(MultiresDisplacer *d, DerivedMesh *dm, Displace } /* Returns in out the corners [0-3] that use v1 and v2 */ -void find_face_corners(MFace *f, int v1, int v2, int out[2]) +static void find_face_corners(MFace *f, int v1, int v2, int out[2]) { int i, end = f->v4 ? 4 : 3; @@ -1259,7 +1259,7 @@ struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, i ***************************/ /* Does not actually free lvl itself */ -void multires_free_level(MultiresLevel *lvl) +static void multires_free_level(MultiresLevel *lvl) { if(lvl) { if(lvl->faces) MEM_freeN(lvl->faces); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 480c79fbc1a..83ee71bfe40 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1048,7 +1048,7 @@ short BKE_nlastrip_within_bounds (NlaStrip *strip, float min, float max) /* Is the given NLA-strip the first one to occur for the given AnimData block */ // TODO: make this an api method if necesary, but need to add prefix first -short nlastrip_is_first (AnimData *adt, NlaStrip *strip) +static short nlastrip_is_first (AnimData *adt, NlaStrip *strip) { NlaTrack *nlt; NlaStrip *ns; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 8fe7beeb247..7e2ec106062 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -127,8 +127,8 @@ void clear_workob(Object *workob) { memset(workob, 0, sizeof(Object)); - workob->size[0]= workob->size[1]= workob->size[2]= 1.0; - + workob->size[0]= workob->size[1]= workob->size[2]= 1.0f; + workob->rotmode= ROT_MODE_EUL; } void copy_baseflags(struct Scene *scene) @@ -1038,6 +1038,11 @@ Object *add_object(struct Scene *scene, int type) ob->data= add_obdata_from_type(type); ob->lay= scene->lay; + + /* objects should default to having Euler XYZ rotations, + * but rotations default to quaternions + */ + ob->rotmode= ROT_MODE_EUL; base= scene_add_base(scene, ob); scene_select_base(scene, base); @@ -1406,7 +1411,7 @@ int object_data_is_libdata(Object *ob) /* *************** PROXY **************** */ /* when you make proxy, ensure the exposed layers are extern */ -void armature_set_id_extern(Object *ob) +static void armature_set_id_extern(Object *ob) { bArmature *arm= ob->data; bPoseChannel *pchan; @@ -1553,13 +1558,11 @@ float bsystem_time(struct Scene *scene, Object *ob, float cfra, float ofs) cfra+= bluroffs+fieldoffs; /* global time */ - cfra*= scene->r.framelen; + if (scene) + cfra*= scene->r.framelen; #if 0 // XXX old animation system if (ob) { - if (no_speed_curve==0 && ob->ipo) - cfra= calc_ipo_time(ob->ipo, cfra); - /* ofset frames */ if ((ob->ipoflag & OB_OFFS_PARENT) && (ob->partype & PARSLOW)==0) cfra-= give_timeoffset(ob); @@ -1574,29 +1577,44 @@ float bsystem_time(struct Scene *scene, Object *ob, float cfra, float ofs) void object_scale_to_mat3(Object *ob, float mat[][3]) { float vec[3]; - if(ob->ipo) { - vec[0]= ob->size[0]+ob->dsize[0]; - vec[1]= ob->size[1]+ob->dsize[1]; - vec[2]= ob->size[2]+ob->dsize[2]; - SizeToMat3(vec, mat); - } - else { - SizeToMat3(ob->size, mat); - } + + vec[0]= ob->size[0]+ob->dsize[0]; + vec[1]= ob->size[1]+ob->dsize[1]; + vec[2]= ob->size[2]+ob->dsize[2]; + SizeToMat3(vec, mat); } +// TODO: this should take rotation orders into account later... void object_rot_to_mat3(Object *ob, float mat[][3]) { - float vec[3]; - if(ob->ipo) { - vec[0]= ob->rot[0]+ob->drot[0]; - vec[1]= ob->rot[1]+ob->drot[1]; - vec[2]= ob->rot[2]+ob->drot[2]; - EulToMat3(vec, mat); + float rmat[3][3], dmat[3][3]; + + /* initialise the delta-rotation matrix, which will get (pre)multiplied + * with the rotation matrix to yield the appropriate rotation + */ + Mat3One(dmat); + + /* rotations may either be quats, eulers (with various rotation orders), or axis-angle */ + if (ob->rotmode > 0) { + /* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */ + EulOToMat3(ob->rot, ob->rotmode, rmat); + EulOToMat3(ob->drot, ob->rotmode, dmat); + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ + AxisAngleToMat3(&ob->quat[1], ob->quat[0], rmat); + AxisAngleToMat3(&ob->dquat[1], ob->dquat[0], dmat); } else { - EulToMat3(ob->rot, mat); + /* quats are normalised before use to eliminate scaling issues */ + NormalQuat(ob->quat); + QuatToMat3(ob->quat, rmat); + QuatToMat3(ob->dquat, dmat); } + + /* combine these rotations */ + // XXX is this correct? if errors, change the order of multiplication... + Mat3MulMat3(mat, dmat, rmat); } void object_to_mat3(Object *ob, float mat[][3]) /* no parent */ @@ -1609,19 +1627,7 @@ void object_to_mat3(Object *ob, float mat[][3]) /* no parent */ object_scale_to_mat3(ob, smat); /* rot */ - /* Quats arnt used yet */ - /*if(ob->transflag & OB_QUAT) { - if(ob->ipo) { - QuatMul(q1, ob->quat, ob->dquat); - QuatToMat3(q1, rmat); - } - else { - QuatToMat3(ob->quat, rmat); - } - } - else {*/ - object_rot_to_mat3(ob, rmat); - /*}*/ + object_rot_to_mat3(ob, rmat); Mat3MulMat3(mat, rmat, smat); } @@ -1633,12 +1639,9 @@ void object_to_mat4(Object *ob, float mat[][4]) Mat4CpyMat3(mat, tmat); - VECCOPY(mat[3], ob->loc); - if(ob->ipo) { - mat[3][0]+= ob->dloc[0]; - mat[3][1]+= ob->dloc[1]; - mat[3][2]+= ob->dloc[2]; - } + mat[3][0]= ob->loc[0] + ob->dloc[0]; + mat[3][1]= ob->loc[1] + ob->dloc[1]; + mat[3][2]= ob->loc[2] + ob->dloc[2]; } int enable_cu_speed= 1; @@ -2562,7 +2565,7 @@ int ray_hit_boundbox(struct BoundBox *bb, float ray_start[3], float ray_normal[3 static int pc_cmp(void *a, void *b) { LinkData *ad = a, *bd = b; - if((int)ad->data > (int)bd->data) + if(GET_INT_FROM_POINTER(ad->data) > GET_INT_FROM_POINTER(bd->data)) return 1; else return 0; } @@ -2576,14 +2579,14 @@ int object_insert_ptcache(Object *ob) for(link=ob->pc_ids.first, i = 0; link; link=link->next, i++) { - int index =(int)link->data; + int index = GET_INT_FROM_POINTER(link->data); if(i < index) break; } link = MEM_callocN(sizeof(LinkData), "PCLink"); - link->data = (void *)i; + link->data = SET_INT_IN_POINTER(i); BLI_addtail(&ob->pc_ids, link); return i; diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index bd0b1a5e36e..0de97b9c703 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -236,7 +236,7 @@ void packAll(Main *bmain, ReportList *reports) // attempt to create a function that generates an unique filename // this will work when all funtions in fileops.c understand relative filenames... -char *find_new_name(char *name) +static char *find_new_name(char *name) { char tempname[FILE_MAXDIR + FILE_MAXFILE]; char *newname; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 7c5b2b82b4b..f17d2fbdcac 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -46,19 +46,24 @@ const char PAINT_CURSOR_TEXTURE_PAINT[3] = {255, 255, 255}; Paint *paint_get_active(Scene *sce) { - if(sce && sce->basact && sce->basact->object) { + if(sce) { ToolSettings *ts = sce->toolsettings; - - switch(sce->basact->object->mode) { - case OB_MODE_SCULPT: - return &ts->sculpt->paint; - case OB_MODE_VERTEX_PAINT: - return &ts->vpaint->paint; - case OB_MODE_WEIGHT_PAINT: - return &ts->wpaint->paint; - case OB_MODE_TEXTURE_PAINT: - return &ts->imapaint.paint; + + if(sce->basact && sce->basact->object) { + switch(sce->basact->object->mode) { + case OB_MODE_SCULPT: + return &ts->sculpt->paint; + case OB_MODE_VERTEX_PAINT: + return &ts->vpaint->paint; + case OB_MODE_WEIGHT_PAINT: + return &ts->wpaint->paint; + case OB_MODE_TEXTURE_PAINT: + return &ts->imapaint.paint; + } } + + /* default to image paint */ + return &ts->imapaint.paint; } return NULL; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 2d3e3210afc..e18e7f54e49 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -69,7 +69,7 @@ #include "BKE_particle.h" #include "BKE_DerivedMesh.h" #include "BKE_object.h" -#include "BKE_softbody.h" +#include "BKE_cloth.h" #include "BKE_material.h" #include "BKE_key.h" #include "BKE_library.h" @@ -81,12 +81,11 @@ #include "RE_render_ext.h" -static void key_from_object(Object *ob, ParticleKey *key); static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float *fuv, float *orco, ParticleTexture *ptex, int event); static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex); -static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, +static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t); @@ -96,11 +95,10 @@ int count_particles(ParticleSystem *psys){ PARTICLE_P; int tot=0; - LOOP_PARTICLES { + LOOP_SHOWN_PARTICLES { if(pa->alive == PARS_KILLED); else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0); - else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)); else tot++; } return tot; @@ -110,55 +108,14 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur){ PARTICLE_P; int tot=0; - LOOP_PARTICLES { + LOOP_SHOWN_PARTICLES { if(pa->alive == PARS_KILLED); else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0); - else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)); else if(p%totgr==cur) tot++; } return tot; } -int psys_count_keys(ParticleSystem *psys) -{ - PARTICLE_P; - int totkey=0; - - LOOP_PARTICLES - totkey += pa->totkey; - - return totkey; -} -/* remember to free the pointer returned from this! */ -char *psys_menu_string(Object *ob, int for_sb) -{ - ParticleSystem *psys; - DynStr *ds; - char *str, num[6]; - int i; - - ds = BLI_dynstr_new(); - - if(for_sb) - BLI_dynstr_append(ds, "|Object%x-1"); - - for(i=0,psys=ob->particlesystem.first; psys; i++,psys=psys->next){ - - BLI_dynstr_append(ds, "|"); - sprintf(num,"%i. ",i+1); - BLI_dynstr_append(ds, num); - BLI_dynstr_append(ds, psys->part->id.name+2); - sprintf(num,"%%x%i",i+1); - BLI_dynstr_append(ds, num); - } - - str = BLI_dynstr_get_cstring(ds); - - BLI_dynstr_free(ds); - - return str; -} - /* we allocate path cache memory in chunks instead of a big continguous * chunk, windows' memory allocater fails to find big blocks of memory often */ @@ -258,30 +215,13 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys) return NULL; } -/* change object's active particle system */ -void psys_change_act(void *ob_v, void *act_v) -{ - Object *ob = ob_v; - ParticleSystem *npsys, *psys; - short act = *((short*)act_v)-1; - - if(act>=0){ - npsys=BLI_findlink(&ob->particlesystem,act); - psys=psys_get_current(ob); - - if(psys) - psys->flag &= ~PSYS_CURRENT; - if(npsys) - npsys->flag |= PSYS_CURRENT; - } -} -Object *psys_get_lattice(Scene *scene, Object *ob, ParticleSystem *psys) +Object *psys_get_lattice(ParticleSimulationData *sim) { Object *lattice=0; - if(psys_in_edit_mode(scene, psys)==0){ + if(psys_in_edit_mode(sim->scene, sim->psys)==0){ - ModifierData *md = (ModifierData*)psys_get_modifier(ob,psys); + ModifierData *md = (ModifierData*)psys_get_modifier(sim->ob, sim->psys); for(; md; md=md->next){ if(md->type==eModifierType_Lattice){ @@ -310,20 +250,20 @@ void psys_enable_all(Object *ob) for(; psys; psys=psys->next) psys->flag &= ~PSYS_DISABLED; } -int psys_ob_has_hair(Object *ob) -{ - ParticleSystem *psys = ob->particlesystem.first; - - for(; psys; psys=psys->next) - if(psys->part->type == PART_HAIR) - return 1; - - return 0; -} int psys_in_edit_mode(Scene *scene, ParticleSystem *psys) { return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys==psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit)); } +static void psys_create_frand(ParticleSystem *psys) +{ + int i; + float *rand = psys->frand = MEM_callocN(PSYS_FRAND_COUNT * sizeof(float), "particle randoms"); + + BLI_srandom(psys->seed); + + for(i=0; i<1024; i++, rand++) + *rand = BLI_frand(); +} int psys_check_enabled(Object *ob, ParticleSystem *psys) { ParticleSystemModifierData *psmd; @@ -345,6 +285,14 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) } else if(!(psmd->modifier.mode & eModifierMode_Realtime)) return 0; + + /* perhaps not the perfect place, but we have to be sure the rands are there before usage */ + if(!psys->frand) + psys_create_frand(psys); + else if(psys->recalc & PSYS_RECALC_RESET) { + MEM_freeN(psys->frand); + psys_create_frand(psys); + } return 1; } @@ -424,7 +372,7 @@ void free_keyed_keys(ParticleSystem *psys) } } } -void free_child_path_cache(ParticleSystem *psys) +static void free_child_path_cache(ParticleSystem *psys) { psys_free_path_cache_buffers(psys->childcache, &psys->childcachebufs); psys->childcache = NULL; @@ -478,6 +426,24 @@ void psys_free_particles(ParticleSystem *psys) psys->totpart= 0; } } +void psys_free_pdd(ParticleSystem *psys) +{ + if(psys->pdd->cdata) + MEM_freeN(psys->pdd->cdata); + psys->pdd->cdata = NULL; + + if(psys->pdd->vdata) + MEM_freeN(psys->pdd->vdata); + psys->pdd->vdata = NULL; + + if(psys->pdd->ndata) + MEM_freeN(psys->pdd->ndata); + psys->pdd->ndata = NULL; + + if(psys->pdd->vedata) + MEM_freeN(psys->pdd->vedata); + psys->pdd->vedata = NULL; +} /* free everything */ void psys_free(Object *ob, ParticleSystem * psys) { @@ -531,6 +497,14 @@ void psys_free(Object *ob, ParticleSystem * psys) BLI_kdtree_free(psys->tree); + if(psys->frand) + MEM_freeN(psys->frand); + + if(psys->pdd) { + psys_free_pdd(psys); + MEM_freeN(psys->pdd); + } + MEM_freeN(psys); } } @@ -722,12 +696,12 @@ void psys_render_restore(Object *ob, ParticleSystem *psys) int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) { DerivedMesh *dm= ctx->dm; - Mesh *me= (Mesh*)(ctx->ob->data); + Mesh *me= (Mesh*)(ctx->sim.ob->data); MFace *mf, *mface; MVert *mvert; ParticleRenderData *data; ParticleRenderElem *elems, *elem; - ParticleSettings *part= ctx->psys->part; + ParticleSettings *part= ctx->sim.psys->part; float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp; float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport; double vprate; @@ -736,10 +710,10 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) if(part->ren_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) return tot; - if(!ctx->psys->renderdata) + if(!ctx->sim.psys->renderdata) return tot; - data= ctx->psys->renderdata; + data= ctx->sim.psys->renderdata; if(data->timeoffset) return 0; if(!(part->simplify_flag & PART_SIMPLIFY_ENABLE)) @@ -816,7 +790,7 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) /* set simplification parameters per original face */ for(a=0, elem=elems; a<totorigface; a++, elem++) { - area = psys_render_projected_area(ctx->psys, facecenter[a], facearea[a], vprate, &viewport); + area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport); arearatio= fac*area/facearea[a]; if((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) { @@ -1438,7 +1412,7 @@ void psys_interpolate_mcol(MCol *mcol, int quad, float *w, MCol *mc) } } -float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, float *fw, float *values) +static float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, float *fw, float *values) { if(values==0 || index==-1) return 0.0; @@ -2075,7 +2049,7 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float VECADDFAC(state->co,state->co,mat[0],rough[0]); VECADDFAC(state->co,state->co,mat[1],rough[1]); } -static void do_path_effectors(Scene *scene, Object *ob, ParticleSystem *psys, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) +static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) { float force[3] = {0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f}; ParticleKey eff_key; @@ -2085,10 +2059,10 @@ static void do_path_effectors(Scene *scene, Object *ob, ParticleSystem *psys, in VECCOPY(eff_key.vel,(ca-1)->vel); QUATCOPY(eff_key.rot,(ca-1)->rot); - pa= psys->particles+i; - do_effectors(i, pa, &eff_key, scene, ob, psys, rootco, force, vel, dfra, cfra); + pa= sim->psys->particles+i; + do_effectors(sim, i, pa, &eff_key, rootco, force, vel, dfra, cfra); - VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) / (float)steps); + VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * sim->psys->part->eff_hair) / (float)steps); VecAddf(force, force, vec); @@ -2155,12 +2129,12 @@ float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup) } return vg; } -void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys) +void psys_find_parents(ParticleSimulationData *sim) { - ParticleSettings *part=psys->part; + ParticleSettings *part=sim->psys->part; KDTree *tree; ChildParticle *cpa; - int p, totparent,totchild=psys->totchild; + int p, totparent,totchild=sim->psys->totchild; float co[3], orco[3]; int from=PART_FROM_FACE; totparent=(int)(totchild*part->parents*0.3); @@ -2170,15 +2144,15 @@ void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSys tree=BLI_kdtree_new(totparent); - for(p=0,cpa=psys->child; p<totparent; p++,cpa++){ - psys_particle_on_emitter(psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); + for(p=0,cpa=sim->psys->child; p<totparent; p++,cpa++){ + psys_particle_on_emitter(sim->psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); BLI_kdtree_insert(tree, p, orco, NULL); } BLI_kdtree_balance(tree); for(; p<totchild; p++,cpa++){ - psys_particle_on_emitter(psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); + psys_particle_on_emitter(sim->psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); cpa->parent=BLI_kdtree_find_nearest(tree, orco, NULL, NULL); } @@ -2216,11 +2190,11 @@ static void get_strand_normal(Material *ma, float *surfnor, float surfdist, floa VECCOPY(nor, vnor); } -int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate) +static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate) { ParticleThreadContext *ctx= threads[0].ctx; - Object *ob= ctx->ob; - ParticleSystem *psys= ctx->psys; +/* Object *ob= ctx->sim.ob; */ + ParticleSystem *psys= ctx->sim.psys; ParticleSettings *part = psys->part; ParticleEditSettings *pset = &scene->toolsettings->particle; int totparent=0, between=0; @@ -2253,10 +2227,10 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in if(totchild==0) return 0; /* init random number generator */ - if(ctx->psys->part->flag & PART_ANIM_BRANCHING) - seed= 31415926 + ctx->psys->seed + (int)cfra; + if(ctx->sim.psys->part->flag & PART_ANIM_BRANCHING) + seed= 31415926 + ctx->sim.psys->seed + (int)cfra; else - seed= 31415926 + ctx->psys->seed; + seed= 31415926 + ctx->sim.psys->seed; if(part->flag & PART_BRANCHING || ctx->editupdate || totchild < 10000) totthread= 1; @@ -2274,7 +2248,7 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in ctx->parent_pass= 0; ctx->cfra= cfra; - psys->lattice = psys_get_lattice(scene, ob, psys); + psys->lattice = psys_get_lattice(&ctx->sim); /* cache all relevant vertex groups if they exist */ if(part->from!=PART_FROM_PARTICLE){ @@ -2300,11 +2274,11 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in } /* note: this function must be thread safe, except for branching! */ -void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i) +static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i) { ParticleThreadContext *ctx= thread->ctx; - Object *ob= ctx->ob; - ParticleSystem *psys = ctx->psys; + Object *ob= ctx->sim.ob; + ParticleSystem *psys = ctx->sim.psys; ParticleSettings *part = psys->part; ParticleCacheKey **cache= psys->childcache; ParticleCacheKey **pcache= psys->pathcache; @@ -2373,7 +2347,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, cpa_fuv = cpa->fuv; cpa_from = PART_FROM_FACE; - psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0); + psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0); if(part->path_start==0.0f) { /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ @@ -2383,7 +2357,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, pa = psys->particles + cpa->parent; - psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat); pa=0; } @@ -2405,9 +2379,9 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, cpa_num=pa->num; cpa_fuv=pa->fuv; - psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0); + psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0); - psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat); } keys->steps = ctx->steps; @@ -2424,7 +2398,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, /* get different child parameters from textures & vgroups */ get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex); - if(ptex.exist < cpa->rand[1]) { + if(ptex.exist < PSYS_FRAND(i + 24)) { keys->steps = -1; return; } @@ -2473,7 +2447,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, if(part->flag & PART_CHILD_EFFECT) { for(k=0,state=keys; k<=ctx->steps; k++,state++) { if(k) { - do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec); + do_path_effectors(&ctx->sim, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec); } else { VecSubf(eff_vec,(state+1)->co,state->co); @@ -2499,7 +2473,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, } /* apply different deformations to the child path */ - do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t); + do_child_modifiers(&ctx->sim, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t); /* TODO: better branching */ //if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING) @@ -2576,7 +2550,7 @@ static void *exec_child_path_cache(void *data) { ParticleThread *thread= (ParticleThread*)data; ParticleThreadContext *ctx= thread->ctx; - ParticleSystem *psys= ctx->psys; + ParticleSystem *psys= ctx->sim.psys; ParticleCacheKey **cache= psys->childcache; ChildParticle *cpa; int i, totchild= ctx->totchild, first= 0; @@ -2593,21 +2567,21 @@ static void *exec_child_path_cache(void *data) return 0; } -void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int editupdate) +void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupdate) { - ParticleSettings *part = psys->part; + ParticleSettings *part = sim->psys->part; ParticleThread *pthreads; ParticleThreadContext *ctx; ParticleCacheKey **cache; ListBase threads; int i, totchild, totparent, totthread; - if(psys->flag & PSYS_GLOBAL_HAIR) + if(sim->psys->flag & PSYS_GLOBAL_HAIR) return; - pthreads= psys_threads_create(scene, ob, psys); + pthreads= psys_threads_create(sim); - if(!psys_threads_init_path(pthreads, scene, cfra, editupdate)) { + if(!psys_threads_init_path(pthreads, sim->scene, cfra, editupdate)) { psys_threads_free(pthreads); return; } @@ -2616,14 +2590,14 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa totchild= ctx->totchild; totparent= ctx->totparent; - if(editupdate && psys->childcache && !(part->flag & PART_BRANCHING) && totchild == psys->totchildcache) { - cache = psys->childcache; + if(editupdate && sim->psys->childcache && !(part->flag & PART_BRANCHING) && totchild == sim->psys->totchildcache) { + cache = sim->psys->childcache; } else { /* clear out old and create new empty path cache */ - free_child_path_cache(psys); - psys->childcache= psys_alloc_path_cache_buffers(&psys->childcachebufs, totchild, ctx->steps+1); - psys->totchildcache = totchild; + free_child_path_cache(sim->psys); + sim->psys->childcache= psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx->steps+1); + sim->psys->totchildcache = totchild; } totthread= pthreads[0].tot; @@ -2661,27 +2635,29 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Makes child strands possible and creates them too into the cache. */ /* -Cached path data is also used to determine cut position for the editmode tool. */ -void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra) +void psys_cache_paths(ParticleSimulationData *sim, float cfra) { - ParticleCacheKey *ca, **cache= psys->pathcache; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); + PARTICLE_PSMD; + ParticleEditSettings *pset = &sim->scene->toolsettings->particle; + ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; - ParticleEditSettings *pset = &scene->toolsettings->particle; + ParticleCacheKey *ca, **cache= psys->pathcache; DerivedMesh *hair_dm = psys->hair_out_dm; - ParticleData *pa = psys->particles; ParticleKey result; Material *ma; ParticleInterpolationData pind; + + PARTICLE_P; float birthtime = 0.0, dietime = 0.0; - float t, time = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec; + float t, time = 0.0, dfra = 1.0, frs_sec = sim->scene->r.frs_sec; float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}; float prev_tangent[3], hairmat[4][4]; float rotmat[3][3]; - int k,i; + int k; int steps = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step)); int totpart = psys->totpart; float length, vec[3]; @@ -2693,7 +2669,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra if((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) return; - if(psys_in_edit_mode(scene, psys)) + if(psys_in_edit_mode(sim->scene, psys)) if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0) return; @@ -2706,8 +2682,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra psys_free_path_cache(psys, psys->edit); cache= psys->pathcache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1); - psys->lattice = psys_get_lattice(scene, ob, psys); - ma= give_current_material(ob, psys->part->omat); + psys->lattice = psys_get_lattice(sim); + ma= give_current_material(sim->ob, psys->part->omat); if(ma && (psys->part->draw & PART_DRAW_MAT_COL)) VECCOPY(col, &ma->r) @@ -2720,12 +2696,9 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra } /*---first main loop: create all actual particles' paths---*/ - for(i=0; i<totpart; i++, pa++){ - if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) - continue; - + LOOP_SHOWN_PARTICLES { if(!psys->totchild) { - BLI_srandom(psys->seed + i); + BLI_srandom(psys->seed + p); pa_length = 1.0f - part->randlength * BLI_frand(); if(vg_length) pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length); @@ -2737,15 +2710,15 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE); pind.dm = hair_dm; - memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); + memset(cache[p], 0, sizeof(*cache[p])*(steps+1)); - cache[i]->steps = steps; + cache[p]->steps = steps; /*--get the first data points--*/ - init_particle_interpolation(ob, psys, pa, &pind); + init_particle_interpolation(sim->ob, sim->psys, pa, &pind); /* hairmat is needed for for non-hair particle too so we get proper rotations */ - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, psmd->dm, psys->part->from, pa, hairmat); VECCOPY(rotmat[0], hairmat[2]); VECCOPY(rotmat[1], hairmat[1]); VECCOPY(rotmat[2], hairmat[0]); @@ -2761,26 +2734,26 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra } if(birthtime >= dietime) { - cache[i]->steps = -1; + cache[p]->steps = -1; continue; } dietime = birthtime + pa_length * (dietime - birthtime); /*--interpolate actual path from data points--*/ - for(k=0, ca=cache[i]; k<=steps; k++, ca++){ + for(k=0, ca=cache[p]; k<=steps; k++, ca++){ time = (float)k / (float)steps; t = birthtime + time * (dietime - birthtime); result.time = -t; - do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result); + do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, &result); /* dynamic hair is in object space */ /* keyed and baked are allready in global space */ if(hair_dm) - Mat4MulVecfl(ob->obmat, result.co); + Mat4MulVecfl(sim->ob->obmat, result.co); else if(!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR)) Mat4MulVecfl(hairmat, result.co); @@ -2790,23 +2763,23 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra /*--modify paths and calculate rotation & velocity--*/ - VecSubf(vec,(cache[i]+1)->co,cache[i]->co); + VecSubf(vec,(cache[p]+1)->co,cache[p]->co); length = VecLength(vec); effector= 1.0f; if(vg_effector) effector*= psys_particle_value_from_verts(psmd->dm,psys->part->from,pa,vg_effector); - for(k=0, ca=cache[i]; k<=steps; k++, ca++) { + for(k=0, ca=cache[p]; k<=steps; k++, ca++) { if(!(psys->flag & PSYS_GLOBAL_HAIR)) { /* apply effectors */ if(!(psys->part->flag & PART_CHILD_EFFECT) && k) - do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); + do_path_effectors(sim, p, ca, k, steps, cache[p]->co, effector, dfra, cfra, &length, vec); /* apply guide curves to path data */ if(psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0) /* ca is safe to cast, since only co and vel are used */ - do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); + do_guide(sim->scene, (ParticleKey*)ca, p, (float)k/(float)steps, &psys->effectors); /* apply lattice */ if(psys->lattice) @@ -3022,23 +2995,7 @@ void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, flo if(time) *time=key->time; } /*-------changing particle keys from space to another-------*/ -void psys_key_to_object(Object *ob, ParticleKey *key, float imat[][4]){ - float q[4], imat2[4][4]; - - if(imat==0){ - Mat4Invert(imat2,ob->obmat); - imat=imat2; - } - - VECADD(key->vel,key->vel,key->co); - - Mat4MulVecfl(imat,key->co); - Mat4MulVecfl(imat,key->vel); - Mat4ToQuat(imat,q); - - VECSUB(key->vel,key->vel,key->co); - QuatMul(key->rot,q,key->rot); -} +#if 0 static void key_from_object(Object *ob, ParticleKey *key){ float q[4]; @@ -3051,6 +3008,7 @@ static void key_from_object(Object *ob, ParticleKey *key){ VECSUB(key->vel,key->vel,key->co); QuatMul(key->rot,q,key->rot); } +#endif static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat[][4]) { @@ -3409,41 +3367,6 @@ void psys_flush_particle_settings(Scene *scene, ParticleSettings *part, int reca } } -LinkNode *psys_using_settings(struct Scene *scene, ParticleSettings *part, int flush_update) -{ - Object *ob, *tob; - ParticleSystem *psys, *tpsys; - LinkNode *node= NULL; - int found; - - /* update all that have same particle settings */ - for(ob=G.main->object.first; ob; ob=ob->id.next) { - found= 0; - - for(psys=ob->particlesystem.first; psys; psys=psys->next) { - if(psys->part == part) { - BLI_linklist_append(&node, psys); - found++; - } - else if(psys->part->type == PART_REACTOR){ - tob= (psys->target_ob)? psys->target_ob: ob; - tpsys= BLI_findlink(&tob->particlesystem, psys->target_psys-1); - - if(tpsys && tpsys->part==part) { - BLI_linklist_append(&node, tpsys); - found++; - } - } - } - - if(flush_update && found) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - } - - return node; -} - - /************************************************/ /* Textures */ /************************************************/ @@ -3540,7 +3463,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float } if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } } -void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleData *pa, ParticleTexture *ptex, int event) +void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *pa, ParticleTexture *ptex, int event) { MTex *mtex; int m; @@ -3555,14 +3478,14 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd short blend=mtex->blendtype; short neg=mtex->pmaptoneg; - if((mtex->texco & TEXCO_UV) && ELEM(psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { - if(!get_particle_uv(psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) { + if((mtex->texco & TEXCO_UV) && ELEM(sim->psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { + if(!get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) { /* failed to get uv's, let's try orco's */ - psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); + psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); } } else { - psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); + psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); } externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3); @@ -3607,38 +3530,9 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd /************************************************/ /* Particle State */ /************************************************/ -float psys_get_timestep(ParticleSettings *part) +float psys_get_timestep(ParticleSimulationData *sim) { - return 0.04f*part->timetweak; -} -/* part->size should be updated with possible ipo effection before this is called */ -float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd, IpoCurve *icu_size, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, float *vg_size) -{ - ParticleTexture ptex; - float size=1.0f; - - BLI_srandom(psys->seed + (pa - psys->particles) + 100); - - if(ma && part->from!=PART_FROM_PARTICLE){ - ptex.size=size; - psys_get_texture(ob,ma,psmd,psys,pa,&ptex,MAP_PA_SIZE); - size=ptex.size; - } - -#if 0 // XXX old animation system - if(icu_size){ - calc_icu(icu_size,pa->time); - size*=icu_size->curval; - } -#endif // XXX old animation system - - if(vg_size) - size*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_size); - - if(part->randsize!=0.0) - size*= 1.0f - part->randsize * BLI_frand(); - - return size*part->size; + return 0.04f * sim->psys->part->timetweak; } float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime) { @@ -3653,7 +3547,7 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, w++; } - life = part->lifetime*(1.0f-part->randlife*cpa->rand[1]); + life = part->lifetime * (1.0f - part->randlife * PSYS_FRAND(cpa - psys->child + 25)); } else{ ParticleData *pa = psys->particles + cpa->parent; @@ -3702,13 +3596,16 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, size*=part->childsize; if(part->childrandsize!=0.0) - size *= 1.0f - part->childrandsize*cpa->rand[2]; + size *= 1.0f - part->childrandsize * PSYS_FRAND(cpa - psys->child + 26); return size; } static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex) { - ptex->length= 1.0f - part->randlength*cpa->rand[0]; + ParticleSystem *psys = ctx->sim.psys; + int i = cpa - psys->child; + + ptex->length= 1.0f - part->randlength * PSYS_FRAND(i + 26); ptex->clump=1.0; ptex->kink=1.0; ptex->rough1= 1.0; @@ -3717,13 +3614,13 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread ptex->exist= 1.0; ptex->effector= 1.0; - ptex->length*= part->clength_thres < cpa->rand[1] ? part->clength : 1.0f; + ptex->length*= part->clength_thres < PSYS_FRAND(i + 27) ? part->clength : 1.0f; get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex, MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); - if(ptex->exist < cpa->rand[1]) + if(ptex->exist < PSYS_FRAND(i + 24)) return; if(ctx->vg_length) @@ -3741,18 +3638,20 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread if(ctx->vg_effector) ptex->effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector); } -static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t) +static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t) { + ParticleSettings *part = sim->psys->part; + int i = cpa - sim->psys->child; int guided = 0; if(part->flag & PART_CHILD_EFFECT) /* state is safe to cast, since only co and vel are used */ - guided = do_guide(scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors)); + guided = do_guide(sim->scene, (ParticleKey*)state, cpa->parent, t, &(sim->psys->effectors)); if(guided==0){ if(part->kink) do_prekink(state, par, par_rot, t, part->kink_freq * ptex->kink, part->kink_shape, - part->kink_amp, part->kink, part->kink_axis, ob->obmat); + part->kink_amp, part->kink, part->kink_axis, sim->ob->obmat); do_clump(state, par, t, part->clumpfac, part->clumppow, ptex->clump); } @@ -3761,17 +3660,18 @@ static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, P do_rough(orco, mat, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state); if(part->rough2 != 0.0 && ptex->rough2 != 0.0) - do_rough(cpa->rand, mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state); + do_rough(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state); if(part->rough_end != 0.0 && ptex->roughe != 0.0) - do_rough_end(cpa->rand, mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state); + do_rough_end(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state); } /* get's hair (or keyed) particles state at the "path time" specified in state->time */ -void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel) +void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, int vel) { - ParticleSettings *part = psys->part; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - Material *ma = give_current_material(ob, part->omat); + PARTICLE_PSMD; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = sim->psys->part; + Material *ma = give_current_material(sim->ob, part->omat); ParticleData *pa; ChildParticle *cpa; ParticleTexture ptex; @@ -3779,7 +3679,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i ParticleThreadContext ctx; /* fake thread context for child modifiers */ ParticleInterpolationData pind; - float t, frs_sec = scene->r.frs_sec; + float t, frs_sec = sim->scene->r.frs_sec; float co[3], orco[3]; float hairmat[4][4]; int totparent = 0; @@ -3807,17 +3707,17 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i pind.cache = cached ? psys->pointcache : NULL; pind.epoint = NULL; pind.dm = psys->hair_out_dm; - init_particle_interpolation(ob, psys, pa, &pind); + init_particle_interpolation(sim->ob, psys, pa, &pind); do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state); if(!keyed && !cached) { if((pa->flag & PARS_REKEY)==0) { - psys_mat_hair_to_global(ob, psmd->dm, part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, part->from, pa, hairmat); Mat4MulVecfl(hairmat, state->co); Mat4Mul3Vecfl(hairmat, state->vel); if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) { - do_guide(scene, state, p, state->time, &psys->effectors); + do_guide(sim->scene, state, p, state->time, &psys->effectors); /* TODO: proper velocity handling */ } @@ -3850,7 +3750,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i /* get parent states */ while(w<4 && cpa->pa[w]>=0){ keys[w].time = state->time; - psys_get_particle_on_path(scene, ob, psys, cpa->pa[w], keys+w, 1); + psys_get_particle_on_path(sim, cpa->pa[w], keys+w, 1); w++; } @@ -3870,14 +3770,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i pa = psys->particles + cpa->parent; - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); pa=0; } else{ /* get the parent state */ keys->time = state->time; - psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1); + psys_get_particle_on_path(sim, cpa->parent, keys,1); /* get the original coordinates (orco) for texture usage */ pa=psys->particles+cpa->parent; @@ -3888,7 +3788,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0); - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); } /* correct child ipo timing */ @@ -3937,7 +3837,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i copy_particle_key(&tstate, state, 1); /* apply different deformations to the child path */ - do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, hairmat, state, t); + do_child_modifiers(sim, &ptex, par, par->rot, cpa, orco, hairmat, state, t); /* try to estimate correct velocity */ if(vel){ @@ -3946,13 +3846,13 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i if(t>=0.001f){ tstate.time=t-0.001f; - psys_get_particle_on_path(scene,ob,psys,p,&tstate,0); + psys_get_particle_on_path(sim,p,&tstate,0); VECSUB(state->vel,state->co,tstate.co); Normalize(state->vel); } else{ tstate.time=t+0.001f; - psys_get_particle_on_path(scene, ob,psys,p,&tstate,0); + psys_get_particle_on_path(sim,p,&tstate,0); VECSUB(state->vel,tstate.co,state->co); Normalize(state->vel); } @@ -3962,39 +3862,52 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i } } /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */ -int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int always){ - ParticleSettings *part=psys->part; - ParticleData *pa=0; +int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always){ + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + ParticleData *pa = NULL; + ChildParticle *cpa = NULL; float cfra; - int totpart=psys->totpart, between=0; + int totpart = psys->totpart; /* negative time means "use current time" */ - if(state->time>0) - cfra=state->time; - else - cfra= bsystem_time(scene, 0, (float)scene->r.cfra,0.0); + cfra = state->time > 0 ? state->time : bsystem_time(sim->scene, 0, (float)sim->scene->r.cfra, 0.0); - if(psys->totchild && p>=totpart){ - if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ - between=1; + if(p>=totpart){ + if(!psys->totchild) + return 0; + + if(part->from != PART_FROM_PARTICLE && part->childtype == PART_CHILD_FACES){ + if(!(psys->flag & PSYS_KEYED)) + return 0; + + cpa = psys->child + p - totpart; + + state->time = psys_get_child_time(psys, cpa, cfra, NULL, NULL); + + if(!always) + if((state->time < 0.0 && !(part->flag & PART_UNBORN)) + || (state->time > 1.0 && !(part->flag & PART_DIED))) + return 0; + + state->time= (cfra - (part->sta + (part->end - part->sta) * PSYS_FRAND(p + 23))) / (part->lifetime * PSYS_FRAND(p + 24)); + + psys_get_particle_on_path(sim, p, state,1); + return 1; + } + else { + cpa = sim->psys->child + p - totpart; + pa = sim->psys->particles + cpa->parent; } - else - pa=psys->particles+(psys->child+p-totpart)->parent; } - else - pa=psys->particles+p; + else { + pa = sim->psys->particles + p; + } - if(between){ - state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra,NULL,NULL); + if(pa) { + if(pa->alive == PARS_KILLED) return 0; - if(always==0) - if((state->time<0.0 && (part->flag & PART_UNBORN)==0) - || (state->time>1.0 && (part->flag & PART_DIED)==0)) - return 0; - } - else{ - if(pa->alive==PARS_KILLED) return 0; - if(always==0) + if(!always) if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0) || (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0)) return 0; @@ -4002,38 +3915,28 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy state->time = MIN2(state->time, pa->dietime); } - if(psys->flag & PSYS_KEYED){ - if(between){ - ChildParticle *cpa=psys->child+p-totpart; - state->time= (cfra-(part->sta+(part->end-part->sta)*cpa->rand[0]))/(part->lifetime*cpa->rand[1]); - } - else - state->time= -cfra; - - psys_get_particle_on_path(scene, ob, psys, p, state,1); + if(sim->psys->flag & PSYS_KEYED){ + state->time= -cfra; + psys_get_particle_on_path(sim, p, state,1); return 1; } else{ - if(between) - return 0; /* currently not supported */ - else if(psys->totchild && p>=psys->totpart){ - ChildParticle *cpa=psys->child+p-psys->totpart; + if(cpa){ ParticleKey *key1; float t = (cfra - pa->time + pa->loop * pa->lifetime) / pa->lifetime; - pa = psys->particles + cpa->parent; key1=&pa->state; offset_child(cpa, key1, state, part->childflat, part->childrad); CLAMP(t,0.0,1.0); if(part->kink) /* TODO: part->kink_freq*pa_kink */ - do_prekink(state,key1,key1->rot,t,part->kink_freq,part->kink_shape,part->kink_amp,part->kink,part->kink_axis,ob->obmat); + do_prekink(state,key1,key1->rot,t,part->kink_freq,part->kink_shape,part->kink_amp,part->kink,part->kink_axis,sim->ob->obmat); /* TODO: pa_clump vgroup */ do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0); if(psys->lattice) - calc_latt_deform(psys->lattice, state->co,1.0f); + calc_latt_deform(sim->psys->lattice, state->co,1.0f); } else{ if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)) @@ -4044,7 +3947,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy /* let's interpolate to try to be as accurate as possible */ if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { ParticleKey keys[4]; - float dfra, keytime, frs_sec = scene->r.frs_sec; + float dfra, keytime, frs_sec = sim->scene->r.frs_sec; if(pa->prev_state.time >= pa->state.time) { /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */ @@ -4079,8 +3982,8 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy } } - if(psys->lattice) - calc_latt_deform(psys->lattice, state->co,1.0f); + if(sim->psys->lattice) + calc_latt_deform(sim->psys->lattice, state->co,1.0f); } return 1; @@ -4136,8 +4039,11 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo } } -void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) +void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) { + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; + ParticleSystemModifierData *psmd = sim->psmd; float loc[3], nor[3], vec[3], side[3], len, obrotmat[4][4], qmat[4][4]; float xvec[3] = {-1.0, 0.0, 0.0}, q[4]; @@ -4145,7 +4051,7 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys len= Normalize(vec); if(pa) - psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0); + psys_particle_on_emitter(psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0); else psys_particle_on_emitter(psmd, (psys->part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE, diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index fb12cfe3147..1b6d56e6459 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -122,7 +122,6 @@ static int get_current_display_percentage(ParticleSystem *psys) void psys_reset(ParticleSystem *psys, int mode) { - ParticleSettings *part= psys->part; PARTICLE_P; if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) { @@ -165,20 +164,22 @@ void psys_reset(ParticleSystem *psys, int mode) psys->pointcache->simframe= 0; } -static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) +static void realloc_particles(ParticleSimulationData *sim, int new_totpart) { + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; ParticleData *newpars = NULL; BoidParticle *newboids = NULL; PARTICLE_P; int totpart, totsaved = 0; if(new_totpart<0) { - if(psys->part->distr==PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) { - totpart= psys->part->grid_res; + if(part->distr==PART_DISTR_GRID && part->from != PART_FROM_VERT) { + totpart= part->grid_res; totpart*=totpart*totpart; } else - totpart=psys->part->totpart; + totpart=part->totpart; } else totpart=new_totpart; @@ -213,6 +214,7 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) if(pa->hair) MEM_freeN(pa->hair); MEM_freeN(psys->particles); + psys_free_pdd(psys); } psys->particles=newpars; @@ -606,13 +608,13 @@ static int binary_search_distribution(float *sum, int n, float value) /* note: this function must be thread safe, for from == PART_FROM_CHILD */ #define ONLY_WORKING_WITH_PA_VERTS 0 -void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p) +static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p) { ParticleThreadContext *ctx= thread->ctx; - Object *ob= ctx->ob; + Object *ob= ctx->sim.ob; DerivedMesh *dm= ctx->dm; ParticleData *tpa; - ParticleSettings *part= ctx->psys->part; +/* ParticleSettings *part= ctx->sim.psys->part; */ float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3], ornor1[3]; float cur_d, min_d, randu, randv; int from= ctx->from; @@ -625,7 +627,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C pa->num= ctx->index[p]; pa->fuv[0] = 1.0f; pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0; - //pa->verts[0] = pa->verts[1] = pa->verts[2] = 0; #if ONLY_WORKING_WITH_PA_VERTS if(ctx->tree){ @@ -653,7 +654,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel); psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv); ctx->jitoff[i]++; - //ctx->jitoff[i]=(float)fmod(ctx->jitoff[i]+ctx->maxweight/ctx->weight[i],(float)ctx->jitlevel); break; case PART_DISTR_RAND: randu= rng_getFloat(thread->rng); @@ -663,12 +663,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C } pa->foffset= 0.0f; - /* - pa->verts[0] = mface->v1; - pa->verts[1] = mface->v2; - pa->verts[2] = mface->v3; - */ - /* experimental */ if(from==PART_FROM_VOLUME){ MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); @@ -724,10 +718,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C } } else if(from == PART_FROM_PARTICLE) { - //pa->verts[0]=0; /* not applicable */ - //pa->verts[1]=0; - //pa->verts[2]=0; - tpa=ctx->tpars+ctx->index[p]; pa->num=ctx->index[p]; pa->fuv[0]=tpa->fuv[0]; @@ -743,42 +733,30 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C cpa->num=0; cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f; cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; - cpa->rand[0]=cpa->rand[1]=cpa->rand[2]=0.0f; return; } mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE); - //switch(distr){ - // case PART_DISTR_JIT: - // i=index[p]; - // psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mf->v4, cpa->fuv); - // ctx->jitoff[i]=(float)fmod(ctx->jitoff[i]+ctx->maxweight/ctx->weight[i],(float)ctx->jitlevel); - // break; - // case PART_DISTR_RAND: - randu= rng_getFloat(thread->rng); - randv= rng_getFloat(thread->rng); - psys_uv_to_w(randu, randv, mf->v4, cpa->fuv); - // break; - //} + randu= rng_getFloat(thread->rng); + randv= rng_getFloat(thread->rng); + psys_uv_to_w(randu, randv, mf->v4, cpa->fuv); - cpa->rand[0] = rng_getFloat(thread->rng); - cpa->rand[1] = rng_getFloat(thread->rng); - cpa->rand[2] = rng_getFloat(thread->rng); cpa->num = ctx->index[p]; if(ctx->tree){ KDTreeNearest ptn[10]; - int w,maxw, do_seams; + int w,maxw;//, do_seams; float maxd,mind,dd,totw=0.0; int parent[10]; float pweight[10]; - do_seams= (part->flag&PART_CHILD_SEAMS && ctx->seams); + /*do_seams= (part->flag&PART_CHILD_SEAMS && ctx->seams);*/ psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,0,0,orco1,ornor1); transform_mesh_orco_verts((Mesh*)ob->data, &orco1, 1, 1); - maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,orco1,ornor1,ptn); + //maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,orco1,ornor1,ptn); + maxw = BLI_kdtree_find_n_nearest(ctx->tree,4,orco1,ornor1,ptn); maxd=ptn[maxw-1].dist; mind=ptn[0].dist; @@ -788,70 +766,68 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C for(w=0; w<maxw; w++){ parent[w]=ptn[w].index; pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd)); - //pweight[w]= (1.0f - ptn[w].dist*ptn[w].dist/(maxd*maxd)); - //pweight[w] *= pweight[w]; } for(;w<10; w++){ parent[w]=-1; pweight[w]=0.0f; } - if(do_seams){ - ParticleSeam *seam=ctx->seams; - float temp[3],temp2[3],tan[3]; - float inp,cur_len,min_len=10000.0f; - int min_seam=0, near_vert=0; - /* find closest seam */ - for(i=0; i<ctx->totseam; i++, seam++){ - VecSubf(temp,co1,seam->v0); - inp=Inpf(temp,seam->dir)/seam->length2; - if(inp<0.0f){ - cur_len=VecLenf(co1,seam->v0); - } - else if(inp>1.0f){ - cur_len=VecLenf(co1,seam->v1); - } - else{ - VecCopyf(temp2,seam->dir); - VecMulf(temp2,inp); - cur_len=VecLenf(temp,temp2); - } - if(cur_len<min_len){ - min_len=cur_len; - min_seam=i; - if(inp<0.0f) near_vert=-1; - else if(inp>1.0f) near_vert=1; - else near_vert=0; - } - } - seam=ctx->seams+min_seam; - - VecCopyf(temp,seam->v0); - - if(near_vert){ - if(near_vert==-1) - VecSubf(tan,co1,seam->v0); - else{ - VecSubf(tan,co1,seam->v1); - VecCopyf(temp,seam->v1); - } + //if(do_seams){ + // ParticleSeam *seam=ctx->seams; + // float temp[3],temp2[3],tan[3]; + // float inp,cur_len,min_len=10000.0f; + // int min_seam=0, near_vert=0; + // /* find closest seam */ + // for(i=0; i<ctx->totseam; i++, seam++){ + // VecSubf(temp,co1,seam->v0); + // inp=Inpf(temp,seam->dir)/seam->length2; + // if(inp<0.0f){ + // cur_len=VecLenf(co1,seam->v0); + // } + // else if(inp>1.0f){ + // cur_len=VecLenf(co1,seam->v1); + // } + // else{ + // VecCopyf(temp2,seam->dir); + // VecMulf(temp2,inp); + // cur_len=VecLenf(temp,temp2); + // } + // if(cur_len<min_len){ + // min_len=cur_len; + // min_seam=i; + // if(inp<0.0f) near_vert=-1; + // else if(inp>1.0f) near_vert=1; + // else near_vert=0; + // } + // } + // seam=ctx->seams+min_seam; + // + // VecCopyf(temp,seam->v0); + // + // if(near_vert){ + // if(near_vert==-1) + // VecSubf(tan,co1,seam->v0); + // else{ + // VecSubf(tan,co1,seam->v1); + // VecCopyf(temp,seam->v1); + // } + + // Normalize(tan); + // } + // else{ + // VecCopyf(tan,seam->tan); + // VecSubf(temp2,co1,temp); + // if(Inpf(tan,temp2)<0.0f) + // VecNegf(tan); + // } + // for(w=0; w<maxw; w++){ + // VecSubf(temp2,ptn[w].co,temp); + // if(Inpf(tan,temp2)<0.0f){ + // parent[w]=-1; + // pweight[w]=0.0f; + // } + // } - Normalize(tan); - } - else{ - VecCopyf(tan,seam->tan); - VecSubf(temp2,co1,temp); - if(Inpf(tan,temp2)<0.0f) - VecNegf(tan); - } - for(w=0; w<maxw; w++){ - VecSubf(temp2,ptn[w].co,temp); - if(Inpf(tan,temp2)<0.0f){ - parent[w]=-1; - pweight[w]=0.0f; - } - } - - } + //} for(w=0,i=0; w<maxw && i<4; w++){ if(parent[w]>=0){ @@ -877,7 +853,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C static void *exec_distribution(void *data) { ParticleThread *thread= (ParticleThread*)data; - ParticleSystem *psys= thread->ctx->psys; + ParticleSystem *psys= thread->ctx->sim.psys; ParticleData *pa; ChildParticle *cpa; int p, totpart; @@ -944,11 +920,11 @@ static int compare_orig_index(const void *p1, const void *p2) /* 6. and we're done! */ /* This is to denote functionality that does not yet work with mesh - only derived mesh */ -int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from) +static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from) { ParticleThreadContext *ctx= threads[0].ctx; - Object *ob= ctx->ob; - ParticleSystem *psys= ctx->psys; + Object *ob= ctx->sim.ob; + ParticleSystem *psys= ctx->sim.psys; Object *tob; ParticleData *pa=0, *tpars= 0; ParticleSettings *part; @@ -1000,49 +976,49 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive totpart=get_psys_tot_child(scene, psys); cfrom=from=PART_FROM_FACE; - if(part->flag&PART_CHILD_SEAMS){ - MEdge *ed, *medge=dm->getEdgeDataArray(dm,CD_MEDGE); - MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); - int totedge=dm->getNumEdges(dm); + //if(part->flag&PART_CHILD_SEAMS){ + // MEdge *ed, *medge=dm->getEdgeDataArray(dm,CD_MEDGE); + // MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); + // int totedge=dm->getNumEdges(dm); - for(p=0, ed=medge; p<totedge; p++,ed++) - if(ed->flag&ME_SEAM) - totseam++; + // for(p=0, ed=medge; p<totedge; p++,ed++) + // if(ed->flag&ME_SEAM) + // totseam++; - if(totseam){ - ParticleSeam *cur_seam=seams=MEM_callocN(totseam*sizeof(ParticleSeam),"Child Distribution Seams"); - float temp[3],temp2[3]; + // if(totseam){ + // ParticleSeam *cur_seam=seams=MEM_callocN(totseam*sizeof(ParticleSeam),"Child Distribution Seams"); + // float temp[3],temp2[3]; - for(p=0, ed=medge; p<totedge; p++,ed++){ - if(ed->flag&ME_SEAM){ - VecCopyf(cur_seam->v0,(mvert+ed->v1)->co); - VecCopyf(cur_seam->v1,(mvert+ed->v2)->co); + // for(p=0, ed=medge; p<totedge; p++,ed++){ + // if(ed->flag&ME_SEAM){ + // VecCopyf(cur_seam->v0,(mvert+ed->v1)->co); + // VecCopyf(cur_seam->v1,(mvert+ed->v2)->co); - VecSubf(cur_seam->dir,cur_seam->v1,cur_seam->v0); + // VecSubf(cur_seam->dir,cur_seam->v1,cur_seam->v0); - cur_seam->length2=VecLength(cur_seam->dir); - cur_seam->length2*=cur_seam->length2; + // cur_seam->length2=VecLength(cur_seam->dir); + // cur_seam->length2*=cur_seam->length2; - temp[0]=(float)((mvert+ed->v1)->no[0]); - temp[1]=(float)((mvert+ed->v1)->no[1]); - temp[2]=(float)((mvert+ed->v1)->no[2]); - temp2[0]=(float)((mvert+ed->v2)->no[0]); - temp2[1]=(float)((mvert+ed->v2)->no[1]); - temp2[2]=(float)((mvert+ed->v2)->no[2]); + // temp[0]=(float)((mvert+ed->v1)->no[0]); + // temp[1]=(float)((mvert+ed->v1)->no[1]); + // temp[2]=(float)((mvert+ed->v1)->no[2]); + // temp2[0]=(float)((mvert+ed->v2)->no[0]); + // temp2[1]=(float)((mvert+ed->v2)->no[1]); + // temp2[2]=(float)((mvert+ed->v2)->no[2]); - VecAddf(cur_seam->nor,temp,temp2); - Normalize(cur_seam->nor); + // VecAddf(cur_seam->nor,temp,temp2); + // Normalize(cur_seam->nor); - Crossf(cur_seam->tan,cur_seam->dir,cur_seam->nor); + // Crossf(cur_seam->tan,cur_seam->dir,cur_seam->nor); - Normalize(cur_seam->tan); + // Normalize(cur_seam->tan); - cur_seam++; - } - } - } - - } + // cur_seam++; + // } + // } + // } + // + //} } else{ /* no need to figure out distribution */ @@ -1064,10 +1040,6 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive length=VecLength(cpa->fuv); } - cpa->rand[0]=BLI_frand(); - cpa->rand[1]=BLI_frand(); - cpa->rand[2]=BLI_frand(); - cpa->num=-1; } } @@ -1346,7 +1318,6 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive jitlevel= totpart/tot; if(part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */ if(jitlevel<3) jitlevel= 3; - //if(jitlevel>100) jitlevel= 100; } jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit"); @@ -1365,7 +1336,7 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive ctx->tree= tree; ctx->seams= seams; ctx->totseam= totseam; - ctx->psys= psys; + ctx->sim.psys= psys; ctx->index= index; ctx->jit= jit; ctx->jitlevel= jitlevel; @@ -1386,7 +1357,7 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive if(!children || psys->totchild < 10000) totthread= 1; - seed= 31415926 + ctx->psys->seed; + seed= 31415926 + ctx->sim.psys->seed; for(i=0; i<totthread; i++) { threads[i].rng= rng_new(seed); threads[i].tot= totthread; @@ -1395,16 +1366,17 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive return 1; } -static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Object *ob, ParticleSystem *psys, int from) +static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) { + DerivedMesh *finaldm = sim->psmd->dm; ListBase threads; ParticleThread *pthreads; ParticleThreadContext *ctx; int i, totthread; - pthreads= psys_threads_create(scene, ob, psys); + pthreads= psys_threads_create(sim); - if(!psys_threads_init_distribution(pthreads, scene, finaldm, from)) { + if(!psys_threads_init_distribution(pthreads, sim->scene, finaldm, from)) { psys_threads_free(pthreads); return; } @@ -1421,7 +1393,7 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Objec else exec_distribution(&pthreads[0]); - psys_calc_dmcache(ob, finaldm, psys); + psys_calc_dmcache(sim->ob, finaldm, sim->psys); ctx= pthreads[0].ctx; if(ctx->dm != finaldm) @@ -1431,8 +1403,9 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Objec } /* ready for future use, to emit particles without geometry */ -static void distribute_particles_on_shape(Object *ob, ParticleSystem *psys, int from) +static void distribute_particles_on_shape(ParticleSimulationData *sim, int from) { + ParticleSystem *psys = sim->psys; PARTICLE_P; fprintf(stderr,"Shape emission not yet possible!\n"); @@ -1443,22 +1416,22 @@ static void distribute_particles_on_shape(Object *ob, ParticleSystem *psys, int pa->num= -1; } } -static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys, int from) +static void distribute_particles(ParticleSimulationData *sim, int from) { - ParticleSystemModifierData *psmd=0; + PARTICLE_PSMD; int distr_error=0; - psmd=psys_get_modifier(ob,psys); if(psmd){ if(psmd->dm) - distribute_particles_on_dm(psmd->dm, scene, ob, psys, from); + distribute_particles_on_dm(sim, from); else distr_error=1; } else - distribute_particles_on_shape(ob,psys,from); + distribute_particles_on_shape(sim, from); if(distr_error){ + ParticleSystem *psys = sim->psys; PARTICLE_P; fprintf(stderr,"Particle distribution error!\n"); @@ -1472,26 +1445,23 @@ static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys, } /* threaded child particle distribution and path caching */ -ParticleThread *psys_threads_create(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys) +ParticleThread *psys_threads_create(ParticleSimulationData *sim) { ParticleThread *threads; ParticleThreadContext *ctx; int i, totthread; - if(scene->r.mode & R_FIXED_THREADS) - totthread= scene->r.threads; + if(sim->scene->r.mode & R_FIXED_THREADS) + totthread= sim->scene->r.threads; else totthread= BLI_system_thread_count(); threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread"); ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext"); - ctx->scene= scene; - ctx->ob= ob; - ctx->psys= psys; - ctx->psmd= psys_get_modifier(ob, psys); - ctx->dm= ctx->psmd->dm; - ctx->ma= give_current_material(ob, psys->part->omat); + ctx->sim = *sim; + ctx->dm= ctx->sim.psmd->dm; + ctx->ma= give_current_material(sim->ob, sim->psys->part->omat); memset(threads, 0, sizeof(ParticleThread)*totthread); @@ -1523,9 +1493,9 @@ void psys_threads_free(ParticleThread *threads) if(ctx->vg_roughe) MEM_freeN(ctx->vg_roughe); - if(ctx->psys->lattice){ - end_latt_deform(ctx->psys->lattice); - ctx->psys->lattice= NULL; + if(ctx->sim.psys->lattice){ + end_latt_deform(ctx->sim.psys->lattice); + ctx->sim.psys->lattice= NULL; } /* distribution */ @@ -1551,37 +1521,34 @@ void psys_threads_free(ParticleThread *threads) } /* set particle parameters that don't change during particle's life */ -void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p) { - ParticleSettings *part; + ParticleSettings *part = sim->psys->part; ParticleTexture ptex; Material *ma=0; //IpoCurve *icu=0; // XXX old animation system int totpart; - float rand; - - part=psys->part; - totpart=psys->totpart; + totpart=sim->psys->totpart; ptex.life=ptex.size=ptex.exist=ptex.length=1.0; ptex.time=(float)p/(float)totpart; - BLI_srandom(psys->seed+p); + BLI_srandom(sim->psys->seed + p + 125); if(part->from!=PART_FROM_PARTICLE && part->type!=PART_FLUID){ - ma=give_current_material(ob,part->omat); + ma=give_current_material(sim->ob,part->omat); /* TODO: needs some work to make most blendtypes generally usefull */ - psys_get_texture(ob,ma,psmd,psys,pa,&ptex,MAP_PA_INIT); + psys_get_texture(sim,ma,pa,&ptex,MAP_PA_INIT); } pa->lifetime= part->lifetime*ptex.life; if(part->type==PART_HAIR) pa->time= 0.0f; - else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0) - pa->time= 300000.0f; /* max frame */ + //else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0) + // pa->time= 300000.0f; /* max frame */ else{ //icu=find_ipocurve(psys->part->ipo,PART_EMIT_TIME); //if(icu){ @@ -1605,10 +1572,8 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps } #endif // XXX old animation system - /* need to get every rand even if we don't use them so that randoms don't affect each other */ - rand= BLI_frand(); if(part->randlife!=0.0) - pa->lifetime*= 1.0f - part->randlife*rand; + pa->lifetime*= 1.0f - part->randlife * BLI_frand(); } pa->dietime= pa->time+pa->lifetime; @@ -1625,13 +1590,14 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps /* usage other than straight after distribute has to handle this index by itself - jahka*/ //pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we dont have a derived mesh face */ } -static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +static void initialize_all_particles(ParticleSimulationData *sim) { //IpoCurve *icu=0; // XXX old animation system + ParticleSystem *psys = sim->psys; PARTICLE_P; LOOP_PARTICLES - initialize_particle(pa,p,ob,psys,psmd); + initialize_particle(sim, pa, p); if(psys->part->type != PART_FLUID) { #if 0 // XXX old animation system @@ -1688,66 +1654,51 @@ static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleS } } /* sets particle to the emitter surface with initial velocity & rotation */ -void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, ParticleSystemModifierData *psmd, Object *ob, - float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot) +void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra) { + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; ParticleSettings *part; ParticleTexture ptex; ParticleKey state; //IpoCurve *icu=0; // XXX old animation system - float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; + float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0}; float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; - float q_phase[4], length, r_phase; + float q_phase[4], r_phase; + int p = pa - psys->particles; part=psys->part; ptex.ivel=1.0; - BLI_srandom(psys->seed + (pa - psys->particles)); - /* we need to get every random even if they're not used so that they don't effect eachother */ - /* while loops are to have a spherical distribution (avoid cubic distribution) */ - length=2.0f; - while(length>1.0){ - r_vel[0]=2.0f*(BLI_frand()-0.5f); - r_vel[1]=2.0f*(BLI_frand()-0.5f); - r_vel[2]=2.0f*(BLI_frand()-0.5f); - length=VecLength(r_vel); - } - - length=2.0f; - while(length>1.0){ - r_ave[0]=2.0f*(BLI_frand()-0.5f); - r_ave[1]=2.0f*(BLI_frand()-0.5f); - r_ave[2]=2.0f*(BLI_frand()-0.5f); - length=VecLength(r_ave); - } - - r_rot[0]=2.0f*(BLI_frand()-0.5f); - r_rot[1]=2.0f*(BLI_frand()-0.5f); - r_rot[2]=2.0f*(BLI_frand()-0.5f); - r_rot[3]=2.0f*(BLI_frand()-0.5f); - + r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f); + r_vel[1] = 2.0f * (PSYS_FRAND(p + 11) - 0.5f); + r_vel[2] = 2.0f * (PSYS_FRAND(p + 12) - 0.5f); + + r_ave[0] = 2.0f * (PSYS_FRAND(p + 13) - 0.5f); + r_ave[1] = 2.0f * (PSYS_FRAND(p + 14) - 0.5f); + r_ave[2] = 2.0f * (PSYS_FRAND(p + 15) - 0.5f); + + r_rot[0] = 2.0f * (PSYS_FRAND(p + 16) - 0.5f); + r_rot[1] = 2.0f * (PSYS_FRAND(p + 17) - 0.5f); + r_rot[2] = 2.0f * (PSYS_FRAND(p + 18) - 0.5f); + r_rot[3] = 2.0f * (PSYS_FRAND(p + 19) - 0.5f); NormalQuat(r_rot); - r_phase = BLI_frand(); + r_phase = PSYS_FRAND(p + 20); if(part->from==PART_FROM_PARTICLE){ - Object *tob; - ParticleSystem *tpsys=0; + ParticleSimulationData tsim = {sim->scene, psys->target_ob ? psys->target_ob : ob, NULL, NULL}; float speed; - tob=psys->target_ob; - if(tob==0) - tob=ob; - - tpsys=BLI_findlink(&tob->particlesystem, psys->target_psys-1); + tsim.psys = BLI_findlink(&tsim.ob->particlesystem, sim->psys->target_psys-1); state.time = pa->time; if(pa->num == -1) memset(&state, 0, sizeof(state)); else - psys_get_particle_state(scene, tob,tpsys,pa->num,&state,1); + psys_get_particle_state(&tsim, pa->num, &state, 1); psys_get_from_key(&state, loc, nor, rot, 0); QuatMulVecf(rot, vtan); @@ -1764,23 +1715,20 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic } else{ /* get precise emitter matrix if particle is born */ - if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= psys->cfra) - where_is_object_time(scene, ob,pa->time); + if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) + where_is_object_time(sim->scene, sim->ob, pa->time); /* get birth location from object */ if(part->tanfac!=0.0) - psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); else - psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); - - /* save local coordinates for later */ - VECCOPY(tloc,loc); + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); /* get possible textural influence */ - psys_get_texture(ob,give_current_material(ob,part->omat),psmd,psys,pa,&ptex,MAP_PA_IVEL); + psys_get_texture(sim, give_current_material(sim->ob,part->omat), pa, &ptex, MAP_PA_IVEL); - if(vg_vel && pa->num != -1) - ptex.ivel*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_vel); + //if(vg_vel && pa->num != -1) + // ptex.ivel*=psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_vel); /* particles live in global space so */ /* let's convert: */ @@ -1788,21 +1736,18 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic Mat4MulVecfl(ob->obmat,loc); /* -normal */ - VECADD(nor,tloc,nor); - Mat4MulVecfl(ob->obmat,nor); - VECSUB(nor,nor,loc); + Mat4Mul3Vecfl(ob->obmat,nor); Normalize(nor); /* -tangent */ if(part->tanfac!=0.0){ - float phase=vg_rot?2.0f*(psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; + //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; + float phase=0.0f; VecMulf(vtan,-(float)cos(M_PI*(part->tanphase+phase))); fac=-(float)sin(M_PI*(part->tanphase+phase)); VECADDFAC(vtan,vtan,utan,fac); - VECADD(vtan,tloc,vtan); - Mat4MulVecfl(ob->obmat,vtan); - VECSUB(vtan,vtan,loc); + Mat4Mul3Vecfl(ob->obmat,vtan); VECCOPY(utan,nor); VecMulf(utan,Inpf(vtan,nor)); @@ -1854,11 +1799,6 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic if(part->acc[2]!=0.0f) bpa->gravity[2] = part->acc[2]; - //pa->r_ve[0] = pa->r_ve[1] = 0.0f; - //pa->r_ve[2] = -1.0f; - //if(part->acc[2]!=0.0f) - // pa->r_ve[2] = part->acc[2]; - /* calculate rotation matrix */ Projf(dvec, r_vel, pa->state.ave); VecSubf(mat[0], pa->state.ave, dvec); @@ -1897,8 +1837,9 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic VECADDFAC(vel,vel,nor,part->normfac); /* *emitter tangent */ - if(psmd && part->tanfac!=0.0) - VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_tan):1.0f)); + if(sim->psmd && part->tanfac!=0.0) + VECADDFAC(vel,vel,vtan,part->tanfac); + //VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_tan):1.0f)); /* *texture */ /* TODO */ @@ -1918,9 +1859,6 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic //} VecMulf(vel,ptex.ivel); - - //if(ELEM(part->phystype, PART_PHYS_GRADU_EX, PART_PHYS_GRADU_SIM)) - // VecAddf(vel,vel,part->acc); VECCOPY(pa->state.vel,vel); @@ -2002,22 +1940,20 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic pa->alive = PARS_UNBORN; pa->state.time = cfra; - -// pa->flag &= ~PARS_STICKY; } -static void reset_all_particles(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from) +static void reset_all_particles(ParticleSimulationData *sim, float dtime, float cfra, int from) { ParticleData *pa; - int p, totpart=psys->totpart; - float *vg_vel=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_VEL); - float *vg_tan=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_TAN); - float *vg_rot=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT); + int p, totpart=sim->psys->totpart; + //float *vg_vel=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_VEL); + //float *vg_tan=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_TAN); + //float *vg_rot=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_ROT); - for(p=from, pa=psys->particles+from; p<totpart; p++, pa++) - reset_particle(scene, pa, psys, psmd, ob, dtime, cfra, vg_vel, vg_tan, vg_rot); + for(p=from, pa=sim->psys->particles+from; p<totpart; p++, pa++) + reset_particle(sim, pa, dtime, cfra); - if(vg_vel) - MEM_freeN(vg_vel); + //if(vg_vel) + // MEM_freeN(vg_vel); } /************************************************/ /* Particle targets */ @@ -2042,15 +1978,15 @@ ParticleSystem *psys_get_target_system(Object *ob, ParticleTarget *pt) /* Keyed particles */ /************************************************/ /* Counts valid keyed targets */ -void psys_count_keyed_targets(Object *ob, ParticleSystem *psys) +void psys_count_keyed_targets(ParticleSimulationData *sim) { - ParticleSystem *kpsys; + ParticleSystem *psys = sim->psys, *kpsys; ParticleTarget *pt = psys->targets.first; int keys_valid = 1; psys->totkeyed = 0; for(; pt; pt=pt->next) { - kpsys = psys_get_target_system(ob, pt); + kpsys = psys_get_target_system(sim->ob, pt); if(kpsys && kpsys->totpart) { psys->totkeyed += keys_valid; @@ -2065,9 +2001,10 @@ void psys_count_keyed_targets(Object *ob, ParticleSystem *psys) psys->totkeyed *= psys->flag & PSYS_KEYED_TIMING ? 1 : psys->part->keyed_loops; } -static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) +static void set_keyed_keys(ParticleSimulationData *sim) { - ParticleSystem *kpsys = psys; + ParticleSystem *psys = sim->psys; + ParticleSimulationData ksim = {sim->scene, NULL, NULL, NULL}; ParticleTarget *pt; PARTICLE_P; ParticleKey *key; @@ -2097,16 +2034,14 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) pt = psys->targets.first; for(k=0; k<totkeys; k++) { - if(pt->ob) - kpsys = BLI_findlink(&pt->ob->particlesystem, pt->psys - 1); - else - kpsys = BLI_findlink(&ob->particlesystem, pt->psys - 1); + ksim.ob = pt->ob ? pt->ob : sim->ob; + ksim.psys = BLI_findlink(&ksim.ob->particlesystem, pt->psys - 1); LOOP_PARTICLES { key = pa->keys + k; key->time = -1.0; /* use current time */ - psys_get_particle_state(scene, pt->ob, kpsys, p%kpsys->totpart, key, 1); + psys_get_particle_state(&ksim, p%ksim.psys->totpart, key, 1); if(psys->flag & PSYS_KEYED_TIMING){ key->time = pa->time + pt->time; @@ -2132,111 +2067,109 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) /************************************************/ /* Reactors */ /************************************************/ -static void push_reaction(Object* ob, ParticleSystem *psys, int pa_num, int event, ParticleKey *state) -{ - Object *rob; - ParticleSystem *rpsys; - ParticleSettings *rpart; - ParticleData *pa; - ListBase *lb=&psys->effectors; - ParticleEffectorCache *ec; - ParticleReactEvent *re; - - if(lb->first) for(ec = lb->first; ec; ec= ec->next){ - if(ec->type & PSYS_EC_REACTOR){ - /* all validity checks already done in add_to_effectors */ - rob=ec->ob; - rpsys=BLI_findlink(&rob->particlesystem,ec->psys_nbr); - rpart=rpsys->part; - if(rpsys->part->reactevent==event){ - pa=psys->particles+pa_num; - re= MEM_callocN(sizeof(ParticleReactEvent), "react event"); - re->event=event; - re->pa_num = pa_num; - re->ob = ob; - re->psys = psys; - re->size = pa->size; - copy_particle_key(&re->state,state,1); - - switch(event){ - case PART_EVENT_DEATH: - re->time=pa->dietime; - break; - case PART_EVENT_COLLIDE: - re->time=state->time; - break; - case PART_EVENT_NEAR: - re->time=state->time; - break; - } - - BLI_addtail(&rpsys->reactevents, re); - } - } - } -} -static void react_to_events(ParticleSystem *psys, int pa_num) -{ - ParticleSettings *part=psys->part; - ParticleData *pa=psys->particles+pa_num; - ParticleReactEvent *re=psys->reactevents.first; - int birth=0; - float dist=0.0f; - - for(re=psys->reactevents.first; re; re=re->next){ - birth=0; - if(part->from==PART_FROM_PARTICLE){ - if(pa->num==re->pa_num && pa->alive==PARS_UNBORN){ - if(re->event==PART_EVENT_NEAR){ - ParticleData *tpa = re->psys->particles+re->pa_num; - float pa_time=tpa->time + pa->foffset*tpa->lifetime; - if(re->time >= pa_time){ - pa->time=pa_time; - pa->dietime=pa->time+pa->lifetime; - } - } - else{ - pa->time=re->time; - pa->dietime=pa->time+pa->lifetime; - } - } - } - else{ - dist=VecLenf(pa->state.co, re->state.co); - if(dist <= re->size){ - if(pa->alive==PARS_UNBORN){ - pa->time=re->time; - pa->dietime=pa->time+pa->lifetime; - birth=1; - } - if(birth || part->flag&PART_REACT_MULTIPLE){ - float vec[3]; - VECSUB(vec,pa->state.co, re->state.co); - if(birth==0) - VecMulf(vec,(float)pow(1.0f-dist/re->size,part->reactshape)); - VECADDFAC(pa->state.vel,pa->state.vel,vec,part->reactfac); - VECADDFAC(pa->state.vel,pa->state.vel,re->state.vel,part->partfac); - } - if(birth) - VecMulf(pa->state.vel,(float)pow(1.0f-dist/re->size,part->reactshape)); - } - } - } -} -void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_ob, ParticleSystem **target_psys) -{ - Object *tob; - - tob=psys->target_ob; - if(tob==0) - tob=ob; - - *target_psys=BLI_findlink(&tob->particlesystem,psys->target_psys-1); - if(*target_psys) - *target_ob=tob; - else - *target_ob=0; -} +//static void push_reaction(ParticleSimulationData *sim, int pa_num, int event, ParticleKey *state) +//{ +// Object *rob; +// ParticleSystem *rpsys; +// ParticleSettings *rpart; +// ParticleData *pa; +// ListBase *lb=&sim->psys->effectors; +// ParticleEffectorCache *ec; +// ParticleReactEvent *re; +// +// if(lb->first) for(ec = lb->first; ec; ec= ec->next){ +// if(ec->type & PSYS_EC_REACTOR){ +// /* all validity checks already done in add_to_effectors */ +// rob=ec->ob; +// rpsys=BLI_findlink(&rob->particlesystem,ec->psys_nbr); +// rpart=rpsys->part; +// if(rpsys->part->reactevent==event){ +// pa=sim->psys->particles+pa_num; +// re= MEM_callocN(sizeof(ParticleReactEvent), "react event"); +// re->event=event; +// re->pa_num = pa_num; +// re->ob = sim->ob; +// re->psys = sim->psys; +// re->size = pa->size; +// copy_particle_key(&re->state,state,1); +// +// switch(event){ +// case PART_EVENT_DEATH: +// re->time=pa->dietime; +// break; +// case PART_EVENT_COLLIDE: +// re->time=state->time; +// break; +// case PART_EVENT_NEAR: +// re->time=state->time; +// break; +// } +// +// BLI_addtail(&rpsys->reactevents, re); +// } +// } +// } +//} +//static void react_to_events(ParticleSystem *psys, int pa_num) +//{ +// ParticleSettings *part=psys->part; +// ParticleData *pa=psys->particles+pa_num; +// ParticleReactEvent *re=psys->reactevents.first; +// int birth=0; +// float dist=0.0f; +// +// for(re=psys->reactevents.first; re; re=re->next){ +// birth=0; +// if(part->from==PART_FROM_PARTICLE){ +// if(pa->num==re->pa_num && pa->alive==PARS_UNBORN){ +// if(re->event==PART_EVENT_NEAR){ +// ParticleData *tpa = re->psys->particles+re->pa_num; +// float pa_time=tpa->time + pa->foffset*tpa->lifetime; +// if(re->time >= pa_time){ +// pa->time=pa_time; +// pa->dietime=pa->time+pa->lifetime; +// } +// } +// else{ +// pa->time=re->time; +// pa->dietime=pa->time+pa->lifetime; +// } +// } +// } +// else{ +// dist=VecLenf(pa->state.co, re->state.co); +// if(dist <= re->size){ +// if(pa->alive==PARS_UNBORN){ +// pa->time=re->time; +// pa->dietime=pa->time+pa->lifetime; +// birth=1; +// } +// if(birth || part->flag&PART_REACT_MULTIPLE){ +// float vec[3]; +// VECSUB(vec,pa->state.co, re->state.co); +// if(birth==0) +// VecMulf(vec,(float)pow(1.0f-dist/re->size,part->reactshape)); +// VECADDFAC(pa->state.vel,pa->state.vel,vec,part->reactfac); +// VECADDFAC(pa->state.vel,pa->state.vel,re->state.vel,part->partfac); +// } +// if(birth) +// VecMulf(pa->state.vel,(float)pow(1.0f-dist/re->size,part->reactshape)); +// } +// } +// } +//} +//void psys_get_reactor_target(ParticleSimulationData *sim, Object **target_ob, ParticleSystem **target_psys) +//{ +// Object *tob; +// +// tob = sim->psys->target_ob ? sim->psys->target_ob : sim->ob; +// +// *target_psys = BLI_findlink(&tob->particlesystem, sim->psys->target_psys-1); +// if(*target_psys) +// *target_ob=tob; +// else +// *target_ob=0; +//} /************************************************/ /* Point Cache */ /************************************************/ @@ -2252,7 +2185,7 @@ void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys) BKE_ptcache_disk_to_mem(&pid); } -void psys_clear_temp_pointcache(ParticleSystem *psys) +static void psys_clear_temp_pointcache(ParticleSystem *psys) { if((psys->pointcache->flag & PTCACHE_DISK_CACHE)==0) return; @@ -2281,11 +2214,9 @@ static void update_particle_tree(ParticleSystem *psys) psys->tree = BLI_kdtree_new(psys->totpart); - LOOP_PARTICLES { - if(pa->flag & (PARS_NO_DISP+PARS_UNEXIST) || pa->alive != PARS_ALIVE) - continue; - - BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL); + LOOP_SHOWN_PARTICLES { + if(pa->alive == PARS_ALIVE) + BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL); } BLI_kdtree_balance(psys->tree); @@ -2302,7 +2233,7 @@ static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla, result[0].nor = result[1].nor = result[2].nor = result[3].nor = 0; - strength= force_val*falloff;///(float)pow((double)distance,(double)power); + strength= force_val*falloff; VECCOPY(tex_co,pa_co); @@ -2365,19 +2296,19 @@ static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla, VecAddf(field,field,mag_vec); } -static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obsrc, ParticleSystem *psys) +static void add_to_effectors(ParticleSimulationData *sim, ListBase *lb, Object *ob) { ParticleEffectorCache *ec; PartDeflect *pd= ob->pd; short type=0,i; - if(pd && ob != obsrc){ + if(pd && ob != sim->ob){ if(pd->forcefield == PFIELD_GUIDE) { if(ob->type==OB_CURVE) { Curve *cu= ob->data; if(cu->flag & CU_PATH) { if(cu->path==NULL || cu->path->data==NULL) - makeDispListCurveTypes(scene, ob, 0); + makeDispListCurveTypes(sim->scene, ob, 0); if(cu->path && cu->path->data) { type |= PSYS_EC_EFFECTOR; } @@ -2411,13 +2342,13 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs if(ob->particlesystem.first){ ParticleSystem *epsys=ob->particlesystem.first; ParticleSettings *epart=0; - Object *tob; + //Object *tob; for(i=0; epsys; epsys=epsys->next,i++){ if(!psys_check_enabled(ob, epsys)) continue; type=0; - if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){ + if(epsys!=sim->psys || (sim->psys->part->flag & PART_SELF_EFFECT)){ epart=epsys->part; if((epsys->part->pd && epsys->part->pd->forcefield) @@ -2426,13 +2357,13 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs type=PSYS_EC_PARTICLE; } - if(epart->type==PART_REACTOR) { - tob=epsys->target_ob; - if(tob==0) - tob=ob; - if(BLI_findlink(&tob->particlesystem,epsys->target_psys-1)==psys) - type|=PSYS_EC_REACTOR; - } + //if(epart->type==PART_REACTOR) { + // tob=epsys->target_ob; + // if(tob==0) + // tob=ob; + // if(BLI_findlink(&tob->particlesystem,epsys->target_psys-1)==sim->psys) + // type|=PSYS_EC_REACTOR; + //} if(type){ ec= MEM_callocN(sizeof(ParticleEffectorCache), "effector cache"); @@ -2450,29 +2381,29 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs } } -static void psys_init_effectors_recurs(Scene *scene, Object *ob, Object *obsrc, ParticleSystem *psys, ListBase *listb, int level) +static void psys_init_effectors_recurs(ParticleSimulationData *sim, Object *ob, ListBase *listb, int level) { Group *group; GroupObject *go; - unsigned int layer= obsrc->lay; + unsigned int layer= sim->ob->lay; if(level>MAX_DUPLI_RECUR) return; if(ob->lay & layer) { if(ob->pd || ob->particlesystem.first) - add_to_effectors(listb, scene, ob, obsrc, psys); + add_to_effectors(sim, listb, ob); if(ob->dup_group) { group= ob->dup_group; for(go= group->gobject.first; go; go= go->next) - psys_init_effectors_recurs(scene, go->ob, obsrc, psys, listb, level+1); + psys_init_effectors_recurs(sim, go->ob, listb, level+1); } } } -void psys_init_effectors(Scene *scene, Object *obsrc, Group *group, ParticleSystem *psys) +static void psys_init_effectors(ParticleSimulationData *sim, Group *group) { - ListBase *listb= &psys->effectors; + ListBase *listb= &sim->psys->effectors; Base *base; listb->first=listb->last=0; @@ -2481,11 +2412,11 @@ void psys_init_effectors(Scene *scene, Object *obsrc, Group *group, ParticleSyst GroupObject *go; for(go= group->gobject.first; go; go= go->next) - psys_init_effectors_recurs(scene, go->ob, obsrc, psys, listb, 0); + psys_init_effectors_recurs(sim, go->ob, listb, 0); } else { - for(base = scene->base.first; base; base= base->next) - psys_init_effectors_recurs(scene, base->object, obsrc, psys, listb, 0); + for(base = sim->scene->base.first; base; base= base->next) + psys_init_effectors_recurs(sim, base->object, listb, 0); } } @@ -2519,13 +2450,16 @@ void psys_end_effectors(ParticleSystem *psys) BLI_freelistN(&psys->effectors); } -static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) +/* precalcs effectors and returns 1 if there were any collision object + * so collision checks can be avoided as quickly as possible */ +static int precalc_effectors(ParticleSimulationData *sim, float cfra) { + ParticleSystem *psys = sim->psys; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; ParticleSettings *part=psys->part; PARTICLE_P; - int totpart; + int totpart, collision = 0; float vec2[3],loc[3],radius,*co=0; for(ec= lb->first; ec; ec= ec->next) { @@ -2557,9 +2491,9 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa VECCOPY(loc, pa->fuv); } else - psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0); + psys_particle_on_emitter(sim->psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0); - Mat4MulVecfl(ob->obmat,loc); + Mat4MulVecfl(sim->ob->obmat,loc); ec->distances[p]=VecLenf(loc,vec); VECSUB(loc,loc,vec); VECCOPY(ec->locations+3*p,loc); @@ -2567,11 +2501,10 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa } } else if(ec->type==PSYS_EC_PARTICLE){ - Object *eob = ec->ob; - ParticleSystem *epsys = BLI_findlink(&eob->particlesystem,ec->psys_nbr); - ParticleSettings *epart = epsys->part; + ParticleSimulationData esim = {sim->scene, ec->ob, BLI_findlink(&ec->ob->particlesystem, ec->psys_nbr), NULL}; + ParticleSettings *epart = esim.psys->part; ParticleData *epa; - int p, totepart = epsys->totpart; + int p, totepart = esim.psys->totpart; if(psys->part->phystype==PART_PHYS_BOIDS){ ParticleKey state; @@ -2584,8 +2517,8 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa tree=BLI_kdtree_new(totepart); ec->tree=tree; - for(p=0, epa=epsys->particles; p<totepart; p++,epa++) - if(epa->alive==PARS_ALIVE && psys_get_particle_state(scene, eob,epsys,p,&state,0)) + for(p=0, epa=esim.psys->particles; p<totepart; p++,epa++) + if(epa->alive==PARS_ALIVE && psys_get_particle_state(&esim,p,&state,0)) BLI_kdtree_insert(tree, p, state.co, NULL); BLI_kdtree_balance(tree); @@ -2595,12 +2528,23 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa } else if(ec->type==PSYS_EC_DEFLECT) { CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); - if(collmd) + if(collmd) { collision_move_object(collmd, 1.0, 0.0); + collision = 1; + } } } + + return collision; } +/* updates particle effectors and returns if any collision objects were found */ +int psys_update_effectors(ParticleSimulationData *sim, float cfra, int precalc) +{ + psys_end_effectors(sim->psys); + psys_init_effectors(sim, sim->psys->part->eff_group); + return (precalc ? precalc_effectors(sim, cfra) : 0); +} int effector_find_co(Scene *scene, float *pco, SurfaceModifierData *sur, Object *ob, PartDeflect *pd, float *co, float *nor, float *vel, int *index) { SurfaceModifierData *surmd = NULL; @@ -2680,10 +2624,10 @@ int effector_find_co(Scene *scene, float *pco, SurfaceModifierData *sur, Object return ret; } /* calculate forces that all effectors apply to a particle*/ -void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, Object *ob, ParticleSystem *psys, float *rootco, float *force_field, float *vel,float framestep, float cfra) +void do_effectors(ParticleSimulationData *sim, int pa_no, ParticleData *pa, ParticleKey *state, float *rootco, float *force_field, float *vel,float framestep, float cfra) { Object *eob; - ParticleSystem *epsys; + ParticleSystem *psys = sim->psys; ParticleSettings *epart; ParticleData *epa; ParticleKey estate; @@ -2713,19 +2657,19 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, if(ec->type & PSYS_EC_EFFECTOR){ pd=eob->pd; if(psys->part->type!=PART_HAIR && psys->part->integrator) - where_is_object_time(scene, eob,cfra); + where_is_object_time(sim->scene, eob, cfra); if(pd && pd->flag&PFIELD_SURFACE) { float velocity[3]; /* using velocity corrected location allows for easier sliding over effector surface */ VecCopyf(velocity, state->vel); - VecMulf(velocity, psys_get_timestep(psys->part)); + VecMulf(velocity, psys_get_timestep(sim)); VecAddf(pco, state->co, velocity); } else VECCOPY(pco, state->co); - effector_find_co(scene, pco, NULL, eob, pd, co, NULL, NULL, &face_index); + effector_find_co(sim->scene, pco, NULL, eob, pd, co, NULL, NULL, &face_index); VecSubf(vec_to_part, state->co, co); @@ -2742,68 +2686,69 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, pd->flag & PFIELD_TEX_OBJECT, (pd->flag & PFIELD_TEX_ROOTCO) ? rootco : state->co, eob->obmat, strength, falloff, force_field); } else { - do_physical_effector(scene, eob, state->co, pd->forcefield,strength,distance, + do_physical_effector(sim->scene, eob, state->co, pd->forcefield,strength,distance, falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part, state->vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size); } } if(ec->type & PSYS_EC_PARTICLE){ + ParticleSimulationData esim = {sim->scene, eob, BLI_findlink(&eob->particlesystem,ec->psys_nbr), NULL}; int totepart, i; - epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr); - epart= epsys->part; - pd=epart->pd; - totepart= epsys->totpart; + + epart = esim.psys->part; + pd = epart->pd; + totepart = esim.psys->totpart; if(totepart <= 0) continue; if(pd && pd->forcefield==PFIELD_HARMONIC){ /* every particle is mapped to only one harmonic effector particle */ - p= pa_no%epsys->totpart; + p= pa_no%esim.psys->totpart; totepart= p+1; } else{ p=0; } - epsys->lattice= psys_get_lattice(scene, ob, psys); + esim.psys->lattice= psys_get_lattice(sim); for(; p<totepart; p++){ /* particle skips itself as effector */ - if(epsys==psys && p == pa_no) continue; + if(esim.psys == psys && p == pa_no) continue; - epa = epsys->particles + p; - estate.time=cfra; - if(psys_get_particle_state(scene, eob,epsys,p,&estate,0)){ + epa = esim.psys->particles + p; + estate.time = cfra; + if(psys_get_particle_state(&esim, p, &estate, 0)){ VECSUB(vec_to_part, state->co, estate.co); distance = VecLength(vec_to_part); for(i=0, pd = epart->pd; i<2; i++,pd = epart->pd2) { if(pd==NULL || pd->forcefield==0) continue; - falloff=effector_falloff(pd,estate.vel,vec_to_part); + falloff = effector_falloff(pd, estate.vel, vec_to_part); strength = pd->f_strength * psys->part->effector_weight[0] * psys->part->effector_weight[pd->forcefield]; if(falloff<=0.0f) ; /* don't do anything */ else - do_physical_effector(scene, eob, state->co, pd->forcefield,strength,distance, + do_physical_effector(sim->scene, eob, state->co, pd->forcefield,strength,distance, falloff,epart->size,pd->f_damp,estate.vel,vec_to_part, state->vel,force_field,0, ec->rng, pd->f_noise,charge,pa->size); } } else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ /* first step after key release */ - psys_get_particle_state(scene, eob,epsys,p,&estate,1); - VECADD(vel,vel,estate.vel); + psys_get_particle_state(&esim, p, &estate, 1); + VECADD(vel, vel, estate.vel); /* TODO: add rotation handling here too */ } } - if(epsys->lattice){ - end_latt_deform(epsys->lattice); - epsys->lattice= NULL; + if(esim.psys->lattice){ + end_latt_deform(esim.psys->lattice); + esim.psys->lattice= NULL; } } } @@ -2814,11 +2759,14 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, /* Newtonian physics */ /************************************************/ /* gathers all forces that effect particles and calculates a new state for the particle */ -static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra) +static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra, float cfra) { + ParticleSettings *part = sim->psys->part; + ParticleData *pa = sim->psys->particles + p; ParticleKey states[5], tkey; + float timestep = psys_get_timestep(sim); float force[3],tvel[3],dx[4][3],dv[4][3]; - float dtime=dfra*timestep, time, pa_mass=part->mass, fac, fra=psys->cfra; + float dtime=dfra*timestep, time, pa_mass=part->mass, fac, fra=sim->psys->cfra; int i, steps=1; /* maintain angular velocity */ @@ -2846,7 +2794,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj tvel[0]=tvel[1]=tvel[2]=0.0; /* add effectors */ if(part->type != PART_HAIR) - do_effectors(pa_no,pa,states+i,scene, ob, psys,states->co,force,tvel,dfra,fra); + do_effectors(sim, p, pa, states+i, states->co, force, tvel, dfra, fra); /* calculate air-particle interaction */ if(part->dragfac!=0.0f){ @@ -2879,7 +2827,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj if(i==0){ VECADDFAC(states[1].co,states->co,states->vel,dtime*0.5f); VECADDFAC(states[1].vel,states->vel,force,dtime*0.5f); - fra=psys->cfra+0.5f*dfra; + fra=sim->psys->cfra+0.5f*dfra; } else{ VECADDFAC(pa->state.co,states->co,states[1].vel,dtime); @@ -2896,7 +2844,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj VECADDFAC(states[1].co,states->co,dx[0],0.5f); VECADDFAC(states[1].vel,states->vel,dv[0],0.5f); - fra=psys->cfra+0.5f*dfra; + fra=sim->psys->cfra+0.5f*dfra; break; case 1: VECADDFAC(dx[1],states->vel,dv[0],0.5f); @@ -2950,7 +2898,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj tkey.time=pa->state.time; if(part->type != PART_HAIR) { - if(do_guide(scene, &tkey, pa_no, time, &psys->effectors)) { + if(do_guide(sim->scene, &tkey, p, time, &sim->psys->effectors)) { VECCOPY(pa->state.co,tkey.co); /* guides don't produce valid velocity */ VECSUB(pa->state.vel,tkey.co,pa->prev_state.co); @@ -3214,15 +3162,18 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B /* angular momentum <-> linear momentum and swept sphere - mesh collisions */ /* 1. check for all possible deflectors for closest intersection on particle path */ /* 2. if deflection was found kill the particle or calculate new coordinates */ -static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra){ +static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, float cfra){ Object *ob = NULL, *skip_ob = NULL; - ListBase *lb=&psys->effectors; + ParticleSettings *part = sim->psys->part; + ListBase *lb=&sim->psys->effectors; ParticleEffectorCache *ec; ParticleKey reaction_state; ParticleCollision col; + ParticleData *pa = sim->psys->particles + p; BVHTreeRayHit hit; float ray_dir[3], zerovec[3]={0.0,0.0,0.0}; float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f), boid_z = 0.0f; + float timestep = psys_get_timestep(sim); int deflections=0, max_deflections=10; VECCOPY(col.co1, pa->prev_state.co); @@ -3259,11 +3210,11 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa continue; /* particles should not collide with emitter at birth */ - if(ob==pob && pa->time < cfra && pa->time >= psys->cfra) + if(ob==sim->ob && pa->time < cfra && pa->time >= sim->psys->cfra) continue; if(part->type!=PART_HAIR) - where_is_object_time(scene,ob,cfra); + where_is_object_time(sim->scene, sim->ob, cfra); col.md = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); col.ob_t = ob; @@ -3400,9 +3351,9 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa } /* store state for reactors */ - VECCOPY(reaction_state.co, co); - VecLerpf(reaction_state.vel, pa->prev_state.vel, pa->state.vel, dt); - QuatInterpol(reaction_state.rot, pa->prev_state.rot, pa->state.rot, dt); + //VECCOPY(reaction_state.co, co); + //VecLerpf(reaction_state.vel, pa->prev_state.vel, pa->state.vel, dt); + //QuatInterpol(reaction_state.rot, pa->prev_state.rot, pa->state.rot, dt); /* set coordinates for next iteration */ VECCOPY(col.co1, co); @@ -3424,8 +3375,8 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa } deflections++; - reaction_state.time = cfra - (1.0f - dt) * dfra; - push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); + //reaction_state.time = cfra - (1.0f - dt) * dfra; + //push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); } else return; @@ -3435,29 +3386,30 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa /* Hair */ /************************************************/ /* check if path cache or children need updating and do it if needed */ -static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void psys_update_path_cache(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part=psys->part; - ParticleEditSettings *pset=&scene->toolsettings->particle; - int distr=0,alloc=0,skip=0; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + ParticleEditSettings *pset = &sim->scene->toolsettings->particle; + int distr=0, alloc=0, skip=0; - if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET) + if((psys->part->childtype && psys->totchild != get_psys_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET) alloc=1; - if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))) + if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT))) distr=1; if(distr){ if(alloc) - realloc_particles(ob,psys,psys->totpart); + realloc_particles(sim, sim->psys->totpart); - if(get_psys_tot_child(scene, psys)) { + if(get_psys_tot_child(sim->scene, psys)) { /* don't generate children while computing the hair keys */ if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { - distribute_particles(scene, ob, psys, PART_FROM_CHILD); + distribute_particles(sim, PART_FROM_CHILD); if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0) - psys_find_parents(ob,psmd,psys); + psys_find_parents(sim); } } } @@ -3471,7 +3423,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif skip = 1; /* draw visualization */ else if(psys->pointcache->flag & PTCACHE_BAKING) skip = 1; /* no need to cache paths while baking dynamics */ - else if(psys_in_edit_mode(scene, psys)) { + else if(psys_in_edit_mode(sim->scene, psys)) { if((pset->flag & PE_DRAW_PART)==0) skip = 1; else if(part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0) @@ -3480,7 +3432,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif } if(!skip) { - psys_cache_paths(scene, ob, psys, cfra); + psys_cache_paths(sim, cfra); /* for render, child particle paths are computed on the fly */ if(part->childtype) { @@ -3490,15 +3442,16 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif skip = 1; if(!skip) - psys_cache_child_paths(scene, ob, psys, cfra, 0); + psys_cache_child_paths(sim, cfra, 0); } } else if(psys->pathcache) psys_free_path_cache(psys, NULL); } -static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +static void do_hair_dynamics(ParticleSimulationData *sim) { + ParticleSystem *psys = sim->psys; DerivedMesh *dm = psys->hair_in_dm; MVert *mvert = NULL; MEdge *medge = NULL; @@ -3521,7 +3474,8 @@ static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, Par LOOP_PARTICLES totpoint += pa->totkey; - totedge = totpoint - psys->totpart; + totedge = totpoint; + totpoint += psys->totpart; if(dm && (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm))) { dm->release(dm); @@ -3540,14 +3494,39 @@ static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, Par psys->clmd->sim_parms->vgroup_mass = 1; /* make vgroup for pin roots etc.. */ - psys->particles->hair_index = 0; + psys->particles->hair_index = 1; LOOP_PARTICLES { if(p) - pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey; + pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey + 1; - psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_object(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); for(k=0, key=pa->hair; k<pa->totkey; k++,key++) { + + /* create fake root before actual root to resist bending */ + if(k==0) { + float temp[3]; + VECSUB(temp, key->co, (key+1)->co); + VECCOPY(mvert->co, key->co); + VECADD(mvert->co, mvert->co, temp); + Mat4MulVecfl(hairmat, mvert->co); + mvert++; + + medge->v1 = pa->hair_index - 1; + medge->v2 = pa->hair_index; + medge++; + + if(dvert) { + if(!dvert->totweight) { + dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); + dvert->totweight = 1; + } + + dvert->dw->weight = 1.0f; + dvert++; + } + } + VECCOPY(mvert->co, key->co); Mat4MulVecfl(hairmat, mvert->co); mvert++; @@ -3577,18 +3556,19 @@ static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, Par psys->clmd->point_cache = psys->pointcache; - psys->hair_out_dm = clothModifier_do(psys->clmd, scene, ob, dm, 0, 0); + psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, 0, 0); } -static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void hair_step(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part = psys->part; + ParticleSystem *psys = sim->psys; +/* ParticleSettings *part = psys->part; */ PARTICLE_P; float disp = (float)get_current_display_percentage(psys)/100.0f; BLI_srandom(psys->seed); LOOP_PARTICLES { - if(BLI_frand() > disp) + if(PSYS_FRAND(p) > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -3596,36 +3576,33 @@ static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd if(psys->recalc & PSYS_RECALC_RESET) { /* need this for changing subsurf levels */ - psys_calc_dmcache(ob, psmd->dm, psys); + psys_calc_dmcache(sim->ob, sim->psmd->dm, psys); if(psys->clmd) - cloth_free_modifier(ob, psys->clmd); + cloth_free_modifier(sim->ob, psys->clmd); } - if(psys->effectors.first) - psys_end_effectors(psys); - /* dynamics with cloth simulation */ if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) - do_hair_dynamics(scene, ob, psys, psmd); + do_hair_dynamics(sim); - psys_init_effectors(scene, ob, part->eff_group, psys); - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); + psys_update_effectors(sim, cfra, 1); - psys_update_path_cache(scene, ob,psmd,psys,cfra); + psys_update_path_cache(sim, cfra); psys->flag |= PSYS_HAIR_UPDATED; } -static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){ +static void save_hair(ParticleSimulationData *sim, float cfra){ + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; HairKey *key, *root; PARTICLE_P; int totpart; - Mat4Invert(ob->imat,ob->obmat); + Mat4Invert(ob->imat, ob->obmat); - psys->lattice= psys_get_lattice(scene, ob, psys); + psys->lattice= psys_get_lattice(sim); if(psys->totpart==0) return; @@ -3648,7 +3625,7 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy if(pa->totkey) { VECSUB(key->co, key->co, root->co); - psys_vec_rot_to_face(psmd->dm, pa, key->co); + psys_vec_rot_to_face(sim->psmd->dm, pa, key->co); } key->time = pa->state.time; @@ -3666,17 +3643,17 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy /* System Core */ /************************************************/ /* unbaked particles are calculated dynamically */ -static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra, - float *vg_vel, float *vg_tan, float *vg_rot, float *vg_size) +static void dynamics_step(ParticleSimulationData *sim, float cfra) { + ParticleSystem *psys = sim->psys; ParticleSettings *part=psys->part; KDTree *tree=0; IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system - Material *ma=give_current_material(ob,part->omat); +/* Material *ma=give_current_material(sim->ob, part->omat); */ BoidBrainData bbd; PARTICLE_P; float timestep; - int totpart; + int totpart, check_collisions = 0; /* current time */ float ctime, ipotime; // XXX old animation system /* frame & time changes */ @@ -3688,7 +3665,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic totpart=psys->totpart; - timestep=psys_get_timestep(part); + timestep=psys_get_timestep(sim); dtime= dfra*timestep; ctime= cfra*timestep; ipotime= cfra; // XXX old animation system @@ -3702,12 +3679,10 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic if(dfra<0.0){ float *vg_size=0; - if(part->type==PART_REACTOR) - vg_size=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); - - LOOP_PARTICLES { - if(pa->flag & PARS_UNEXIST) continue; + //if(part->type==PART_REACTOR) + // vg_size=psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE); + LOOP_EXISTING_PARTICLES { /* set correct ipo timing */ #if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ @@ -3716,13 +3691,15 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic execute_ipo((ID *)part, part->ipo); } #endif // XXX old animation system - pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + pa->size = part->size; + if(part->randsize > 0.0) + pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); - reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); + reset_particle(sim, pa, dtime, cfra); - if(cfra>pa->time && part->flag & PART_LOOP && part->type!=PART_HAIR){ - pa->loop=(short)((cfra-pa->time)/pa->lifetime); - pa->alive=PARS_UNBORN; + if(cfra > pa->time && part->flag & PART_LOOP && part->type!=PART_HAIR){ + pa->loop = (short)((cfra-pa->time)/pa->lifetime); + pa->alive = PARS_UNBORN; } else{ pa->loop = 0; @@ -3743,21 +3720,12 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } else{ BLI_srandom(31415926 + (int)cfra + psys->seed); - - /* update effectors */ - if(psys->effectors.first) - psys_end_effectors(psys); - psys_init_effectors(scene, ob, part->eff_group, psys); - - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); + psys_update_effectors(sim, cfra, 1); if(part->phystype==PART_PHYS_BOIDS){ ParticleTarget *pt = psys->targets.first; - bbd.scene = scene; - bbd.ob = ob; - bbd.psys = psys; + bbd.sim = sim; bbd.part = part; bbd.cfra = cfra; bbd.dfra = dfra; @@ -3774,9 +3742,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } /* main loop: calculate physics for all particles */ - LOOP_PARTICLES { - if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; - + LOOP_SHOWN_PARTICLES { copy_particle_key(&pa->prev_state,&pa->state,1); /* set correct ipo timing */ @@ -3787,23 +3753,19 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic execute_ipo((ID *)part, part->ipo); } #endif // XXX old animation system - pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + //update_particle_settings(psys, part, &tpart, pa); + + pa->size = part->size; + if(part->randsize > 0.0) + pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); - /* reactions can change birth time so they need to be checked first */ - if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) - react_to_events(psys,p); + ///* reactions can change birth time so they need to be checked first */ + //if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) + // react_to_events(psys,p); birthtime = pa->time + pa->loop * pa->lifetime; dietime = birthtime + pa->lifetime; - /* allways reset particles to emitter before birth */ - if(pa->alive==PARS_UNBORN - || pa->alive==PARS_KILLED - || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) - || birthtime >= psys->cfra){ - reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); - } - pa_dfra = dfra; pa_dtime = dtime; @@ -3816,6 +3778,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } else if(birthtime <= cfra && birthtime >= psys->cfra){ /* particle is born some time between this and last step*/ + reset_particle(sim, pa, dtime, cfra); pa->alive = PARS_ALIVE; pa_dfra = cfra - birthtime; pa_dtime = pa_dfra*timestep; @@ -3824,18 +3787,22 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic /* nothing to be done when particle is dead */ } + /* only reset unborn particles if they're shown */ + if(pa->alive==PARS_UNBORN && part->flag & PART_UNBORN) + reset_particle(sim, pa, dtime, cfra); if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ switch(part->phystype){ case PART_PHYS_NEWTON: /* do global forces & effectors */ - apply_particle_forces(scene, p, pa, ob, psys, part, timestep,pa_dfra,cfra); + apply_particle_forces(sim, p, pa_dfra, cfra); /* deflection */ - deflect_particle(scene, ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra); + if(check_collisions) + deflect_particle(sim, p, pa_dfra, cfra); /* rotations */ - rotate_particle(part,pa,pa_dfra,timestep); + rotate_particle(part, pa, pa_dfra, timestep); break; case PART_PHYS_BOIDS: { @@ -3845,18 +3812,18 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic boid_body(&bbd, pa); /* deflection */ - deflect_particle(scene,ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra); + deflect_particle(sim, p, pa_dfra, cfra); } break; } } if(pa->alive == PARS_DYING){ - push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state); + //push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state); if(part->flag & PART_LOOP && part->type!=PART_HAIR){ pa->loop++; - reset_particle(scene, pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot); + reset_particle(sim, pa, 0.0, cfra); pa->alive=PARS_ALIVE; } else{ @@ -3867,7 +3834,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic else pa->state.time=cfra; - push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state); + //push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state); } } } @@ -3879,28 +3846,21 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } /* updates cached particles' alive & other flags etc..*/ -static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void cached_step(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part=psys->part; - ParticleKey state; - IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system - Material *ma=give_current_material(ob,part->omat); + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + IpoCurve *icu_esize = NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system +/* Material *ma = give_current_material(sim->ob,part->omat); */ PARTICLE_P; float disp, birthtime, dietime, *vg_size= NULL; // XXX ipotime=cfra BLI_srandom(psys->seed); if(part->from!=PART_FROM_PARTICLE) - vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); + vg_size= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE); - if(psys->effectors.first) - psys_end_effectors(psys); - - //if(part->flag & (PART_BAKED_GUIDES+PART_BAKED_DEATHS)){ - psys_init_effectors(scene, ob, part->eff_group, psys); - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); - //} + psys_update_effectors(sim, cfra, 1); disp= (float)get_current_display_percentage(psys)/100.0f; @@ -3912,9 +3872,13 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps execute_ipo((ID *)part, part->ipo); } #endif // XXX old animation system - pa->size= psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + //update_settings_with_particle(psys, part, pa); + + pa->size = part->size; + if(part->randsize > 0.0) + pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); - psys->lattice= psys_get_lattice(scene, ob, psys); + psys->lattice= psys_get_lattice(sim); if(part->flag & PART_LOOP && part->type!=PART_HAIR) pa->loop = (short)((cfra - pa->time) / pa->lifetime); @@ -3925,25 +3889,16 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps dietime = birthtime + (1 + pa->loop) * (pa->dietime - pa->time); /* update alive status and push events */ - if(pa->time >= cfra) { - pa->alive = pa->time==cfra ? PARS_ALIVE : PARS_UNBORN; - if((psys->pointcache->flag & PTCACHE_EXTERNAL) == 0) - reset_particle(scene, pa, psys, psmd, ob, 0.0f, cfra, NULL, NULL, NULL); + if(pa->time > cfra) { + pa->alive = PARS_UNBORN; + if(part->flag & PART_UNBORN && (psys->pointcache->flag & PTCACHE_EXTERNAL) == 0) + reset_particle(sim, pa, 0.0f, cfra); } else if(dietime <= cfra){ - if(dietime > psys->cfra){ - state.time = dietime; - psys_get_particle_state(scene, ob,psys,p,&state,1); - push_reaction(ob,psys,p,PART_EVENT_DEATH,&state); - } pa->alive = PARS_DEAD; } else{ pa->alive = PARS_ALIVE; - state.time = cfra; - psys_get_particle_state(scene, ob,psys,p,&state,1); - state.time = cfra; - push_reaction(ob,psys,p,PART_EVENT_NEAR,&state); } if(psys->lattice){ @@ -3951,43 +3906,41 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps psys->lattice= NULL; } - if(BLI_frand() > disp) + if(PSYS_FRAND(p) > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; } /* make sure that children are up to date */ - if(psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) { - realloc_particles(ob, psys, psys->totpart); - distribute_particles(scene, ob, psys, PART_FROM_CHILD); + if(psys->part->childtype && psys->totchild != get_psys_tot_child(sim->scene, psys)) { + realloc_particles(sim, psys->totpart); + distribute_particles(sim, PART_FROM_CHILD); } - psys_update_path_cache(scene, ob,psmd,psys,cfra); + psys_update_path_cache(sim, cfra); if(vg_size) MEM_freeN(vg_size); } -static void psys_changed_type(Object *ob, ParticleSystem *psys) +static void psys_changed_type(ParticleSimulationData *sim) { - ParticleSettings *part; + ParticleSettings *part = sim->psys->part; PTCacheID pid; - part= psys->part; - - BKE_ptcache_id_from_particles(&pid, ob, psys); + BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys); /* system type has changed so set sensible defaults and clear non applicable flags */ if(part->from == PART_FROM_PARTICLE) { - if(part->type != PART_REACTOR) - part->from = PART_FROM_FACE; + //if(part->type != PART_REACTOR) + part->from = PART_FROM_FACE; if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT) part->distr = PART_DISTR_JIT; } if(part->phystype != PART_PHYS_KEYED) - psys->flag &= ~PSYS_KEYED; + sim->psys->flag &= ~PSYS_KEYED; if(part->type == PART_HAIR) { if(ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0) @@ -4002,13 +3955,13 @@ static void psys_changed_type(Object *ob, ParticleSystem *psys) BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { - free_hair(ob, psys, 1); + free_hair(sim->ob, sim->psys, 1); CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime)); CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime)); } - psys_reset(psys, PSYS_RESET_ALL); + psys_reset(sim->psys, PSYS_RESET_ALL); } void psys_check_boid_data(ParticleSystem *psys) { @@ -4034,24 +3987,24 @@ void psys_check_boid_data(ParticleSystem *psys) pa->boid = NULL; } } -static void psys_changed_physics(Object *ob, ParticleSystem *psys) +static void psys_changed_physics(ParticleSimulationData *sim) { - ParticleSettings *part = psys->part; + ParticleSettings *part = sim->psys->part; if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) { PTCacheID pid; - BKE_ptcache_id_from_particles(&pid, ob, psys); + BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys); BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { - free_keyed_keys(psys); - psys->flag &= ~PSYS_KEYED; + free_keyed_keys(sim->psys); + sim->psys->flag &= ~PSYS_KEYED; } if(part->phystype == PART_PHYS_BOIDS && part->boids == NULL) { BoidState *state; - psys_check_boid_data(psys); + psys_check_boid_data(sim->psys); part->boids = MEM_callocN(sizeof(BoidSettings), "Boid Settings"); boid_default_settings(part->boids); @@ -4066,8 +4019,9 @@ static void psys_changed_physics(Object *ob, ParticleSystem *psys) BLI_addtail(&part->boids->states, state); } } -static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, int cfra) +static void particles_fluid_step(ParticleSimulationData *sim, int cfra) { + ParticleSystem *psys = sim->psys; if(psys->particles){ MEM_freeN(psys->particles); psys->particles = 0; @@ -4077,7 +4031,7 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, /* fluid sim particle import handling, actual loading of particles from file */ #ifndef DISABLE_ELBEEM { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); + FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(sim->ob, eModifierType_Fluidsim); if( fluidmd && fluidmd->fss) { FluidsimSettings *fss= fluidmd->fss; @@ -4087,7 +4041,7 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, char *suffix2 = ".gz"; char filename[256]; char debugStrBuffer[256]; - int curFrame = scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading + int curFrame = sim->scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading int p, j, numFileParts, totpart; int readMask, activeParts = 0, fileParts = 0; gzFile gzf; @@ -4115,11 +4069,11 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, part->totpart= totpart; part->sta=part->end = 1.0f; - part->lifetime = scene->r.efra + 1; + part->lifetime = sim->scene->r.efra + 1; /* initialize particles */ - realloc_particles(ob, psys, part->totpart); - initialize_all_particles(ob, psys, 0); + realloc_particles(sim, part->totpart); + initialize_all_particles(sim); // set up reading mask readMask = fss->typeFlags; @@ -4175,10 +4129,11 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, /* Calculates the next state for all particles of the system */ /* In particles code most fra-ending are frames, time-ending are fra*timestep (seconds)*/ -static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) +static void system_step(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part; - PointCache *cache; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + PointCache *cache = psys->pointcache; PTCacheID pid; PARTICLE_P; int totpart, oldtotpart, totchild, oldtotchild; @@ -4186,20 +4141,17 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0; int framenr, framedelta, startframe, endframe; - part= psys->part; - cache= psys->pointcache; - - framenr= (int)scene->r.cfra; + framenr= (int)sim->scene->r.cfra; framedelta= framenr - cache->simframe; /* set suitable cache range automatically */ if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0 && !(psys->flag & PSYS_HAIR_DYNAMICS)) - psys_get_pointcache_start_end(scene, psys, &cache->startframe, &cache->endframe); + psys_get_pointcache_start_end(sim->scene, sim->psys, &cache->startframe, &cache->endframe); - BKE_ptcache_id_from_particles(&pid, ob, psys); - BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL); + BKE_ptcache_id_from_particles(&pid, sim->ob, psys); + BKE_ptcache_id_time(&pid, sim->scene, 0.0f, &startframe, &endframe, NULL); - psys_clear_temp_pointcache(psys); + psys_clear_temp_pointcache(sim->psys); /* update ipo's */ #if 0 // XXX old animation system @@ -4211,14 +4163,14 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* hair if it's already done is handled separate */ if(part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)) { - hair_step(scene, ob, psmd, psys, cfra); + hair_step(sim, cfra); psys->cfra = cfra; psys->recalc = 0; return; } /* fluid is also handled separate */ else if(part->type == PART_FLUID) { - particles_fluid_step(scene, ob, psys, framenr); + particles_fluid_step(sim, framenr); psys->cfra = cfra; psys->recalc = 0; return; @@ -4255,7 +4207,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle totpart = part->grid_res*part->grid_res*part->grid_res; else totpart = psys->part->totpart; - totchild = get_psys_tot_child(scene, psys); + totchild = get_psys_tot_child(sim->scene, psys); if(oldtotpart != totpart || oldtotchild != totchild) { only_children_changed = (oldtotpart == totpart); @@ -4272,45 +4224,45 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle if(init) { if(distr) { if(alloc) { - realloc_particles(ob, psys, totpart); + realloc_particles(sim, totpart); if(usecache && !only_children_changed) { BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); - BKE_ptcache_id_from_particles(&pid, ob, psys); + BKE_ptcache_id_from_particles(&pid, sim->ob, psys); } } if(!only_children_changed) - distribute_particles(scene, ob, psys, part->from); + distribute_particles(sim, part->from); if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE)) /* don't generate children while growing hair - waste of time */ psys_free_children(psys); - else if(get_psys_tot_child(scene, psys)) - distribute_particles(scene, ob, psys, PART_FROM_CHILD); + else if(get_psys_tot_child(sim->scene, psys)) + distribute_particles(sim, PART_FROM_CHILD); } if(!only_children_changed) { free_keyed_keys(psys); - initialize_all_particles(ob, psys, psmd); + initialize_all_particles(sim); if(alloc) { - reset_all_particles(scene, ob, psys, psmd, 0.0, cfra, oldtotpart); + reset_all_particles(sim, 0.0, cfra, oldtotpart); } } /* flag for possible explode modifiers after this system */ - psmd->flag |= eParticleSystemFlag_Pars; + sim->psmd->flag |= eParticleSystemFlag_Pars; } /* try to read from the cache */ if(usecache) { - int result = BKE_ptcache_read_cache(&pid, cfra, scene->r.frs_sec); + int result = BKE_ptcache_read_cache(&pid, cfra, sim->scene->r.frs_sec); if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) { - cached_step(scene, ob, psmd, psys, cfra); + cached_step(sim, cfra); psys->cfra=cfra; psys->recalc = 0; @@ -4334,7 +4286,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle pa->alive = PARS_ALIVE; } } - else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { + else if(sim->ob->id.lib || (cache->flag & PTCACHE_BAKED)) { psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra=cfra; psys->recalc = 0; @@ -4352,14 +4304,14 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle BKE_ptcache_write_cache(&pid, startframe); if(part->phystype==PART_PHYS_KEYED) - psys_count_keyed_targets(ob,psys); + psys_count_keyed_targets(sim); /* initialize vertex groups */ if(part->from!=PART_FROM_PARTICLE) { - vg_vel= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_VEL); - vg_tan= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_TAN); - vg_rot= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT); - vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); + vg_vel= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_VEL); + vg_tan= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_TAN); + vg_rot= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_ROT); + vg_size= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE); } /* set particles to be not calculated TODO: can't work with pointcache */ @@ -4367,7 +4319,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle BLI_srandom(psys->seed); LOOP_PARTICLES { - if(BLI_frand() > disp) + if(PSYS_FRAND(p) > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -4383,7 +4335,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle for(dframe=-totframesback; dframe<=0; dframe++) { /* ok now we're all set so let's go */ - dynamics_step(scene, ob, psys, psmd, cfra+dframe, vg_vel, vg_tan, vg_rot, vg_size); + dynamics_step(sim, cfra+dframe); psys->cfra = cfra+dframe; } } @@ -4400,8 +4352,8 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* for keyed particles the path is allways known so it can be drawn */ if(part->phystype==PART_PHYS_KEYED) { - set_keyed_keys(scene, ob, psys); - psys_update_path_cache(scene, ob, psmd, psys,(int)cfra); + set_keyed_keys(sim); + psys_update_path_cache(sim,(int)cfra); } else if(psys->pathcache) psys_free_path_cache(psys, NULL); @@ -4431,30 +4383,33 @@ static int hair_needs_recalc(ParticleSystem *psys) /* main particle update call, checks that things are ok on the large scale before actual particle calculations */ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) { - ParticleSystemModifierData *psmd; + ParticleSimulationData sim = {scene, ob, psys, NULL}; float cfra; + /* drawdata is outdated after ANY change */ + if(psys->pdd) psys->pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED; + if(!psys_check_enabled(ob, psys)) return; cfra= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0f); - psmd= psys_get_modifier(ob, psys); + sim.psmd= psys_get_modifier(ob, psys); /* system was already updated from modifier stack */ - if(psmd->flag & eParticleSystemFlag_psys_updated) { - psmd->flag &= ~eParticleSystemFlag_psys_updated; + if(sim.psmd->flag & eParticleSystemFlag_psys_updated) { + sim.psmd->flag &= ~eParticleSystemFlag_psys_updated; /* make sure it really was updated to cfra */ if(psys->cfra == cfra) return; } - if(!psmd->dm) + if(!sim.psmd->dm) return; if(psys->recalc & PSYS_RECALC_TYPE) - psys_changed_type(ob, psys); + psys_changed_type(&sim); else if(psys->recalc & PSYS_RECALC_PHYS) - psys_changed_physics(ob, psys); + psys_changed_physics(&sim); /* (re-)create hair */ if(psys->part->type==PART_HAIR && hair_needs_recalc(psys)) { @@ -4468,15 +4423,15 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) for(i=0; i<=psys->part->hair_step; i++){ hcfra=100.0f*(float)i/(float)psys->part->hair_step; - system_step(scene, ob, psys, psmd, hcfra); - save_hair(scene, ob, psys, psmd, hcfra); + system_step(&sim, hcfra); + save_hair(&sim, hcfra); } psys->flag |= PSYS_HAIR_DONE; } /* the main particle system step */ - system_step(scene, ob, psys, psmd, cfra); + system_step(&sim, cfra); /* save matrix for duplicators */ Mat4Invert(psys->imat, ob->obmat); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index f351f8a4335..3915a6901a0 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -56,15 +56,23 @@ #include "BKE_smoke.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" +#include "BIK_api.h" #include "BLI_blenlib.h" /* both in intern */ #include "smoke_API.h" + +#ifdef WITH_LZO #include "minilzo.h" +#else +/* used for non-lzo cases */ +#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3) +#endif +#ifdef WITH_LZMA #include "LzmaLib.h" - +#endif /* needed for directory lookup */ /* untitled blend's need getpid for a unique name */ @@ -79,6 +87,20 @@ static void ptcache_data_to(void **data, int type, int index, void *to); static void ptcache_data_from(void **data, int type, void *from); +#define PTCACHE_DATA_FROM(data, type, from) if(data[type]) { memcpy(data[type], from, ptcache_data_size[type]); } +#define PTCACHE_DATA_TO(data, type, index, to) if(data[type]) { memcpy(to, (char*)data[type] + (index ? index * ptcache_data_size[type] : 0), ptcache_data_size[type]); } + +int ptcache_data_size[] = { + sizeof(int), // BPHYS_DATA_INDEX + 3 * sizeof(float), // BPHYS_DATA_LOCATION: + 3 * sizeof(float), // BPHYS_DATA_VELOCITY: + 4 * sizeof(float), // BPHYS_DATA_ROTATION: + 3 * sizeof(float), // BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */ + sizeof(float), // BPHYS_DATA_SIZE: + 3 * sizeof(float), // BPHYS_DATA_TIMES: + sizeof(BoidData) // case BPHYS_DATA_BOIDS: +}; + /* Common functions */ static int ptcache_read_basic_header(PTCacheFile *pf) { @@ -110,8 +132,8 @@ static int ptcache_write_softbody(int index, void *soft_v, void **data) SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; - ptcache_data_from(data, BPHYS_DATA_LOCATION, bp->pos); - ptcache_data_from(data, BPHYS_DATA_VELOCITY, bp->vec); + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, bp->pos); + PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, bp->vec); return 1; } @@ -125,8 +147,8 @@ static void ptcache_read_softbody(int index, void *soft_v, void **data, float fr memcpy(bp->vec, data + 3, 3 * sizeof(float)); } else { - ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, bp->pos); - ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, bp->vec); + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, bp->pos); + PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec); } } static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) @@ -181,25 +203,25 @@ static int ptcache_write_particle(int index, void *psys_v, void **data) return 0; } - ptcache_data_from(data, BPHYS_DATA_INDEX, &index); - ptcache_data_from(data, BPHYS_DATA_LOCATION, pa->state.co); - ptcache_data_from(data, BPHYS_DATA_VELOCITY, pa->state.vel); - ptcache_data_from(data, BPHYS_DATA_ROTATION, pa->state.rot); - ptcache_data_from(data, BPHYS_DATA_AVELOCITY, pa->state.ave); - ptcache_data_from(data, BPHYS_DATA_SIZE, &pa->size); - ptcache_data_from(data, BPHYS_DATA_TIMES, times); + PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index); + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co); + PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel); + PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot); + PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave); + PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size); + PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times); if(boid) - ptcache_data_from(data, BPHYS_DATA_BOIDS, &boid->data); + PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); return 1; } void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time) { - ptcache_data_to(data, BPHYS_DATA_LOCATION, index, key->co); - ptcache_data_to(data, BPHYS_DATA_VELOCITY, index, key->vel); - ptcache_data_to(data, BPHYS_DATA_ROTATION, index, key->rot); - ptcache_data_to(data, BPHYS_DATA_AVELOCITY, index, key->ave); + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co); + PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel); + PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot); + PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave); key->time = time; } static void ptcache_read_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) @@ -220,18 +242,18 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); if(data[BPHYS_DATA_SIZE]) - ptcache_data_to(data, BPHYS_DATA_SIZE, 0, &pa->size); + PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); if(data[BPHYS_DATA_TIMES]) { float times[3]; - ptcache_data_to(data, BPHYS_DATA_TIMES, 0, ×); + PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×); pa->time = times[0]; pa->dietime = times[1]; pa->lifetime = times[2]; } if(boid) - ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &boid->data); + PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); /* determine velocity from previous location */ if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { @@ -307,6 +329,132 @@ static int ptcache_totwrite_particle(void *psys_v) return totwrite; } +//static int ptcache_write_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v) +//{ +// ParticleSystem *psys= psys_v; +// ParticleData *pa = psys->particles; +// BoidParticle *boid = NULL; +// float times[3]; +// int i = 0; +// +// if(!pf && !pm) +// return 0; +// +// for(i=0; i<psys->totpart; i++, pa++) { +// +// 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) +// continue; +// } +// +// times[0] = pa->time; +// times[1] = pa->dietime; +// times[2] = pa->lifetime; +// +// PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times); +// +// boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; +// if(boid) +// PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); +// +// if(pf && !ptcache_file_write_data(pf)) +// return 0; +// +// if(pm) +// BKE_ptcache_mem_incr_pointers(pm); +// } +// +// return 1; +//} +//static void ptcache_read_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) +//{ +// ParticleSystem *psys= psys_v; +// ParticleData *pa = psys->particles + index; +// BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; +// +// if(cfra > pa->state.time) +// memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey)); +// +// if(old_data){ +// /* old format cache */ +// memcpy(&pa->state, old_data, sizeof(ParticleKey)); +// return; +// } +// +// BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); +// +// if(data[BPHYS_DATA_SIZE]) +// PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); +// +// if(data[BPHYS_DATA_TIMES]) { +// float times[3]; +// PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×); +// pa->time = times[0]; +// pa->dietime = times[1]; +// pa->lifetime = times[2]; +// } +// +// if(boid) +// PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); +// +// /* determine velocity from previous location */ +// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { +// if(cfra > pa->prev_state.time) { +// VecSubf(pa->state.vel, pa->state.co, pa->prev_state.co); +// VecMulf(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec); +// } +// else { +// VecSubf(pa->state.vel, pa->prev_state.co, pa->state.co); +// VecMulf(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec); +// } +// } +// +// /* determine rotation from velocity */ +// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { +// vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot); +// } +//} +//static void ptcache_interpolate_particle_stream(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +//{ +// ParticleSystem *psys= psys_v; +// ParticleData *pa = psys->particles + index; +// ParticleKey keys[4]; +// float dfra; +// +// cfra = MIN2(cfra, pa->dietime); +// cfra1 = MIN2(cfra1, pa->dietime); +// cfra2 = MIN2(cfra2, pa->dietime); +// +// if(cfra1 == cfra2) +// return; +// +// memcpy(keys+1, &pa->state, sizeof(ParticleKey)); +// if(old_data) +// memcpy(keys+2, old_data, sizeof(ParticleKey)); +// else +// BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); +// +// dfra = cfra2 - cfra1; +// +// VecMulf(keys[1].vel, dfra / frs_sec); +// VecMulf(keys[2].vel, dfra / frs_sec); +// +// psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); +// QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra); +// +// VecMulf(pa->state.vel, frs_sec / dfra); +// +// pa->state.time = cfra; +//} +// /* Cloth functions */ static int ptcache_write_cloth(int index, void *cloth_v, void **data) { @@ -314,9 +462,9 @@ static int ptcache_write_cloth(int index, void *cloth_v, void **data) Cloth *cloth= clmd->clothObject; ClothVertex *vert = cloth->verts + index; - ptcache_data_from(data, BPHYS_DATA_LOCATION, vert->x); - ptcache_data_from(data, BPHYS_DATA_VELOCITY, vert->v); - ptcache_data_from(data, BPHYS_DATA_XCONST, vert->xconst); + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, vert->x); + PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, vert->v); + PTCACHE_DATA_FROM(data, BPHYS_DATA_XCONST, vert->xconst); return 1; } @@ -332,9 +480,9 @@ static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_ memcpy(vert->v, data + 6, 3 * sizeof(float)); } else { - ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, vert->x); - ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, vert->v); - ptcache_data_to(data, BPHYS_DATA_XCONST, 0, vert->xconst); + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, vert->x); + PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, vert->v); + PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst); } } static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) @@ -484,20 +632,25 @@ static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size); static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode) { int r = 0; - unsigned char compressed; - LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); - unsigned int out_len = LZO_OUT_LEN(in_len); + unsigned char compressed = 0; + unsigned int out_len= 0; unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); size_t sizeOfIt = 5; +#ifdef WITH_LZO + out_len= LZO_OUT_LEN(in_len); if(mode == 1) { + LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); + r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); if (!(r == LZO_E_OK) || (out_len >= in_len)) compressed = 0; else compressed = 1; } - else if(mode == 2) { +#endif +#ifdef WITH_LZMA + if(mode == 2) { r = LzmaCompress(out, (size_t *)&out_len, in, in_len,//assume sizeof(char)==1.... props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); @@ -507,7 +660,8 @@ static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned i else compressed = 2; } - +#endif + ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); if(compressed) { ptcache_file_write(pf, &out_len, 1, sizeof(unsigned int)); @@ -570,9 +724,9 @@ static int ptcache_write_smoke_turbulence(PTCacheFile *pf, void *smoke_v) SmokeDomainSettings *sds = smd->domain; if(sds->wt) { - unsigned int res_big_array[3]; - unsigned int res_big; - unsigned int res = sds->res[0]*sds->res[1]*sds->res[2]; + int res_big_array[3]; + int res_big; + int res = sds->res[0]*sds->res[1]*sds->res[2]; float *dens, *densold, *tcu, *tcv, *tcw; unsigned int in_len = sizeof(float)*(unsigned int)res; unsigned int in_len_big; @@ -621,16 +775,19 @@ static int ptcache_compress_read(PTCacheFile *pf, unsigned char *result, unsigne in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); +#ifdef WITH_LZO if(compressed == 1) r = lzo1x_decompress(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); - else if(compressed == 2) +#endif +#ifdef WITH_LZMA + if(compressed == 2) { size_t leni = in_len, leno = out_len; ptcache_file_read(pf, &sizeOfIt, 1, sizeof(unsigned int)); ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); } - +#endif MEM_freeN(in); } else { @@ -678,8 +835,8 @@ static void ptcache_read_smoke_turbulence(PTCacheFile *pf, void *smoke_v) SmokeDomainSettings *sds = smd->domain; if(sds->fluid) { - unsigned int res = sds->res[0]*sds->res[1]*sds->res[2]; - unsigned int res_big, res_big_array[3]; + int res = sds->res[0]*sds->res[1]*sds->res[2]; + int res_big, res_big_array[3]; float *dens, *densold, *tcu, *tcv, *tcw; unsigned int out_len = sizeof(float)*(unsigned int)res; unsigned int out_len_big; @@ -987,7 +1144,7 @@ static int ptcache_file_read_data(PTCacheFile *pf) int i; for(i=0; i<BPHYS_TOT_DATA; i++) { - if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, BKE_ptcache_data_size(i))) + if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i])) return 0; } @@ -998,7 +1155,7 @@ static int ptcache_file_write_data(PTCacheFile *pf) int i; for(i=0; i<BPHYS_TOT_DATA; i++) { - if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, BKE_ptcache_data_size(i))) + if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i])) return 0; } @@ -1045,38 +1202,7 @@ static int ptcache_file_write_header_begin(PTCacheFile *pf) /* Data pointer handling */ int BKE_ptcache_data_size(int data_type) { - switch(data_type) { - case BPHYS_DATA_INDEX: - return sizeof(int); - case BPHYS_DATA_LOCATION: - case BPHYS_DATA_VELOCITY: - case BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */ - case BPHYS_DATA_TIMES: - return 3 * sizeof(float); - case BPHYS_DATA_ROTATION: - return 4 * sizeof(float); - case BPHYS_DATA_SIZE: - return sizeof(float); - case BPHYS_DATA_BOIDS: - return sizeof(BoidData); - default: - return 0; - } -} -static void ptcache_data_to(void **data, int type, int index, void *to) -{ - if(data[type]) { - if(index) - memcpy(to, (char*)data[type] + index * BKE_ptcache_data_size(type), BKE_ptcache_data_size(type)); - else - memcpy(to, data[type], BKE_ptcache_data_size(type)); - } -} - -static void ptcache_data_from(void **data, int type, void *from) -{ - if(data[type]) - memcpy(data[type], from, BKE_ptcache_data_size(type)); + return ptcache_data_size[data_type]; } static void ptcache_file_init_pointers(PTCacheFile *pf) @@ -1108,7 +1234,7 @@ void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm) for(i=0; i<BPHYS_TOT_DATA; i++) { if(pm->cur[i]) - pm->cur[i] = (char*)pm->cur[i] + BKE_ptcache_data_size(i); + pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i]; } } static void ptcache_alloc_data(PTCacheMem *pm) @@ -1119,7 +1245,7 @@ static void ptcache_alloc_data(PTCacheMem *pm) for(i=0; i<BPHYS_TOT_DATA; i++) { if(data_types & (1<<i)) - pm->data[i] = MEM_callocN(totpoint * BKE_ptcache_data_size(i), "PTCache Data"); + pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data"); } } static void ptcache_free_data(void *data[]) @@ -1136,7 +1262,7 @@ static void ptcache_copy_data(void *from[], void *to[]) int i; for(i=0; i<BPHYS_TOT_DATA; i++) { if(from[i]) - memcpy(to[i], from[i], BKE_ptcache_data_size(i)); + memcpy(to[i], from[i], ptcache_data_size[i]); } } @@ -1898,6 +2024,9 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } } + if (ob->type == OB_ARMATURE) + BIK_clear_cache(ob->pose); + return reset; } @@ -2119,6 +2248,25 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker) if((cache->flag & PTCACHE_BAKED)==0) { if(pid->type==PTCACHE_TYPE_PARTICLES) psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); + else if(pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) { + /* get all pids from the object and search for smoke low res */ + ListBase pidlist2; + PTCacheID *pid2; + BKE_ptcache_ids_from_object(&pidlist2, pid->ob); + for(pid2=pidlist2.first; pid2; pid2=pid2->next) { + if(pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) + { + if(pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) { + if(bake || pid2->cache->flag & PTCACHE_REDO_NEEDED) + BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0); + if(bake) { + pid2->cache->flag |= PTCACHE_BAKING; + pid2->cache->flag &= ~PTCACHE_BAKED; + } + } + } + } + } if(bake || cache->flag & PTCACHE_REDO_NEEDED) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index 391adfb762a..e524359d2bc 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -230,7 +230,7 @@ char *BKE_reports_string(ReportList *reports, ReportType level) DynStr *ds; char *cstring; - if(!reports) + if(!reports || !reports->list.first) return NULL; ds= BLI_dynstr_new(); diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index de2118af202..5cd554725ff 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -128,6 +128,9 @@ void init_sensor(bSensor *sens) case SENS_PROPERTY: sens->data= MEM_callocN(sizeof(bPropertySensor), "propsens"); break; + case SENS_ARMATURE: + sens->data= MEM_callocN(sizeof(bArmatureSensor), "armsens"); + break; case SENS_ACTUATOR: sens->data= MEM_callocN(sizeof(bActuatorSensor), "actsens"); break; @@ -455,6 +458,9 @@ void init_actuator(bActuator *act) case ACT_STATE: act->data = MEM_callocN(sizeof( bStateActuator ), "state act"); break; + case ACT_ARMATURE: + act->data = MEM_callocN(sizeof( bArmatureActuator ), "armature act"); + break; default: ; /* this is very severe... I cannot make any memory for this */ /* logic brick... */ @@ -596,6 +602,8 @@ void sca_remove_ob_poin(Object *obt, Object *ob) bEditObjectActuator *eoa; bPropertyActuator *pa; bMessageActuator *ma; + bParentActuator *para; + bArmatureActuator *aa; sens= obt->sensors.first; while(sens) { @@ -634,7 +642,15 @@ void sca_remove_ob_poin(Object *obt, Object *ob) ma= act->data; if(ma->toObject==ob) ma->toObject= NULL; break; - + case ACT_PARENT: + para = act->data; + if (para->ob==ob) para->ob = NULL; + break; + case ACT_ARMATURE: + aa = act->data; + if (aa->target == ob) aa->target = NULL; + if (aa->subtarget == ob) aa->subtarget = NULL; + break; } act= act->next; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 6f9ed3e0978..4de9ff3b6d9 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -419,7 +419,11 @@ Scene *add_scene(char *name) pset->brush[PE_BRUSH_CUT].strength= 100; sce->jumpframe = 10; - sce->r.audio.mixrate = 44100; + sce->r.ffcodecdata.audio_mixrate = 44100; + + sce->audio.distance_model = 2.0; + sce->audio.doppler_factor = 1.0; + sce->audio.speed_of_sound = 343.3; strcpy(sce->r.backbuf, "//backbuf"); strcpy(sce->r.pic, U.renderdir); diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index cc740d7fb3d..661d0da1550 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -33,8 +33,10 @@ #include "MEM_guardedalloc.h" +#include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "DNA_view3d_types.h" #include "BLI_blenlib.h" @@ -321,4 +323,23 @@ void free_screen(bScreen *sc) BLI_freelistN(&sc->areabase); } +/* for depsgraph */ +unsigned int BKE_screen_visible_layers(bScreen *screen) +{ + ScrArea *sa; + unsigned int layer= 0; + + if(!screen) + return layer; + + /* get all used view3d layers */ + for(sa= screen->areabase.first; sa; sa= sa->next) + if(sa->spacetype==SPACE_VIEW3D) + layer |= ((View3D *)sa->spacedata.first)->lay; + + if(!layer) + return screen->scene->lay; + + return layer; +} diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c index c6b714c3125..7f3e2789232 100644 --- a/source/blender/blenkernel/intern/sequence.c +++ b/source/blender/blenkernel/intern/sequence.c @@ -127,7 +127,7 @@ void new_tstripdata(Sequence *seq) /* free */ -void free_proxy_seq(Sequence *seq) +static void free_proxy_seq(Sequence *seq) { if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) { IMB_free_anim(seq->strip->proxy->anim); @@ -682,7 +682,7 @@ void clear_scene_in_allseqs(Scene *sce) } } -char *give_seqname_by_type(int type) +static char *give_seqname_by_type(int type) { switch(type) { case SEQ_META: return "Meta"; @@ -949,7 +949,7 @@ static TStripElem* alloc_tstripdata(int len, const char * name) return se; } -TStripElem *give_tstripelem(Sequence *seq, int cfra) +static TStripElem *give_tstripelem(Sequence *seq, int cfra) { TStripElem *se; int nr; @@ -1297,7 +1297,7 @@ static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int re se->ibuf = 0; } -void seq_proxy_rebuild(Scene *scene, Sequence * seq) +static void seq_proxy_rebuild(Scene *scene, Sequence * seq) { int cfra; float rsize = seq->strip->proxy->size; @@ -2623,7 +2623,7 @@ ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown } /* check used when we need to change seq->blend_mode but not to effect or audio strips */ -int seq_can_blend(Sequence *seq) +static int seq_can_blend(Sequence *seq) { if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) { return 1; @@ -2749,7 +2749,7 @@ static void *seq_prefetch_thread(void * This_) return 0; } -void seq_start_threads(Scene *scene) +static void seq_start_threads(Scene *scene) { int i; @@ -2782,7 +2782,7 @@ void seq_start_threads(Scene *scene) BLI_init_threads(0, 0, 0); } -void seq_stop_threads() +static void seq_stop_threads() { PrefetchThread *tslot; PrefetchQueueElem *e; @@ -2850,7 +2850,7 @@ void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, pthread_mutex_unlock(&wakeup_lock); } -void seq_wait_for_prefetch_ready() +static void seq_wait_for_prefetch_ready() { PrefetchThread *tslot; @@ -2984,7 +2984,7 @@ static void free_anim_seq(Sequence *seq) } } -void free_imbuf_seq_except(Scene *scene, int cfra) +static void free_imbuf_seq_except(Scene *scene, int cfra) { Editing *ed= seq_give_editing(scene, FALSE); Sequence *seq; @@ -3178,7 +3178,7 @@ void free_imbuf_seq() } #endif -void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) +static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) { /* force update of all sequences with this ipo, on ipo changes */ Editing *ed= seq_give_editing(scene, FALSE); diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 67744ab56a2..62463b3d555 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -167,7 +167,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive // calc other res with max_res provided VECSUB(size, max, min); - printf("size: %f, %f, %f\n", size[0], size[1], size[2]); + // printf("size: %f, %f, %f\n", size[0], size[1], size[2]); // prevent crash when initializing a plane as domain if((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON)) @@ -212,7 +212,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive } } - printf("smd->domain->dx: %f\n", smd->domain->dx); + // printf("smd->domain->dx: %f\n", smd->domain->dx); // TODO: put in failsafe if res<=0 - dg @@ -228,8 +228,8 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive smd->domain->res_wt[1] = smd->domain->res[1] * (smd->domain->amplify + 1); smd->domain->res_wt[2] = smd->domain->res[2] * (smd->domain->amplify + 1); smd->domain->dx_wt = smd->domain->dx / (smd->domain->amplify + 1); - printf("smd->domain->amplify: %d\n", smd->domain->amplify); - printf("(smd->domain->flags & MOD_SMOKE_HIGHRES)\n"); + // printf("smd->domain->amplify: %d\n", smd->domain->amplify); + // printf("(smd->domain->flags & MOD_SMOKE_HIGHRES)\n"); } if(!smd->domain->shadow) @@ -240,7 +240,7 @@ int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, Derive if(smd->domain->wt) { smoke_initWaveletBlenderRNA(smd->domain->wt, &(smd->domain->strength)); - printf("smoke_initWaveletBlenderRNA\n"); + // printf("smoke_initWaveletBlenderRNA\n"); } return 1; } @@ -526,7 +526,7 @@ void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *faces, int } } -void smokeModifier_freeDomain(SmokeModifierData *smd) +static void smokeModifier_freeDomain(SmokeModifierData *smd) { if(smd->domain) { @@ -550,7 +550,7 @@ void smokeModifier_freeDomain(SmokeModifierData *smd) } } -void smokeModifier_freeFlow(SmokeModifierData *smd) +static void smokeModifier_freeFlow(SmokeModifierData *smd) { if(smd->flow) { @@ -567,7 +567,7 @@ void smokeModifier_freeFlow(SmokeModifierData *smd) } } -void smokeModifier_freeCollision(SmokeModifierData *smd) +static void smokeModifier_freeCollision(SmokeModifierData *smd) { if(smd->coll) { @@ -624,7 +624,7 @@ void smokeModifier_reset(struct SmokeModifierData *smd) smd->time = -1; - printf("reset domain end\n"); + // printf("reset domain end\n"); } else if(smd->flow) { @@ -741,7 +741,7 @@ void smokeModifier_createType(struct SmokeModifierData *smd) } // forward decleration -void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct); +static void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct); static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct); static int get_lamp(Scene *scene, float *light) { @@ -1111,7 +1111,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM framenr = scene->r.cfra; - printf("time: %d\n", scene->r.cfra); + // printf("time: %d\n", scene->r.cfra); if(framenr == smd->time) return; @@ -1123,17 +1123,22 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM cache_wt = sds->point_cache[1]; BKE_ptcache_id_from_smoke_turbulence(&pid_wt, ob, smd); + if(!smd->domain->fluid) + { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_OUTDATED); + } + if(framenr < startframe) return; if(framenr > endframe) return; - if(!smd->domain->fluid) - { - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); - BKE_ptcache_id_reset(scene, &pid_wt, PTCACHE_RESET_OUTDATED); - } + if(!smd->domain->fluid && (framenr != startframe)) + return; + + // printf("startframe: %d, framenr: %d\n", startframe, framenr); if(!smokeModifier_init(smd, ob, scene, dm)) { @@ -1143,7 +1148,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM /* try to read from cache */ cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec); - printf("cache_result: %d\n", cache_result); + // printf("cache_result: %d\n", cache_result); if(cache_result == PTCACHE_READ_EXACT) { @@ -1177,8 +1182,14 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM cache->simframe= framenr; // simulate the actual smoke (c++ code in intern/smoke) + // DG: interesting commenting this line + deactivating loading of noise files if(framenr!=startframe) smoke_step(sds->fluid, smd->time); + + // create shadows before writing cache so we get nice shadows for sstartframe, too + if(get_lamp(scene, light)) + smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx); + BKE_ptcache_write_cache(&pid, framenr); if(sds->wt) @@ -1191,9 +1202,6 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM BKE_ptcache_write_cache(&pid_wt, framenr); } - if(get_lamp(scene, light)) - smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx); - tend(); printf ( "Frame: %d, Time: %f\n", (int)smd->time, ( float ) tval() ); } @@ -1335,7 +1343,7 @@ static void get_cell(float *p0, int res[3], float dx, float *pos, int *cell, int } } -void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct) +static void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct) { int x, y, z; float bv[6]; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 2d5d8dad7a8..6ac9b020f21 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -340,7 +340,7 @@ void sound_update_playing(struct bContext *C) for(handle = scene->sound_handles.first; handle; handle = handle->next) { - if(cfra < handle->startframe || cfra >= handle->endframe || handle->mute) + if(cfra < handle->startframe || cfra >= handle->endframe || handle->mute || (scene->audio.flag & AUDIO_MUTE)) { if(handle->state == AUD_STATUS_PLAYING) { @@ -421,7 +421,7 @@ void sound_scrub(struct bContext *C) int cfra = CFRA; float fps = FPS; - if(scene->r.audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) + if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) { AUD_lock(); @@ -443,7 +443,7 @@ void sound_scrub(struct bContext *C) } } -AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end) +AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end, float volume) { AUD_Device* mixdown = AUD_openReadDevice(specs); SoundHandle *handle; @@ -453,6 +453,8 @@ AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int e end++; + AUD_setDeviceVolume(mixdown, volume); + for(handle = scene->sound_handles.first; handle; handle = handle->next) { if(start < handle->endframe && end > handle->startframe && !handle->mute && handle->source && handle->source->handle) diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index dac426de4eb..8bf0f6b8bdf 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -130,8 +130,10 @@ undo position static void txt_pop_first(Text *text); static void txt_pop_last(Text *text); static void txt_undo_add_op(Text *text, int op); -static void txt_undo_add_block(Text *text, int op, char *buf); +static void txt_undo_add_block(Text *text, int op, const char *buf); static void txt_delete_line(Text *text, TextLine *line); +static void txt_delete_sel (Text *text); +static void txt_make_dirty (Text *text); /***/ @@ -537,6 +539,30 @@ void unlink_text(Main *bmain, Text *text) text->id.us= 0; } +void clear_text(Text *text) /* called directly from rna */ +{ + int oldstate; + + oldstate = txt_get_undostate( ); + txt_set_undostate( 1 ); + txt_sel_all( text ); + txt_delete_sel(text); + txt_set_undostate( oldstate ); + + txt_make_dirty(text); +} + +void write_text(Text *text, char *str) /* called directly from rna */ +{ + int oldstate; + + oldstate = txt_get_undostate( ); + txt_insert_buf( text, str ); + txt_move_eof( text, 0 ); + txt_set_undostate( oldstate ); + + txt_make_dirty(text); +} /*****************************/ /* Editing utility functions */ @@ -570,17 +596,15 @@ static TextLine *txt_new_line(char *str) return tmp; } -static TextLine *txt_new_linen(char *str, int n) +static TextLine *txt_new_linen(const char *str, int n) { TextLine *tmp; - if(!str) str= ""; - tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(n+1, "textline_string"); tmp->format= NULL; - BLI_strncpy(tmp->line, str, n+1); + BLI_strncpy(tmp->line, (str)? str: "", n+1); tmp->len= strlen(tmp->line); tmp->next= tmp->prev= NULL; @@ -1315,7 +1339,7 @@ char *txt_sel_to_buf (Text *text) return buf; } -void txt_insert_buf(Text *text, char *in_buffer) +void txt_insert_buf(Text *text, const char *in_buffer) { int i=0, l=0, j, u, len; TextLine *add; @@ -1544,7 +1568,7 @@ static void txt_undo_add_op(Text *text, int op) text->undo_buf[text->undo_pos+1]= 0; } -static void txt_undo_add_block(Text *text, int op, char *buf) +static void txt_undo_add_block(Text *text, int op, const char *buf) { int length; @@ -2808,3 +2832,60 @@ TextMarker *txt_next_marker(Text *text, TextMarker *marker) { } return NULL; /* Only if marker==NULL */ } + + +/*******************************/ +/* Character utility functions */ +/*******************************/ + +int text_check_bracket(char ch) +{ + int a; + char opens[] = "([{"; + char close[] = ")]}"; + + for(a=0; a<(sizeof(opens)-1); a++) { + if(ch==opens[a]) + return a+1; + else if(ch==close[a]) + return -(a+1); + } + return 0; +} + +int text_check_delim(char ch) +{ + int a; + char delims[] = "():\"\' ~!%^&*-+=[]{};/<>|.#\t,"; + + for(a=0; a<(sizeof(delims)-1); a++) { + if(ch==delims[a]) + return 1; + } + return 0; +} + +int text_check_digit(char ch) +{ + if(ch < '0') return 0; + if(ch <= '9') return 1; + return 0; +} + +int text_check_identifier(char ch) +{ + if(ch < '0') return 0; + if(ch <= '9') return 1; + if(ch < 'A') return 0; + if(ch <= 'Z' || ch == '_') return 1; + if(ch < 'a') return 0; + if(ch <= 'z') return 1; + return 0; +} + +int text_check_whitespace(char ch) +{ + if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') + return 1; + return 0; +} diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index f8e3b3c5ad2..1f72c894cc8 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -75,7 +75,7 @@ static struct bUnitCollection buDummyCollecton = {buDummyDef, 0, 0, sizeof(buDum /* Lengths */ static struct bUnitDef buMetricLenDef[] = { {"kilometer", "kilometers", "km", NULL, "Kilometers", 1000.0, 0.0, B_UNIT_DEF_NONE}, - {"hectometer", "hectometers", "hm", NULL, "10 Meters", 100.0, 0.0, B_UNIT_DEF_SUPPRESS}, + {"hectometer", "hectometers", "hm", NULL, "100 Meters", 100.0, 0.0, B_UNIT_DEF_SUPPRESS}, {"dekameter", "dekameters", "dkm",NULL, "10 Meters", 10.0, 0.0, B_UNIT_DEF_SUPPRESS}, {"meter", "meters", "m", NULL, "Meters", 1.0, 0.0, B_UNIT_DEF_NONE}, /* base unit */ {"decimetre", "decimetres", "dm", NULL, "10 Centimeters", 0.1, 0.0, B_UNIT_DEF_SUPPRESS}, @@ -485,7 +485,7 @@ int bUnit_ReplaceString(char *str, int len_max, char *str_prev, double scale_pre if(unit==NULL) unit= unit_default(usys); - /* add the unit prefic and re-run, use brackets incase there was an expression given */ + /* add the unit prefix and re-run, use brackets incase there was an expression given */ if(snprintf(str_tmp, sizeof(str_tmp), "(%s)%s", str, unit->name) < sizeof(str_tmp)) { strncpy(str, str_tmp, len_max); return bUnit_ReplaceString(str, len_max, NULL, scale_pref, system, type); diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index e7164dc4794..1953058fddf 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -148,7 +148,7 @@ static int write_audio_frame(void) #else pkt.pts = c->coded_frame->pts; #endif - fprintf(stderr, "Audio Frame PTS: %lld\n", pkt.pts); + fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts); pkt.stream_index = audio_stream->index; pkt.flags |= PKT_FLAG_KEY; @@ -265,7 +265,7 @@ static void write_video_frame(RenderData *rd, AVFrame* frame) #else packet.pts = c->coded_frame->pts; #endif - fprintf(stderr, "Video Frame PTS: %lld\n", packet.pts); + fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts); } else { fprintf(stderr, "Video Frame PTS: not set\n"); } @@ -559,7 +559,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex c->codec_id = codec_id; c->codec_type = CODEC_TYPE_AUDIO; - c->sample_rate = rd->audio.mixrate; + c->sample_rate = rd->ffcodecdata.audio_mixrate; c->bit_rate = ffmpeg_audio_bitrate*1000; c->channels = 2; codec = avcodec_find_encoder(c->codec_id); @@ -613,7 +613,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex } /* essential functions -- start, append, end */ -void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) +static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) { /* Handle to the output file */ AVFormatContext* of; @@ -734,7 +734,7 @@ void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) if (ffmpeg_type == FFMPEG_DV) { fmt->audio_codec = CODEC_ID_PCM_S16LE; - if (ffmpeg_multiplex_audio && rd->audio.mixrate != 48000) { + if (ffmpeg_multiplex_audio && rd->ffcodecdata.audio_mixrate != 48000) { G.afbreek = 1; //XXX error("FFMPEG only supports 48khz / stereo " // "audio for DV!"); @@ -831,7 +831,6 @@ static void makeffmpegstring(RenderData* rd, char* string) { } } - void start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty) { ffmpeg_autosplit_count = 0; @@ -844,8 +843,8 @@ void start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty) AUD_Specs specs; specs.channels = c->channels; specs.format = AUD_FORMAT_S16; - specs.rate = rd->audio.mixrate; - audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->efra); + specs.rate = rd->ffcodecdata.audio_mixrate; + audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->efra, rd->ffcodecdata.audio_volume); } } diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index c2d707f60f0..1d275e70a17 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -178,7 +178,7 @@ float power_of_2(float val); */ /* Defines for rotation orders - * WARNING: must match the ePchan_RotMode in DNA_action_types.h + * WARNING: must match the eRotationModes in DNA_action_types.h * order matters - types are saved to file! */ typedef enum eEulerRotationOrders { @@ -364,7 +364,8 @@ void printvec4f(char *str, float v[4]); void VecAddf(float *v, float *v1, float *v2); void VecSubf(float *v, float *v1, float *v2); void VecMulVecf(float *v, float *v1, float *v2); -void VecLerpf(float *target, float *a, float *b, float t); +void VecLerpf(float *target, const float *a, const float *b, const float t); +void VecLerp3f(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3]); void VecMidf(float *v, float *v1, float *v2); void VecOrthoBasisf(float *v, float *v1, float *v2); @@ -375,7 +376,8 @@ void Vec2Mulf(float *v1, float f); void Vec2Addf(float *v, float *v1, float *v2); void Vec2Subf(float *v, float *v1, float *v2); void Vec2Copyf(float *v1, float *v2); -void Vec2Lerpf(float *target, float *a, float *b, float t); +void Vec2Lerpf(float *target, const float *a, const float *b, const float t); +void Vec2Lerp3f(float p[2], const float v1[2], const float v2[2], const float v3[2], const float w[3]); void AxisAngleToQuat(float q[4], float axis[3], float angle); void QuatToAxisAngle(float q[4], float axis[3], float *angle); @@ -401,7 +403,7 @@ float VecAngle2(float *v1, float *v2); float VecAngle3(float *v1, float *v2, float *v3); float NormalizedVecAngle2(float *v1, float *v2); -float VecAngle3_2D(float *v1, float *v2, float *v3); +float Vec2Angle3(float *v1, float *v2, float *v3); float NormalizedVecAngle2_2D(float *v1, float *v2); void NormalShortToFloat(float *out, short *in); @@ -454,6 +456,8 @@ void i_window( #define BLI_CS_REC709 1 #define BLI_CS_CIE 2 +#define RAD2DEG(_rad) ((_rad)*(180.0/M_PI)) + void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b); void hex_to_rgb(char *hexcol, float *r, float *g, float *b); void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv); @@ -525,6 +529,8 @@ int point_in_tri_prism(float p[3], float v1[3], float v2[3], float v3[3]); float lambda_cp_line_ex(float p[3], float l1[3], float l2[3], float cp[3]); +float AngleToLength(const float angle); + typedef struct DualQuat { float quat[4]; float trans[4]; diff --git a/source/blender/blenlib/BLI_bfile.h b/source/blender/blenlib/BLI_bfile.h new file mode 100644 index 00000000000..92543558a19 --- /dev/null +++ b/source/blender/blenlib/BLI_bfile.h @@ -0,0 +1,138 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 by Stichting Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * BFILE* based abstraction of file access. + */ + +#ifndef BLI_BFILE_H +#define BLI_BFILE_H + +/* For fopen's FILE */ +#include <stdio.h> + +/** + Defines for the bflags param. + */ +/* Special handling: */ +/* For "symmetry" of flags */ +#define BFILE_NORMAL (0) +/* No supervision, just translate // if needed, RISKY */ +#define BFILE_RAW (1<<0) +/* Path is relative to config dirs */ +#define BFILE_CONFIG (1<<1) +/* Path is for current session temp file */ +#define BFILE_TEMP (1<<2) + +/* Config handling, special cases: */ +#define BFILE_USERONLY (1<<3) +#define BFILE_SYSONLY (1<<4) + +/* Compression to apply on close: */ +#define BFILE_GZIP (1<<5) + +/** + File descriptor for Blender abstracted file access. + */ +typedef struct { + FILE *stream; + int fd; + + /* Anything below should not be touched directly */ + int uflags; /* Special options requested by upper level, copy of bflags */ + char *fpath; /* Final/requested path name */ + char *tpath; /* Temp path name if applicable */ + int type; /* Own flags, common classification of open and fopen */ + int error; /* An op caused an error, unsafe to replace older files */ +} BFILE; + +/** + Open a BFILE* with fopen()-like syntax. + */ +BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags); + +/** + Open a BFILE* with open()-like syntax. + */ +BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags); + +/** + Get the FILE* associated with the BFILE*. + */ +FILE *BLI_bfile_file_from_bfile(BFILE *bfile); + +/** + Get the fd associated with the BFILE*. + */ +int BLI_bfile_fd_from_bfile(BFILE *bfile); + +/** + write()-like using BFILE*. + */ +ssize_t BLI_bfile_write(BFILE *f, const void *buf, size_t count); + +/** + read()-like using BFILE*. + */ +ssize_t BLI_bfile_read(BFILE *f, void *buf, size_t count); + +/** + fwrite()-like using BFILE*. + */ +size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb, BFILE *f); + +/** + fread()-like using BFILE*. + */ +size_t BLI_bfile_fread(void *ptr, size_t size, size_t nmemb, BFILE *f); + +/** + Close a BFILE, to match close() and fclose(). + */ +void BLI_bfile_close(BFILE *bfile); + +/** + Clear error status. + Call it only if the error has been really handled. + */ +void BLI_bfile_clear_error(BFILE *bfile); + +/** + Set the error status. + Call it to mark writing by a 3rd party failed (libjpeg reported error, ie). + */ +void BLI_bfile_set_error(BFILE *bfile, int error); + +/* +TODO +Maybe also provide more OS/libc things like: +fflush +fprintf and related +fscanf +fgetc/fputc and related +fseek and related + +Probably good to do: +readdir (compacted list showing all files for a "directory" (user versions on top of system's)) +*/ + +#endif /* ifndef BLI_BFILE_H */ diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index c77e82f0a2b..c9a8b1b841f 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -32,6 +32,10 @@ #ifndef BLI_GHASH_H #define BLI_GHASH_H +#ifdef __cplusplus +extern "C" { +#endif + struct GHash; typedef struct GHash GHash; @@ -125,5 +129,9 @@ int BLI_ghashutil_strcmp (void *a, void *b); unsigned int BLI_ghashutil_inthash (void *ptr); int BLI_ghashutil_intcmp(void *a, void *b); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index d0b106b59c3..21b4c83bd88 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -34,6 +34,7 @@ //#include "DNA_listbase.h" struct ListBase; +struct LinkData; #ifdef __cplusplus extern "C" { @@ -56,6 +57,9 @@ int BLI_countlist(struct ListBase *listbase); void BLI_freelinkN(struct ListBase *listbase, void *vlink); void BLI_duplicatelist(struct ListBase *list1, struct ListBase *list2); /* copy from 2 to 1 */ +/* create a generic list node containing link to provided data */ +struct LinkData *BLI_genericNodeN(void *data); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_util.h b/source/blender/blenlib/BLI_util.h index f9a84e071e7..1ce7a8cdb77 100644 --- a/source/blender/blenlib/BLI_util.h +++ b/source/blender/blenlib/BLI_util.h @@ -42,7 +42,14 @@ struct ListBase; struct direntry; char *BLI_gethome(void); -char *BLI_gethome_folder(char *folder_name); +char *BLI_gethome_folder(char *folder_name, int flag); + +/* BLI_gethome_folder flag */ +#define BLI_GETHOME_LOCAL 1<<1 /* relative location for portable binaries */ +#define BLI_GETHOME_SYSTEM 1<<2 /* system location, or set from the BLENDERPATH env variable (UNIX only) */ +#define BLI_GETHOME_USER 1<<3 /* home folder ~/.blender */ +#define BLI_GETHOME_ALL (BLI_GETHOME_SYSTEM|BLI_GETHOME_LOCAL|BLI_GETHOME_USER) + void BLI_setenv(const char *env, const char *val); void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file); diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index b46ebebacd5..757b3605203 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -28,7 +28,13 @@ * * ***** END GPL LICENSE BLOCK ***** */ + +#ifndef __WINSTUFF_H__ +#define __WINSTUFF_H__ + +#ifndef FREE_WINDOWS #pragma warning(once: 4761 4305 4244 4018) +#endif #define WIN32_LEAN_AND_MEAN @@ -56,10 +62,7 @@ #undef small -#ifndef __WINSTUFF_H__ -#define __WINSTUFF_H__ - - // These definitions are also in arithb for simplicity +// These definitions are also in arithb for simplicity #ifdef __cplusplus extern "C" { @@ -91,6 +94,16 @@ extern "C" { typedef unsigned int mode_t; #endif +/* mingw using _SSIZE_T_ to declare ssize_t type */ +#ifndef _SSIZE_T_ +#define _SSIZE_T_ +/* python uses HAVE_SSIZE_T */ +#ifndef HAVE_SSIZE_T +#define HAVE_SSIZE_T 1 +typedef long ssize_t; +#endif +#endif + struct dirent { int d_ino; int d_off; diff --git a/source/blender/blenlib/intern/BLI_bfile.c b/source/blender/blenlib/intern/BLI_bfile.c new file mode 100644 index 00000000000..a7ce1df5712 --- /dev/null +++ b/source/blender/blenlib/intern/BLI_bfile.c @@ -0,0 +1,236 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 by Stichting Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * BFILE* based abstraction for file access. + */ + +#include <string.h> + +#ifndef WIN32 + #include <unistd.h> +#else + #include <io.h> + #include "BLI_winstuff.h" +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_bfile.h" + +// This would provide config paths and their oldest viable version +// so if there is an uncompatible change, user's old versions are not loaded +//#include "bfile_tables.h" + +/* Internal bfile type flags */ +#define BTF_OPEN (0) +#define BTF_FOPEN (1<<0) +#define BTF_READ (1<<1) +#define BTF_WRITE (1<<2) +#define BTF_AT_END (1<<3) +#define BTF_DISCARD (1<<4) + + +void fill_paths(BFILE *bfile, const char *path) { + char* source_path = NULL; + int bflags = bfile->uflags; + + if(bflags & BFILE_NORMAL || bflags & BFILE_RAW) { +// bfile->fpath is path with // replaced + } + if(bflags & BFILE_TEMP) { +// bfile->fpath is tempdir+path + } + if(bflags & BFILE_CONFIG) { +// bfile->fpath is userdir+version+path +// source_path is first hit in (if using fallback to older versions) +// userdir+curversion+path (... userdir+limitversion+path) sysdir+path +// (limitversion is based in path, using some kind of regex or "tables") + } + + if(bfile->type & BTF_WRITE && !(bflags & BFILE_RAW)) { + /* Generate temp path */ + // bfile->tpath is fpath+randstring + if(!(bfile->type & BTF_DISCARD)) { + /* Copy data to tpath */ + if(source_path) { + // copy it from older version or sys version + } + } + } else { + bfile->tpath = bfile->fpath; + } +} + +BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags) { + BFILE *bfile; + + bfile = MEM_mallocN(sizeof(BFILE), "bfile-fopen"); + bfile->type = BTF_FOPEN; + bfile->uflags = bflags; + + /* From fopen() doc, we can guess some logic: + r BTF_READ + r+ BTF_READ | BTF_WRITE + w BTF_DISCARD | BTF_WRITE + w+ BTF_DISCARD | BTF_WRITE | BTF_READ + a BTF_AT_END | BTF_WRITE + a+ BTF_AT_END | BTF_WRITE | BTF_READ + */ + if(strchr(mode, 'r')) + bfile->type |= BTF_READ; + if(strchr(mode, 'w')) + bfile->type |= (BTF_DISCARD | BTF_WRITE); + if(strchr(mode, 'a')) + bfile->type |= (BTF_AT_END | BTF_WRITE); + if(strchr(mode, '+')) + bfile->type |= (BTF_READ | BTF_WRITE); + + fill_paths(bfile, path); + + bfile->stream = fopen(bfile->tpath, mode); + // detect failed fopen + bfile->fd = fileno(bfile->stream); + return bfile; +} + + +BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags) { + BFILE *bfile; + + bfile = MEM_mallocN(sizeof(BFILE), "bfile-open"); + bfile->type = BTF_OPEN; + bfile->uflags = bflags; + + /* Easy mapping for open() */ + if(flags & O_RDONLY) + bfile->type |= BTF_READ; + if(flags & O_WRONLY) + bfile->type |= BTF_WRITE; + if(flags & O_RDWR) + bfile->type |= (BTF_READ | BTF_WRITE); + if(flags & O_APPEND) + bfile->type |= BTF_AT_END; + if(flags & O_TRUNC) + bfile->type |= BTF_DISCARD; + + fill_paths(bfile, pathname); + + bfile->fd = open(bfile->tpath, flags); + // detect failed open +// bfile->stream = fdopen(bfile->fd, XXX); /* MSWindows _fdopen? */ + return bfile; +} + + +FILE *BLI_bfile_file_from_bfile(BFILE *bfile) { + return bfile->stream; +} + + +int BLI_bfile_fd_from_bfile(BFILE *bfile) { + return bfile->fd; +} + + +ssize_t BLI_bfile_write(BFILE *f, const void *buf, size_t count) { + ssize_t ret; + + ret = write((f->fd), buf, count); + if (ret == -1) { + f->error = 1; + } + + return ret; +} + + +ssize_t BLI_bfile_read(BFILE *f, void *buf, size_t count) { + ssize_t ret; + + ret = read((f->fd), buf, count); + if (ret == -1) { + f->error = 1; + } + + return ret; +} + + +size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb, BFILE *f) { + size_t ret; + + ret = fwrite(ptr, size, nmemb, f->stream); + if (ret < 0) { + f->error = 1; + } + + return ret; +} + + +size_t BLI_bfile_fread(void *ptr, size_t size, size_t nmemb, BFILE *f) { + size_t ret; + + ret = fread(ptr, size, nmemb, f->stream); + if ((ret < 0) && ferror(f->stream)) { + f->error = 1; + } + + return ret; +} + + +void BLI_bfile_close(BFILE *bfile) { + if((bfile->type | BTF_WRITE) && + !(bfile->uflags | BFILE_RAW)) { + /* Make sure data is on disk */ + /* Move to final name if no errors */ + } + + /* Normal close */ + + /* Cleanup */ + if(bfile->fpath) { + MEM_freeN(bfile->fpath); + } + if(bfile->tpath) { + MEM_freeN(bfile->tpath); + } +} + + +void BLI_bfile_clear_error(BFILE *bfile) { + bfile->error = 0; +} + + +void BLI_bfile_set_error(BFILE *bfile, int error) { + /* No cheating, use clear_error() for 0 */ + if (error) { + bfile->error = error; + } +} diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index c5e6ca4b1ae..eea49254a0e 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -332,7 +332,7 @@ static void sort(BVHNode **a0, int begin, int end, int axis) bvh_insertionsort(a, begin, end, axis); } } -void sort_along_axis(BVHTree *tree, int start, int end, int axis) +static void sort_along_axis(BVHTree *tree, int start, int end, int axis) { sort(tree->nodes, start, end, axis); } @@ -340,7 +340,7 @@ void sort_along_axis(BVHTree *tree, int start, int end, int axis) //after a call to this function you can expect one of: // every node to left of a[n] are smaller or equal to it // every node to the right of a[n] are greater or equal to it -int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ +static int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ int begin = _begin, end = _end, cut; while(end-begin > 3) { diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c index 1f3a861ba6a..ccf79ed42dc 100644 --- a/source/blender/blenlib/intern/BLI_kdtree.c +++ b/source/blender/blenlib/intern/BLI_kdtree.c @@ -337,7 +337,7 @@ int BLI_kdtree_find_n_nearest(KDTree *tree, int n, float *co, float *nor, KDTree return found; } -int range_compare(const void * a, const void * b) +static int range_compare(const void * a, const void * b) { const KDTreeNearest *kda = a; const KDTreeNearest *kdb = b; diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 9e769e19674..26bbbf040f3 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2187,23 +2187,40 @@ void VecMulVecf(float *v, float *v1, float *v2) v[2] = v1[2] * v2[2]; } -void VecLerpf(float *target, float *a, float *b, float t) +void VecLerpf(float *target, const float *a, const float *b, const float t) { - float s = 1.0f-t; + const float s = 1.0f-t; target[0]= s*a[0] + t*b[0]; target[1]= s*a[1] + t*b[1]; target[2]= s*a[2] + t*b[2]; } -void Vec2Lerpf(float *target, float *a, float *b, float t) +void Vec2Lerpf(float *target, const float *a, const float *b, const float t) { - float s = 1.0f-t; + const float s = 1.0f-t; target[0]= s*a[0] + t*b[0]; target[1]= s*a[1] + t*b[1]; } +/* weight 3 vectors, (VecWeightf in 2.4x) + * 'w' must be unit length but is not a vector, just 3 weights */ +void VecLerp3f(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3]) +{ + p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2]; + p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2]; + p[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2]; +} + +/* weight 3 2D vectors, (Vec2Weightf in 2.4x) + * 'w' must be unit length but is not a vector, just 3 weights */ +void Vec2Lerp3f(float p[2], const float v1[2], const float v2[2], const float v3[2], const float w[3]) +{ + p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2]; + p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2]; +} + void VecMidf(float *v, float *v1, float *v2) { v[0]= 0.5f*(v1[0]+ v2[0]); @@ -3548,10 +3565,10 @@ float VecAngle3(float *v1, float *v2, float *v3) Normalize(vec1); Normalize(vec2); - return NormalizedVecAngle2(vec1, vec2) * (float)(180.0/M_PI); + return NormalizedVecAngle2(vec1, vec2); } -float VecAngle3_2D(float *v1, float *v2, float *v3) +float Vec2Angle3(float *v1, float *v2, float *v3) { float vec1[2], vec2[2]; @@ -3564,7 +3581,7 @@ float VecAngle3_2D(float *v1, float *v2, float *v3) Normalize2(vec1); Normalize2(vec2); - return NormalizedVecAngle2_2D(vec1, vec2) * (float)(180.0/M_PI); + return NormalizedVecAngle2_2D(vec1, vec2); } /* Return the shortest angle in degrees between the 2 vectors */ @@ -3577,7 +3594,7 @@ float VecAngle2(float *v1, float *v2) Normalize(vec1); Normalize(vec2); - return NormalizedVecAngle2(vec1, vec2)* (float)(180.0/M_PI); + return NormalizedVecAngle2(vec1, vec2); } float NormalizedVecAngle2(float *v1, float *v2) @@ -4093,19 +4110,19 @@ void spheremap(float x, float y, float z, float *u, float *v) /* proposed api by ton and zr, not used yet */ #if 0 /* ***************** m1 = m2 ***************** */ -void cpy_m3_m3(float m1[][3], float m2[][3]) +static void cpy_m3_m3(float m1[][3], float m2[][3]) { memcpy(m1[0], m2[0], 9*sizeof(float)); } /* ***************** m1 = m2 ***************** */ -void cpy_m4_m4(float m1[][4], float m2[][4]) +static void cpy_m4_m4(float m1[][4], float m2[][4]) { memcpy(m1[0], m2[0], 16*sizeof(float)); } /* ***************** identity matrix ***************** */ -void ident_m4(float m[][4]) +static void ident_m4(float m[][4]) { m[0][0]= m[1][1]= m[2][2]= m[3][3]= 1.0; @@ -4116,7 +4133,7 @@ void ident_m4(float m[][4]) } /* ***************** m1 = m2 (pre) * m3 (post) ***************** */ -void mul_m3_m3m3(float m1[][3], float m2[][3], float m3[][3]) +static void mul_m3_m3m3(float m1[][3], float m2[][3], float m3[][3]) { float m[3][3]; @@ -4136,7 +4153,7 @@ void mul_m3_m3m3(float m1[][3], float m2[][3], float m3[][3]) } /* ***************** m1 = m2 (pre) * m3 (post) ***************** */ -void mul_m4_m4m4(float m1[][4], float m2[][4], float m3[][4]) +static void mul_m4_m4m4(float m1[][4], float m2[][4], float m3[][4]) { float m[4][4]; @@ -4164,7 +4181,7 @@ void mul_m4_m4m4(float m1[][4], float m2[][4], float m3[][4]) } /* ***************** m1 = inverse(m2) ***************** */ -void inv_m3_m3(float m1[][3], float m2[][3]) +static void inv_m3_m3(float m1[][3], float m2[][3]) { short a,b; float det; @@ -4187,7 +4204,7 @@ void inv_m3_m3(float m1[][3], float m2[][3]) } /* ***************** m1 = inverse(m2) ***************** */ -int inv_m4_m4(float inverse[][4], float mat[][4]) +static int inv_m4_m4(float inverse[][4], float mat[][4]) { int i, j, k; double temp; @@ -4240,7 +4257,7 @@ int inv_m4_m4(float inverse[][4], float mat[][4]) } /* ***************** v1 = v2 * mat ***************** */ -void mul_v3_v3m4(float *v1, float *v2, float mat[][4]) +static void mul_v3_v3m4(float *v1, float *v2, float mat[][4]) { float x, y; @@ -4715,7 +4732,7 @@ int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float VecSubf(c, v3t, v1); VecSubf(a, v2, v1); - VecSubf(b, v4t, v3); + VecSubf(b, v4t, v3t); Crossf(ab, a, b); Crossf(cb, c, b); @@ -4823,6 +4840,15 @@ static float lambda_cp_line(float p[3], float l1[3], float l2[3]) } #endif +/* useful to calculate an even width shell, by taking the angle between 2 planes. + * The return value is a scale on the offset. + * no angle between planes is 1.0, as the angle between the 2 planes approches 180d + * the distance gets very high, 180d would be inf, but this case isn't valid */ +float AngleToLength(const float angle) +{ + return (angle < SMALL_NUMBER) ? 1.0f : fabsf(1.0f / cosf(angle * (M_PI/180.0f))); +} + /* Similar to LineIntersectsTriangleUV, except it operates on a quad and in 2d, assumes point is in quad */ void PointInQuad2DUV(float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv) { diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 985700efda1..cb5632df569 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -65,7 +65,7 @@ static FT_Library library; static FT_Error err; -void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd) +static void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd) { // Blender struct Nurb *nu; @@ -275,7 +275,7 @@ void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd) } } -int objchr_to_ftvfontdata(VFont *vfont, FT_ULong charcode) +static int objchr_to_ftvfontdata(VFont *vfont, FT_ULong charcode) { // Freetype2 FT_Face face; diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c index cc15c499290..49a3cad53f1 100644 --- a/source/blender/blenlib/intern/graph.c +++ b/source/blender/blenlib/intern/graph.c @@ -354,7 +354,7 @@ void BLI_ReflagSubgraph(BGraph *graph, int old_subgraph, int new_subgraph) /*************************************** CYCLE DETECTION ***********************************************/ -int detectCycle(BNode *node, BArc *src_arc) +static int detectCycle(BNode *node, BArc *src_arc) { int value = 0; @@ -520,7 +520,7 @@ void BLI_calcGraphLength(BGraph *graph) /********************************* SYMMETRY DETECTION **************************************************/ -void markdownSymmetryArc(BGraph *graph, BArc *arc, BNode *node, int level, float limit); +static void markdownSymmetryArc(BGraph *graph, BArc *arc, BNode *node, int level, float limit); void BLI_mirrorAlongAxis(float v[3], float center[3], float axis[3]) { @@ -935,7 +935,7 @@ static void markdownSecondarySymmetry(BGraph *graph, BNode *node, int depth, int } } -void markdownSymmetryArc(BGraph *graph, BArc *arc, BNode *node, int level, float limit) +static void markdownSymmetryArc(BGraph *graph, BArc *arc, BNode *node, int level, float limit) { int i; diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index 3194593374f..b3a4722d6d9 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -359,3 +359,17 @@ void BLI_duplicatelist(ListBase *list1, ListBase *list2) /* copy from 2 to 1 */ } } +/* create a generic list node containing link to provided data */ +LinkData *BLI_genericNodeN (void *data) +{ + LinkData *ld; + + if (data == NULL) + return NULL; + + /* create new link, and make it hold the given data */ + ld= MEM_callocN(sizeof(LinkData), "BLI_genericNodeN()"); + ld->data= data; + + return ld; +} diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index 0bd30a69d05..66e9a65dba5 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -42,9 +42,9 @@ #endif /* local */ -float noise3_perlin(float vec[3]); -float turbulence_perlin(float *point, float lofreq, float hifreq); -float turbulencep(float noisesize, float x, float y, float z, int nr); +static float noise3_perlin(float vec[3]); +static float turbulence_perlin(float *point, float lofreq, float hifreq); +static float turbulencep(float noisesize, float x, float y, float z, int nr); #define HASHVEC(x,y,z) hashvectf+3*hash[ (hash[ (hash[(z) & 255]+(y)) & 255]+(x)) & 255] @@ -915,7 +915,7 @@ float g[512+2][3]= { r1 = r0 - 1.; -float noise3_perlin(float vec[3]) +static float noise3_perlin(float vec[3]) { int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; float rx0, rx1, ry0, ry1, rz0, rz1, *q, sx, sy, sz, a, b, c, d, t, u, v; @@ -976,7 +976,7 @@ float noise3_perlin(float vec[3]) return 1.5 * lerp(sz, c, d); /* interpolate in z */ } -float turbulence_perlin(float *point, float lofreq, float hifreq) +static float turbulence_perlin(float *point, float lofreq, float hifreq) { float freq, t, p[3]; @@ -1029,7 +1029,7 @@ float BLI_hnoisep(float noisesize, float x, float y, float z) return noise3_perlin(vec); } -float turbulencep(float noisesize, float x, float y, float z, int nr) +static float turbulencep(float noisesize, float x, float y, float z, int nr) { float vec[3]; diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index ed3e07b7f7e..ce9f9adeb90 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -316,7 +316,7 @@ typedef struct WorkParam { int index; } WorkParam; -void *exec_work_fnct(void *v_param) +static void *exec_work_fnct(void *v_param) { WorkParam *p = (WorkParam*)v_param; void *value; diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index c7bb7a54457..b1539d22909 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -856,98 +856,123 @@ char *BLI_gethome(void) { #endif } -/* this function returns the path to a blender folder, if it exists, - * trying in this order: - * - * path_to_executable/release/folder_name (in svn) - * ./release/folder_name (in svn) - * $HOME/.blender/folder_name - * path_to_executable/.blender/folder_name - * - * returns NULL if none is found. */ +/* this function returns the path to a blender folder, if it exists + * utility functions for BLI_gethome_folder */ + +/* #define PATH_DEBUG */ /* for testing paths that are checked */ + +static int test_data_path(char *targetpath, char *path_base, char *path_sep, char *folder_name) +{ + char tmppath[FILE_MAXDIR]; + + if(path_sep) BLI_join_dirfile(tmppath, path_base, path_sep); + else BLI_strncpy(tmppath, path_base, sizeof(tmppath)); + + BLI_make_file_string("/", targetpath, tmppath, folder_name); + + if (BLI_exists(targetpath)) { +#ifdef PATH_DEBUG + printf("\tpath found: %s\n", targetpath); +#endif + return 1; + } + else { +#ifdef PATH_DEBUG + printf("\tpath missing: %s\n", targetpath); +#endif + targetpath[0] = '\0'; + return 0; + } +} -char *BLI_gethome_folder(char *folder_name) +static int gethome_path_local(char *targetpath, char *folder_name) { extern char bprogname[]; /* argv[0] from creator.c */ - static char homedir[FILE_MAXDIR] = ""; - static char fulldir[FILE_MAXDIR] = ""; - char tmpdir[FILE_MAXDIR]; char bprogdir[FILE_MAXDIR]; + char cwd[FILE_MAXDIR]; char *s; int i; - + +#ifdef PATH_DEBUG + printf("gethome_path_local...\n"); +#endif + + /* try release/folder_name (binary relative) */ /* use argv[0] (bprogname) to get the path to the executable */ s = BLI_last_slash(bprogname); - i = s - bprogname + 1; BLI_strncpy(bprogdir, bprogname, i); + + /* try ./.blender/folder_name */ + if(test_data_path(targetpath, bprogdir, ".blender", folder_name)) + return 1; + + if(test_data_path(targetpath, bprogdir, "release", folder_name)) + return 1; + + /* try release/folder_name (CWD relative) */ + if(test_data_path(targetpath, BLI_getwdN(cwd), "release", folder_name)) + return 1; + + return 0; +} - /* try path_to_executable/release/folder_name (in svn) */ - if (folder_name) { - BLI_snprintf(tmpdir, sizeof(tmpdir), "release/%s", folder_name); - BLI_make_file_string("/", fulldir, bprogdir, tmpdir); - if (BLI_exists(fulldir)) return fulldir; - else fulldir[0] = '\0'; - } +static int gethome_path_user(char *targetpath, char *folder_name) +{ + char *home_path= BLI_gethome(); - /* try ./release/folder_name (in svn) */ - if(folder_name) { - BLI_snprintf(fulldir, sizeof(fulldir), "./release/%s", folder_name); - if (BLI_exists(fulldir)) return fulldir; - else fulldir[0] = '\0'; - } +#ifdef PATH_DEBUG + printf("gethome_path_user...\n"); +#endif + + /* try $HOME/folder_name */ + return test_data_path(targetpath, home_path, ".blender", folder_name); +} - /* BLI_gethome() can return NULL if env vars are not set */ - s = BLI_gethome(); +static int gethome_path_system(char *targetpath, char *folder_name) +{ + extern char blender_path[]; /* unix prefix eg. /usr/share/blender/2.5 creator.c */ + + if(!blender_path[0]) + return 0; + +#ifdef PATH_DEBUG + printf("gethome_path_system...\n"); +#endif + + /* try $BLENDERPATH/folder_name */ + return test_data_path(targetpath, blender_path, NULL, folder_name); +} - if(!s) { /* bail if no $HOME */ - printf("$HOME is NOT set\n"); - return NULL; +char *BLI_gethome_folder(char *folder_name, int flag) +{ + static char fulldir[FILE_MAXDIR] = ""; + + /* first check if this is a redistributable bundle */ + if(flag & BLI_GETHOME_LOCAL) { + if (gethome_path_local(fulldir, folder_name)) + return fulldir; } - if(strstr(s, ".blender")) - BLI_strncpy(homedir, s, FILE_MAXDIR); - else - BLI_make_file_string("/", homedir, s, ".blender"); - - /* if $HOME/.blender/folder_name exists, return it */ - if(BLI_exists(homedir)) { - if (folder_name) { - BLI_make_file_string("/", fulldir, homedir, folder_name); - if(BLI_exists(fulldir)) - return fulldir; - } - else - return homedir; - } - else - homedir[0] = '\0'; - - /* using tmpdir to preserve homedir (if) found above: - * the ideal is to have a home dir with folder_name dir inside - * it, but if that isn't available, it's possible to - * have a 'broken' home dir somewhere and a folder_name dir in the - * svn sources */ - BLI_make_file_string("/", tmpdir, bprogdir, ".blender"); - - if(BLI_exists(tmpdir)) { - if(folder_name) { - BLI_make_file_string("/", fulldir, tmpdir, folder_name); - if(BLI_exists(fulldir)) { - BLI_strncpy(homedir, tmpdir, FILE_MAXDIR); - return fulldir; - } - else { - homedir[0] = '\0'; - fulldir[0] = '\0'; - } - } - else return homedir; + /* then check if the OS has blender data files installed in a global location */ + if(flag & BLI_GETHOME_SYSTEM) { + if (gethome_path_system(fulldir, folder_name)) + return fulldir; } - + + /* now check the users home dir for data files */ + if(flag & BLI_GETHOME_USER) { + if (gethome_path_user(fulldir, folder_name)) + return fulldir; + } + return NULL; } +#ifdef PATH_DEBUG +#undef PATH_DEBUG +#endif + void BLI_setenv(const char *env, const char*val) { /* SGI or free windows */ diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 6e2772efea4..52295dc3092 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -211,7 +211,7 @@ void BLO_library_append_named_part(const struct bContext *C, struct Main *mainl, void BLO_library_append_end(const struct bContext *C, struct Main *mainl, BlendHandle** bh, int idcode, short flag); /* deprecated */ -#if 0 +#if 1 void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Main *mainvar, struct Scene *scene, struct ReportList *reports); #endif diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 9cd45a268da..3d21bb54e2b 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -99,7 +99,6 @@ static IDType idtypes[]= { { ID_IP, "Ipo", IDTYPE_FLAGS_ISLINKABLE}, { ID_KE, "Key", 0}, { ID_LA, "Lamp", IDTYPE_FLAGS_ISLINKABLE}, - { ID_LF, "Life", 0}, { ID_LI, "Library", 0}, { ID_LT, "Lattice", IDTYPE_FLAGS_ISLINKABLE}, { ID_MA, "Material", IDTYPE_FLAGS_ISLINKABLE}, @@ -110,7 +109,6 @@ static IDType idtypes[]= { { ID_SCE, "Scene", IDTYPE_FLAGS_ISLINKABLE}, { ID_SCR, "Screen", 0}, { ID_SEQ, "Sequence", 0}, - { ID_SE, "Sector", 0}, { ID_SO, "Sound", IDTYPE_FLAGS_ISLINKABLE}, { ID_TE, "Texture", IDTYPE_FLAGS_ISLINKABLE}, { ID_TXT, "Text", IDTYPE_FLAGS_ISLINKABLE}, diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c2d745bfc8e..114ec9095b1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2184,6 +2184,8 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist) data = ((bKinematicConstraint*)con->data); data->tar = newlibadr(fd, id->lib, data->tar); data->poletar = newlibadr(fd, id->lib, data->poletar); + con->lin_error = 0.f; + con->rot_error = 0.f; } break; case CONSTRAINT_TYPE_TRACKTO: @@ -2331,6 +2333,7 @@ static void lib_link_armature(FileData *fd, Main *main) while(arm) { if(arm->id.flag & LIB_NEEDLINK) { + if (arm->adt) lib_link_animdata(fd, &arm->id, arm->adt); arm->id.flag -= LIB_NEEDLINK; } arm= arm->id.next; @@ -2357,6 +2360,7 @@ static void direct_link_armature(FileData *fd, bArmature *arm) link_list(fd, &arm->bonebase); arm->edbo= NULL; arm->sketch = NULL; + arm->adt= newdataadr(fd, arm->adt); bone=arm->bonebase.first; while (bone) { @@ -3163,6 +3167,8 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles) psys->pathcachebufs.first = psys->pathcachebufs.last = 0; psys->childcachebufs.first = psys->childcachebufs.last = 0; psys->reactevents.first = psys->reactevents.last = 0; + psys->frand = NULL; + psys->pdd = NULL; direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache); @@ -3611,6 +3617,11 @@ static void lib_link_object(FileData *fd, Main *main) else if(act->type==ACT_STATE) { /* bStateActuator *statea = act->data; */ } + else if(act->type==ACT_ARMATURE) { + bArmatureActuator *arma= act->data; + arma->target= newlibadr(fd, ob->id.lib, arma->target); + arma->subtarget= newlibadr(fd, ob->id.lib, arma->subtarget); + } act= act->next; } @@ -3672,6 +3683,10 @@ static void direct_link_pose(FileData *fd, bPose *pose) pchan->iktree.first= pchan->iktree.last= NULL; pchan->path= NULL; } + pose->ikdata = NULL; + if (pose->ikparam != NULL) { + pose->ikparam= newdataadr(fd, pose->ikparam); + } } static void direct_link_modifiers(FileData *fd, ListBase *lb) @@ -4369,6 +4384,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) win->timers.first= win->timers.last= NULL; win->queue.first= win->queue.last= NULL; win->handlers.first= win->handlers.last= NULL; + win->modalhandlers.first= win->modalhandlers.last= NULL; win->subwindows.first= win->subwindows.last= NULL; win->gesture.first= win->gesture.last= NULL; @@ -4683,7 +4699,6 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene) v3d->layact= v3d->localvd->layact; MEM_freeN(v3d->localvd); v3d->localvd= NULL; - v3d->localview= 0; } */ } @@ -4826,7 +4841,6 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) rv3d->ri= NULL; rv3d->sms= NULL; rv3d->smooth_timer= NULL; - rv3d->lastmode= 0; } } @@ -4861,6 +4875,10 @@ static void view3d_split_250(View3D *v3d, ListBase *regions) QUATCOPY(rv3d->viewquat, v3d->viewquat); } } + + /* this was not initialized correct always */ + if(v3d->twtype == 0) + v3d->twtype= V3D_MANIP_TRANSLATE; } static void direct_link_screen(FileData *fd, bScreen *sc) @@ -9346,10 +9364,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) */ //do_versions_ipos_to_animato(main); - /* toolsettings */ - for(scene= main->scene.first; scene; scene= scene->id.next) - scene->r.audio = scene->audio; - /* shader, composit and texture node trees have id.name empty, put something in * to have them show in RNA viewer and accessible otherwise. */ @@ -9363,7 +9377,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) strcpy(sce->nodetree->id.name, "NTComposit Nodetree"); /* move to cameras */ - if(sce->r.scemode & R_PANORAMA) { + if(sce->r.mode & R_PANORAMA) { for(base=sce->base.first; base; base=base->next) { ob= newlibadr(fd, lib, base->object); @@ -9373,7 +9387,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - sce->r.scemode &= ~R_PANORAMA; + sce->r.mode &= ~R_PANORAMA; } } /* and texture trees */ @@ -9687,6 +9701,33 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* put 2.50 compatibility code here until next subversion bump */ { + Scene *sce; + Object *ob; + + for(sce = main->scene.first; sce; sce = sce->id.next) + if(sce->unit.scale_length == 0.0f) + sce->unit.scale_length= 1.0f; + + for(ob = main->object.first; ob; ob = ob->id.next) { + /* fluid-sim stuff */ + FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); + if (fluidmd) fluidmd->fss->fmd = fluidmd; + + /* rotation modes were added, but old objects would now default to being 'quaternion based' */ + ob->rotmode= ROT_MODE_EUL; + } + + for(sce= main->scene.first; sce; sce= sce->id.next) + { + if(sce->audio.main == 0.0) + sce->audio.main = 1.0; + + sce->r.ffcodecdata.audio_mixrate = sce->audio.mixrate; + sce->r.ffcodecdata.audio_volume = sce->audio.main; + sce->audio.distance_model = 2.0; + sce->audio.doppler_factor = 1.0; + sce->audio.speed_of_sound = 343.3; + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ @@ -10402,6 +10443,9 @@ static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm) { Bone *curBone; + if(arm->adt) + expand_animdata(fd, mainvar, arm->adt); + for (curBone = arm->bonebase.first; curBone; curBone=curBone->next) { expand_bones(fd, mainvar, curBone); } @@ -10550,11 +10594,19 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) bObjectActuator *oa= act->data; expand_doit(fd, mainvar, oa->reference); } + else if(act->type==ACT_ADD_OBJECT) { + bAddObjectActuator *aoa= act->data; + expand_doit(fd, mainvar, aoa->ob); + } else if(act->type==ACT_SCENE) { bSceneActuator *sa= act->data; expand_doit(fd, mainvar, sa->camera); expand_doit(fd, mainvar, sa->scene); } + else if(act->type==ACT_2DFILTER) { + bTwoDFilterActuator *tdfa= act->data; + expand_doit(fd, mainvar, tdfa->text); + } else if(act->type==ACT_ACTION) { bActionActuator *aa= act->data; expand_doit(fd, mainvar, aa->act); @@ -10571,6 +10623,14 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) bMessageActuator *ma= act->data; expand_doit(fd, mainvar, ma->toObject); } + else if(act->type==ACT_PARENT) { + bParentActuator *pa= act->data; + expand_doit(fd, mainvar, pa->ob); + } + else if(act->type==ACT_ARMATURE) { + bArmatureActuator *arma= act->data; + expand_doit(fd, mainvar, arma->target); + } act= act->next; } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 98db27182ab..fda35d28d0e 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -712,6 +712,9 @@ static void write_sensors(WriteData *wd, ListBase *lb) case SENS_PROPERTY: writestruct(wd, DATA, "bPropertySensor", 1, sens->data); break; + case SENS_ARMATURE: + writestruct(wd, DATA, "bArmatureSensor", 1, sens->data); + break; case SENS_ACTUATOR: writestruct(wd, DATA, "bActuatorSensor", 1, sens->data); break; @@ -830,6 +833,9 @@ static void write_actuators(WriteData *wd, ListBase *lb) case ACT_STATE: writestruct(wd, DATA, "bStateActuator", 1, act->data); break; + case ACT_ARMATURE: + writestruct(wd, DATA, "bArmatureActuator", 1, act->data); + break; default: ; /* error: don't know how to write this file */ } @@ -1093,8 +1099,16 @@ static void write_pose(WriteData *wd, bPose *pose) for (grp=pose->agroups.first; grp; grp=grp->next) writestruct(wd, DATA, "bActionGroup", 1, grp); + /* write IK param */ + if (pose->ikparam) { + const char *structname = get_ikparam_name(pose); + if (structname) + writestruct(wd, DATA, structname, 1, pose->ikparam); + } + /* Write this pose */ writestruct(wd, DATA, "bPose", 1, pose); + } static void write_defgroups(WriteData *wd, ListBase *defbase) @@ -2116,6 +2130,8 @@ static void write_armatures(WriteData *wd, ListBase *idbase) writestruct(wd, ID_AR, "bArmature", 1, arm); if (arm->id.properties) IDP_WriteProperty(arm->id.properties, wd); + if (arm->adt) write_animdata(wd, arm->adt); + /* Direct data */ bone= arm->bonebase.first; while(bone) { diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index 066d42e723e..d13d7ce2ff2 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -40,6 +40,7 @@ SET(INC ../windowmanager ../nodes ../gpu ../blenfont + ../ikplugin ) IF(WITH_GAMEENGINE) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index e3418fa194f..8f8700cc43b 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -461,6 +461,9 @@ static void acf_object_name(bAnimListElem *ale, char *name) /* check if some setting exists for this channel */ static short acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) { + Base *base= (Base *)ale->data; + Object *ob= base->object; + switch (setting) { /* muted only in NLA */ case ACHANNEL_SETTING_MUTE: @@ -468,7 +471,7 @@ static short acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, int /* visible only in Graph Editor */ case ACHANNEL_SETTING_VISIBLE: - return ((ac) && (ac->spacetype == SPACE_IPO)); + return ((ac) && (ac->spacetype == SPACE_IPO) && (ob->adt)); /* only select and expand supported otherwise */ case ACHANNEL_SETTING_SELECT: @@ -759,7 +762,7 @@ static int acf_fillactd_setting_flag(int setting, short *neg) switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ - return ACT_SELECTED; + return ADT_UI_SELECTED; case ACHANNEL_SETTING_EXPAND: /* expanded */ *neg= 1; @@ -774,13 +777,18 @@ static int acf_fillactd_setting_flag(int setting, short *neg) static void *acf_fillactd_setting_ptr(bAnimListElem *ale, int setting, short *type) { bAction *act= (bAction *)ale->data; + AnimData *adt= ale->adt; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ - GET_ACF_FLAG_PTR(act->flag); + if (adt) { + GET_ACF_FLAG_PTR(adt->flag); + } + else + return 0; case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(act->flag); @@ -998,6 +1006,9 @@ static int acf_dsmat_setting_flag(int setting, short *neg) case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ *neg= 1; return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; default: /* unsupported */ return 0; @@ -1016,6 +1027,7 @@ static void *acf_dsmat_setting_ptr(bAnimListElem *ale, int setting, short *type) case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(ma->flag); + case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (ma->adt) @@ -1067,6 +1079,9 @@ static int acf_dslam_setting_flag(int setting, short *neg) case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ *neg= 1; return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; default: /* unsupported */ return 0; @@ -1085,6 +1100,7 @@ static void *acf_dslam_setting_ptr(bAnimListElem *ale, int setting, short *type) case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(la->flag); + case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (la->adt) @@ -1136,6 +1152,9 @@ static int acf_dscam_setting_flag(int setting, short *neg) case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ *neg= 1; return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; default: /* unsupported */ return 0; @@ -1154,6 +1173,7 @@ static void *acf_dscam_setting_ptr(bAnimListElem *ale, int setting, short *type) case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(ca->flag); + case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (ca->adt) @@ -1205,6 +1225,9 @@ static int acf_dscur_setting_flag(int setting, short *neg) case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ *neg= 1; return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; default: /* unsupported */ return 0; @@ -1223,6 +1246,7 @@ static void *acf_dscur_setting_ptr(bAnimListElem *ale, int setting, short *type) case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(cu->flag); + case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (cu->adt) @@ -1274,6 +1298,9 @@ static int acf_dsskey_setting_flag(int setting, short *neg) case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ *neg= 1; return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; default: /* unsupported */ return 0; @@ -1292,6 +1319,7 @@ static void *acf_dsskey_setting_ptr(bAnimListElem *ale, int setting, short *type case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(key->flag); + case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (key->adt) @@ -1343,6 +1371,9 @@ static int acf_dswor_setting_flag(int setting, short *neg) case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ *neg= 1; return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; default: /* unsupported */ return 0; @@ -1361,6 +1392,7 @@ static void *acf_dswor_setting_ptr(bAnimListElem *ale, int setting, short *type) case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(wo->flag); + case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (wo->adt) @@ -1412,6 +1444,9 @@ static int acf_dspart_setting_flag(int setting, short *neg) case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ *neg= 1; return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; default: /* unsupported */ return 0; @@ -1430,6 +1465,7 @@ static void *acf_dspart_setting_ptr(bAnimListElem *ale, int setting, short *type case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(part->flag); + case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (part->adt) @@ -1482,6 +1518,9 @@ static int acf_dsmball_setting_flag(int setting, short *neg) *neg= 1; return ADT_CURVES_NOT_VISIBLE; + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; + default: /* unsupported */ return 0; } @@ -1499,6 +1538,7 @@ static void *acf_dsmball_setting_ptr(bAnimListElem *ale, int setting, short *typ case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(mb->flag); + case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (mb->adt) @@ -1526,6 +1566,80 @@ static bAnimChannelType ACF_DSMBALL= acf_dsmball_setting_ptr /* pointer for setting */ }; +/* Armature Expander ------------------------------------------- */ + +// TODO: just get this from RNA? +static int acf_dsarm_icon(bAnimListElem *ale) +{ + return ICON_ARMATURE_DATA; +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_dsarm_setting_flag(int setting, short *neg) +{ + /* clear extra return data first */ + *neg= 0; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return ARM_DS_EXPAND; + + case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */ + return ADT_NLA_EVAL_OFF; + + case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ + *neg= 1; + return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; + + default: /* unsupported */ + return 0; + } +} + +/* get pointer to the setting */ +static void *acf_dsarm_setting_ptr(bAnimListElem *ale, int setting, short *type) +{ + bArmature *arm= (bArmature *)ale->data; + + /* clear extra return data first */ + *type= 0; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + GET_ACF_FLAG_PTR(arm->flag); + + case ACHANNEL_SETTING_SELECT: /* selected */ + case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ + case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ + if (arm->adt) + GET_ACF_FLAG_PTR(arm->adt->flag) + else + return NULL; + + default: /* unsupported */ + return NULL; + } +} + +/* metaball expander type define */ +static bAnimChannelType ACF_DSARM= +{ + acf_generic_dataexpand_backdrop,/* backdrop */ + acf_generic_indention_1, /* indent level */ + acf_generic_basic_offset, /* offset */ + + acf_generic_idblock_name, /* name */ + acf_dsarm_icon, /* icon */ + + acf_generic_dataexpand_setting_valid, /* has setting */ + acf_dsarm_setting_flag, /* flag for setting */ + acf_dsarm_setting_ptr /* pointer for setting */ +}; + + /* ShapeKey Entry ------------------------------------------- */ // XXX ... this is currently obsolete... @@ -1709,6 +1823,7 @@ void ANIM_init_channel_typeinfo_data (void) animchannelTypeInfo[type++]= &ACF_DSWOR; /* World Channel */ animchannelTypeInfo[type++]= &ACF_DSPART; /* Particle Channel */ animchannelTypeInfo[type++]= &ACF_DSMBALL; /* MetaBall Channel */ + animchannelTypeInfo[type++]= &ACF_DSARM; /* Armature Channel */ animchannelTypeInfo[type++]= NULL; /* ShapeKey */ // XXX this is no longer used for now... diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 72d8f71bc26..83f5fca5af5 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -91,6 +91,7 @@ /* -------------------------- Exposed API ----------------------------------- */ /* Set the given animation-channel as the active one for the active context */ +// TODO: extend for animdata types... void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type) { ListBase anim_data = {NULL, NULL}; @@ -130,11 +131,29 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE); } break; + + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + { + /* need to verify that this data is valid for now */ + if (ale->adt) { + ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE); + } + } + break; } } /* set active flag */ - if (channel_data != NULL) { + if (channel_data) { switch (channel_type) { case ANIMTYPE_GROUP: { @@ -154,6 +173,23 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int nlt->flag |= NLATRACK_ACTIVE; } break; + + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + { + /* need to verify that this data is valid for now */ + if (ale->adt) + ale->adt->flag |= ADT_UI_ACTIVE; + } + break; } } @@ -174,7 +210,7 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short int filter; /* filter data */ - filter= ANIMFILTER_VISIBLE; + filter= ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS; ANIM_animdata_filter(NULL, &anim_data, filter, data, datatype); /* See if we should be selecting or deselecting */ @@ -189,12 +225,10 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short sel= ACHANNEL_SETFLAG_CLEAR; break; case ANIMTYPE_OBJECT: + #if 0 /* for now, do not take object selection into account, since it gets too annoying */ if (ale->flag & SELECT) sel= ACHANNEL_SETFLAG_CLEAR; - break; - case ANIMTYPE_FILLACTD: - if (ale->flag & ACT_SELECTED) - sel= ACHANNEL_SETFLAG_CLEAR; + #endif break; case ANIMTYPE_GROUP: if (ale->flag & AGRP_SELECTED) @@ -208,6 +242,22 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short if (ale->flag & NLATRACK_SELECTED) sel= ACHANNEL_SETFLAG_CLEAR; break; + + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + { + if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) + sel= ACHANNEL_SETFLAG_CLEAR; + } + break; } } } @@ -220,23 +270,26 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short Scene *scene= (Scene *)ale->data; ACHANNEL_SET_FLAG(scene, sel, SCE_DS_SELECTED); + + if (scene->adt) { + ACHANNEL_SET_FLAG(scene, sel, ADT_UI_SELECTED); + } } break; case ANIMTYPE_OBJECT: + #if 0 /* for now, do not take object selection into account, since it gets too annoying */ { Base *base= (Base *)ale->data; Object *ob= base->object; ACHANNEL_SET_FLAG(base, sel, SELECT); ACHANNEL_SET_FLAG(ob, sel, SELECT); - } - break; - case ANIMTYPE_FILLACTD: - { - bAction *act= (bAction *)ale->data; - ACHANNEL_SET_FLAG(act, sel, ACT_SELECTED); + if (ob->adt) { + ACHANNEL_SET_FLAG(ob, sel, ADT_UI_SELECTED); + } } + #endif break; case ANIMTYPE_GROUP: { @@ -262,6 +315,25 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short nlt->flag &= ~NLATRACK_ACTIVE; } break; + + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + { + /* need to verify that this data is valid for now */ + if (ale->adt) { + ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED); + ale->adt->flag &= ~ADT_UI_ACTIVE; + } + } + break; } } @@ -1310,18 +1382,22 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh } /* action to take depends on what channel we've got */ + // WARNING: must keep this in sync with the equivalent function in nla_channels.c switch (ale->type) { case ANIMTYPE_SCENE: { Scene *sce= (Scene *)ale->data; + AnimData *adt= sce->adt; /* set selection status */ if (selectmode == SELECT_INVERT) { /* swap select */ sce->flag ^= SCE_DS_SELECTED; + if (adt) adt->flag ^= ADT_UI_SELECTED; } else { sce->flag |= SCE_DS_SELECTED; + if (adt) adt->flag |= ADT_UI_SELECTED; } notifierFlags |= ND_ANIMCHAN_SELECT; @@ -1333,34 +1409,75 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh Scene *sce= (Scene *)ads->source; Base *base= (Base *)ale->data; Object *ob= base->object; + AnimData *adt= ob->adt; /* set selection status */ if (selectmode == SELECT_INVERT) { /* swap select */ base->flag ^= SELECT; ob->flag= base->flag; + + if (adt) adt->flag ^= ADT_UI_SELECTED; } else { Base *b; - /* deleselect all */ + /* deselect all */ + // TODO: should this deselect all other types of channels too? for (b= sce->base.first; b; b= b->next) { b->flag &= ~SELECT; b->object->flag= b->flag; + if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED|ADT_UI_ACTIVE); } /* select object now */ base->flag |= SELECT; ob->flag |= SELECT; + if (adt) adt->flag |= ADT_UI_SELECTED; } /* xxx should be ED_base_object_activate(), but we need context pointer for that... */ //set_active_base(base); + if ((adt) && (adt->flag & ADT_UI_SELECTED)) + adt->flag |= ADT_UI_ACTIVE; notifierFlags |= ND_ANIMCHAN_SELECT; } break; + + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + { + /* sanity checking... */ + if (ale->adt) { + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this AnimData block only */ + ale->adt->flag ^= ADT_UI_SELECTED; + } + else { + /* select AnimData block by itself */ + ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + ale->adt->flag |= ADT_UI_SELECTED; + } + + /* set active? */ + if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) + ale->adt->flag |= ADT_UI_ACTIVE; + } + notifierFlags |= ND_ANIMCHAN_SELECT; + } + break; + case ANIMTYPE_GROUP: { bActionGroup *agrp= (bActionGroup *)ale->data; @@ -1572,7 +1689,7 @@ void ED_operatortypes_animchannels(void) void ED_keymap_animchannels(wmWindowManager *wm) { - ListBase *keymap = WM_keymap_listbase(wm, "Animation_Channels", 0, 0); + wmKeyMap *keymap = WM_keymap_find(wm, "Animation_Channels", 0, 0); /* selection */ /* click-select */ diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index af2355b91a5..62341a5d6ae 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -43,6 +43,7 @@ #include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "BKE_utildefines.h" #include "RNA_access.h" @@ -57,26 +58,17 @@ /* ***************** depsgraph calls and anim updates ************* */ /* ***************** only these can be called from editors ******** */ -/* generic update flush, reads from context Screen (layers) and scene */ -/* this is for compliancy, later it can do all windows etc */ void ED_anim_dag_flush_update(const bContext *C) { - Scene *scene= CTX_data_scene(C); - bScreen *screen= CTX_wm_screen(C); - - DAG_scene_flush_update(scene, ED_screen_view3d_layers(screen), 0); + DAG_ids_flush_update(0); } /* flushes changes from object to all relations in scene */ void ED_anim_object_flush_update(const bContext *C, Object *ob) { - Scene *scene= CTX_data_scene(C); - bScreen *screen= CTX_wm_screen(C); - - DAG_object_update_flags(scene, ob, ED_screen_view3d_layers(screen)); + DAG_id_update_flags(&ob->id); } - /* **************************** pose <-> action syncing ******************************** */ /* Summary of what needs to be synced between poses and actions: * 1) Flags diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 6388106fdb5..507bf03e7ef 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -55,6 +55,7 @@ #include "ED_anim_api.h" #include "ED_keyframes_edit.h" +#include "ED_types.h" #include "ED_util.h" #include "WM_api.h" @@ -316,3 +317,52 @@ void ANIM_nla_mapping_apply_fcurve (AnimData *adt, FCurve *fcu, short restore, s } /* *************************************************** */ +/* ANIMATION EDITOR UI-WIDGETS */ + +/* ui button event */ +#define B_REDR 1 + +/* standard header buttons for Animation Editors */ +short ANIM_headerUI_standard_buttons (const bContext *C, bDopeSheet *ads, uiBlock *block, short xco, short yco) +{ + ScrArea *sa= CTX_wm_area(C); + short nlaActive= ((sa) && (sa->spacetype==SPACE_NLA)); + + /* check if the DopeSheet data exists, just in case... */ + if (ads) { + /* more 'generic' filtering options */ + if (nlaActive) uiBlockBeginAlign(block); + uiDefIconButBitI(block, TOG, ADS_FILTER_ONLYSEL, B_REDR, ICON_RESTRICT_SELECT_OFF, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Only display selected Objects"); + if (nlaActive) uiDefIconButBitI(block, TOGN, ADS_FILTER_NLA_NOACT, B_REDR, ICON_ACTION, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Include AnimData blocks with no NLA Data"); + if (nlaActive) uiBlockEndAlign(block); + xco += 5; + + /* datatype based */ + // TODO: only show the datablocks which exist + uiBlockBeginAlign(block); + uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSCE, B_REDR, ICON_SCENE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Display Scene Animation"); + uiDefIconButBitI(block, TOGN, ADS_FILTER_NOWOR, B_REDR, ICON_WORLD_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Display World Animation"); + uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSHAPEKEYS, B_REDR, ICON_SHAPEKEY_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Display ShapeKeys"); + uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMAT, B_REDR, ICON_MATERIAL_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Display Material Data"); + uiDefIconButBitI(block, TOGN, ADS_FILTER_NOLAM, B_REDR, ICON_LAMP_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Display Lamp Data"); + uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCAM, B_REDR, ICON_CAMERA_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Display Camera Data"); + uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCUR, B_REDR, ICON_CURVE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Display Curve Data"); + uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMBA, B_REDR, ICON_META_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Display MetaBall Data"); + uiDefIconButBitI(block, TOGN, ADS_FILTER_NOARM, B_REDR, ICON_ARMATURE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Display Armature Data"); + uiDefIconButBitI(block, TOGN, ADS_FILTER_NOPART, B_REDR, ICON_PARTICLE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(ads->filterflag), 0, 0, 0, 0, "Display Particle Data"); + uiBlockEndAlign(block); + xco += 30; + } + else { + // XXX this case shouldn't happen at all... for now, just pad out same amount of space + printf("ERROR: dopesheet data not available when drawing Animation Editor header \n"); + xco += 11*XIC + 30; + } + + // TODO: include auto-snapping menu here too... + + /* return the width of the buttons */ + return xco; +} + +/* *************************************************** */ diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 55fb1ccace0..13b050e4497 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -52,6 +52,7 @@ #include "DNA_ID.h" #include "DNA_anim_types.h" #include "DNA_action_types.h" +#include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_camera_types.h" #include "DNA_curve_types.h" @@ -412,7 +413,9 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac) }\ } - +/* quick macro to test if an anim-channel representing an AnimData block is suitably active */ +#define ANIMCHANNEL_ACTIVEOK(ale) \ + ( !(filter_mode & ANIMFILTER_ACTIVE) || !(ale->adt) || (ale->adt->flag & ADT_UI_ACTIVE) ) /* quick macro to test if an anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */ #define ANIMCHANNEL_SELOK(test_func) \ @@ -979,10 +982,13 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, /* include material-expand widget? */ // hmm... do we need to store the index of this material in the array anywhere? if (filter_mode & ANIMFILTER_CHANNELS) { - ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma); - if (ale) { - BLI_addtail(anim_data, ale); - items++; + /* check if filtering by active status */ + if ANIMCHANNEL_ACTIVEOK(ma) { + ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } } } @@ -1036,11 +1042,14 @@ static int animdata_filter_dopesheet_particles (ListBase *anim_data, bDopeSheet /* add particle settings? */ if (FILTER_PART_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) { - if ((filter_mode & ANIMFILTER_CHANNELS)){ - ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, base, ANIMTYPE_OBJECT, (ID *)psys->part); - if (ale) { - BLI_addtail(anim_data, ale); - items++; + if ((filter_mode & ANIMFILTER_CHANNELS)) { + /* check if filtering by active status */ + if ANIMCHANNEL_ACTIVEOK(psys->part) { + ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, base, ANIMTYPE_OBJECT, (ID *)psys->part); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } } } @@ -1101,6 +1110,14 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad expanded= FILTER_MBALL_OBJD(mb); } break; + case OB_ARMATURE: /* ------- Armature ---------- */ + { + bArmature *arm= (bArmature *)ob->data; + + type= ANIMTYPE_DSARM; + expanded= FILTER_ARM_OBJD(arm); + } + break; } /* special exception for drivers instead of action */ @@ -1108,9 +1125,12 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad expanded= EXPANDED_DRVD(adt); /* include data-expand widget? */ - if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) { - ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat); - if (ale) BLI_addtail(anim_data, ale); + if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) { + /* check if filtering by active status */ + if ANIMCHANNEL_ACTIVEOK(iat) { + ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat); + if (ale) BLI_addtail(anim_data, ale); + } } /* add object-data animation channels? */ @@ -1140,10 +1160,13 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) { /* check if filtering by selection */ if ANIMCHANNEL_SELOK((base->flag & SELECT)) { - ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, NULL); - if (ale) { - BLI_addtail(anim_data, ale); - items++; + /* check if filtering by active status */ + if ANIMCHANNEL_ACTIVEOK(ob) { + ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, (ID *)ob); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } } } } @@ -1203,8 +1226,21 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B ANIMDATA_FILTER_CASES(key, { /* AnimData blocks - do nothing... */ }, { /* nla */ - /* add NLA tracks */ - items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); + /* include shapekey-expand widget? */ + if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { + /* check if filtering by active status */ + if ANIMCHANNEL_ACTIVEOK(key) { + ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } + } + } + + /* add NLA tracks - only if expanded or so */ + if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) + items += animdata_filter_nla(anim_data, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob); }, { /* drivers */ /* include shapekey-expand widget? */ @@ -1224,10 +1260,13 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B { /* action (keyframes) */ /* include shapekey-expand widget? */ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) { - ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob); - if (ale) { - BLI_addtail(anim_data, ale); - items++; + /* check if filtering by active status */ + if ANIMCHANNEL_ACTIVEOK(key) { + ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob); + if (ale) { + BLI_addtail(anim_data, ale); + items++; + } } } @@ -1297,6 +1336,19 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B } } break; + case OB_ARMATURE: /* ------- Armature ---------- */ + { + bArmature *arm= (bArmature *)ob->data; + + if ((ads->filterflag & ADS_FILTER_NOARM) == 0) { + ANIMDATA_FILTER_CASES(arm, + { /* AnimData blocks - do nothing... */ }, + obdata_ok= 1;, + obdata_ok= 1;, + obdata_ok= 1;) + } + } + break; } if (obdata_ok) items += animdata_filter_dopesheet_obdata(anim_data, ads, base, filter_mode); @@ -1652,6 +1704,23 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);) } break; + case OB_ARMATURE: /* ------- Armature ---------- */ + { + bArmature *arm= (bArmature *)ob->data; + dataOk= 0; + ANIMDATA_FILTER_CASES(arm, + if ((ads->filterflag & ADS_FILTER_NOARM)==0) { + /* for the special AnimData blocks only case, we only need to add + * the block if it is valid... then other cases just get skipped (hence ok=0) + */ + ANIMDATA_ADD_ANIMDATA(arm); + dataOk=0; + }, + dataOk= !(ads->filterflag & ADS_FILTER_NOARM);, + dataOk= !(ads->filterflag & ADS_FILTER_NOARM);, + dataOk= !(ads->filterflag & ADS_FILTER_NOARM);) + } + break; default: /* --- other --- */ dataOk= 0; break; @@ -1734,6 +1803,12 @@ static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int dataOk= ANIMDATA_HAS_KEYS(mb); } break; + case OB_ARMATURE: /* -------- Armature ---------- */ + { + bArmature *arm= (bArmature *)ob->data; + dataOk= ANIMDATA_HAS_KEYS(arm); + } + break; default: /* --- other --- */ dataOk= 0; break; diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index d33eece52c9..bed534ae070 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -458,7 +458,7 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt) mm->event_type= evt->type; /* add temp handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); /* reset frs delta */ RNA_int_set(op->ptr, "frames", 0); @@ -992,7 +992,7 @@ void ED_operatortypes_marker(void) /* called in screen_ops.c:ED_keymap_screen() */ void ED_marker_keymap(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Markers", 0, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Markers", 0, 0); WM_keymap_verify_item(keymap, "MARKER_OT_add", MKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "MARKER_OT_move", EVT_TWEAK_S, KM_ANY, 0, 0); diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index fedbe12c0e6..a4038028062 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -162,7 +162,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event) change_frame_apply(C, op); /* add temp handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -193,7 +193,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event) /* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init * the modal op) doesn't work for some reason */ - if (event->val==0) { + if (event->val==KM_RELEASE) { change_frame_exit(C, op); return OPERATOR_FINISHED; } @@ -399,6 +399,8 @@ void ED_operatortypes_anim(void) WM_operatortype_append(ANIM_OT_add_driver_button); WM_operatortype_append(ANIM_OT_remove_driver_button); + WM_operatortype_append(ANIM_OT_copy_driver_button); + WM_operatortype_append(ANIM_OT_paste_driver_button); WM_operatortype_append(ANIM_OT_add_keyingset_button); WM_operatortype_append(ANIM_OT_remove_keyingset_button); @@ -406,7 +408,7 @@ void ED_operatortypes_anim(void) void ED_keymap_anim(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Animation", 0, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Animation", 0, 0); /* frame management */ /* NOTE: 'ACTIONMOUSE' not 'LEFTMOUSE', as user may have swapped mouse-buttons */ diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 8b9224511ba..363a5a80f00 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -80,6 +80,10 @@ /* Get (or add relevant data to be able to do so) F-Curve from the driver stack, * for the given Animation Data block. This assumes that all the destinations are valid. + * + * - add: 0 - don't add anything if not found, + * 1 - add new Driver FCurve, + * -1 - add new Driver FCurve without driver stuff (for pasting) */ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_index, short add) { @@ -115,11 +119,14 @@ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_ind fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path)); fcu->array_index= array_index; - /* add some new driver data */ - fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); - - /* add simple generator modifier for driver so that there is some visible representation */ - add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); + /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */ + if (add > 0) { + /* add some new driver data */ + fcu->driver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); + + /* add simple generator modifier for driver so that there is some visible representation */ + add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); + } /* just add F-Curve to end of driver list */ BLI_addtail(&adt->drivers, fcu); @@ -144,7 +151,7 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla /* validate pointer first - exit if failure */ RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { - printf("Insert Key: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path); + printf("Add Driver: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path); return 0; } @@ -163,7 +170,7 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla float fval; if (proptype == PROP_BOOLEAN) { - if(!array) val= RNA_property_boolean_get(&ptr, prop); + if (!array) val= RNA_property_boolean_get(&ptr, prop); else val= RNA_property_boolean_get_index(&ptr, prop, array_index); BLI_strncpy(expression, (val)? "True": "False", maxlen); @@ -180,7 +187,6 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short fla BLI_snprintf(expression, maxlen, "%.3f", fval); } - } } @@ -218,6 +224,127 @@ short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, return 0; } +/* ************************************************** */ +/* Driver Management API - Copy/Paste Drivers */ + +/* Copy/Paste Buffer for Driver Data... */ +static FCurve *channeldriver_copypaste_buf = NULL; + +/* This function frees any MEM_calloc'ed copy/paste buffer data */ +// XXX find some header to put this in! +void free_anim_drivers_copybuf (void) +{ + /* free the buffer F-Curve if it exists, as if it were just another F-Curve */ + if (channeldriver_copypaste_buf) + free_fcurve(channeldriver_copypaste_buf); + channeldriver_copypaste_buf= NULL; +} + +/* Checks if there is a driver in the copy/paste buffer */ +short ANIM_driver_can_paste (void) +{ + return (channeldriver_copypaste_buf != NULL); +} + +/* ------------------- */ + +/* Main Driver Management API calls: + * Make a copy of the driver for the specified property on the given ID block + */ +short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short flag) +{ + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + FCurve *fcu; + + /* validate pointer first - exit if failure */ + RNA_id_pointer_create(id, &id_ptr); + if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { + printf("Copy Driver: Could not find Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path); + return 0; + } + + /* try to get F-Curve with Driver */ + fcu= verify_driver_fcurve(id, rna_path, array_index, 0); + + /* clear copy/paste buffer first (for consistency with other copy/paste buffers) */ + free_anim_drivers_copybuf(); + + /* copy this to the copy/paste buf if it exists */ + if (fcu && fcu->driver) { + /* make copies of some info such as the rna_path, then clear this info from the F-Curve temporarily + * so that we don't end up wasting memory storing the path which won't get used ever... + */ + char *tmp_path = fcu->rna_path; + fcu->rna_path= NULL; + + /* make a copy of the F-Curve with */ + channeldriver_copypaste_buf= copy_fcurve(fcu); + + /* restore the path */ + fcu->rna_path= tmp_path; + + /* copied... */ + return 1; + } + + /* done */ + return 0; +} + +/* Main Driver Management API calls: + * Add a new driver for the specified property on the given ID block or replace an existing one + * with the driver + driver-curve data from the buffer + */ +short ANIM_paste_driver (ID *id, const char rna_path[], int array_index, short flag) +{ + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + FCurve *fcu; + + /* validate pointer first - exit if failure */ + RNA_id_pointer_create(id, &id_ptr); + if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { + printf("Paste Driver: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path); + return 0; + } + + /* if the buffer is empty, cannot paste... */ + if (channeldriver_copypaste_buf == NULL) { + printf("Paste Driver: No Driver to paste. \n"); + return 0; + } + + /* create Driver F-Curve, but without data which will be copied across... */ + fcu= verify_driver_fcurve(id, rna_path, array_index, -1); + + if (fcu) { + /* copy across the curve data from the buffer curve + * NOTE: this step needs care to not miss new settings + */ + /* keyframes/samples */ + fcu->bezt= MEM_dupallocN(channeldriver_copypaste_buf->bezt); + fcu->fpt= MEM_dupallocN(channeldriver_copypaste_buf->fpt); + fcu->totvert= channeldriver_copypaste_buf->totvert; + + /* modifiers */ + copy_fmodifiers(&fcu->modifiers, &channeldriver_copypaste_buf->modifiers); + + /* flags - on a per-relevant-flag basis */ + if (channeldriver_copypaste_buf->flag & FCURVE_AUTO_HANDLES) + fcu->flag |= FCURVE_AUTO_HANDLES; + else + fcu->flag &= ~FCURVE_AUTO_HANDLES; + /* extrapolation mode */ + fcu->extend= channeldriver_copypaste_buf->extend; + + /* the 'juicy' stuff - the driver */ + fcu->driver= fcurve_copy_driver(channeldriver_copypaste_buf->driver); + } + + /* done */ + return (fcu != NULL); +} /* ************************************************** */ /* UI-Button Interface */ @@ -272,10 +399,11 @@ void ANIM_OT_add_driver_button (wmOperatorType *ot) /* identifiers */ ot->name= "Add Driver"; ot->idname= "ANIM_OT_add_driver_button"; + ot->description= "Add driver(s) for the property(s) connected represented by the highlighted button."; /* callbacks */ ot->exec= add_driver_button_exec; - //op->poll= ??? + //op->poll= ??? // TODO: need to have some animateable property to do this /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -335,10 +463,11 @@ void ANIM_OT_remove_driver_button (wmOperatorType *ot) /* identifiers */ ot->name= "Remove Driver"; ot->idname= "ANIM_OT_remove_driver_button"; + ot->description= "Remove the driver(s) for the property(s) connected represented by the highlighted button."; /* callbacks */ ot->exec= remove_driver_button_exec; - //op->poll= ??? + //op->poll= ??? // TODO: need to have some driver to be able to do this... /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -347,4 +476,92 @@ void ANIM_OT_remove_driver_button (wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array."); } +/* Copy Driver Button Operator ------------------------ */ + +static int copy_driver_button_exec (bContext *C, wmOperator *op) +{ + PointerRNA ptr; + PropertyRNA *prop= NULL; + char *path; + short success= 0; + int index; + + /* try to create driver using property retrieved from UI */ + memset(&ptr, 0, sizeof(PointerRNA)); + uiAnimContextProperty(C, &ptr, &prop, &index); + + if (ptr.data && prop && RNA_property_animateable(ptr.data, prop)) { + path= RNA_path_from_ID_to_property(&ptr, prop); + + if (path) { + /* only copy the driver for the button that this was involved for */ + success= ANIM_copy_driver(ptr.id.data, path, index, 0); + + MEM_freeN(path); + } + } + + /* since we're just copying, we don't really need to do anything else...*/ + return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; +} + +void ANIM_OT_copy_driver_button (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Copy Driver"; + ot->idname= "ANIM_OT_copy_driver_button"; + ot->description= "Copy the driver for the highlighted button."; + + /* callbacks */ + ot->exec= copy_driver_button_exec; + //op->poll= ??? // TODO: need to have some driver to be able to do this... + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* Paste Driver Button Operator ------------------------ */ + +static int paste_driver_button_exec (bContext *C, wmOperator *op) +{ + PointerRNA ptr; + PropertyRNA *prop= NULL; + char *path; + short success= 0; + int index; + + /* try to create driver using property retrieved from UI */ + memset(&ptr, 0, sizeof(PointerRNA)); + uiAnimContextProperty(C, &ptr, &prop, &index); + + if (ptr.data && prop && RNA_property_animateable(ptr.data, prop)) { + path= RNA_path_from_ID_to_property(&ptr, prop); + + if (path) { + /* only copy the driver for the button that this was involved for */ + success= ANIM_paste_driver(ptr.id.data, path, index, 0); + + MEM_freeN(path); + } + } + + /* since we're just copying, we don't really need to do anything else...*/ + return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED; +} + +void ANIM_OT_paste_driver_button (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Paste Driver"; + ot->idname= "ANIM_OT_paste_driver_button"; + ot->description= "Paste the driver in the copy/paste buffer for the highlighted button."; + + /* callbacks */ + ot->exec= paste_driver_button_exec; + //op->poll= ??? // TODO: need to have some driver to be able to do this... + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /* ************************************************** */ diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index abea38e129e..e8b25f70b06 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -316,7 +316,7 @@ static void set_touched_actkeyblock (ActKeyBlock *ab) /* *************************** Keyframe Drawing *************************** */ /* helper function - find actkeycolumn that occurs on cframe */ -static ActKeyColumn *cfra_find_actkeycolumn (ActKeyColumn *ak, float cframe) +ActKeyColumn *cfra_find_actkeycolumn (ActKeyColumn *ak, float cframe) { /* sanity checks */ if (ak == NULL) @@ -331,6 +331,29 @@ static ActKeyColumn *cfra_find_actkeycolumn (ActKeyColumn *ak, float cframe) return ak; /* match */ } +/* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */ +// FIXME: this is buggy... next() is ignored completely... +ActKeyColumn *cfra_find_nearest_next_ak (ActKeyColumn *ak, float cframe, short next) +{ + ActKeyColumn *akn= NULL; + + /* sanity checks */ + if (ak == NULL) + return NULL; + + /* check if this is a match, or whether it is in some subtree */ + if (cframe < ak->cfra) + akn= cfra_find_nearest_next_ak(ak->left, cframe, next); + else if (cframe > ak->cfra) + akn= cfra_find_nearest_next_ak(ak->right, cframe, next); + + /* if no match found (or found match), just use the current one */ + if (akn == NULL) + return ak; + else + return akn; +} + /* -------- */ /* coordinates for diamond shape */ @@ -396,6 +419,13 @@ void draw_keyframe_shape (float x, float y, float xscale, float hsize, short sel } break; + case BEZT_KEYTYPE_EXTREME: /* redish frames for now */ + { + if (sel) glColor3f(95.0f, 0.5f, 0.5f); + else glColor3f(0.91f, 0.70f, 0.80f); + } + break; + case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames for now */ default: { diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index ac04dc7d1a8..65f7d845b29 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -461,6 +461,13 @@ static short snap_bezier_horizontal(BeztEditData *bed, BezTriple *bezt) return 0; } +static short snap_bezier_value(BeztEditData *bed, BezTriple *bezt) +{ + /* value to snap to is stored in the custom data -> first float value slot */ + if (bezt->f2 & SELECT) + bezt->vec[1][1]= bed->f1; + return 0; +} BeztEditFunc ANIM_editkeyframes_snap(short type) { @@ -476,6 +483,8 @@ BeztEditFunc ANIM_editkeyframes_snap(short type) return snap_bezier_nearestsec; case SNAP_KEYS_HORIZONTAL: /* snap handles to same value */ return snap_bezier_horizontal; + case SNAP_KEYS_VALUE: /* snap to given value */ + return snap_bezier_value; default: /* just in case */ return snap_bezier_nearest; } @@ -685,6 +694,13 @@ static short set_keytype_breakdown(BeztEditData *bed, BezTriple *bezt) return 0; } +static short set_keytype_extreme(BeztEditData *bed, BezTriple *bezt) +{ + if (bezt->f2 & SELECT) + BEZKEYTYPE(bezt)= BEZT_KEYTYPE_EXTREME; + return 0; +} + /* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one */ BeztEditFunc ANIM_editkeyframes_keytype(short code) { @@ -692,6 +708,9 @@ BeztEditFunc ANIM_editkeyframes_keytype(short code) case BEZT_KEYTYPE_BREAKDOWN: /* breakdown */ return set_keytype_breakdown; + case BEZT_KEYTYPE_EXTREME: /* extreme keyframe */ + return set_keytype_extreme; + case BEZT_KEYTYPE_KEYFRAME: /* proper keyframe */ default: return set_keytype_keyframe; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 7135f8802bc..10d45d53761 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -176,85 +176,6 @@ FCurve *verify_fcurve (bAction *act, const char group[], const char rna_path[], /* -------------- BezTriple Insertion -------------------- */ -/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */ -#define BEZT_INSERT_THRESH 0.00001f - -/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu) - * Returns the index to insert at (data already at that index will be offset if replace is 0) - */ -static int binarysearch_bezt_index (BezTriple array[], float frame, int arraylen, short *replace) -{ - int start=0, end=arraylen; - int loopbreaker= 0, maxloop= arraylen * 2; - - /* initialise replace-flag first */ - *replace= 0; - - /* sneaky optimisations (don't go through searching process if...): - * - keyframe to be added is to be added out of current bounds - * - keyframe to be added would replace one of the existing ones on bounds - */ - if ((arraylen <= 0) || (array == NULL)) { - printf("Warning: binarysearch_bezt_index() encountered invalid array \n"); - return 0; - } - else { - /* check whether to add before/after/on */ - float framenum; - - /* 'First' Keyframe (when only one keyframe, this case is used) */ - framenum= array[0].vec[1][0]; - if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { - *replace = 1; - return 0; - } - else if (frame < framenum) - return 0; - - /* 'Last' Keyframe */ - framenum= array[(arraylen-1)].vec[1][0]; - if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { - *replace= 1; - return (arraylen - 1); - } - else if (frame > framenum) - return arraylen; - } - - - /* most of the time, this loop is just to find where to put it - * 'loopbreaker' is just here to prevent infinite loops - */ - for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { - /* compute and get midpoint */ - int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */ - float midfra= array[mid].vec[1][0]; - - /* check if exactly equal to midpoint */ - if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) { - *replace = 1; - return mid; - } - - /* repeat in upper/lower half */ - if (frame > midfra) - start= mid + 1; - else if (frame < midfra) - end= mid - 1; - } - - /* print error if loop-limit exceeded */ - if (loopbreaker == (maxloop-1)) { - printf("Error: binarysearch_bezt_index() was taking too long \n"); - - // include debug info - printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); - } - - /* not found, so return where to place it */ - return start; -} - /* This function adds a given BezTriple to an F-Curve. It will allocate * memory for the array if needed, and will insert the BezTriple into a * suitable place in chronological order. @@ -286,8 +207,13 @@ int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt, short flag) // TODO: perform some other operations? } else { + char oldKeyType= BEZKEYTYPE(fcu->bezt + i); + /* just brutally replace the values */ *(fcu->bezt + i) = *bezt; + + /* special exception for keyframe type - copy value back so that this info isn't lost */ + BEZKEYTYPE(fcu->bezt + i)= oldKeyType; } } } @@ -717,14 +643,14 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_ else if (pchan->bone->parent == NULL) return tmat[3][array_index]; } - else if (strstr(identifier, "euler_rotation")) { + else if (strstr(identifier, "rotation_euler")) { float eul[3]; /* euler-rotation test before standard rotation, as standard rotation does quats */ Mat4ToEulO(tmat, eul, pchan->rotmode); return eul[array_index]; } - else if (strstr(identifier, "rotation")) { + else if (strstr(identifier, "rotation_quaternion")) { float trimat[3][3], quat[4]; Mat3CpyMat4(trimat, tmat); @@ -732,6 +658,7 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_ return quat[array_index]; } + // TODO: axis-angle... } /* as the function hasn't returned yet, read value from system in the default way */ diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 60efcce4e73..81259ae7ced 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -770,7 +770,7 @@ static bBuiltinKeyingSet def_builtin_keyingsets_v3d[] = /* Keying Set - "Rotation" ---------- */ BI_KS_DEFINE_BEGIN("Rotation", 0) BI_KS_PATHS_BEGIN(1) - BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_PCHAN_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) + BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) BI_KS_PATHS_END BI_KS_DEFINE_END, @@ -786,7 +786,7 @@ static bBuiltinKeyingSet def_builtin_keyingsets_v3d[] = BI_KS_DEFINE_BEGIN("LocRot", 0) BI_KS_PATHS_BEGIN(2) BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), - BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_PCHAN_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) + BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) BI_KS_PATHS_END BI_KS_DEFINE_END, @@ -794,7 +794,7 @@ static bBuiltinKeyingSet def_builtin_keyingsets_v3d[] = BI_KS_DEFINE_BEGIN("LocRotScale", 0) BI_KS_PATHS_BEGIN(3) BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), - BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_PCHAN_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), + BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "scale", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) BI_KS_PATHS_END BI_KS_DEFINE_END, @@ -810,7 +810,7 @@ static bBuiltinKeyingSet def_builtin_keyingsets_v3d[] = /* Keying Set - "Rotation" ---------- */ BI_KS_DEFINE_BEGIN("VisualRot", INSERTKEY_MATRIX) BI_KS_PATHS_BEGIN(1) - BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_PCHAN_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) + BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) BI_KS_PATHS_END BI_KS_DEFINE_END, @@ -818,7 +818,7 @@ static bBuiltinKeyingSet def_builtin_keyingsets_v3d[] = BI_KS_DEFINE_BEGIN("VisualLocRot", INSERTKEY_MATRIX) BI_KS_PATHS_BEGIN(2) BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN, "location", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM), - BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_PCHAN_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) + BI_KSP_DEFINE(ID_OB, KSP_TEMPLATE_OBJECT|KSP_TEMPLATE_PCHAN|KSP_TEMPLATE_ROT, "rotation", 0, KSP_FLAG_WHOLE_ARRAY, KSP_GROUP_TEMPLATE_ITEM) BI_KS_PATHS_END BI_KS_DEFINE_END }; @@ -1145,7 +1145,12 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet * int arraylen, i; /* set initial group name */ - groupname= (cks->id) ? cks->id->name+2 : NULL; + if (cks->id == NULL) { + printf("ERROR: Skipping 'Common-Key' Source. No valid ID present.\n"); + continue; + } + else + groupname= cks->id->name+2; /* construct the path */ // FIXME: this currently only works with a few hardcoded cases @@ -1173,14 +1178,24 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet * BLI_dynstr_append(pathds, "."); /* apply some further templates? */ - if ((ksp->templates & KSP_TEMPLATE_PCHAN_ROT) && (cks->pchan)) { - /* if this path is exactly "rotation", and the rotation mode is set to eulers, - * use "euler_rotation" instead so that rotations will be keyed correctly + if (ksp->templates & KSP_TEMPLATE_ROT) { + /* for builtin Keying Sets, this template makes the best fitting path for the + * current rotation mode of the Object / PoseChannel to be used */ - if (strcmp(ksp->rna_path, "rotation")==0 && (cks->pchan->rotmode > 0)) - BLI_dynstr_append(pathds, "euler_rotation"); - else - BLI_dynstr_append(pathds, ksp->rna_path); + if (strcmp(ksp->rna_path, "rotation")==0) { + /* get rotation mode */ + short rotmode= (cks->pchan)? (cks->pchan->rotmode) : + (GS(cks->id->name)==ID_OB)? ( ((Object *)cks->id)->rotmode ) : + (0); + + /* determine path to build */ + if (rotmode == ROT_MODE_QUAT) + BLI_dynstr_append(pathds, "rotation_quaternion"); + else if (rotmode == ROT_MODE_AXISANGLE) + BLI_dynstr_append(pathds, "rotation_axis_angle"); + else + BLI_dynstr_append(pathds, "rotation_euler"); + } } else { /* just directly use the path */ diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 0c8c0e8e644..6f5a5f44d87 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -118,12 +118,20 @@ void SKETCH_OT_select(struct wmOperatorType *ot); /* ******************************************************* */ /* PoseLib */ + void POSELIB_OT_pose_add(struct wmOperatorType *ot); void POSELIB_OT_pose_remove(struct wmOperatorType *ot); void POSELIB_OT_pose_rename(struct wmOperatorType *ot); void POSELIB_OT_browse_interactive(struct wmOperatorType *ot); /* ******************************************************* */ +/* Pose Sliding Tools */ + +void POSE_OT_push(struct wmOperatorType *ot); +void POSE_OT_relax(struct wmOperatorType *ot); +void POSE_OT_breakdown(struct wmOperatorType *ot); + +/* ******************************************************* */ /* editarmature.c */ struct bArmature; struct EditBone; diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 389a0a5174a..fae0b093551 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -196,17 +196,23 @@ void ED_operatortypes_armature(void) WM_operatortype_append(POSELIB_OT_pose_remove); WM_operatortype_append(POSELIB_OT_pose_rename); + /* POSE SLIDING */ + WM_operatortype_append(POSE_OT_push); + WM_operatortype_append(POSE_OT_relax); + WM_operatortype_append(POSE_OT_breakdown); + /* TESTS */ WM_operatortype_append(ARMATURE_OT_test); // XXX temp test for context iterators... to be removed } void ED_keymap_armature(wmWindowManager *wm) { - ListBase *keymap; + wmKeyMap *keymap; wmKeymapItem *kmi; /* Armature ------------------------ */ - keymap= WM_keymap_listbase(wm, "Armature", 0, 0); + keymap= WM_keymap_find(wm, "Armature", 0, 0); + keymap->poll= ED_operator_editarmature; /* only set in editmode armature, by space_view3d listener */ // WM_keymap_add_item(keymap, "ARMATURE_OT_hide", HKEY, KM_PRESS, 0, 0); @@ -278,9 +284,22 @@ void ED_keymap_armature(wmWindowManager *wm) WM_keymap_add_item(keymap, "SKETCH_OT_cancel_stroke", ESCKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "SKETCH_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); + /* sketch poll checks mode */ + WM_keymap_add_item(keymap, "SKETCH_OT_gesture", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "snap", 1); + WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, 0, 0); + kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "snap", 1); + /* Pose ------------------------ */ /* only set in posemode, by space_view3d listener */ - keymap= WM_keymap_listbase(wm, "Pose", 0, 0); + keymap= WM_keymap_find(wm, "Pose", 0, 0); + keymap->poll= ED_operator_posemode; + + // XXX: set parent is object-based operator, but it should also be available here... + WM_keymap_add_item(keymap, "OBJECT_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "POSE_OT_hide", HKEY, KM_PRESS, 0, 0); kmi= WM_keymap_add_item(keymap, "POSE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0); @@ -294,7 +313,6 @@ void ED_keymap_armature(wmWindowManager *wm) WM_keymap_add_item(keymap, "POSE_OT_loc_clear", GKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "POSE_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0); - // for now, we include hotkeys for copy/paste WM_keymap_add_item(keymap, "POSE_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0); kmi= WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); @@ -354,5 +372,11 @@ void ED_keymap_armature(wmWindowManager *wm) WM_keymap_add_item(keymap, "POSELIB_OT_pose_add", LKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "POSELIB_OT_pose_remove", LKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "POSELIB_OT_pose_rename", LKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + + /* Pose -> Pose Sliding ------------- */ + /* only set in posemode, by space_view3d listener */ + WM_keymap_add_item(keymap, "POSE_OT_push", EKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "POSE_OT_relax", EKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "POSE_OT_breakdown", EKEY, KM_PRESS, KM_SHIFT, 0); } diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 7d196d23c98..402715dbb02 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -1736,7 +1736,7 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op) ED_armature_sync_selection(arm->edbo); - WM_event_add_notifier(C, NC_OBJECT, obedit); + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit); return OPERATOR_FINISHED; } @@ -2539,6 +2539,8 @@ EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, ListBase *edit VECCOPY(channew->limitmax, chanold->limitmax); VECCOPY(channew->stiffness, chanold->stiffness); channew->ikstretch= chanold->ikstretch; + channew->ikrotweight= chanold->ikrotweight; + channew->iklinweight= chanold->iklinweight; /* constraints */ listnew = &channew->constraints; @@ -2630,6 +2632,9 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op) /* copy transform locks */ channew->protectflag = chanold->protectflag; + /* copy rotation mode */ + channew->rotmode = chanold->rotmode; + /* copy bone group */ channew->agrp_index= chanold->agrp_index; @@ -2639,6 +2644,8 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op) VECCOPY(channew->limitmax, chanold->limitmax); VECCOPY(channew->stiffness, chanold->stiffness); channew->ikstretch= chanold->ikstretch; + channew->ikrotweight= chanold->ikrotweight; + channew->iklinweight= chanold->iklinweight; /* constraints */ listnew = &channew->constraints; @@ -3441,7 +3448,8 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) else VecAddf(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z - WM_event_add_notifier(C, NC_OBJECT, obedit); + /* note, notifier might evolve */ + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit); return OPERATOR_FINISHED; } @@ -3930,7 +3938,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op) ED_armature_sync_selection(arm->edbo); /* note, notifier might evolve */ - WM_event_add_notifier(C, NC_OBJECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob); return OPERATOR_FINISHED; } @@ -4330,7 +4338,7 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor } /* in weightpaint we select the associated vertex group too */ - if (ob->mode & OB_MODE_WEIGHT_PAINT) { + if (OBACT && OBACT->mode & OB_MODE_WEIGHT_PAINT) { if (nearBone->flag & BONE_ACTIVE) { ED_vgroup_select_by_name(OBACT, nearBone->name); DAG_id_flush_update(&OBACT->id, OB_RECALC_DATA); @@ -4854,7 +4862,7 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) if (pchan->protectflag & OB_LOCK_ROT4D) { /* perform clamping on a component by component basis */ if ((pchan->protectflag & OB_LOCK_ROTW) == 0) - pchan->quat[0]= (pchan->rotmode == PCHAN_ROT_AXISANGLE) ? 0.0f : 1.0f; + pchan->quat[0]= (pchan->rotmode == ROT_MODE_AXISANGLE) ? 0.0f : 1.0f; if ((pchan->protectflag & OB_LOCK_ROTX) == 0) pchan->quat[1]= 0.0f; if ((pchan->protectflag & OB_LOCK_ROTY) == 0) @@ -4866,11 +4874,11 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) /* perform clamping using euler form (3-components) */ float eul[3], oldeul[3], quat1[4]; - if (pchan->rotmode == PCHAN_ROT_QUAT) { + if (pchan->rotmode == ROT_MODE_QUAT) { QUATCOPY(quat1, pchan->quat); QuatToEul(pchan->quat, oldeul); } - else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + else if (pchan->rotmode == ROT_MODE_AXISANGLE) { AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT); } else { @@ -4886,14 +4894,14 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) if (pchan->protectflag & OB_LOCK_ROTZ) eul[2]= oldeul[2]; - if (pchan->rotmode == PCHAN_ROT_QUAT) { + if (pchan->rotmode == ROT_MODE_QUAT) { EulToQuat(eul, pchan->quat); /* quaternions flip w sign to accumulate rotations correctly */ if ((quat1[0]<0.0f && pchan->quat[0]>0.0f) || (quat1[0]>0.0f && pchan->quat[0]<0.0f)) { QuatMulf(pchan->quat, -1.0f); } } - else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + else if (pchan->rotmode == ROT_MODE_AXISANGLE) { AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], oldeul, EULER_ORDER_DEFAULT); } else { @@ -4902,11 +4910,11 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) } } else { - if (pchan->rotmode == PCHAN_ROT_QUAT) { + if (pchan->rotmode == ROT_MODE_QUAT) { pchan->quat[1]=pchan->quat[2]=pchan->quat[3]= 0.0f; pchan->quat[0]= 1.0f; } - else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + else if (pchan->rotmode == ROT_MODE_AXISANGLE) { /* by default, make rotation of 0 radians around y-axis (roll) */ pchan->quat[0]=pchan->quat[1]=pchan->quat[3]= 0.0f; pchan->quat[2]= 1.0f; diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c index 16e78f7c8d1..4d65059c4c6 100644 --- a/source/blender/editors/armature/editarmature_retarget.c +++ b/source/blender/editors/armature/editarmature_retarget.c @@ -2716,7 +2716,6 @@ static void finishRetarget(RigGraph *rigg) static void adjustGraphs(bContext *C, RigGraph *rigg) { - Scene *scene = CTX_data_scene(C); bArmature *arm= rigg->ob->data; RigArc *arc; @@ -2739,7 +2738,6 @@ static void adjustGraphs(bContext *C, RigGraph *rigg) static void retargetGraphs(bContext *C, RigGraph *rigg) { - Scene *scene = CTX_data_scene(C); bArmature *arm= rigg->ob->data; ReebGraph *reebg = rigg->link_mesh; RigNode *inode; diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index 79d3d7b1366..74876691dac 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -1814,7 +1814,7 @@ int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch) VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p); VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p); - angle = VecAngle2(s1, s2); + angle = RAD2DEG(VecAngle2(s1, s2)); if (angle > 60 && angle < 120) { @@ -1932,7 +1932,7 @@ int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch) VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p); VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p); - angle = VecAngle2(s1, s2); + angle = RAD2DEG(VecAngle2(s1, s2)); if (angle > 120) { @@ -2064,7 +2064,7 @@ int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch) VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p); } - angle = VecAngle2(start_v, end_v); + angle = RAD2DEG(VecAngle2(start_v, end_v)); if (angle > 120) { @@ -2618,7 +2618,7 @@ static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event) sk_draw_stroke(C, sketch, sketch->active_stroke, dd, snap); - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -2644,7 +2644,7 @@ static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event) sk_start_draw_gesture(sketch); sk_draw_stroke(C, sketch, sketch->gesture, dd, snap); - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -2675,7 +2675,7 @@ static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short retval = OPERATOR_CANCELLED; break; case LEFTMOUSE: - if (event->val == 0) + if (event->val == KM_RELEASE) { if (gesture == 0) { diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 436048f5427..82843a49851 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -177,9 +177,9 @@ static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3 t2= cotan_weight(v2, v3, v1); t3= cotan_weight(v3, v1, v2); - if(VecAngle3(v2, v1, v3) > 90) obtuse= 1; - else if(VecAngle3(v1, v2, v3) > 90) obtuse= 2; - else if(VecAngle3(v1, v3, v2) > 90) obtuse= 3; + if(RAD2DEG(VecAngle3(v2, v1, v3)) > 90) obtuse= 1; + else if(RAD2DEG(VecAngle3(v1, v2, v3)) > 90) obtuse= 2; + else if(RAD2DEG(VecAngle3(v1, v3, v2)) > 90) obtuse= 3; if (obtuse > 0) { area= AreaT3Dfl(v1, v2, v3); diff --git a/source/blender/editors/armature/poseSlide.c b/source/blender/editors/armature/poseSlide.c new file mode 100644 index 00000000000..c73208c54c2 --- /dev/null +++ b/source/blender/editors/armature/poseSlide.c @@ -0,0 +1,936 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009, Blender Foundation, Joshua Leung + * This is a new part of Blender + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stddef.h> +#include <string.h> +#include <math.h> +#include <float.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_dynstr.h" +#include "BLI_dlrbTree.h" + +#include "DNA_listBase.h" +#include "DNA_anim_types.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_scene_types.h" +#include "DNA_userdef_types.h" + +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_depsgraph.h" +#include "BKE_fcurve.h" +#include "BKE_object.h" + +#include "BKE_global.h" +#include "BKE_context.h" +#include "BKE_report.h" +#include "BKE_utildefines.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "BIF_gl.h" + +#include "ED_anim_api.h" +#include "ED_armature.h" +#include "ED_keyframes_draw.h" +#include "ED_keyframing.h" +#include "ED_keyframes_edit.h" +#include "ED_screen.h" + +#include "armature_intern.h" + +/* **************************************************** */ +/* == POSE 'SLIDING' TOOLS == + * + * A) Push & Relax, Breakdowner + * These tools provide the animator with various capabilities + * for interactively controlling the spacing of poses, but also + * for 'pushing' and/or 'relaxing' extremes as they see fit. + * + * B) Pose Sculpting + * This is yet to be implemented, but the idea here is to use + * sculpting techniques to make it easier to pose rigs by allowing + * rigs to be manipulated using a familiar paint-based interface. + */ +/* **************************************************** */ +/* A) Push & Relax, Breakdowner */ + +/* Temporary data shared between these operators */ +typedef struct tPoseSlideOp { + Scene *scene; /* current scene */ + ARegion *ar; /* region that we're operating in (needed for */ + Object *ob; /* active object that Pose Info comes from */ + bArmature *arm; /* armature for pose */ + + ListBase pfLinks; /* links between posechannels and f-curves */ + DLRBT_Tree keys; /* binary tree for quicker searching for keyframes (when applicable) */ + + KeyingSet *ks_loc; /* builtin KeyingSet for keyframing locations */ + KeyingSet *ks_rot; /* builtin KeyingSet for keyframing rotations */ + KeyingSet *ks_scale;/* builtin KeyingSet for keyframing scale */ + + int cframe; /* current frame number */ + int prevFrame; /* frame before current frame (blend-from) */ + int nextFrame; /* frame after current frame (blend-to) */ + + int mode; /* sliding mode (ePoseSlide_Modes) */ + int flag; // unused for now, but can later get used for storing runtime settings.... + + float percentage; /* 0-1 value for determining the influence of whatever is relevant */ +} tPoseSlideOp; + +/* Pose Sliding Modes */ +typedef enum ePoseSlide_Modes { + POSESLIDE_PUSH = 0, /* exaggerate the pose... */ + POSESLIDE_RELAX, /* soften the pose... */ + POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */ +} ePoseSlide_Modes; + +/* Temporary data linking PoseChannels with the F-Curves they affect */ +typedef struct tPChanFCurveLink { + struct tPChanFCurveLink *next, *prev; + + ListBase fcurves; /* F-Curves for this PoseChannel */ + bPoseChannel *pchan; /* Pose Channel which data is attached to */ + + char *pchan_path; /* RNA Path to this Pose Channel (needs to be freed when we're done) */ + + float oldloc[3]; /* transform values at start of operator (to be restored before each modal step) */ + float oldrot[3]; + float oldscale[3]; + float oldquat[4]; +} tPChanFCurveLink; + +/* ------------------------------------ */ + +/* operator init */ +static int pose_slide_init (bContext *C, wmOperator *op, short mode) +{ + tPoseSlideOp *pso; + bAction *act= NULL; + + /* init slide-op data */ + pso= op->customdata= MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp"); + + /* get info from context */ + pso->scene= CTX_data_scene(C); + pso->ob= CTX_data_active_object(C); + pso->arm= (pso->ob)? pso->ob->data : NULL; + pso->ar= CTX_wm_region(C); /* only really needed when doing modal() */ + + pso->cframe= pso->scene->r.cfra; + pso->mode= mode; + + /* set range info from property values - these may get overridden for the invoke() */ + pso->percentage= RNA_float_get(op->ptr, "percentage"); + pso->prevFrame= RNA_int_get(op->ptr, "prev_frame"); + pso->nextFrame= RNA_int_get(op->ptr, "next_frame"); + + /* check the settings from the context */ + if (ELEM4(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action)) + return 0; + else + act= pso->ob->adt->action; + + /* for each Pose-Channel which gets affected, get the F-Curves for that channel + * and set the relevant transform flags... + */ + CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) + { + ListBase curves = {NULL, NULL}; + int transFlags = action_get_item_transforms(act, pso->ob, pchan, &curves); + + pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); + + /* check if any transforms found... */ + if (transFlags) { + /* make new linkage data */ + tPChanFCurveLink *pfl= MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink"); + PointerRNA ptr; + + pfl->fcurves= curves; + pfl->pchan= pchan; + + /* get the RNA path to this pchan - this needs to be freed! */ + RNA_pointer_create((ID *)pso->ob, &RNA_PoseChannel, pchan, &ptr); + pfl->pchan_path= RNA_path_from_ID_to_struct(&ptr); + + /* add linkage data to operator data */ + BLI_addtail(&pso->pfLinks, pfl); + + /* set pchan's transform flags */ + if (transFlags & ACT_TRANS_LOC) + pchan->flag |= POSE_LOC; + if (transFlags & ACT_TRANS_ROT) + pchan->flag |= POSE_ROT; + if (transFlags & ACT_TRANS_SCALE) + pchan->flag |= POSE_SIZE; + + /* store current transforms */ + VECCOPY(pfl->oldloc, pchan->loc); + VECCOPY(pfl->oldrot, pchan->eul); + VECCOPY(pfl->oldscale, pchan->size); + QUATCOPY(pfl->oldquat, pchan->quat); + } + } + CTX_DATA_END; + + /* set depsgraph flags */ + /* make sure the lock is set OK, unlock can be accidentally saved? */ + pso->ob->pose->flag |= POSE_LOCKED; + pso->ob->pose->flag &= ~POSE_DO_UNLOCK; + + /* do basic initialise of RB-BST used for finding keyframes, but leave the filling of it up + * to the caller of this (usually only invoke() will do it, to make things more efficient). + */ + BLI_dlrbTree_init(&pso->keys); + + /* get builtin KeyingSets */ + pso->ks_loc= ANIM_builtin_keyingset_get_named(NULL, "Location"); + pso->ks_rot= ANIM_builtin_keyingset_get_named(NULL, "Rotation"); + pso->ks_scale= ANIM_builtin_keyingset_get_named(NULL, "Scaling"); + + /* return status is whether we've got all the data we were requested to get */ + return 1; +} + +/* exiting the operator - free data */ +static void pose_slide_exit (bContext *C, wmOperator *op) +{ + tPoseSlideOp *pso= op->customdata; + + /* if data exists, clear its data and exit */ + if (pso) { + tPChanFCurveLink *pfl, *pfln=NULL; + + /* free the temp pchan links and their data */ + for (pfl= pso->pfLinks.first; pfl; pfl= pfln) { + pfln= pfl->next; + + /* free list of F-Curve reference links */ + BLI_freelistN(&pfl->fcurves); + + /* free pchan RNA Path */ + MEM_freeN(pfl->pchan_path); + + /* free link itself */ + BLI_freelinkN(&pso->pfLinks, pfl); + } + + /* free RB-BST for keyframes (if it contained data) */ + BLI_dlrbTree_free(&pso->keys); + + /* free data itself */ + MEM_freeN(pso); + } + + /* cleanup */ + op->customdata= NULL; +} + +/* ------------------------------------ */ + +/* helper for apply() / reset() - refresh the data */ +static void pose_slide_refresh (bContext *C, tPoseSlideOp *pso) +{ + /* old optimize trick... this enforces to bypass the depgraph + * - note: code copied from transform_generics.c -> recalcData() + */ + // FIXME: shouldn't this use the builtin stuff? + if ((pso->arm->flag & ARM_DELAYDEFORM)==0) + DAG_id_flush_update(&pso->ob->id, OB_RECALC_DATA); /* sets recalc flags */ + else + where_is_pose(pso->scene, pso->ob); + + /* note, notifier might evolve */ + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, pso->ob); + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); +} + +/* helper for apply() callabcks - find the next F-Curve with matching path... */ +static LinkData *find_next_fcurve_link (ListBase *fcuLinks, LinkData *prev, char *path) +{ + LinkData *first= (prev)? prev->next : (fcuLinks)? fcuLinks->first : NULL; + LinkData *ld; + + /* check each link to see if the linked F-Curve has a matching path */ + for (ld= first; ld; ld= ld->next) { + FCurve *fcu= (FCurve *)ld->data; + + /* check if paths match */ + if (strcmp(path, fcu->rna_path) == 0) + return ld; + } + + /* none found */ + return NULL; +} + +/* helper for apply() - perform sliding for some 3-element vector */ +static void pose_slide_apply_vec3 (tPoseSlideOp *pso, tPChanFCurveLink *pfl, float vec[3], char *propName) +{ + LinkData *ld=NULL; + char *path=NULL; + float cframe; + + /* get the path to use... */ + path= BLI_sprintfN("%s.%s", pfl->pchan_path, propName); + + /* get the current frame number */ + cframe= (float)pso->cframe; + + /* using this path, find each matching F-Curve for the variables we're interested in */ + while ( (ld= find_next_fcurve_link(&pfl->fcurves, ld, path)) ) { + FCurve *fcu= (FCurve *)ld->data; + float sVal, eVal; + float w1, w2; + int ch; + + /* get keyframe values for endpoint poses to blend with */ + /* previous/start */ + sVal= evaluate_fcurve(fcu, (float)pso->prevFrame); + /* next/end */ + eVal= evaluate_fcurve(fcu, (float)pso->nextFrame); + + /* get channel index */ + ch= fcu->array_index; + + /* calculate the relative weights of the endpoints */ + if (pso->mode == POSESLIDE_BREAKDOWN) { + /* get weights from the percentage control */ + w1= pso->percentage; /* this must come second */ + w2= 1.0f - w1; /* this must come first */ + } + else { + /* - these weights are derived from the relative distance of these + * poses from the current frame + * - they then get normalised so that they only sum up to 1 + */ + float wtot; + + w1 = cframe - (float)pso->prevFrame; + w2 = (float)pso->nextFrame - cframe; + + wtot = w1 + w2; + w1 = (w1/wtot); + w2 = (w2/wtot); + } + + /* depending on the mode, calculate the new value + * - in all of these, the start+end values are multiplied by w2 and w1 (respectively), + * since multiplication in another order would decrease the value the current frame is closer to + */ + switch (pso->mode) { + case POSESLIDE_PUSH: /* make the current pose more pronounced */ + { + /* perform a weighted average here, favouring the middle pose + * - numerator should be larger than denominator to 'expand' the result + * - perform this weighting a number of times given by the percentage... + */ + int iters= (int)ceil(10.0f*pso->percentage); // TODO: maybe a sensitivity ctrl on top of this is needed + + while (iters-- > 0) { + vec[ch]= ( -((sVal * w2) + (eVal * w1)) + (vec[ch] * 6.0f) ) / 5.0f; + } + } + break; + + case POSESLIDE_RELAX: /* make the current pose more like its surrounding ones */ + { + /* perform a weighted average here, favouring the middle pose + * - numerator should be smaller than denominator to 'relax' the result + * - perform this weighting a number of times given by the percentage... + */ + int iters= (int)ceil(10.0f*pso->percentage); // TODO: maybe a sensitivity ctrl on top of this is needed + + while (iters-- > 0) { + vec[ch]= ( ((sVal * w2) + (eVal * w1)) + (vec[ch] * 5.0f) ) / 6.0f; + } + } + break; + + case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */ + { + /* perform simple linear interpolation - coefficient for start must come from pso->percentage... */ + // TODO: make this use some kind of spline interpolation instead? + vec[ch]= ((sVal * w2) + (eVal * w1)); + } + break; + } + + } + + /* free the temp path we got */ + MEM_freeN(path); +} + +/* helper for apply() - perform sliding for quaternion rotations (using quat blending) */ +static void pose_slide_apply_quat (tPoseSlideOp *pso, tPChanFCurveLink *pfl) +{ + FCurve *fcu_w=NULL, *fcu_x=NULL, *fcu_y=NULL, *fcu_z=NULL; + bPoseChannel *pchan= pfl->pchan; + LinkData *ld=NULL; + char *path=NULL; + float cframe; + + /* get the path to use - this should be quaternion rotations only (needs care) */ + path= BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation"); + + /* get the current frame number */ + cframe= (float)pso->cframe; + + /* using this path, find each matching F-Curve for the variables we're interested in */ + while ( (ld= find_next_fcurve_link(&pfl->fcurves, ld, path)) ) { + FCurve *fcu= (FCurve *)ld->data; + + /* assign this F-Curve to one of the relevant pointers... */ + switch (fcu->array_index) { + case 3: /* z */ + fcu_z= fcu; + break; + case 2: /* y */ + fcu_y= fcu; + break; + case 1: /* x */ + fcu_x= fcu; + break; + case 0: /* w */ + fcu_w= fcu; + break; + } + } + + /* only if all channels exist, proceed */ + if (fcu_w && fcu_x && fcu_y && fcu_z) { + float quat_prev[4], quat_next[4]; + + /* get 2 quats */ + quat_prev[0] = evaluate_fcurve(fcu_w, pso->prevFrame); + quat_prev[1] = evaluate_fcurve(fcu_x, pso->prevFrame); + quat_prev[2] = evaluate_fcurve(fcu_y, pso->prevFrame); + quat_prev[3] = evaluate_fcurve(fcu_z, pso->prevFrame); + + quat_next[0] = evaluate_fcurve(fcu_w, pso->nextFrame); + quat_next[1] = evaluate_fcurve(fcu_x, pso->nextFrame); + quat_next[2] = evaluate_fcurve(fcu_y, pso->nextFrame); + quat_next[3] = evaluate_fcurve(fcu_z, pso->nextFrame); + + /* perform blending */ + if (pso->mode == POSESLIDE_BREAKDOWN) { + /* just perform the interpol between quat_prev and quat_next using pso->percentage as a guide */ + QuatInterpol(pchan->quat, quat_prev, quat_next, pso->percentage); + } + else { + float quat_interp[4], quat_orig[4]; + int iters= (int)ceil(10.0f*pso->percentage); // TODO: maybe a sensitivity ctrl on top of this is needed + + /* perform this blending several times until a satisfactory result is reached */ + while (iters-- > 0) { + /* calculate the interpolation between the endpoints */ + QuatInterpol(quat_interp, quat_prev, quat_next, (cframe-pso->prevFrame) / (pso->nextFrame-pso->prevFrame) ); + + /* make a copy of the original rotation */ + QUATCOPY(quat_orig, pchan->quat); + + /* tricky interpolations - mode-dependent blending between original and new */ + if (pso->mode == POSESLIDE_RELAX) // xxx this was the original code, so should work fine + QuatInterpol(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f); + else // I'm just guessing here... + QuatInterpol(pchan->quat, quat_orig, quat_interp, 6.0f/5.0f); + } + } + } + + /* free the path now */ + MEM_freeN(path); +} + +/* apply() - perform the pose sliding based on weighting various poses */ +static void pose_slide_apply (bContext *C, wmOperator *op, tPoseSlideOp *pso) +{ + tPChanFCurveLink *pfl; + + /* sanitise the frame ranges */ + if (pso->prevFrame == pso->nextFrame) { + /* move out one step either side */ + pso->prevFrame--; + pso->nextFrame++; + } + + /* for each link, handle each set of transforms */ + for (pfl= pso->pfLinks.first; pfl; pfl= pfl->next) { + /* valid transforms for each PoseChannel should have been noted already + * - sliding the pose should be a straightforward exercise for location+rotation, + * but rotations get more complicated since we may want to use quaternion blending + * for quaternions instead... + */ + bPoseChannel *pchan= pfl->pchan; + + if (pchan->flag & POSE_LOC) { + /* calculate these for the 'location' vector, and use location curves */ + pose_slide_apply_vec3(pso, pfl, pchan->loc, "location"); + } + + if (pchan->flag & POSE_SIZE) { + /* calculate these for the 'scale' vector, and use scale curves */ + pose_slide_apply_vec3(pso, pfl, pchan->size, "scale"); + } + + if (pchan->flag & POSE_ROT) { + /* everything depends on the rotation mode */ + if (pchan->rotmode > 0) { + /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */ + pose_slide_apply_vec3(pso, pfl, pchan->eul, "rotation_euler"); + } + else if (pchan->rotmode == ROT_MODE_AXISANGLE) { + // TODO: need to figure out how to do this! + } + else { + /* quaternions - use quaternion blending */ + pose_slide_apply_quat(pso, pfl); + } + } + } + + /* depsgraph updates + redraws */ + pose_slide_refresh(C, pso); +} + +/* perform autokeyframing after changes were made + confirmed */ +static void pose_slide_autoKeyframe (bContext *C, tPoseSlideOp *pso) +{ + /* insert keyframes as necessary if autokeyframing */ + if (autokeyframe_cfra_can_key(pso->scene, &pso->ob->id)) { + bCommonKeySrc cks; + ListBase dsources = {&cks, &cks}; + tPChanFCurveLink *pfl; + + /* init common-key-source for use by KeyingSets */ + memset(&cks, 0, sizeof(bCommonKeySrc)); + cks.id= &pso->ob->id; + + /* iterate over each pose-channel affected, applying the changes */ + for (pfl= pso->pfLinks.first; pfl; pfl= pfl->next) { + bPoseChannel *pchan= pfl->pchan; + /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */ + cks.pchan= pchan; + + /* insert keyframes */ + if (pchan->flag & POSE_LOC) + modify_keyframes(C, &dsources, NULL, pso->ks_loc, MODIFYKEY_MODE_INSERT, (float)pso->cframe); + if (pchan->flag & POSE_ROT) + modify_keyframes(C, &dsources, NULL, pso->ks_rot, MODIFYKEY_MODE_INSERT, (float)pso->cframe); + if (pchan->flag & POSE_SIZE) + modify_keyframes(C, &dsources, NULL, pso->ks_scale, MODIFYKEY_MODE_INSERT, (float)pso->cframe); + } + } +} + +/* reset changes made to current pose */ +static void pose_slide_reset (bContext *C, tPoseSlideOp *pso) +{ + tPChanFCurveLink *pfl; + + /* iterate over each pose-channel affected, restoring all channels to their original values */ + for (pfl= pso->pfLinks.first; pfl; pfl= pfl->next) { + bPoseChannel *pchan= pfl->pchan; + + /* just copy all the values over regardless of whether they changed or not */ + VECCOPY(pchan->loc, pfl->oldloc); + VECCOPY(pchan->eul, pfl->oldrot); + VECCOPY(pchan->size, pfl->oldscale); + QUATCOPY(pchan->quat, pfl->oldquat); + } +} + +/* ------------------------------------ */ + +/* common code for invoke() methods */ +static int pose_slide_invoke_common (bContext *C, wmOperator *op, tPoseSlideOp *pso) +{ + tPChanFCurveLink *pfl; + AnimData *adt= pso->ob->adt; + wmWindow *win= CTX_wm_window(C); + + /* for each link, add all its keyframes to the search tree */ + for (pfl= pso->pfLinks.first; pfl; pfl= pfl->next) { + LinkData *ld; + + /* do this for each F-Curve */ + for (ld= pfl->fcurves.first; ld; ld= ld->next) { + FCurve *fcu= (FCurve *)ld->data; + fcurve_to_keylist(adt, fcu, &pso->keys, NULL); + } + } + + /* consolidate these keyframes, and figure out the nearest ones */ + BLI_dlrbTree_linkedlist_sync(&pso->keys); + + /* cancel if no keyframes found... */ + if (pso->keys.root) { + ActKeyColumn *ak; + + /* firstly, check if the current frame is a keyframe... */ + ak= cfra_find_actkeycolumn(pso->keys.root, pso->cframe); + + if (ak == NULL) { + /* current frame is not a keyframe, so search */ + ActKeyColumn *pk= cfra_find_nearest_next_ak(pso->keys.root, pso->cframe, 0); + ActKeyColumn *nk= cfra_find_nearest_next_ak(pso->keys.root, pso->cframe, 1); + + /* check if we found good keyframes */ + if ((pk == nk) && (pk != NULL)) { + if (pk->cfra < pso->cframe) + nk= nk->next; + else if (nk->cfra > pso->cframe) + pk= pk->prev; + } + + /* new set the frames */ + /* prev frame */ + pso->prevFrame= (pk)? (pk->cfra) : (pso->cframe - 1); + RNA_int_set(op->ptr, "prev_frame", pso->prevFrame); + /* next frame */ + pso->nextFrame= (nk)? (nk->cfra) : (pso->cframe + 1); + RNA_int_set(op->ptr, "next_frame", pso->nextFrame); + } + else { + /* current frame itself is a keyframe, so just take keyframes on either side */ + /* prev frame */ + pso->prevFrame= (ak->prev)? (ak->prev->cfra) : (pso->cframe - 1); + RNA_int_set(op->ptr, "prev_frame", pso->prevFrame); + /* next frame */ + pso->nextFrame= (ak->next)? (ak->next->cfra) : (pso->cframe + 1); + RNA_int_set(op->ptr, "next_frame", pso->nextFrame); + } + } + else { + BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between."); + return OPERATOR_CANCELLED; + } + + /* initial apply for operator... */ + // TODO: need to calculate percentage for initial round too... + pose_slide_apply(C, op, pso); + + /* depsgraph updates + redraws */ + pose_slide_refresh(C, pso); + + /* set cursor to indicate modal */ + WM_cursor_modal(win, BC_EW_SCROLLCURSOR); + + /* add a modal handler for this operator */ + WM_event_add_modal_handler(C, op); + return OPERATOR_RUNNING_MODAL; +} + +/* common code for modal() */ +static int pose_slide_modal (bContext *C, wmOperator *op, wmEvent *evt) +{ + tPoseSlideOp *pso= op->customdata; + wmWindow *win= CTX_wm_window(C); + + switch (evt->type) { + case LEFTMOUSE: /* confirm */ + { + /* return to normal cursor */ + WM_cursor_restore(win); + + /* insert keyframes as required... */ + pose_slide_autoKeyframe(C, pso); + pose_slide_exit(C, op); + + /* done! */ + return OPERATOR_FINISHED; + } + + case ESCKEY: /* cancel */ + case RIGHTMOUSE: + { + /* return to normal cursor */ + WM_cursor_restore(win); + + /* reset transforms back to original state */ + pose_slide_reset(C, pso); + + /* depsgraph updates + redraws */ + pose_slide_refresh(C, pso); + + /* clean up temp data */ + pose_slide_exit(C, op); + + /* cancelled! */ + return OPERATOR_CANCELLED; + } + + case MOUSEMOVE: /* calculate new position */ + { + /* calculate percentage based on position of mouse (we only use x-axis for now. + * since this is more conveninent for users to do), and store new percentage value + */ + pso->percentage= (evt->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx); + RNA_float_set(op->ptr, "percentage", pso->percentage); + + /* reset transforms (to avoid accumulation errors) */ + pose_slide_reset(C, pso); + + /* apply... */ + pose_slide_apply(C, op, pso); + } + break; + + default: /* unhandled event (maybe it was some view manip? */ + /* allow to pass through */ + return OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH; + } + + /* still running... */ + return OPERATOR_RUNNING_MODAL; +} + +/* common code for cancel() */ +static int pose_slide_cancel (bContext *C, wmOperator *op) +{ + /* cleanup and done */ + pose_slide_exit(C, op); + return OPERATOR_CANCELLED; +} + +/* common code for exec() methods */ +static int pose_slide_exec_common (bContext *C, wmOperator *op, tPoseSlideOp *pso) +{ + /* settings should have been set up ok for applying, so just apply! */ + pose_slide_apply(C, op, pso); + + /* insert keyframes if needed */ + pose_slide_autoKeyframe(C, pso); + + /* cleanup and done */ + pose_slide_exit(C, op); + + return OPERATOR_FINISHED; +} + +/* common code for defining RNA properties */ +static void pose_slide_opdef_properties (wmOperatorType *ot) +{ + RNA_def_int(ot->srna, "prev_frame", 0, MINAFRAME, MAXFRAME, "Previous Keyframe", "Frame number of keyframe immediately before the current frame.", 0, 50); + RNA_def_int(ot->srna, "next_frame", 0, MINAFRAME, MAXFRAME, "Next Keyframe", "Frame number of keyframe immediately after the current frame.", 0, 50); + RNA_def_float_percentage(ot->srna, "percentage", 0.5f, 0.0f, 1.0f, "Percentage", "Weighting factor for the sliding operation", 0.3, 0.7); +} + +/* ------------------------------------ */ + +/* invoke() - for 'push' mode */ +static int pose_slide_push_invoke (bContext *C, wmOperator *op, wmEvent *evt) +{ + tPoseSlideOp *pso; + + /* initialise data */ + if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) { + pose_slide_exit(C, op); + return OPERATOR_CANCELLED; + } + else + pso= op->customdata; + + /* do common setup work */ + return pose_slide_invoke_common(C, op, pso); +} + +/* exec() - for push */ +static int pose_slide_push_exec (bContext *C, wmOperator *op) +{ + tPoseSlideOp *pso; + + /* initialise data (from RNA-props) */ + if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) { + pose_slide_exit(C, op); + return OPERATOR_CANCELLED; + } + else + pso= op->customdata; + + /* do common exec work */ + return pose_slide_exec_common(C, op, pso); +} + +void POSE_OT_push (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Push Pose"; + ot->idname= "POSE_OT_push"; + ot->description= "Exaggerate the current pose"; + + /* callbacks */ + ot->exec= pose_slide_push_exec; + ot->invoke= pose_slide_push_invoke; + ot->modal= pose_slide_modal; + ot->cancel= pose_slide_cancel; + ot->poll= ED_operator_posemode; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; + + /* Properties */ + pose_slide_opdef_properties(ot); +} + +/* ........................ */ + +/* invoke() - for 'relax' mode */ +static int pose_slide_relax_invoke (bContext *C, wmOperator *op, wmEvent *evt) +{ + tPoseSlideOp *pso; + + /* initialise data */ + if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) { + pose_slide_exit(C, op); + return OPERATOR_CANCELLED; + } + else + pso= op->customdata; + + /* do common setup work */ + return pose_slide_invoke_common(C, op, pso); +} + +/* exec() - for relax */ +static int pose_slide_relax_exec (bContext *C, wmOperator *op) +{ + tPoseSlideOp *pso; + + /* initialise data (from RNA-props) */ + if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) { + pose_slide_exit(C, op); + return OPERATOR_CANCELLED; + } + else + pso= op->customdata; + + /* do common exec work */ + return pose_slide_exec_common(C, op, pso); +} + +void POSE_OT_relax (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Relax Pose"; + ot->idname= "POSE_OT_relax"; + ot->description= "Make the current pose more similar to its surrounding ones."; + + /* callbacks */ + ot->exec= pose_slide_relax_exec; + ot->invoke= pose_slide_relax_invoke; + ot->modal= pose_slide_modal; + ot->cancel= pose_slide_cancel; + ot->poll= ED_operator_posemode; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; + + /* Properties */ + pose_slide_opdef_properties(ot); +} + +/* ........................ */ + +/* invoke() - for 'breakdown' mode */ +static int pose_slide_breakdown_invoke (bContext *C, wmOperator *op, wmEvent *evt) +{ + tPoseSlideOp *pso; + + /* initialise data */ + if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) { + pose_slide_exit(C, op); + return OPERATOR_CANCELLED; + } + else + pso= op->customdata; + + /* do common setup work */ + return pose_slide_invoke_common(C, op, pso); +} + +/* exec() - for breakdown */ +static int pose_slide_breakdown_exec (bContext *C, wmOperator *op) +{ + tPoseSlideOp *pso; + + /* initialise data (from RNA-props) */ + if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) { + pose_slide_exit(C, op); + return OPERATOR_CANCELLED; + } + else + pso= op->customdata; + + /* do common exec work */ + return pose_slide_exec_common(C, op, pso); +} + +void POSE_OT_breakdown (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Pose Breakdowner"; + ot->idname= "POSE_OT_breakdown"; + ot->description= "Create a suitable breakdown pose on the current frame."; + + /* callbacks */ + ot->exec= pose_slide_breakdown_exec; + ot->invoke= pose_slide_breakdown_invoke; + ot->modal= pose_slide_modal; + ot->cancel= pose_slide_cancel; + ot->poll= ED_operator_posemode; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; + + /* Properties */ + pose_slide_opdef_properties(ot); +} + +/* **************************************************** */ diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c index c332a297e57..386cb6512a3 100644 --- a/source/blender/editors/armature/poselib.c +++ b/source/blender/editors/armature/poselib.c @@ -44,7 +44,6 @@ #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_curve_types.h" -#include "DNA_ipo_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_scene_types.h" @@ -62,8 +61,6 @@ #include "BKE_report.h" #include "BKE_utildefines.h" -#include "PIL_time.h" /* sleep */ - #include "RNA_access.h" #include "RNA_define.h" #include "RNA_types.h" @@ -470,6 +467,7 @@ static int poselib_remove_exec (bContext *C, wmOperator *op) marker= BLI_findlink(&act->markers, RNA_int_get(op->ptr, "index")); if (marker == NULL) { BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose"); + return OPERATOR_CANCELLED; } /* remove relevant keyframes */ @@ -536,6 +534,7 @@ static int poselib_rename_exec (bContext *C, wmOperator *op) marker= BLI_findlink(&act->markers, RNA_int_get(op->ptr, "index")); if (marker == NULL) { BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose"); + return OPERATOR_CANCELLED; } /* get new name */ @@ -769,6 +768,10 @@ static void poselib_keytag_pose (bContext *C, Scene *scene, tPoseLib_PreviewData if (poselib_ks_locrotscale == NULL) poselib_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; + + /* now insert the keyframe */ modify_keyframes(C, &dsources, NULL, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA); /* clear any unkeyed tags */ @@ -1411,7 +1414,7 @@ static int poselib_preview_invoke(bContext *C, wmOperator *op, wmEvent *event) poselib_preview_apply(C, op); /* add temp handler if we're running as a modal operator */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index bab7111dbd7..d4b7aa149df 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -798,6 +798,8 @@ void pose_copy_menu(Scene *scene) VECCOPY(pchan->limitmax, pchanact->limitmax); VECCOPY(pchan->stiffness, pchanact->stiffness); pchan->ikstretch= pchanact->ikstretch; + pchan->ikrotweight= pchanact->ikrotweight; + pchan->iklinweight= pchanact->iklinweight; } break; case 8: /* Custom Bone Shape */ @@ -812,14 +814,14 @@ void pose_copy_menu(Scene *scene) armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat); - if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + if (pchan->rotmode == ROT_MODE_AXISANGLE) { float tmp_quat[4]; /* need to convert to quat first (in temp var)... */ Mat4ToQuat(delta_mat, tmp_quat); QuatToAxisAngle(tmp_quat, &pchan->quat[1], &pchan->quat[0]); } - else if (pchan->rotmode == PCHAN_ROT_QUAT) + else if (pchan->rotmode == ROT_MODE_QUAT) Mat4ToQuat(delta_mat, pchan->quat); else Mat4ToEulO(delta_mat, pchan->eul, pchan->rotmode); @@ -1021,12 +1023,12 @@ static int pose_paste_exec (bContext *C, wmOperator *op) } else if (pchan->rotmode > 0) { /* quat/axis-angle to euler */ - if (chan->rotmode == PCHAN_ROT_AXISANGLE) + if (chan->rotmode == ROT_MODE_AXISANGLE) AxisAngleToEulO(&chan->quat[1], chan->quat[0], pchan->eul, pchan->rotmode); else QuatToEulO(chan->quat, pchan->eul, pchan->rotmode); } - else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + else if (pchan->rotmode == ROT_MODE_AXISANGLE) { /* quat/euler to axis angle */ if (chan->rotmode > 0) EulOToAxisAngle(chan->eul, chan->rotmode, &pchan->quat[1], &pchan->quat[0]); @@ -1050,7 +1052,7 @@ static int pose_paste_exec (bContext *C, wmOperator *op) pchan->eul[1] *= -1; pchan->eul[2] *= -1; } - else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + else if (pchan->rotmode == ROT_MODE_AXISANGLE) { float eul[3]; AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], eul, EULER_ORDER_DEFAULT); @@ -1084,6 +1086,9 @@ static int pose_paste_exec (bContext *C, wmOperator *op) 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(C, &dsources, NULL, posePaste_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)CFRA); /* clear any unkeyed tags */ @@ -1939,7 +1944,7 @@ static int armature_bone_layers_invoke (bContext *C, wmOperator *op, wmEvent *ev /* Set the visible layers for the active armature (edit and pose modes) */ static int armature_bone_layers_exec (bContext *C, wmOperator *op) { - Object *ob= CTX_data_active_object(C); + Object *ob= CTX_data_edit_object(C); bArmature *arm= (ob)? ob->data : NULL; PointerRNA ptr; int layers[16]; /* hardcoded for now - we can only have 16 armature layers, so this should be fine... */ @@ -1952,7 +1957,7 @@ static int armature_bone_layers_exec (bContext *C, wmOperator *op) { /* get pointer for pchan, and write flags this way */ RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr); - RNA_boolean_set_array(&ptr, "layers", layers); + RNA_boolean_set_array(&ptr, "layer", layers); } CTX_DATA_END; @@ -1983,175 +1988,6 @@ void ARMATURE_OT_bone_layers (wmOperatorType *ot) /* ********************************************** */ -#if 0 -// XXX old sys -/* for use with pose_relax only */ -static int pose_relax_icu(struct IpoCurve *icu, float framef, float *val, float *frame_prev, float *frame_next) -{ - if (!icu) { - return 0; - } - else { - BezTriple *bezt = icu->bezt; - - BezTriple *bezt_prev=NULL, *bezt_next=NULL; - float w1, w2, wtot; - int i; - - for (i=0; i < icu->totvert; i++, bezt++) { - if (bezt->vec[1][0] < framef - 0.5) { - bezt_prev = bezt; - } else { - break; - } - } - - if (bezt_prev==NULL) return 0; - - /* advance to the next, dont need to advance i */ - bezt = bezt_prev+1; - - for (; i < icu->totvert; i++, bezt++) { - if (bezt->vec[1][0] > framef + 0.5) { - bezt_next = bezt; - break; - } - } - - if (bezt_next==NULL) return 0; - - if (val) { - w1 = framef - bezt_prev->vec[1][0]; - w2 = bezt_next->vec[1][0] - framef; - wtot = w1 + w2; - w1=w1/wtot; - w2=w2/wtot; -#if 0 - val = (bezt_prev->vec[1][1] * w2) + (bezt_next->vec[1][1] * w1); -#else - /* apply the value with a hard coded 6th */ - *val = (((bezt_prev->vec[1][1] * w2) + (bezt_next->vec[1][1] * w1)) + (*val * 5.0f)) / 6.0f; -#endif - } - - if (frame_prev) *frame_prev = bezt_prev->vec[1][0]; - if (frame_next) *frame_next = bezt_next->vec[1][0]; - - return 1; - } -} -#endif - -void pose_relax(Scene *scene) -{ - Object *ob = OBACT; - bPose *pose; - bAction *act; - bArmature *arm; - -// IpoCurve *icu_w, *icu_x, *icu_y, *icu_z; - - bPoseChannel *pchan; -// bActionChannel *achan; -// float framef = F_CFRA; -// float frame_prev, frame_next; -// float quat_prev[4], quat_next[4], quat_interp[4], quat_orig[4]; - - int do_scale = 0; - int do_loc = 0; - int do_quat = 0; - int flag = 0; -// int do_x, do_y, do_z; - - if (!ob) return; - - pose = ob->pose; - act = ob->action; - arm = (bArmature *)ob->data; - - if (!pose || !act || !arm) return; - - for (pchan=pose->chanbase.first; pchan; pchan= pchan->next) { - - pchan->bone->flag &= ~BONE_TRANSFORM; - - if (pchan->bone->layer & arm->layer) { - if (pchan->bone->flag & BONE_SELECTED) { - /* do we have an ipo curve? */ -#if 0 // XXX old animation system - achan= get_action_channel(act, pchan->name); - - if (achan && achan->ipo) { - /*calc_ipo(achan->ipo, ctime);*/ - - do_x = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_X), framef, &pchan->loc[0], NULL, NULL); - do_y = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Y), framef, &pchan->loc[1], NULL, NULL); - do_z = pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Z), framef, &pchan->loc[2], NULL, NULL); - do_loc += do_x + do_y + do_z; - - do_x = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_X), framef, &pchan->size[0], NULL, NULL); - do_y = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Y), framef, &pchan->size[1], NULL, NULL); - do_z = pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Z), framef, &pchan->size[2], NULL, NULL); - do_scale += do_x + do_y + do_z; - - if( ((icu_w = find_ipocurve(achan->ipo, AC_QUAT_W))) && - ((icu_x = find_ipocurve(achan->ipo, AC_QUAT_X))) && - ((icu_y = find_ipocurve(achan->ipo, AC_QUAT_Y))) && - ((icu_z = find_ipocurve(achan->ipo, AC_QUAT_Z))) ) - { - /* use the quatw keyframe as a basis for others */ - if (pose_relax_icu(icu_w, framef, NULL, &frame_prev, &frame_next)) { - /* get 2 quats */ - quat_prev[0] = eval_icu(icu_w, frame_prev); - quat_prev[1] = eval_icu(icu_x, frame_prev); - quat_prev[2] = eval_icu(icu_y, frame_prev); - quat_prev[3] = eval_icu(icu_z, frame_prev); - - quat_next[0] = eval_icu(icu_w, frame_next); - quat_next[1] = eval_icu(icu_x, frame_next); - quat_next[2] = eval_icu(icu_y, frame_next); - quat_next[3] = eval_icu(icu_z, frame_next); - -#if 0 - /* apply the setting, completely smooth */ - QuatInterpol(pchan->quat, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) ); -#else - /* tricky interpolation */ - QuatInterpol(quat_interp, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) ); - QUATCOPY(quat_orig, pchan->quat); - QuatInterpol(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f); - /* done */ -#endif - do_quat++; - } - } - - /* apply BONE_TRANSFORM tag so that autokeying will pick it up */ - pchan->bone->flag |= BONE_TRANSFORM; - } - -#endif // XXX old animation system - } - } - } - - ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); - - /* do auto-keying */ - if (do_loc) flag |= TFM_TRANSLATION; - if (do_scale) flag |= TFM_RESIZE; - if (do_quat) flag |= TFM_ROTATION; - autokeyframe_pose_cb_func(ob, flag, 0); - - /* clear BONE_TRANSFORM flags */ - for (pchan=pose->chanbase.first; pchan; pchan= pchan->next) - pchan->bone->flag &= ~ BONE_TRANSFORM; - - /* do depsgraph flush */ - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - BIF_undo_push("Relax Pose"); -} - /* for use in insertkey, ensure rotation goes other way around */ void pose_flipquats(Scene *scene) { diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index 8a90dace40b..77c5ed1de2c 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -163,7 +163,10 @@ void ED_operatortypes_curve(void) void ED_keymap_curve(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Font", 0, 0); + wmKeyMap *keymap; + + keymap= WM_keymap_find(wm, "Font", 0, 0); + keymap->poll= ED_operator_editfont; /* only set in editmode font, by space_view3d listener */ RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_style_toggle", BKEY, KM_PRESS, KM_CTRL, 0)->ptr, "style", CU_BOLD); @@ -212,7 +215,8 @@ void ED_keymap_curve(wmWindowManager *wm) WM_keymap_add_item(keymap, "FONT_OT_text_insert", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last! /* only set in editmode curve, by space_view3d listener */ - keymap= WM_keymap_listbase(wm, "Curve", 0, 0); + keymap= WM_keymap_find(wm, "Curve", 0, 0); + keymap->poll= ED_operator_editsurfcurve; WM_keymap_add_item(keymap, "OBJECT_OT_curve_add", AKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "CURVE_OT_vertex_add", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 8dabe24de91..a18815d04a6 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1078,7 +1078,7 @@ void CURVE_OT_spline_weight_set(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - RNA_def_float_percentage(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f); + RNA_def_float_factor(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f); } /******************* set radius operator ******************/ diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 868c5902670..2be567e1921 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -381,19 +381,19 @@ static int paste_file(bContext *C, ReportList *reports, char *filename) static int paste_file_exec(bContext *C, wmOperator *op) { - char *filename; + char *path; int retval; - filename= RNA_string_get_alloc(op->ptr, "filename", NULL, 0); - retval= paste_file(C, op->reports, filename); - MEM_freeN(filename); + path= RNA_string_get_alloc(op->ptr, "path", NULL, 0); + retval= paste_file(C, op->reports, path); + MEM_freeN(path); return retval; } static int paste_file_invoke(bContext *C, wmOperator *op, wmEvent *event) { - if(RNA_property_is_set(op->ptr, "filename")) + if(RNA_property_is_set(op->ptr, "path")) return paste_file_exec(C, op); WM_event_add_fileselect(C, op); diff --git a/source/blender/editors/datafiles/splash.jpg.c b/source/blender/editors/datafiles/splash.png.c index c1ca8b575e6..bbce480ecba 100644 --- a/source/blender/editors/datafiles/splash.jpg.c +++ b/source/blender/editors/datafiles/splash.png.c @@ -1,7 +1,7 @@ -/* DataToC output of file <splash_jpg> */ +/* DataToC output of file <splash_png> */ -int datatoc_splash_jpg_size= 79258; -char datatoc_splash_jpg[]= { +int datatoc_splash_png_size= 79258; +char datatoc_splash_png[]= { 255,216,255,224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 1, 0, 72, 0, 72, 0, 0,255,225, 0, 22, 69,120, 105,102, 0, 0, 77, 77, 0, 42, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,255,219, 0, 67, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index d33ad16dfb1..d311b39b9a3 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -47,7 +47,7 @@ void ED_keymap_gpencil(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Grease Pencil", 0, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Grease Pencil", 0, 0); wmKeymapItem *kmi; /* Draw */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 99b85d62026..92ae2400666 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1341,7 +1341,7 @@ static int gpencil_draw_invoke (bContext *C, wmOperator *op, wmEvent *event) } /* add a modal handler for this operator, so that we can then draw continuous strokes */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 799829a6e87..d9439956569 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -42,11 +42,14 @@ struct View2D; struct Scene; struct Object; +struct bDopeSheet; + struct bActionGroup; struct FCurve; struct FModifier; struct uiBlock; +struct uiLayout; /* ************************************************ */ /* ANIMATION CHANNEL FILTERING */ @@ -137,6 +140,7 @@ typedef enum eAnim_ChannelType { ANIMTYPE_DSWOR, ANIMTYPE_DSPART, ANIMTYPE_DSMBALL, + ANIMTYPE_DSARM, ANIMTYPE_SHAPEKEY, // XXX probably can become depreceated??? @@ -206,6 +210,7 @@ typedef enum eAnimFilter_Flags { #define FILTER_CUR_OBJD(cu) ((cu->flag & CU_DS_EXPAND)) #define FILTER_PART_OBJD(part) ((part->flag & PART_DS_EXPAND)) #define FILTER_MBALL_OBJD(mb) ((mb->flag2 & MB_DS_EXPAND)) +#define FILTER_ARM_OBJD(arm) ((arm->flag & ARM_DS_EXPAND)) /* 'Sub-object/Action' channels (flags stored in Action) */ #define SEL_ACTC(actc) ((actc->flag & ACT_SELECTED)) #define EXPANDED_ACTC(actc) ((actc->flag & ACT_COLLAPSED)==0) @@ -392,11 +397,14 @@ void ANIM_draw_cfra(const struct bContext *C, struct View2D *v2d, short flag); /* main call to draw preview range curtains */ void ANIM_draw_previewrange(const struct bContext *C, struct View2D *v2d); +/* ------------- Preview Range Drawing -------------- */ + +/* standard header buttons for Animation Editors */ +short ANIM_headerUI_standard_buttons(const struct bContext *C, struct bDopeSheet *ads, struct uiBlock *block, short xco, short yco); + /* ************************************************* */ /* F-MODIFIER TOOLS */ -struct uiLayout; - /* draw a given F-Modifier for some layout/UI-Block */ void ANIM_uiTemplate_fmodifier_draw(struct uiLayout *layout, struct ID *id, ListBase *modifiers, struct FModifier *fcm); diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h index 5d24b93418b..993cbceae18 100644 --- a/source/blender/editors/include/ED_datafiles.h +++ b/source/blender/editors/include/ED_datafiles.h @@ -40,8 +40,8 @@ extern char datatoc_blenderbuttons[]; extern int datatoc_prvicons_size; extern char datatoc_prvicons[]; -extern int datatoc_splash_jpg_size; -extern char datatoc_splash_jpg[]; +extern int datatoc_splash_png_size; +extern char datatoc_splash_png[]; extern int datatoc_Bfont_size; extern char datatoc_Bfont[]; diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 57ab6a5f8f6..221b377dd25 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -51,21 +51,21 @@ typedef enum FileListColumns { typedef struct FileLayout { /* view settings - XXX - move into own struct */ - short prv_w; - short prv_h; - short tile_w; - short tile_h; - short tile_border_x; - short tile_border_y; - short prv_border_x; - short prv_border_y; - short rows; - short columns; - short width; - short height; - short flag; - short dirty; - short textheight; + int prv_w; + int prv_h; + int tile_w; + int tile_h; + int tile_border_x; + int tile_border_y; + int prv_border_x; + int prv_border_y; + int rows; + int columns; + int width; + int height; + int flag; + int dirty; + int textheight; float column_widths[MAX_FILE_COLUMN]; } FileLayout; @@ -84,7 +84,7 @@ FileLayout* ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *ar int ED_fileselect_layout_numfiles(FileLayout* layout, struct ARegion *ar); int ED_fileselect_layout_offset(FileLayout* layout, int x, int y); -void ED_fileselect_layout_tilepos(FileLayout* layout, int tile, short *x, short *y); +void ED_fileselect_layout_tilepos(FileLayout* layout, int tile, int *x, int *y); #endif /* ED_FILES_H */ diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 566105109b2..a4263f7bd77 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -53,9 +53,6 @@ int ED_space_image_show_paint(struct SpaceImage *sima); int ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit); int ED_space_image_show_uvshadow(struct SpaceImage *sima, struct Object *obedit); -void ED_image_uiblock_panel(const struct bContext *C, struct uiBlock *block, struct Image **ima_pp, - struct ImageUser *iuser, short redraw, short imagechanged); - /* image_render.c, export for screen_ops.c, render operator */ void ED_space_image_output(struct bContext *C); diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index 0969398f1e2..51d7c664fba 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -119,5 +119,9 @@ void ob_to_keylist(struct bDopeSheet *ads, struct Object *ob, struct DLRBT_Tree void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks); void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks); +/* Keyframe Finding */ +ActKeyColumn *cfra_find_actkeycolumn(ActKeyColumn *ak, float cframe); +ActKeyColumn *cfra_find_nearest_next_ak(ActKeyColumn *ak, float cframe, short next); + #endif /* ED_KEYFRAMES_DRAW_H */ diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index b2bf05ea5ea..57a6c5fc773 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -73,6 +73,7 @@ typedef enum eEditKeyframes_Snap { SNAP_KEYS_NEARSEC, SNAP_KEYS_NEARMARKER, SNAP_KEYS_HORIZONTAL, + SNAP_KEYS_VALUE, } eEditKeyframes_Snap; /* mirroring tools */ diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 20c2301d2ac..d30fccfe4de 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -163,6 +163,9 @@ void ANIM_OT_remove_keyingset_button(struct wmOperatorType *ot); /* ************ Drivers ********************** */ +/* Returns whether there is a driver in the copy/paste buffer to paste */ +short ANIM_driver_can_paste(void); + /* Main Driver Management API calls: * Add a new driver for the specified property on the given ID block */ @@ -171,11 +174,24 @@ short ANIM_add_driver (struct ID *id, const char rna_path[], int array_index, sh /* Main Driver Management API calls: * Remove the driver for the specified property on the given ID block (if available) */ -short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short flag); +short ANIM_remove_driver(struct ID *id, const char rna_path[], int array_index, short flag); + +/* Main Driver Management API calls: + * Make a copy of the driver for the specified property on the given ID block + */ +short ANIM_copy_driver(struct ID *id, const char rna_path[], int array_index, short flag); + +/* Main Driver Management API calls: + * Add a new driver for the specified property on the given ID block or replace an existing one + * with the driver + driver-curve data from the buffer + */ +short ANIM_paste_driver(struct ID *id, const char rna_path[], int array_index, short flag); /* Driver management operators for UI buttons */ void ANIM_OT_add_driver_button(struct wmOperatorType *ot); void ANIM_OT_remove_driver_button(struct wmOperatorType *ot); +void ANIM_OT_copy_driver_button(struct wmOperatorType *ot); +void ANIM_OT_paste_driver_button(struct wmOperatorType *ot); /* ************ Auto-Keyframing ********************** */ /* Notes: diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index a2dba89ec20..634a3bc278b 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -118,6 +118,7 @@ void EM_select_face(struct EditFace *efa, int sel); void EM_select_face_fgon(struct EditMesh *em, struct EditFace *efa, int val); void EM_select_swap(struct EditMesh *em); void EM_toggle_select_all(struct EditMesh *em); +void EM_select_all(struct EditMesh *em); void EM_selectmode_flush(struct EditMesh *em); void EM_deselect_flush(struct EditMesh *em); void EM_selectmode_set(struct EditMesh *em); @@ -175,5 +176,13 @@ float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int ver struct MDeformWeight *ED_vgroup_weight_verify(struct MDeformVert *dv, int defgroup); struct MDeformWeight *ED_vgroup_weight_get(struct MDeformVert *dv, int defgroup); +/*needed by edge slide*/ +struct EditVert *editedge_getOtherVert(struct EditEdge *eed, struct EditVert *eve); +struct EditVert *editedge_getSharedVert(struct EditEdge *eed, struct EditEdge *eed2); +int editedge_containsVert(struct EditEdge *eed, struct EditVert *eve); +int editface_containsVert(struct EditFace *efa, struct EditVert *eve); +int editface_containsEdge(struct EditFace *efa, struct EditEdge *eed); +short sharesFace(struct EditMesh *em, struct EditEdge *e1, struct EditEdge *e2); + #endif /* ED_MESH_H */ diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index bf4632dc3da..305b2a64ffe 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -31,10 +31,15 @@ struct Material; struct Scene; struct Tex; +struct bContext; +struct bNode; /* drawnode.c */ void ED_init_node_butfuncs(void); +/* node_draw.c */ +void ED_node_changed_update(struct bContext *C, struct bNode *node); + /* node_edit.c */ void ED_node_shader_default(struct Material *ma); void ED_node_composit_default(struct Scene *sce); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 67dc6dada5f..363795afeab 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -88,6 +88,8 @@ void object_test_constraints(struct Object *ob); void ED_object_constraint_rename(struct Object *ob, struct bConstraint *con, char *oldname); void ED_object_constraint_set_active(struct Object *ob, struct bConstraint *con); +void ED_object_constraint_update(struct Object *ob); +void ED_object_constraint_dependency_update(struct Scene *scene, struct Object *ob); /* object_lattice.c */ void mouse_lattice(struct bContext *C, short mval[2], int extend); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 0153b3c9bdb..63b6a067389 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -58,6 +58,7 @@ void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar); void ED_region_panels(const struct bContext *C, struct ARegion *ar, int vertical, char *context, int contextnr); void ED_region_header_init(struct ARegion *ar); void ED_region_header(const struct bContext *C, struct ARegion *ar); +void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar); void region_scissor_winrct(struct ARegion *ar, struct rcti *winrct); /* spaces */ @@ -104,7 +105,6 @@ void ED_screen_new_window(struct bContext *C, struct rcti *position, int type); /* anim */ void ED_update_for_newframe(const struct bContext *C, int mute); -unsigned int ED_screen_view3d_layers(struct bScreen *screen); void ED_operatortypes_screen(void); void ED_keymap_screen(struct wmWindowManager *wm); diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h index c6a8881a0c6..a08f0576f42 100644 --- a/source/blender/editors/include/ED_sculpt.h +++ b/source/blender/editors/include/ED_sculpt.h @@ -33,10 +33,10 @@ struct wmWindowManager; /* sculpt.c */ void ED_operatortypes_sculpt(void); -void ED_keymap_sculpt(struct wmWindowManager *wm); /* paint_ops.c */ void ED_operatortypes_paint(void); +void ED_keymap_paint(struct wmWindowManager *wm); /* paint_image.c */ void undo_imagepaint_step(int step); diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 984def760ae..bf3111de5dc 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -41,8 +41,9 @@ struct Object; struct uiLayout; struct EnumPropertyItem; struct wmOperatorType; +struct wmKeyMap; -void transform_keymap_for_space(struct wmWindowManager *wm, struct ListBase *keymap, int spaceid); +void transform_keymap_for_space(struct wmWindowManager *wm, struct wmKeyMap *keymap, int spaceid); void transform_operatortypes(void); /* ******************** Macros & Prototypes *********************** */ @@ -74,7 +75,8 @@ enum { TFM_BAKE_TIME, TFM_BEVEL, TFM_BWEIGHT, - TFM_ALIGN + TFM_ALIGN, + TFM_EDGE_SLIDE } TfmMode; /* TRANSFORM CONTEXTS */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index b45ab2d4997..dc4744c9832 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -146,6 +146,7 @@ typedef struct uiLayout uiLayout; #define UI_BUT_DRIVEN (1<<22) #define UI_BUT_INACTIVE (1<<23) #define UI_BUT_LAST_ACTIVE (1<<24) +#define UI_BUT_UNDO (1<<25) #define UI_PANEL_WIDTH 340 #define UI_COMPACT_PANEL_WIDTH 160 @@ -417,7 +418,8 @@ typedef void (*uiIDPoinFunc)(struct bContext *C, struct ID *id, int event); uiBut *uiDefIDPoinBut(uiBlock *block, uiIDPoinFuncFP func, short blocktype, int retval, char *str, short x1, short y1, short x2, short y2, void *idpp, char *tip); -int uiDefIDPoinButs(uiBlock *block, struct Main *main, struct ID *parid, struct ID *id, int id_code, short *pin_p, int x, int y, uiIDPoinFunc func, int events); + +int uiIconFromID(struct ID *id); uiBut *uiDefPulldownBut(uiBlock *block, uiBlockCreateFunc func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip); uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip); @@ -429,7 +431,7 @@ uiBut *uiDefBlockButN(uiBlock *block, uiBlockCreateFunc func, void *argN, char * uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int retval, int icon, short x1, short y1, short x2, short y2, char *tip); uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip); -void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip); +uiBut *uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip); uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *keypoin, short *modkeypoin, char *tip); uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxlen, short x1, short y1, short x2, short y2, char *tip); @@ -484,6 +486,7 @@ int uiSearchBoxhHeight(void); void uiBlockSetHandleFunc(uiBlock *block, uiBlockHandleFunc func, void *arg); void uiBlockSetButmFunc (uiBlock *block, uiMenuHandleFunc func, void *arg); void uiBlockSetFunc (uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2); +void uiBlockSetNFunc (uiBlock *block, uiButHandleFunc func, void *argN, void *arg2); void uiButSetRenameFunc (uiBut *but, uiButHandleRenameFunc func, void *arg1); void uiButSetFunc (uiBut *but, uiButHandleFunc func, void *arg1, void *arg2); @@ -527,29 +530,6 @@ void UI_add_region_handlers(struct ListBase *handlers); void UI_add_area_handlers(struct ListBase *handlers); void UI_add_popup_handlers(struct bContext *C, struct ListBase *handlers, uiPopupBlockHandle *menu); -/* Legacy code - * Callbacks and utils to get 2.48 work */ - -void test_idbutton_cb(struct bContext *C, void *namev, void *arg2); -void test_scriptpoin_but(struct bContext *C, char *name, struct ID **idpp); -void test_actionpoin_but(struct bContext *C, char *name, struct ID **idpp); -void test_obpoin_but(struct bContext *C, char *name, struct ID **idpp); -void test_meshobpoin_but(struct bContext *C, char *name, struct ID **idpp); -void test_meshpoin_but(struct bContext *C, char *name, struct ID **idpp); -void test_matpoin_but(struct bContext *C, char *name, struct ID **idpp); -void test_scenepoin_but(struct bContext *C, char *name, struct ID **idpp); -void test_grouppoin_but(struct bContext *C, char *name, struct ID **idpp); -void test_texpoin_but(struct bContext *C, char *name, struct ID **idpp); -void test_imapoin_but(struct bContext *C, char *name, struct ID **idpp); -void autocomplete_bone(struct bContext *C, char *str, void *arg_v); -void autocomplete_vgroup(struct bContext *C, char *str, void *arg_v); - -struct rctf; -void curvemap_buttons(uiBlock *block, struct CurveMapping *cumap, char labeltype, short event, short redraw, struct rctf *rect); -void curvemap_layout(uiLayout *layout, struct CurveMapping *cumap, char labeltype, short event, short redraw, struct rctf *rect); -void colorband_buttons(uiBlock *block, struct ColorBand *coba, struct rctf *rect, int small); - - /* Module * * init and exit should be called before using this module. init_userdef must @@ -593,7 +573,7 @@ void UI_exit(void); uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, struct uiStyle *style); void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout); -void uiBlockLayoutResolve(const struct bContext *C, uiBlock *block, int *x, int *y); +void uiBlockLayoutResolve(uiBlock *block, int *x, int *y); uiBlock *uiLayoutGetBlock(uiLayout *layout); @@ -638,10 +618,11 @@ void uiTemplateID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, uiLayout *uiTemplateModifier(uiLayout *layout, struct PointerRNA *ptr); uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); void uiTemplatePreview(uiLayout *layout, struct ID *id, struct ID *parent, struct MTex *slot); -void uiTemplateColorRamp(uiLayout *layout, struct ColorBand *coba, int expand); -void uiTemplateCurveMapping(uiLayout *layout, struct CurveMapping *cumap, int type, int compact); +void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand); +void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, char *propname, int type, int levels); void uiTemplateTriColorSet(uiLayout *layout, struct PointerRNA *ptr, char *propname); void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, char *propname); +void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *userptr, int compact); void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser); void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C); void uiTemplateOperatorSearch(uiLayout *layout); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 3c6e12905d6..1b05958b679 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -597,7 +597,7 @@ void uiEndBlock(const bContext *C, uiBlock *block) if(but->context) CTX_store_set((bContext*)C, but->context); - if(ot==NULL || (ot->poll && ot->poll((bContext *)C)==0)) { + if(ot == NULL || WM_operator_poll((bContext*)C, ot)==0) { but->flag |= UI_BUT_DISABLED; but->lock = 1; } @@ -622,7 +622,7 @@ void uiEndBlock(const bContext *C, uiBlock *block) } /* handle pending stuff */ - if(block->layouts.first) uiBlockLayoutResolve(C, block, NULL, NULL); + if(block->layouts.first) uiBlockLayoutResolve(block, NULL, NULL); ui_block_do_align(block); if(block->flag & UI_BLOCK_LOOP) ui_menu_block_set_keymaps(C, block); @@ -1684,6 +1684,9 @@ void uiFreeBlock(const bContext *C, uiBlock *block) ui_free_but(C, but); } + if(block->func_argN) + MEM_freeN(block->func_argN); + CTX_store_free_list(&block->contexts); BLI_freelistN(&block->saferct); @@ -2232,6 +2235,10 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short but->func= block->func; but->func_arg1= block->func_arg1; but->func_arg2= block->func_arg2; + + but->funcN= block->funcN; + if(block->func_argN) + but->func_argN= MEM_dupallocN(block->func_argN); but->pos= -1; /* cursor invisible */ @@ -2264,6 +2271,10 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short } } + if(ELEM8(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, SEARCH_MENU, BUTM)); + else if(ELEM5(but->type, SCROLL, SEPR, LINK, INLINK, FTPREVIEW)); + else but->flag |= UI_BUT_UNDO; + BLI_addtail(&block->buttons, but); if(block->curlayout) @@ -2942,6 +2953,16 @@ void uiBlockSetFunc(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2 block->func_arg2= arg2; } +void uiBlockSetNFunc(uiBlock *block, uiButHandleFunc func, void *argN, void *arg2) +{ + if(block->func_argN) + MEM_freeN(block->func_argN); + + block->funcN= func; + block->func_argN= argN; + block->func_arg2= arg2; +} + void uiButSetRenameFunc(uiBut *but, uiButHandleRenameFunc func, void *arg1) { but->rename_func= func; @@ -2964,6 +2985,9 @@ void uiButSetFunc(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2) void uiButSetNFunc(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2) { + if(but->func_argN) + MEM_freeN(but->func_argN); + but->funcN= funcN; but->func_argN= argN; but->func_arg2= arg2; @@ -3000,6 +3024,8 @@ uiBut *uiDefBlockButN(uiBlock *block, uiBlockCreateFunc func, void *argN, char * { uiBut *but= ui_def_but(block, BLOCK, 0, str, x1, y1, x2, y2, NULL, 0.0, 0.0, 0.0, 0.0, tip); but->block_create_func= func; + if(but->func_argN) + MEM_freeN(but->func_argN); but->func_argN= argN; ui_check_but(but); return but; @@ -3073,10 +3099,11 @@ uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int return but; } -void uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip) +uiBut *uiDefKeyevtButS(uiBlock *block, int retval, char *str, short x1, short y1, short x2, short y2, short *spoin, char *tip) { uiBut *but= ui_def_but(block, KEYEVT|SHO, retval, str, x1, y1, x2, y2, spoin, 0.0, 0.0, 0.0, 0.0, tip); ui_check_but(but); + return but; } /* short pointers hardcoded */ diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 8c41726b81b..8037a609a2f 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -209,6 +209,18 @@ void ui_but_anim_remove_driver(bContext *C) WM_operator_name_call(C, "ANIM_OT_remove_driver_button", WM_OP_INVOKE_DEFAULT, NULL); } +void ui_but_anim_copy_driver(bContext *C) +{ + /* this operator calls uiAnimContextProperty above */ + WM_operator_name_call(C, "ANIM_OT_copy_driver_button", WM_OP_INVOKE_DEFAULT, NULL); +} + +void ui_but_anim_paste_driver(bContext *C) +{ + /* this operator calls uiAnimContextProperty above */ + WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL); +} + void ui_but_anim_add_keyingset(bContext *C) { /* this operator calls uiAnimContextProperty above */ @@ -264,6 +276,10 @@ void ui_but_anim_menu(bContext *C, uiBut *but) } else uiItemBooleanO(layout, "Delete Driver", 0, "ANIM_OT_remove_driver_button", "all", 0); + + uiItemO(layout, "Copy Driver", 0, "ANIM_OT_copy_driver_button"); + if (ANIM_driver_can_paste()) + uiItemO(layout, "Paste Driver", 0, "ANIM_OT_paste_driver_button"); } else if(but->flag & UI_BUT_ANIMATED_KEY); else if(RNA_property_animateable(&but->rnapoin, but->rnaprop)) { @@ -275,6 +291,9 @@ void ui_but_anim_menu(bContext *C, uiBut *but) } else uiItemBooleanO(layout, "Add Driver", 0, "ANIM_OT_add_driver_button", "all", 0); + + if (ANIM_driver_can_paste()) + uiItemO(layout, "Paste Driver", 0, "ANIM_OT_paste_driver_button"); } if(RNA_property_animateable(&but->rnapoin, but->rnaprop)) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 259ccba6b89..b5de855cb80 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -246,7 +246,13 @@ static void ui_apply_but_func(bContext *C, uiBut *but) if(but->func || but->funcN || block->handle_func || but->rename_func || (but->type == BUTM && block->butm_func) || but->optype || but->rnaprop) { after= MEM_callocN(sizeof(uiAfterFunc), "uiAfterFunc"); - after->func= but->func; + if(but->func && ELEM(but, but->func_arg1, but->func_arg2)) { + /* exception, this will crash due to removed button otherwise */ + but->func(C, but->func_arg1, but->func_arg2); + } + else + after->func= but->func; + after->func_arg1= but->func_arg1; after->func_arg2= but->func_arg2; after->func_arg3= but->func_arg3; @@ -292,8 +298,7 @@ static void ui_apply_autokey_undo(bContext *C, uiBut *but) uiAfterFunc *after; char *str= NULL; - if ELEM6(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX); - else { + if(but->flag & UI_BUT_UNDO) { /* define which string to use for undo */ if ELEM(but->type, LINK, INLINK) str= "Add button link"; else if ELEM(but->type, MENU, ICONTEXTROW) str= but->drawstr; @@ -850,6 +855,7 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut ui_apply_but_CHARTAB(C, but, data); break; #endif + case KEYEVT: case HOTKEYEVT: ui_apply_but_BUT(C, but, data); break; @@ -1440,16 +1446,20 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa for(but= actbut->next; but; but= but->next) { if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) { - data->postbut= but; - data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; - return; + if(!(but->flag & UI_BUT_DISABLED)) { + data->postbut= but; + data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; + return; + } } } for(but= block->buttons.first; but!=actbut; but= but->next) { if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) { - data->postbut= but; - data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; - return; + if(!(but->flag & UI_BUT_DISABLED)) { + data->postbut= but; + data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; + return; + } } } } @@ -1464,16 +1474,20 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa for(but= actbut->prev; but; but= but->prev) { if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) { - data->postbut= but; - data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; - return; + if(!(but->flag & UI_BUT_DISABLED)) { + data->postbut= but; + data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; + return; + } } } for(but= block->buttons.last; but!=actbut; but= but->prev) { if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) { - data->postbut= but; - data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; - return; + if(!(but->flag & UI_BUT_DISABLED)) { + data->postbut= but; + data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; + return; + } } } } @@ -1646,7 +1660,7 @@ static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, u break; } case LEFTMOUSE: - if(event->val == 0) + if(event->val == KM_RELEASE) button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); retval= WM_UI_HANDLER_BREAK; break; @@ -2109,7 +2123,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton wmTabletData *wmtab= event->customdata; /* de-sensitise based on tablet pressure */ - if (ELEM(wmtab->Active, DEV_STYLUS, DEV_ERASER)) + if (wmtab->Active != EVT_TABLET_NONE) fac *= wmtab->Pressure; } @@ -3647,11 +3661,11 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s if(!(but->block->handle && but->block->handle->popup)) { if(button_modal_state(state)) { if(!button_modal_state(data->state)) - WM_event_add_ui_handler(C, &data->window->handlers, ui_handler_region_menu, NULL, data); + WM_event_add_ui_handler(C, &data->window->modalhandlers, ui_handler_region_menu, NULL, data); } else { if(button_modal_state(data->state)) - WM_event_remove_ui_handler(&data->window->handlers, ui_handler_region_menu, NULL, data); + WM_event_remove_ui_handler(&data->window->modalhandlers, ui_handler_region_menu, NULL, data); } } @@ -4587,7 +4601,7 @@ static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata) uiPopupBlockHandle temp= *menu; ui_popup_block_free(C, menu); - WM_event_remove_ui_handler(&CTX_wm_window(C)->handlers, ui_handler_popup, ui_handler_remove_popup, menu); + WM_event_remove_ui_handler(&CTX_wm_window(C)->modalhandlers, ui_handler_popup, ui_handler_remove_popup, menu); if(temp.menuretval == UI_RETURN_OK) { if(temp.popup_func) diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 2e623114fe9..885005ba06e 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -263,6 +263,9 @@ struct uiBlock { void *func_arg1; void *func_arg2; + uiButHandleNFunc funcN; + void *func_argN; + uiMenuHandleFunc butm_func; void *butm_func_arg; @@ -467,6 +470,8 @@ void ui_but_anim_insert_keyframe(struct bContext *C); void ui_but_anim_delete_keyframe(struct bContext *C); void ui_but_anim_add_driver(struct bContext *C); void ui_but_anim_remove_driver(struct bContext *C); +void ui_but_anim_copy_driver(struct bContext *C); +void ui_but_anim_paste_driver(struct bContext *C); void ui_but_anim_add_keyingset(struct bContext *C); void ui_but_anim_remove_keyingset(struct bContext *C); void ui_but_anim_menu(struct bContext *C, uiBut *but); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 6211c79beca..e3c392a145e 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -480,7 +480,8 @@ static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr, static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h, int icon_only) { uiLayout *sub; - uiBut *but; + uiBut *but=NULL; + PropertyType type; PropertySubType subtype; int labelw; @@ -496,6 +497,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, i w= w-labelw; } + type= RNA_property_type(prop); subtype= RNA_property_subtype(prop); if(subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) { @@ -505,8 +507,10 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, i /* BUTTONS_OT_file_browse calls uiFileBrowseContextProperty */ but= uiDefIconButO(block, BUT, "BUTTONS_OT_file_browse", WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, "Browse for file or directory."); } + else if(subtype == PROP_DIRECTION) + uiDefButR(block, BUT_NORMAL, 0, name, 0, 0, 100, 100, ptr, RNA_property_identifier(prop), index, 0, 0, -1, -1, NULL); else - but= uiDefAutoButR(block, ptr, prop, index, (icon_only)? "": NULL, icon, x, y, w, h); + but= uiDefAutoButR(block, ptr, prop, index, (type == PROP_ENUM && !icon_only)? NULL: "", icon, x, y, w, h); uiBlockSetCurLayout(block, layout); return but; @@ -529,7 +533,7 @@ void uiFileBrowseContextProperty(const bContext *C, PointerRNA *ptr, PropertyRNA prevbut= but->prev; /* find the button before the active one */ - if((but->flag & UI_BUT_LAST_ACTIVE) && prevbut && prevbut->rnapoin.id.data) { + if((but->flag & UI_BUT_LAST_ACTIVE) && prevbut && prevbut->rnapoin.data) { if(RNA_property_type(prevbut->rnaprop) == PROP_STRING) { *ptr= prevbut->rnapoin; *prop= prevbut->rnaprop; @@ -840,9 +844,6 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper char namestr[UI_MAX_NAME_STR]; int len, w, h, slider, toggle, expand, icon_only; - if(!ptr->data || !prop) - return; - uiBlockSetCurLayout(block, layout); /* retrieve info */ @@ -913,12 +914,7 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper void uiItemR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, char *propname, int flag) { - PropertyRNA *prop; - - if(!ptr->data || !propname) - return; - - prop= RNA_struct_find_property(ptr, propname); + PropertyRNA *prop= RNA_struct_find_property(ptr, propname); if(!prop) { ui_item_disabled(layout, propname); @@ -931,12 +927,7 @@ void uiItemR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, char *prop void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value) { - PropertyRNA *prop; - - if(!ptr->data || !propname) - return; - - prop= RNA_struct_find_property(ptr, propname); + PropertyRNA *prop= RNA_struct_find_property(ptr, propname); if(!prop || RNA_property_type(prop) != PROP_ENUM) { ui_item_disabled(layout, propname); @@ -949,15 +940,10 @@ void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, void uiItemEnumR_string(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, char *value) { - PropertyRNA *prop; + PropertyRNA *prop= RNA_struct_find_property(ptr, propname); EnumPropertyItem *item; int ivalue, a, free; - if(!ptr->data || !propname) - return; - - prop= RNA_struct_find_property(ptr, propname); - if(!prop || RNA_property_type(prop) != PROP_ENUM) { ui_item_disabled(layout, propname); printf("uiItemEnumR: enum property not found: %s\n", propname); @@ -1107,7 +1093,7 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN but->hardmax= MAX2(but->hardmax, 256); but->rnasearchpoin= *searchptr; but->rnasearchprop= searchprop; - but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT; + but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT|UI_BUT_UNDO; uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL); } @@ -1123,9 +1109,6 @@ void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *p int w, h; /* validate arguments */ - if(!ptr->data || !searchptr->data) - return; - prop= RNA_struct_find_property(ptr, propname); if(!prop) { @@ -2227,18 +2210,13 @@ static void ui_item_layout(uiItem *item) } } -static void ui_layout_items(const bContext *C, uiBlock *block, uiLayout *layout) -{ - ui_item_estimate(&layout->item); - ui_item_layout(&layout->item); -} - -static void ui_layout_end(const bContext *C, uiBlock *block, uiLayout *layout, int *x, int *y) +static void ui_layout_end(uiBlock *block, uiLayout *layout, int *x, int *y) { if(layout->root->handlefunc) uiBlockSetButmFunc(block, layout->root->handlefunc, layout->root->argv); - ui_layout_items(C, block, layout); + ui_item_estimate(&layout->item); + ui_item_layout(&layout->item); if(x) *x= layout->x; if(y) *y= layout->y; @@ -2346,7 +2324,7 @@ void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv) layout->root->argv= argv; } -void uiBlockLayoutResolve(const bContext *C, uiBlock *block, int *x, int *y) +void uiBlockLayoutResolve(uiBlock *block, int *x, int *y) { uiLayoutRoot *root; @@ -2357,7 +2335,7 @@ void uiBlockLayoutResolve(const bContext *C, uiBlock *block, int *x, int *y) for(root=block->layouts.first; root; root=root->next) { /* NULL in advance so we don't interfere when adding button */ - ui_layout_end(C, block, root->layout, x, y); + ui_layout_end(block, root->layout, x, y); ui_layout_free(root->layout); } diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 05001109b53..fa24aa72b9f 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -963,6 +963,7 @@ static void check_panel_overlap(ARegion *ar, Panel *panel) } } +#if 0 // XXX panel docking/tabbing code that's no longer used static void test_add_new_tabs(ARegion *ar) { Panel *pa, *pasel=NULL, *palap=NULL; @@ -990,6 +991,7 @@ static void test_add_new_tabs(ARegion *ar) } if(pasel==NULL || palap==NULL) return; + if(palap->type && palap->type->flag & PNL_NO_HEADER) return; /* the overlapped panel becomes a tab */ palap->paneltab= pasel; @@ -1015,6 +1017,7 @@ static void test_add_new_tabs(ARegion *ar) pa= pa->next; } } +#endif /************************ panel dragging ****************************/ @@ -1381,7 +1384,12 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat if(state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) { if(data && data->state != PANEL_STATE_ANIMATION) { - test_add_new_tabs(ar); // also copies locations of tabs in dragged panel + /* XXX: + * - the panel tabbing function call below (test_add_new_tabs()) has been commented out + * "It is too easy to do by accident when reordering panels, is very hard to control and use, and has no real benefit." - BillRey + * Aligorith, 2009Sep + */ + //test_add_new_tabs(ar); // also copies locations of tabs in dragged panel check_panel_overlap(ar, NULL); // clears } @@ -1399,14 +1407,14 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat MEM_freeN(data); pa->activedata= NULL; - WM_event_remove_ui_handler(&win->handlers, ui_handler_panel, ui_handler_remove_panel, pa); + WM_event_remove_ui_handler(&win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa); } else { if(!data) { data= MEM_callocN(sizeof(uiHandlePanelData), "uiHandlePanelData"); pa->activedata= data; - WM_event_add_ui_handler(C, &win->handlers, ui_handler_panel, ui_handler_remove_panel, pa); + WM_event_add_ui_handler(C, &win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa); } if(ELEM(state, PANEL_STATE_ANIMATION, PANEL_STATE_DRAG)) diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 1d911fef418..0f04333c6c5 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -758,7 +758,7 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, int reset) data->active= a+1; if(cpoin) cpoin[0]= '|'; } - if(data->items.totitem==1) + if(data->items.totitem==1 && but->editstr[0]) data->active= 1; } @@ -2192,7 +2192,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi block->direction= direction; - uiBlockLayoutResolve(C, block, NULL, NULL); + uiBlockLayoutResolve(block, NULL, NULL); if(pup->popup) { uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_RET_1); @@ -2226,7 +2226,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi } block->minbounds= minwidth; - uiTextBoundsBlock(block, 40); + uiTextBoundsBlock(block, 50); } /* if menu slides out of other menu, override direction */ @@ -2275,7 +2275,7 @@ uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut if(!but) { handle->popup= 1; - UI_add_popup_handlers(C, &window->handlers, handle); + UI_add_popup_handlers(C, &window->modalhandlers, handle); WM_event_add_mousemove(C); } @@ -2332,7 +2332,7 @@ void uiPupMenuEnd(bContext *C, uiPopupMenu *pup) menu= ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPUP, pup); menu->popup= 1; - UI_add_popup_handlers(C, &window->handlers, menu); + UI_add_popup_handlers(C, &window->modalhandlers, menu); WM_event_add_mousemove(C); MEM_freeN(pup); @@ -2493,7 +2493,7 @@ void uiPupBlockO(bContext *C, uiBlockCreateFunc func, void *arg, char *opname, i handle->optype= (opname)? WM_operatortype_find(opname, 0): NULL; handle->opcontext= opcontext; - UI_add_popup_handlers(C, &window->handlers, handle); + UI_add_popup_handlers(C, &window->modalhandlers, handle); WM_event_add_mousemove(C); } @@ -2516,7 +2516,7 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int handle->cancel_func= confirm_cancel_operator; handle->opcontext= opcontext; - UI_add_popup_handlers(C, &window->handlers, handle); + UI_add_popup_handlers(C, &window->modalhandlers, handle); WM_event_add_mousemove(C); } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 2b7d6f383bf..af4a4c13c80 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -36,6 +36,7 @@ #include "BKE_icons.h" #include "BKE_global.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_utildefines.h" #include "ED_screen.h" @@ -75,7 +76,7 @@ typedef struct TemplateID { } TemplateID; /* Search browse menu, assign */ -static void id_search_call_cb(struct bContext *C, void *arg_template, void *item) +static void id_search_call_cb(bContext *C, void *arg_template, void *item) { TemplateID *template= (TemplateID*)arg_template; @@ -90,7 +91,7 @@ static void id_search_call_cb(struct bContext *C, void *arg_template, void *item } /* ID Search browse menu, do the search */ -static void id_search_cb(const struct bContext *C, void *arg_template, char *str, uiSearchItems *items) +static void id_search_cb(const bContext *C, void *arg_template, char *str, uiSearchItems *items) { TemplateID *template= (TemplateID*)arg_template; Scene *scene= CTX_data_scene(C); @@ -291,7 +292,7 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6; if(newop) { - but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_REGION_WIN, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL); + but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW)); } else { @@ -344,9 +345,6 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname StructRNA *type; int flag; - if(!ptr->data) - return; - prop= RNA_struct_find_property(ptr, propname); if(!prop || RNA_property_type(prop) != PROP_POINTER) { @@ -407,10 +405,12 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v) { Object *ob = ob_v; - ModifierData *md; - + ModifierData *md= md_v; int i, cageIndex = modifiers_getCageIndex(ob, NULL ); + /* undo button operation */ + md->mode ^= eModifierMode_OnCage; + for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) { if(md == md_v) { if(i >= cageIndex) @@ -519,9 +519,10 @@ static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, i /* XXX uiBlockSetEmboss(block, UI_EMBOSSR); */ if(ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) { - /* XXX uiBlockSetCol(block, color); */ - but = uiDefIconBut(block, BUT, 0, ICON_MESH_DATA, 0, 0, 16, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode"); + but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, 16, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode"); + if(index < cageIndex) + uiButSetFlag(but, UI_BUT_DISABLED); uiButSetFunc(but, modifiers_setOnCage, ob, md); uiBlockEndAlign(block); /* XXX uiBlockSetCol(block, TH_AUTO); */ @@ -675,6 +676,8 @@ void do_constraint_panels(bContext *C, void *arg, int event) if(ob->type==OB_ARMATURE) DAG_id_flush_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB); else DAG_id_flush_update(&ob->id, OB_RECALC_OB); + + WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); // XXX allqueue(REDRAWVIEW3D, 0); // XXX allqueue(REDRAWBUTSOBJECT, 0); @@ -686,19 +689,15 @@ static void constraint_active_func(bContext *C, void *ob_v, void *con_v) ED_object_constraint_set_active(ob_v, con_v); } -static void verify_constraint_name_func (bContext *C, void *con_v, void *name_v) +static void verify_constraint_name_func (bContext *C, void *con_v, void *dummy) { Object *ob= CTX_data_active_object(C); bConstraint *con= con_v; - char oldname[32]; if (!con) return; - /* put on the stack */ - BLI_strncpy(oldname, (char *)name_v, 32); - - ED_object_constraint_rename(ob, con, oldname); + ED_object_constraint_rename(ob, con, NULL); ED_object_constraint_set_active(ob, con); // XXX allqueue(REDRAWACTION, 0); } @@ -764,6 +763,22 @@ static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short } } +static void test_obpoin_but(bContext *C, char *name, ID **idpp) +{ + ID *id; + + id= CTX_data_main(C)->object.first; + while(id) { + if( strcmp(name, id->name+2)==0 ) { + *idpp= id; + id_lib_extern(id); /* checks lib data, sets correct flag for saving then */ + return; + } + id= id->next; + } + *idpp= NULL; +} + /* draw panel showing settings for a constraint */ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) { @@ -887,10 +902,11 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) uiDefIconButO(block, BUT, "CONSTRAINT_OT_move_down", WM_OP_INVOKE_DEFAULT, VICON_MOVE_DOWN, xco+width-50+18, yco, 16, 18, "Move constraint down in constraint stack"); uiBlockEndAlign(block); } - - + /* Close 'button' - emboss calls here disable drawing of 'button' behind X */ uiBlockSetEmboss(block, UI_EMBOSSN); + uiDefIconButBitS(block, ICONTOGN, CONSTRAINT_OFF, B_CONSTRAINT_TEST, ICON_CHECKBOX_DEHLT, xco+243, yco, 19, 19, &con->flag, 0.0, 0.0, 0.0, 0.0, "enable/disable constraint"); + uiDefIconButO(block, BUT, "CONSTRAINT_OT_delete", WM_OP_INVOKE_DEFAULT, ICON_X, xco+262, yco, 19, 19, "Delete constraint"); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -958,11 +974,11 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) /* subtarget */ if (is_armature_target(ct->tar)) { but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", xco+120, yco-(66+yoffset),150,18, &ct->subtarget, 0, 24, 0, 0, "Subtarget Bone"); - uiButSetCompleteFunc(but, autocomplete_bone, (void *)ct->tar); + //uiButSetCompleteFunc(but, autocomplete_bone, (void *)ct->tar); } else if (is_geom_target(ct->tar)) { but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", xco+120, yco-(66+yoffset),150,18, &ct->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points"); - uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ct->tar); + //uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ct->tar); } else { strcpy(ct->subtarget, ""); @@ -1241,54 +1257,501 @@ void uiTemplatePreview(uiLayout *layout, ID *id, ID *parent, MTex *slot) /********************** ColorRamp Template **************************/ -void uiTemplateColorRamp(uiLayout *layout, ColorBand *coba, int expand) +#include "BKE_texture.h" + +typedef struct RNAUpdateCb { + PointerRNA ptr; + PropertyRNA *prop; +} RNAUpdateCb; + +static void rna_update_cb(bContext *C, void *arg_cb, void *arg_unused) +{ + RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb; + + /* we call update here on the pointer property, this way the + owner of the curve mapping can still define it's own update + and notifier, even if the CurveMapping struct is shared. */ + RNA_property_update(C, &cb->ptr, cb->prop); +} + +#define B_BANDCOL 1 + +static int vergcband(const void *a1, const void *a2) +{ + const CBData *x1=a1, *x2=a2; + + if( x1->pos > x2->pos ) return 1; + else if( x1->pos < x2->pos) return -1; + return 0; +} + +static void colorband_pos_cb(bContext *C, void *cb_v, void *coba_v) +{ + ColorBand *coba= coba_v; + int a; + + if(coba->tot<2) return; + + for(a=0; a<coba->tot; a++) coba->data[a].cur= a; + qsort(coba->data, coba->tot, sizeof(CBData), vergcband); + for(a=0; a<coba->tot; a++) { + if(coba->data[a].cur==coba->cur) { + coba->cur= a; + break; + } + } + + rna_update_cb(C, cb_v, NULL); +} + +static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v) +{ + ColorBand *coba= coba_v; + + if(coba->tot < MAXCOLORBAND-1) coba->tot++; + coba->cur= coba->tot-1; + + colorband_pos_cb(C, cb_v, coba_v); + + ED_undo_push(C, "Add colorband"); +} + +static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v) +{ + ColorBand *coba= coba_v; + int a; + + if(coba->tot<2) return; + + for(a=coba->cur; a<coba->tot; a++) { + coba->data[a]= coba->data[a+1]; + } + if(coba->cur) coba->cur--; + coba->tot--; + + ED_undo_push(C, "Delete colorband"); + + rna_update_cb(C, cb_v, NULL); +} + + +/* offset aligns from bottom, standard width 300, height 115 */ +static void colorband_buttons_large(uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb) +{ + + uiBut *bt; + + if(coba==NULL) return; + + bt= uiDefBut(block, BUT, 0, "Add", 0+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Add a new color stop to the colorband"); + uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba); + + bt= uiDefBut(block, BUT, 0, "Delete", 60+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Delete the active position"); + uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba); + + uiDefButS(block, NUM, 0, "", 120+xoffs,100+yoffs,80, 20, &coba->cur, 0.0, (float)(MAX2(0, coba->tot-1)), 0, 0, "Choose active color stop"); + + bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4", + 210+xoffs, 100+yoffs, 90, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops"); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + uiBlockEndAlign(block); + + bt= uiDefBut(block, BUT_COLORBAND, 0, "", xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, ""); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + + if(coba->tot) { + CBData *cbd= coba->data + coba->cur; + + bt= uiDefButF(block, NUM, 0, "Pos:", 0+xoffs,40+yoffs,100, 20, &cbd->pos, 0.0, 1.0, 10, 0, "The position of the active color stop"); + uiButSetNFunc(bt, colorband_pos_cb, MEM_dupallocN(cb), coba); + bt= uiDefButF(block, COL, 0, "", 110+xoffs,40+yoffs,80,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop"); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + bt= uiDefButF(block, NUMSLI, 0, "A ", 200+xoffs,40+yoffs,100,20, &cbd->a, 0.0, 1.0, 10, 0, "The alpha value of the active color stop"); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + } + +} + +static void colorband_buttons_small(uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb) +{ + uiBut *bt; + float unit= (butr->xmax-butr->xmin)/14.0f; + float xs= butr->xmin; + + + bt= uiDefBut(block, BUT, 0, "Add", xs,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband"); + uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba); + bt= uiDefBut(block, BUT, 0, "Delete", xs+2.0f*unit,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Delete the active position"); + uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba); + + if(coba->tot) { + CBData *cbd= coba->data + coba->cur; + bt= uiDefButF(block, COL, 0, "", xs+4.0f*unit,butr->ymin+20.0f,2.0f*unit,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop"); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + bt= uiDefButF(block, NUMSLI, 0, "A:", xs+6.0f*unit,butr->ymin+20.0f,4.0f*unit,20, &(cbd->a), 0.0f, 1.0f, 10, 2, "The alpha value of the active color stop"); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + } + + bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4", + xs+10.0f*unit, butr->ymin+20.0f, unit*4, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops"); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + + bt= uiDefBut(block, BUT_COLORBAND, 0, "", xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, ""); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + + uiBlockEndAlign(block); +} + +static void colorband_buttons_layout(uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb) +{ + if(small) + colorband_buttons_small(block, coba, butr, cb); + else + colorband_buttons_large(block, coba, 0, 0, cb); +} + +void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, char *propname, int expand) { + PropertyRNA *prop= RNA_struct_find_property(ptr, propname); + PointerRNA cptr; + RNAUpdateCb *cb; uiBlock *block; rctf rect; - if(coba) { - rect.xmin= 0; rect.xmax= 200; - rect.ymin= 0; rect.ymax= 190; - - block= uiLayoutFreeBlock(layout); - colorband_buttons(block, coba, &rect, !expand); - } + if(!prop || RNA_property_type(prop) != PROP_POINTER) + return; + + cptr= RNA_property_pointer_get(ptr, prop); + if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp)) + return; + + cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); + cb->ptr= *ptr; + cb->prop= prop; + + rect.xmin= 0; rect.xmax= 200; + rect.ymin= 0; rect.ymax= 190; + + block= uiLayoutFreeBlock(layout); + colorband_buttons_layout(block, cptr.data, &rect, !expand, cb); + + MEM_freeN(cb); } /********************* CurveMapping Template ************************/ #include "DNA_color_types.h" +#include "BKE_colortools.h" -void uiTemplateCurveMapping(uiLayout *layout, CurveMapping *cumap, int type, int compact) +static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *unused) { - rctf rect; + CurveMapping *cumap = cumap_v; + float d; + + /* we allow 20 times zoom */ + if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) { + d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin); + cumap->curr.xmin+= d; + cumap->curr.xmax-= d; + d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin); + cumap->curr.ymin+= d; + cumap->curr.ymax-= d; + } + + ED_region_tag_redraw(CTX_wm_region(C)); +} + +static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *unused) +{ + CurveMapping *cumap = cumap_v; + float d, d1; + + /* we allow 20 times zoom, but dont view outside clip */ + if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) { + d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin); + + if(cumap->flag & CUMA_DO_CLIP) + if(cumap->curr.xmin-d < cumap->clipr.xmin) + d1= cumap->curr.xmin - cumap->clipr.xmin; + cumap->curr.xmin-= d1; + + d1= d; + if(cumap->flag & CUMA_DO_CLIP) + if(cumap->curr.xmax+d > cumap->clipr.xmax) + d1= -cumap->curr.xmax + cumap->clipr.xmax; + cumap->curr.xmax+= d1; + + d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin); + + if(cumap->flag & CUMA_DO_CLIP) + if(cumap->curr.ymin-d < cumap->clipr.ymin) + d1= cumap->curr.ymin - cumap->clipr.ymin; + cumap->curr.ymin-= d1; + + d1= d; + if(cumap->flag & CUMA_DO_CLIP) + if(cumap->curr.ymax+d > cumap->clipr.ymax) + d1= -cumap->curr.ymax + cumap->clipr.ymax; + cumap->curr.ymax+= d1; + } + + ED_region_tag_redraw(CTX_wm_region(C)); +} + +static void curvemap_buttons_setclip(bContext *C, void *cumap_v, void *unused) +{ + CurveMapping *cumap = cumap_v; + + curvemapping_changed(cumap, 0); +} + +static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v) +{ + CurveMapping *cumap = cumap_v; + + curvemap_remove(cumap->cm+cumap->cur, SELECT); + curvemapping_changed(cumap, 0); - if(cumap) { - if(compact) { - rect.xmin= 0; rect.xmax= 150; - rect.ymin= 0; rect.ymax= 140; + rna_update_cb(C, cb_v, NULL); +} + +/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */ +static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v) +{ + CurveMapping *cumap = cumap_v; + uiBlock *block; + uiBut *bt; + + block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS); + + /* use this for a fake extra empy space around the buttons */ + uiDefBut(block, LABEL, 0, "", -4, 16, 128, 106, NULL, 0, 0, 0, 0, ""); + + bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping", + 0,100,120,18, &cumap->flag, 0.0, 0.0, 10, 0, ""); + uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL); + + uiBlockBeginAlign(block); + uiDefButF(block, NUM, 0, "Min X ", 0,74,120,18, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, ""); + uiDefButF(block, NUM, 0, "Min Y ", 0,56,120,18, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, ""); + uiDefButF(block, NUM, 0, "Max X ", 0,38,120,18, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, ""); + uiDefButF(block, NUM, 0, "Max Y ", 0,20,120,18, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, ""); + + uiBlockSetDirection(block, UI_RIGHT); + + uiEndBlock(C, block); + return block; +} + +static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event) +{ + CurveMapping *cumap = cumap_v; + CurveMap *cuma= cumap->cm+cumap->cur; + + switch(event) { + case 0: + curvemap_reset(cuma, &cumap->clipr); + curvemapping_changed(cumap, 0); + break; + case 1: + cumap->curr= cumap->clipr; + break; + case 2: /* set vector */ + curvemap_sethandle(cuma, 1); + curvemapping_changed(cumap, 0); + break; + case 3: /* set auto */ + curvemap_sethandle(cuma, 0); + curvemapping_changed(cumap, 0); + break; + case 4: /* extend horiz */ + cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + curvemapping_changed(cumap, 0); + break; + case 5: /* extend extrapolate */ + cuma->flag |= CUMA_EXTEND_EXTRAPOLATE; + curvemapping_changed(cumap, 0); + break; + } + ED_region_tag_redraw(CTX_wm_region(C)); +} + +static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v) +{ + uiBlock *block; + short yco= 0, menuwidth=120; + + block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS); + uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, ""); + + uiBlockSetDirection(block, UI_RIGHT); + uiTextBoundsBlock(block, 50); + + uiEndBlock(C, block); + return block; +} + +static void curvemap_buttons_redraw(bContext *C, void *arg1, void *arg2) +{ + ED_region_tag_redraw(CTX_wm_region(C)); +} + +static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) +{ + CurveMapping *cumap = cumap_v; + int a; + + for(a=0; a<CM_TOT; a++) + curvemap_reset(cumap->cm+a, &cumap->clipr); + + cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f; + cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f; + curvemapping_set_black_white(cumap, NULL, NULL); + + curvemapping_changed(cumap, 0); + + rna_update_cb(C, cb_v, NULL); +} + +/* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */ +static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, RNAUpdateCb *cb) +{ + CurveMapping *cumap= ptr->data; + uiLayout *row, *sub, *split; + uiBlock *block; + uiBut *bt; + float dx= UI_UNIT_X; + int icon, size; + + block= uiLayoutGetBlock(layout); + + /* curve chooser */ + row= uiLayoutRow(layout, 0); + + if(labeltype=='v') { + /* vector */ + sub= uiLayoutRow(row, 1); + uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); + + if(cumap->cm[0].curve) { + bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, ""); + uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); } - else { - rect.xmin= 0; rect.xmax= 200; - rect.ymin= 0; rect.ymax= 190; + if(cumap->cm[1].curve) { + bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, ""); + uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); } - - curvemap_layout(layout, cumap, type, 0, 0, &rect); + if(cumap->cm[2].curve) { + bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, ""); + uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); + } + } + else if(labeltype=='c') { + /* color */ + sub= uiLayoutRow(row, 1); + uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); + + if(cumap->cm[3].curve) { + bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, ""); + uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); + } + if(cumap->cm[0].curve) { + bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, ""); + uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); + } + if(cumap->cm[1].curve) { + bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, ""); + uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); + } + if(cumap->cm[2].curve) { + bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, ""); + uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); + } + } + else + uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT); + + /* operation buttons */ + sub= uiLayoutRow(row, 1); + + uiBlockSetEmboss(block, UI_EMBOSSN); + + bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in"); + uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL); + + bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out"); + uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL); + + bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, 18, "Tools"); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + + if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT; + bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, 18, "Clipping Options"); + uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); + + bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points"); + uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap); + + uiBlockSetEmboss(block, UI_EMBOSS); + + uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL); + + /* curve itself */ + size= uiLayoutGetWidth(layout); + row= uiLayoutRow(layout, 0); + uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, 0, 0, ""); + + /* black/white levels */ + if(levels) { + split= uiLayoutSplit(layout, 0); + uiItemR(uiLayoutColumn(split, 0), NULL, 0, ptr, "black_level", UI_ITEM_R_EXPAND); + uiItemR(uiLayoutColumn(split, 0), NULL, 0, ptr, "white_level", UI_ITEM_R_EXPAND); + + uiLayoutRow(layout, 0); + bt=uiDefBut(block, BUT, 0, "Reset", 0, 0, UI_UNIT_X*10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves"); + uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap); } + + uiBlockSetNFunc(block, NULL, NULL, NULL); +} + +void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, char *propname, int type, int levels) +{ + RNAUpdateCb *cb; + PropertyRNA *prop= RNA_struct_find_property(ptr, propname); + PointerRNA cptr; + + if(!prop || RNA_property_type(prop) != PROP_POINTER) + return; + + cptr= RNA_property_pointer_get(ptr, prop); + if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping)) + return; + + cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); + cb->ptr= *ptr; + cb->prop= prop; + + curvemap_buttons_layout(layout, &cptr, type, levels, cb); + + MEM_freeN(cb); } /********************* TriColor (ThemeWireColorSet) Template ************************/ void uiTemplateTriColorSet(uiLayout *layout, PointerRNA *ptr, char *propname) { + PropertyRNA *prop= RNA_struct_find_property(ptr, propname); uiLayout *row; - PropertyRNA *prop; PointerRNA csPtr; - - if (!ptr->data) - return; - - prop= RNA_struct_find_property(ptr, propname); + if (!prop) { printf("uiTemplateTriColorSet: property not found: %s\n", propname); return; @@ -1319,9 +1782,6 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname) int groups, cols, layers; int group, col, layer, row; - if (!ptr->data) - return; - prop= RNA_struct_find_property(ptr, propname); if (!prop) { printf("uiTemplateLayer: layers property not found: %s\n", propname); @@ -1593,7 +2053,7 @@ ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr /************************* Operator Search Template **************************/ -static void operator_call_cb(struct bContext *C, void *arg1, void *arg2) +static void operator_call_cb(bContext *C, void *arg1, void *arg2) { wmOperatorType *ot= arg2; @@ -1601,14 +2061,14 @@ static void operator_call_cb(struct bContext *C, void *arg1, void *arg2) WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL); } -static void operator_search_cb(const struct bContext *C, void *arg, char *str, uiSearchItems *items) +static void operator_search_cb(const bContext *C, void *arg, char *str, uiSearchItems *items) { wmOperatorType *ot = WM_operatortype_first(); for(; ot; ot= ot->next) { if(BLI_strcasestr(ot->name, str)) { - if(ot->poll==NULL || ot->poll((bContext *)C)) { + if(WM_operator_poll((bContext*)C, ot)) { char name[256]; int len= strlen(ot->name); @@ -1682,17 +2142,4 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C) uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_REC, "Anim Player", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop animation playback"); } -/************************* Image Template **************************/ - -#include "ED_image.h" - -void uiTemplateTextureImage(uiLayout *layout, bContext *C, Tex *tex) -{ - uiBlock *block; - - if(tex) { - block= uiLayoutFreeBlock(layout); - ED_image_uiblock_panel(C, block, &tex->ima, &tex->iuser, 0, 0); - } -} diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 63f81c9e46c..1d56ed4fb6a 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -23,30 +23,13 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include <math.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> -#include "MEM_guardedalloc.h" - -#include "DNA_action_types.h" -#include "DNA_color_types.h" -#include "DNA_listBase.h" -#include "DNA_material_types.h" #include "DNA_object_types.h" -#include "DNA_screen_types.h" -#include "DNA_texture_types.h" -#include "DNA_windowmanager_types.h" - -#include "BLI_blenlib.h" -#include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_idprop.h" -#include "BKE_icons.h" -#include "BKE_library.h" -#include "BKE_main.h" -#include "BKE_texture.h" #include "BKE_utildefines.h" #include "RNA_access.h" @@ -54,18 +37,6 @@ #include "UI_interface.h" #include "UI_resources.h" -#include "ED_screen.h" -#include "ED_util.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "interface_intern.h" - -#define DEF_BUT_WIDTH 150 -#define DEF_ICON_BUT_WIDTH 20 -#define DEF_BUT_HEIGHT 20 - /*************************** RNA Utilities ******************************/ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, char *name, int icon, int x1, int y1, int x2, int y2) @@ -102,7 +73,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind if(RNA_property_subtype(prop) == PROP_COLOR) but= uiDefButR(block, COL, 0, name, x1, y1, x2, y2, ptr, propname, 0, 0, 0, -1, -1, NULL); } - else if(RNA_property_subtype(prop) == PROP_PERCENTAGE) + else if(RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR) but= uiDefButR(block, NUMSLI, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); else but= uiDefButR(block, NUM, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); @@ -176,989 +147,38 @@ void uiDefAutoButsRNA(const bContext *C, uiLayout *layout, PointerRNA *ptr, int else col= NULL; - /* temp hack to show normal button for spin/screw */ - if(strcmp(name, "Axis")==0) { - uiDefButR(uiLayoutGetBlock(col), BUT_NORMAL, 0, name, 0, 0, 100, 100, ptr, "axis", -1, 0, 0, -1, -1, NULL); - } - else uiItemFullR(col, "", 0, ptr, prop, -1, 0, 0); + uiItemFullR(col, "", 0, ptr, prop, -1, 0, 0); } RNA_STRUCT_END; } /***************************** ID Utilities *******************************/ -/* note, C code version, will be replaced with version in interface_templates.c */ - -typedef struct uiIDPoinParams { - uiIDPoinFunc func; - ListBase *lb; - ID *id; - short id_code; - short browsenr; -} uiIDPoinParams; - -static void idpoin_cb(bContext *C, void *arg_params, void *arg_event) -{ - uiIDPoinParams *params= (uiIDPoinParams*)arg_params; - ListBase *lb= params->lb; - uiIDPoinFunc func= params->func; - ID *id= params->id, *idtest; - int nr, event= GET_INT_FROM_POINTER(arg_event); - - if(event == UI_ID_BROWSE && params->browsenr == 32767) - event= UI_ID_ADD_NEW; - else if(event == UI_ID_BROWSE && params->browsenr == 32766) - event= UI_ID_OPEN; - - switch(event) { - case UI_ID_RENAME: - if(id) test_idbutton(id->name+2); - else return; - break; - case UI_ID_BROWSE: { - /* ID can be NULL, if nothing was assigned yet */ - if(lb->first==NULL) return; - - if(params->browsenr== -2) { - /* XXX implement or find a replacement (ID can be NULL!) - * activate_databrowse((ID *)G.buts->lockpoin, GS(id->name), 0, B_MESHBROWSE, ¶ms->browsenr, do_global_buttons); */ - return; - } - if(params->browsenr < 0) - return; - - for(idtest=lb->first, nr=1; idtest; idtest=idtest->next, nr++) { - if(nr==params->browsenr) { - if(id == idtest) - return; - - id= idtest; - - break; - } - } - break; - } - case UI_ID_DELETE: - id= NULL; - break; - case UI_ID_FAKE_USER: - if(id) { - if(id->flag & LIB_FAKEUSER) id->us++; - else id->us--; - } - else return; - break; - case UI_ID_PIN: - break; - case UI_ID_ADD_NEW: - break; - case UI_ID_OPEN: - break; - case UI_ID_ALONE: - if(!id || id->us < 1) - return; - break; - case UI_ID_LOCAL: - if(!id || id->us < 1) - return; - break; - case UI_ID_AUTO_NAME: - break; - } - - if(func) - func(C, id, event); -} - -/* ***************************** ID Search browse menu ********************** */ - -static void id_search_call_cb(struct bContext *C, void *arg_params, void *item) -{ - uiIDPoinParams *params= (uiIDPoinParams*)arg_params; - - if(item && params->func) - params->func(C, item, UI_ID_BROWSE); - -} - -static void id_search_cb(const struct bContext *C, void *arg_params, char *str, uiSearchItems *items) -{ - uiIDPoinParams *params= (uiIDPoinParams*)arg_params; - ID *id; - - for(id= params->lb->first; id; id= id->next) { - int iconid= 0; - - - /* icon */ - switch(GS(id->name)) - { - case ID_MA: /* fall through */ - case ID_TE: /* fall through */ - case ID_IM: /* fall through */ - case ID_WO: /* fall through */ - case ID_LA: /* fall through */ - iconid= BKE_icon_getid(id); - break; - default: - break; - } - - if(BLI_strcasestr(id->name+2, str)) { - if(0==uiSearchItemAdd(items, id->name+2, id, iconid)) - break; - } - } -} - -static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_params) -{ - static char search[256]; - static uiIDPoinParams params; - wmEvent event; - wmWindow *win= CTX_wm_window(C); - uiBlock *block; - uiBut *but; - - /* clear initial search string, then all items show */ - search[0]= 0; - /* params is malloced, can be freed by parent button */ - params= *((uiIDPoinParams*)arg_params); - - block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); - uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1); - - /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); - - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, ""); - uiButSetSearchFunc(but, id_search_cb, ¶ms, id_search_call_cb, NULL); - - uiBoundsBlock(block, 6); - uiBlockSetDirection(block, UI_DOWN); - uiEndBlock(C, block); - - event= *(win->eventstate); /* XXX huh huh? make api call */ - event.type= EVT_BUT_OPEN; - event.val= KM_PRESS; - event.customdata= but; - event.customdatafree= FALSE; - wm_event_add(win, &event); - - return block; -} - -/* ****************** */ - -int uiDefIDPoinButs(uiBlock *block, Main *bmain, ID *parid, ID *id, int id_code, short *pin_p, int x, int y, uiIDPoinFunc func, int events) -{ - uiBut *but; - uiIDPoinParams *params, *dup_params; - char str1[10]; - int len, add_addbutton=0; - - /* setup struct that we will pass on with the buttons */ - params= MEM_callocN(sizeof(uiIDPoinParams), "uiIDPoinParams"); - params->lb= wich_libbase(bmain, id_code); - params->id= id; - params->id_code= id_code; - params->func= func; - - /* create buttons */ - uiBlockBeginAlign(block); - - /* XXX solve? - if(id && id->us>1) - uiBlockSetCol(block, TH_BUT_SETTING1); - - if((events & UI_ID_PIN) && *pin_p) - uiBlockSetCol(block, TH_BUT_SETTING2); - */ - - /* pin button */ - if(id && (events & UI_ID_PIN)) { - but= uiDefIconButS(block, ICONTOG, (events & UI_ID_PIN), ICON_KEY_DEHLT, x, y ,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, pin_p, 0, 0, 0, 0, "Keeps this view displaying the current data regardless of what object is selected"); - uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_PIN)); - x+= DEF_ICON_BUT_WIDTH; - } - - /* browse menu */ - if(events & UI_ID_BROWSE) { - uiDefBlockButN(block, id_search_menu, MEM_dupallocN(params), "", x, y, DEF_ICON_BUT_WIDTH, DEF_BUT_HEIGHT, "Browse ID data"); - x+= DEF_ICON_BUT_WIDTH; - } - - - - /* text button with name */ - if(id) { - /* XXX solve? - if(id->us > 1) - uiBlockSetCol(block, TH_BUT_SETTING1); - */ - /* pinned data? - if((events & UI_ID_PIN) && *pin_p) - uiBlockSetCol(block, TH_BUT_SETTING2); - */ - /* redalert overrides pin color - if(id->us<=0) - uiBlockSetCol(block, TH_REDALERT); - */ - uiBlockSetButLock(block, id->lib!=0, "Can't edit external libdata"); - - /* name button */ - text_idbutton(id, str1); - - if(GS(id->name)==ID_IP) len= 110; - else if((y) && (GS(id->name)==ID_AC)) len= 100; // comes from button panel (poselib) - else if(y) len= 140; // comes from button panel - else len= 120; - - but= uiDefBut(block, TEX, 0, str1,x, y, (short)len, DEF_BUT_HEIGHT, id->name+2, 0.0, 21.0, 0, 0, "Displays current Datablock name. Click to change."); - uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_RENAME)); - - x+= len; - - uiBlockClearButLock(block); - - /* lib make local button */ - if(id->lib) { - if(id->flag & LIB_INDIRECT) uiDefIconBut(block, BUT, 0, 0 /* XXX ICON_DATALIB */,x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Indirect Library Datablock. Cannot change."); - else { - but= uiDefIconBut(block, BUT, 0, 0 /* XXX ICON_PARLIB */, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, - (events & UI_ID_LOCAL)? "Direct linked Library Datablock. Click to make local.": "Direct linked Library Datablock, cannot make local."); - uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ALONE)); - } - - x+= DEF_ICON_BUT_WIDTH; - } - - /* number of users / make local button */ - if((events & UI_ID_ALONE) && id->us>1) { - int butwidth; - - uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't make pinned data single-user"); - - sprintf(str1, "%d", id->us); - butwidth= (id->us<10)? DEF_ICON_BUT_WIDTH: DEF_ICON_BUT_WIDTH+10; - - but= uiDefBut(block, BUT, 0, str1, x, y, butwidth, DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy."); - uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ALONE)); - x+= butwidth; - - uiBlockClearButLock(block); - } - - /* add button */ - if(events & UI_ID_ADD_NEW) { - uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't unlink pinned data"); - if(parid && parid->lib); - else { - dup_params= MEM_dupallocN(params); - but= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, &dup_params->browsenr, params->browsenr, 32767.0, 0, 0, "Add new data block"); - uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ADD_NEW)); - x+= DEF_ICON_BUT_WIDTH; - } - - uiBlockClearButLock(block); - } - - /* delete button */ - if(events & UI_ID_DELETE) { - uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't unlink pinned data"); - if(parid && parid->lib); - else { - but= uiDefIconBut(block, BUT, 0, ICON_X, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Deletes link to this Datablock"); - uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_DELETE)); - x+= DEF_ICON_BUT_WIDTH; - } - - uiBlockClearButLock(block); - } - - /* auto name button */ - if(events & UI_ID_AUTO_NAME) { - if(parid && parid->lib); - else { - but= uiDefIconBut(block, BUT, 0, ICON_AUTO,x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Generates an automatic name"); - uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_AUTO_NAME)); - x+= DEF_ICON_BUT_WIDTH; - } - } - - /* fake user button */ - if(events & UI_ID_FAKE_USER) { - but= uiDefButBitS(block, TOG, LIB_FAKEUSER, 0, "F", x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, &id->flag, 0, 0, 0, 0, "Saves this datablock even if it has no users"); - uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_FAKE_USER)); - x+= DEF_ICON_BUT_WIDTH; - } - } - /* add new button */ - else if(add_addbutton) { - if(parid) uiBlockSetButLock(block, parid->lib!=0, "Can't edit external libdata"); - dup_params= MEM_dupallocN(params); - but= uiDefButS(block, TOG, 0, "Add New", x, y, 110, DEF_BUT_HEIGHT, &dup_params->browsenr, params->browsenr, 32767.0, 0, 0, "Add new data block"); - uiButSetNFunc(but, idpoin_cb, dup_params, SET_INT_IN_POINTER(UI_ID_ADD_NEW)); - x+= 110; - } - - uiBlockEndAlign(block); - - MEM_freeN(params); - - return x; -} - -/* ****************************** default button callbacks ******************* */ -/* ************ LEGACY WARNING, only to get things work with 2.48 code! ****** */ - -void test_idbutton_cb(struct bContext *C, void *namev, void *arg2) -{ - char *name= namev; - - test_idbutton(name+2); -} - - -void test_scriptpoin_but(struct bContext *C, char *name, ID **idpp) -{ - ID *id; - - id= CTX_data_main(C)->text.first; - while(id) { - if( strcmp(name, id->name+2)==0 ) { - *idpp= id; - return; - } - id= id->next; - } - *idpp= NULL; -} - -void test_actionpoin_but(struct bContext *C, char *name, ID **idpp) -{ - ID *id; - - id= CTX_data_main(C)->action.first; - while(id) { - if( strcmp(name, id->name+2)==0 ) { - id_us_plus(id); - *idpp= id; - return; - } - id= id->next; - } - *idpp= NULL; -} - - -void test_obpoin_but(struct bContext *C, char *name, ID **idpp) -{ - ID *id; - -// XXX if(idpp == (ID **)&(emptytex.object)) { -// error("You must add a texture first"); -// *idpp= 0; -// return; -// } - - id= CTX_data_main(C)->object.first; - while(id) { - if( strcmp(name, id->name+2)==0 ) { - *idpp= id; - id_lib_extern(id); /* checks lib data, sets correct flag for saving then */ - return; - } - id= id->next; - } - *idpp= NULL; -} - -/* tests for an object of type OB_MESH */ -void test_meshobpoin_but(struct bContext *C, char *name, ID **idpp) -{ - ID *id; - - id = CTX_data_main(C)->object.first; - while(id) { - Object *ob = (Object *)id; - if(ob->type == OB_MESH && strcmp(name, id->name + 2) == 0) { - *idpp = id; - /* checks lib data, sets correct flag for saving then */ - id_lib_extern(id); - return; - } - id = id->next; - } - *idpp = NULL; -} - -void test_meshpoin_but(struct bContext *C, char *name, ID **idpp) -{ - ID *id; - - if( *idpp ) (*idpp)->us--; - - id= CTX_data_main(C)->mesh.first; - while(id) { - if( strcmp(name, id->name+2)==0 ) { - *idpp= id; - id_us_plus(id); - return; - } - id= id->next; - } - *idpp= NULL; -} - -void test_matpoin_but(struct bContext *C, char *name, ID **idpp) -{ - ID *id; - - if( *idpp ) (*idpp)->us--; - - id= CTX_data_main(C)->mat.first; - while(id) { - if( strcmp(name, id->name+2)==0 ) { - *idpp= id; - id_us_plus(id); - return; - } - id= id->next; - } - *idpp= NULL; -} - -void test_scenepoin_but(struct bContext *C, char *name, ID **idpp) -{ - ID *id; - - if( *idpp ) (*idpp)->us--; - - id= CTX_data_main(C)->scene.first; - while(id) { - if( strcmp(name, id->name+2)==0 ) { - *idpp= id; - id_us_plus(id); - return; - } - id= id->next; - } - *idpp= NULL; -} - -void test_grouppoin_but(struct bContext *C, char *name, ID **idpp) -{ - ID *id; - - if( *idpp ) (*idpp)->us--; - - id= CTX_data_main(C)->group.first; - while(id) { - if( strcmp(name, id->name+2)==0 ) { - *idpp= id; - id_us_plus(id); - return; - } - id= id->next; - } - *idpp= NULL; -} -void test_texpoin_but(struct bContext *C, char *name, ID **idpp) +int uiIconFromID(ID *id) { - ID *id; - - if( *idpp ) (*idpp)->us--; - - id= CTX_data_main(C)->tex.first; - while(id) { - if( strcmp(name, id->name+2)==0 ) { - *idpp= id; - id_us_plus(id); - return; - } - id= id->next; - } - *idpp= NULL; -} - -void test_imapoin_but(struct bContext *C, char *name, ID **idpp) -{ - ID *id; - - if( *idpp ) (*idpp)->us--; - - id= CTX_data_main(C)->image.first; - while(id) { - if( strcmp(name, id->name+2)==0 ) { - *idpp= id; - id_us_plus(id); - return; - } - id= id->next; - } - *idpp= NULL; -} - -/* autocomplete callback for buttons */ -void autocomplete_bone(struct bContext *C, char *str, void *arg_v) -{ - Object *ob= (Object *)arg_v; - - if(ob==NULL || ob->pose==NULL) return; - - /* search if str matches the beginning of name */ - if(str[0]) { - AutoComplete *autocpl= autocomplete_begin(str, 32); - bPoseChannel *pchan; - - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) - autocomplete_do_name(autocpl, pchan->name); - - autocomplete_end(autocpl, str); - } -} - -/* autocomplete callback for buttons */ -void autocomplete_vgroup(struct bContext *C, char *str, void *arg_v) -{ - Object *ob= (Object *)arg_v; - - if(ob==NULL) return; - - /* search if str matches the beginning of a name */ - if(str[0]) { - AutoComplete *autocpl= autocomplete_begin(str, 32); - bDeformGroup *dg; - - for(dg= ob->defbase.first; dg; dg= dg->next) - if(dg->name!=str) - autocomplete_do_name(autocpl, dg->name); - - autocomplete_end(autocpl, str); - } -} - - -/* ----------- custom button group ---------------------- */ - -static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *unused) -{ - CurveMapping *cumap = cumap_v; - float d; - - /* we allow 20 times zoom */ - if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) { - d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin); - cumap->curr.xmin+= d; - cumap->curr.xmax-= d; - d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin); - cumap->curr.ymin+= d; - cumap->curr.ymax-= d; - } -} - -static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *unused) -{ - CurveMapping *cumap = cumap_v; - float d, d1; - - /* we allow 20 times zoom, but dont view outside clip */ - if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) { - d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin); - - if(cumap->flag & CUMA_DO_CLIP) - if(cumap->curr.xmin-d < cumap->clipr.xmin) - d1= cumap->curr.xmin - cumap->clipr.xmin; - cumap->curr.xmin-= d1; - - d1= d; - if(cumap->flag & CUMA_DO_CLIP) - if(cumap->curr.xmax+d > cumap->clipr.xmax) - d1= -cumap->curr.xmax + cumap->clipr.xmax; - cumap->curr.xmax+= d1; - - d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin); - - if(cumap->flag & CUMA_DO_CLIP) - if(cumap->curr.ymin-d < cumap->clipr.ymin) - d1= cumap->curr.ymin - cumap->clipr.ymin; - cumap->curr.ymin-= d1; - - d1= d; - if(cumap->flag & CUMA_DO_CLIP) - if(cumap->curr.ymax+d > cumap->clipr.ymax) - d1= -cumap->curr.ymax + cumap->clipr.ymax; - cumap->curr.ymax+= d1; - } -} - -static void curvemap_buttons_setclip(bContext *C, void *cumap_v, void *unused) -{ - CurveMapping *cumap = cumap_v; - - curvemapping_changed(cumap, 0); -} - -static void curvemap_buttons_delete(bContext *C, void *cumap_v, void *unused) -{ - CurveMapping *cumap = cumap_v; - - curvemap_remove(cumap->cm+cumap->cur, SELECT); - curvemapping_changed(cumap, 0); -} - -/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */ -static uiBlock *curvemap_clipping_func(struct bContext *C, struct ARegion *ar, void *cumap_v) -{ - CurveMapping *cumap = cumap_v; - uiBlock *block; - uiBut *bt; - - block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS); - - /* use this for a fake extra empy space around the buttons */ - uiDefBut(block, LABEL, 0, "", -4, 16, 128, 106, NULL, 0, 0, 0, 0, ""); - - bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping", - 0,100,120,18, &cumap->flag, 0.0, 0.0, 10, 0, ""); - uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL); - - uiBlockBeginAlign(block); - uiDefButF(block, NUM, 0, "Min X ", 0,74,120,18, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, ""); - uiDefButF(block, NUM, 0, "Min Y ", 0,56,120,18, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, ""); - uiDefButF(block, NUM, 0, "Max X ", 0,38,120,18, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "Max Y ", 0,20,120,18, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, ""); - - uiBlockSetDirection(block, UI_RIGHT); - - uiEndBlock(C, block); - return block; -} - - -static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event) -{ - CurveMapping *cumap = cumap_v; - CurveMap *cuma= cumap->cm+cumap->cur; - - switch(event) { - case 0: - curvemap_reset(cuma, &cumap->clipr); - curvemapping_changed(cumap, 0); - break; - case 1: - cumap->curr= cumap->clipr; - break; - case 2: /* set vector */ - curvemap_sethandle(cuma, 1); - curvemapping_changed(cumap, 0); - break; - case 3: /* set auto */ - curvemap_sethandle(cuma, 0); - curvemapping_changed(cumap, 0); - break; - case 4: /* extend horiz */ - cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE; - curvemapping_changed(cumap, 0); - break; - case 5: /* extend extrapolate */ - cuma->flag |= CUMA_EXTEND_EXTRAPOLATE; - curvemapping_changed(cumap, 0); - break; - } - ED_region_tag_redraw(CTX_wm_region(C)); -} - -static uiBlock *curvemap_tools_func(struct bContext *C, struct ARegion *ar, void *cumap_v) -{ - uiBlock *block; - short yco= 0, menuwidth=120; - - block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS); - uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, ""); - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 50); - - uiEndBlock(C, block); - return block; -} - -/* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */ -void curvemap_buttons(uiBlock *block, CurveMapping *cumap, char labeltype, short event, short redraw, rctf *rect) -{ - uiBut *bt; - float dx, fy= rect->ymax-18.0f; - int icon; - short xco, yco; - - yco= (short)(rect->ymax-18.0f); - - /* curve choice options + tools/settings, 8 icons + spacer */ - dx= (rect->xmax-rect->xmin)/(9.0f); - - uiBlockBeginAlign(block); - if(labeltype=='v') { /* vector */ - xco= (short)rect->xmin; - if(cumap->cm[0].curve) - uiDefButI(block, ROW, redraw, "X", xco, yco+2, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, ""); - xco= (short)(rect->xmin+1.0f*dx); - if(cumap->cm[1].curve) - uiDefButI(block, ROW, redraw, "Y", xco, yco+2, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, ""); - xco= (short)(rect->xmin+2.0f*dx); - if(cumap->cm[2].curve) - uiDefButI(block, ROW, redraw, "Z", xco, yco+2, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, ""); - } - else if(labeltype=='c') { /* color */ - xco= (short)rect->xmin; - if(cumap->cm[3].curve) - uiDefButI(block, ROW, redraw, "C", xco, yco+2, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, ""); - xco= (short)(rect->xmin+1.0f*dx); - if(cumap->cm[0].curve) - uiDefButI(block, ROW, redraw, "R", xco, yco+2, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, ""); - xco= (short)(rect->xmin+2.0f*dx); - if(cumap->cm[1].curve) - uiDefButI(block, ROW, redraw, "G", xco, yco+2, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, ""); - xco= (short)(rect->xmin+3.0f*dx); - if(cumap->cm[2].curve) - uiDefButI(block, ROW, redraw, "B", xco, yco+2, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, ""); - } - /* else no channels ! */ - uiBlockEndAlign(block); - - xco= (short)(rect->xmin+4.5f*dx); - uiBlockSetEmboss(block, UI_EMBOSSN); - bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMIN, xco, yco, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in"); - uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL); - - xco= (short)(rect->xmin+5.25f*dx); - bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMOUT, xco, yco, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out"); - uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL); - - xco= (short)(rect->xmin+6.0f*dx); - bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, event, ICON_MODIFIER, xco, yco, dx, 18, "Tools"); - - xco= (short)(rect->xmin+7.0f*dx); - if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT; - bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, event, icon, xco, yco, dx, 18, "Clipping Options"); - - xco= (short)(rect->xmin+8.0f*dx); - bt= uiDefIconBut(block, BUT, event, ICON_X, xco, yco, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points"); - uiButSetFunc(bt, curvemap_buttons_delete, cumap, NULL); - - uiBlockSetEmboss(block, UI_EMBOSS); - - uiDefBut(block, BUT_CURVE, event, "", - rect->xmin, rect->ymin, rect->xmax-rect->xmin, fy-rect->ymin, - cumap, 0.0f, 1.0f, 0, 0, ""); -} - -/* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */ -void curvemap_layout(uiLayout *layout, CurveMapping *cumap, char labeltype, short event, short redraw, rctf *rect) -{ - uiLayout *row; - uiBlock *block; - uiBut *bt; - float dx, fy= rect->ymax-18.0f; - int icon; - - block= uiLayoutGetBlock(layout); - - /* curve choice options + tools/settings, 8 icons + spacer */ - dx= UI_UNIT_X; - - row= uiLayoutRow(layout, 0); - uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT); - - if(labeltype=='v') { /* vector */ - row= uiLayoutRow(layout, 1); - - if(cumap->cm[0].curve) - uiDefButI(block, ROW, redraw, "X", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, ""); - if(cumap->cm[1].curve) - uiDefButI(block, ROW, redraw, "Y", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, ""); - if(cumap->cm[2].curve) - uiDefButI(block, ROW, redraw, "Z", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, ""); - } - else if(labeltype=='c') { /* color */ - row= uiLayoutRow(layout, 1); - - if(cumap->cm[3].curve) - uiDefButI(block, ROW, redraw, "C", 0, 0, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, ""); - if(cumap->cm[0].curve) - uiDefButI(block, ROW, redraw, "R", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, ""); - if(cumap->cm[1].curve) - uiDefButI(block, ROW, redraw, "G", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, ""); - if(cumap->cm[2].curve) - uiDefButI(block, ROW, redraw, "B", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, ""); - } - - row= uiLayoutRow(row, 1); + Object *ob; + PointerRNA ptr; + short idcode; - uiBlockSetEmboss(block, UI_EMBOSSN); - bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMIN, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in"); - uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL); - - bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMOUT, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out"); - uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL); - - bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, event, ICON_MODIFIER, 0, 0, dx, 18, "Tools"); - - if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT; - bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, event, icon, 0, 0, dx, 18, "Clipping Options"); + if(id==NULL) + return 0; - bt= uiDefIconBut(block, BUT, event, ICON_X, 0, 0, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points"); - uiButSetFunc(bt, curvemap_buttons_delete, cumap, NULL); - - uiBlockSetEmboss(block, UI_EMBOSS); - - row= uiLayoutRow(layout, 0); - uiDefBut(block, BUT_CURVE, event, "", - rect->xmin, rect->ymin, rect->xmax-rect->xmin, fy-rect->ymin, - cumap, 0.0f, 1.0f, 0, 0, ""); -} - - -#define B_BANDCOL 1 - -static int vergcband(const void *a1, const void *a2) -{ - const CBData *x1=a1, *x2=a2; - - if( x1->pos > x2->pos ) return 1; - else if( x1->pos < x2->pos) return -1; - return 0; -} - -static void colorband_pos_cb(bContext *C, void *coba_v, void *unused_v) -{ - ColorBand *coba= coba_v; - int a; - - if(coba->tot<2) return; - - for(a=0; a<coba->tot; a++) coba->data[a].cur= a; - qsort(coba->data, coba->tot, sizeof(CBData), vergcband); - for(a=0; a<coba->tot; a++) { - if(coba->data[a].cur==coba->cur) { - // XXX if(coba->cur!=a) addqueue(curarea->win, REDRAW, 0); /* button cur */ - coba->cur= a; - break; - } - } + idcode= GS(id->name); - WM_event_add_notifier(C, NC_TEXTURE, NULL); -} - -static void colorband_cb(bContext *C, void *coba_v, void *unused_v) -{ - WM_event_add_notifier(C, NC_TEXTURE, NULL); -} + /* exception for objects */ + if(idcode == ID_OB) { + ob= (Object*)id; -static void colorband_add_cb(bContext *C, void *coba_v, void *unused_v) -{ - ColorBand *coba= coba_v; - - if(coba->tot < MAXCOLORBAND-1) coba->tot++; - coba->cur= coba->tot-1; - - colorband_pos_cb(C, coba, NULL); - ED_undo_push(C, "Add colorband"); - WM_event_add_notifier(C, NC_TEXTURE, NULL); -} - -static void colorband_del_cb(bContext *C, void *coba_v, void *unused_v) -{ - ColorBand *coba= coba_v; - int a; - - if(coba->tot<2) return; - - for(a=coba->cur; a<coba->tot; a++) { - coba->data[a]= coba->data[a+1]; + if(ob->type == OB_EMPTY) + return ICON_EMPTY_DATA; + else + return uiIconFromID(ob->data); } - if(coba->cur) coba->cur--; - coba->tot--; - - ED_undo_push(C, "Delete colorband"); - // XXX BIF_preview_changed(ID_TE); - WM_event_add_notifier(C, NC_TEXTURE, NULL); -} - - -/* offset aligns from bottom, standard width 300, height 115 */ -static void colorband_buttons_large(uiBlock *block, ColorBand *coba, int xoffs, int yoffs, int redraw) -{ - CBData *cbd; - uiBut *bt; - - if(coba==NULL) return; - - bt= uiDefBut(block, BUT, redraw, "Add", 0+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Add a new color stop to the colorband"); - uiButSetFunc(bt, colorband_add_cb, coba, NULL); - bt= uiDefBut(block, BUT, redraw, "Delete", 60+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Delete the active position"); - uiDefButS(block, NUM, redraw, "", 120+xoffs,100+yoffs,80, 20, &coba->cur, 0.0, (float)(coba->tot-1), 0, 0, "Choose active color stop"); - - uiButSetFunc(bt, colorband_del_cb, coba, NULL); - - bt= uiDefButS(block, MENU, redraw, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4", - 210+xoffs, 100+yoffs, 90, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops"); - uiButSetFunc(bt, colorband_cb, coba, NULL); - uiBlockEndAlign(block); - bt= uiDefBut(block, BUT_COLORBAND, redraw, "", xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, ""); - uiButSetFunc(bt, colorband_cb, coba, NULL); - - cbd= coba->data + coba->cur; - - bt= uiDefButF(block, NUM, redraw, "Pos:", 0+xoffs,40+yoffs,100, 20, &cbd->pos, 0.0, 1.0, 10, 0, "The position of the active color stop"); - uiButSetFunc(bt, colorband_pos_cb, coba, NULL); - bt= uiDefButF(block, COL, redraw, "", 110+xoffs,40+yoffs,80,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop"); - uiButSetFunc(bt, colorband_cb, coba, NULL); - bt= uiDefButF(block, NUMSLI, redraw, "A ", 200+xoffs,40+yoffs,100,20, &cbd->a, 0.0, 1.0, 10, 0, "The alpha value of the active color stop"); - uiButSetFunc(bt, colorband_cb, coba, NULL); + /* otherwise get it through RNA, creating the pointer + will set the right type, also with subclassing */ + RNA_id_pointer_create(id, &ptr); -} - -static void colorband_buttons_small(uiBlock *block, ColorBand *coba, rctf *butr, int event) -{ - CBData *cbd; - uiBut *bt; - float unit= (butr->xmax-butr->xmin)/14.0f; - float xs= butr->xmin; - - cbd= coba->data + coba->cur; - - - bt= uiDefBut(block, BUT, event, "Add", xs,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband"); - uiButSetFunc(bt, colorband_add_cb, coba, NULL); - bt= uiDefBut(block, BUT, event, "Delete", xs+2.0f*unit,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Delete the active position"); - uiButSetFunc(bt, colorband_del_cb, coba, NULL); - - uiDefButF(block, COL, event, "", xs+4.0f*unit,butr->ymin+20.0f,2.0f*unit,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop"); - uiDefButF(block, NUMSLI, event, "A:", xs+6.0f*unit,butr->ymin+20.0f,4.0f*unit,20, &(cbd->a), 0.0f, 1.0f, 10, 2, "The alpha value of the active color stop"); - - uiDefButS(block, MENU, event, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4", - xs+10.0f*unit, butr->ymin+20.0f, unit*4, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops"); - - uiDefBut(block, BUT_COLORBAND, event, "", xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, ""); - uiBlockEndAlign(block); -} - -void colorband_buttons(uiBlock *block, ColorBand *coba, rctf *butr, int small) -{ - if(small) - colorband_buttons_small(block, coba, butr, 0); - else - colorband_buttons_large(block, coba, 0, 0, 0); + return (ptr.type)? RNA_struct_ui_icon(ptr.type): 0; } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 2385b5ad15c..ac8750f84e6 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -129,17 +129,21 @@ static float jit[8][2]= {{0.468813 , -0.481430}, {-0.155755 , -0.352820}, {0.219306 , -0.238501}, {-0.393286 , -0.110949}, {-0.024699 , 0.013908}, {0.343805 , 0.147431}, {-0.272855 , 0.269918}, {0.095909 , 0.388710}}; -static float num_tria_vert[19][2]= { +static float num_tria_vert[3][2]= { +{-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.330000, -0.008353}}; + +static int num_tria_face[1][3]= { +{0, 1, 2}}; + +static float scroll_circle_vert[16][2]= { {0.382684, 0.923879}, {0.000001, 1.000000}, {-0.382683, 0.923880}, {-0.707107, 0.707107}, {-0.923879, 0.382684}, {-1.000000, 0.000000}, {-0.923880, -0.382684}, {-0.707107, -0.707107}, {-0.382683, -0.923880}, {0.000000, -1.000000}, {0.382684, -0.923880}, {0.707107, -0.707107}, -{0.923880, -0.382684}, {1.000000, -0.000000}, {0.923880, 0.382683}, {0.707107, 0.707107}, -{-0.352077, 0.532607}, {-0.352077, -0.549313}, {0.729843, -0.008353}}; +{0.923880, -0.382684}, {1.000000, -0.000000}, {0.923880, 0.382683}, {0.707107, 0.707107}}; -static int num_tria_face[19][3]= { -{13, 14, 18}, {17, 5, 6}, {12, 13, 18}, {17, 6, 7}, {15, 18, 14}, {16, 4, 5}, {16, 5, 17}, {18, 11, 12}, -{18, 17, 10}, {18, 10, 11}, {17, 9, 10}, {15, 0, 18}, {18, 0, 16}, {3, 4, 16}, {8, 9, 17}, {8, 17, 7}, -{2, 3, 16}, {1, 2, 16}, {16, 0, 1}}; +static int scroll_circle_face[14][3]= { +{0, 1, 2}, {2, 0, 3}, {3, 0, 15}, {3, 15, 4}, {4, 15, 14}, {4, 14, 5}, {5, 14, 13}, {5, 13, 6}, +{6, 13, 12}, {6, 12, 7}, {7, 12, 11}, {7, 11, 8}, {8, 11, 10}, {8, 10, 9}}; static float menu_tria_vert[6][2]= { {-0.41, 0.16}, {0.41, 0.16}, {0, 0.82}, @@ -451,15 +455,50 @@ static void widget_num_tria(uiWidgetTrias *tria, rcti *rect, float triasize, cha i2=0; i1= 1; } - for(a=0; a<19; a++) { + for(a=0; a<3; a++) { tria->vec[a][0]= sizex*num_tria_vert[a][i1] + centx; tria->vec[a][1]= sizey*num_tria_vert[a][i2] + centy; } - tria->tot= 19; + tria->tot= 1; tria->index= num_tria_face; } +static void widget_scroll_circle(uiWidgetTrias *tria, rcti *rect, float triasize, char where) +{ + float centx, centy, sizex, sizey, minsize; + int a, i1=0, i2=1; + + minsize= MIN2(rect->xmax-rect->xmin, rect->ymax-rect->ymin); + + /* center position and size */ + centx= (float)rect->xmin + 0.5f*minsize; + centy= (float)rect->ymin + 0.5f*minsize; + sizex= sizey= -0.5f*triasize*minsize; + + if(where=='r') { + centx= (float)rect->xmax - 0.5f*minsize; + sizex= -sizex; + } + else if(where=='t') { + centy= (float)rect->ymax - 0.5f*minsize; + sizey= -sizey; + i2=0; i1= 1; + } + else if(where=='b') { + sizex= -sizex; + i2=0; i1= 1; + } + + for(a=0; a<16; a++) { + tria->vec[a][0]= sizex*scroll_circle_vert[a][i1] + centx; + tria->vec[a][1]= sizey*scroll_circle_vert[a][i2] + centy; + } + + tria->tot= 14; + tria->index= scroll_circle_face; +} + static void widget_trias_draw(uiWidgetTrias *tria) { int a; @@ -734,7 +773,8 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, int blend, rcti *rect) /* sets but->ofs to make sure text is correctly visible */ static void ui_text_leftclip(uiFontStyle *fstyle, uiBut *but, rcti *rect) { - int okwidth= rect->xmax-rect->xmin; + int border= (but->flag & UI_BUT_ALIGN_RIGHT)? 8: 10; + int okwidth= rect->xmax-rect->xmin - border; /* need to set this first */ uiStyleFontSet(fstyle); @@ -803,11 +843,8 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b but->drawstr[selend_tmp]= ch; - /* if at pos 0, leave a bit more to the left */ - t= (pos == 0)? 0: 1; - glColor3ubv((unsigned char*)wcol->item); - glRects(rect->xmin+selsta_draw+1, rect->ymin+2, rect->xmin+selwidth_draw+1, rect->ymax-2); + glRects(rect->xmin+selsta_draw, rect->ymin+2, rect->xmin+selwidth_draw, rect->ymax-2); } } else { /* text cursor */ @@ -822,9 +859,6 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b but->drawstr[pos]= ch; } - /* if at pos 0, leave a bit more to the left */ - t += (pos == 0)? 0: 1; - glColor3ub(255,0,0); glRects(rect->xmin+t, rect->ymin+2, rect->xmin+t+2, rect->ymax-2); } @@ -1736,12 +1770,12 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int stat wcol->item[3]= 255; if(horizontal) { - widget_num_tria(&wtb.tria1, slider, 0.6f, 'l'); - widget_num_tria(&wtb.tria2, slider, 0.6f, 'r'); + widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'l'); + widget_scroll_circle(&wtb.tria2, slider, 0.6f, 'r'); } else { - widget_num_tria(&wtb.tria1, slider, 0.6f, 'b'); - widget_num_tria(&wtb.tria2, slider, 0.6f, 't'); + widget_scroll_circle(&wtb.tria1, slider, 0.6f, 'b'); + widget_scroll_circle(&wtb.tria2, slider, 0.6f, 't'); } } widgetbase_draw(&wtb, wcol); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index c54e09b2b40..87026bd1a5d 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -517,10 +517,12 @@ void ui_theme_init_userdef(void) /* space file */ /* to have something initialized */ btheme->tfile= btheme->tv3d; - SETCOL(btheme->tfile.back, 90, 90, 90, 255); + SETCOLF(btheme->tfile.back, 0.3, 0.3, 0.3, 1); + SETCOLF(btheme->tfile.panel, 0.3, 0.3, 0.3, 1); + SETCOLF(btheme->tfile.list, 0.4, 0.4, 0.4, 1); SETCOL(btheme->tfile.text, 250, 250, 250, 255); SETCOL(btheme->tfile.text_hi, 15, 15, 15, 255); - SETCOL(btheme->tfile.panel, 180, 180, 180, 255); // bookmark/ui regions + SETCOL(btheme->tfile.panel, 145, 145, 145, 255); // bookmark/ui regions SETCOL(btheme->tfile.active, 130, 130, 130, 255); // selected files SETCOL(btheme->tfile.hilite, 255, 140, 25, 255); // selected files @@ -604,11 +606,11 @@ void ui_theme_init_userdef(void) /* space node, re-uses syntax color storage */ btheme->tnode= btheme->tv3d; SETCOL(btheme->tnode.edge_select, 255, 255, 255, 255); - SETCOL(btheme->tnode.syntaxl, 150, 150, 150, 255); /* TH_NODE, backdrop */ - SETCOL(btheme->tnode.syntaxn, 129, 131, 144, 255); /* in/output */ - SETCOL(btheme->tnode.syntaxb, 127,127,127, 255); /* operator */ - SETCOL(btheme->tnode.syntaxv, 142, 138, 145, 255); /* generator */ - SETCOL(btheme->tnode.syntaxc, 120, 145, 120, 255); /* group */ + SETCOL(btheme->tnode.syntaxl, 155, 155, 155, 160); /* TH_NODE, backdrop */ + SETCOL(btheme->tnode.syntaxn, 100, 100, 100, 255); /* in/output */ + SETCOL(btheme->tnode.syntaxb, 108, 105, 111, 255); /* operator */ + SETCOL(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */ + SETCOL(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */ /* space logic */ btheme->tlogic= btheme->tv3d; diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index f9fb7a9306f..f7546e94f86 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -831,6 +831,7 @@ void UI_view2d_totRect_set_resize (View2D *v2d, int width, int height, int resiz height= abs(height); /* hrumf! */ + /* XXX: there are work arounds for this in the panel and file browse code. */ if(scroll & V2D_SCROLL_HORIZONTAL) width -= V2D_SCROLL_WIDTH; if(scroll & V2D_SCROLL_VERTICAL) @@ -973,8 +974,8 @@ void UI_view2d_view_ortho(const bContext *C, View2D *v2d) /* XXX brecht: instead of zero at least use a tiny offset, otherwise * pixel rounding is effectively random due to float inaccuracy */ - xofs= 0.001f; - yofs= 0.001f; + xofs= 0.001f*(v2d->cur.xmax - v2d->cur.xmin)/(v2d->mask.xmax - v2d->mask.xmin); + yofs= 0.001f*(v2d->cur.ymax - v2d->cur.ymin)/(v2d->mask.ymax - v2d->mask.ymin); /* apply mask-based adjustments to cur rect (due to scrollers), to eliminate scaling artifacts */ view2d_map_cur_using_mask(v2d, &curmasked); @@ -1351,7 +1352,7 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short vert= v2d->vert; hor= v2d->hor; - /* slider rects smaller than region */ + /* slider rects need to be smaller than region */ hor.xmin+=4; hor.xmax-=4; if (scroll & V2D_SCROLL_BOTTOM) @@ -1393,13 +1394,24 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short else scrollers->hor_max= (int)(hor.xmin + (fac2 * scrollsize)); + /* prevent inverted sliders */ if (scrollers->hor_min > scrollers->hor_max) scrollers->hor_min= scrollers->hor_max; + /* prevent sliders from being too small, and disappearing */ + if ((scrollers->hor_max - scrollers->hor_min) < V2D_SCROLLER_HANDLE_SIZE) { + scrollers->hor_max= scrollers->hor_min + V2D_SCROLLER_HANDLE_SIZE; + + if(scrollers->hor_max > hor.xmax) { + scrollers->hor_max= hor.xmax; + scrollers->hor_min= MAX2(scrollers->hor_max - V2D_SCROLLER_HANDLE_SIZE, hor.xmin); + } + } /* check whether sliders can disappear */ - if(v2d->keeptot) + if(v2d->keeptot) { if(fac1 <= 0.0f && fac2 >= 1.0f) scrollers->horfull= 1; + } } /* vertical scrollers */ @@ -1420,13 +1432,24 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short else scrollers->vert_max= (int)(vert.ymin + (fac2 * scrollsize)); + /* prevent inverted sliders */ if (scrollers->vert_min > scrollers->vert_max) scrollers->vert_min= scrollers->vert_max; + /* prevent sliders from being too small, and disappearing */ + if ((scrollers->vert_max - scrollers->vert_min) < V2D_SCROLLER_HANDLE_SIZE) { + scrollers->vert_max= scrollers->vert_min + V2D_SCROLLER_HANDLE_SIZE; + + if(scrollers->vert_max > vert.ymax) { + scrollers->vert_max= vert.ymax; + scrollers->vert_min= MAX2(scrollers->vert_max - V2D_SCROLLER_HANDLE_SIZE, vert.ymin); + } + } /* check whether sliders can disappear */ - if(v2d->keeptot) + if(v2d->keeptot) { if(fac1 <= 0.0f && fac2 >= 1.0f) scrollers->vertfull= 1; + } } /* grid markings on scrollbars */ @@ -1550,14 +1573,6 @@ static void scroll_printstr(View2DScrollers *scrollers, Scene *scene, float x, f BLF_draw_default(x, y, 0.0f, str); } -/* local defines for scrollers drawing */ - /* radius of scroller 'button' caps */ -#define V2D_SCROLLCAP_RAD 5 - /* shading factor for scroller 'bar' */ -#define V2D_SCROLLBAR_SHADE 0.1f - /* shading factor for scroller 'button' caps */ -#define V2D_SCROLLCAP_SHADE 0.2f - /* Draw scrollbars in the given 2d-region */ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *vs) { @@ -1571,7 +1586,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v /* horizontal scrollbar */ if (scroll & V2D_SCROLL_HORIZONTAL) { - + /* only draw scrollbar when it doesn't fill the entire space */ if(vs->horfull==0) { bTheme *btheme= U.themes.first; uiWidgetColors wcol= btheme->tui.wcol_scroll; @@ -1584,13 +1599,15 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v slider.ymax= hor.ymax; state= (v2d->scroll_ui & V2D_SCROLL_H_ACTIVE)?UI_SCROLL_PRESSED:0; + + // TODO: disable this for button regions... if (!(v2d->keepzoom & V2D_LOCKZOOM_X)) state |= UI_SCROLL_ARROWS; + uiWidgetScrollDraw(&wcol, &hor, &slider, state); } /* scale indicators */ - // XXX will need to update the font drawing when the new stuff comes in if ((scroll & V2D_SCROLL_SCALE_HORIZONTAL) && (vs->grid)) { View2DGrid *grid= vs->grid; float fac, dfac, fac2, val; @@ -1667,7 +1684,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v /* vertical scrollbar */ if (scroll & V2D_SCROLL_VERTICAL) { - + /* only draw scrollbar when it doesn't fill the entire space */ if(vs->vertfull==0) { bTheme *btheme= U.themes.first; uiWidgetColors wcol= btheme->tui.wcol_scroll; @@ -1680,14 +1697,16 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v slider.ymax= vs->vert_max; state= (v2d->scroll_ui & V2D_SCROLL_V_ACTIVE)?UI_SCROLL_PRESSED:0; - if (!(v2d->keepzoom & V2D_LOCKZOOM_Y)) + + // TODO: disable this for button regions... + if (!(v2d->keepzoom & V2D_LOCKZOOM_Y)) state |= UI_SCROLL_ARROWS; + uiWidgetScrollDraw(&wcol, &vert, &slider, state); } /* scale indiators */ - // XXX will need to update the font drawing when the new stuff comes in if ((scroll & V2D_SCROLL_SCALE_VERTICAL) && (vs->grid)) { View2DGrid *grid= vs->grid; float fac, dfac, val; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 3e009884dee..0af5a5cac97 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -210,7 +210,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) WM_cursor_modal(window, BC_NSEW_SCROLLCURSOR); /* add temp handler */ - WM_event_add_modal_handler(C, &window->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -237,7 +237,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event) case LEFTMOUSE: case MIDDLEMOUSE: - if (event->val==0) { + if (event->val==KM_RELEASE) { /* calculate overall delta mouse-movement for redo */ RNA_int_set(op->ptr, "deltax", (vpd->startx - vpd->lastx)); RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty)); @@ -764,7 +764,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event) WM_cursor_modal(window, BC_NSEW_SCROLLCURSOR); /* add temp handler */ - WM_event_add_modal_handler(C, &window->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -836,7 +836,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event) case LEFTMOUSE: case MIDDLEMOUSE: - if (event->val==0) { + if (event->val==KM_RELEASE) { /* for redo, store the overall deltas - need to respect zoom-locks here... */ if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) RNA_float_set(op->ptr, "deltax", vzd->dx); @@ -1244,7 +1244,7 @@ static int scroller_activate_modal(bContext *C, wmOperator *op, wmEvent *event) break; case LEFTMOUSE: - if (event->val==0) { + if (event->val==KM_RELEASE) { scroller_activate_exit(C, op); return OPERATOR_FINISHED; } @@ -1292,7 +1292,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event) v2d->scroll_ui |= V2D_SCROLL_V_ACTIVE; /* still ok, so can add */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } else { @@ -1409,7 +1409,7 @@ void ui_view2d_operatortypes(void) void UI_view2d_keymap(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "View2D", 0, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "View2D", 0, 0); /* pan/scroll */ WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, 0, 0); @@ -1445,7 +1445,7 @@ void UI_view2d_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "VIEW2D_OT_scroller_activate", LEFTMOUSE, KM_PRESS, 0, 0); /* Alternative keymap for buttons listview */ - keymap= WM_keymap_listbase(wm, "View2D Buttons List", 0, 0); + keymap= WM_keymap_find(wm, "View2D Buttons List", 0, 0); WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/editors/mesh/editmesh_loop.c b/source/blender/editors/mesh/editmesh_loop.c index c98b387d28a..28103828dd4 100644 --- a/source/blender/editors/mesh/editmesh_loop.c +++ b/source/blender/editors/mesh/editmesh_loop.c @@ -60,6 +60,7 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv #include "BKE_library.h" #include "BKE_mesh.h" #include "BKE_object.h" +#include "BKE_report.h" #include "BKE_utildefines.h" #include "PIL_time.h" @@ -637,6 +638,10 @@ static int knife_cut_exec(bContext *C, wmOperator *op) int len=0; short numcuts=1, mode= RNA_int_get(op->ptr, "type"); + /* edit-object needed for matrix, and ar->regiondata for projections to work */ + if (ELEM3(NULL, obedit, ar, ar->regiondata)) + return OPERATOR_CANCELLED; + if (EM_nvertices_selected(em) < 2) { error("No edges are selected to operate on"); BKE_mesh_end_editmesh(obedit->data, em); diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c index 7301901aff5..325a1aeec99 100644 --- a/source/blender/editors/mesh/editmesh_mods.c +++ b/source/blender/editors/mesh/editmesh_mods.c @@ -761,7 +761,7 @@ static int similar_face_select__internal(Scene *scene, EditMesh *em, int mode) float angle; for(efa= em->faces.first; efa; efa= efa->next) { if (!(efa->f & SELECT) && !efa->h) { - angle= VecAngle2(base_efa->n, efa->n); + angle= RAD2DEG(VecAngle2(base_efa->n, efa->n)); if (angle/180.0<=thresh) { EM_select_face(efa, 1); selcount++; @@ -776,7 +776,7 @@ static int similar_face_select__internal(Scene *scene, EditMesh *em, int mode) base_dot= Inpf(base_efa->cent, base_efa->n); for(efa= em->faces.first; efa; efa= efa->next) { if (!(efa->f & SELECT) && !efa->h) { - angle= VecAngle2(base_efa->n, efa->n); + angle= RAD2DEG(VecAngle2(base_efa->n, efa->n)); if (angle/180.0<=thresh) { dot=Inpf(efa->cent, base_efa->n); if (fabs(base_dot-dot) <= thresh) { @@ -916,7 +916,7 @@ static int similar_edge_select__internal(ToolSettings *ts, EditMesh *em, int mod else if (eed->f2==0) /* first access, assign the face */ eed->tmp.f= efa; else if (eed->f2==1) /* second, we assign the angle*/ - eed->tmp.fp= VecAngle2(eed->tmp.f->n, efa->n)/180; + eed->tmp.fp= RAD2DEG(VecAngle2(eed->tmp.f->n, efa->n))/180; eed->f2++; /* f2==0 no face assigned. f2==1 one face found. f2==2 angle calculated.*/ } j++; @@ -946,7 +946,7 @@ static int similar_edge_select__internal(ToolSettings *ts, EditMesh *em, int mod for(eed= em->edges.first; eed; eed= eed->next) { if (!(eed->f & SELECT) && !eed->h) { VecSubf(dir, eed->v1->co, eed->v2->co); - angle= VecAngle2(base_dir, dir); + angle= RAD2DEG(VecAngle2(base_dir, dir)); if (angle>90) /* use the smallest angle between the edges */ angle= fabs(angle-180.0f); @@ -1137,7 +1137,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) float angle; for(eve= em->verts.first; eve; eve= eve->next) { if (!(eve->f & SELECT) && !eve->h) { - angle= VecAngle2(base_eve->no, eve->no); + angle= RAD2DEG(VecAngle2(base_eve->no, eve->no)); if (angle/180.0<=thresh) { eve->f |= SELECT; selcount++; @@ -2033,6 +2033,9 @@ static void mouse_mesh_loop(bContext *C, short mval[2], short extend, short ring vc.mval[0]= mval[0]; vc.mval[1]= mval[1]; em= vc.em; + + /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ + view3d_validate_backbuf(&vc); eed= findnearestedge(&vc, &dist); if(eed) { @@ -2110,6 +2113,9 @@ static void mouse_mesh_shortest_path(bContext *C, short mval[2]) vc.mval[1]= mval[1]; em= vc.em; + /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ + view3d_validate_backbuf(&vc); + eed= findnearestedge(&vc, &dist); if(eed) { Mesh *me= vc.obedit->data; @@ -3287,6 +3293,11 @@ void EM_toggle_select_all(EditMesh *em) /* exported for UV */ EM_set_flag_all(em, SELECT); } +void EM_select_all(EditMesh *em) +{ + EM_set_flag_all(em, SELECT); +} + static int toggle_select_all_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); @@ -3547,7 +3558,7 @@ void MESH_OT_select_random(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* props */ - RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "Percentage of vertices to select randomly.", 0.0001f, 1.0f); + RNA_def_float_percentage(ot->srna, "percent", 50.0f, 0.0f, 100.0f, "Percent", "Percentage of vertices to select randomly.", 0.0001f, 1.0f); } void EM_select_by_material(EditMesh *em, int index) diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 7698faf3178..510f6ab464b 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -140,7 +140,7 @@ static int vergface(const void *v1, const void *v2) /* *********************************** */ -void convert_to_triface(EditMesh *em, int direction) +static void convert_to_triface(EditMesh *em, int direction) { EditFace *efa, *efan, *next; float fac; @@ -482,10 +482,8 @@ int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) / static int removedoublesflag_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); - ToolSettings *ts= CTX_data_tool_settings(C); EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - char msg[100]; - + /*char msg[100];*/ int cnt = removedoublesflag(em,1,0,RNA_float_get(op->ptr, "limit")); /*XXX this messes up last operator panel @@ -516,7 +514,7 @@ void MESH_OT_remove_doubles(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - RNA_def_float(ot->srna, "limit", 0.00001f, 0.000001f, 50.0f, "Merge Threshold", "Minimum distance between merged verts", 0.00001f, 10.0f); + RNA_def_float(ot->srna, "limit", 0.0001f, 0.000001f, 50.0f, "Merge Threshold", "Minimum distance between merged verts", 0.00001f, 2.0f); } // XXX is this needed? @@ -3122,13 +3120,13 @@ static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert CalcNormFloat(v1->co, v3->co, v4->co, noA2); if(noA1[0] == noA2[0] && noA1[1] == noA2[1] && noA1[2] == noA2[2]) normalADiff = 0.0; - else normalADiff = VecAngle2(noA1, noA2); + else normalADiff = RAD2DEG(VecAngle2(noA1, noA2)); //if(!normalADiff) normalADiff = 179; CalcNormFloat(v2->co, v3->co, v4->co, noB1); CalcNormFloat(v4->co, v1->co, v2->co, noB2); if(noB1[0] == noB2[0] && noB1[1] == noB2[1] && noB1[2] == noB2[2]) normalBDiff = 0.0; - else normalBDiff = VecAngle2(noB1, noB2); + else normalBDiff = RAD2DEG(VecAngle2(noB1, noB2)); //if(!normalBDiff) normalBDiff = 179; measure += (normalADiff/360) + (normalBDiff/360); @@ -3143,10 +3141,10 @@ static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert diff = 0.0; diff = ( - fabs(VecAngle2(edgeVec1, edgeVec2) - 90) + - fabs(VecAngle2(edgeVec2, edgeVec3) - 90) + - fabs(VecAngle2(edgeVec3, edgeVec4) - 90) + - fabs(VecAngle2(edgeVec4, edgeVec1) - 90)) / 360; + fabs(RAD2DEG(VecAngle2(edgeVec1, edgeVec2)) - 90) + + fabs(RAD2DEG(VecAngle2(edgeVec2, edgeVec3)) - 90) + + fabs(RAD2DEG(VecAngle2(edgeVec3, edgeVec4)) - 90) + + fabs(RAD2DEG(VecAngle2(edgeVec4, edgeVec1)) - 90)) / 360; if(!diff) return 0.0; measure += diff; @@ -3869,11 +3867,11 @@ typedef struct SlideVert { EditVert origvert; } SlideVert; +#if 0 int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc) { return 0; /* XXX REFACTOR - #if 0'd for now, otherwise can't make 64bit windows builds on 64bit machine */ -#if 0 useless: goto useless // because it doesn't do anything right now @@ -4655,11 +4653,12 @@ useless: } return 1; -#endif // END OF XXX } +#endif // END OF XXX int EdgeLoopDelete(EditMesh *em, wmOperator *op) { +#if 0 //XXX won't work with new edgeslide /* temporal flag setting so we keep UVs when deleting edge loops, * this is a bit of a hack but it works how you would want in almost all cases */ @@ -4678,6 +4677,8 @@ int EdgeLoopDelete(EditMesh *em, wmOperator *op) EM_select_flush(em); // DAG_id_flush_update(obedit->data, OB_RECALC_DATA); return 1; +#endif + return 0; } @@ -5636,7 +5637,7 @@ static void collapseuvs(EditMesh *em, EditVert *mergevert) } } -int collapseEdges(EditMesh *em) +static int collapseEdges(EditMesh *em) { EditVert *eve; EditEdge *eed; @@ -5702,7 +5703,7 @@ int collapseEdges(EditMesh *em) return mergecount; } -int merge_firstlast(EditMesh *em, int first, int uvmerge) +static int merge_firstlast(EditMesh *em, int first, int uvmerge) { EditVert *eve,*mergevert; EditSelection *ese; @@ -5736,7 +5737,7 @@ int merge_firstlast(EditMesh *em, int first, int uvmerge) return removedoublesflag(em, 1, 0, MERGELIMIT); } -void em_snap_to_center(EditMesh *em) +static void em_snap_to_center(EditMesh *em) { EditVert *eve; float cent[3] = {0.0f, 0.0f, 0.0f}; @@ -5761,7 +5762,7 @@ void em_snap_to_center(EditMesh *em) } } -void em_snap_to_cursor(EditMesh *em, bContext *C) +static void em_snap_to_cursor(EditMesh *em, bContext *C) { Scene *scene = CTX_data_scene(C); Object *ob= CTX_data_edit_object(C); @@ -5782,7 +5783,7 @@ void em_snap_to_cursor(EditMesh *em, bContext *C) } } -int merge_target(bContext *C, EditMesh *em, int target, int uvmerge) +static int merge_target(bContext *C, EditMesh *em, int target, int uvmerge) { EditVert *eve; @@ -5925,7 +5926,7 @@ typedef struct PathEdge { #define PATH_SELECT_EDGE_LENGTH 0 #define PATH_SELECT_TOPOLOGICAL 1 -int select_vertex_path_exec(bContext *C, wmOperator *op) +static int select_vertex_path_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); @@ -7138,7 +7139,7 @@ void MESH_OT_edge_flip(wmOperatorType *ot) /********************** Smooth/Solid Operators *************************/ -void mesh_set_smooth_faces(EditMesh *em, short smooth) +static void mesh_set_smooth_faces(EditMesh *em, short smooth) { EditFace *efa; diff --git a/source/blender/editors/mesh/loopcut.c b/source/blender/editors/mesh/loopcut.c index c7e10d5809f..d1ef4ebc233 100644 --- a/source/blender/editors/mesh/loopcut.c +++ b/source/blender/editors/mesh/loopcut.c @@ -93,6 +93,7 @@ typedef struct tringselOpData { EditEdge *eed; int extend; + int do_cut; } tringselOpData; /* modal loop selection drawing callback */ @@ -128,7 +129,7 @@ static void edgering_sel(tringselOpData *lcd, int previewlines, int select) float (*edges)[2][3] = NULL; V_DYNDECLARE(edges); float co[2][3]; - int looking=1, i, j=0, tot=0; + int looking=1, i, tot=0; if (!startedge) return; @@ -258,8 +259,17 @@ static void ringsel_finish(bContext *C, wmOperator *op) { tringselOpData *lcd= op->customdata; - if (lcd->eed); + if (lcd->eed) { edgering_sel(lcd, 0, 1); + if (lcd->do_cut) { + EditMesh *em = BKE_mesh_get_editmesh(lcd->ob->data); + esubdivideflag(lcd->ob, em, SELECT, 0.0f, + 0.0f, 0, 1, SUBDIV_SELECT_LOOPCUT); + + DAG_id_flush_update(lcd->ob->data, OB_RECALC_DATA); + } + WM_event_add_notifier(C, NC_GEOM|ND_DATA, lcd->ob->data); + } } /* called when modal loop selection is done... */ @@ -281,7 +291,7 @@ static void ringsel_exit (bContext *C, wmOperator *op) } /* called when modal loop selection gets set up... */ -static int ringsel_init (bContext *C, wmOperator *op) +static int ringsel_init (bContext *C, wmOperator *op, int do_cut) { tringselOpData *lcd; @@ -293,7 +303,8 @@ static int ringsel_init (bContext *C, wmOperator *op) lcd->draw_handle= ED_region_draw_cb_activate(lcd->ar->type, ringsel_draw, lcd, REGION_DRAW_POST); lcd->ob = CTX_data_edit_object(C); lcd->em= BKE_mesh_get_editmesh((Mesh *)lcd->ob->data); - lcd->extend = RNA_boolean_get(op->ptr, "extend"); + lcd->extend = do_cut ? 0 : RNA_boolean_get(op->ptr, "extend"); + lcd->do_cut = do_cut; em_setup_viewcontext(C, &lcd->vc); ED_region_tag_redraw(lcd->ar); @@ -310,18 +321,45 @@ static int ringsel_cancel (bContext *C, wmOperator *op) static int ringsel_invoke (bContext *C, wmOperator *op, wmEvent *evt) { - ScrArea *sa = CTX_wm_area(C); tringselOpData *lcd; EditEdge *edge; int dist = 75; view3d_operator_needs_opengl(C); - if (!ringsel_init(C, op)) + if (!ringsel_init(C, op, 0)) return OPERATOR_CANCELLED; /* add a modal handler for this operator - handles loop selection */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); + + lcd = op->customdata; + lcd->vc.mval[0] = evt->mval[0]; + lcd->vc.mval[1] = evt->mval[1]; + + edge = findnearestedge(&lcd->vc, &dist); + if (edge != lcd->eed) { + lcd->eed = edge; + ringsel_find_edge(lcd, C, lcd->ar); + } + + return OPERATOR_RUNNING_MODAL; +} + + +static int ringcut_invoke (bContext *C, wmOperator *op, wmEvent *evt) +{ + tringselOpData *lcd; + EditEdge *edge; + int dist = 75; + + view3d_operator_needs_opengl(C); + + if (!ringsel_init(C, op, 1)) + return OPERATOR_CANCELLED; + + /* add a modal handler for this operator - handles loop selection */ + WM_event_add_modal_handler(C, op); lcd = op->customdata; lcd->vc.mval[0] = evt->mval[0]; @@ -345,7 +383,7 @@ static int ringsel_modal (bContext *C, wmOperator *op, wmEvent *event) switch (event->type) { case RIGHTMOUSE: case LEFTMOUSE: /* confirm */ // XXX hardcoded - if (event->val == 0) { + if (event->val == KM_RELEASE) { /* finish */ ED_region_tag_redraw(lcd->ar); @@ -379,13 +417,12 @@ static int ringsel_modal (bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -// naming is whatever this should use... void MESH_OT_edgering_select (wmOperatorType *ot) { /* description */ - ot->name= "Loop Cut"; + ot->name= "Edge Ring Select"; ot->idname= "MESH_OT_edgering_select"; - ot->description= "Add a new loop between existing loops."; + ot->description= "Select an edge ring"; /* callbacks */ ot->invoke= ringsel_invoke; @@ -398,3 +435,20 @@ void MESH_OT_edgering_select (wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection"); } + +void MESH_OT_loopcut (wmOperatorType *ot) +{ + /* description */ + ot->name= "Loop Cut"; + ot->idname= "MESH_OT_loopcut"; + ot->description= "Add a new loop between existing loops."; + + /* callbacks */ + ot->invoke= ringcut_invoke; + ot->modal= ringsel_modal; + ot->cancel= ringsel_cancel; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; +} diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 887474414b3..37a6d0f384f 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -61,12 +61,6 @@ extern struct EditEdge *addedgelist(EditMesh *em, struct EditVert *v1, struct Ed extern struct EditFace *addfacelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct EditFace *example, struct EditFace *exampleEdges); extern struct EditEdge *findedgelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2); -EditVert *editedge_getOtherVert(EditEdge *eed, EditVert *eve); -EditVert *editedge_getSharedVert(EditEdge *eed, EditEdge *eed2); -int editedge_containsVert(struct EditEdge *eed, struct EditVert *eve); -int editface_containsVert(struct EditFace *efa, struct EditVert *eve); -int editface_containsEdge(struct EditFace *efa, struct EditEdge *eed); - void em_setup_viewcontext(struct bContext *C, ViewContext *vc); void MESH_OT_separate(struct wmOperatorType *ot); @@ -243,6 +237,7 @@ void MESH_OT_sticky_add(struct wmOperatorType *ot); void MESH_OT_sticky_remove(struct wmOperatorType *ot); void MESH_OT_edgering_select(struct wmOperatorType *ot); +void MESH_OT_loopcut(struct wmOperatorType *ot); #endif // MESH_INTERN_H diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 606614cd1f1..21148e59153 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -113,6 +113,7 @@ static int edge_specials_invoke(bContext *C, wmOperator *op, wmEvent *event) uiItemEnumO(layout, "Rotate Edge CCW", 0, "MESH_OT_edge_rotate", "direction", 2); //uiItemO(layout, "Loopcut", 0, "MESH_OT_loop_cut"); // CutEdgeloop(em, 1); //uiItemO(layout, "Edge Slide", 0, "MESH_OT_edge_slide"); // EdgeSlide(em, 0,0.0); + uiItemO(layout, "Edge Slide", 0, "TFM_OT_edge_slide"); uiItemO(layout, "Edge Loop", 0, "MESH_OT_loop_multi_select"); uiItemBooleanO(layout, "Edge Ring", 0, "MESH_OT_loop_multi_select", "ring", 1); uiItemO(layout, NULL, 0, "MESH_OT_loop_to_region"); @@ -321,8 +322,17 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_specials); WM_operatortype_append(MESH_OT_edgering_select); + WM_operatortype_append(MESH_OT_loopcut); /* macros */ + + /*combining operators with invoke and exec portions doesn't work yet. + + ot= WM_operatortype_append_macro("MESH_OT_loopcut", "Loopcut", OPTYPE_UNDO|OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "MESH_OT_edgering_select"); + WM_operatortype_macro_define(ot, "MESH_OT_subdivide"); + */ + ot= WM_operatortype_append_macro("MESH_OT_duplicate_move", "Add Duplicate", OPTYPE_UNDO|OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "MESH_OT_duplicate"); WM_operatortype_macro_define(ot, "TFM_OT_translate"); @@ -335,21 +345,18 @@ void ED_operatortypes_mesh(void) WM_operatortype_macro_define(ot, "MESH_OT_extrude"); WM_operatortype_macro_define(ot, "TFM_OT_translate"); - /*combining operators with invoke and exec portions doesn't work yet. - - ot= WM_operatortype_append_macro("MESH_OT_loopcut", "Loopcut", OPTYPE_UNDO|OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "MESH_OT_edgering_select"); - WM_operatortype_macro_define(ot, "MESH_OT_subdivide"); - */ } /* note mesh keymap also for other space? */ void ED_keymap_mesh(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "EditMesh", 0, 0); + wmKeyMap *keymap; wmKeymapItem *kmi; - //WM_keymap_add_item(keymap, "MESH_OT_loopcut", RKEY, KM_PRESS, KM_CTRL, 0); + keymap= WM_keymap_find(wm, "EditMesh", 0, 0); + keymap->poll= ED_operator_editmesh; + + WM_keymap_add_item(keymap, "MESH_OT_loopcut", RKEY, KM_PRESS, KM_CTRL, 0); /* selecting */ /* standard mouse selection goes via space_view3d */ @@ -422,7 +429,7 @@ void ED_keymap_mesh(wmWindowManager *wm) WM_keymap_add_item(keymap, "MESH_OT_edge_face_add", FKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MESH_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "OBJECT_OT_mesh_add", AKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "MESH_OT_separate", PKEY, KM_PRESS, 0, 0); /* use KM_RELEASE because same key is used for tweaks */ WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", LEFTMOUSE, KM_RELEASE, KM_CTRL, 0); @@ -431,7 +438,7 @@ void ED_keymap_mesh(wmWindowManager *wm) WM_keymap_add_item(keymap, "MESH_OT_fgon_make", FKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MESH_OT_fgon_clear", FKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0); - WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, XKEY); + WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, 0, KKEY); /* menus */ WM_keymap_add_item(keymap, "MESH_OT_vertex_specials", VKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 4aa99820a6e..00893f10165 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -632,7 +632,7 @@ void sort_faces(Scene *scene, View3D *v3d) if (event == 1) Mat4MulMat4(mat, OBACT->obmat, rv3d->viewmat); /* apply the view matrix to the object matrix */ else if (event == 2) { /* sort from cursor */ - if( v3d && v3d->localview ) { + if( v3d && v3d->localvd ) { VECCOPY(cur, v3d->cursor); } else { VECCOPY(cur, scene->cursor); diff --git a/source/blender/editors/metaball/mball_ops.c b/source/blender/editors/metaball/mball_ops.c index 38593af372f..dd8a18f385c 100644 --- a/source/blender/editors/metaball/mball_ops.c +++ b/source/blender/editors/metaball/mball_ops.c @@ -34,6 +34,8 @@ #include "DNA_listBase.h" #include "DNA_windowmanager_types.h" +#include "ED_screen.h" + #include "mball_intern.h" void ED_operatortypes_metaball(void) @@ -51,7 +53,10 @@ void ED_operatortypes_metaball(void) void ED_keymap_metaball(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Metaball", 0, 0); + wmKeyMap *keymap; + + keymap= WM_keymap_find(wm, "Metaball", 0, 0); + keymap->poll= ED_operator_editmball; WM_keymap_add_item(keymap, "OBJECT_OT_metaball_add", AKEY, KM_PRESS, KM_SHIFT, 0); @@ -60,6 +65,7 @@ void ED_keymap_metaball(wmWindowManager *wm) RNA_enum_set(WM_keymap_add_item(keymap, "MBALL_OT_hide_metaelems", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1); WM_keymap_add_item(keymap, "MBALL_OT_delete_metaelems", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MBALL_OT_delete_metaelems", DELKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MBALL_OT_duplicate_metaelems", DKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "MBALL_OT_select_deselect_all_metaelems", AKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/object/Makefile b/source/blender/editors/object/Makefile index 70ada46c80f..fd2af305d87 100644 --- a/source/blender/editors/object/Makefile +++ b/source/blender/editors/object/Makefile @@ -47,6 +47,7 @@ CPPFLAGS += -I../../makesdna CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../python CPPFLAGS += -I../../imbuf +CPPFLAGS += -I../../ikplugin # own include diff --git a/source/blender/editors/object/SConscript b/source/blender/editors/object/SConscript index 3371e172a82..6ecc80f2d81 100644 --- a/source/blender/editors/object/SConscript +++ b/source/blender/editors/object/SConscript @@ -6,7 +6,7 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc' incs += ' #/intern/guardedalloc' -incs += ' ../../makesrna ../../python' +incs += ' ../../makesrna ../../python ../../ikplugin' defs = [] diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 833d3914e47..05905cd42a4 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -32,6 +32,7 @@ #include "DNA_action_types.h" #include "DNA_curve_types.h" #include "DNA_group_types.h" +#include "DNA_lamp_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meta_types.h" @@ -109,7 +110,7 @@ void ED_object_base_init_from_view(bContext *C, Base *base) VECCOPY(ob->loc, scene->cursor); } else { - if (v3d->localview) { + if (v3d->localvd) { base->lay= ob->lay= v3d->layact | v3d->lay; VECCOPY(ob->loc, v3d->cursor); } @@ -165,7 +166,7 @@ static Object *object_add_type(bContext *C, int type) /* for object add operator */ static int object_add_exec(bContext *C, wmOperator *op) { - object_add_type(C, RNA_int_get(op->ptr, "type")); + object_add_type(C, RNA_enum_get(op->ptr, "type")); return OPERATOR_FINISHED; } @@ -467,7 +468,7 @@ static int object_metaball_add_invoke(bContext *C, wmOperator *op, wmEvent *even void OBJECT_OT_metaball_add(wmOperatorType *ot) { /* identifiers */ - ot->name= "Metaball"; + ot->name= "Add Metaball"; ot->description= "Add an metaball object to the scene."; ot->idname= "OBJECT_OT_metaball_add"; @@ -559,6 +560,45 @@ void OBJECT_OT_armature_add(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +static int object_lamp_add_exec(bContext *C, wmOperator *op) +{ + Object *ob; + int type= RNA_enum_get(op->ptr, "type"); + + ob= object_add_type(C, OB_LAMP); + if(ob && ob->data) + ((Lamp*)ob->data)->type= type; + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_lamp_add(wmOperatorType *ot) +{ + static EnumPropertyItem lamp_type_items[] = { + {LA_LOCAL, "POINT", ICON_LAMP_POINT, "Point", "Omnidirectional point light source."}, + {LA_SUN, "SUN", ICON_LAMP_SUN, "Sun", "Constant direction parallel ray light source."}, + {LA_SPOT, "SPOT", ICON_LAMP_SPOT, "Spot", "Directional cone light source."}, + {LA_HEMI, "HEMI", ICON_LAMP_HEMI, "Hemi", "180 degree constant light source."}, + {LA_AREA, "AREA", ICON_LAMP_AREA, "Area", "Directional area light source."}, + {0, NULL, 0, NULL, NULL}}; + + /* identifiers */ + ot->name= "Add Lamp"; + ot->description = "Add a lamp object to the scene."; + ot->idname= "OBJECT_OT_lamp_add"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= object_lamp_add_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_enum(ot->srna, "type", lamp_type_items, 0, "Type", ""); +} + static int object_primitive_add_invoke(bContext *C, wmOperator *op, wmEvent *event) { uiPopupMenu *pup= uiPupMenuBegin(C, "Add Object", 0); @@ -567,7 +607,7 @@ static int object_primitive_add_invoke(bContext *C, wmOperator *op, wmEvent *eve uiItemMenuEnumO(layout, "Mesh", ICON_OUTLINER_OB_MESH, "OBJECT_OT_mesh_add", "type"); uiItemMenuEnumO(layout, "Curve", ICON_OUTLINER_OB_CURVE, "OBJECT_OT_curve_add", "type"); uiItemMenuEnumO(layout, "Surface", ICON_OUTLINER_OB_SURFACE, "OBJECT_OT_surface_add", "type"); - uiItemMenuEnumO(layout, NULL, ICON_OUTLINER_OB_META, "OBJECT_OT_metaball_add", "type"); + uiItemMenuEnumO(layout, "Metaball", ICON_OUTLINER_OB_META, "OBJECT_OT_metaball_add", "type"); uiItemO(layout, "Text", ICON_OUTLINER_OB_FONT, "OBJECT_OT_text_add"); uiItemS(layout); uiItemO(layout, "Armature", ICON_OUTLINER_OB_ARMATURE, "OBJECT_OT_armature_add"); @@ -575,7 +615,7 @@ static int object_primitive_add_invoke(bContext *C, wmOperator *op, wmEvent *eve uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_EMPTY, "OBJECT_OT_add", "type", OB_EMPTY); uiItemS(layout); uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_CAMERA, "OBJECT_OT_add", "type", OB_CAMERA); - uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_LAMP, "OBJECT_OT_add", "type", OB_LAMP); + uiItemMenuEnumO(layout, "Lamp", ICON_OUTLINER_OB_LAMP, "OBJECT_OT_lamp_add", "type"); uiPupMenuEnd(C, pup); @@ -885,7 +925,7 @@ static int convert_poll(bContext *C) static int convert_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); - Base *basen=NULL, *basact, *basedel=NULL; + Base *basen=NULL, *basact=NULL, *basedel=NULL; Object *ob, *ob1, *obact= CTX_data_active_object(C); DerivedMesh *dm; Curve *cu; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 9b073ed5878..8c0da354938 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -56,6 +56,7 @@ #include "BKE_object.h" #include "BKE_report.h" #include "BKE_utildefines.h" +#include "BIK_api.h" #ifndef DISABLE_PYTHON #include "BPY_extern.h" @@ -334,6 +335,7 @@ static void test_constraints (Object *owner, const char substring[]) * optional... otherwise poletarget must exist too or else * the constraint is deemed invalid */ + /* default IK check ... */ if (exist_object(data->tar) == 0) { data->tar = NULL; curcon->flag |= CONSTRAINT_DISABLE; @@ -355,7 +357,8 @@ static void test_constraints (Object *owner, const char substring[]) } } } - + /* ... can be overwritten here */ + BIK_test_constraint(owner, curcon); /* targets have already been checked for this */ continue; } @@ -702,6 +705,25 @@ void ED_object_constraint_set_active(Object *ob, bConstraint *con) } } +void ED_object_constraint_update(Object *ob) +{ + + if(ob->pose) update_pose_constraint_flags(ob->pose); + + object_test_constraints(ob); + + if(ob->type==OB_ARMATURE) DAG_id_flush_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB); + else DAG_id_flush_update(&ob->id, OB_RECALC_OB); +} + +void ED_object_constraint_dependency_update(Scene *scene, Object *ob) +{ + ED_object_constraint_update(ob); + + if(ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels + DAG_scene_sort(scene); +} + static int constraint_poll(bContext *C) { PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); @@ -717,6 +739,10 @@ static int constraint_delete_exec (bContext *C, wmOperator *op) /* remove constraint itself */ lb= get_active_constraints(ob); + if (BLI_findindex(lb, con) == -1) + /* abnormal situation which happens on bone constraint when the armature is not in pose mode */ + return OPERATOR_CANCELLED; + free_constraint_data(con); BLI_freelinkN(lb, con); @@ -823,17 +849,22 @@ void CONSTRAINT_OT_move_up (wmOperatorType *ot) static int pose_constraints_clear_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_active_object(C); + Scene *scene= CTX_data_scene(C); /* free constraints for all selected bones */ CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) { free_constraints(&pchan->constraints); + pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_CONST); } CTX_DATA_END; + /* force depsgraph to get recalculated since relationships removed */ + DAG_scene_sort(scene); /* sort order of objects */ + /* do updates */ - DAG_id_flush_update(&ob->id, OB_RECALC_OB); - WM_event_add_notifier(C, NC_OBJECT|ND_POSE|ND_CONSTRAINT|NA_REMOVED, ob); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); return OPERATOR_FINISHED; } @@ -854,14 +885,18 @@ void POSE_OT_constraints_clear(wmOperatorType *ot) static int object_constraints_clear_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_active_object(C); + Scene *scene= CTX_data_scene(C); /* do freeing */ // TODO: we should free constraints for all selected objects instead (to be more consistent with bones) free_constraints(&ob->constraints); + /* force depsgraph to get recalculated since relationships removed */ + DAG_scene_sort(scene); /* sort order of objects */ + /* do updates */ DAG_id_flush_update(&ob->id, OB_RECALC_OB); - WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT|NA_REMOVED, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); return OPERATOR_FINISHED; } @@ -910,7 +945,6 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o /* restricted target-type constraints -------------- */ /* NOTE: for these, we cannot try to add a target object if no valid ones are found, since that doesn't work */ /* curve-based constraints - set the only_curve and only_ob flags */ - case CONSTRAINT_TYPE_TRACKTO: case CONSTRAINT_TYPE_CLAMPTO: case CONSTRAINT_TYPE_FOLLOWPATH: only_curve= 1; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index e5a8df8cb26..c734a7c606d 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1957,29 +1957,26 @@ static int object_mode_set_compat(bContext *C, wmOperator *op, Object *ob) ObjectMode mode = RNA_enum_get(op->ptr, "mode"); if(ob) { + if(mode == OB_MODE_OBJECT) + return 1; + switch(ob->type) { - case OB_EMPTY: - case OB_LAMP: - case OB_CAMERA: - if(mode & OB_MODE_OBJECT) - return 1; - return 0; case OB_MESH: - if(mode & ( OB_MODE_OBJECT|OB_MODE_EDIT|OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT|OB_MODE_PARTICLE_EDIT)) + if(mode & (OB_MODE_EDIT|OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT|OB_MODE_PARTICLE_EDIT)) return 1; return 0; case OB_CURVE: case OB_SURF: case OB_FONT: case OB_MBALL: - if(mode & (OB_MODE_OBJECT|OB_MODE_EDIT)) + if(mode & (OB_MODE_EDIT)) return 1; return 0; case OB_LATTICE: - if(mode & (OB_MODE_OBJECT|OB_MODE_EDIT|OB_MODE_WEIGHT_PAINT)) + if(mode & (OB_MODE_EDIT|OB_MODE_WEIGHT_PAINT)) return 1; case OB_ARMATURE: - if(mode & (OB_MODE_OBJECT|OB_MODE_EDIT|OB_MODE_POSE)) + if(mode & (OB_MODE_EDIT|OB_MODE_POSE)) return 1; } } @@ -2036,7 +2033,7 @@ void OBJECT_OT_mode_set(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - prop= RNA_def_enum(ot->srna, "mode", object_mode_items, 0, "Mode", ""); + prop= RNA_def_enum(ot->srna, "mode", object_mode_items, OB_MODE_OBJECT, "Mode", ""); RNA_def_enum_funcs(prop, object_mode_set_itemsf); RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", ""); diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 7d52e9c7c56..87c4560916d 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -79,6 +79,7 @@ void OBJECT_OT_select_by_layer(struct wmOperatorType *ot); void OBJECT_OT_select_linked(struct wmOperatorType *ot); void OBJECT_OT_select_grouped(struct wmOperatorType *ot); void OBJECT_OT_select_mirror(struct wmOperatorType *ot); +void OBJECT_OT_select_name(struct wmOperatorType *ot); /* object_add.c */ void OBJECT_OT_add(struct wmOperatorType *ot); @@ -88,6 +89,7 @@ void OBJECT_OT_surface_add(struct wmOperatorType *ot); void OBJECT_OT_metaball_add(struct wmOperatorType *ot); void OBJECT_OT_text_add(struct wmOperatorType *ot); void OBJECT_OT_armature_add(struct wmOperatorType *ot); +void OBJECT_OT_lamp_add(struct wmOperatorType *ot); void OBJECT_OT_primitive_add(struct wmOperatorType *ot); /* only used as menu */ void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index ddcecdeb1f1..7397cead505 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -102,6 +102,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_select_linked); WM_operatortype_append(OBJECT_OT_select_grouped); WM_operatortype_append(OBJECT_OT_select_mirror); + WM_operatortype_append(OBJECT_OT_select_name); /* XXX - weak, not compat with linked objects */ WM_operatortype_append(GROUP_OT_group_create); WM_operatortype_append(GROUP_OT_objects_remove); @@ -114,6 +115,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_text_add); WM_operatortype_append(OBJECT_OT_surface_add); WM_operatortype_append(OBJECT_OT_armature_add); + WM_operatortype_append(OBJECT_OT_lamp_add); WM_operatortype_append(OBJECT_OT_add); WM_operatortype_append(OBJECT_OT_primitive_add); WM_operatortype_append(OBJECT_OT_mesh_add); @@ -183,11 +185,19 @@ void ED_operatortypes_object(void) } } +static int object_mode_poll(bContext *C) +{ + Object *ob= CTX_data_active_object(C); + return (!ob || ob->mode == OB_MODE_OBJECT); +} + void ED_keymap_object(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Object Non-modal", 0, 0); + wmKeyMap *keymap; wmKeymapItem *kmi; + keymap= WM_keymap_find(wm, "Object Non-modal", 0, 0); + /* Note: this keymap works disregarding mode */ WM_keymap_add_item(keymap, "OBJECT_OT_editmode_toggle", TABKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "OBJECT_OT_posemode_toggle", TABKEY, KM_PRESS, KM_CTRL, 0); @@ -202,7 +212,8 @@ void ED_keymap_object(wmWindowManager *wm) WM_keymap_add_item(keymap, "OBJECT_OT_center_set", CKEY, KM_PRESS, KM_ALT|KM_SHIFT|KM_CTRL, 0); /* Note: this keymap gets disabled in non-objectmode, */ - keymap= WM_keymap_listbase(wm, "Object Mode", 0, 0); + keymap= WM_keymap_find(wm, "Object Mode", 0, 0); + keymap->poll= object_mode_poll; WM_keymap_add_item(keymap, "OBJECT_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "OBJECT_OT_select_inverse", IKEY, KM_PRESS, KM_CTRL, 0); @@ -227,11 +238,13 @@ void ED_keymap_object(wmWindowManager *wm) WM_keymap_add_item(keymap, "OBJECT_OT_restrictview_set", HKEY, KM_PRESS, 0, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "OBJECT_OT_restrictview_set", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "unselected", 1); - WM_keymap_verify_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "OBJECT_OT_delete", DELKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "OBJECT_OT_primitive_add", AKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "OBJECT_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "OBJECT_OT_duplicate", DKEY, KM_PRESS, KM_ALT, 0)->ptr, "linked", 1); WM_keymap_add_item(keymap, "OBJECT_OT_join", JKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "OBJECT_OT_convert", CKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "OBJECT_OT_proxy_make", PKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); // XXX this should probably be in screen instead... here for testing purposes in the meantime... - Aligorith @@ -244,7 +257,8 @@ void ED_keymap_object(wmWindowManager *wm) WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0); /* Lattice */ - keymap= WM_keymap_listbase(wm, "Lattice", 0, 0); + keymap= WM_keymap_find(wm, "Lattice", 0, 0); + keymap->poll= ED_operator_editlattice; WM_keymap_add_item(keymap, "LATTICE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 12cb2b95e06..4a0c812f7b1 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -566,8 +566,9 @@ static int parent_set_exec(bContext *C, wmOperator *op) } else cu->flag |= CU_FOLLOW; - /* fall back on regular parenting now */ - partype= PAR_OBJECT; + /* fall back on regular parenting now (for follow only) */ + if(partype == PAR_FOLLOW) + partype= PAR_OBJECT; } } else if(partype==PAR_BONE) { @@ -593,7 +594,9 @@ static int parent_set_exec(bContext *C, wmOperator *op) /* apply transformation of previous parenting */ ED_object_apply_obmat(ob); - ob->parent= par; + /* set the parent (except for follow-path constraint option) */ + if(partype != PAR_PATH_CONST) + ob->parent= par; /* handle types */ if (pchan) @@ -602,7 +605,7 @@ static int parent_set_exec(bContext *C, wmOperator *op) ob->parsubstr[0]= 0; /* constraint */ - if(partype==PAR_PATH_CONST) { + if(partype == PAR_PATH_CONST) { bConstraint *con; bFollowPathConstraint *data; float cmat[4][4], vec[3]; @@ -620,6 +623,7 @@ static int parent_set_exec(bContext *C, wmOperator *op) ob->loc[0] = vec[0]; ob->loc[1] = vec[1]; + ob->loc[2] = vec[2]; } else if(pararm && ob->type==OB_MESH && par->type == OB_ARMATURE) { if(partype == PAR_ARMATURE_NAME) @@ -645,8 +649,12 @@ static int parent_set_exec(bContext *C, wmOperator *op) ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA; + if(partype == PAR_PATH_CONST) + ; /* don't do anything here, since this is not technically "parenting" */ if( ELEM(partype, PAR_CURVE, PAR_LATTICE) || pararm ) ob->partype= PARSKEL; /* note, dna define, not operator property */ + else if (partype == PAR_BONE) + ob->partype= PARBONE; /* note, dna define, not operator property */ else ob->partype= PAROBJECT; /* note, dna define, not operator property */ } @@ -986,7 +994,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) if(lay==0) return OPERATOR_CANCELLED; - if(v3d && v3d->localview) { + if(v3d && v3d->localvd) { /* now we can move out of localview. */ // XXX if (!okee("Move from localview")) return; CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 50ba4ab2934..98603ee843a 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -30,6 +30,8 @@ #include <stdlib.h> #include <string.h> +#include "MEM_guardedalloc.h" + #include "DNA_group_types.h" #include "DNA_material_types.h" #include "DNA_modifier_types.h" @@ -53,6 +55,7 @@ #include "BKE_property.h" #include "BKE_report.h" #include "BKE_scene.h" +#include "BKE_utildefines.h" #include "WM_api.h" #include "WM_types.h" @@ -117,22 +120,16 @@ void ED_base_object_activate(bContext *C, Base *base) /********************** Selection Operators **********************/ -static EnumPropertyItem prop_select_types[] = { - {0, "EXCLUSIVE", 0, "Exclusive", ""}, - {1, "EXTEND", 0, "Extend", ""}, - {0, NULL, 0, NULL, NULL} -}; - /************************ Select by Type *************************/ static int object_select_by_type_exec(bContext *C, wmOperator *op) { - short obtype, seltype; + short obtype, extend; obtype = RNA_enum_get(op->ptr, "type"); - seltype = RNA_enum_get(op->ptr, "seltype"); + extend= RNA_boolean_get(op->ptr, "extend"); - if (seltype == 0) { + if (extend == 0) { CTX_DATA_BEGIN(C, Base*, base, visible_bases) { ED_base_object_select(base, BA_DESELECT); } @@ -166,9 +163,9 @@ void OBJECT_OT_select_by_type(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - RNA_def_enum(ot->srna, "seltype", prop_select_types, 0, "Selection", "Extend selection or clear selection then select"); + /* properties */ + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); RNA_def_enum(ot->srna, "type", object_type_items, 1, "Type", ""); - } /*********************** Selection by Links *********************/ @@ -192,7 +189,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) Tex *tex=0; int a, b; int nr = RNA_enum_get(op->ptr, "type"); - short changed = 0, seltype; + short changed = 0, extend; /* events (nr): * Object Ipo: 1 * ObData: 2 @@ -202,9 +199,9 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) * PSys: 6 */ - seltype = RNA_enum_get(op->ptr, "seltype"); + extend= RNA_boolean_get(op->ptr, "extend"); - if (seltype == 0) { + if (extend == 0) { CTX_DATA_BEGIN(C, Base*, base, visible_bases) { ED_base_object_select(base, BA_DESELECT); } @@ -327,9 +324,9 @@ void OBJECT_OT_select_linked(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + /* properties */ + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", ""); - RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select"); - } /*********************** Selected Grouped ********************/ @@ -575,11 +572,11 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) Scene *scene= CTX_data_scene(C); Object *ob; int nr = RNA_enum_get(op->ptr, "type"); - short changed = 0, seltype; + short changed = 0, extend; - seltype = RNA_enum_get(op->ptr, "seltype"); + extend= RNA_boolean_get(op->ptr, "extend"); - if (seltype == 0) { + if (extend == 0) { CTX_DATA_BEGIN(C, Base*, base, visible_bases) { ED_base_object_select(base, BA_DESELECT); } @@ -628,8 +625,8 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", ""); - RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select"); } /************************* Select by Layer **********************/ @@ -637,12 +634,12 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot) static int object_select_by_layer_exec(bContext *C, wmOperator *op) { unsigned int layernum; - short seltype; + short extend; - seltype = RNA_enum_get(op->ptr, "seltype"); + extend= RNA_boolean_get(op->ptr, "extend"); layernum = RNA_int_get(op->ptr, "layer"); - if (seltype == 0) { + if (extend == 0) { CTX_DATA_BEGIN(C, Base*, base, visible_bases) { ED_base_object_select(base, BA_DESELECT); } @@ -676,8 +673,9 @@ void OBJECT_OT_select_by_layer(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + /* properties */ + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); RNA_def_int(ot->srna, "layer", 1, 1, 20, "Layer", "", 1, 20); - RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select"); } /************************** Select Inverse *************************/ @@ -878,9 +876,9 @@ void object_flip_name (char *name) static int object_select_mirror_exec(bContext *C, wmOperator *op) { char tmpname[32]; - short seltype; + short extend; - seltype = RNA_enum_get(op->ptr, "seltype"); + extend= RNA_boolean_get(op->ptr, "extend"); CTX_DATA_BEGIN(C, Base*, primbase, selected_bases) { @@ -894,7 +892,7 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - if (seltype == 0) ED_base_object_select(primbase, BA_DESELECT); + if (extend == 0) ED_base_object_select(primbase, BA_DESELECT); } CTX_DATA_END; @@ -920,7 +918,60 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select"); + RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first."); +} + + +static int object_select_name_exec(bContext *C, wmOperator *op) +{ + char *name= RNA_string_get_alloc(op->ptr, "name", NULL, 0); + short extend= RNA_boolean_get(op->ptr, "extend"); + short changed = 0; + + if(!extend) { + CTX_DATA_BEGIN(C, Base*, base, visible_bases) { + ED_base_object_select(base, BA_DESELECT); + } + CTX_DATA_END; + } + + CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { + if(strcmp(name, base->object->id.name+2)==0) { + ED_base_object_select(base, BA_SELECT); + changed= 1; + } + } + CTX_DATA_END; + + MEM_freeN(name); + + /* undo? */ + if(changed) { + WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C)); + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void OBJECT_OT_select_name(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Select Name"; + ot->description = "Select an object with this name"; + ot->idname= "OBJECT_OT_select_name"; + + /* api callbacks */ + ot->exec= object_select_name_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_string(ot->srna, "name", "", 0, "Name", "Object name to select."); + RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first."); } /**************************** Select Random ****************************/ @@ -928,11 +979,11 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot) static int object_select_random_exec(bContext *C, wmOperator *op) { float percent; - short seltype; + short extend; - seltype = RNA_enum_get(op->ptr, "seltype"); + extend= RNA_boolean_get(op->ptr, "extend"); - if (seltype == 0) { + if (extend == 0) { CTX_DATA_BEGIN(C, Base*, base, visible_bases) { ED_base_object_select(base, BA_DESELECT); } @@ -967,8 +1018,9 @@ void OBJECT_OT_select_random(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + /* properties */ + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "percentage of objects to randomly select", 0.0001f, 1.0f); - RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select"); } diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 2b207f2f27c..cd0d97eed44 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -27,6 +27,7 @@ #include <stdlib.h> +#include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" @@ -115,13 +116,72 @@ static int object_rotation_clear_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) { if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) { - /* eulers can only get cleared if they are not protected */ - if((ob->protectflag & OB_LOCK_ROTX)==0) - ob->rot[0]= ob->drot[0]= 0.0f; - if((ob->protectflag & OB_LOCK_ROTY)==0) - ob->rot[1]= ob->drot[1]= 0.0f; - if((ob->protectflag & OB_LOCK_ROTZ)==0) - ob->rot[2]= ob->drot[2]= 0.0f; + if (ob->protectflag & (OB_LOCK_ROTX|OB_LOCK_ROTY|OB_LOCK_ROTZ|OB_LOCK_ROTW)) { + /* check if convert to eulers for locking... */ + if (ob->protectflag & OB_LOCK_ROT4D) { + /* perform clamping on a component by component basis */ + if ((ob->protectflag & OB_LOCK_ROTW) == 0) + ob->quat[0]= (ob->rotmode == ROT_MODE_AXISANGLE) ? 0.0f : 1.0f; + if ((ob->protectflag & OB_LOCK_ROTX) == 0) + ob->quat[1]= 0.0f; + if ((ob->protectflag & OB_LOCK_ROTY) == 0) + ob->quat[2]= 0.0f; + if ((ob->protectflag & OB_LOCK_ROTZ) == 0) + ob->quat[3]= 0.0f; + } + else { + /* perform clamping using euler form (3-components) */ + float eul[3], oldeul[3], quat1[4]; + + if (ob->rotmode == ROT_MODE_QUAT) { + QUATCOPY(quat1, ob->quat); + QuatToEul(ob->quat, oldeul); + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + AxisAngleToEulO(&ob->quat[1], ob->quat[0], oldeul, EULER_ORDER_DEFAULT); + } + else { + VECCOPY(oldeul, ob->rot); + } + + eul[0]= eul[1]= eul[2]= 0.0f; + + if (ob->protectflag & OB_LOCK_ROTX) + eul[0]= oldeul[0]; + if (ob->protectflag & OB_LOCK_ROTY) + eul[1]= oldeul[1]; + if (ob->protectflag & OB_LOCK_ROTZ) + eul[2]= oldeul[2]; + + if (ob->rotmode == ROT_MODE_QUAT) { + EulToQuat(eul, ob->quat); + /* quaternions flip w sign to accumulate rotations correctly */ + if ((quat1[0]<0.0f && ob->quat[0]>0.0f) || (quat1[0]>0.0f && ob->quat[0]<0.0f)) { + QuatMulf(ob->quat, -1.0f); + } + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + AxisAngleToEulO(&ob->quat[1], ob->quat[0], oldeul, EULER_ORDER_DEFAULT); + } + else { + VECCOPY(ob->rot, eul); + } + } + } + else { + if (ob->rotmode == ROT_MODE_QUAT) { + ob->quat[1]=ob->quat[2]=ob->quat[3]= 0.0f; + ob->quat[0]= 1.0f; + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + /* by default, make rotation of 0 radians around y-axis (roll) */ + ob->quat[0]=ob->quat[1]=ob->quat[3]= 0.0f; + ob->quat[2]= 1.0f; + } + else { + ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0f; + } + } } ob->recalc |= OB_RECALC_OB; } diff --git a/source/blender/editors/physics/ed_pointcache.c b/source/blender/editors/physics/ed_pointcache.c index f2c7b64032f..ed3aaf0cfd1 100644 --- a/source/blender/editors/physics/ed_pointcache.c +++ b/source/blender/editors/physics/ed_pointcache.c @@ -347,7 +347,7 @@ void ED_operatortypes_pointcache(void) //void ED_keymap_pointcache(wmWindowManager *wm) //{ -// ListBase *keymap= WM_keymap_listbase(wm, "Pointcache", 0, 0); +// wmKeyMap *keymap= WM_keymap_find(wm, "Pointcache", 0, 0); // // WM_keymap_add_item(keymap, "PHYSICS_OT_bake_all", AKEY, KM_PRESS, 0, 0); // WM_keymap_add_item(keymap, "PHYSICS_OT_free_all", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/physics/editparticle.c b/source/blender/editors/physics/editparticle.c index 5acdcb40613..a5e169eba06 100644 --- a/source/blender/editors/physics/editparticle.c +++ b/source/blender/editors/physics/editparticle.c @@ -1184,6 +1184,9 @@ void PE_update_object(Scene *scene, Object *ob, int useflag) point->flag &= ~PEP_EDIT_RECALC; } + if(edit->psys) + edit->psys->flag &= ~PSYS_HAIR_UPDATED; + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); } @@ -1761,6 +1764,7 @@ static void rekey_particle(PEData *data, int pa_index) { PTCacheEdit *edit= data->edit; ParticleSystem *psys= edit->psys; + ParticleSimulationData sim = {data->scene, data->ob, edit->psys, NULL}; ParticleData *pa= psys->particles + pa_index; PTCacheEditPoint *point = edit->points + pa_index; ParticleKey state; @@ -1785,7 +1789,7 @@ static void rekey_particle(PEData *data, int pa_index) /* interpolate new keys from old ones */ for(k=1,key++; k<data->totrekey-1; k++,key++) { state.time= (float)k / (float)(data->totrekey-1); - psys_get_particle_on_path(data->scene, data->ob, psys, pa_index, &state, 0); + psys_get_particle_on_path(&sim, pa_index, &state, 0); VECCOPY(key->co, state.co); key->time= sta + k * dval; } @@ -1853,6 +1857,7 @@ static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float { PTCacheEdit *edit= PE_get_current(scene, ob); ParticleSystem *psys; + ParticleSimulationData sim = {scene, ob, edit ? edit->psys : NULL, NULL}; ParticleData *pa; ParticleKey state; HairKey *new_keys, *key; @@ -1872,7 +1877,7 @@ static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float /* interpolate new keys from old ones (roots stay the same) */ for(k=1, key++; k < pa->totkey; k++, key++) { state.time= path_time * (float)k / (float)(pa->totkey-1); - psys_get_particle_on_path(scene, ob, psys, pa_index, &state, 0); + psys_get_particle_on_path(&sim, pa_index, &state, 0); VECCOPY(key->co, state.co); } @@ -2044,6 +2049,7 @@ static void subdivide_particle(PEData *data, int pa_index) { PTCacheEdit *edit= data->edit; ParticleSystem *psys= edit->psys; + ParticleSimulationData sim = {data->scene, data->ob, edit->psys, NULL}; ParticleData *pa= psys->particles + pa_index; PTCacheEditPoint *point = edit->points + pa_index; ParticleKey state; @@ -2083,7 +2089,7 @@ static void subdivide_particle(PEData *data, int pa_index) if(ekey->flag & PEK_SELECT && (ekey+1)->flag & PEK_SELECT) { nkey->time= (key->time + (key+1)->time)*0.5f; state.time= (endtime != 0.0f)? nkey->time/endtime: 0.0f; - psys_get_particle_on_path(data->scene, data->ob, psys, pa_index, &state, 0); + psys_get_particle_on_path(&sim, pa_index, &state, 0); VECCOPY(nkey->co, state.co); nekey->co= nkey->co; @@ -2875,12 +2881,13 @@ static void brush_add(PEData *data, short number) ParticleSystem *psys= edit->psys; ParticleData *add_pars= MEM_callocN(number*sizeof(ParticleData),"ParticleData add"); ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys); + ParticleSimulationData sim = {scene, ob, psys, psmd}; ParticleEditSettings *pset= PE_settings(scene); int i, k, n= 0, totpart= psys->totpart; short mco[2]; short dmx= 0, dmy= 0; float co1[3], co2[3], min_d, imat[4][4]; - float framestep, timestep= psys_get_timestep(psys->part); + float framestep, timestep= psys_get_timestep(&sim); short size= pset->brush[PE_BRUSH_ADD].size; short size2= size*size; DerivedMesh *dm=0; @@ -2975,8 +2982,8 @@ static void brush_add(PEData *data, short number) } pa->size= 1.0f; - initialize_particle(pa,i,ob,psys,psmd); - reset_particle(scene, pa,psys,psmd,ob,0.0,1.0,0,0,0); + initialize_particle(&sim, pa,i); + reset_particle(&sim, pa, 0.0, 1.0); point->flag |= PEP_EDIT_RECALC; if(pset->flag & PE_X_MIRROR) point->flag |= PEP_TAG; /* signal for duplicate */ @@ -3013,18 +3020,18 @@ static void brush_add(PEData *data, short number) hkey->time= pa->time + k * framestep; key[0].time= hkey->time/ 100.0f; - psys_get_particle_on_path(scene, ob, psys, ptn[0].index, key, 0); + psys_get_particle_on_path(&sim, ptn[0].index, key, 0); VecMulf(key[0].co, weight[0]); if(maxw>1) { key[1].time= key[0].time; - psys_get_particle_on_path(scene, ob, psys, ptn[1].index, key + 1, 0); + psys_get_particle_on_path(&sim, ptn[1].index, key + 1, 0); VecMulf(key[1].co, weight[1]); VECADD(key[0].co, key[0].co, key[1].co); if(maxw>2) { key[2].time= key[0].time; - psys_get_particle_on_path(scene, ob, psys, ptn[2].index, key + 2, 0); + psys_get_particle_on_path(&sim, ptn[2].index, key + 2, 0); VecMulf(key[2].co, weight[2]); VECADD(key[0].co, key[0].co, key[2].co); } @@ -3345,7 +3352,7 @@ static int brush_edit_invoke(bContext *C, wmOperator *op, wmEvent *event) brush_edit_apply_event(C, op, event); - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -3911,7 +3918,6 @@ static int specials_menu_invoke(bContext *C, wmOperator *op, wmEvent *event) { Scene *scene= CTX_data_scene(C); ParticleEditSettings *pset=PE_settings(scene); - PTCacheEdit *edit = PE_get_current(scene, CTX_data_active_object(C)); uiPopupMenu *pup; uiLayout *layout; @@ -3974,7 +3980,10 @@ void ED_operatortypes_particle(void) void ED_keymap_particle(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Particle", 0, 0); + wmKeyMap *keymap; + + keymap= WM_keymap_find(wm, "Particle", 0, 0); + keymap->poll= PE_poll; WM_keymap_add_item(keymap, "PARTICLE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "PARTICLE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/preview/previewrender.c b/source/blender/editors/preview/previewrender.c index 714ebcef0fb..7a4cc1c7865 100644 --- a/source/blender/editors/preview/previewrender.c +++ b/source/blender/editors/preview/previewrender.c @@ -88,7 +88,6 @@ #include "WM_api.h" #include "WM_types.h" -#include "ED_anim_api.h" #include "ED_previewrender.h" #include "ED_view3d.h" @@ -636,7 +635,6 @@ void BIF_view3d_previewrender_clear(ScrArea *sa) /* afterqueue call */ void BIF_view3d_previewrender(Scene *scene, ScrArea *sa) { - bContext *C= NULL; View3D *v3d= sa->spacedata.first; RegionView3D *rv3d= NULL; // XXX Render *re; @@ -736,7 +734,7 @@ void BIF_view3d_previewrender(Scene *scene, ScrArea *sa) /* database can have created render-resol data... */ if(rstats->convertdone) - ED_anim_dag_flush_update(C); // <--- only current scene XXX + DAG_scene_flush_update(scene, scene->lay, 0); //printf("dbase update\n"); } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 81f06611c39..87901d75494 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -824,24 +824,24 @@ static void ed_default_handlers(wmWindowManager *wm, ListBase *handlers, int fla UI_add_region_handlers(handlers); } if(flag & ED_KEYMAP_VIEW2D) { - ListBase *keymap= WM_keymap_listbase(wm, "View2D", 0, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "View2D", 0, 0); WM_event_add_keymap_handler(handlers, keymap); } if(flag & ED_KEYMAP_MARKERS) { - ListBase *keymap= WM_keymap_listbase(wm, "Markers", 0, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Markers", 0, 0); WM_event_add_keymap_handler(handlers, keymap); // XXX need boundbox check urgently!!! } if(flag & ED_KEYMAP_ANIMATION) { - ListBase *keymap= WM_keymap_listbase(wm, "Animation", 0, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Animation", 0, 0); WM_event_add_keymap_handler(handlers, keymap); } if(flag & ED_KEYMAP_FRAMES) { - ListBase *keymap= WM_keymap_listbase(wm, "Frames", 0, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Frames", 0, 0); WM_event_add_keymap_handler(handlers, keymap); } if(flag & ED_KEYMAP_GPENCIL) { - ListBase *keymap= WM_keymap_listbase(wm, "Grease Pencil", 0, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Grease Pencil", 0, 0); WM_event_add_keymap_handler(handlers, keymap); } } @@ -916,6 +916,19 @@ void ED_region_init(bContext *C, ARegion *ar) } +void ED_region_toggle_hidden(bContext *C, ARegion *ar) +{ + ScrArea *sa= CTX_wm_area(C); + + ar->flag ^= RGN_FLAG_HIDDEN; + ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */ + + if(ar->flag & RGN_FLAG_HIDDEN) + WM_event_remove_handlers(C, &ar->handlers); + + ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); + ED_area_tag_redraw(sa); +} /* sa2 to sa1, we swap spaces for fullscreen to keep all allocated data */ /* area vertices were set */ @@ -1241,7 +1254,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, char *contex pt->draw_header(C, panel); - uiBlockLayoutResolve(C, block, &xco, &yco); + uiBlockLayoutResolve(block, &xco, &yco); panel->labelofs= xco - triangle; panel->layout= NULL; } @@ -1252,7 +1265,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, char *contex pt->draw(C, panel); - uiBlockLayoutResolve(C, block, &xco, &yco); + uiBlockLayoutResolve(block, &xco, &yco); panel->layout= NULL; yco -= 2*style->panelspace; @@ -1340,7 +1353,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, char *contex void ED_region_panels_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; // XXX quick hacks for files saved with 2.5 already (i.e. the builtin defaults file) // scrollbars for button regions @@ -1353,7 +1366,7 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy); - keymap= WM_keymap_listbase(wm, "View2D Buttons List", 0, 0); + keymap= WM_keymap_find(wm, "View2D Buttons List", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } @@ -1398,7 +1411,7 @@ void ED_region_header(const bContext *C, ARegion *ar) maxco= xco; } - uiBlockLayoutResolve(C, block, &xco, &yco); + uiBlockLayoutResolve(block, &xco, &yco); /* for view2d */ if(xco > maxco) diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index aa36675fb90..2cc5500c3ef 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1140,7 +1140,7 @@ static void screen_cursor_set(wmWindow *win, wmEvent *event) if(az->type==AZONE_AREA) WM_cursor_set(win, CURSOR_EDIT); else if(az->type==AZONE_REGION) { - if(az->x1==az->x2) + if(az->edge == 'l' || az->edge == 'r') WM_cursor_set(win, CURSOR_X_MOVE); else WM_cursor_set(win, CURSOR_Y_MOVE); @@ -1580,23 +1580,6 @@ void ED_screen_animation_timer_update(bContext *C, int redraws) } } -unsigned int ED_screen_view3d_layers(bScreen *screen) -{ - if(screen) { - unsigned int layer= screen->scene->lay; /* as minimum this */ - ScrArea *sa; - - /* get all used view3d layers */ - for(sa= screen->areabase.first; sa; sa= sa->next) { - if(sa->spacetype==SPACE_VIEW3D) - layer |= ((View3D *)sa->spacedata.first)->lay; - } - return layer; - } - return 0; -} - - /* results in fully updated anim system */ void ED_update_for_newframe(const bContext *C, int mute) { @@ -1607,7 +1590,7 @@ void ED_update_for_newframe(const bContext *C, int mute) /* this function applies the changes too */ /* XXX future: do all windows */ - scene_update_for_newframe(scene, ED_screen_view3d_layers(screen)); /* BKE_scene.h */ + scene_update_for_newframe(scene, BKE_screen_visible_layers(screen)); /* BKE_scene.h */ //if ( (CFRA>1) && (!mute) && (scene->r.audio.flag & AUDIO_SCRUB)) // audiostream_scrub( CFRA ); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index dba882200ce..ae3f74403f2 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -456,7 +456,7 @@ static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event) } else { /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -588,7 +588,7 @@ static int area_swap_invoke(bContext *C, wmOperator *op, wmEvent *event) /* add modal handler */ WM_cursor_modal(CTX_wm_window(C), BC_SWAPAREA_CURSOR); - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; @@ -604,8 +604,8 @@ static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event) sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y); break; case LEFTMOUSE: /* release LMB */ - if(event->val==0) { - if(sad->sa1 == sad->sa2) { + if(event->val==KM_RELEASE) { + if(!sad->sa2 || sad->sa1 == sad->sa2) { return area_swap_cancel(C, op); } @@ -870,7 +870,7 @@ static int area_move_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_PASS_THROUGH; /* add temp handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -1160,7 +1160,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event) area_move_set_limits(CTX_wm_screen(C), dir, &sd->bigger, &sd->smaller); /* add temp handler for edge move or cancel */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -1225,7 +1225,7 @@ static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event) break; case LEFTMOUSE: - if(event->val==0) { /* mouse up */ + if(event->val==KM_RELEASE) { /* mouse up */ area_split_exit(C, op); return OPERATOR_FINISHED; } @@ -1296,7 +1296,7 @@ static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event) rmd->origval= rmd->ar->type->minsizey; /* add temp handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -1320,10 +1320,11 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) CLAMP(rmd->ar->type->minsizex, 0, 1000); if(rmd->ar->type->minsizex < 24) { rmd->ar->type->minsizex= rmd->origval; - rmd->ar->flag |= RGN_FLAG_HIDDEN; + if(!(rmd->ar->flag & RGN_FLAG_HIDDEN)) + ED_region_toggle_hidden(C, rmd->ar); } - else - rmd->ar->flag &= ~RGN_FLAG_HIDDEN; + else if(rmd->ar->flag & RGN_FLAG_HIDDEN) + ED_region_toggle_hidden(C, rmd->ar); } else { delta= event->y - rmd->origy; @@ -1332,10 +1333,11 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) CLAMP(rmd->ar->type->minsizey, 0, 1000); if(rmd->ar->type->minsizey < 24) { rmd->ar->type->minsizey= rmd->origval; - rmd->ar->flag |= RGN_FLAG_HIDDEN; + if(!(rmd->ar->flag & RGN_FLAG_HIDDEN)) + ED_region_toggle_hidden(C, rmd->ar); } - else - rmd->ar->flag &= ~RGN_FLAG_HIDDEN; + else if(rmd->ar->flag & RGN_FLAG_HIDDEN) + ED_region_toggle_hidden(C, rmd->ar); } WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); @@ -1343,12 +1345,14 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) break; case LEFTMOUSE: - if(event->val==0) { + if(event->val==KM_RELEASE) { if(ABS(event->x - rmd->origx) < 2 && ABS(event->y - rmd->origy) < 2) { - rmd->ar->flag ^= RGN_FLAG_HIDDEN; - WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); - } + if(rmd->ar->flag & RGN_FLAG_HIDDEN) { + ED_region_toggle_hidden(C, rmd->ar); + WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); + } + } MEM_freeN(op->customdata); op->customdata = NULL; @@ -1442,29 +1446,6 @@ static void SCREEN_OT_frame_jump(wmOperatorType *ot) /* ************** jump to keyframe operator ***************************** */ -/* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */ -// TODO: make this an API func? -static ActKeyColumn *cfra_find_nearest_next_ak (ActKeyColumn *ak, float cframe, short next) -{ - ActKeyColumn *akn= NULL; - - /* sanity checks */ - if (ak == NULL) - return NULL; - - /* check if this is a match, or whether it is in some subtree */ - if (cframe < ak->cfra) - akn= cfra_find_nearest_next_ak(ak->left, cframe, next); - else if (cframe > ak->cfra) - akn= cfra_find_nearest_next_ak(ak->right, cframe, next); - - /* if no match found (or found match), just use the current one */ - if (akn == NULL) - return ak; - else - return akn; -} - /* function to be called outside UI context, or for redo */ static int keyframe_jump_exec(bContext *C, wmOperator *op) { @@ -1593,7 +1574,7 @@ static int screen_full_area_exec(bContext *C, wmOperator *op) static void SCREEN_OT_screen_full_area(wmOperatorType *ot) { - ot->name = "Toggle Make Area Fullscreen"; + ot->name = "Toggle Full Screen"; ot->idname = "SCREEN_OT_screen_full_area"; ot->exec= screen_full_area_exec; @@ -1747,7 +1728,7 @@ static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_PASS_THROUGH; /* add temp handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -1847,7 +1828,7 @@ static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event) } break; case LEFTMOUSE: - if(event->val==0) { + if(event->val==KM_RELEASE) { area_join_apply(C, op); WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); area_join_exit(C, op); @@ -2116,7 +2097,7 @@ static int region_foursplit_exec(bContext *C, wmOperator *op) static void SCREEN_OT_region_foursplit(wmOperatorType *ot) { /* identifiers */ - ot->name= "Split Region in 4 Parts"; + ot->name= "Toggle Quad View"; ot->idname= "SCREEN_OT_region_foursplit"; /* api callbacks */ @@ -2195,6 +2176,10 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws) if(redraws & (TIME_SEQ|TIME_ALL_ANIM_WIN)) return 1; break; + case SPACE_NODE: + if(redraws & (TIME_NODES)) + return 1; + break; case SPACE_IMAGE: if(redraws & TIME_ALL_IMAGE_WIN) return 1; @@ -2227,7 +2212,7 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event) /* sync, don't sync, or follow scene setting */ if(sad->flag & ANIMPLAY_FLAG_SYNC) sync= 1; else if(sad->flag & ANIMPLAY_FLAG_NO_SYNC) sync= 0; - else sync= (scene->r.audio.flag & AUDIO_SYNC); + else sync= (scene->audio.flag & AUDIO_SYNC); if(sync) { /* skip frames */ @@ -2362,7 +2347,7 @@ static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event) static void SCREEN_OT_animation_play(wmOperatorType *ot) { /* identifiers */ - ot->name= "Animation player"; + ot->name= "Play Animation"; ot->idname= "SCREEN_OT_animation_play"; /* api callbacks */ @@ -2942,7 +2927,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene); /* add modal handler for ESC */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -3289,19 +3274,15 @@ static void keymap_modal_set(wmWindowManager *wm) /* called in spacetypes.c */ void ED_keymap_screen(wmWindowManager *wm) { - ListBase *keymap; - - /* Screen General ------------------------------------------------ */ - keymap= WM_keymap_listbase(wm, "Screen", 0, 0); + wmKeyMap *keymap; - - /* standard timers */ - WM_keymap_add_item(keymap, "SCREEN_OT_animation_step", TIMER0, KM_ANY, KM_ANY, 0); + /* Screen Editing ------------------------------------------------ */ + keymap= WM_keymap_find(wm, "Screen Editing", 0, 0); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "modifier", 0); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "modifier", 1); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "modifier", 2); - + /* screen tools */ WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE_AREA, 0, 0, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE_AREA, 0, 0, 0); @@ -3310,6 +3291,14 @@ void ED_keymap_screen(wmWindowManager *wm) WM_keymap_verify_item(keymap, "SCREEN_OT_region_scale", EVT_ACTIONZONE_REGION, 0, 0, 0); /* area move after action zones */ WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0); + + + /* Screen General ------------------------------------------------ */ + keymap= WM_keymap_find(wm, "Screen", 0, 0); + + /* standard timers */ + WM_keymap_add_item(keymap, "SCREEN_OT_animation_step", TIMER0, KM_ANY, KM_ANY, 0); + RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1); @@ -3359,7 +3348,7 @@ void ED_keymap_screen(wmWindowManager *wm) /* Anim Playback ------------------------------------------------ */ - keymap= WM_keymap_listbase(wm, "Frames", 0, 0); + keymap= WM_keymap_find(wm, "Frames", 0, 0); /* frame offsets */ RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 10); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 870b66cdbbd..d223c423690 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -625,19 +625,6 @@ static void BarycentricWeightsPersp2f(float pt[2], float v1[4], float v2[4], flo w[0] = w[1] = w[2] = 1.0f/3.0f; } -static void VecWeightf(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3]) -{ - p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2]; - p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2]; - p[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2]; -} - -static void Vec2Weightf(float p[2], const float v1[2], const float v2[2], const float v3[2], const float w[3]) -{ - p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2]; - p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2]; -} - static float VecZDepthOrtho(float pt[2], float v1[3], float v2[3], float v3[3], float w[3]) { BarycentricWeights2f(pt, v1, v2, v3, w); @@ -746,10 +733,10 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float tf = ps->dm_mtface + face_index; if (side == 0) { - Vec2Weightf(uv, tf->uv[0], tf->uv[1], tf->uv[2], w); + Vec2Lerp3f(uv, tf->uv[0], tf->uv[1], tf->uv[2], w); } else { /* QUAD */ - Vec2Weightf(uv, tf->uv[0], tf->uv[2], tf->uv[3], w); + Vec2Lerp3f(uv, tf->uv[0], tf->uv[2], tf->uv[3], w); } ibuf = tf->tpage->ibufs.first; /* we must have got the imbuf before getting here */ @@ -870,8 +857,8 @@ static int project_paint_occlude_ptv_clip( } /* Test if we're in the clipped area, */ - if (side) VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); - else VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); + if (side) VecLerp3f(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); + else VecLerp3f(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); Mat4MulVecfl(ps->ob->obmat, wco); if(!view3d_test_clipping(ps->rv3d, wco)) { @@ -1146,19 +1133,6 @@ static int check_seam(const ProjPaintState *ps, const int orig_face, const int o return 1; } -/* TODO - move to arithb.c */ -/* Converts an angle to a length that can be used for maintaining an even margin around UV's */ -static float angleToLength(float angle) -{ - // already accounted for - if (angle < 0.000001f) { - return 1.0f; - } - else { - return fabsf(1.0f / cosf(angle * (M_PI/180.0f))); - } -} - /* Calculate outset UV's, this is not the same as simply scaling the UVs, * since the outset coords are a margin that keep an even distance from the original UV's, * note that the image aspect is taken into account */ @@ -1204,15 +1178,15 @@ static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const fl } if (is_quad) { - a1 = angleToLength(NormalizedVecAngle2_2D(dir4, dir1)); - a2 = angleToLength(NormalizedVecAngle2_2D(dir1, dir2)); - a3 = angleToLength(NormalizedVecAngle2_2D(dir2, dir3)); - a4 = angleToLength(NormalizedVecAngle2_2D(dir3, dir4)); + a1 = AngleToLength(NormalizedVecAngle2_2D(dir4, dir1)); + a2 = AngleToLength(NormalizedVecAngle2_2D(dir1, dir2)); + a3 = AngleToLength(NormalizedVecAngle2_2D(dir2, dir3)); + a4 = AngleToLength(NormalizedVecAngle2_2D(dir3, dir4)); } else { - a1 = angleToLength(NormalizedVecAngle2_2D(dir3, dir1)); - a2 = angleToLength(NormalizedVecAngle2_2D(dir1, dir2)); - a3 = angleToLength(NormalizedVecAngle2_2D(dir2, dir3)); + a1 = AngleToLength(NormalizedVecAngle2_2D(dir3, dir1)); + a2 = AngleToLength(NormalizedVecAngle2_2D(dir1, dir2)); + a3 = AngleToLength(NormalizedVecAngle2_2D(dir2, dir3)); } if (is_quad) { @@ -1329,7 +1303,7 @@ static void screen_px_from_ortho( float w[3]) { BarycentricWeights2f(uv, uv1co, uv2co, uv3co, w); - VecWeightf(pixelScreenCo, v1co, v2co, v3co, w); + VecLerp3f(pixelScreenCo, v1co, v2co, v3co, w); } /* same as screen_px_from_ortho except we need to take into account @@ -1363,7 +1337,7 @@ static void screen_px_from_persp( } /* done re-weighting */ - VecWeightf(pixelScreenCo, v1co, v2co, v3co, w); + VecLerp3f(pixelScreenCo, v1co, v2co, v3co, w); } static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const float w[3], int side, unsigned char rgba_ub[4], float rgba_f[4]) @@ -1381,7 +1355,7 @@ static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const uvCo3 = (float *)tf_other->uv[2]; } - Vec2Weightf(uv_other, uvCo1, uvCo2, uvCo3, w); + Vec2Lerp3f(uv_other, uvCo1, uvCo2, uvCo3, w); /* use */ uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y); @@ -1916,22 +1890,22 @@ static void rect_to_uvspace_ortho( uv[0] = bucket_bounds->xmax; uv[1] = bucket_bounds->ymin; BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w); - Vec2Weightf(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w); + Vec2Lerp3f(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w); //uv[0] = bucket_bounds->xmax; // set above uv[1] = bucket_bounds->ymax; BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w); - Vec2Weightf(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w); + Vec2Lerp3f(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w); uv[0] = bucket_bounds->xmin; //uv[1] = bucket_bounds->ymax; // set above BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w); - Vec2Weightf(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w); + Vec2Lerp3f(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w); //uv[0] = bucket_bounds->xmin; // set above uv[1] = bucket_bounds->ymin; BarycentricWeights2f(uv, v1coSS, v2coSS, v3coSS, w); - Vec2Weightf(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w); + Vec2Lerp3f(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w); } /* same as above but use BarycentricWeightsPersp2f */ @@ -1950,22 +1924,22 @@ static void rect_to_uvspace_persp( uv[0] = bucket_bounds->xmax; uv[1] = bucket_bounds->ymin; BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w); - Vec2Weightf(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w); + Vec2Lerp3f(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w); //uv[0] = bucket_bounds->xmax; // set above uv[1] = bucket_bounds->ymax; BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w); - Vec2Weightf(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w); + Vec2Lerp3f(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w); uv[0] = bucket_bounds->xmin; //uv[1] = bucket_bounds->ymax; // set above BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w); - Vec2Weightf(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w); + Vec2Lerp3f(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w); //uv[0] = bucket_bounds->xmin; // set above uv[1] = bucket_bounds->ymin; BarycentricWeightsPersp2f(uv, v1coSS, v2coSS, v3coSS, w); - Vec2Weightf(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w); + Vec2Lerp3f(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w); } /* This works as we need it to but we can save a few steps and not use it */ @@ -2209,13 +2183,13 @@ static void project_bucket_clip_face( if (is_ortho) { for(i=0; i<(*tot); i++) { BarycentricWeights2f(isectVCosSS[i], v1coSS, v2coSS, v3coSS, w); - Vec2Weightf(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w); + Vec2Lerp3f(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w); } } else { for(i=0; i<(*tot); i++) { BarycentricWeightsPersp2f(isectVCosSS[i], v1coSS, v2coSS, v3coSS, w); - Vec2Weightf(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w); + Vec2Lerp3f(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w); } } } @@ -2470,7 +2444,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i /* a pitty we need to get the worldspace pixel location here */ if(ps->rv3d->rflag & RV3D_CLIPPING) { - VecWeightf(wco, ps->dm_mvert[ (*(&mf->v1 + i1)) ].co, ps->dm_mvert[ (*(&mf->v1 + i2)) ].co, ps->dm_mvert[ (*(&mf->v1 + i3)) ].co, w); + VecLerp3f(wco, ps->dm_mvert[ (*(&mf->v1 + i1)) ].co, ps->dm_mvert[ (*(&mf->v1 + i2)) ].co, ps->dm_mvert[ (*(&mf->v1 + i3)) ].co, w); Mat4MulVecfl(ps->ob->obmat, wco); if(view3d_test_clipping(ps->rv3d, wco)) { continue; /* Watch out that no code below this needs to run */ @@ -2686,8 +2660,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i /* a pitty we need to get the worldspace pixel location here */ if(ps->rv3d->rflag & RV3D_CLIPPING) { - if (side) VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); - else VecWeightf(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); + if (side) VecLerp3f(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); + else VecLerp3f(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); Mat4MulVecfl(ps->ob->obmat, wco); if(view3d_test_clipping(ps->rv3d, wco)) { @@ -3757,7 +3731,7 @@ static void *do_projectpaint_thread(void *ph_v) /*if (dist < s->brush->size) {*/ /* correct but uses a sqrtf */ if (dist_nosqrt < brush_size_sqared && (dist=sqrtf(dist_nosqrt)) < size_half) { - falloff = brush_curve_strength(ps->brush, dist, size_half); + falloff = brush_curve_strength_clamp(ps->brush, dist, size_half); if (falloff > 0.0f) { if (ps->is_texbrush) { brush_sample_tex(ps->brush, projPixel->projCoSS, rgba); @@ -4443,6 +4417,7 @@ typedef struct PaintOperation { int first; int prevmouse[2]; + float prev_pressure; /* need this since we dont get tablet events for pressure change */ int brush_size_orig; double starttime; @@ -4722,8 +4697,8 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) if(wmtab->Active == EVT_TABLET_ERASER) pop->s.blend= IMB_BLEND_ERASE_ALPHA; } - else - pressure= 1.0f; + else /* otherwise airbrush becomes 1.0 pressure instantly */ + pressure= pop->prev_pressure ? pop->prev_pressure : 1.0f; if(pop->first) { pop->prevmouse[0]= mouse[0]; @@ -4732,8 +4707,7 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) /* special exception here for too high pressure values on first touch in windows for some tablets, then we just skip first touch .. */ - if ((pop->s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE| - BRUSH_SPACING_PRESSURE|BRUSH_RAD_PRESSURE)) && tablet && (pressure >= 0.99f)) + if ((pop->s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE|BRUSH_SPACING_PRESSURE)) && tablet && (pressure >= 0.99f)) return; } @@ -4748,6 +4722,8 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) /* apply */ paint_apply(C, op, &itemptr); + + pop->prev_pressure= pressure; } static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event) @@ -4762,7 +4738,7 @@ static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event) paint_apply_event(C, op, event); pop= op->customdata; - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); if(pop->s.brush->flag & BRUSH_AIRBRUSH) pop->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f); @@ -4897,12 +4873,15 @@ static int paint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *even static int paint_radial_control_exec(bContext *C, wmOperator *op) { + Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->imapaint.paint); float zoom; int ret; char str[256]; get_imapaint_zoom(C, &zoom, &zoom); - ret = brush_radial_control_exec(op, paint_brush(&CTX_data_scene(C)->toolsettings->imapaint.paint), 2.0 / zoom); + ret = brush_radial_control_exec(op, brush, 2.0 / zoom); WM_radial_control_string(op, str, 256); + + WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush); return ret; } @@ -4961,7 +4940,7 @@ static int grab_clone_invoke(bContext *C, wmOperator *op, wmEvent *event) cmv->starty= event->y; op->customdata= cmv; - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -5216,10 +5195,13 @@ static int texture_paint_radial_control_invoke(bContext *C, wmOperator *op, wmEv static int texture_paint_radial_control_exec(bContext *C, wmOperator *op) { - int ret = brush_radial_control_exec(op, paint_brush(&CTX_data_scene(C)->toolsettings->imapaint.paint), 2); + Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->imapaint.paint); + int ret = brush_radial_control_exec(op, brush, 2); char str[256]; WM_radial_control_string(op, str, 256); + WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush); + return ret; } @@ -5232,6 +5214,11 @@ static int texture_paint_poll(bContext *C) return 0; } +int image_texture_paint_poll(bContext *C) +{ + return (texture_paint_poll(C) || image_paint_poll(C)); +} + void PAINT_OT_texture_paint_radial_control(wmOperatorType *ot) { WM_OT_radial_control_partial(ot); diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index ba1b57a1bef..8251d1a5a1a 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -57,7 +57,10 @@ int paint_poll(bContext *C); void paint_cursor_start(struct bContext *C, int (*poll)(struct bContext *C)); /* paint_vertex.c */ -int vertex_paint_mode_poll(bContext *C); +int weight_paint_poll(struct bContext *C); +int vertex_paint_poll(struct bContext *C); +int vertex_paint_mode_poll(struct bContext *C); + void clear_vpaint(Scene *scene, int selected); void PAINT_OT_weight_paint_toggle(struct wmOperatorType *ot); @@ -69,6 +72,8 @@ void PAINT_OT_vertex_paint_toggle(struct wmOperatorType *ot); void PAINT_OT_vertex_paint(struct wmOperatorType *ot); /* paint_image.c */ +int image_texture_paint_poll(struct bContext *C); + void PAINT_OT_image_paint(struct wmOperatorType *ot); void PAINT_OT_image_paint_radial_control(struct wmOperatorType *ot); void PAINT_OT_grab_clone(struct wmOperatorType *ot); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 19b46f5a941..514c80d929d 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -38,6 +38,7 @@ #include "RNA_enum_types.h" #include "paint_intern.h" +#include "sculpt_intern.h" #include <string.h> @@ -133,3 +134,48 @@ void ED_operatortypes_paint(void) WM_operatortype_append(PAINT_OT_vertex_color_set); } +void ED_keymap_paint(wmWindowManager *wm) +{ + wmKeyMap *keymap; + + /* Sculpt mode */ + keymap= WM_keymap_find(wm, "Sculpt", 0, 0); + keymap->poll= sculpt_poll; + + RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE); + RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH); + RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", WM_RADIALCONTROL_ANGLE); + + WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); + + /* Vertex Paint mode */ + keymap= WM_keymap_find(wm, "Vertex Paint", 0, 0); + keymap->poll= vertex_paint_poll; + + RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_vertex_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE); + RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_vertex_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH); + WM_keymap_verify_item(keymap, "PAINT_OT_vertex_paint", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "PAINT_OT_sample_color", RIGHTMOUSE, KM_PRESS, 0, 0); + + /* Weight Paint mode */ + keymap= WM_keymap_find(wm, "Weight Paint", 0, 0); + keymap->poll= weight_paint_poll; + + RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE); + RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH); + + WM_keymap_verify_item(keymap, "PAINT_OT_weight_paint", LEFTMOUSE, KM_PRESS, 0, 0); + + /* Image/Texture Paint mode */ + keymap= WM_keymap_find(wm, "Image Paint", 0, 0); + keymap->poll= image_texture_paint_poll; + + RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_texture_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE); + RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_texture_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH); + + WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "PAINT_OT_sample_color", RIGHTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "PAINT_OT_clone_cursor_set", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); +} + diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index bd9ea50e0f8..b83352ae70c 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -263,7 +263,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) } /* TODO: fix hardcoded event here */ - if(event->type == LEFTMOUSE && event->val == 0) { + if(event->type == LEFTMOUSE && event->val == KM_RELEASE) { /* Exit stroke, free data */ if(stroke->smooth_stroke_cursor) diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 25ff57ca87f..5afc4954c9c 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -119,7 +119,7 @@ int vertex_paint_mode_poll(bContext *C) return ob && ob->mode == OB_MODE_VERTEX_PAINT; } -static int vp_poll(bContext *C) +int vertex_paint_poll(bContext *C) { if(vertex_paint_mode_poll(C) && paint_brush(&CTX_data_tool_settings(C)->vpaint->paint)) { @@ -133,7 +133,7 @@ static int vp_poll(bContext *C) return 0; } -static int wp_poll(bContext *C) +int weight_paint_poll(bContext *C) { Object *ob = CTX_data_active_object(C); @@ -710,7 +710,9 @@ static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x if(totface+4>=MAXINDEX) return 0; - if(size>64.0) size= 64.0; + /* brecht: disabled this because it obviously failes for + brushes with size > 64, why is this here? */ + /*if(size>64.0) size= 64.0;*/ ibuf= view3d_read_backbuf(vc, x-size, y-size, x+size, y+size); if(ibuf) { @@ -1058,7 +1060,7 @@ static int set_wpaint(bContext *C, wmOperator *op) /* toggle */ wp= scene->toolsettings->wpaint= new_vpaint(1); paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT); - paint_cursor_start(C, wp_poll); + paint_cursor_start(C, weight_paint_poll); mesh_octree_table(ob, NULL, NULL, 's'); @@ -1127,14 +1129,18 @@ static int vpaint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *eve { int ret = WM_radial_control_modal(C, op, event); if(ret != OPERATOR_RUNNING_MODAL) - paint_cursor_start(C, vp_poll); + paint_cursor_start(C, vertex_paint_poll); return ret; } static int vpaint_radial_control_exec(bContext *C, wmOperator *op) { Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->vpaint->paint); - return brush_radial_control_exec(op, brush, 1); + int ret = brush_radial_control_exec(op, brush, 1); + + WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush); + + return ret; } static int wpaint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event) @@ -1152,14 +1158,18 @@ static int wpaint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *eve { int ret = WM_radial_control_modal(C, op, event); if(ret != OPERATOR_RUNNING_MODAL) - paint_cursor_start(C, wp_poll); + paint_cursor_start(C, weight_paint_poll); return ret; } static int wpaint_radial_control_exec(bContext *C, wmOperator *op) { Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->wpaint->paint); - return brush_radial_control_exec(op, brush, 1); + int ret = brush_radial_control_exec(op, brush, 1); + + WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush); + + return ret; } void PAINT_OT_weight_paint_radial_control(wmOperatorType *ot) @@ -1172,7 +1182,7 @@ void PAINT_OT_weight_paint_radial_control(wmOperatorType *ot) ot->invoke= wpaint_radial_control_invoke; ot->modal= wpaint_radial_control_modal; ot->exec= wpaint_radial_control_exec; - ot->poll= wp_poll; + ot->poll= weight_paint_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; @@ -1188,7 +1198,7 @@ void PAINT_OT_vertex_paint_radial_control(wmOperatorType *ot) ot->invoke= vpaint_radial_control_invoke; ot->modal= vpaint_radial_control_modal; ot->exec= vpaint_radial_control_exec; - ot->poll= vp_poll; + ot->poll= vertex_paint_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; @@ -1492,7 +1502,7 @@ static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) wpaint_stroke_done); /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); op->type->modal(C, op, event); @@ -1510,7 +1520,7 @@ void PAINT_OT_weight_paint(wmOperatorType *ot) ot->invoke= wpaint_invoke; ot->modal= paint_stroke_modal; /* ot->exec= vpaint_exec; <-- needs stroke property */ - ot->poll= wp_poll; + ot->poll= weight_paint_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; @@ -1557,7 +1567,7 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */ if(vp==NULL) vp= scene->toolsettings->vpaint= new_vpaint(0); - paint_cursor_start(C, vp_poll); + paint_cursor_start(C, vertex_paint_poll); paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT); } @@ -1732,6 +1742,10 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P } Mat4SwapMat4(vc->rv3d->persmat, mat); + + /* was disabled because it is slow, but necessary for blur */ + if(vp->mode == VP_BLUR) + do_shared_vertexcol(me); ED_region_tag_redraw(vc->ar); @@ -1761,7 +1775,7 @@ static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) vpaint_stroke_done); /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); op->type->modal(C, op, event); @@ -1778,7 +1792,7 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot) ot->invoke= vpaint_invoke; ot->modal= paint_stroke_modal; /* ot->exec= vpaint_exec; <-- needs stroke property */ - ot->poll= vp_poll; + ot->poll= vertex_paint_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index b08e8ab5c2b..64af39ea497 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1039,7 +1039,7 @@ static int sculpt_mode_poll(bContext *C) return ob && ob->mode & OB_MODE_SCULPT; } -static int sculpt_poll(bContext *C) +int sculpt_poll(bContext *C) { return sculpt_mode_poll(C) && paint_poll(C); } @@ -1091,8 +1091,11 @@ static int sculpt_radial_control_modal(bContext *C, wmOperator *op, wmEvent *eve static int sculpt_radial_control_exec(bContext *C, wmOperator *op) { Brush *brush = paint_brush(&CTX_data_tool_settings(C)->sculpt->paint); + int ret = brush_radial_control_exec(op, brush, 1); - return brush_radial_control_exec(op, brush, 1); + WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush); + + return ret; } static void SCULPT_OT_radial_control(wmOperatorType *ot) @@ -1437,7 +1440,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even sculpt_stroke_done); /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); op->type->modal(C, op, event); @@ -1566,10 +1569,10 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *op) paint_init(&ts->sculpt->paint, PAINT_CURSOR_SCULPT); paint_cursor_start(C, sculpt_poll); - - WM_event_add_notifier(C, NC_SCENE|ND_MODE, CTX_data_scene(C)); } + WM_event_add_notifier(C, NC_SCENE|ND_MODE, CTX_data_scene(C)); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 25f97b862e6..15ccacc294a 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -33,6 +33,7 @@ #include "DNA_listBase.h" #include "DNA_vec_types.h" +struct bContext; struct Brush; struct Mesh; struct Object; @@ -53,6 +54,8 @@ struct Brush *sculptmode_brush(void); char sculpt_modifiers_active(struct Object *ob); void sculpt(Sculpt *sd); +int sculpt_poll(struct bContext *C); + /* Stroke */ struct SculptStroke *sculpt_stroke_new(const int max); void sculpt_stroke_free(struct SculptStroke *); diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 89633d0cdfe..865d072d938 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -89,6 +89,44 @@ #include "action_intern.h" /* ************************************************************************** */ +/* ACTION MANAGEMENT */ + +/* ******************** New Action Operator *********************** */ + +static int act_new_exec(bContext *C, wmOperator *op) +{ + bAction *action; + + // XXX need to restore behaviour to copy old actions... + action= add_empty_action("Action"); + + /* combined with RNA property, this will assign & increase user, + so decrease here to compensate for that */ + action->id.us--; + + /* set notifier that keyframes have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); + + return OPERATOR_FINISHED; +} + +void ACT_OT_new (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "New"; + ot->idname= "ACT_OT_new"; + ot->description= "Create new action."; + + /* api callbacks */ + ot->exec= act_new_exec; + // NOTE: this is used in the NLA too... + //ot->poll= ED_operator_action_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* ************************************************************************** */ /* KEYFRAME-RANGE STUFF */ /* *************************** Calculate Range ************************** */ diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c index 8674f481a18..25a5123d1b5 100644 --- a/source/blender/editors/space_action/action_header.c +++ b/source/blender/editors/space_action/action_header.c @@ -189,6 +189,7 @@ static void act_edit_keytypesmenu(bContext *C, uiLayout *layout, void *arg_unuse uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); uiItemEnumO(layout, NULL, 0, "ACT_OT_keyframe_type", "type", BEZT_KEYTYPE_KEYFRAME); uiItemEnumO(layout, NULL, 0, "ACT_OT_keyframe_type", "type", BEZT_KEYTYPE_BREAKDOWN); + uiItemEnumO(layout, NULL, 0, "ACT_OT_keyframe_type", "type", BEZT_KEYTYPE_EXTREME); } static void act_edit_handlesmenu(bContext *C, uiLayout *layout, void *arg_unused) @@ -260,61 +261,6 @@ static void do_action_buttons(bContext *C, void *arg, int event) } } -static void saction_idpoin_handle(bContext *C, ID *id, int event) -{ - SpaceAction *saction= CTX_wm_space_action(C); - Object *obact= CTX_data_active_object(C); - - printf("actedit do id: \n"); - - switch (event) { - case UI_ID_BROWSE: - printf("browse \n"); - case UI_ID_DELETE: - printf("browse or delete \n"); - saction->action= (bAction*)id; - - /* we must set this action to be the one used by active object (if not pinned) */ - if (saction->pin == 0) { - AnimData *adt= BKE_id_add_animdata(&obact->id); /* this only adds if non-existant */ - - /* set action */ - printf("\tset action \n"); - adt->action= saction->action; - adt->action->id.us++; - } - - ED_area_tag_redraw(CTX_wm_area(C)); - ED_undo_push(C, "Assign Action"); - break; - case UI_ID_RENAME: - printf("actedit rename \n"); - break; - case UI_ID_ADD_NEW: - printf("actedit addnew \n"); - if (saction->pin == 0) { - AnimData *adt= BKE_id_add_animdata(&obact->id); /* this only adds if non-existant */ - - /* set new action */ - // XXX need to restore behaviour to copy old actions... - printf("\tset new action \n"); - adt->action= saction->action= add_empty_action("Action"); - } - break; - case UI_ID_OPEN: - printf("actedit open \n"); - /* XXX not implemented */ - break; - case UI_ID_ALONE: - printf("actedit alone \n"); - /* XXX not implemented */ - break; - case UI_ID_PIN: - printf("actedit pin \n"); - break; - } -} - void action_header_buttons(const bContext *C, ARegion *ar) { ScrArea *sa= CTX_wm_area(C); @@ -390,28 +336,18 @@ void action_header_buttons(const bContext *C, ARegion *ar) /* FILTERING OPTIONS */ xco -= 10; - //uiBlockBeginAlign(block); - uiDefIconButBitI(block, TOG, ADS_FILTER_ONLYSEL, B_REDR, ICON_RESTRICT_SELECT_OFF, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Only display selected Objects"); - //uiBlockEndAlign(block); - xco += 5; - - uiBlockBeginAlign(block); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSCE, B_REDR, ICON_SCENE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Scene Animation"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOWOR, B_REDR, ICON_WORLD_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display World Animation"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSHAPEKEYS, B_REDR, ICON_SHAPEKEY_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display ShapeKeys"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMAT, B_REDR, ICON_MATERIAL_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Materials"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOLAM, B_REDR, ICON_LAMP_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Lamps"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCAM, B_REDR, ICON_CAMERA_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Cameras"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCUR, B_REDR, ICON_CURVE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Curves"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMBA, B_REDR, ICON_META_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display MetaBalls"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOPART, B_REDR, ICON_PARTICLE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Display Particles"); - uiBlockEndAlign(block); - xco += 30; + xco= ANIM_headerUI_standard_buttons(C, &saction->ads, block, xco, yco); } else if (saction->mode == SACTCONT_ACTION) { - /* NAME ETC */ - xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)saction->action, ID_AC, &saction->pin, xco, yco, - saction_idpoin_handle, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_DELETE|UI_ID_FAKE_USER|UI_ID_ALONE|UI_ID_PIN); + uiLayout *layout; + bScreen *sc= CTX_wm_screen(C); + PointerRNA ptr; + + RNA_pointer_create(&sc->id, &RNA_SpaceDopeSheetEditor, saction, &ptr); + + layout= uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, 20+3, 20, 1, U.uistyles.first); + uiTemplateID(layout, (bContext*)C, &ptr, "action", "ACT_OT_new", NULL, NULL); + uiBlockLayoutResolve(block, &xco, NULL); xco += 8; } diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index e5f0ab8994e..4326bed62d3 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -99,6 +99,8 @@ void ACT_OT_frame_jump(struct wmOperatorType *ot); void ACT_OT_snap(struct wmOperatorType *ot); void ACT_OT_mirror(struct wmOperatorType *ot); +void ACT_OT_new(struct wmOperatorType *ot); + /* defines for snap keyframes * NOTE: keep in sync with eEditKeyframes_Snap (in ED_keyframes_edit.h) */ diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 42b033040b1..00b22232608 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -83,6 +83,7 @@ void action_operatortypes(void) WM_operatortype_append(ACT_OT_insert_keyframe); WM_operatortype_append(ACT_OT_copy); WM_operatortype_append(ACT_OT_paste); + WM_operatortype_append(ACT_OT_new); WM_operatortype_append(ACT_OT_previewrange_set); WM_operatortype_append(ACT_OT_view_all); @@ -90,7 +91,7 @@ void action_operatortypes(void) /* ************************** registration - keymaps **********************************/ -static void action_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) +static void action_keymap_keyframes (wmWindowManager *wm, wmKeyMap *keymap) { wmKeymapItem *kmi; @@ -165,7 +166,7 @@ static void action_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) void action_keymap(wmWindowManager *wm) { - ListBase *keymap; + wmKeyMap *keymap; /* channels */ /* Channels are not directly handled by the Action Editor module, but are inherited from the Animation module. @@ -174,7 +175,7 @@ void action_keymap(wmWindowManager *wm) */ /* keyframes */ - keymap= WM_keymap_listbase(wm, "Action_Keys", SPACE_ACTION, 0); + keymap= WM_keymap_find(wm, "Action_Keys", SPACE_ACTION, 0); action_keymap_keyframes(wm, keymap); } diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index b7a3df563ea..3b275cab814 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -153,12 +153,12 @@ static SpaceLink *action_duplicate(SpaceLink *sl) /* add handlers, stuff you only do once or on area/region changes */ static void action_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "Action_Keys", SPACE_ACTION, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "Action_Keys", SPACE_ACTION, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -216,12 +216,12 @@ static void action_main_area_draw(const bContext *C, ARegion *ar) /* add handlers, stuff you only do once or on area/region changes */ static void action_channel_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "Animation_Channels", 0, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "Animation_Channels", 0, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -323,6 +323,7 @@ static void action_main_area_listener(ARegion *ar, wmNotifier *wmn) break; case NC_SCENE: switch(wmn->data) { + case ND_RENDER_OPTIONS: case ND_OB_ACTIVE: case ND_FRAME: case ND_MARKERS: diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index edd5da44526..18bc7ec9555 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -129,6 +129,7 @@ void ED_spacetypes_keymap(wmWindowManager *wm) ED_keymap_armature(wm); ED_keymap_particle(wm); ED_keymap_metaball(wm); + ED_keymap_paint(wm); ED_marker_keymap(wm); UI_view2d_keymap(wm); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 635abd429f6..9333ba9209c 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -463,6 +463,7 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma found= buttons_context_path_texture(C, path); break; case BCONTEXT_BONE: + case BCONTEXT_BONE_CONSTRAINT: found= buttons_context_path_bone(path); if(!found) found= buttons_context_path_data(path, OB_ARMATURE); @@ -553,7 +554,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r "world", "object", "mesh", "armature", "lattice", "curve", "meta_ball", "lamp", "camera", "material", "material_slot", "texture", "texture_slot", "bone", "edit_bone", "particle_system", - "cloth", "soft_body", "fluid", "smoke", "smoke_hr", "collision", "brush", NULL}; + "cloth", "soft_body", "fluid", "smoke", "collision", "brush", NULL}; CTX_data_dir_set(result, dir); return 1; diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c index a1041bc5106..83dd679c543 100644 --- a/source/blender/editors/space_buttons/buttons_header.c +++ b/source/blender/editors/space_buttons/buttons_header.c @@ -114,13 +114,15 @@ void buttons_header_buttons(const bContext *C, ARegion *ar) if(sbuts->pathflag & (1<<BCONTEXT_OBJECT)) uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_OBJECT_DATA, xco+=BUTS_UI_UNIT, yco, BUTS_UI_UNIT, BUTS_UI_UNIT, &(sbuts->mainb), 0.0, (float)BCONTEXT_OBJECT, 0, 0, "Object"); if(sbuts->pathflag & (1<<BCONTEXT_CONSTRAINT)) - uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_CONSTRAINT, xco+=BUTS_UI_UNIT, yco, BUTS_UI_UNIT, BUTS_UI_UNIT, &(sbuts->mainb), 0.0, (float)BCONTEXT_CONSTRAINT, 0, 0, "Constraint"); + uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_CONSTRAINT, xco+=BUTS_UI_UNIT, yco, BUTS_UI_UNIT, BUTS_UI_UNIT, &(sbuts->mainb), 0.0, (float)BCONTEXT_CONSTRAINT, 0, 0, "Object Constraints"); if(sbuts->pathflag & (1<<BCONTEXT_DATA)) uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, sbuts->dataicon, xco+=BUTS_UI_UNIT, yco, BUTS_UI_UNIT, BUTS_UI_UNIT, &(sbuts->mainb), 0.0, (float)BCONTEXT_DATA, 0, 0, "Object Data"); if(sbuts->pathflag & (1<<BCONTEXT_MODIFIER)) - uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_MODIFIER, xco+=BUTS_UI_UNIT, yco, BUTS_UI_UNIT, BUTS_UI_UNIT, &(sbuts->mainb), 0.0, (float)BCONTEXT_MODIFIER, 0, 0, "Modifier"); + uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_MODIFIER, xco+=BUTS_UI_UNIT, yco, BUTS_UI_UNIT, BUTS_UI_UNIT, &(sbuts->mainb), 0.0, (float)BCONTEXT_MODIFIER, 0, 0, "Modifiers"); if(sbuts->pathflag & (1<<BCONTEXT_BONE)) uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_BONE_DATA, xco+=BUTS_UI_UNIT, yco, BUTS_UI_UNIT, BUTS_UI_UNIT, &(sbuts->mainb), 0.0, (float)BCONTEXT_BONE, 0, 0, "Bone"); + if(sbuts->pathflag & (1<<BCONTEXT_BONE_CONSTRAINT)) + uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_CONSTRAINT, xco+=BUTS_UI_UNIT, yco, BUTS_UI_UNIT, BUTS_UI_UNIT, &(sbuts->mainb), 0.0, (float)BCONTEXT_BONE_CONSTRAINT, 0, 0, "Bone Constraints"); if(sbuts->pathflag & (1<<BCONTEXT_MATERIAL)) uiDefIconButS(block, ROW, B_CONTEXT_SWITCH, ICON_MATERIAL, xco+=BUTS_UI_UNIT, yco, BUTS_UI_UNIT, BUTS_UI_UNIT, &(sbuts->mainb), 0.0, (float)BCONTEXT_MATERIAL, 0, 0, "Material"); if(sbuts->pathflag & (1<<BCONTEXT_TEXTURE)) diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 9b335b86163..4387da19341 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -738,9 +738,9 @@ void PARTICLE_OT_target_move_down(wmOperatorType *ot) static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) { ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); - ParticleData *pa = psys->particles; - PTCacheEdit *edit = psys->edit; - PTCacheEditPoint *point = edit ? edit->points : NULL; + ParticleData *pa; + PTCacheEdit *edit; + PTCacheEditPoint *point; PTCacheEditKey *ekey = NULL; HairKey *key; int i, k; @@ -751,8 +751,11 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) if(!psys->part || psys->part->type != PART_HAIR) return; + + edit = psys->edit; + point= edit ? edit->points : NULL; - for(i=0; i<psys->totpart; i++,pa++) { + for(i=0, pa=psys->particles; i<psys->totpart; i++,pa++) { if(point) { ekey = point->keys; point++; @@ -820,9 +823,9 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot) static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) { ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); - ParticleData *pa = psys->particles; - PTCacheEdit *edit = psys->edit; - PTCacheEditPoint *point = edit ? edit->points : NULL; + ParticleData *pa; + PTCacheEdit *edit; + PTCacheEditPoint *point; PTCacheEditKey *ekey; HairKey *key; BVHTreeFromMesh bvhtree; @@ -836,7 +839,10 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) if(!psys || !psys->part || psys->part->type != PART_HAIR) return; - + + edit= psys->edit; + point= edit ? edit->points : NULL; + if(psmd->dm->deformedOnly) dm= psmd->dm; else @@ -852,7 +858,7 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6); - for(i=0; i<psys->totpart; i++,pa++) { + for(i=0, pa= psys->particles; i<psys->totpart; i++,pa++) { key = pa->hair; nearest.index = -1; @@ -1107,7 +1113,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, wmEvent *event) op->customdata= fbo; str= RNA_property_string_get_alloc(&ptr, prop, 0, 0); - RNA_string_set(op->ptr, "filename", str); + RNA_string_set(op->ptr, "path", str); MEM_freeN(str); WM_event_add_fileselect(C, op); diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index d4ad77daca7..48acaffd580 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -138,11 +138,11 @@ static SpaceLink *buttons_duplicate(SpaceLink *sl) /* add handlers, stuff you only do once or on area/region changes */ static void buttons_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; ED_region_panels_init(wm, ar); - keymap= WM_keymap_listbase(wm, "Buttons Generic", SPACE_BUTS, 0); + keymap= WM_keymap_find(wm, "Buttons Generic", SPACE_BUTS, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } @@ -176,6 +176,8 @@ static void buttons_main_area_draw(const bContext *C, ARegion *ar) ED_region_panels(C, ar, vertical, "modifier", sbuts->mainb); else if (sbuts->mainb == BCONTEXT_CONSTRAINT) ED_region_panels(C, ar, vertical, "constraint", sbuts->mainb); + else if(sbuts->mainb == BCONTEXT_BONE_CONSTRAINT) + ED_region_panels(C, ar, vertical, "bone_constraint", sbuts->mainb); sbuts->re_align= 0; sbuts->mainbo= sbuts->mainb; @@ -216,7 +218,7 @@ void buttons_operatortypes(void) void buttons_keymap(struct wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Buttons Generic", SPACE_BUTS, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Buttons Generic", SPACE_BUTS, 0); WM_keymap_add_item(keymap, "BUTTONS_OT_toolbox", RIGHTMOUSE, KM_PRESS, 0, 0); } @@ -259,58 +261,6 @@ static void buttons_header_area_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); } -#if 0 -/* add handlers, stuff you only do once or on area/region changes */ -static void buttons_context_area_init(wmWindowManager *wm, ARegion *ar) -{ - UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy); -} - -#define CONTEXTY 30 - -static void buttons_context_area_draw(const bContext *C, ARegion *ar) -{ - SpaceButs *sbuts= CTX_wm_space_buts(C); - uiStyle *style= U.uistyles.first; - uiBlock *block; - uiLayout *layout; - View2D *v2d= &ar->v2d; - float col[3]; - int x, y, w, h; - - buttons_context_compute(C, sbuts); - - w= v2d->cur.xmax - v2d->cur.xmin; - h= v2d->cur.ymax - v2d->cur.ymin; - UI_view2d_view_ortho(C, v2d); - - /* create UI */ - block= uiBeginBlock(C, ar, "buttons_context", UI_EMBOSS); - layout= uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_PANEL, - style->panelspace, h - (h-UI_UNIT_Y)/2, w, 20, style); - - buttons_context_draw(C, layout); - - uiBlockLayoutResolve(C, block, &x, &y); - uiEndBlock(C, block); - - /* draw */ - UI_SetTheme(SPACE_BUTS, RGN_TYPE_WINDOW); /* XXX */ - - UI_GetThemeColor3fv(TH_BACK, col); - glClearColor(col[0], col[1], col[2], 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - UI_view2d_totRect_set(v2d, x, -y); - UI_view2d_view_ortho(C, v2d); - - uiDrawBlock(C, block); - - /* restore view matrix */ - UI_view2d_view_restore(C); -} -#endif - /* reused! */ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) { @@ -424,19 +374,6 @@ void ED_spacetype_buttons(void) art->draw= buttons_header_area_draw; BLI_addhead(&st->regiontypes, art); -#if 0 - /* regions: context */ - art= MEM_callocN(sizeof(ARegionType), "spacetype buttons region"); - art->regionid = RGN_TYPE_CHANNELS; - art->minsizey= CONTEXTY; - art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; - art->init= buttons_context_area_init; - art->draw= buttons_context_area_draw;; - art->listener= buttons_area_listener; - - BLI_addhead(&st->regiontypes, art); -#endif - BKE_spacetype_register(st); } diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 2120b97becf..ccf7dbff946 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -51,6 +51,7 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_report.h" +#include "BKE_text.h" /* only for character utility funcs */ #include "WM_api.h" #include "WM_types.h" @@ -119,6 +120,48 @@ static int console_line_cursor_set(ConsoleLine *cl, int cursor) return 1; } +static char cursor_char(ConsoleLine *cl) +{ + /* assume cursor is clamped */ + return cl->line[cl->cursor]; +} + +static char cursor_char_prev(ConsoleLine *cl) +{ + /* assume cursor is clamped */ + if(cl->cursor <= 0) + return '\0'; + + return cl->line[cl->cursor-1]; +} + +static char cursor_char_next(ConsoleLine *cl) +{ + /* assume cursor is clamped */ + if(cl->cursor + 1 >= cl->len) + return '\0'; + + return cl->line[cl->cursor+1]; +} + +static void console_lb_debug__internal(ListBase *lb) +{ + ConsoleLine *cl; + + printf("%d: ", BLI_countlist(lb)); + for(cl= lb->first; cl; cl= cl->next) + printf("<%s> ", cl->line); + printf("\n"); + +} + +static void console_history_debug(const bContext *C) +{ + SpaceConsole *sc= CTX_wm_space_console(C); + + console_lb_debug__internal(&sc->history); +} + static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from) { ConsoleLine *ci= MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add"); @@ -251,7 +294,7 @@ static EnumPropertyItem move_type_items[]= { {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""}, {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""}, {0, NULL, 0, NULL, NULL}}; - + static int move_exec(bContext *C, wmOperator *op) { ConsoleLine *ci= console_history_verify(C); @@ -272,6 +315,37 @@ static int move_exec(bContext *C, wmOperator *op) case NEXT_CHAR: done= console_line_cursor_set(ci, ci->cursor+1); break; + + /* - if the character is a delimiter then skip delimiters (including white space) + * - when jump over the word */ + case PREV_WORD: + while(text_check_delim(cursor_char_prev(ci))) + if(console_line_cursor_set(ci, ci->cursor-1)==FALSE) + break; + + while(text_check_delim(cursor_char_prev(ci))==FALSE) + if(console_line_cursor_set(ci, ci->cursor-1)==FALSE) + break; + + /* This isnt used for NEXT_WORD because when going back + * its more useful to have the cursor directly after a word then whitespace */ + while(text_check_whitespace(cursor_char_prev(ci))==TRUE) + if(console_line_cursor_set(ci, ci->cursor-1)==FALSE) + break; + + done= 1; /* assume changed */ + break; + case NEXT_WORD: + while(text_check_delim(cursor_char(ci))==TRUE) + if (console_line_cursor_set(ci, ci->cursor+1)==FALSE) + break; + + while(text_check_delim(cursor_char(ci))==FALSE) + if (console_line_cursor_set(ci, ci->cursor+1)==FALSE) + break; + + done= 1; /* assume changed */ + break; } if(done) { @@ -466,7 +540,16 @@ static int history_cycle_exec(bContext *C, wmOperator *op) ConsoleLine *ci= console_history_verify(C); /* TODO - stupid, just prevernts crashes when no command line */ short reverse= RNA_boolean_get(op->ptr, "reverse"); /* assumes down, reverse is up */ - + + /* keep a copy of the line above so when history is cycled + * this is the only function that needs to know about the double-up */ + if(ci->prev) { + ConsoleLine *ci_prev= (ConsoleLine *)ci->prev; + + if(strcmp(ci->line, ci_prev->line)==0) + console_history_free(sc, ci_prev); + } + if(reverse) { /* last item in mistory */ ci= sc->history.last; BLI_remlink(&sc->history, ci); @@ -477,9 +560,17 @@ static int history_cycle_exec(bContext *C, wmOperator *op) BLI_remlink(&sc->history, ci); BLI_addtail(&sc->history, ci); } - + + { /* add a duplicate of the new arg and remove all other instances */ + ConsoleLine *cl; + while((cl= console_history_find(sc, ci->line, ci))) + console_history_free(sc, cl); + + console_history_add(C, (ConsoleLine *)sc->history.last); + } + ED_area_tag_redraw(CTX_wm_area(C)); - + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index dfaaa269970..19fb575ed16 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -147,12 +147,12 @@ static SpaceLink *console_duplicate(SpaceLink *sl) /* add handlers, stuff you only do once or on area/region changes */ static void console_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "Console", SPACE_CONSOLE, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "Console", SPACE_CONSOLE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -174,6 +174,9 @@ static void console_main_area_draw(const bContext *C, ARegion *ar) console_scrollback_add_str(C, "Autocomplete: Ctrl+Space", 0); console_scrollback_add_str(C, "Ctrl +/- Wheel: Zoom", 0); console_scrollback_add_str(C, "Builtin Modules: bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.ui", 0); + + /* This is normally set by python but to start with its easier just to set it like this rather then running python with no args */ + strcpy(sc->prompt, ">>> "); } /* clear and setup matrix */ @@ -231,15 +234,15 @@ void console_operatortypes(void) void console_keymap(struct wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Console", SPACE_CONSOLE, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Console", SPACE_CONSOLE, 0); - #ifdef __APPLE__ +#ifdef __APPLE__ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN); RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_END); - #endif +#endif - RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", LINE_BEGIN); - RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", LINE_END); + RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD); + RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD); RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", HOMEKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_BEGIN); RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END); diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 00024ffa961..5d02e096228 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -133,24 +133,24 @@ static void do_file_buttons(bContext *C, void *arg, int event) void file_draw_buttons(const bContext *C, ARegion *ar) { /* Button layout. */ - const short min_x = 10; - const short max_x = ar->winx - 10; - const short line1_y = IMASEL_BUTTONS_HEIGHT/2 + IMASEL_BUTTONS_MARGIN*2; - const short line2_y = IMASEL_BUTTONS_MARGIN; - const short input_minw = 20; - const short btn_h = UI_UNIT_Y; - const short btn_fn_w = UI_UNIT_X; - const short btn_minw = 80; - const short btn_margin = 20; - const short separator = 4; + const int min_x = 10; + const int max_x = ar->winx - 10; + const int line1_y = IMASEL_BUTTONS_HEIGHT/2 + IMASEL_BUTTONS_MARGIN*2; + const int line2_y = IMASEL_BUTTONS_MARGIN; + const int input_minw = 20; + const int btn_h = UI_UNIT_Y; + const int btn_fn_w = UI_UNIT_X; + const int btn_minw = 80; + const int btn_margin = 20; + const int separator = 4; /* Additional locals. */ char name[20]; - short loadbutton; - short fnumbuttons; - short available_w = max_x - min_x; - short line1_w = available_w; - short line2_w = available_w; + int loadbutton; + int fnumbuttons; + int available_w = max_x - min_x; + int line1_w = available_w; + int line2_w = available_w; uiBut* but; uiBlock* block; @@ -189,7 +189,7 @@ void file_draw_buttons(const bContext *C, ARegion *ar) if (available_w > 0) { but = uiDefBut(block, TEX, B_FS_DIRNAME, "", min_x, line1_y, line1_w, btn_h, - params->dir, 0.0, (float)FILE_MAXDIR-1, 0, 0, + params->dir, 0.0, (float)FILE_MAX-1, 0, 0, "File path."); uiButSetCompleteFunc(but, autocomplete_directory, NULL); uiDefBut(block, TEX, B_FS_FILENAME, "", @@ -230,7 +230,7 @@ void file_draw_buttons(const bContext *C, ARegion *ar) } -static void draw_tile(short sx, short sy, short width, short height, int colorid, int shade) +static void draw_tile(int sx, int sy, int width, int height, int colorid, int shade) { UI_ThemeColorShade(colorid, shade); uiSetRoundBox(15); @@ -310,7 +310,7 @@ static int get_file_icon(struct direntry *file) return ICON_FILE_BLANK; } -static void file_draw_icon(short sx, short sy, int icon, short width, short height) +static void file_draw_icon(int sx, int sy, int icon, int width, int height) { float x,y; int blend=0; @@ -326,9 +326,9 @@ static void file_draw_icon(short sx, short sy, int icon, short width, short heig } -static void file_draw_string(short sx, short sy, const char* string, float width, short height, int flag) +static void file_draw_string(int sx, int sy, const char* string, float width, int height, int flag) { - short soffs; + int soffs; char fname[FILE_MAXFILE]; float sw; float x,y; @@ -350,18 +350,19 @@ void file_calc_previews(const bContext *C, ARegion *ar) View2D *v2d= &ar->v2d; ED_fileselect_init_layout(sfile, ar); - UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height); + /* +SCROLL_HEIGHT is bad hack to work around issue in UI_view2d_totRect_set */ + UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height+V2D_SCROLL_HEIGHT); } -static void file_draw_preview(short sx, short sy, ImBuf *imb, FileLayout *layout, short dropshadow) +static void file_draw_preview(int sx, int sy, ImBuf *imb, FileLayout *layout, short dropshadow) { if (imb) { float fx, fy; float dx, dy; - short xco, yco; + int xco, yco; float scaledx, scaledy; float scale; - short ex, ey; + int ex, ey; if ( (imb->x > layout->prv_w) || (imb->y > layout->prv_h) ) { if (imb->x > imb->y) { @@ -379,8 +380,8 @@ static void file_draw_preview(short sx, short sy, ImBuf *imb, FileLayout *layout scaledy = (float)imb->y; scale = 1.0; } - ex = (short)scaledx; - ey = (short)scaledy; + ex = (int)scaledx; + ey = (int)scaledy; fx = ((float)layout->prv_w - (float)ex)/2.0f; fy = ((float)layout->prv_h - (float)ey)/2.0f; dx = (fx + 0.5f + layout->prv_border_x); @@ -442,7 +443,7 @@ static void renamebutton_cb(bContext *C, void *arg1, char *oldname) static void draw_background(FileLayout *layout, View2D *v2d) { int i; - short sy; + int sy; /* alternating flat shade background */ for (i=0; (i <= layout->rows); i+=2) @@ -457,7 +458,7 @@ static void draw_background(FileLayout *layout, View2D *v2d) static void draw_dividers(FileLayout *layout, View2D *v2d) { - short sx; + int sx; /* vertical column dividers */ sx = v2d->tot.xmin; @@ -483,7 +484,7 @@ void file_draw_list(const bContext *C, ARegion *ar) int numfiles; int numfiles_layout; int colorid = 0; - short sx, sy; + int sx, sy; int offset; int i; float sw, spos; @@ -491,12 +492,6 @@ void file_draw_list(const bContext *C, ARegion *ar) numfiles = filelist_numfiles(files); - sx = ar->v2d.tot.xmin + layout->tile_border_x/2; - sy = ar->v2d.cur.ymax - layout->tile_border_y; - - offset = ED_fileselect_layout_offset(layout, 0, 0); - if (offset<0) offset=0; - if (params->display != FILE_IMGDISPLAY) { draw_background(layout, v2d); @@ -504,9 +499,9 @@ void file_draw_list(const bContext *C, ARegion *ar) draw_dividers(layout, v2d); } - sx = ar->v2d.cur.xmin + layout->tile_border_x; - sy = ar->v2d.cur.ymax - layout->tile_border_y; - + offset = ED_fileselect_layout_offset(layout, ar->v2d.cur.xmin, -ar->v2d.cur.ymax); + if (offset<0) offset=0; + numfiles_layout = ED_fileselect_layout_numfiles(layout, ar); for (i=offset; (i < numfiles) && (i<offset+numfiles_layout); ++i) @@ -552,7 +547,7 @@ void file_draw_list(const bContext *C, ARegion *ar) sw = file_string_width(file->relname); if (file->flags & EDITING) { - short but_width = (FILE_IMGDISPLAY == params->display) ? layout->tile_w : layout->column_widths[COLUMN_NAME]; + int but_width = (FILE_IMGDISPLAY == params->display) ? layout->tile_w : layout->column_widths[COLUMN_NAME]; uiBlock *block = uiBeginBlock(C, ar, "FileName", UI_EMBOSS); uiBut *but = uiDefBut(block, TEX, 1, "", spos, sy-layout->tile_h-3, but_width, layout->textheight*2, file->relname, 1.0f, (float)FILE_MAX,0,0,""); @@ -573,15 +568,14 @@ void file_draw_list(const bContext *C, ARegion *ar) spos += layout->column_widths[COLUMN_NAME] + 12; if (!(file->type & S_IFDIR)) { sw = file_string_width(file->size); - spos += layout->column_widths[COLUMN_SIZE] + 12 - sw; file_draw_string(spos, sy, file->size, sw+1, layout->tile_h, FILE_SHORTEN_END); + spos += layout->column_widths[COLUMN_SIZE] + 12; } } else if (params->display == FILE_LONGDISPLAY) { spos += layout->column_widths[COLUMN_NAME] + 12; #ifndef WIN32 /* rwx rwx rwx */ - spos += 20; sw = file_string_width(file->mode1); file_draw_string(spos, sy, file->mode1, sw, layout->tile_h, FILE_SHORTEN_END); spos += layout->column_widths[COLUMN_MODE1] + 12; @@ -609,8 +603,8 @@ void file_draw_list(const bContext *C, ARegion *ar) if (!(file->type & S_IFDIR)) { sw = file_string_width(file->size); - spos += layout->column_widths[COLUMN_SIZE] + 12 - sw; file_draw_string(spos, sy, file->size, sw, layout->tile_h, FILE_SHORTEN_END); + spos += layout->column_widths[COLUMN_SIZE] + 12; } } } diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 9705a36fc75..75230813a41 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -68,25 +68,15 @@ /* ---------- FILE SELECTION ------------ */ -static int find_file_mouse(SpaceFile *sfile, struct ARegion* ar, short x, short y, short clamp) +static int find_file_mouse(SpaceFile *sfile, struct ARegion* ar, int x, int y) { float fx,fy; int active_file = -1; - int numfiles = filelist_numfiles(sfile->files); View2D* v2d = &ar->v2d; UI_view2d_region_to_view(v2d, x, y, &fx, &fy); active_file = ED_fileselect_layout_offset(sfile->layout, v2d->tot.xmin + fx, v2d->tot.ymax - fy); - - if(active_file < 0) { - if(clamp) active_file= 0; - else active_file= -1; - } - else if(active_file >= numfiles) { - if(clamp) active_file= numfiles-1; - else active_file= -1; - } return active_file; } @@ -109,6 +99,31 @@ typedef enum FileSelect { FILE_SELECT_DIR = 1, FILE_SELECT_FILE = 2 } FileSelect; +static void clamp_to_filelist(int numfiles, int *first_file, int *last_file) +{ + /* border select before the first file */ + if ( (*first_file < 0) && (*last_file >=0 ) ) { + *first_file = 0; + } + /* don't select if everything is outside filelist */ + if ( (*first_file >= numfiles) && ((*last_file < 0) || (*last_file >= numfiles)) ) { + *first_file = -1; + *last_file = -1; + } + + /* fix if last file invalid */ + if ( (*first_file > 0) && (*last_file < 0) ) + *last_file = numfiles-1; + + /* clamp */ + if ( (*first_file >= numfiles) ) { + *first_file = numfiles-1; + } + if ( (*last_file >= numfiles) ) { + *last_file = numfiles-1; + } +} + static FileSelect file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, short val) { int first_file = -1; @@ -123,9 +138,11 @@ static FileSelect file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, s int numfiles = filelist_numfiles(sfile->files); params->selstate = NOTACTIVE; - first_file = find_file_mouse(sfile, ar, rect->xmin, rect->ymax, 1); - last_file = find_file_mouse(sfile, ar, rect->xmax, rect->ymin, 1); + first_file = find_file_mouse(sfile, ar, rect->xmin, rect->ymax); + last_file = find_file_mouse(sfile, ar, rect->xmax, rect->ymin); + clamp_to_filelist(numfiles, &first_file, &last_file); + /* select all valid files between first and last indicated */ if ( (first_file >= 0) && (first_file < numfiles) && (last_file >= 0) && (last_file < numfiles) ) { for (act_file = first_file; act_file <= last_file; act_file++) { @@ -137,6 +154,9 @@ static FileSelect file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, s } } + /* Don't act on multiple selected files */ + if (first_file != last_file) selecting= 0; + /* make the last file active */ if (selecting && (last_file >= 0 && last_file < numfiles)) { struct direntry* file = filelist_file(sfile->files, last_file); @@ -168,7 +188,7 @@ static FileSelect file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, s } } - } + } return retval; } @@ -449,7 +469,7 @@ int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my) my -= ar->winrct.ymin; if(BLI_in_rcti(&ar->v2d.mask, mx, my)) { - actfile = find_file_mouse(sfile, ar, mx , my, 0); + actfile = find_file_mouse(sfile, ar, mx , my); if((actfile >= 0) && (actfile < numfiles)) params->active_file=actfile; @@ -496,9 +516,26 @@ int file_cancel_exec(bContext *C, wmOperator *unused) WM_event_fileselect_event(C, sfile->op, EVT_FILESELECT_CANCEL); sfile->op = NULL; + if (sfile->files) { + filelist_freelib(sfile->files); + filelist_free(sfile->files); + MEM_freeN(sfile->files); + sfile->files= NULL; + } + return OPERATOR_FINISHED; } +int file_operator_poll(bContext *C) +{ + int poll = ED_operator_file_active(C); + SpaceFile *sfile= CTX_wm_space_file(C); + + if (!sfile || !sfile->op) poll= 0; + + return poll; +} + void FILE_OT_cancel(struct wmOperatorType *ot) { /* identifiers */ @@ -507,7 +544,7 @@ void FILE_OT_cancel(struct wmOperatorType *ot) /* api callbacks */ ot->exec= file_cancel_exec; - ot->poll= ED_operator_file_active; + ot->poll= file_operator_poll; } /* sends events now, so things get handled on windowqueue level */ @@ -525,9 +562,10 @@ int file_exec(bContext *C, wmOperator *unused) RNA_string_set(op->ptr, "directory", name); strcat(name, sfile->params->file); - if ( RNA_boolean_get(op->ptr, "relative_paths") ) { - BLI_makestringcode(G.sce, name); - } + if(RNA_struct_find_property(op->ptr, "relative_paths")) + if(RNA_boolean_get(op->ptr, "relative_paths")) + BLI_makestringcode(G.sce, name); + RNA_string_set(op->ptr, "path", name); /* some ops have multiple files to select */ @@ -567,6 +605,11 @@ int file_exec(bContext *C, wmOperator *unused) BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs"); fsmenu_write_file(fsmenu_get(), name); WM_event_fileselect_event(C, op, EVT_FILESELECT_EXEC); + + filelist_freelib(sfile->files); + filelist_free(sfile->files); + MEM_freeN(sfile->files); + sfile->files= NULL; } return OPERATOR_FINISHED; @@ -580,7 +623,7 @@ void FILE_OT_execute(struct wmOperatorType *ot) /* api callbacks */ ot->exec= file_exec; - ot->poll= ED_operator_file_active; /* <- important, handler is on window level */ + ot->poll= file_operator_poll; } @@ -855,13 +898,9 @@ int file_bookmark_toggle_exec(bContext *C, wmOperator *unused) ScrArea *sa= CTX_wm_area(C); ARegion *ar= file_buttons_region(sa); - if(ar) { - ar->flag ^= RGN_FLAG_HIDDEN; - ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */ - - ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); - ED_area_tag_redraw(sa); - } + if(ar) + ED_region_toggle_hidden(C, ar); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 23f24f26dc0..8257aa5482f 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -592,10 +592,12 @@ void filelist_loadimage_timer(struct FileList* filelist) } if (limg->done) { FileImage *oimg = limg; - BLI_remlink(&filelist->loadimages, oimg); BLI_remove_thread(&filelist->threads, oimg); + /* brecht: keep failed images in the list, otherwise + it keeps trying to load them over and over? + BLI_remlink(&filelist->loadimages, oimg); + MEM_freeN(oimg);*/ limg = oimg->next; - MEM_freeN(oimg); refresh = 1; } else { limg= limg->next; @@ -802,6 +804,8 @@ static void filelist_read_library(struct FileList* filelist) if(!filelist->libfiledata) { int num; struct direntry *file; + + BLI_make_exist(filelist->dir); filelist_read_dir(filelist); file = filelist->filelist; for(num=0; num<filelist->numfiles; num++, file++) { @@ -1184,11 +1188,6 @@ void filelist_from_main(struct FileList *filelist) id= lb->first; filelist->numfiles= 0; while(id) { - /* XXXXX TODO: the selection of the ipo blocktype might go somewhere else? - if(filelist->has_func && idcode==ID_IP) { - if(filelist->ipotype== ((Ipo *)id)->blocktype) filelist->numfiles++; - } - else */ if (!filelist->hide_dot || id->name[2] != '.') { filelist->numfiles++; } @@ -1214,14 +1213,6 @@ void filelist_from_main(struct FileList *filelist) totlib= totbl= 0; while(id) { -#if 0 - // XXXXX TODO: this is deprecated, checks for correct IPO block? - ok= 0; - if(filelist->has_func && idcode==ID_IP) { - if(filelist->ipotype== ((Ipo *)id)->blocktype) ok= 1; - } - else ok= 1; -#endif ok = 1; if(ok) { if (!filelist->hide_dot || id->name[2] != '.') { diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 085eecd2a7d..1f461f1bbd5 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -117,8 +117,6 @@ short ED_fileselect_set_params(SpaceFile *sfile) BLI_strncpy(sfile->params->file, file, sizeof(sfile->params->file)); BLI_make_file_string(G.sce, sfile->params->dir, dir, ""); /* XXX needed ? - also solve G.sce */ } - - ED_fileselect_reset_params(sfile); params = sfile->params; @@ -169,18 +167,13 @@ short ED_fileselect_set_params(SpaceFile *sfile) } else { /* default values, if no operator */ + params->type = FILE_UNIX; params->flag |= FILE_HIDE_DOT; params->display = FILE_SHORTDISPLAY; params->filter = 0; params->sort = FILE_SORT_ALPHA; } - /* new params, refresh file list */ - if(sfile->files) { - filelist_free(sfile->files); - filelist_setdir(sfile->files, params->dir); - } - return 1; } @@ -196,14 +189,14 @@ int ED_fileselect_layout_numfiles(FileLayout* layout, struct ARegion *ar) int numfiles; if (layout->flag & FILE_LAYOUT_HOR) { - short width = ar->v2d.cur.xmax - ar->v2d.cur.xmin - 2*layout->tile_border_x; + int width = ar->v2d.cur.xmax - ar->v2d.cur.xmin - 2*layout->tile_border_x; numfiles = width/layout->tile_w + 1; + return numfiles*layout->rows; } else { - short height = ar->v2d.cur.ymax - ar->v2d.cur.ymin - 2*layout->tile_border_y; + int height = ar->v2d.cur.ymax - ar->v2d.cur.ymin - 2*layout->tile_border_y; numfiles = height/layout->tile_h + 1; + return numfiles*layout->columns; } - - return layout->columns*layout->rows; } int ED_fileselect_layout_offset(FileLayout* layout, int x, int y) @@ -227,7 +220,7 @@ int ED_fileselect_layout_offset(FileLayout* layout, int x, int y) return active_file; } -void ED_fileselect_layout_tilepos(FileLayout* layout, int tile, short *x, short *y) +void ED_fileselect_layout_tilepos(FileLayout* layout, int tile, int *x, int *y) { if (layout->flag == FILE_LAYOUT_HOR) { *x = layout->tile_border_x + (tile/layout->rows)*(layout->tile_w+2*layout->tile_border_x); @@ -270,7 +263,7 @@ static void column_widths(struct FileList* files, struct FileLayout* layout) if (file) { int len; len = file_string_width(file->relname); - if (len > layout->column_widths[COLUMN_NAME]) layout->column_widths[COLUMN_NAME] = len; + if (len > layout->column_widths[COLUMN_NAME]) layout->column_widths[COLUMN_NAME] = len + 20; len = file_string_width(file->date); if (len > layout->column_widths[COLUMN_DATE]) layout->column_widths[COLUMN_DATE] = len; len = file_string_width(file->time); @@ -342,18 +335,23 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *ar) column_widths(sfile->files, layout); if (params->display == FILE_SHORTDISPLAY) { - maxlen = layout->column_widths[COLUMN_NAME] + + maxlen = layout->column_widths[COLUMN_NAME] + 12 + layout->column_widths[COLUMN_SIZE]; - maxlen += 20+2*10; // for icon and space between columns + maxlen += 20; // for icon } else { - maxlen = layout->column_widths[COLUMN_NAME] + - layout->column_widths[COLUMN_DATE] + - layout->column_widths[COLUMN_TIME] + + maxlen = layout->column_widths[COLUMN_NAME] + 12 + +#ifndef WIN32 + layout->column_widths[COLUMN_MODE1] + 12 + + layout->column_widths[COLUMN_MODE2] + 12 + + layout->column_widths[COLUMN_MODE3] + 12 + + layout->column_widths[COLUMN_OWNER] + 12 + +#endif + layout->column_widths[COLUMN_DATE] + 12 + + layout->column_widths[COLUMN_TIME] + 12 + layout->column_widths[COLUMN_SIZE]; - /* XXX add mode1, mode2, mode3, owner columns for non-windows platforms */ - maxlen += 20+4*10; // for icon and space between columns + maxlen += 20; // for icon } - layout->tile_w = maxlen + 40; + layout->tile_w = maxlen; if(layout->rows > 0) layout->columns = numfiles/layout->rows + 1; // XXX dirty, modulo is zero else { @@ -424,13 +422,16 @@ void autocomplete_directory(struct bContext *C, char *str, void *arg_v) struct direntry* file = filelist_file(sfile->files, i); const char* dir = filelist_dir(sfile->files); if (file && S_ISDIR(file->type)) { - BLI_make_file_string(G.sce, tmp, dir, file->relname); + // BLI_make_file_string(G.sce, tmp, dir, file->relname); + BLI_join_dirfile(tmp, dir, file->relname); autocomplete_do_name(autocpl,tmp); } } autocomplete_end(autocpl, str); if (BLI_exists(str)) { BLI_add_slash(str); + } else { + BLI_make_exist(str); } } } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 47839ea0342..ed0d998ef40 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -156,9 +156,9 @@ static void file_free(SpaceLink *sl) static void file_init(struct wmWindowManager *wm, ScrArea *sa) { SpaceFile *sfile= (SpaceFile*)sa->spacedata.first; - MEM_freeN(sfile->params); - sfile->params = 0; printf("file_init\n"); + + if(sfile->layout) sfile->layout->dirty= 1; } @@ -205,6 +205,7 @@ static void file_refresh(const bContext *C, ScrArea *sa) if (filelist_empty(sfile->files)) { filelist_readdir(sfile->files); + BLI_strncpy(params->dir, filelist_dir(sfile->files), FILE_MAX); } if(params->sort!=FILE_SORT_NONE) filelist_sort(sfile->files, params->sort); @@ -247,15 +248,15 @@ static void file_listener(ScrArea *sa, wmNotifier *wmn) /* add handlers, stuff you only do once or on area/region changes */ static void file_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); /* own keymaps */ - keymap= WM_keymap_listbase(wm, "File", SPACE_FILE, 0); + keymap= WM_keymap_find(wm, "File", SPACE_FILE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - keymap= WM_keymap_listbase(wm, "FileMain", SPACE_FILE, 0); + keymap= WM_keymap_find(wm, "FileMain", SPACE_FILE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); @@ -367,7 +368,7 @@ void file_keymap(struct wmWindowManager *wm) { wmKeymapItem *kmi; /* keys for all areas */ - ListBase *keymap= WM_keymap_listbase(wm, "File", SPACE_FILE, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "File", SPACE_FILE, 0); WM_keymap_add_item(keymap, "FILE_OT_bookmark_toggle", NKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_parent", PKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_add_bookmark", BKEY, KM_PRESS, KM_CTRL, 0); @@ -378,7 +379,7 @@ void file_keymap(struct wmWindowManager *wm) WM_keymap_add_item(keymap, "FILE_OT_delete", XKEY, KM_PRESS, 0, 0); /* keys for main area */ - keymap= WM_keymap_listbase(wm, "FileMain", SPACE_FILE, 0); + keymap= WM_keymap_find(wm, "FileMain", SPACE_FILE, 0); WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_select_border", BKEY, KM_PRESS, 0, 0); @@ -399,7 +400,7 @@ void file_keymap(struct wmWindowManager *wm) RNA_int_set(kmi->ptr, "increment",-100); /* keys for button area (top) */ - keymap= WM_keymap_listbase(wm, "FileButtons", SPACE_FILE, 0); + keymap= WM_keymap_find(wm, "FileButtons", SPACE_FILE, 0); WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, 0, 0); RNA_int_set(kmi->ptr, "increment", 1); @@ -418,12 +419,12 @@ void file_keymap(struct wmWindowManager *wm) static void file_channel_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; ED_region_panels_init(wm, ar); /* own keymaps */ - keymap= WM_keymap_listbase(wm, "File", SPACE_FILE, 0); + keymap= WM_keymap_find(wm, "File", SPACE_FILE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -454,15 +455,15 @@ static void file_header_area_draw(const bContext *C, ARegion *ar) /* add handlers, stuff you only do once or on area/region changes */ static void file_ui_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "File", SPACE_FILE, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "File", SPACE_FILE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - keymap= WM_keymap_listbase(wm, "FileButtons", SPACE_FILE, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "FileButtons", SPACE_FILE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index fb995285ab7..09008f8d2d1 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -46,15 +46,16 @@ #include "BLI_editVert.h" #include "BLI_rand.h" -#include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" #include "BKE_fcurve.h" +#include "BKE_library.h" +#include "BKE_main.h" #include "BKE_object.h" -#include "BKE_global.h" #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_utildefines.h" @@ -250,6 +251,22 @@ static int graph_panel_drivers_poll(const bContext *C, PanelType *pt) return graph_panel_context(C, NULL, NULL); } +static void test_obpoin_but(struct bContext *C, char *name, ID **idpp) +{ + ID *id; + + id= CTX_data_main(C)->object.first; + while(id) { + if( strcmp(name, id->name+2)==0 ) { + *idpp= id; + id_lib_extern(id); /* checks lib data, sets correct flag for saving then */ + return; + } + id= id->next; + } + *idpp= NULL; +} + /* driver settings for active F-Curve (only for 'Drivers' mode) */ static void graph_panel_drivers(const bContext *C, Panel *pa) { @@ -427,13 +444,9 @@ static int graph_properties(bContext *C, wmOperator *op) ScrArea *sa= CTX_wm_area(C); ARegion *ar= graph_has_buttons_region(sa); - if(ar) { - ar->flag ^= RGN_FLAG_HIDDEN; - ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */ - - ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); - ED_area_tag_redraw(sa); - } + if(ar) + ED_region_toggle_hidden(C, ar); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 9ae7e8263ee..57e2208f089 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -91,6 +91,26 @@ extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad); /* *************************** */ +/* Utility Drawing Defines */ + +/* determine the alpha value that should be used when + * drawing components for some F-Curve (fcu) + * - selected F-Curves should be more visible than partially visible ones + */ +#define drawFCurveFade(fcu) ( ((fcu)->flag & FCURVE_SELECTED)? 1.0f : 0.5f ) + +/* set the colour for some point from some value given packed into an int + * - intV: integer value containing color info packed into an int + * - alpha: float value describing the + */ +#define cpackA(intVC, alpha) \ + { \ + float _cpackCol[3]; \ + cpack_to_rgb(intVC, &_cpackCol[0], &_cpackCol[1], &_cpackCol[2]); \ + glColor4f(_cpackCol[0], _cpackCol[1], _cpackCol[2], alpha); \ + } + +/* *************************** */ /* F-Curve Modifier Drawing */ /* Envelope -------------- */ @@ -258,22 +278,20 @@ static void draw_fcurve_vertices_handles (FCurve *fcu, View2D *v2d, short sel) /* helper func - set color to draw F-Curve data with */ static void set_fcurve_vertex_color (SpaceIpo *sipo, FCurve *fcu, short sel) { -#if 0 - if (sipo->showkey) { - if (sel) UI_ThemeColor(TH_TEXT_HI); - else UI_ThemeColor(TH_TEXT); - } -#endif - if ((fcu->flag & FCURVE_PROTECTED)==0) { - /* Curve's points are being edited */ - if (sel) UI_ThemeColor(TH_VERTEX_SELECT); - else UI_ThemeColor(TH_VERTEX); - } - else { - /* Curve's points cannot be edited */ - if (sel) UI_ThemeColor(TH_TEXT_HI); - else UI_ThemeColor(TH_TEXT); - } + /* Fade the 'intensity' of the vertices based on the selection of the curves too */ + int alphaOffset= (int)((drawFCurveFade(fcu) - 1.0f) * 255); + + /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */ + if ((fcu->flag & FCURVE_PROTECTED)==0) { + /* Curve's points ARE BEING edited */ + if (sel) UI_ThemeColorShadeAlpha(TH_VERTEX_SELECT, 0, alphaOffset); + else UI_ThemeColorShadeAlpha(TH_VERTEX, 0, alphaOffset); + } + else { + /* Curve's points CANNOT BE edited */ + if (sel) UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, alphaOffset); + else UI_ThemeColorShadeAlpha(TH_TEXT, 0, alphaOffset); + } } @@ -322,7 +340,7 @@ static void draw_fcurve_handles (SpaceIpo *sipo, ARegion *ar, FCurve *fcu) if ((sipo->flag & SIPO_NOHANDLES) || (fcu->flag & FCURVE_PROTECTED) || (fcu->flag & FCURVE_INT_VALUES)) return; - /* slightly hacky, but we want to draw unselected points before selected ones*/ + /* slightly hacky, but we want to draw unselected points before selected ones */ for (sel= 0; sel < 2; sel++) { BezTriple *bezt=fcu->bezt, *prevbezt=NULL; float *fp; @@ -337,7 +355,7 @@ static void draw_fcurve_handles (SpaceIpo *sipo, ARegion *ar, FCurve *fcu) /* only draw first handle if previous segment had handles */ if ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) { - cpack(col[(unsigned char)bezt->h1]); + cpackA(col[(unsigned char)bezt->h1], drawFCurveFade(fcu)); glBegin(GL_LINE_STRIP); glVertex2fv(fp); glVertex2fv(fp+3); glEnd(); @@ -347,7 +365,7 @@ static void draw_fcurve_handles (SpaceIpo *sipo, ARegion *ar, FCurve *fcu) /* only draw second handle if this segment is bezier */ if (bezt->ipo == BEZT_IPO_BEZ) { - cpack(col[(unsigned char)bezt->h2]); + cpackA(col[(unsigned char)bezt->h2], drawFCurveFade(fcu)); glBegin(GL_LINE_STRIP); glVertex2fv(fp+3); glVertex2fv(fp+6); glEnd(); @@ -359,7 +377,7 @@ static void draw_fcurve_handles (SpaceIpo *sipo, ARegion *ar, FCurve *fcu) ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) ) { fp= bezt->vec[0]; - cpack(col[(unsigned char)bezt->h1]); + cpackA(col[(unsigned char)bezt->h1], drawFCurveFade(fcu)); glBegin(GL_LINE_STRIP); glVertex2fv(fp); glVertex2fv(fp+3); @@ -371,7 +389,7 @@ static void draw_fcurve_handles (SpaceIpo *sipo, ARegion *ar, FCurve *fcu) (bezt->ipo == BEZT_IPO_BEZ) ) { fp= bezt->vec[1]; - cpack(col[(unsigned char)bezt->h2]); + cpackA(col[(unsigned char)bezt->h2], drawFCurveFade(fcu)); glBegin(GL_LINE_STRIP); glVertex2fv(fp); glVertex2fv(fp+3); @@ -410,7 +428,6 @@ static void draw_fcurve_sample_control (float x, float y, float xscale, float ys glScalef(1.0f/xscale*hsize, 1.0f/yscale*hsize, 1.0f); /* anti-aliased lines for more consistent appearance */ - // XXX needed here? glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); @@ -506,7 +523,6 @@ static void draw_fcurve_curve (FCurve *fcu, SpaceIpo *sipo, View2D *v2d, View2DG } /* helper func - draw a samples-based F-Curve */ -// TODO: add offset stuff... static void draw_fcurve_curve_samples (FCurve *fcu, View2D *v2d) { FPoint *prevfpt= fcu->fpt; @@ -647,7 +663,7 @@ static void draw_fcurve_curve_bezts (FCurve *fcu, View2D *v2d, View2DGrid *grid) */ /* resol not depending on horizontal resolution anymore, drivers for example... */ - // XXX need to take into account the scale + // TODO: would be nice to make this depend on the scale of the graph too... if (fcu->driver) resol= 32; else @@ -809,7 +825,7 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri /* set whatever color the curve has set * - unselected curves draw less opaque to help distinguish the selected ones */ - glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], ((sel) ? 1.0f : 0.5f)); + glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], drawFCurveFade(fcu)); } /* anti-aliased lines for less jagged appearance */ @@ -855,7 +871,10 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) { if (fcu->bezt) { /* only draw handles/vertices on keyframes */ - draw_fcurve_handles(sipo, ar, fcu); + glEnable(GL_BLEND); + draw_fcurve_handles(sipo, ar, fcu); + glDisable(GL_BLEND); + draw_fcurve_vertices(sipo, ar, fcu); } else { diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index d718ef28e99..3e0f9760773 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1296,8 +1296,7 @@ void GRAPH_OT_handle_type (wmOperatorType *ot) /* set of three euler-rotation F-Curves */ typedef struct tEulerFilter { ID *id; /* ID-block which owns the channels */ - FCurve *fcu1, *fcu2, *fcu3; /* x,y,z rotation curves */ - int i1, i2, i3; /* current index for each curve */ + FCurve (*fcurves)[3]; /* 3 Pointers to F-Curves */ } tEulerFilter; static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op) @@ -1336,7 +1335,7 @@ static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op) if (ELEM(0, fcu->rna_path, strstr(fcu->rna_path, "rotation"))) continue; if (strstr(fcu->rna_path, "pose.pose_channels")) { - if (strstr(fcu->rna_path, "euler_rotation") == 0) + if (strstr(fcu->rna_path, "rotation_euler") == 0) continue; } @@ -1345,12 +1344,30 @@ static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op) * - first check if id-blocks are compatible */ if ((euf) && (ale->id != euf->id)) { + /* if the paths match, add this curve to the set of curves */ + // NOTE: simple string compare for now... could be a bit more fancy... } + else { + /* just add to a new block */ + euf= MEM_callocN(sizeof(tEulerFilter), "tEulerFilter"); + BLI_addtail(&eulers, euf); + + euf->id= ale->id; + euf->fcurves[fcu->array_index]= fcu; + } } + BLI_freelistN(&anim_data); - // XXX for now - return OPERATOR_CANCELLED; + /* step 2: go through each set of curves, processing the values at each keyframe + * - it is assumed that there must be a full set of keyframes at each keyframe position + */ + for (euf= eulers.first; euf; euf= euf->next) { + + } + BLI_freelistN(&eulers); + + return OPERATOR_FINISHED; } void GRAPH_OT_euler_filter (wmOperatorType *ot) @@ -1710,13 +1727,18 @@ static int graph_fmodifier_add_invoke (bContext *C, wmOperator *op, wmEvent *eve /* start from 1 to skip the 'Invalid' modifier type */ for (i = 1; i < FMODIFIER_NUM_TYPES; i++) { FModifierTypeInfo *fmi= get_fmodifier_typeinfo(i); + PointerRNA props_ptr; /* check if modifier is valid for this context */ if (fmi == NULL) continue; - /* add entry to add this type of modifier */ - uiItemEnumO(layout, fmi->name, 0, "GRAPH_OT_fmodifier_add", "type", i); + /* create operator menu item with relevant properties filled in */ + props_ptr= uiItemFullO(layout, fmi->name, 0, "GRAPH_OT_fmodifier_add", NULL, WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS); + /* the only thing that gets set from the menu is the type of F-Modifier to add */ + RNA_enum_set(&props_ptr, "type", i); + /* the following properties are just repeats of existing ones... */ + RNA_boolean_set(&props_ptr, "only_active", RNA_boolean_get(op->ptr, "only_active")); } uiItemS(layout); @@ -1728,36 +1750,41 @@ static int graph_fmodifier_add_invoke (bContext *C, wmOperator *op, wmEvent *eve static int graph_fmodifier_add_exec(bContext *C, wmOperator *op) { bAnimContext ac; + ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; - FCurve *fcu; - FModifier *fcm; + int filter; short type; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - - // xxx call the raw methods here instead? - ale= get_active_fcurve_channel(&ac); - if (ale == NULL) - return OPERATOR_CANCELLED; - fcu= (FCurve *)ale->data; - MEM_freeN(ale); - if (fcu == NULL) - return OPERATOR_CANCELLED; - /* get type of modifier to add */ type= RNA_enum_get(op->ptr, "type"); - /* add F-Modifier of specified type to active F-Curve, and make it the active one */ - fcm= add_fmodifier(&fcu->modifiers, type); - if (fcm) - set_active_fmodifier(&fcu->modifiers, fcm); - else { - BKE_report(op->reports, RPT_ERROR, "Modifier couldn't be added. See console for details."); - return OPERATOR_CANCELLED; + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE| ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY); + if (RNA_boolean_get(op->ptr, "only_active")) + filter |= ANIMFILTER_ACTIVE; + else + filter |= ANIMFILTER_SEL; + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* smooth keyframes */ + for (ale= anim_data.first; ale; ale= ale->next) { + FCurve *fcu= (FCurve *)ale->data; + FModifier *fcm; + + /* add F-Modifier of specified type to active F-Curve, and make it the active one */ + fcm= add_fmodifier(&fcu->modifiers, type); + if (fcm) + set_active_fmodifier(&fcu->modifiers, fcm); + else { // TODO: stop when this happens? + BKE_report(op->reports, RPT_ERROR, "Modifier couldn't be added. See console for details."); + break; + } } + BLI_freelistN(&anim_data); /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); @@ -1779,13 +1806,14 @@ void GRAPH_OT_fmodifier_add (wmOperatorType *ot) /* api callbacks */ ot->invoke= graph_fmodifier_add_invoke; ot->exec= graph_fmodifier_add_exec; - ot->poll= graphop_active_fcurve_poll; + ot->poll= graphop_selected_fcurve_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* id-props */ RNA_def_enum(ot->srna, "type", fmodifier_type_items, 0, "Type", ""); + RNA_def_boolean(ot->srna, "only_active", 1, "Only Active", "Only add F-Modifier to active F-Curve."); } /* ************************************************************************** */ diff --git a/source/blender/editors/space_graph/graph_header.c b/source/blender/editors/space_graph/graph_header.c index dd304cd8cf3..98d58c92da4 100644 --- a/source/blender/editors/space_graph/graph_header.c +++ b/source/blender/editors/space_graph/graph_header.c @@ -298,29 +298,7 @@ void graph_header_buttons(const bContext *C, ARegion *ar) xco+= 120; /* filtering buttons */ - if (sipo->ads) { - //uiBlockBeginAlign(block); - uiDefIconButBitI(block, TOG, ADS_FILTER_ONLYSEL, B_REDR, ICON_RESTRICT_SELECT_OFF, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Only display selected Objects"); - //uiBlockEndAlign(block); - xco += 5; - - uiBlockBeginAlign(block); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSCE, B_REDR, ICON_SCENE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Scene Animation"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOWOR, B_REDR, ICON_WORLD_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display World Animation"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSHAPEKEYS, B_REDR, ICON_SHAPEKEY_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display ShapeKeys"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMAT, B_REDR, ICON_MATERIAL_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Materials"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOLAM, B_REDR, ICON_LAMP_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Lamps"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCAM, B_REDR, ICON_CAMERA_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Cameras"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCUR, B_REDR, ICON_CURVE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Curves"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMBA, B_REDR, ICON_META_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display MetaBalls"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOPART, B_REDR, ICON_PARTICLE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(sipo->ads->filterflag), 0, 0, 0, 0, "Display Particles"); - uiBlockEndAlign(block); - xco += 30; - } - else { - // XXX this case shouldn't happen at all... for now, just pad out same amount of space - xco += 10*XIC + 30; - } + xco= ANIM_headerUI_standard_buttons(C, sipo->ads, block, xco, yco); /* auto-snap selector */ if (sipo->flag & SIPO_DRAWTIME) { diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 2e8d0655d2d..83a565e485f 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -155,6 +155,7 @@ short fcurve_needs_draw_fmodifier_controls(struct FCurve *fcu, struct FModifier int graphop_visible_keyframes_poll(struct bContext *C); int graphop_editable_keyframes_poll(struct bContext *C); int graphop_active_fcurve_poll(struct bContext *C); +int graphop_selected_fcurve_poll(struct bContext *C); /* ***************************************** */ /* graph_ops.c */ diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index fc4c05915c9..b82055064f8 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -141,7 +141,7 @@ void graphedit_operatortypes(void) /* ************************** registration - keymaps **********************************/ -static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) +static void graphedit_keymap_keyframes (wmWindowManager *wm, wmKeyMap *keymap) { wmKeymapItem *kmi; @@ -221,7 +221,7 @@ static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); /* F-Modifiers */ - WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "GRAPH_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "only_active", 0); /* transform system */ @@ -232,10 +232,10 @@ static void graphedit_keymap_keyframes (wmWindowManager *wm, ListBase *keymap) void graphedit_keymap(wmWindowManager *wm) { - ListBase *keymap; + wmKeyMap *keymap; /* keymap for all regions */ - keymap= WM_keymap_listbase(wm, "GraphEdit Generic", SPACE_IPO, 0); + keymap= WM_keymap_find(wm, "GraphEdit Generic", SPACE_IPO, 0); WM_keymap_add_item(keymap, "GRAPH_OT_properties", NKEY, KM_PRESS, 0, 0); /* channels */ @@ -245,7 +245,7 @@ void graphedit_keymap(wmWindowManager *wm) */ /* keyframes */ - keymap= WM_keymap_listbase(wm, "GraphEdit Keys", SPACE_IPO, 0); + keymap= WM_keymap_find(wm, "GraphEdit Keys", SPACE_IPO, 0); graphedit_keymap_keyframes(wm, keymap); } diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 728c9310a47..7eec9f31d86 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -142,9 +142,13 @@ static void deselect_graph_keys (bAnimContext *ac, short test, short sel) /* Keyframes First */ ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, sel_cb, NULL); - /* deactivate the F-Curve, and deselect if deselecting keyframes */ + /* deactivate the F-Curve, and deselect if deselecting keyframes. + * otherwise select the F-Curve too since we've selected all the keyframes + */ if (sel == SELECT_SUBTRACT) fcu->flag &= ~FCURVE_SELECTED; + else + fcu->flag |= FCURVE_SELECTED; fcu->flag &= ~FCURVE_ACTIVE; } @@ -259,8 +263,9 @@ static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, sho /* select the curve too * NOTE: this should really only happen if the curve got touched... */ - if (selectmode == SELECT_ADD) + if (selectmode == SELECT_ADD) { fcu->flag |= FCURVE_SELECTED; + } } /* cleanup */ diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c index f00e7845549..25087441b6a 100644 --- a/source/blender/editors/space_graph/graph_utils.c +++ b/source/blender/editors/space_graph/graph_utils.c @@ -285,4 +285,33 @@ int graphop_active_fcurve_poll (bContext *C) return has_fcurve; } +/* has selected F-Curve that's editable */ +int graphop_selected_fcurve_poll (bContext *C) +{ + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + ScrArea *sa= CTX_wm_area(C); + int filter, items; + short found = 0; + + /* firstly, check if in Graph Editor */ + // TODO: also check for region? + if ((sa == NULL) || (sa->spacetype != SPACE_IPO)) + return 0; + + /* try to init Anim-Context stuff ourselves and check */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return 0; + + /* get the editable + selected F-Curves, and as long as we got some, we can return */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY); + items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + if (items == 0) + return 0; + + /* cleanup and return findings */ + BLI_freelistN(&anim_data); + return found; +} + /* ************************************************************** */ diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 8887d464f30..a7ea2294ed4 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -203,14 +203,14 @@ static SpaceLink *graph_duplicate(SpaceLink *sl) /* add handlers, stuff you only do once or on area/region changes */ static void graph_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "GraphEdit Keys", SPACE_IPO, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "GraphEdit Keys", SPACE_IPO, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - keymap= WM_keymap_listbase(wm, "GraphEdit Generic", SPACE_IPO, 0); + keymap= WM_keymap_find(wm, "GraphEdit Generic", SPACE_IPO, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } @@ -281,14 +281,14 @@ static void graph_main_area_draw(const bContext *C, ARegion *ar) static void graph_channel_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "Animation_Channels", 0, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "Animation_Channels", 0, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - keymap= WM_keymap_listbase(wm, "GraphEdit Generic", SPACE_IPO, 0); + keymap= WM_keymap_find(wm, "GraphEdit Generic", SPACE_IPO, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } @@ -352,11 +352,11 @@ static void graph_header_area_draw(const bContext *C, ARegion *ar) /* add handlers, stuff you only do once or on area/region changes */ static void graph_buttons_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; ED_region_panels_init(wm, ar); - keymap= WM_keymap_listbase(wm, "GraphEdit Generic", SPACE_IPO, 0); + keymap= WM_keymap_find(wm, "GraphEdit Generic", SPACE_IPO, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -374,6 +374,7 @@ static void graph_region_listener(ARegion *ar, wmNotifier *wmn) break; case NC_SCENE: switch(wmn->data) { + case ND_RENDER_OPTIONS: case ND_OB_ACTIVE: case ND_FRAME: case ND_MARKERS: diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 21fccdc65f8..bdf3e9416b9 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -100,8 +100,6 @@ #define B_FACESEL_PAINT_TEST 11 #define B_SIMA_RECORD 12 #define B_SIMA_PLAY 13 -#define B_SIMARANGE 14 -#define B_SIMACURVES 15 #define B_SIMANOTHING 16 #define B_SIMABRUSHCHANGE 17 @@ -116,10 +114,8 @@ #define B_SIMACLONEDELETE 26 /* XXX */ -static int okee() {return 0;} static int simaFaceDraw_Check() {return 0;} static int simaUVSel_Check() {return 0;} -static int is_uv_tface_editing_allowed_silent() {return 0;} /* XXX */ /* proto */ @@ -135,13 +131,6 @@ static void do_image_panel_events(bContext *C, void *arg, int event) switch(event) { case B_REDR: break; - case B_SIMACURVES: - curvemapping_do_ibuf(sima->cumap, ED_space_image_buffer(sima)); - break; - case B_SIMARANGE: - curvemapping_set_black_white(sima->cumap, NULL, NULL); - curvemapping_do_ibuf(sima->cumap, ED_space_image_buffer(sima)); - break; case B_TRANS_IMAGE: image_editvertex_buts(C, NULL); break; @@ -149,12 +138,11 @@ static void do_image_panel_events(bContext *C, void *arg, int event) image_editcursor_buts(C, &ar->v2d, NULL); break; } + /* all events now */ WM_event_add_notifier(C, NC_IMAGE, sima->image); } - - static void image_info(Image *ima, ImBuf *ibuf, char *str) { int ofs= 0; @@ -168,12 +156,12 @@ static void image_info(Image *ima, ImBuf *ibuf, char *str) } if(ima->source==IMA_SRC_MOVIE) { - ofs= sprintf(str, "Movie "); + ofs= sprintf(str, "Movie"); if(ima->anim) ofs+= sprintf(str+ofs, "%d frs", IMB_anim_get_duration(ima->anim)); } else - ofs= sprintf(str, "Image "); + ofs= sprintf(str, "Image"); ofs+= sprintf(str+ofs, ": size %d x %d,", ibuf->x, ibuf->y); @@ -246,10 +234,6 @@ static void image_editvertex_buts(const bContext *C, uiBlock *block) EditFace *efa; MTFace *tf; - if(obedit==NULL || obedit->type!=OB_MESH) return; - - if( is_uv_tface_editing_allowed_silent()==0 ) return; - image_transform_but_attr(sima, &imx, &imy, &step, &digits); em= BKE_mesh_get_editmesh((Mesh *)obedit->data); @@ -354,8 +338,6 @@ static void image_editcursor_buts(const bContext *C, View2D *v2d, uiBlock *block int imx= 256, imy= 256; int step, digits; - if( is_uv_tface_editing_allowed_silent()==0 ) return; - image_transform_but_attr(sima, &imx, &imy, &step, &digits); if(block) { // do the buttons @@ -388,59 +370,6 @@ static void image_editcursor_buts(const bContext *C, View2D *v2d, uiBlock *block #if 0 static void image_panel_view_properties(const bContext *C, Panel *pa) { - SpaceImage *sima= CTX_wm_space_image(C); - ARegion *ar= CTX_wm_region(C); - Object *obedit= CTX_data_edit_object(C); - uiBlock *block; - - block= uiLayoutFreeBlock(pa->layout); - uiBlockSetHandleFunc(block, do_image_panel_events, NULL); - - uiDefButBitI(block, TOG, SI_DRAW_TILE, B_REDR, "Repeat Image", 10,160,140,19, &sima->flag, 0, 0, 0, 0, "Repeat/Tile the image display"); - uiDefButBitI(block, TOG, SI_COORDFLOATS, B_REDR, "Normalized Coords", 165,160,145,19, &sima->flag, 0, 0, 0, 0, "Display coords from 0.0 to 1.0 rather then in pixels"); - - if (sima->image) { - uiDefBut(block, LABEL, B_NOP, "Image Display:", 10,140,140,19, 0, 0, 0, 0, 0, ""); - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_REDR, "AspX:", 10,120,140,19, &sima->image->aspx, 0.1, 5000.0, 100, 0, "X Display Aspect for this image, does not affect renderingm 0 disables."); - uiDefButF(block, NUM, B_REDR, "AspY:", 10,100,140,19, &sima->image->aspy, 0.1, 5000.0, 100, 0, "X Display Aspect for this image, does not affect rendering 0 disables."); - uiBlockEndAlign(block); - } - - if (obedit && obedit->type==OB_MESH) { - Mesh *me= obedit->data; - EditMesh *em= BKE_mesh_get_editmesh(me); - - if(EM_texFaceCheck(em)) { - uiDefBut(block, LABEL, B_NOP, "Draw Type:", 10, 80,120,19, 0, 0, 0, 0, 0, ""); - uiBlockBeginAlign(block); - uiDefButC(block, ROW, B_REDR, "Outline", 10,60,58,19, &sima->dt_uv, 0.0, SI_UVDT_OUTLINE, 0, 0, "Outline Wire UV drawtype"); - uiDefButC(block, ROW, B_REDR, "Dash", 68, 60,58,19, &sima->dt_uv, 0.0, SI_UVDT_DASH, 0, 0, "Dashed Wire UV drawtype"); - uiDefButC(block, ROW, B_REDR, "Black", 126, 60,58,19, &sima->dt_uv, 0.0, SI_UVDT_BLACK, 0, 0, "Black Wire UV drawtype"); - uiDefButC(block, ROW, B_REDR, "White", 184,60,58,19, &sima->dt_uv, 0.0, SI_UVDT_WHITE, 0, 0, "White Wire UV drawtype"); - - uiBlockEndAlign(block); - uiDefButBitI(block, TOG, SI_SMOOTH_UV, B_REDR, "Smooth", 250,60,60,19, &sima->flag, 0, 0, 0, 0, "Display smooth lines in the UV view"); - - - uiDefButBitI(block, TOG, ME_DRAWFACES, B_REDR, "Faces", 10,30,60,19, &me->drawflag, 0, 0, 0, 0, "Displays all faces as shades in the 3d view and UV editor"); - uiDefButBitI(block, TOG, ME_DRAWEDGES, B_REDR, "Edges", 70, 30,60,19, &me->drawflag, 0, 0, 0, 0, "Displays selected edges using hilights in the 3d view and UV editor"); - - uiDefButBitI(block, TOG, SI_DRAWSHADOW, B_REDR, "Final Shadow", 130, 30,110,19, &sima->flag, 0, 0, 0, 0, "Draw the final result from the objects modifiers"); - uiDefButBitI(block, TOG, SI_DRAW_OTHER, B_REDR, "Other Objs", 230, 30, 80, 19, &sima->flag, 0, 0, 0, 0, "Also draw all 3d view selected mesh objects that use this image"); - - uiDefButBitI(block, TOG, SI_DRAW_STRETCH, B_REDR, "UV Stretch", 10,0,100,19, &sima->flag, 0, 0, 0, 0, "Difference between UV's and the 3D coords (blue for low distortion, red is high)"); - if (sima->flag & SI_DRAW_STRETCH) { - uiBlockBeginAlign(block); - uiDefButC(block, ROW, B_REDR, "Area", 120,0,60,19, &sima->dt_uvstretch, 0.0, SI_UVDT_STRETCH_AREA, 0, 0, "Area distortion between UV's and 3D coords"); - uiDefButC(block, ROW, B_REDR, "Angle", 180,0,60,19, &sima->dt_uvstretch, 0.0, SI_UVDT_STRETCH_ANGLE, 0, 0, "Angle distortion between UV's and 3D coords"); - uiBlockEndAlign(block); - } - } - - BKE_mesh_end_editmesh(me, em); - } - image_editcursor_buts(C, &ar->v2d, block); } #endif @@ -524,8 +453,8 @@ void brush_buttons(const bContext *C, uiBlock *block, short fromsima, uiDefIconButBitS(block, TOG|BIT, BRUSH_ALPHA_PRESSURE, evt_nop, ICON_STYLUS_PRESSURE, 180,yco-20,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); uiDefButI(block, NUMSLI, evt_nop, "Size ", 0,yco-40,180,19, &brush->size, 1, 200, 0, 0, "The size of the brush"); uiDefIconButBitS(block, TOG|BIT, BRUSH_SIZE_PRESSURE, evt_nop, ICON_STYLUS_PRESSURE, 180,yco-40,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); - uiDefButF(block, NUMSLI, evt_nop, "Falloff ", 0,yco-60,180,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush"); - uiDefIconButBitS(block, TOG|BIT, BRUSH_RAD_PRESSURE, evt_nop, ICON_STYLUS_PRESSURE, 180,yco-60,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); +// uiDefButF(block, NUMSLI, evt_nop, "Falloff ", 0,yco-60,180,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush"); +// uiDefIconButBitS(block, TOG|BIT, BRUSH_RAD_PRESSURE, evt_nop, ICON_STYLUS_PRESSURE, 180,yco-60,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); uiDefButF(block, NUMSLI, evt_nop, "Spacing ",0,yco-80,180,19, &brush->spacing, 1.0, 100.0, 0, 0, "Repeating paint on %% of brush diameter"); uiDefIconButBitS(block, TOG|BIT, BRUSH_SPACING_PRESSURE, evt_nop, ICON_STYLUS_PRESSURE, 180,yco-80,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets"); uiBlockEndAlign(block); @@ -565,104 +494,33 @@ void brush_buttons(const bContext *C, uiBlock *block, short fromsima, #endif } -static int image_panel_paint_poll(const bContext *C, PanelType *pt) +static int image_panel_poll(const bContext *C, PanelType *pt) { SpaceImage *sima= CTX_wm_space_image(C); + ImBuf *ibuf= ED_space_image_buffer(sima); - return (sima->image && (sima->flag & SI_DRAWTOOL)); -} - -static void image_panel_paintcolor(const bContext *C, Panel *pa) -{ - SpaceImage *sima= CTX_wm_space_image(C); - ToolSettings *settings= CTX_data_tool_settings(C); - Brush *brush= paint_brush(&settings->imapaint.paint); - uiBlock *block; - static float hsv[3], old[3]; // used as temp mem for picker - static char hexcol[128]; - - if(!sima->image || (sima->flag & SI_DRAWTOOL)==0) - return; - - block= uiLayoutFreeBlock(pa->layout); - uiBlockSetHandleFunc(block, do_image_panel_events, NULL); - - if(brush) - uiBlockPickerButtons(block, brush->rgb, hsv, old, hexcol, 'f', B_REDR); -} - -static void image_panel_paint(const bContext *C, Panel *pa) -{ - SpaceImage *sima= CTX_wm_space_image(C); - uiBlock *block; - - if(!sima->image || (sima->flag & SI_DRAWTOOL)==0) - return; - - block= uiLayoutFreeBlock(pa->layout); - uiBlockSetHandleFunc(block, do_image_panel_events, NULL); - - brush_buttons(C, block, 1, B_SIMANOTHING, B_SIMABRUSHCHANGE, B_SIMABRUSHBROWSE, B_SIMABRUSHLOCAL, B_SIMABRUSHDELETE, B_KEEPDATA, B_SIMABTEXBROWSE, B_SIMABTEXDELETE); -} - -static void image_panel_curves_reset(bContext *C, void *cumap_v, void *ibuf_v) -{ - SpaceImage *sima= CTX_wm_space_image(C); - CurveMapping *cumap = cumap_v; - int a; - - for(a=0; a<CM_TOT; a++) - curvemap_reset(cumap->cm+a, &cumap->clipr); - - cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f; - cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f; - curvemapping_set_black_white(cumap, NULL, NULL); - - curvemapping_changed(cumap, 0); - curvemapping_do_ibuf(cumap, ibuf_v); - - WM_event_add_notifier(C, NC_IMAGE, sima->image); + return (ibuf != NULL); } - static void image_panel_curves(const bContext *C, Panel *pa) { + bScreen *sc= CTX_wm_screen(C); SpaceImage *sima= CTX_wm_space_image(C); ImBuf *ibuf; - uiBlock *block; - uiBut *bt; + PointerRNA simaptr; + int levels; - /* and we check for spare */ ibuf= ED_space_image_buffer(sima); - block= uiLayoutFreeBlock(pa->layout); - uiBlockSetHandleFunc(block, do_image_panel_events, NULL); - - if (ibuf) { - rctf rect; - + if(ibuf) { if(sima->cumap==NULL) sima->cumap= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); - - rect.xmin= 110; rect.xmax= 310; - rect.ymin= 10; rect.ymax= 200; - curvemap_buttons(block, sima->cumap, 'c', B_SIMACURVES, B_REDR, &rect); - - /* curvemap min/max only works for RGBA */ - if(ibuf->channels==4) { - bt=uiDefBut(block, BUT, B_SIMARANGE, "Reset", 10, 160, 90, 19, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves"); - uiButSetFunc(bt, image_panel_curves_reset, sima->cumap, ibuf); - - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_SIMARANGE, "Min R:", 10, 120, 90, 19, sima->cumap->black, -1000.0f, 1000.0f, 10, 2, "Black level"); - uiDefButF(block, NUM, B_SIMARANGE, "Min G:", 10, 100, 90, 19, sima->cumap->black+1, -1000.0f, 1000.0f, 10, 2, "Black level"); - uiDefButF(block, NUM, B_SIMARANGE, "Min B:", 10, 80, 90, 19, sima->cumap->black+2, -1000.0f, 1000.0f, 10, 2, "Black level"); - - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_SIMARANGE, "Max R:", 10, 50, 90, 19, sima->cumap->white, -1000.0f, 1000.0f, 10, 2, "White level"); - uiDefButF(block, NUM, B_SIMARANGE, "Max G:", 10, 30, 90, 19, sima->cumap->white+1, -1000.0f, 1000.0f, 10, 2, "White level"); - uiDefButF(block, NUM, B_SIMARANGE, "Max B:", 10, 10, 90, 19, sima->cumap->white+2, -1000.0f, 1000.0f, 10, 2, "White level"); - } + + /* curvemap black/white levels only works for RGBA */ + levels= (ibuf->channels==4); + + RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &simaptr); + uiTemplateCurveMapping(pa->layout, &simaptr, "curves", 'c', levels); } } @@ -799,81 +657,11 @@ static void image_panel_preview(ScrArea *sa, short cntrl) // IMAGE_HANDLER_PREVI uiBlockSetDrawExtraFunc(block, preview_cb); } - -static void image_panel_gpencil(short cntrl) // IMAGE_HANDLER_GREASEPENCIL -{ - uiBlock *block; - SpaceImage *sima; - - sima= curarea->spacedata.first; - - block= uiBeginBlock(C, ar, "image_panel_gpencil", UI_EMBOSS); - uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); - uiSetPanelHandler(IMAGE_HANDLER_GREASEPENCIL); // for close and esc - if (uiNewPanel(C, ar, block, "Grease Pencil", "SpaceImage", 100, 30, 318, 204)==0) return; - - /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */ - if (sima->flag & SI_DISPGP) { - if (sima->gpd == NULL) - gpencil_data_setactive(curarea, gpencil_data_addnew()); - } - - if (sima->flag & SI_DISPGP) { - bGPdata *gpd= sima->gpd; - short newheight; - - /* this is a variable height panel, newpanel doesnt force new size on existing panels */ - /* so first we make it default height */ - uiNewPanelHeight(block, 204); - - /* draw button for showing gpencil settings and drawings */ - uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor (draw using Shift-LMB)"); - - /* extend the panel if the contents won't fit */ - newheight= draw_gpencil_panel(block, gpd, curarea); - uiNewPanelHeight(block, newheight); - } - else { - uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor"); - uiDefBut(block, LABEL, 1, " ", 160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); - } -} #endif /* ********************* callbacks for standard image buttons *************** */ -/* called from fileselect or button */ -static void load_image_cb(bContext *C, char *str, void *ima_pp_v, void *iuser_v) -{ - Image **ima_pp= (Image **)ima_pp_v; - Image *ima= NULL; - - ima= BKE_add_image_file(str, 0); - if(ima) { - if(*ima_pp) { - (*ima_pp)->id.us--; - } - *ima_pp= ima; - - BKE_image_signal(ima, iuser_v, IMA_SIGNAL_RELOAD); - WM_event_add_notifier(C, NC_IMAGE, ima); - - /* button event gets lost when it goes via filewindow */ -// if(G.buts && G.buts->lockpoin) { -// Tex *tex= G.buts->lockpoin; -// if(GS(tex->id.name)==ID_TE) { -// BIF_preview_changed(ID_TE); -// allqueue(REDRAWBUTSSHADING, 0); -// allqueue(REDRAWVIEW3D, 0); -// allqueue(REDRAWOOPS, 0); -// } -// } - } - - ED_undo_push(C, "Load image"); -} - static char *layer_menu(RenderResult *rr, short *curlay) { RenderLayer *rl; @@ -937,92 +725,6 @@ static void set_frames_cb(bContext *C, void *ima_v, void *iuser_v) } } -static void image_src_change_cb(bContext *C, void *ima_v, void *iuser_v) -{ - BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_SRC_CHANGE); -} - -/* buttons have 2 arg callbacks, filewindow has 3 args... so thats why the wrapper below */ -static void image_browse_cb1(bContext *C, void *ima_pp_v, void *iuser_v) -{ - Image **ima_pp= (Image **)ima_pp_v; - ImageUser *iuser= iuser_v; - - if(ima_pp) { - Image *ima= *ima_pp; - - if(iuser->menunr== -2) { - // XXX activate_databrowse_args(&ima->id, ID_IM, 0, &iuser->menunr, image_browse_cb1, ima_pp, iuser); - } - else if (iuser->menunr>0) { - Image *newima= (Image*) BLI_findlink(&CTX_data_main(C)->image, iuser->menunr-1); - - if (newima && newima!=ima) { - *ima_pp= newima; - id_us_plus(&newima->id); - if(ima) ima->id.us--; - - BKE_image_signal(newima, iuser, IMA_SIGNAL_USER_NEW_IMAGE); - - ED_undo_push(C, "Browse image"); - } - } - } -} - -static void image_browse_cb(bContext *C, void *ima_pp_v, void *iuser_v) -{ - image_browse_cb1(C, ima_pp_v, iuser_v); -} - -static void image_reload_cb(bContext *C, void *ima_v, void *iuser_v) -{ - if(ima_v) { - BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_RELOAD); - } -} - -static void image_field_test(bContext *C, void *ima_v, void *iuser_v) -{ - Image *ima= ima_v; - - if(ima) { - ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v); - if(ibuf) { - short nr= 0; - if( !(ima->flag & IMA_FIELDS) && (ibuf->flags & IB_fields) ) nr= 1; - if( (ima->flag & IMA_FIELDS) && !(ibuf->flags & IB_fields) ) nr= 1; - if(nr) { - BKE_image_signal(ima, iuser_v, IMA_SIGNAL_FREE); - } - } - } -} - -static void image_unlink_cb(bContext *C, void *ima_pp_v, void *unused) -{ - Image **ima_pp= (Image **)ima_pp_v; - - if(ima_pp && *ima_pp) { - Image *ima= *ima_pp; - /* (for time being, texturefaces are no users, conflict in design...) */ - if(ima->id.us>1) - ima->id.us--; - *ima_pp= NULL; - } -} - -static void image_load_fs_cb(bContext *C, void *ima_pp_v, void *iuser_v) -{ - ScrArea *sa= CTX_wm_area(C); -// Image **ima_pp= (Image **)ima_pp_v; - - if(sa->spacetype==SPACE_IMAGE) - WM_operator_name_call(C, "IMAGE_OT_open", WM_OP_INVOKE_REGION_WIN, NULL); - else - printf("not supported yet\n"); -} - /* 5 layer button callbacks... */ static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) { @@ -1077,6 +779,7 @@ static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) } } +#if 0 static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v) { if(ima_v) { @@ -1106,282 +809,273 @@ static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v) } } } +#endif -static void image_load_cb(bContext *C, void *ima_pp_v, void *iuser_v) -{ - if(ima_pp_v) { - Image *ima= *((Image **)ima_pp_v); - ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v); - char str[FILE_MAX]; - - /* name in ima has been changed by button! */ - BLI_strncpy(str, ima->name, FILE_MAX); - if(ibuf) BLI_strncpy(ima->name, ibuf->name, FILE_MAX); - - load_image_cb(C, str, ima_pp_v, iuser_v); - } -} - +#if 0 static void image_freecache_cb(bContext *C, void *ima_v, void *unused) { Scene *scene= CTX_data_scene(C); BKE_image_free_anim_ibufs(ima_v, scene->r.cfra); WM_event_add_notifier(C, NC_IMAGE, ima_v); } +#endif -static void image_generated_change_cb(bContext *C, void *ima_v, void *iuser_v) -{ - BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_FREE); -} - +#if 0 static void image_user_change(bContext *C, void *iuser_v, void *unused) { Scene *scene= CTX_data_scene(C); BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0); } +#endif -static void uiblock_layer_pass_buttons(uiBlock *block, RenderResult *rr, ImageUser *iuser, int event, int x, int y, int w) +static void uiblock_layer_pass_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, int w) { + uiBlock *block= uiLayoutGetBlock(layout); uiBut *but; RenderLayer *rl= NULL; int wmenu1, wmenu2; char *strp; + uiLayoutRow(layout, 1); + /* layer menu is 1/3 larger than pass */ wmenu1= (3*w)/5; wmenu2= (2*w)/5; /* menu buts */ strp= layer_menu(rr, &iuser->layer); - but= uiDefButS(block, MENU, event, strp, x, y, wmenu1, 20, &iuser->layer, 0,0,0,0, "Select Layer"); + but= uiDefButS(block, MENU, 0, strp, 0, 0, wmenu1, 20, &iuser->layer, 0,0,0,0, "Select Layer"); uiButSetFunc(but, image_multi_cb, rr, iuser); MEM_freeN(strp); rl= BLI_findlink(&rr->layers, iuser->layer - (rr->rectf?1:0)); /* fake compo layer, return NULL is meant to be */ strp= pass_menu(rl, &iuser->pass); - but= uiDefButS(block, MENU, event, strp, x+wmenu1, y, wmenu2, 20, &iuser->pass, 0,0,0,0, "Select Pass"); + but= uiDefButS(block, MENU, 0, strp, 0, 0, wmenu2, 20, &iuser->pass, 0,0,0,0, "Select Pass"); uiButSetFunc(but, image_multi_cb, rr, iuser); MEM_freeN(strp); } -static void uiblock_layer_pass_arrow_buttons(uiBlock *block, RenderResult *rr, ImageUser *iuser, int imagechanged) +static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser) { + uiBlock *block= uiLayoutGetBlock(layout); + uiLayout *row; uiBut *but; + row= uiLayoutRow(layout, 1); + if(rr==NULL || iuser==NULL) return; if(rr->layers.first==NULL) { - uiDefBut(block, LABEL, 0, "No Layers in Render Result,", 10, 107, 300, 20, NULL, 1, 0, 0, 0, ""); + uiItemL(row, "No Layers in Render Result.", 0); return; } - - uiBlockBeginAlign(block); /* decrease, increase arrows */ - but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_LEFT, 10,107,17,20, NULL, 0, 0, 0, 0, "Previous Layer"); + but= uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT, 0,0,17,20, NULL, 0, 0, 0, 0, "Previous Layer"); uiButSetFunc(but, image_multi_declay_cb, rr, iuser); - but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_RIGHT, 27,107,18,20, NULL, 0, 0, 0, 0, "Next Layer"); + but= uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT, 0,0,18,20, NULL, 0, 0, 0, 0, "Next Layer"); uiButSetFunc(but, image_multi_inclay_cb, rr, iuser); - uiblock_layer_pass_buttons(block, rr, iuser, imagechanged, 45, 107, 230); + uiblock_layer_pass_buttons(row, rr, iuser, 230); /* decrease, increase arrows */ - but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_LEFT, 275,107,17,20, NULL, 0, 0, 0, 0, "Previous Pass"); + but= uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT, 0,0,17,20, NULL, 0, 0, 0, 0, "Previous Pass"); uiButSetFunc(but, image_multi_decpass_cb, rr, iuser); - but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_RIGHT, 292,107,18,20, NULL, 0, 0, 0, 0, "Next Pass"); + but= uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT, 0,0,18,20, NULL, 0, 0, 0, 0, "Next Pass"); uiButSetFunc(but, image_multi_incpass_cb, rr, iuser); uiBlockEndAlign(block); - } // XXX HACK! -static int packdummy=0; +// static int packdummy=0; -/* The general Image panel with the loadsa callbacks! */ -void ED_image_uiblock_panel(const bContext *C, uiBlock *block, Image **ima_pp, ImageUser *iuser, - short redraw, short imagechanged) +typedef struct RNAUpdateCb { + PointerRNA ptr; + PropertyRNA *prop; + ImageUser *iuser; +} RNAUpdateCb; + +static void rna_update_cb(bContext *C, void *arg_cb, void *arg_unused) +{ + RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb; + + /* ideally this would be done by RNA itself, but there we have + no image user available, so we just update this flag here */ + cb->iuser->ok= 1; + + /* we call update here on the pointer property, this way the + owner of the image pointer can still define it's own update + and notifier */ + RNA_property_update(C, &cb->ptr, cb->prop); +} + +void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *userptr, int compact) { + PropertyRNA *prop; + PointerRNA imaptr; + RNAUpdateCb *cb; + Image *ima; + ImageUser *iuser; + ImBuf *ibuf; Scene *scene= CTX_data_scene(C); - SpaceImage *sima= CTX_wm_space_image(C); - Image *ima= *ima_pp; + uiLayout *row, *split, *col; + uiBlock *block; uiBut *but; - char str[128], *strp; + char str[128]; + + if(!ptr->data) + return; - /* different stuff when we show viewer */ - if(ima && ima->source==IMA_SRC_VIEWER) { - ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser); - - image_info(ima, ibuf, str); - uiDefBut(block, LABEL, 0, ima->id.name+2, 10, 180, 300, 20, NULL, 1, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, str, 10, 160, 300, 20, NULL, 1, 0, 0, 0, ""); - - if(ima->type==IMA_TYPE_COMPOSITE) { - iuser= ntree_get_active_iuser(scene->nodetree); - if(iuser) { - uiBlockBeginAlign(block); - uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10,120,100,20, 0, 0, 0, 0, 0, ""); - uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play", 110,120,100,20, 0, 0, 0, 0, 0, ""); - but= uiDefBut(block, BUT, B_NOP, "Free Cache", 210,120,100,20, 0, 0, 0, 0, 0, ""); - uiButSetFunc(but, image_freecache_cb, ima, NULL); - - if(iuser->frames) - sprintf(str, "(%d) Frames:", iuser->framenr); - else strcpy(str, "Frames:"); - uiBlockBeginAlign(block); - uiDefButI(block, NUM, imagechanged, str, 10, 90,150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); - uiDefButI(block, NUM, imagechanged, "StartFr:", 160,90,150,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie"); - } - } - else if(ima->type==IMA_TYPE_R_RESULT) { - /* browse layer/passes */ - uiblock_layer_pass_arrow_buttons(block, RE_GetResult(RE_GetRender(scene->id.name)), iuser, imagechanged); - } + prop= RNA_struct_find_property(ptr, propname); + if(!prop) { + printf("uiTemplateImage: property not found: %s\n", propname); return; } - - /* the main ima source types */ + + block= uiLayoutGetBlock(layout); + + imaptr= RNA_property_pointer_get(ptr, prop); + ima= imaptr.data; + iuser= userptr->data; + + cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); + cb->ptr= *ptr; + cb->prop= prop; + cb->iuser= iuser; + + if(!compact) + uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL); + + // XXX missing: reload, pack + if(ima) { -// XXX uiSetButLock(ima->id.lib!=NULL, ERROR_LIBDATA_MESSAGE); - uiBlockBeginAlign(block); - uiBlockSetFunc(block, image_src_change_cb, ima, iuser); - uiDefButS(block, ROW, imagechanged, "Still", 0, 180, 105, 20, &ima->source, 0.0, IMA_SRC_FILE, 0, 0, "Single Image file"); - uiDefButS(block, ROW, imagechanged, "Movie", 105, 180, 105, 20, &ima->source, 0.0, IMA_SRC_MOVIE, 0, 0, "Movie file"); - uiDefButS(block, ROW, imagechanged, "Sequence", 210, 180, 105, 20, &ima->source, 0.0, IMA_SRC_SEQUENCE, 0, 0, "Multiple Image files, as a sequence"); - uiDefButS(block, ROW, imagechanged, "Generated", 315, 180, 105, 20, &ima->source, 0.0, IMA_SRC_GENERATED, 0, 0, "Generated Image"); - uiBlockSetFunc(block, NULL, NULL, NULL); - } - else - uiDefBut(block, LABEL, 0, " ", 0, 180, 440, 20, 0, 0, 0, 0, 0, ""); /* for align in panel */ + uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL); + + if(ima->source == IMA_SRC_VIEWER) { + ibuf= BKE_image_get_ibuf(ima, iuser); + image_info(ima, ibuf, str); + + uiItemL(layout, ima->id.name+2, 0); + uiItemL(layout, str, 0); + + if(ima->type==IMA_TYPE_COMPOSITE) { + // XXX not working yet +#if 0 + iuser= ntree_get_active_iuser(scene->nodetree); + if(iuser) { + uiBlockBeginAlign(block); + uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10,120,100,20, 0, 0, 0, 0, 0, ""); + uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play", 110,120,100,20, 0, 0, 0, 0, 0, ""); + but= uiDefBut(block, BUT, B_NOP, "Free Cache", 210,120,100,20, 0, 0, 0, 0, 0, ""); + uiButSetFunc(but, image_freecache_cb, ima, NULL); + + if(iuser->frames) + sprintf(str, "(%d) Frames:", iuser->framenr); + else strcpy(str, "Frames:"); + uiBlockBeginAlign(block); + uiDefButI(block, NUM, imagechanged, str, 10, 90,150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); + uiDefButI(block, NUM, imagechanged, "StartFr:", 160,90,150,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie"); + } +#endif + } + else if(ima->type==IMA_TYPE_R_RESULT) { + /* browse layer/passes */ + uiblock_layer_pass_arrow_buttons(layout, RE_GetResult(RE_GetRender(scene->id.name)), iuser); + } + } + else { + row= uiLayoutRow(layout, 0); + uiItemR(row, NULL, 0, &imaptr, "source", (compact)? 0: UI_ITEM_R_EXPAND); + + if(ima->source != IMA_SRC_GENERATED) { + row= uiLayoutRow(layout, 0); + uiItemR(row, "", 0, &imaptr, "filename", 0); + //uiItemO(row, "Reload", 0, "image.reload"); + } + + // XXX what was this for? +#if 0 + /* check for re-render, only buttons */ + if(imagechanged==B_IMAGECHANGED) { + if(iuser->flag & IMA_ANIM_REFRESHED) { + iuser->flag &= ~IMA_ANIM_REFRESHED; + WM_event_add_notifier(C, NC_IMAGE, ima); + } + } +#endif + + /* multilayer? */ + if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) { + uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser); + } + else if(ima->source != IMA_SRC_GENERATED) { + ibuf= BKE_image_get_ibuf(ima, iuser); + image_info(ima, ibuf, str); + uiItemL(layout, str, 0); + } + + if(ima->source != IMA_SRC_GENERATED) { + uiItemS(layout); + + split= uiLayoutSplit(layout, 0); + + col= uiLayoutColumn(split, 0); + uiItemR(col, NULL, 0, &imaptr, "fields", 0); + row= uiLayoutRow(col, 0); + uiItemR(row, NULL, 0, &imaptr, "field_order", UI_ITEM_R_EXPAND); + uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "fields")); + + col= uiLayoutColumn(split, 0); + uiItemR(col, NULL, 0, &imaptr, "antialias", 0); + uiItemR(col, NULL, 0, &imaptr, "premultiply", 0); + } + + if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { + uiItemS(layout); + + split= uiLayoutSplit(layout, 0); + + col= uiLayoutColumn(split, 0); - /* Browse */ - IMAnames_to_pupstring(&strp, NULL, NULL, &(CTX_data_main(C)->image), NULL, &iuser->menunr); - - uiBlockBeginAlign(block); - but= uiDefButS(block, MENU, imagechanged, strp, 0,155,40,20, &iuser->menunr, 0, 0, 0, 0, "Selects an existing Image or Movie"); - uiButSetFunc(but, image_browse_cb, ima_pp, iuser); - - MEM_freeN(strp); - - /* name + options, or only load */ - if(ima) { - int drawpack= (ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE && ima->ok); - - but= uiDefBut(block, TEX, B_IDNAME, "IM:", 40, 155, 220, 20, ima->id.name+2, 0.0, 21.0, 0, 0, "Current Image Datablock name."); - uiButSetFunc(but, test_idbutton_cb, ima->id.name, NULL); - but= uiDefBut(block, BUT, imagechanged, "Reload", 260, 155, 70, 20, NULL, 0, 0, 0, 0, "Reloads Image or Movie"); - uiButSetFunc(but, image_reload_cb, ima, iuser); - - but= uiDefIconBut(block, BUT, imagechanged, ICON_X, 330, 155, 40, 20, 0, 0, 0, 0, 0, "Unlink Image block"); - uiButSetFunc(but, image_unlink_cb, ima_pp, NULL); - sprintf(str, "%d", ima->id.us); - uiDefBut(block, BUT, B_NOP, str, 370, 155, 40, 20, 0, 0, 0, 0, 0, "Only displays number of users of Image block"); - uiBlockEndAlign(block); - - uiBlockBeginAlign(block); - but= uiDefIconBut(block, BUT, imagechanged, ICON_FILESEL, 0, 130, 40, 20, 0, 0, 0, 0, 0, "Open Fileselect to load new Image"); - uiButSetFunc(but, image_load_fs_cb, ima_pp, iuser); - but= uiDefBut(block, TEX, imagechanged, "", 40,130, 340+(drawpack?0:20),20, ima->name, 0.0, 239.0, 0, 0, "Image/Movie file name, change to load new"); - uiButSetFunc(but, image_load_cb, ima_pp, iuser); - uiBlockEndAlign(block); - - if(drawpack) { - if (ima->packedfile) packdummy = 1; - else packdummy = 0; - but= uiDefIconButBitI(block, TOG, 1, redraw, ICON_PACKAGE, 380, 130, 40, 20, &packdummy, 0, 0, 0, 0, "Toggles Packed status of this Image"); - uiButSetFunc(but, image_pack_cb, ima, iuser); - } - - } - else { - but= uiDefBut(block, BUT, imagechanged, "Load", 33, 155, 200,20, NULL, 0, 0, 0, 0, "Load new Image of Movie"); - uiButSetFunc(but, image_load_fs_cb, ima_pp, iuser); - } - uiBlockEndAlign(block); - - if(ima) { - ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser); - - /* check for re-render, only buttons */ - if(imagechanged==B_IMAGECHANGED) { - if(iuser->flag & IMA_ANIM_REFRESHED) { - iuser->flag &= ~IMA_ANIM_REFRESHED; - WM_event_add_notifier(C, NC_IMAGE, ima); - } - } - - /* multilayer? */ - if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) { - uiblock_layer_pass_arrow_buttons(block, ima->rr, iuser, imagechanged); - } - else { - image_info(ima, ibuf, str); - uiDefBut(block, LABEL, 0, str, 10, 112, 300, 20, NULL, 1, 0, 0, 0, ""); - } - - /* exception, let's do because we only use this panel 3 times in blender... but not real good code! */ - if( (paint_facesel_test(CTX_data_active_object(C))) && sima && &sima->iuser==iuser) - return; - /* left side default per-image options, right half the additional options */ - - /* fields */ - - but= uiDefButBitS(block, TOGBUT, IMA_FIELDS, imagechanged, "Fields", 0, 80, 200, 20, &ima->flag, 0, 0, 0, 0, "Click to enable use of fields in Image"); - uiButSetFunc(but, image_field_test, ima, iuser); - uiDefButBitS(block, TOGBUT, IMA_STD_FIELD, B_NOP, "Odd", 0, 55, 200, 20, &ima->flag, 0, 0, 0, 0, "Standard Field Toggle"); - - - uiBlockSetFunc(block, image_reload_cb, ima, iuser); - uiDefButBitS(block, TOGBUT, IMA_ANTIALI, B_NOP, "Anti", 0, 5, 200, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors"); - uiDefButBitS(block, TOGBUT, IMA_DO_PREMUL, imagechanged, "Premul", 0, -20, 200, 20, &ima->flag, 0, 0, 0, 0, "Toggles premultiplying alpha"); - - - if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { - sprintf(str, "(%d) Frames:", iuser->framenr); - - //uiBlockBeginAlign(block); - uiBlockSetFunc(block, image_user_change, iuser, NULL); - - if(ima->anim) { - uiBlockBeginAlign(block); - uiDefButI(block, NUM, imagechanged, str, 220, 80, 160, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); - but= uiDefBut(block, BUT, redraw, "<", 380, 80, 40, 20, 0, 0, 0, 0, 0, "Copies number of frames in movie file to Frames: button"); - uiButSetFunc(but, set_frames_cb, ima, iuser); - uiBlockEndAlign(block); - } - else - uiDefButI(block, NUM, imagechanged, str, 220, 80, 200, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use"); - - uiDefButI(block, NUM, imagechanged, "Start Frame:", 220, 55, 200, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie"); - uiDefButI(block, NUM, imagechanged, "Offset:", 220, 30, 200, 20, &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation"); - uiDefButS(block, NUM, imagechanged, "Fields:", 0, 30, 200, 20, &iuser->fie_ima, 1.0, 200.0, 0, 0, "The number of fields per rendered frame (2 fields is 1 image)"); - - uiDefButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NOP, "Auto Refresh", 220, 5, 200, 20, &iuser->flag, 0, 0, 0, 0, "Always refresh Image on frame changes"); - - uiDefButS(block, TOG, imagechanged, "Cyclic", 220, -20, 200, 20, &iuser->cycl, 0.0, 1.0, 0, 0, "Cycle the images in the movie"); - - uiBlockSetFunc(block, NULL, iuser, NULL); - } - else if(ima->source==IMA_SRC_GENERATED) { - - uiDefBut(block, LABEL, 0, "Size:", 220, 80, 200, 20, 0, 0, 0, 0, 0, ""); - - uiBlockBeginAlign(block); - uiBlockSetFunc(block, image_generated_change_cb, ima, iuser); - uiDefButS(block, NUM, imagechanged, "X:", 220, 55,200,20, &ima->gen_x, 1.0, 5000.0, 0, 0, "Image size x"); - uiDefButS(block, NUM, imagechanged, "Y:", 220, 35,200,20, &ima->gen_y, 1.0, 5000.0, 0, 0, "Image size y"); - uiBlockEndAlign(block); - - uiDefButS(block, TOGBUT, imagechanged, "UV Test grid", 220,10,200,20, &ima->gen_type, 0.0, 1.0, 0, 0, ""); - uiBlockSetFunc(block, NULL, NULL, NULL); - } - } - uiBlockEndAlign(block); -} + sprintf(str, "(%d) Frames", iuser->framenr); + row= uiLayoutRow(col, 1); + uiItemR(col, str, 0, userptr, "frames", 0); + if(ima->anim) { + block= uiLayoutGetBlock(row); + but= uiDefBut(block, BUT, 0, "<", 0, 0, UI_UNIT_X*2, UI_UNIT_Y, 0, 0, 0, 0, 0, "Set the number of frames from the movie or sequence."); + uiButSetFunc(but, set_frames_cb, ima, iuser); + } + + uiItemR(col, "Start", 0, userptr, "start_frame", 0); + uiItemR(col, NULL, 0, userptr, "offset", 0); + + col= uiLayoutColumn(split, 0); + uiItemR(col, "Fields", 0, userptr, "fields_per_frame", 0); + uiItemR(col, NULL, 0, userptr, "auto_refresh", 0); + uiItemR(col, NULL, 0, userptr, "cyclic", 0); + } + else if(ima->source==IMA_SRC_GENERATED) { + split= uiLayoutSplit(layout, 0); + + col= uiLayoutColumn(split, 1); + uiItemR(col, "X", 0, &imaptr, "generated_width", 0); + uiItemR(col, "Y", 0, &imaptr, "generated_height", 0); + + col= uiLayoutColumn(split, 0); + uiItemR(col, NULL, 0, &imaptr, "generated_type", UI_ITEM_R_EXPAND); + } + + } + + uiBlockSetNFunc(block, NULL, NULL, NULL); + } + + MEM_freeN(cb); +} void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser) { - uiBlock *block= uiLayoutFreeBlock(layout); Scene *scene= CTX_data_scene(C); RenderResult *rr; @@ -1389,55 +1083,46 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser if(ima && iuser) { rr= BKE_image_get_renderresult(scene, ima); - if(rr) { - uiBlockBeginAlign(block); - uiblock_layer_pass_buttons(block, rr, iuser, 0, 0, 0, 160); - uiBlockEndAlign(block); - } + if(rr) + uiblock_layer_pass_buttons(layout, rr, iuser, 160); } } -static void image_panel_properties(const bContext *C, Panel *pa) +static int image_panel_uv_poll(const bContext *C, PanelType *pt) { - SpaceImage *sima= CTX_wm_space_image(C); + Object *obedit= CTX_data_edit_object(C); + return ED_uvedit_test(obedit); +} + +static void image_panel_uv(const bContext *C, Panel *pa) +{ + ARegion *ar= CTX_wm_region(C); uiBlock *block; block= uiLayoutFreeBlock(pa->layout); uiBlockSetHandleFunc(block, do_image_panel_events, NULL); - /* note, it draws no bottom half in facemode, for vertex buttons */ - ED_image_uiblock_panel(C, block, &sima->image, &sima->iuser, B_REDR, B_REDR); image_editvertex_buts(C, block); + image_editcursor_buts(C, &ar->v2d, block); } void image_buttons_register(ARegionType *art) { PanelType *pt; - pt= MEM_callocN(sizeof(PanelType), "spacetype image panel properties"); - strcpy(pt->idname, "IMAGE_PT_properties"); - strcpy(pt->label, "Image Properties"); - pt->draw= image_panel_properties; - BLI_addtail(&art->paneltypes, pt); - - pt= MEM_callocN(sizeof(PanelType), "spacetype image panel paint"); - strcpy(pt->idname, "IMAGE_PT_paint"); - strcpy(pt->label, "Paint"); - pt->draw= image_panel_paint; - pt->poll= image_panel_paint_poll; - BLI_addtail(&art->paneltypes, pt); - - pt= MEM_callocN(sizeof(PanelType), "spacetype image panel paint color"); - strcpy(pt->idname, "IMAGE_PT_paint_color"); - strcpy(pt->label, "Paint Color"); - pt->draw= image_panel_paintcolor; - pt->poll= image_panel_paint_poll; + pt= MEM_callocN(sizeof(PanelType), "spacetype image panel uv"); + strcpy(pt->idname, "IMAGE_PT_uv"); + strcpy(pt->label, "UV"); + pt->draw= image_panel_uv; + pt->poll= image_panel_uv_poll; BLI_addtail(&art->paneltypes, pt); pt= MEM_callocN(sizeof(PanelType), "spacetype image panel curves"); strcpy(pt->idname, "IMAGE_PT_curves"); strcpy(pt->label, "Curves"); pt->draw= image_panel_curves; + pt->poll= image_panel_poll; + pt->flag |= PNL_DEFAULT_CLOSED; BLI_addtail(&art->paneltypes, pt); pt= MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil"); @@ -1452,13 +1137,9 @@ static int image_properties(bContext *C, wmOperator *op) ScrArea *sa= CTX_wm_area(C); ARegion *ar= image_has_buttons_region(sa); - if(ar) { - ar->flag ^= RGN_FLAG_HIDDEN; - ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */ - - ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); - ED_area_tag_redraw(sa); - } + if(ar) + ED_region_toggle_hidden(C, ar); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index cf9bac1ebee..fa736a29ce8 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -541,7 +541,7 @@ void draw_image_grease_pencil(bContext *C, short onlyv2d) } else { /* assume that UI_view2d_restore(C) has been called... */ - SpaceImage *sima= (SpaceImage *)CTX_wm_space_data(C); + //SpaceImage *sima= (SpaceImage *)CTX_wm_space_data(C); /* draw grease-pencil ('screen' strokes) */ //if (sima->flag & SI_DISPGP) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 806d0d7ce52..317a058d20e 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -161,7 +161,7 @@ static void view_pan_init(bContext *C, wmOperator *op, wmEvent *event) vpd->xof= sima->xof; vpd->yof= sima->yof; - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); } static void view_pan_exit(bContext *C, wmOperator *op, int cancel) @@ -224,7 +224,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event) view_pan_exec(C, op); break; case MIDDLEMOUSE: - if(event->val==0) { + if(event->val==KM_RELEASE) { view_pan_exit(C, op, 0); return OPERATOR_FINISHED; } @@ -280,7 +280,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, wmEvent *event) vpd->y= event->y; vpd->zoom= sima->zoom; - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); } static void view_zoom_exit(bContext *C, wmOperator *op, int cancel) @@ -339,7 +339,7 @@ static int view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event) ED_area_tag_redraw(CTX_wm_area(C)); break; case MIDDLEMOUSE: - if(event->val==0) { + if(event->val==KM_RELEASE) { view_zoom_exit(C, op, 0); return OPERATOR_FINISHED; } @@ -628,9 +628,14 @@ static int open_exec(bContext *C, wmOperator *op) if(!ima) return OPERATOR_CANCELLED; + + /* already set later */ + ima->id.us--; - BKE_image_signal(ima, &sima->iuser, IMA_SIGNAL_RELOAD); - ED_space_image_set(C, sima, scene, obedit, ima); + // XXX other users? + BKE_image_signal(ima, (sima)? &sima->iuser: NULL, IMA_SIGNAL_RELOAD); + if(sima) + ED_space_image_set(C, sima, scene, obedit, ima); return OPERATOR_FINISHED; } @@ -638,7 +643,7 @@ static int open_exec(bContext *C, wmOperator *op) static int open_invoke(bContext *C, wmOperator *op, wmEvent *event) { SpaceImage *sima= CTX_wm_space_image(C); - char *path= (sima->image)? sima->image->name: U.textudir; + char *path= (sima && sima->image)? sima->image->name: U.textudir; if(RNA_property_is_set(op->ptr, "path")) return open_exec(C, op); @@ -651,13 +656,12 @@ static int open_invoke(bContext *C, wmOperator *op, wmEvent *event) void IMAGE_OT_open(wmOperatorType *ot) { /* identifiers */ - ot->name= "Open Image"; + ot->name= "Open"; ot->idname= "IMAGE_OT_open"; /* api callbacks */ ot->exec= open_exec; ot->invoke= open_invoke; - ot->poll= ED_operator_image_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1051,8 +1055,12 @@ static int new_exec(bContext *C, wmOperator *op) color[3]= RNA_float_get(op->ptr, "alpha"); ima = BKE_add_image_size(width, height, name, floatbuf, uvtestgrid, color); - BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE); - ED_space_image_set(C, sima, scene, obedit, ima); + ima->id.us--; /* already set later */ + + if(sima) { // XXX other users? + BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE); + ED_space_image_set(C, sima, scene, obedit, ima); + } return OPERATOR_FINISHED; } @@ -1066,7 +1074,6 @@ void IMAGE_OT_new(wmOperatorType *ot) /* api callbacks */ ot->exec= new_exec; ot->invoke= WM_operator_props_popup; - ot->poll= ED_operator_image_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1446,7 +1453,7 @@ static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event) sample_apply(C, op, event); - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -1614,7 +1621,7 @@ static int record_composite_invoke(bContext *C, wmOperator *op, wmEvent *event) rcd= op->customdata; rcd->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.0f); - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); if(!record_composite_apply(C, op)) return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index c57bc5773b0..55b910cf6b4 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -204,7 +204,7 @@ void image_operatortypes(void) void image_keymap(struct wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Image Generic", SPACE_IMAGE, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Image Generic", SPACE_IMAGE, 0); WM_keymap_add_item(keymap, "IMAGE_OT_new", NKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "IMAGE_OT_open", OKEY, KM_PRESS, KM_ALT, 0); @@ -212,7 +212,7 @@ void image_keymap(struct wmWindowManager *wm) WM_keymap_add_item(keymap, "IMAGE_OT_save", SKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "IMAGE_OT_properties", NKEY, KM_PRESS, 0, 0); - keymap= WM_keymap_listbase(wm, "Image", SPACE_IMAGE, 0); + keymap= WM_keymap_find(wm, "Image", SPACE_IMAGE, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); @@ -232,9 +232,9 @@ void image_keymap(struct wmWindowManager *wm) RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD4, KM_PRESS, 0, 0)->ptr, "ratio", 0.25f); RNA_float_set(WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_ratio", PAD8, KM_PRESS, 0, 0)->ptr, "ratio", 0.125f); - WM_keymap_add_item(keymap, "PAINT_OT_image_paint", ACTIONMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "PAINT_OT_grab_clone", SELECTMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "PAINT_OT_sample_color", SELECTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "PAINT_OT_grab_clone", RIGHTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "PAINT_OT_sample_color", RIGHTMOUSE, KM_PRESS, 0, 0); RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE); RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH); @@ -374,8 +374,8 @@ static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar, Scene *sce ar->v2d.mask.ymax= winy; /* which part of the image space do we see? */ - x1= ar->winrct.xmin+(winx-sima->zoom*w)/2; - y1= ar->winrct.ymin+(winy-sima->zoom*h)/2; + x1= ar->winrct.xmin+(winx-sima->zoom*w)/2.0f; + y1= ar->winrct.ymin+(winy-sima->zoom*h)/2.0f; x1-= sima->zoom*sima->xof; y1-= sima->zoom*sima->yof; @@ -398,23 +398,22 @@ static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar, Scene *sce /* add handlers, stuff you only do once or on area/region changes */ static void image_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; // image space manages own v2d // UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); /* image paint polls for mode */ - keymap= WM_keymap_listbase(wm, "ImagePaint", SPACE_IMAGE, 0); + keymap= WM_keymap_find(wm, "Image Paint", SPACE_IMAGE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - /* XXX need context here? - keymap= WM_keymap_listbase(wm, "UVEdit", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap);*/ + keymap= WM_keymap_find(wm, "UVEdit", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); /* own keymaps */ - keymap= WM_keymap_listbase(wm, "Image Generic", SPACE_IMAGE, 0); + keymap= WM_keymap_find(wm, "Image Generic", SPACE_IMAGE, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap= WM_keymap_listbase(wm, "Image", SPACE_IMAGE, 0); + keymap= WM_keymap_find(wm, "Image", SPACE_IMAGE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -441,11 +440,13 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) /* and uvs in 0.0-1.0 space */ UI_view2d_view_ortho(C, v2d); - draw_uvedit_main(sima, ar, scene, obedit); - ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST); + draw_uvedit_main(sima, ar, scene, obedit); + + ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST); - /* Grease Pencil too (in addition to UV's) */ - draw_image_grease_pencil((bContext *)C, 1); + /* Grease Pencil too (in addition to UV's) */ + draw_image_grease_pencil((bContext *)C, 1); + UI_view2d_view_restore(C); /* draw Grease Pencil - screen space only */ @@ -457,29 +458,11 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) UI_view2d_scrollers_free(scrollers);*/ } -static void image_modal_keymaps(wmWindowManager *wm, ARegion *ar, int stype) -{ - ListBase *keymap; - - keymap= WM_keymap_listbase(wm, "UVEdit", 0, 0); - - if(stype==NS_EDITMODE_MESH) - WM_event_add_keymap_handler(&ar->handlers, keymap); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); -} - static void image_main_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch(wmn->category) { - case NC_SCENE: - switch(wmn->data) { - case ND_MODE: - image_modal_keymaps(wmn->wm, ar, wmn->subtype); - break; - } - break; + /* nothing yet */ } } @@ -488,11 +471,11 @@ static void image_main_area_listener(ARegion *ar, wmNotifier *wmn) /* add handlers, stuff you only do once or on area/region changes */ static void image_buttons_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; ED_region_panels_init(wm, ar); - keymap= WM_keymap_listbase(wm, "Image Generic", SPACE_IMAGE, 0); + keymap= WM_keymap_find(wm, "Image Generic", SPACE_IMAGE, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } @@ -505,7 +488,10 @@ static void image_buttons_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch(wmn->category) { - + case NC_BRUSH: + if(wmn->action==NA_EDITED) + ED_region_tag_redraw(ar); + break; } } @@ -639,7 +625,7 @@ ImBuf *ED_space_image_buffer(SpaceImage *sima) { ImBuf *ibuf; - if(sima->image) { + if(sima && sima->image) { #if 0 if(sima->image->type==IMA_TYPE_R_RESULT && BIF_show_render_spare()) return BIF_render_spare_imbuf(); diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c index 58c1eddb6c1..304c3601cdd 100644 --- a/source/blender/editors/space_logic/logic_buttons.c +++ b/source/blender/editors/space_logic/logic_buttons.c @@ -124,13 +124,9 @@ static int logic_properties(bContext *C, wmOperator *op) ScrArea *sa= CTX_wm_area(C); ARegion *ar= logic_has_buttons_region(sa); - if(ar) { - ar->flag ^= RGN_FLAG_HIDDEN; - ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */ - - ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); - ED_area_tag_redraw(sa); - } + if(ar) + ED_region_toggle_hidden(C, ar); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 3040d73bda9..dc8b111821d 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -39,6 +39,9 @@ #include "DNA_screen_types.h" #include "DNA_sensor_types.h" #include "DNA_sound_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_action_types.h" #include "DNA_windowmanager_types.h" #include "MEM_guardedalloc.h" @@ -608,6 +611,8 @@ static char *sensor_name(int type) return "Keyboard"; case SENS_PROPERTY: return "Property"; + case SENS_ARMATURE: + return "Armature"; case SENS_ACTUATOR: return "Actuator"; case SENS_DELAY: @@ -635,7 +640,7 @@ static char *sensor_pup(void) /* the number needs to match defines in game.h */ return "Sensors %t|Always %x0|Delay %x13|Keyboard %x3|Mouse %x5|" "Touch %x1|Collision %x6|Near %x2|Radar %x7|" - "Property %x4|Random %x8|Ray %x9|Message %x10|Joystick %x11|Actuator %x12"; + "Property %x4|Random %x8|Ray %x9|Message %x10|Joystick %x11|Actuator %x12|Armature %x14"; } static char *controller_name(int type) @@ -709,6 +714,8 @@ static char *actuator_name(int type) return "Parent"; case ACT_STATE: return "State"; + case ACT_ARMATURE: + return "Armature"; } return "unknown"; } @@ -721,7 +728,7 @@ static char *actuator_pup(Object *owner) switch (owner->type) { case OB_ARMATURE: - return "Actuators %t|Action %x15|Motion %x0|Constraint %x9|Ipo %x1" + return "Actuators %t|Action %x15|Armature %x23|Motion %x0|Constraint %x9|Ipo %x1" "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10" "|Scene %x11|Random %x13|Message %x14|Game %x17" "|Visibility %x18|2D Filter %x19|Parent %x20|State %x22"; @@ -936,6 +943,7 @@ static int get_col_sensor(int type) case SENS_NEAR: return TH_PANEL; case SENS_KEYBOARD: return TH_PANEL; case SENS_PROPERTY: return TH_PANEL; + case SENS_ARMATURE: return TH_PANEL; case SENS_ACTUATOR: return TH_PANEL; case SENS_MOUSE: return TH_PANEL; case SENS_RADAR: return TH_PANEL; @@ -965,6 +973,120 @@ static void verify_logicbutton_func(bContext *C, void *data1, void *data2) } } +static void test_scriptpoin_but(struct bContext *C, char *name, ID **idpp) +{ + ID *id; + + id= CTX_data_main(C)->text.first; + while(id) { + if( strcmp(name, id->name+2)==0 ) { + *idpp= id; + return; + } + id= id->next; + } + *idpp= NULL; +} + +static void test_actionpoin_but(struct bContext *C, char *name, ID **idpp) +{ + ID *id; + + id= CTX_data_main(C)->action.first; + while(id) { + if( strcmp(name, id->name+2)==0 ) { + id_us_plus(id); + *idpp= id; + return; + } + id= id->next; + } + *idpp= NULL; +} + + +static void test_obpoin_but(struct bContext *C, char *name, ID **idpp) +{ + ID *id; + + id= CTX_data_main(C)->object.first; + while(id) { + if( strcmp(name, id->name+2)==0 ) { + *idpp= id; + id_lib_extern(id); /* checks lib data, sets correct flag for saving then */ + return; + } + id= id->next; + } + *idpp= NULL; +} + +static void test_meshpoin_but(struct bContext *C, char *name, ID **idpp) +{ + ID *id; + + if( *idpp ) (*idpp)->us--; + + id= CTX_data_main(C)->mesh.first; + while(id) { + if( strcmp(name, id->name+2)==0 ) { + *idpp= id; + id_us_plus(id); + return; + } + id= id->next; + } + *idpp= NULL; +} + +static void test_matpoin_but(struct bContext *C, char *name, ID **idpp) +{ + ID *id; + + if( *idpp ) (*idpp)->us--; + + id= CTX_data_main(C)->mat.first; + while(id) { + if( strcmp(name, id->name+2)==0 ) { + *idpp= id; + id_us_plus(id); + return; + } + id= id->next; + } + *idpp= NULL; +} + +static void test_scenepoin_but(struct bContext *C, char *name, ID **idpp) +{ + ID *id; + + if( *idpp ) (*idpp)->us--; + + id= CTX_data_main(C)->scene.first; + while(id) { + if( strcmp(name, id->name+2)==0 ) { + *idpp= id; + id_us_plus(id); + return; + } + id= id->next; + } + *idpp= NULL; +} + + +static void test_keyboard_event(struct bContext *C, void *arg_ks, void *arg_unused) +{ + bKeyboardSensor *ks= (bKeyboardSensor*)arg_ks; + + if(!ISKEYBOARD(ks->key)) + ks->key= 0; + if(!ISKEYBOARD(ks->qual)) + ks->qual= 0; + if(!ISKEYBOARD(ks->qual2)) + ks->qual2= 0; +} /** * Draws a toggle for pulse mode, a frequency field and a toggle to invert @@ -1015,12 +1137,51 @@ static void draw_default_sensor_header(bSensor *sens, "Invert the level (output) of this sensor"); } -static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname) +static void check_armature_bone_constraint(Object *ob, char *posechannel, char *constraint) +{ + /* check that bone exist in the active object */ + if (ob->type == OB_ARMATURE && ob->pose) { + bPoseChannel *pchan; + bPose *pose = ob->pose; + for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { + if (!strcmp(pchan->name, posechannel)) { + /* found it, now look for constraint channel */ + bConstraint *con; + for (con=pchan->constraints.first; con; con=con->next) { + if (!strcmp(con->name, constraint)) { + /* found it, all ok */ + return; + } + } + /* didn't find constraint, make empty */ + constraint[0] = 0; + return; + } + } + } + /* didn't find any */ + posechannel[0] = 0; + constraint[0] = 0; +} + +static void check_armature_sensor(bContext *C, void *arg1_but, void *arg2_sens) +{ + bArmatureSensor *sens = arg2_sens; + uiBut *but = arg1_but; + Object *ob= CTX_data_active_object(C); + + /* check that bone exist in the active object */ + but->retval = B_REDR; + check_armature_bone_constraint(ob, sens->posechannel, sens->constraint); +} + +static short draw_sensorbuttons(Object *ob, bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname) { bNearSensor *ns = NULL; bTouchSensor *ts = NULL; bKeyboardSensor *ks = NULL; bPropertySensor *ps = NULL; + bArmatureSensor *arm = NULL; bMouseSensor *ms = NULL; bCollisionSensor *cs = NULL; bRadarSensor *rs = NULL; @@ -1030,6 +1191,7 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short bJoystickSensor *joy = NULL; bActuatorSensor *as = NULL; bDelaySensor *ds = NULL; + uiBut *but; short ysize; char *str; @@ -1178,12 +1340,15 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short if ((ks->type&1)==0) { /* is All Keys option off? */ /* line 2: hotkey and allkeys toggle */ - uiDefKeyevtButS(block, 0, "", xco+40, yco-44, (width)/2, 19, &ks->key, "Key code"); + but= uiDefKeyevtButS(block, 0, "", xco+40, yco-44, (width)/2, 19, &ks->key, "Key code"); + uiButSetFunc(but, test_keyboard_event, ks, NULL); /* line 3: two key modifyers (qual1, qual2) */ uiDefBut(block, LABEL, 0, "Hold", xco, yco-68, 40, 19, NULL, 0, 0, 0, 0, ""); - uiDefKeyevtButS(block, 0, "", xco+40, yco-68, (width-50)/2, 19, &ks->qual, "Modifier key code"); - uiDefKeyevtButS(block, 0, "", xco+40+(width-50)/2, yco-68, (width-50)/2, 19, &ks->qual2, "Second Modifier key code"); + but= uiDefKeyevtButS(block, 0, "", xco+40, yco-68, (width-50)/2, 19, &ks->qual, "Modifier key code"); + uiButSetFunc(but, test_keyboard_event, ks, NULL); + but= uiDefKeyevtButS(block, 0, "", xco+40+(width-50)/2, yco-68, (width-50)/2, 19, &ks->qual2, "Second Modifier key code"); + uiButSetFunc(but, test_keyboard_event, ks, NULL); } /* line 4: toggle property for string logging mode */ @@ -1242,6 +1407,45 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco-= ysize; break; } + case SENS_ARMATURE: + { + ysize= 70; + + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, + (float)xco+width, (float)yco, 1); + + draw_default_sensor_header(sens, block, xco, yco, width); + arm= sens->data; + + if (ob->type == OB_ARMATURE) { + uiBlockBeginAlign(block); + but = uiDefBut(block, TEX, 1, "Bone: ", + (xco+10), (yco-44), (width-20)/2, 19, + arm->posechannel, 0, 31, 0, 0, + "Bone on which you want to check a constraint"); + uiButSetFunc(but, check_armature_sensor, but, arm); + but = uiDefBut(block, TEX, 1, "Cons: ", + (xco+10)+(width-20)/2, (yco-44), (width-20)/2, 19, + arm->constraint, 0, 31, 0, 0, + "Name of the constraint you want to control"); + uiButSetFunc(but, check_armature_sensor, but, arm); + uiBlockEndAlign(block); + + str= "Type %t|State changed %x0|Lin error below %x1|Lin error above %x2|Rot error below %x3|Rot error above %x4"; + + uiDefButI(block, MENU, B_REDR, str, xco+10,yco-66,0.4*(width-20), 19, + &arm->type, 0, 31, 0, 0, "Type"); + + if (arm->type != SENS_ARM_STATE_CHANGED) + { + uiDefButF(block, NUM, 1, "Value: ", xco+10+0.4*(width-20),yco-66,0.6*(width-20), 19, + &arm->value, -10000.0, 10000.0, 100, 0, "Test the error against this value"); + } + } + yco-= ysize; + break; + } case SENS_ACTUATOR: { ysize= 48; @@ -1534,7 +1738,7 @@ static short draw_controllerbuttons(bController *cont, uiBlock *block, short xco uiBlockBeginAlign(block); uiDefButI(block, MENU, B_REDR, "Execution Method%t|Script%x0|Module%x1", xco+4,yco-23, 66, 19, &pc->mode, 0, 0, 0, 0, "Python script type (textblock or module - faster)"); if(pc->mode==0) - uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "", xco+70,yco-23,width-74, 19, &pc->text, "Blender textblock to run as a script"); + uiDefIDPoinBut(block, test_scriptpoin_but, ID_TXT, 1, "", xco+70,yco-23,width-74, 19, &pc->text, "Blender textblock to run as a script"); else { uiDefBut(block, TEX, 1, "", xco+70,yco-23,(width-70)-25, 19, pc->module, 0, 63, 0, 0, "Module name and function to run e.g. \"someModule.main\". Internal texts and external python files can be used"); uiDefButBitI(block, TOG, CONT_PY_DEBUG, B_REDR, "D", (xco+width)-25, yco-23, 19, 19, &pc->flag, 0, 0, 0, 0, "Continuously reload the module from disk for editing external modules without restarting"); @@ -1576,6 +1780,7 @@ static int get_col_actuator(int type) case ACT_VISIBILITY: return TH_PANEL; case ACT_CONSTRAINT: return TH_PANEL; case ACT_STATE: return TH_PANEL; + case ACT_ARMATURE: return TH_PANEL; default: return TH_PANEL; } } @@ -1656,6 +1861,18 @@ static void check_state_mask(bContext *C, void *arg1_but, void *arg2_mask) but->retval = B_REDR; } +static void check_armature_actuator(bContext *C, void *arg1_but, void *arg2_act) +{ + bArmatureActuator *act = arg2_act; + uiBut *but = arg1_but; + Object *ob= CTX_data_active_object(C); + + /* check that bone exist in the active object */ + but->retval = B_REDR; + check_armature_bone_constraint(ob, act->posechannel, act->constraint); +} + + static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, short xco, short yco, short width) { bSoundActuator *sa = NULL; @@ -1675,6 +1892,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh bTwoDFilterActuator *tdfa = NULL; bParentActuator *parAct = NULL; bStateActuator *staAct = NULL; + bArmatureActuator *armAct = NULL; float *fp; short ysize = 0, wval; @@ -2702,6 +2920,48 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh yco-= ysize; break; + case ACT_ARMATURE: + armAct = act->data; + + if (ob->type == OB_ARMATURE) { + str= "Constraint %t|Run armature %x0|Enable %x1|Disable %x2|Set target %x3|Set weight %x4"; + uiDefButI(block, MENU, B_REDR, str, xco+5, yco-24, (width-10)*0.35, 19, &armAct->type, 0.0, 0.0, 0, 0, ""); + + switch (armAct->type) { + case ACT_ARM_RUN: + ysize = 28; + break; + default: + uiBlockBeginAlign(block); + but = uiDefBut(block, TEX, 1, "Bone: ", + (xco+5), (yco-44), (width-10)/2, 19, + armAct->posechannel, 0, 31, 0, 0, + "Bone on which the constraint is defined"); + uiButSetFunc(but, check_armature_actuator, but, armAct); + but = uiDefBut(block, TEX, 1, "Cons: ", + (xco+5)+(width-10)/2, (yco-44), (width-10)/2, 19, + armAct->constraint, 0, 31, 0, 0, + "Name of the constraint you want to controle"); + uiButSetFunc(but, check_armature_actuator, but, armAct); + uiBlockEndAlign(block); + ysize = 48; + switch (armAct->type) { + case ACT_ARM_SETTARGET: + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "Target: ", xco+5, yco-64, (width-10), 19, &(armAct->target), "Set this object as the target of the constraint"); + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "Secondary Target: ", xco+5, yco-84, (width-10), 19, &(armAct->subtarget), "Set this object as the secondary target of the constraint (only IK polar target at the moment)"); + ysize += 40; + break; + case ACT_ARM_SETWEIGHT: + uiDefButF(block, NUM, B_REDR, "Weight:", xco+5+(width-10)*0.35,yco-24,(width-10)*0.65,19,&armAct->weight,0.0,1.0,0.0,0.0,"Set weight of this constraint"); + break; + } + } + } + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + yco-= ysize; + break; + default: ysize= 4; @@ -3216,7 +3476,7 @@ void logic_buttons(bContext *C, ARegion *ar) uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0); sens->otype= sens->type; - yco= draw_sensorbuttons(sens, block, xco, yco, width,ob->id.name); + yco= draw_sensorbuttons(ob, sens, block, xco, yco, width,ob->id.name); if(yco-6 < ycoo) ycoo= (yco+ycoo-20)/2; } else { diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c index 3c46522bba2..7043d625ab0 100644 --- a/source/blender/editors/space_logic/space_logic.c +++ b/source/blender/editors/space_logic/space_logic.c @@ -188,7 +188,7 @@ void logic_operatortypes(void) void logic_keymap(struct wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Logic Generic", SPACE_LOGIC, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Logic Generic", SPACE_LOGIC, 0); WM_keymap_add_item(keymap, "LOGIC_OT_properties", NKEY, KM_PRESS, 0, 0); } @@ -234,12 +234,12 @@ static int logic_context(const bContext *C, const char *member, bContextDataResu /* add handlers, stuff you only do once or on area/region changes */ static void logic_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymaps */ - keymap= WM_keymap_listbase(wm, "Logic Generic", SPACE_LOGIC, 0); + keymap= WM_keymap_find(wm, "Logic Generic", SPACE_LOGIC, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } @@ -276,11 +276,11 @@ static void logic_main_area_draw(const bContext *C, ARegion *ar) /* add handlers, stuff you only do once or on area/region changes */ static void logic_buttons_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; ED_region_panels_init(wm, ar); - keymap= WM_keymap_listbase(wm, "Logic Generic", SPACE_LOGIC, 0); + keymap= WM_keymap_find(wm, "Logic Generic", SPACE_LOGIC, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 8532d78aa06..b193b89d65a 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -114,34 +114,69 @@ static int nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA if (ANIM_animdata_get_context(C, &ac) == 0) return 0; - /* extract list of active channel(s), of which we should only take the first one (expecting it to be an NLA track) */ - filter= (ANIMFILTER_VISIBLE|ANIMFILTER_ACTIVE); + /* extract list of active channel(s), of which we should only take the first one + * - we need the channels flag to get the active AnimData block when there are no NLA Tracks + */ + filter= (ANIMFILTER_VISIBLE|ANIMFILTER_ACTIVE|ANIMFILTER_CHANNELS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); for (ale= anim_data.first; ale; ale= ale->next) { - // TODO: need some way to select active animdata too... - if (ale->type == ANIMTYPE_NLATRACK) { - NlaTrack *nlt= (NlaTrack *)ale->data; - AnimData *adt= ale->adt; - - /* found it, now set the pointers */ - if (adt_ptr) { - /* AnimData pointer */ - RNA_pointer_create(ale->id, &RNA_AnimData, adt, adt_ptr); - } - if (nlt_ptr) { - /* NLA-Track pointer */ - RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr); - } - if (strip_ptr) { - /* NLA-Strip pointer */ - NlaStrip *strip= BKE_nlastrip_find_active(nlt); - RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr); + switch (ale->type) { + case ANIMTYPE_NLATRACK: /* NLA Track - The primary data type which should get caught */ + { + NlaTrack *nlt= (NlaTrack *)ale->data; + AnimData *adt= ale->adt; + + /* found it, now set the pointers */ + if (adt_ptr) { + /* AnimData pointer */ + RNA_pointer_create(ale->id, &RNA_AnimData, adt, adt_ptr); + } + if (nlt_ptr) { + /* NLA-Track pointer */ + RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr); + } + if (strip_ptr) { + /* NLA-Strip pointer */ + NlaStrip *strip= BKE_nlastrip_find_active(nlt); + RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr); + } + + found= 1; } - - found= 1; - break; + break; + + case ANIMTYPE_SCENE: /* Top-Level Widgets doubling up as datablocks */ + case ANIMTYPE_OBJECT: + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + { + /* for these channels, we only do AnimData */ + if (ale->id && ale->adt) { + if (adt_ptr) { + /* AnimData pointer */ + RNA_pointer_create(ale->id, &RNA_AnimData, ale->adt, adt_ptr); + + /* set found status to -1, since setting to 1 would break the loop + * and potentially skip an active NLA-Track in some cases... + */ + found= -1; + } + } + } + break; } + + if (found > 0) + break; } /* free temp data */ @@ -211,7 +246,7 @@ static void nla_panel_animdata (const bContext *C, Panel *pa) /* Active Action Properties ------------------------------------- */ /* action */ row= uiLayoutRow(layout, 1); - uiTemplateID(row, (bContext *)C, &adt_ptr, "action", NULL /*"ACT_OT_new"*/, NULL, NULL /*"ACT_OT_unlink"*/); // XXX: need to make these operators + uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACT_OT_new", NULL, NULL /*"ACT_OT_unlink"*/); // XXX: need to make these operators /* extrapolation */ row= uiLayoutRow(layout, 1); @@ -458,13 +493,9 @@ static int nla_properties(bContext *C, wmOperator *op) ScrArea *sa= CTX_wm_area(C); ARegion *ar= nla_has_buttons_region(sa); - if(ar) { - ar->flag ^= RGN_FLAG_HIDDEN; - ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */ - - ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); - ED_area_tag_redraw(sa); - } + if(ar) + ED_region_toggle_hidden(C, ar); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index ccf23266427..07dc3f0ad89 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -116,18 +116,22 @@ static int mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sho } /* action to take depends on what channel we've got */ + // WARNING: must keep this in sync with the equivalent function in anim_channels_edit.c switch (ale->type) { case ANIMTYPE_SCENE: { Scene *sce= (Scene *)ale->data; + AnimData *adt= sce->adt; /* set selection status */ if (selectmode == SELECT_INVERT) { /* swap select */ sce->flag ^= SCE_DS_SELECTED; + if (adt) adt->flag ^= ADT_UI_SELECTED; } else { sce->flag |= SCE_DS_SELECTED; + if (adt) adt->flag |= ADT_UI_SELECTED; } notifierFlags |= ND_ANIMCHAN_SELECT; @@ -139,6 +143,7 @@ static int mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sho Scene *sce= (Scene *)ads->source; Base *base= (Base *)ale->data; Object *ob= base->object; + AnimData *adt= ob->adt; if (nlaedit_is_tweakmode_on(ac) == 0) { /* set selection status */ @@ -146,23 +151,30 @@ static int mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sho /* swap select */ base->flag ^= SELECT; ob->flag= base->flag; + + if (adt) adt->flag ^= ADT_UI_SELECTED; } else { Base *b; - /* deleselect all */ + /* deselect all */ + // TODO: should this deselect all other types of channels too? for (b= sce->base.first; b; b= b->next) { b->flag &= ~SELECT; b->object->flag= b->flag; + if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED|ADT_UI_ACTIVE); } /* select object now */ base->flag |= SELECT; ob->flag |= SELECT; + if (adt) adt->flag |= ADT_UI_SELECTED; } /* xxx should be ED_base_object_activate(), but we need context pointer for that... */ //set_active_base(base); + if ((adt) && (adt->flag & ADT_UI_SELECTED)) + adt->flag |= ADT_UI_ACTIVE; /* notifiers - channel was selected */ notifierFlags |= ND_ANIMCHAN_SELECT; @@ -170,6 +182,39 @@ static int mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sho } break; + case ANIMTYPE_FILLACTD: /* Action Expander */ + case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ + case ANIMTYPE_DSLAM: + case ANIMTYPE_DSCAM: + case ANIMTYPE_DSCUR: + case ANIMTYPE_DSSKEY: + case ANIMTYPE_DSWOR: + case ANIMTYPE_DSPART: + case ANIMTYPE_DSMBALL: + case ANIMTYPE_DSARM: + { + /* sanity checking... */ + if (ale->adt) { + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this AnimData block only */ + ale->adt->flag ^= ADT_UI_SELECTED; + } + else { + /* select AnimData block by itself */ + ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + ale->adt->flag |= ADT_UI_SELECTED; + } + + /* set active? */ + if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) + ale->adt->flag |= ADT_UI_ACTIVE; + } + + notifierFlags |= ND_ANIMCHAN_SELECT; + } + break; + case ANIMTYPE_NLATRACK: { NlaTrack *nlt= (NlaTrack *)ale->data; diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c index 0d3bf2cb6b1..4eb9fac5cb8 100644 --- a/source/blender/editors/space_nla/nla_header.c +++ b/source/blender/editors/space_nla/nla_header.c @@ -246,31 +246,7 @@ void nla_header_buttons(const bContext *C, ARegion *ar) uiBlockSetEmboss(block, UI_EMBOSS); /* filtering buttons */ - if (snla->ads) { - uiBlockBeginAlign(block); - uiDefIconButBitI(block, TOG, ADS_FILTER_ONLYSEL, B_REDR, ICON_RESTRICT_SELECT_OFF, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Only display selected Objects"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NLA_NOACT, B_REDR, ICON_ACTION, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Include AnimData blocks with no NLA Data"); - uiBlockEndAlign(block); - xco += 5; - - uiBlockBeginAlign(block); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSCE, B_REDR, ICON_SCENE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Scene Animation"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOWOR, B_REDR, ICON_WORLD_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display World Animation"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOSHAPEKEYS, B_REDR, ICON_SHAPEKEY_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display ShapeKeys"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMAT, B_REDR, ICON_MATERIAL_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Materials"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOLAM, B_REDR, ICON_LAMP_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Lamps"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCAM, B_REDR, ICON_CAMERA_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Cameras"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOCUR, B_REDR, ICON_CURVE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Curves"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOMBA, B_REDR, ICON_META_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display MetaBalls"); - uiDefIconButBitI(block, TOGN, ADS_FILTER_NOPART, B_REDR, ICON_PARTICLE_DATA, (short)(xco+=XIC),yco,XIC,YIC, &(snla->ads->filterflag), 0, 0, 0, 0, "Display Particles"); - uiBlockEndAlign(block); - xco += 15; - } - else { - // XXX this case shouldn't happen at all... for now, just pad out same amount of space - xco += 10*XIC + 15; - } - xco += (XIC + 8); + xco= ANIM_headerUI_standard_buttons(C, snla->ads, block, xco, yco); /* auto-snap selector */ if (snla->flag & SNLA_DRAWTIME) { diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index ad5f5174690..5ea2e99ad6a 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -167,7 +167,7 @@ void nla_operatortypes(void) /* ************************** registration - keymaps **********************************/ -static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap) +static void nla_keymap_channels (wmWindowManager *wm, wmKeyMap *keymap) { /* NLA-specific (different to standard channels keymap) -------------------------- */ /* selection */ @@ -210,7 +210,7 @@ static void nla_keymap_channels (wmWindowManager *wm, ListBase *keymap) RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_collapse", PADMINUS, KM_PRESS, KM_CTRL, 0)->ptr, "all", 1); } -static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) +static void nla_keymap_main (wmWindowManager *wm, wmKeyMap *keymap) { wmKeymapItem *kmi; @@ -284,10 +284,10 @@ static void nla_keymap_main (wmWindowManager *wm, ListBase *keymap) void nla_keymap(wmWindowManager *wm) { - ListBase *keymap; + wmKeyMap *keymap; /* keymap for all regions */ - keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0); + keymap= WM_keymap_find(wm, "NLA Generic", SPACE_NLA, 0); WM_keymap_add_item(keymap, "NLA_OT_properties", NKEY, KM_PRESS, 0, 0); /* channels */ @@ -297,11 +297,11 @@ void nla_keymap(wmWindowManager *wm) * * However, those operations which involve clicking on channels and/or the placement of them in the view are implemented here instead */ - keymap= WM_keymap_listbase(wm, "NLA Channels", SPACE_NLA, 0); + keymap= WM_keymap_find(wm, "NLA Channels", SPACE_NLA, 0); nla_keymap_channels(wm, keymap); /* data */ - keymap= WM_keymap_listbase(wm, "NLA Data", SPACE_NLA, 0); + keymap= WM_keymap_find(wm, "NLA Data", SPACE_NLA, 0); nla_keymap_main(wm, keymap); } diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 89d4e7cddf2..41435810889 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -208,15 +208,15 @@ static SpaceLink *nla_duplicate(SpaceLink *sl) /* add handlers, stuff you only do once or on area/region changes */ static void nla_channel_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); /* own keymap */ // TODO: cannot use generic copy, need special NLA version - keymap= WM_keymap_listbase(wm, "NLA Channels", SPACE_NLA, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "NLA Channels", SPACE_NLA, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0); + keymap= WM_keymap_find(wm, "NLA Generic", SPACE_NLA, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -254,14 +254,14 @@ static void nla_channel_area_draw(const bContext *C, ARegion *ar) /* add handlers, stuff you only do once or on area/region changes */ static void nla_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "NLA Data", SPACE_NLA, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "NLA Data", SPACE_NLA, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0); + keymap= WM_keymap_find(wm, "NLA Generic", SPACE_NLA, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } @@ -354,11 +354,11 @@ static void nla_header_area_draw(const bContext *C, ARegion *ar) /* add handlers, stuff you only do once or on area/region changes */ static void nla_buttons_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; ED_region_panels_init(wm, ar); - keymap= WM_keymap_listbase(wm, "NLA Generic", SPACE_NLA, 0); + keymap= WM_keymap_find(wm, "NLA Generic", SPACE_NLA, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -409,6 +409,7 @@ static void nla_main_area_listener(ARegion *ar, wmNotifier *wmn) break; case NC_SCENE: switch(wmn->data) { + case ND_RENDER_OPTIONS: case ND_OB_ACTIVE: case ND_FRAME: case ND_MARKERS: diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 05adb5b75ca..b8da42079c4 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): David Millan Escriva, Juho Vepsäläinen, Bob Holcomb + * Contributor(s): David Millan Escriva, Juho Vepsäläinen, Bob Holcomb, Thomas Dinges * * ***** END GPL LICENSE BLOCK ***** */ @@ -170,9 +170,13 @@ static void node_group_alone_cb(bContext *C, void *node_v, void *unused_v) /* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */ -static int node_buts_group(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_buts_group(uiLayout *layout, PointerRNA *ptr) { - if(block && node->id) { + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + + if(node->id) { uiBut *bt; short width; @@ -197,112 +201,95 @@ static int node_buts_group(uiBlock *block, bNodeTree *ntree, bNode *node, rctf * uiBlockEndAlign(block); } - return 19; } #endif -static int node_buts_value(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_buts_value(uiLayout *layout, PointerRNA *ptr) { - if(block) { - bNodeSocket *sock= node->outputs.first; /* first socket stores value */ - - uiDefButF(block, NUM, B_NODE_EXEC, "", - (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin, 20, - sock->ns.vec, sock->ns.min, sock->ns.max, 10, 2, ""); - - } - return 20; + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + bNodeSocket *sock= node->outputs.first; /* first socket stores value */ + + uiDefButF(block, NUM, B_NODE_EXEC, "", + (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin, 20, + sock->ns.vec, sock->ns.min, sock->ns.max, 10, 2, ""); } -static int node_buts_rgb(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_buts_rgb(uiLayout *layout, PointerRNA *ptr) { - if(block) { - bNodeSocket *sock= node->outputs.first; /* first socket stores value */ - if(sock) { - /* enforce square box drawing */ - uiBlockSetEmboss(block, UI_EMBOSSP); - - uiDefButF(block, HSVCUBE, B_NODE_EXEC, "", - (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin, 12, - sock->ns.vec, 0.0f, 1.0f, 3, 0, ""); - uiDefButF(block, HSVCUBE, B_NODE_EXEC, "", - (short)butr->xmin, (short)butr->ymin+15, butr->xmax-butr->xmin, butr->ymax-butr->ymin -15 -15, - sock->ns.vec, 0.0f, 1.0f, 2, 0, ""); - uiDefButF(block, COL, B_NOP, "", - (short)butr->xmin, (short)butr->ymax-12, butr->xmax-butr->xmin, 12, - sock->ns.vec, 0.0, 0.0, -1, 0, ""); - /* the -1 above prevents col button to popup a color picker */ - - uiBlockSetEmboss(block, UI_EMBOSS); - } - } - return 30 + (int)(node->width-NODE_DY); -} + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + bNodeSocket *sock= node->outputs.first; /* first socket stores value */ -static int node_buts_mix_rgb(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) -{ - if(block) { - uiBut *bt; - int a_but= (ntree->type==NTREE_COMPOSIT); + if(sock) { + /* enforce square box drawing */ + uiBlockSetEmboss(block, UI_EMBOSSP); - /* blend type */ - uiBlockBeginAlign(block); - bt=uiDefButS(block, MENU, B_NODE_EXEC, "Mix %x0|Add %x1|Subtract %x3|Multiply %x2|Screen %x4|Overlay %x9|Divide %x5|Difference %x6|Darken %x7|Lighten %x8|Dodge %x10|Burn %x11|Color %x15|Value %x14|Saturation %x13|Hue %x12|Soft Light %x16|Linear Light %x17", - (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin -(a_but?20:0), 20, - &node->custom1, 0, 0, 0, 0, ""); - uiButSetFunc(bt, node_but_title_cb, node, bt); - /* Alpha option, composite */ - if(a_but) - uiDefIconButS(block, TOG, B_NODE_EXEC, ICON_IMAGE_RGB_ALPHA, - (short)butr->xmax-20, (short)butr->ymin, 20, 20, - &node->custom2, 0, 0, 0, 0, "Include Alpha of 2nd input in this operation"); + uiDefButF(block, HSVCUBE, B_NODE_EXEC, "", + (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin, 12, + sock->ns.vec, 0.0f, 1.0f, 3, 0, ""); + uiDefButF(block, HSVCUBE, B_NODE_EXEC, "", + (short)butr->xmin, (short)butr->ymin+15, butr->xmax-butr->xmin, butr->xmax-butr->xmin -15 -15, + sock->ns.vec, 0.0f, 1.0f, 2, 0, ""); + uiDefButF(block, COL, B_NOP, "", + (short)butr->xmin, (short)butr->ymax-12, butr->xmax-butr->xmin, 12, + sock->ns.vec, 0.0, 0.0, -1, 0, ""); + /* the -1 above prevents col button to popup a color picker */ + + uiBlockSetEmboss(block, UI_EMBOSS); } - return 20; } -static int node_buts_time(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) -{ - if(block) { - CurveMapping *cumap= node->storage; - short dx= (short)((butr->xmax-butr->xmin)/2); - butr->ymin += 26; +static void node_buts_mix_rgb(uiLayout *layout, PointerRNA *ptr) +{ + uiLayout *row; - curvemap_buttons(block, node->storage, 's', B_NODE_EXEC, B_REDR, butr); - - if(cumap) { - //cumap->flag |= CUMA_DRAW_CFRA; - //if(node->custom1<node->custom2) - // cumap->sample[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1); - } + bNodeTree *ntree= (bNodeTree*)ptr->id.data; - uiBlockBeginAlign(block); - uiDefButS(block, NUM, B_NODE_EXEC, "Sta:", - (short)butr->xmin, (short)butr->ymin-22, dx, 19, - &node->custom1, 1.0, 20000.0, 0, 0, "Start frame"); - uiDefButS(block, NUM, B_NODE_EXEC, "End:", - (short)butr->xmin+dx, (short)butr->ymin-22, dx, 19, - &node->custom2, 1.0, 20000.0, 0, 0, "End frame"); - } + row= uiLayoutRow(layout, 1); + uiItemR(row, "", 0, ptr, "blend_type", 0); + if(ntree->type == NTREE_COMPOSIT) + uiItemR(row, "", ICON_IMAGE_RGB_ALPHA, ptr, "alpha", 0); +} + +static void node_buts_time(uiLayout *layout, PointerRNA *ptr) +{ + uiLayout *row; +#if 0 + /* XXX no context access here .. */ + bNode *node= ptr->data; + CurveMapping *cumap= node->storage; - return node->width-NODE_DY; + if(cumap) { + cumap->flag |= CUMA_DRAW_CFRA; + if(node->custom1<node->custom2) + cumap->sample[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1); + } +#endif + + uiTemplateCurveMapping(layout, ptr, "curve", 's', 0); + + row= uiLayoutRow(layout, 1); + uiItemR(row, "Sta", 0, ptr, "start", 0); + uiItemR(row, "End", 0, ptr, "end", 0); } -static int node_buts_valtorgb(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_buts_valtorgb(uiLayout *layout, PointerRNA *ptr) { - if(block) { - if(node->storage) { - uiBlockColorbandButtons(block, node->storage, butr, B_NODE_EXEC); - } + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + + if(node->storage) { + uiBlockColorbandButtons(block, node->storage, butr, B_NODE_EXEC); } - return 40; } -static int node_buts_curvevec(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_buts_curvevec(uiLayout *layout, PointerRNA *ptr) { - if(block) { - curvemap_buttons(block, node->storage, 'v', B_NODE_EXEC, B_REDR, butr); - } - return (int)(node->width-NODE_DY); + uiTemplateCurveMapping(layout, ptr, "mapping", 'v', 0); } static float *_sample_col= NULL; // bad bad, 2.5 will do better? @@ -311,33 +298,31 @@ void node_curvemap_sample(float *col) _sample_col= col; } -static int node_buts_curvecol(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_buts_curvecol(uiLayout *layout, PointerRNA *ptr) { - if(block) { - CurveMapping *cumap= node->storage; - if(_sample_col) { - cumap->flag |= CUMA_DRAW_SAMPLE; - VECCOPY(cumap->sample, _sample_col); - } - else - cumap->flag &= ~CUMA_DRAW_SAMPLE; + bNode *node= ptr->data; + CurveMapping *cumap= node->storage; - curvemap_buttons(block, node->storage, 'c', B_NODE_EXEC, B_REDR, butr); - } - return (int)(node->width-NODE_DY); + if(_sample_col) { + cumap->flag |= CUMA_DRAW_SAMPLE; + VECCOPY(cumap->sample, _sample_col); + } + else + cumap->flag &= ~CUMA_DRAW_SAMPLE; + + uiTemplateCurveMapping(layout, ptr, "mapping", 'c', 0); } -static int node_buts_normal(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_buts_normal(uiLayout *layout, PointerRNA *ptr) { - if(block) { - bNodeSocket *sock= node->outputs.first; /* first socket stores normal */ - - uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "", - (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin, butr->ymax-butr->ymin, - sock->ns.vec, 0.0f, 1.0f, 0, 0, ""); - - } - return (int)(node->width-NODE_DY); + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + bNodeSocket *sock= node->outputs.first; /* first socket stores normal */ + + uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "", + (short)butr->xmin, (short)butr->xmin, butr->xmax-butr->xmin, butr->xmax-butr->xmin, + sock->ns.vec, 0.0f, 1.0f, 0, 0, ""); } static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v) @@ -401,8 +386,13 @@ static void node_dynamic_update_cb(bContext *C, void *ntree_v, void *node_v) // XXX BIF_preview_changed(ID_MA); } -static int node_buts_texture(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_buts_texture(uiLayout *layout, PointerRNA *ptr) { + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + bNodeTree *ntree= ptr->id.data; + rctf *butr= &node->butr; + short multi = ( node->id && ((Tex*)node->id)->use_nodes && @@ -410,49 +400,44 @@ static int node_buts_texture(uiBlock *block, bNodeTree *ntree, bNode *node, rctf (node->type != TEX_NODE_TEXTURE) ); - if(block) { - uiBut *bt; - char *strp; - short width = (short)(butr->xmax - butr->xmin); - - /* browse button texture */ - uiBlockBeginAlign(block); - IDnames_to_pupstring(&strp, NULL, "", &(G.main->tex), NULL, NULL); - node->menunr= 0; - bt= uiDefButS(block, MENU, B_NODE_EXEC, strp, - butr->xmin, butr->ymin+(multi?30:0), 20, 19, - &node->menunr, 0, 0, 0, 0, "Browse texture"); - uiButSetFunc(bt, node_browse_tex_cb, ntree, node); - if(strp) MEM_freeN(strp); - - if(node->id) { - bt= uiDefBut(block, TEX, B_NOP, "TE:", - butr->xmin+19, butr->ymin+(multi?30:0), butr->xmax-butr->xmin-19, 19, - node->id->name+2, 0.0, 19.0, 0, 0, "Texture name"); - uiButSetFunc(bt, node_ID_title_cb, node, NULL); - } - uiBlockEndAlign(block); - - if(multi) { - char *menustr = ntreeTexOutputMenu(((Tex*)node->id)->nodetree); - uiDefButS(block, MENU, B_MATPRV, menustr, butr->xmin, butr->ymin, width, 19, &node->custom1, 0, 0, 0, 0, "Which output to use, for multi-output textures"); - free(menustr); - return 50; - } - return 20; - } - else return multi? 50: 20; + uiBut *bt; + char *strp; + short width = (short)(butr->xmax - butr->xmin); + + /* browse button texture */ + uiBlockBeginAlign(block); + IDnames_to_pupstring(&strp, NULL, "", &(G.main->tex), NULL, NULL); + node->menunr= 0; + bt= uiDefButS(block, MENU, B_NODE_EXEC, strp, + butr->xmin, butr->ymin+(multi?30:0), 20, 19, + &node->menunr, 0, 0, 0, 0, "Browse texture"); + uiButSetFunc(bt, node_browse_tex_cb, ntree, node); + if(strp) MEM_freeN(strp); + + if(node->id) { + bt= uiDefBut(block, TEX, B_NOP, "TE:", + butr->xmin+19, butr->ymin+(multi?30:0), butr->xmax-butr->xmin-19, 19, + node->id->name+2, 0.0, 19.0, 0, 0, "Texture name"); + uiButSetFunc(bt, node_ID_title_cb, node, NULL); + } + uiBlockEndAlign(block); + + if(multi) { + char *menustr = ntreeTexOutputMenu(((Tex*)node->id)->nodetree); + uiDefButS(block, MENU, B_MATPRV, menustr, butr->xmin, butr->ymin, width, 19, &node->custom1, 0, 0, 0, 0, "Which output to use, for multi-output textures"); + free(menustr); + } } -static int node_buts_math(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_buts_math(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiBut *bt; + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + uiBut *bt; - bt=uiDefButS(block, MENU, B_NODE_EXEC, "Add %x0|Subtract %x1|Multiply %x2|Divide %x3|Sine %x4|Cosine %x5|Tangent %x6|Arcsine %x7|Arccosine %x8|Arctangent %x9|Power %x10|Logarithm %x11|Minimum %x12|Maximum %x13|Round %x14|Less Than %x15|Greater Than %x16", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 0, 0, 0, ""); - uiButSetFunc(bt, node_but_title_cb, node, bt); - } - return 20; + bt=uiDefButS(block, MENU, B_NODE_EXEC, "Add %x0|Subtract %x1|Multiply %x2|Divide %x3|Sine %x4|Cosine %x5|Tangent %x6|Arcsine %x7|Arccosine %x8|Arctangent %x9|Power %x10|Logarithm %x11|Minimum %x12|Maximum %x13|Round %x14|Less Than %x15|Greater Than %x16", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 0, 0, 0, ""); + uiButSetFunc(bt, node_but_title_cb, node, bt); } @@ -556,192 +541,192 @@ static void node_texmap_cb(bContext *C, void *texmap_v, void *unused_v) init_mapping(texmap_v); } -static int node_shader_buts_material(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_shader_buts_material(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiBut *bt; - short dx= (short)((butr->xmax-butr->xmin)/3.0f), has_us= (node->id && node->id->us>1); - short dy= (short)butr->ymin; - char *strp; - - /* WATCH IT: we use this callback in material buttons, but then only want first row */ - if(butr->ymax-butr->ymin > 21.0f) dy+= 19; - - uiBlockBeginAlign(block); - /* XXX - if(node->id==NULL) uiBlockSetCol(block, TH_REDALERT); - else if(has_us) uiBlockSetCol(block, TH_BUT_SETTING1); - else uiBlockSetCol(block, TH_BUT_SETTING2); - */ - - /* browse button */ - IDnames_to_pupstring(&strp, NULL, "ADD NEW %x32767", &(G.main->mat), NULL, NULL); - node->menunr= 0; - bt= uiDefButS(block, MENU, B_NOP, strp, - butr->xmin, dy, 19, 19, - &node->menunr, 0, 0, 0, 0, "Browses existing choices or adds NEW"); - uiButSetFunc(bt, node_browse_mat_cb, ntree, node); - if(strp) MEM_freeN(strp); + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + bNodeTree *ntree= ptr->id.data; + rctf *butr= &node->butr; + uiBut *bt; + short dx= (short)((butr->xmax-butr->xmin)/3.0f), has_us= (node->id && node->id->us>1); + short dy= (short)butr->ymin; + char *strp; + + /* WATCH IT: we use this callback in material buttons, but then only want first row */ + if(butr->ymax-butr->ymin > 21.0f) dy+= 19; + + uiBlockBeginAlign(block); + /* XXX + if(node->id==NULL) uiBlockSetCol(block, TH_REDALERT); + else if(has_us) uiBlockSetCol(block, TH_BUT_SETTING1); + else uiBlockSetCol(block, TH_BUT_SETTING2); + */ + + /* browse button */ + IDnames_to_pupstring(&strp, NULL, "ADD NEW %x32767", &(G.main->mat), NULL, NULL); + node->menunr= 0; + bt= uiDefButS(block, MENU, B_NOP, strp, + butr->xmin, dy, 19, 19, + &node->menunr, 0, 0, 0, 0, "Browses existing choices or adds NEW"); + uiButSetFunc(bt, node_browse_mat_cb, ntree, node); + if(strp) MEM_freeN(strp); + + /* Add New button */ + if(node->id==NULL) { + bt= uiDefBut(block, BUT, B_NOP, "Add New", + butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, + NULL, 0.0, 0.0, 0, 0, "Add new Material"); + uiButSetFunc(bt, node_new_mat_cb, ntree, node); + } + else { + /* name button */ + short width= (short)(butr->xmax-butr->xmin-19.0f - (has_us?19.0f:0.0f)); + bt= uiDefBut(block, TEX, B_NOP, "MA:", + butr->xmin+19, dy, width, 19, + node->id->name+2, 0.0, 19.0, 0, 0, "Material name"); + uiButSetFunc(bt, node_ID_title_cb, node, NULL); - /* Add New button */ - if(node->id==NULL) { - bt= uiDefBut(block, BUT, B_NOP, "Add New", - butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, - NULL, 0.0, 0.0, 0, 0, "Add new Material"); - uiButSetFunc(bt, node_new_mat_cb, ntree, node); + /* user amount */ + if(has_us) { + char str1[32]; + sprintf(str1, "%d", node->id->us); + bt= uiDefBut(block, BUT, B_NOP, str1, + butr->xmax-19, dy, 19, 19, + NULL, 0, 0, 0, 0, "Displays number of users. Click to make a single-user copy."); + uiButSetFunc(bt, node_mat_alone_cb, node, NULL); } - else { - /* name button */ - short width= (short)(butr->xmax-butr->xmin-19.0f - (has_us?19.0f:0.0f)); - bt= uiDefBut(block, TEX, B_NOP, "MA:", - butr->xmin+19, dy, width, 19, - node->id->name+2, 0.0, 19.0, 0, 0, "Material name"); - uiButSetFunc(bt, node_ID_title_cb, node, NULL); - - /* user amount */ - if(has_us) { - char str1[32]; - sprintf(str1, "%d", node->id->us); - bt= uiDefBut(block, BUT, B_NOP, str1, - butr->xmax-19, dy, 19, 19, - NULL, 0, 0, 0, 0, "Displays number of users. Click to make a single-user copy."); - uiButSetFunc(bt, node_mat_alone_cb, node, NULL); - } - - /* WATCH IT: we use this callback in material buttons, but then only want first row */ - if(butr->ymax-butr->ymin > 21.0f) { - /* node options */ - uiDefButBitS(block, TOG, SH_NODE_MAT_DIFF, B_NODE_EXEC, "Diff", - butr->xmin, butr->ymin, dx, 19, - &node->custom1, 0, 0, 0, 0, "Material Node outputs Diffuse"); - uiDefButBitS(block, TOG, SH_NODE_MAT_SPEC, B_NODE_EXEC, "Spec", - butr->xmin+dx, butr->ymin, dx, 19, - &node->custom1, 0, 0, 0, 0, "Material Node outputs Specular"); - uiDefButBitS(block, TOG, SH_NODE_MAT_NEG, B_NODE_EXEC, "Neg Normal", - butr->xmax-dx, butr->ymin, dx, 19, - &node->custom1, 0, 0, 0, 0, "Material Node uses inverted Normal"); - } + + /* WATCH IT: we use this callback in material buttons, but then only want first row */ + if(butr->ymax-butr->ymin > 21.0f) { + /* node options */ + uiDefButBitS(block, TOG, SH_NODE_MAT_DIFF, B_NODE_EXEC, "Diff", + butr->xmin, butr->ymin, dx, 19, + &node->custom1, 0, 0, 0, 0, "Material Node outputs Diffuse"); + uiDefButBitS(block, TOG, SH_NODE_MAT_SPEC, B_NODE_EXEC, "Spec", + butr->xmin+dx, butr->ymin, dx, 19, + &node->custom1, 0, 0, 0, 0, "Material Node outputs Specular"); + uiDefButBitS(block, TOG, SH_NODE_MAT_NEG, B_NODE_EXEC, "Neg Normal", + butr->xmax-dx, butr->ymin, dx, 19, + &node->custom1, 0, 0, 0, 0, "Material Node uses inverted Normal"); } - uiBlockEndAlign(block); - } - return 38; + } + uiBlockEndAlign(block); } -static int node_shader_buts_mapping(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_shader_buts_mapping(uiLayout *layout, PointerRNA *ptr) { - if(block) { - TexMapping *texmap= node->storage; - short dx= (short)((butr->xmax-butr->xmin)/7.0f); - short dy= (short)(butr->ymax-19); - - uiBlockSetFunc(block, node_texmap_cb, texmap, NULL); /* all buttons get this */ - - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->loc, -1000.0f, 1000.0f, 10, 2, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->loc+1, -1000.0f, 1000.0f, 10, 2, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->loc+2, -1000.0f, 1000.0f, 10, 2, ""); - dy-= 19; - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->rot, -1000.0f, 1000.0f, 1000, 1, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->rot+1, -1000.0f, 1000.0f, 1000, 1, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->rot+2, -1000.0f, 1000.0f, 1000, 1, ""); - dy-= 19; - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->size, -1000.0f, 1000.0f, 10, 2, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->size+1, -1000.0f, 1000.0f, 10, 2, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->size+2, -1000.0f, 1000.0f, 10, 2, ""); - dy-= 25; - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->min, -10.0f, 10.0f, 100, 2, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->min+1, -10.0f, 10.0f, 100, 2, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->min+2, -10.0f, 10.0f, 100, 2, ""); - dy-= 19; - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->max, -10.0f, 10.0f, 10, 2, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->max+1, -10.0f, 10.0f, 10, 2, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->max+2, -10.0f, 10.0f, 10, 2, ""); - uiBlockEndAlign(block); - - /* labels/options */ - - dy= (short)(butr->ymax-19); - uiDefBut(block, LABEL, B_NOP, "Loc", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, ""); - dy-= 19; - uiDefBut(block, LABEL, B_NOP, "Rot", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, ""); - dy-= 19; - uiDefBut(block, LABEL, B_NOP, "Size", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, ""); - dy-= 25; - uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC, "Min", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, ""); - dy-= 19; - uiDefButBitI(block, TOG, TEXMAP_CLIP_MAX, B_NODE_EXEC, "Max", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, ""); - - } - return 5*19 + 6; + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + TexMapping *texmap= node->storage; + short dx= (short)((butr->xmax-butr->xmin)/7.0f); + short dy= (short)(butr->ymax-19); + + uiBlockSetFunc(block, node_texmap_cb, texmap, NULL); /* all buttons get this */ + + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->loc, -1000.0f, 1000.0f, 10, 2, ""); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->loc+1, -1000.0f, 1000.0f, 10, 2, ""); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->loc+2, -1000.0f, 1000.0f, 10, 2, ""); + dy-= 19; + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->rot, -1000.0f, 1000.0f, 1000, 1, ""); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->rot+1, -1000.0f, 1000.0f, 1000, 1, ""); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->rot+2, -1000.0f, 1000.0f, 1000, 1, ""); + dy-= 19; + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->size, -1000.0f, 1000.0f, 10, 2, ""); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->size+1, -1000.0f, 1000.0f, 10, 2, ""); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->size+2, -1000.0f, 1000.0f, 10, 2, ""); + dy-= 25; + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->min, -10.0f, 10.0f, 100, 2, ""); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->min+1, -10.0f, 10.0f, 100, 2, ""); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->min+2, -10.0f, 10.0f, 100, 2, ""); + dy-= 19; + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->max, -10.0f, 10.0f, 10, 2, ""); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->max+1, -10.0f, 10.0f, 10, 2, ""); + uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->max+2, -10.0f, 10.0f, 10, 2, ""); + uiBlockEndAlign(block); + + /* labels/options */ + + dy= (short)(butr->ymax-19); + uiDefBut(block, LABEL, B_NOP, "Loc", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, ""); + dy-= 19; + uiDefBut(block, LABEL, B_NOP, "Rot", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, ""); + dy-= 19; + uiDefBut(block, LABEL, B_NOP, "Size", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, ""); + dy-= 25; + uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC, "Min", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, ""); + dy-= 19; + uiDefButBitI(block, TOG, TEXMAP_CLIP_MAX, B_NODE_EXEC, "Max", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, ""); } -static int node_shader_buts_vect_math(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_shader_buts_vect_math(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiBut *bt; - - bt=uiDefButS(block, MENU, B_NODE_EXEC, "Add %x0|Subtract %x1|Average %x2|Dot Product %x3 |Cross Product %x4|Normalize %x5", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 0, 0, 0, ""); - uiButSetFunc(bt, node_but_title_cb, node, bt); - } - return 20; + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + uiBut *bt; + + bt=uiDefButS(block, MENU, B_NODE_EXEC, "Add %x0|Subtract %x1|Average %x2|Dot Product %x3 |Cross Product %x4|Normalize %x5", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 0, 0, 0, ""); + uiButSetFunc(bt, node_but_title_cb, node, bt); } -static int node_shader_buts_geometry(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_shader_buts_geometry(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiBut *but; - NodeGeometry *ngeo= (NodeGeometry*)node->storage; + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + uiBut *but; + NodeGeometry *ngeo= (NodeGeometry*)node->storage; - // XXX if(!verify_valid_uv_name(ngeo->uvname)) - // XXX uiBlockSetCol(block, TH_REDALERT); - but= uiDefBut(block, TEX, B_NODE_EXEC, "UV:", butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20, ngeo->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer"); - // XXX uiButSetCompleteFunc(but, autocomplete_uv, NULL); + // XXX if(!verify_valid_uv_name(ngeo->uvname)) + // XXX uiBlockSetCol(block, TH_REDALERT); + but= uiDefBut(block, TEX, B_NODE_EXEC, "UV:", butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20, ngeo->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer"); + // XXX uiButSetCompleteFunc(but, autocomplete_uv, NULL); - if(!verify_valid_vcol_name(ngeo->colname)); + if(!verify_valid_vcol_name(ngeo->colname)); // uiBlockSetCol(block, TH_REDALERT); - but= uiDefBut(block, TEX, B_NODE_EXEC, "Col:", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, ngeo->colname, 0, 31, 0, 0, "Set name of vertex color layer to use, default is active vertex color layer"); - uiButSetCompleteFunc(but, autocomplete_vcol, NULL); - } - - return 40; + but= uiDefBut(block, TEX, B_NODE_EXEC, "Col:", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, ngeo->colname, 0, 31, 0, 0, "Set name of vertex color layer to use, default is active vertex color layer"); + uiButSetCompleteFunc(but, autocomplete_vcol, NULL); } -static int node_shader_buts_dynamic(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_shader_buts_dynamic(uiLayout *layout, PointerRNA *ptr) { - if (block) { - uiBut *bt; - // XXX SpaceNode *snode= curarea->spacedata.first; - short dy= (short)butr->ymin; - int xoff=0; - - /* B_NODE_EXEC is handled in butspace.c do_node_buts */ - if(!node->id) { - char *strp; - IDnames_to_pupstring(&strp, NULL, "", &(G.main->text), NULL, NULL); - node->menunr= 0; - bt= uiDefButS(block, MENU, B_NODE_EXEC/*+node->nr*/, strp, - butr->xmin, dy, 19, 19, - &node->menunr, 0, 0, 0, 0, "Browses existing choices"); - uiButSetFunc(bt, node_browse_text_cb, ntree, node); - xoff=19; - if(strp) MEM_freeN(strp); - } - else { - bt = uiDefBut(block, BUT, B_NOP, "Update", - butr->xmin+xoff, butr->ymin+20, 50, 19, - &node->menunr, 0.0, 19.0, 0, 0, "Refresh this node (and all others that use the same script)"); - uiButSetFunc(bt, node_dynamic_update_cb, ntree, node); - - if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) { - // UI_ThemeColor(TH_REDALERT); - // XXX ui_rasterpos_safe(butr->xmin + xoff, butr->ymin + 5, snode->aspect); - // XXX snode_drawstring(snode, "Error! Check console...", butr->xmax - butr->xmin); - ; - } + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + bNodeTree *ntree= ptr->id.data; + rctf *butr= &node->butr; + uiBut *bt; + // XXX SpaceNode *snode= curarea->spacedata.first; + short dy= (short)butr->ymin; + int xoff=0; + + /* B_NODE_EXEC is handled in butspace.c do_node_buts */ + if(!node->id) { + char *strp; + IDnames_to_pupstring(&strp, NULL, "", &(G.main->text), NULL, NULL); + node->menunr= 0; + bt= uiDefButS(block, MENU, B_NODE_EXEC/*+node->nr*/, strp, + butr->xmin, dy, 19, 19, + &node->menunr, 0, 0, 0, 0, "Browses existing choices"); + uiButSetFunc(bt, node_browse_text_cb, ntree, node); + xoff=19; + if(strp) MEM_freeN(strp); + } + else { + bt = uiDefBut(block, BUT, B_NOP, "Update", + butr->xmin+xoff, butr->ymin+20, 50, 19, + &node->menunr, 0.0, 19.0, 0, 0, "Refresh this node (and all others that use the same script)"); + uiButSetFunc(bt, node_dynamic_update_cb, ntree, node); + + if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) { + // UI_ThemeColor(TH_REDALERT); + // XXX ui_rasterpos_safe(butr->xmin + xoff, butr->ymin + 5, snode->aspect); + // XXX snode_drawstring(snode, "Error! Check console...", butr->xmax - butr->xmin); + ; } } - return 20+19; } /* only once called */ @@ -752,49 +737,49 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_MATERIAL: case SH_NODE_MATERIAL_EXT: - ntype->butfunc= node_shader_buts_material; + ntype->uifunc= node_shader_buts_material; break; case SH_NODE_TEXTURE: - ntype->butfunc= node_buts_texture; + ntype->uifunc= node_buts_texture; break; case SH_NODE_NORMAL: - ntype->butfunc= node_buts_normal; + ntype->uifunc= node_buts_normal; break; case SH_NODE_CURVE_VEC: - ntype->butfunc= node_buts_curvevec; + ntype->uifunc= node_buts_curvevec; break; case SH_NODE_CURVE_RGB: - ntype->butfunc= node_buts_curvecol; + ntype->uifunc= node_buts_curvecol; break; case SH_NODE_MAPPING: - ntype->butfunc= node_shader_buts_mapping; + ntype->uifunc= node_shader_buts_mapping; break; case SH_NODE_VALUE: - ntype->butfunc= node_buts_value; + ntype->uifunc= node_buts_value; break; case SH_NODE_RGB: - ntype->butfunc= node_buts_rgb; + ntype->uifunc= node_buts_rgb; break; case SH_NODE_MIX_RGB: - ntype->butfunc= node_buts_mix_rgb; + ntype->uifunc= node_buts_mix_rgb; break; case SH_NODE_VALTORGB: - ntype->butfunc= node_buts_valtorgb; + ntype->uifunc= node_buts_valtorgb; break; case SH_NODE_MATH: - ntype->butfunc= node_buts_math; + ntype->uifunc= node_buts_math; break; case SH_NODE_VECT_MATH: - ntype->butfunc= node_shader_buts_vect_math; + ntype->uifunc= node_shader_buts_vect_math; break; case SH_NODE_GEOMETRY: - ntype->butfunc= node_shader_buts_geometry; + ntype->uifunc= node_shader_buts_geometry; break; case NODE_DYNAMIC: - ntype->butfunc= node_shader_buts_dynamic; + ntype->uifunc= node_shader_buts_dynamic; break; default: - ntype->butfunc= NULL; + ntype->uifunc= NULL; } } @@ -879,112 +864,102 @@ static void image_layer_cb(bContext *C, void *ima_v, void *iuser_v) // allqueue(REDRAWNODE, 0); } -static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_image(uiLayout *layout, PointerRNA *ptr) { + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + bNodeTree *ntree= ptr->id.data; + rctf *butr= &node->butr; ImageUser *iuser= node->storage; + uiBut *bt; + short dy= (short)butr->ymax-19; + char *strp; - if(block) { - uiBut *bt; - short dy= (short)butr->ymax-19; - char *strp; + uiBlockBeginAlign(block); + + /* browse button */ + IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL); + node->menunr= 0; + bt= uiDefButS(block, MENU, B_NOP, strp, + butr->xmin, dy, 19, 19, + &node->menunr, 0, 0, 0, 0, "Browses existing choices"); + uiButSetFunc(bt, node_browse_image_cb, ntree, node); + if(strp) MEM_freeN(strp); + + /* Add New button */ + if(node->id==NULL) { + bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New", + butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, + NULL, 0.0, 0.0, 0, 0, "Add new Image"); + uiButSetFunc(bt, node_active_cb, ntree, node); + } + else { + /* name button + type */ + Image *ima= (Image *)node->id; + short xmin= (short)butr->xmin, xmax= (short)butr->xmax; + short width= xmax - xmin - 45; + short icon= ICON_IMAGE_DATA; - uiBlockBeginAlign(block); + if(ima->source==IMA_SRC_MOVIE) icon= ICON_SEQUENCE; + else if(ima->source==IMA_SRC_SEQUENCE) icon= ICON_IMAGE_COL; + else if(ima->source==IMA_SRC_GENERATED) icon= ICON_BLANK1; - /* browse button */ - IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL); - node->menunr= 0; - bt= uiDefButS(block, MENU, B_NOP, strp, - butr->xmin, dy, 19, 19, - &node->menunr, 0, 0, 0, 0, "Browses existing choices"); - uiButSetFunc(bt, node_browse_image_cb, ntree, node); - if(strp) MEM_freeN(strp); + bt= uiDefBut(block, TEX, B_NOP, "IM:", + xmin+19, dy, width, 19, + node->id->name+2, 0.0, 19.0, 0, 0, "Image name"); + uiButSetFunc(bt, node_ID_title_cb, node, NULL); - /* Add New button */ - if(node->id==NULL) { - bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New", - butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, - NULL, 0.0, 0.0, 0, 0, "Add new Image"); - uiButSetFunc(bt, node_active_cb, ntree, node); - } - else { - /* name button + type */ - Image *ima= (Image *)node->id; - short xmin= (short)butr->xmin, xmax= (short)butr->xmax; - short width= xmax - xmin - 45; - short icon= ICON_IMAGE_DATA; - - if(ima->source==IMA_SRC_MOVIE) icon= ICON_SEQUENCE; - else if(ima->source==IMA_SRC_SEQUENCE) icon= ICON_IMAGE_COL; - else if(ima->source==IMA_SRC_GENERATED) icon= ICON_BLANK1; - - bt= uiDefBut(block, TEX, B_NOP, "IM:", - xmin+19, dy, width, 19, - node->id->name+2, 0.0, 19.0, 0, 0, "Image name"); - uiButSetFunc(bt, node_ID_title_cb, node, NULL); - - /* buffer type option */ - strp= node_image_type_pup(); - bt= uiDefIconTextButS(block, MENU, B_NOP, icon, strp, - xmax-26, dy, 26, 19, - &ima->source, 0.0, 19.0, 0, 0, "Image type"); - uiButSetFunc(bt, node_image_type_cb, node, ima); - MEM_freeN(strp); + /* buffer type option */ + strp= node_image_type_pup(); + bt= uiDefIconTextButS(block, MENU, B_NOP, icon, strp, + xmax-26, dy, 26, 19, + &ima->source, 0.0, 19.0, 0, 0, "Image type"); + uiButSetFunc(bt, node_image_type_cb, node, ima); + MEM_freeN(strp); + + if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) { + width= (xmax-xmin)/2; - if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) { - width= (xmax-xmin)/2; - - dy-= 19; - uiDefButI(block, NUM, B_NODE_EXEC, "Frs:", - xmin, dy, width, 19, - &iuser->frames, 1.0, MAXFRAMEF, 0, 0, "Amount of images used in animation"); - uiDefButI(block, NUM, B_NODE_EXEC, "SFra:", - xmin+width, dy, width, 19, - &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Start frame of animation"); + dy-= 19; + uiDefButI(block, NUM, B_NODE_EXEC, "Frs:", + xmin, dy, width, 19, + &iuser->frames, 1.0, MAXFRAMEF, 0, 0, "Amount of images used in animation"); + uiDefButI(block, NUM, B_NODE_EXEC, "SFra:", + xmin+width, dy, width, 19, + &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Start frame of animation"); + dy-= 19; + uiDefButI(block, NUM, B_NODE_EXEC, "Offs:", + xmin, dy, width, 19, + &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation"); + uiDefButS(block, TOG, B_NODE_EXEC, "Cycl", + xmin+width, dy, width-20, 19, + &iuser->cycl, 0.0, 0.0, 0, 0, "Make animation go cyclic"); + uiDefIconButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NODE_EXEC, ICON_AUTO, + xmax-20, dy, 20, 19, + &iuser->flag, 0.0, 0.0, 0, 0, "Always refresh Image on frame changes"); + } + if( ima->type==IMA_TYPE_MULTILAYER && ima->rr) { + RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); + if(rl) { + width= (xmax-xmin); dy-= 19; - uiDefButI(block, NUM, B_NODE_EXEC, "Offs:", + strp= layer_menu(ima->rr); + bt= uiDefButS(block, MENU, B_NODE_EXEC, strp, xmin, dy, width, 19, - &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation"); - uiDefButS(block, TOG, B_NODE_EXEC, "Cycl", - xmin+width, dy, width-20, 19, - &iuser->cycl, 0.0, 0.0, 0, 0, "Make animation go cyclic"); - uiDefIconButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NODE_EXEC, ICON_AUTO, - xmax-20, dy, 20, 19, - &iuser->flag, 0.0, 0.0, 0, 0, "Always refresh Image on frame changes"); - } - if( ima->type==IMA_TYPE_MULTILAYER && ima->rr) { - RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); - if(rl) { - width= (xmax-xmin); - dy-= 19; - strp= layer_menu(ima->rr); - bt= uiDefButS(block, MENU, B_NODE_EXEC, strp, - xmin, dy, width, 19, - &iuser->layer, 0.0, 10000.0, 0, 0, "Layer"); - uiButSetFunc(bt, image_layer_cb, ima->rr, node->storage); - MEM_freeN(strp); - } + &iuser->layer, 0.0, 10000.0, 0, 0, "Layer"); + uiButSetFunc(bt, image_layer_cb, ima->rr, node->storage); + MEM_freeN(strp); } } + } - } if(node->id) { - Image *ima= (Image *)node->id; - int retval= 19; - /* for each draw we test for anim refresh event */ if(iuser->flag & IMA_ANIM_REFRESHED) { iuser->flag &= ~IMA_ANIM_REFRESHED; // addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC); XXX } - - if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) - retval+= 38; - if( ima->type==IMA_TYPE_MULTILAYER) - retval+= 19; - return retval; } - else - return 19; } /* if we use render layers from other scene, we make a nice title */ @@ -1057,9 +1032,14 @@ static void node_browse_scene_cb(bContext *C, void *ntree_v, void *node_v) } -static int node_composit_buts_renderlayers(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_renderlayers(uiLayout *layout, PointerRNA *ptr) { - if(block && node->id) { + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + bNodeTree *ntree= ptr->id.data; + rctf *butr= &node->butr; + + if(node->id) { Scene *scene= (Scene *)node->id; uiBut *bt; char *strp; @@ -1094,7 +1074,6 @@ static int node_composit_buts_renderlayers(uiBlock *block, bNodeTree *ntree, bNo &node->custom2, 0, 0, 0, 0, "Re-render this Layer"); } - return 19; } static void node_blur_relative_cb(bContext *C, void *node, void *poin2) @@ -1126,734 +1105,426 @@ static void node_blur_update_sizey_cb(bContext *C, void *node, void *poin2) nbd->sizey= (int)(nbd->percenty*nbd->image_in_height); } -static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_blur(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeBlurData *nbd= node->storage; - uiBut *bt; - short dy= butr->ymin+58; - short dx= (butr->xmax-butr->xmin)/2; - char str[256]; - - uiBlockBeginAlign(block); - sprintf(str, "Filter Type%%t|Flat %%x%d|Tent %%x%d|Quad %%x%d|Cubic %%x%d|Gauss %%x%d|Fast Gauss%%x%d|CatRom %%x%d|Mitch %%x%d", R_FILTER_BOX, R_FILTER_TENT, R_FILTER_QUAD, R_FILTER_CUBIC, R_FILTER_GAUSS, R_FILTER_FAST_GAUSS, R_FILTER_CATROM, R_FILTER_MITCH); - uiDefButS(block, MENU, B_NODE_EXEC,str, - butr->xmin, dy, dx*2, 19, - &nbd->filtertype, 0, 0, 0, 0, "Set sampling filter for blur"); - dy-=19; - if (nbd->filtertype != R_FILTER_FAST_GAUSS) { - uiDefButC(block, TOG, B_NODE_EXEC, "Bokeh", - butr->xmin, dy, dx, 19, - &nbd->bokeh, 0, 0, 0, 0, "Uses circular filter, warning it's slow!"); - uiDefButC(block, TOG, B_NODE_EXEC, "Gamma", - butr->xmin+dx, dy, dx, 19, - &nbd->gamma, 0, 0, 0, 0, "Applies filter on gamma corrected values"); - } else { - uiBlockEndAlign(block); - uiBlockBeginAlign(block); - } - dy-=19; - bt= uiDefButS(block, TOG, B_NOP, "Relative", - butr->xmin, dy, dx*2, 19, - &nbd->relative, 0, 0, 0, 0, "Use relative (percent) values to define blur radius"); - uiButSetFunc(bt, node_blur_relative_cb, node, NULL); - - dy-=19; - if(nbd->relative) { - bt= uiDefButF(block, NUM, B_NODE_EXEC, "X:", - butr->xmin, dy, dx, 19, - &nbd->percentx, 0.0f, 1.0f, 0, 0, ""); - uiButSetFunc(bt, node_blur_update_sizex_cb, node, NULL); - bt= uiDefButF(block, NUM, B_NODE_EXEC, "Y:", - butr->xmin+dx, dy, dx, 19, - &nbd->percenty, 0.0f, 1.0f, 0, 0, ""); - uiButSetFunc(bt, node_blur_update_sizey_cb, node, NULL); - } - else { - uiDefButS(block, NUM, B_NODE_EXEC, "X:", - butr->xmin, dy, dx, 19, - &nbd->sizex, 0, 256, 0, 0, ""); - uiDefButS(block, NUM, B_NODE_EXEC, "Y:", - butr->xmin+dx, dy, dx, 19, - &nbd->sizey, 0, 256, 0, 0, ""); - } - uiBlockEndAlign(block); + uiLayout *col; + + col= uiLayoutColumn(layout, 0); + + uiItemR(col, "", 0, ptr, "filter_type", 0); + /* Only for "Fast Gaussian" */ + if (RNA_enum_get(ptr, "filter_type")!= 7) { + uiItemR(col, NULL, 0, ptr, "bokeh", 0); + uiItemR(col, NULL, 0, ptr, "gamma", 0); + } + + uiItemR(col, NULL, 0, ptr, "relative", 0); + col= uiLayoutColumn(layout, 1); + if (RNA_boolean_get(ptr, "relative")== 1) { + uiItemR(col, "X", 0, ptr, "factor_x", 0); + uiItemR(col, "Y", 0, ptr, "factor_y", 0); + } + else { + uiItemR(col, "X", 0, ptr, "sizex", 0); + uiItemR(col, "Y", 0, ptr, "sizey", 0); } - return 77; } -static int node_composit_buts_dblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_dblur(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeDBlurData *ndbd = node->storage; - short dy = butr->ymin + 171; - short dx = butr->xmax - butr->xmin; - short halfdx= (short)dx/2; - - uiBlockBeginAlign(block); - uiDefButS(block, NUM, B_NODE_EXEC, "Iterations:", - butr->xmin, dy, dx, 19, - &ndbd->iter, 1, 32, 10, 0, "Amount of iterations"); - uiDefButC(block, TOG, B_NODE_EXEC, "Wrap", - butr->xmin, dy-= 19, dx, 19, - &ndbd->wrap, 0, 0, 0, 0, "Wrap blur"); - uiBlockEndAlign(block); - - dy-= 9; - - uiDefBut(block, LABEL, B_NOP, "Center", butr->xmin, dy-= 19, dx, 19, NULL, 0.0f, 0.0f, 0, 0, ""); - - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_NODE_EXEC, "X:", - butr->xmin, dy-= 19, halfdx, 19, - &ndbd->center_x, 0.0f, 1.0f, 10, 0, "X center in percents"); - uiDefButF(block, NUM, B_NODE_EXEC, "Y:", - butr->xmin+halfdx, dy, halfdx, 19, - &ndbd->center_y, 0.0f, 1.0f, 10, 0, "Y center in percents"); - uiBlockEndAlign(block); + uiLayout *col; + + uiItemR(layout, NULL, 0, ptr, "iterations", 0); + uiItemR(layout, NULL, 0, ptr, "wrap", 0); + + col= uiLayoutColumn(layout, 1); + uiItemL(col, "Center:", 0); + uiItemR(col, "X", 0, ptr, "center_x", 0); + uiItemR(col, "Y", 0, ptr, "center_y", 0); + + uiItemS(layout); + + col= uiLayoutColumn(layout, 1); + uiItemR(col, NULL, 0, ptr, "distance", 0); + uiItemR(col, NULL, 0, ptr, "angle", 0); + + uiItemS(layout); + + uiItemR(layout, NULL, 0, ptr, "spin", 0); + uiItemR(layout, NULL, 0, ptr, "zoom", 0); +} - dy-= 9; +static void node_composit_buts_bilateralblur(uiLayout *layout, PointerRNA *ptr) +{ + uiLayout *col; + + col= uiLayoutColumn(layout, 1); + uiItemR(col, NULL, 0, ptr, "iterations", 0); + uiItemR(col, NULL, 0, ptr, "sigma_color", 0); + uiItemR(col, NULL, 0, ptr, "sigma_space", 0); +} - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_NODE_EXEC, "Distance:", - butr->xmin, dy-= 19, dx, 19, - &ndbd->distance, -1.0f, 1.0f, 10, 0, "Amount of which the image moves"); - uiDefButF(block, NUM, B_NODE_EXEC, "Angle:", - butr->xmin, dy-= 19, dx, 19, - &ndbd->angle, 0.0f, 360.0f, 1000, 0, "Angle in which the image will be moved"); - uiBlockEndAlign(block); +/* qdn: defocus node */ +static void node_composit_buts_defocus(uiLayout *layout, PointerRNA *ptr) +{ + uiLayout *sub, *col; + + col= uiLayoutColumn(layout, 0); + uiItemL(col, "Bokeh Type:", 0); + uiItemR(col, "", 0, ptr, "bokeh", 0); + uiItemR(col, NULL, 0, ptr, "angle", 0); - dy-= 9; + uiItemR(layout, NULL, 0, ptr, "gamma_correction", 0); - uiDefButF(block, NUM, B_NODE_EXEC, "Spin:", - butr->xmin, dy-= 19, dx, 19, - &ndbd->spin, -360.0f, 360.0f, 1000, 0, "Angle that is used to spin the image"); + col = uiLayoutColumn(layout, 0); + uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer")==0); + uiItemR(col, NULL, 0, ptr, "f_stop", 0); - dy-= 9; + uiItemR(layout, NULL, 0, ptr, "max_blur", 0); + uiItemR(layout, NULL, 0, ptr, "threshold", 0); + + // Preview + col = uiLayoutColumn(layout, 0); + uiItemR(col, NULL, 0, ptr, "preview", 0); + sub = uiLayoutColumn(col, 0); + uiLayoutSetActive(sub, RNA_boolean_get(ptr, "preview")); + uiItemR(sub, NULL, 0, ptr, "samples", 0); + + // Z-Buffer + col = uiLayoutColumn(layout, 0); + uiItemR(col, NULL, 0, ptr, "use_zbuffer", 0); + sub = uiLayoutColumn(col, 0); + uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer")); + uiItemR(sub, NULL, 0, ptr, "z_scale", 0); +} - uiDefButF(block, NUM, B_NODE_EXEC, "Zoom:", - butr->xmin, dy-= 19, dx, 19, - &ndbd->zoom, 0.0f, 100.0f, 100, 0, "Amount of which the image is zoomed"); +/* qdn: glare node */ +static void node_composit_buts_glare(uiLayout *layout, PointerRNA *ptr) +{ + uiItemR(layout, "", 0, ptr, "glare_type", 0); + uiItemR(layout, "", 0, ptr, "quality", 0); + if (RNA_enum_get(ptr, "glare_type")!= 1) { + uiItemR(layout, NULL, 0, ptr, "iterations", 0); + + if (RNA_enum_get(ptr, "glare_type")!= 0) + uiItemR(layout, NULL, 0, ptr, "color_modulation", UI_ITEM_R_SLIDER); } - return 190; -} + + uiItemR(layout, NULL, 0, ptr, "mix", 0); + uiItemR(layout, NULL, 0, ptr, "threshold", 0); -static int node_composit_buts_bilateralblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) -{ - if(block) { - NodeBilateralBlurData *nbbd= node->storage; - short dy= butr->ymin+38; - short dx= (butr->xmax-butr->xmin); - - uiBlockBeginAlign(block); - uiDefButS(block, NUM, B_NODE_EXEC, "Iterations:", - butr->xmin, dy, dx, 19, - &nbbd->iter, 1, 128, 0, 0, "Amount of iterations"); - dy-=19; - uiDefButF(block, NUM, B_NODE_EXEC, "Color Sigma:", - butr->xmin, dy, dx, 19, - &nbbd->sigma_color,0.01, 3, 10, 0, "Sigma value used to modify color"); - dy-=19; - uiDefButF(block, NUM, B_NODE_EXEC, "Space Sigma:", - butr->xmin, dy, dx, 19, - &nbbd->sigma_space ,0.01, 30, 10, 0, "Sigma value used to modify space"); + if (RNA_enum_get(ptr, "glare_type")== 2) { + uiItemR(layout, NULL, 0, ptr, "streaks", 0); + uiItemR(layout, NULL, 0, ptr, "angle_offset", 0); + } + if (RNA_enum_get(ptr, "glare_type")== 0 || RNA_enum_get(ptr, "glare_type")== 2) { + uiItemR(layout, NULL, 0, ptr, "fade", UI_ITEM_R_SLIDER); + if (RNA_enum_get(ptr, "glare_type")== 0) + uiItemR(layout, NULL, 0, ptr, "rotate_45", 0); } - return 57; -} - -/* qdn: defocus node */ -static int node_composit_buts_defocus(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) -{ - if(block) { - NodeDefocus *nqd = node->storage; - short dy = butr->ymin + 209; - short dx = butr->xmax - butr->xmin; - char* mstr1 = "Bokeh Type%t|Octagon %x8|Heptagon %x7|Hexagon %x6|Pentagon %x5|Square %x4|Triangle %x3|Disk %x0"; - - uiDefBut(block, LABEL, B_NOP, "Bokeh Type", butr->xmin, dy, dx, 19, NULL, 0, 0, 0, 0, ""); - uiDefButC(block, MENU, B_NODE_EXEC, mstr1, - butr->xmin, dy-19, dx, 19, - &nqd->bktype, 0, 0, 0, 0, "Bokeh type"); - if (nqd->bktype) { /* for some reason rotating a disk doesn't seem to work... ;) */ - uiDefButC(block, NUM, B_NODE_EXEC, "Rotate:", - butr->xmin, dy-38, dx, 19, - &nqd->rotation, 0, 90, 0, 0, "Bokeh shape rotation offset in degrees"); - } - uiDefButC(block, TOG, B_NODE_EXEC, "Gamma Correct", - butr->xmin, dy-57, dx, 19, - &nqd->gamco, 0, 0, 0, 0, "Enable gamma correction before and after main process"); - if (nqd->no_zbuf==0) { - // only needed for zbuffer input - uiDefButF(block, NUM, B_NODE_EXEC, "fStop:", - butr->xmin, dy-76, dx, 19, - &nqd->fstop, 0.5, 128, 10, 0, "Amount of focal blur, 128=infinity=perfect focus, half the value doubles the blur radius"); - } - uiDefButF(block, NUM, B_NODE_EXEC, "Maxblur:", - butr->xmin, dy-95, dx, 19, - &nqd->maxblur, 0, 10000, 1000, 0, "blur limit, maximum CoC radius, 0=no limit"); - uiDefButF(block, NUM, B_NODE_EXEC, "BThreshold:", - butr->xmin, dy-114, dx, 19, - &nqd->bthresh, 0, 100, 100, 0, "CoC radius threshold, prevents background bleed on in-focus midground, 0=off"); - uiDefButC(block, TOG, B_NODE_EXEC, "Preview", - butr->xmin, dy-142, dx, 19, - &nqd->preview, 0, 0, 0, 0, "Enable sampling mode, useful for preview when using low samplecounts"); - if (nqd->preview) { - /* only visible when sampling mode enabled */ - uiDefButS(block, NUM, B_NODE_EXEC, "Samples:", - butr->xmin, dy-161, dx, 19, - &nqd->samples, 16, 256, 0, 0, "Number of samples (16=grainy, higher=less noise)"); - } - uiDefButS(block, TOG, B_NODE_EXEC, "No zbuffer", - butr->xmin, dy-190, dx, 19, - &nqd->no_zbuf, 0, 0, 0, 0, "Enable when using an image as input instead of actual zbuffer (auto enabled if node not image based, eg. time node)"); - if (nqd->no_zbuf) { - uiDefButF(block, NUM, B_NODE_EXEC, "Zscale:", - butr->xmin, dy-209, dx, 19, - &nqd->scale, 0, 1000, 100, 0, "Scales the Z input when not using a zbuffer, controls maximum blur designated by the color white or input value 1"); - } + if (RNA_enum_get(ptr, "glare_type")== 1) { + uiItemR(layout, NULL, 0, ptr, "size", 0); } - return 228; } +/* qdn: tonemap node */ +static void node_composit_buts_tonemap(uiLayout *layout, PointerRNA *ptr) +{ + uiLayout *col; -/* qdn: glare node */ -static int node_composit_buts_glare(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) -{ - if(block) { - NodeGlare *ndg = node->storage; - short dy = butr->ymin + 152, dx = butr->xmax - butr->xmin; - char* mn1 = "Type%t|Ghosts%x3|Streaks%x2|Fog Glow%x1|Simple Star%x0"; - char* mn2 = "Quality/Speed%t|High/Slow%x0|Medium/Medium%x1|Low/Fast%x2"; - uiDefButC(block, MENU, B_NODE_EXEC, mn1, - butr->xmin, dy, dx, 19, - &ndg->type, 0, 0, 0, 0, "Glow/Flare/Bloom type"); - uiDefButC(block, MENU, B_NODE_EXEC, mn2, - butr->xmin, dy-19, dx, 19, - &ndg->quality, 0, 0, 0, 0, - "Quality speed trade off, if not set to high quality, effect will be applied to low-res copy of source image"); - if (ndg->type != 1) { - uiDefButC(block, NUM, B_NODE_EXEC, "Iterations:", - butr->xmin, dy-38, dx, 19, - &ndg->iter, 2, 5, 1, 0, - "higher values will generate longer/more streaks/ghosts"); - if (ndg->type != 0) - uiDefButF(block, NUM, B_NODE_EXEC, "ColMod:", - butr->xmin, dy-57, dx, 19, - &ndg->colmod, 0, 1, 10, 0, - "Amount of Color Modulation, modulates colors of streaks and ghosts for a spectral dispersion effect"); - } - uiDefButF(block, NUM, B_NODE_EXEC, "Mix:", - butr->xmin, dy-76, dx, 19, - &ndg->mix, -1, 1, 10, 0, - "Mix balance, -1 is original image only, 0 is exact 50/50 mix, 1 is processed image only"); - uiDefButF(block, NUM, B_NODE_EXEC, "Threshold:", - butr->xmin, dy-95, dx, 19, - &ndg->threshold, 0, 1000, 10, 0, - "Brightness threshold, the glarefilter will be applied only to pixels brighter than this value"); - if ((ndg->type == 2) || (ndg->type == 0)) - { - if (ndg->type == 2) { - uiDefButC(block, NUM, B_NODE_EXEC, "streaks:", - butr->xmin, dy-114, dx, 19, - &ndg->angle, 2, 16, 1000, 0, - "Total number of streaks"); - uiDefButC(block, NUM, B_NODE_EXEC, "AngOfs:", - butr->xmin, dy-133, dx, 19, - &ndg->angle_ofs, 0, 180, 1000, 0, - "Streak angle rotation offset in degrees"); - } - uiDefButF(block, NUM, B_NODE_EXEC, "Fade:", - butr->xmin, dy-152, dx, 19, - &ndg->fade, 0.75, 1, 5, 0, - "Streak fade out factor"); - } - if (ndg->type == 0) - uiDefButC(block, TOG, B_NODE_EXEC, "Rot45", - butr->xmin, dy-114, dx, 19, - &ndg->angle, 0, 0, 0, 0, - "simple star filter, add 45 degree rotation offset"); - if ((ndg->type == 1) || (ndg->type > 3)) // PBGH and fog glow - uiDefButC(block, NUM, B_NODE_EXEC, "Size:", - butr->xmin, dy-114, dx, 19, - &ndg->size, 6, 9, 1000, 0, - "glow/glare size (not actual size, relative to initial size of bright area of pixels)"); + col = uiLayoutColumn(layout, 0); + uiItemR(col, "", 0, ptr, "tonemap_type", 0); + if (RNA_enum_get(ptr, "tonemap_type")== 0) { + uiItemR(col, NULL, 0, ptr, "key", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "offset", 0); + uiItemR(col, NULL, 0, ptr, "gamma", 0); } - return 171; -} - -/* qdn: tonemap node */ -static int node_composit_buts_tonemap(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) -{ - if(block) { - NodeTonemap *ntm = node->storage; - short dy = butr->ymin + 76, dx = butr->xmax - butr->xmin; - char* mn = "Type%t|R/D Photoreceptor%x1|Rh Simple%x0"; - - uiBlockBeginAlign(block); - uiDefButI(block, MENU, B_NODE_EXEC, mn, - butr->xmin, dy, dx, 19, - &ntm->type, 0, 0, 0, 0, - "Tone mapping type"); - if (ntm->type == 0) { - uiDefButF(block, NUM, B_NODE_EXEC, "Key:", - butr->xmin, dy-19, dx, 19, - &ntm->key, 0, 1, 5, 0, - "The value the average luminance is mapped to"); - uiDefButF(block, NUM, B_NODE_EXEC, "Offset:", - butr->xmin, dy-38, dx, 19, - &ntm->offset, 0.001, 10, 5, 0, - "Tonemap offset, normally always 1, but can be used as an extra control to alter the brightness curve"); - uiDefButF(block, NUM, B_NODE_EXEC, "Gamma:", - butr->xmin, dy-57, dx, 19, - &ntm->gamma, 0.001, 3, 5, 0, - "Gamma factor, if not used, set to 1"); - } - else { - uiDefButF(block, NUM, B_NODE_EXEC, "Intensity:", - butr->xmin, dy-19, dx, 19, - &ntm->f, -8, 8, 10, 0, "if less than zero, darkens image, otherwise makes it brighter"); - uiDefButF(block, NUM, B_NODE_EXEC, "Contrast:", - butr->xmin, dy-38, dx, 19, - &ntm->m, 0, 1, 5, 0, "Set to 0 to use estimate from input image"); - uiDefButF(block, NUM, B_NODE_EXEC, "Adaptation:", - butr->xmin, dy-57, dx, 19, - &ntm->a, 0, 1, 5, 0, "if 0, global, if 1, based on pixel intensity"); - uiDefButF(block, NUM, B_NODE_EXEC, "ColCorrect:", - butr->xmin, dy-76, dx, 19, - &ntm->c, 0, 1, 5, 0, "color correction, if 0, same for all channels, if 1, each independent"); - } - uiBlockEndAlign(block); + else { + uiItemR(col, NULL, 0, ptr, "intensity", 0); + uiItemR(col, NULL, 0, ptr, "contrast", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "adaptation", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "correction", UI_ITEM_R_SLIDER); } - return 95; } /* qdn: lens distortion node */ -static int node_composit_buts_lensdist(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_lensdist(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeLensDist *nld = node->storage; - short dy = butr->ymin + 19, dx = butr->xmax - butr->xmin; - uiBlockBeginAlign(block); - uiDefButS(block, TOG, B_NODE_EXEC, "Projector", - butr->xmin, dy, dx, 19, - &nld->proj, 0, 0, 0, 0, - "Enable/disable projector mode, effect is applied in horizontal direction only"); - if (!nld->proj) { - uiDefButS(block, TOG, B_NODE_EXEC, "Jitter", - butr->xmin, dy-19, dx/2, 19, - &nld->jit, 0, 0, 0, 0, - "Enable/disable jittering, faster, but also noisier"); - uiDefButS(block, TOG, B_NODE_EXEC, "Fit", - butr->xmin+dx/2, dy-19, dx/2, 19, - &nld->fit, 0, 0, 0, 0, - "For positive distortion factor only, scale image such that black areas are not visible"); - } - uiBlockEndAlign(block); - } - return 38; -} + uiLayout *col; + col= uiLayoutColumn(layout, 0); + uiItemR(col, NULL, 0, ptr, "projector", 0); -static int node_composit_buts_vecblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) -{ - if(block) { - PointerRNA ptr; - short dy= butr->ymin; - short dx= (butr->xmax-butr->xmin); - - RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr); - - uiBlockBeginAlign(block); - uiDefButR(block, NUM, B_NODE_EXEC, NULL, - butr->xmin, dy+76, dx, 19, - &ptr, "samples", 0, 1, 256, 0, 0, NULL); - uiDefButR(block, NUM, B_NODE_EXEC, NULL, - butr->xmin, dy+57, dx, 19, - &ptr, "min_speed", 0, 0, 1024, 0, 0, NULL); - uiDefButR(block, NUM, B_NODE_EXEC, NULL, - butr->xmin, dy+38, dx, 19, - &ptr, "max_speed", 0, 0, 1024, 0, 0, NULL); - uiDefButR(block, NUM, B_NODE_EXEC, "Blur", - butr->xmin, dy+19, dx, 19, - &ptr, "factor", 0, 0, 2, 10, 2, NULL); - uiDefButR(block, TOG, B_NODE_EXEC, NULL, - butr->xmin, dy, dx, 19, - &ptr, "curved", 0, 0, 2, 10, 2, NULL); - uiBlockEndAlign(block); - } - return 95; + col = uiLayoutColumn(col, 0); + uiLayoutSetActive(col, RNA_boolean_get(ptr, "projector")==0); + uiItemR(col, NULL, 0, ptr, "jitter", 0); + uiItemR(col, NULL, 0, ptr, "fit", 0); } -static int node_composit_buts_filter(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_vecblur(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiBut *bt; - - /* blend type */ - bt=uiDefButS(block, MENU, B_NODE_EXEC, "Soften %x0|Sharpen %x1|Laplace %x2|Sobel %x3|Prewitt %x4|Kirsch %x5|Shadow %x6", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &node->custom1, 0, 0, 0, 0, ""); - uiButSetFunc(bt, node_but_title_cb, node, bt); - } - return 20; + uiLayout *col; + + col= uiLayoutColumn(layout, 0); + uiItemR(col, NULL, 0, ptr, "samples", 0); + uiItemR(col, "Blur", 0, ptr, "factor", 0); + + col= uiLayoutColumn(layout, 1); + uiItemL(col, "Speed:", 0); + uiItemR(col, "Min", 0, ptr, "min_speed", 0); + uiItemR(col, "Max", 0, ptr, "max_speed", 0); + + uiItemR(layout, NULL, 0, ptr, "curved", 0); } -static int node_composit_buts_flip(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_filter(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiBut *bt; - - /* flip x\y */ - bt=uiDefButS(block, MENU, B_NODE_EXEC, "Flip X %x0|Flip Y %x1|Flip X & Y %x2", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &node->custom1, 0, 0, 0, 0, ""); - uiButSetFunc(bt, node_but_title_cb, node, bt); - } - return 20; + uiItemR(layout, "", 0, ptr, "filter_type", 0); } -static int node_composit_buts_crop(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_flip(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeTwoXYs *ntxy= node->storage; - char elementheight = 19; - short dx= (butr->xmax-butr->xmin)/2; - short dy= butr->ymax - elementheight; - short xymin= 0, xymax= 10000; - - uiBlockBeginAlign(block); - - /* crop image size toggle */ - uiDefButS(block, TOG, B_NODE_EXEC, "Crop Image Size", - butr->xmin, dy, dx*2, elementheight, - &node->custom1, 0, 0, 0, 0, "Crop the size of the input image."); - - dy-=elementheight; - - /* x1 */ - uiDefButS(block, NUM, B_NODE_EXEC, "X1:", - butr->xmin, dy, dx, elementheight, - &ntxy->x1, xymin, xymax, 0, 0, ""); - /* y1 */ - uiDefButS(block, NUM, B_NODE_EXEC, "Y1:", - butr->xmin+dx, dy, dx, elementheight, - &ntxy->y1, xymin, xymax, 0, 0, ""); - - dy-=elementheight; - - /* x2 */ - uiDefButS(block, NUM, B_NODE_EXEC, "X2:", - butr->xmin, dy, dx, elementheight, - &ntxy->x2, xymin, xymax, 0, 0, ""); - /* y2 */ - uiDefButS(block, NUM, B_NODE_EXEC, "Y2:", - butr->xmin+dx, dy, dx, elementheight, - &ntxy->y2, xymin, xymax, 0, 0, ""); - - uiBlockEndAlign(block); - } - return 60; + uiItemR(layout, "", 0, ptr, "axis", 0); } -static int node_composit_buts_splitviewer(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_crop(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiBlockBeginAlign(block); - - uiDefButS(block, ROW, B_NODE_EXEC, "X", - butr->xmin, butr->ymin+19, (butr->xmax-butr->xmin)/2, 20, - &node->custom2, 0.0, 0.0, 0, 0, ""); - uiDefButS(block, ROW, B_NODE_EXEC, "Y", - butr->xmin+(butr->xmax-butr->xmin)/2, butr->ymin+19, (butr->xmax-butr->xmin)/2, 20, - &node->custom2, 0.0, 1.0, 0, 0, ""); - - uiDefButS(block, NUMSLI, B_NODE_EXEC, "Split %: ", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 100, 10, 0, ""); - } - return 40; -} - -static int node_composit_buts_map_value(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) -{ - if(block) { - TexMapping *texmap= node->storage; - short xstart= (short)butr->xmin; - short dy= (short)(butr->ymax-19.0f); - short dx= (short)(butr->xmax-butr->xmin)/2; - - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_NODE_EXEC, "Offs:", xstart, dy, 2*dx, 19, texmap->loc, -1000.0f, 1000.0f, 10, 2, ""); - dy-= 19; - uiDefButF(block, NUM, B_NODE_EXEC, "Size:", xstart, dy, 2*dx, 19, texmap->size, -1000.0f, 1000.0f, 10, 3, ""); - dy-= 23; - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC, "Min", xstart, dy, dx, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", xstart+dx, dy, dx, 19, texmap->min, -1000.0f, 1000.0f, 10, 2, ""); - dy-= 19; - uiDefButBitI(block, TOG, TEXMAP_CLIP_MAX, B_NODE_EXEC, "Max", xstart, dy, dx, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, ""); - uiDefButF(block, NUM, B_NODE_EXEC, "", xstart+dx, dy, dx, 19, texmap->max, -1000.0f, 1000.0f, 10, 2, ""); - } - return 80; + uiLayout *col; + + uiItemR(layout, NULL, 0, ptr, "crop_size", 0); + + col= uiLayoutColumn(layout, 1); + uiItemR(col, "Left", 0, ptr, "x1", 0); + uiItemR(col, "Right", 0, ptr, "x2", 0); + uiItemR(col, "Up", 0, ptr, "y1", 0); + uiItemR(col, "Down", 0, ptr, "y2", 0); } -static int node_composit_buts_alphaover(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_splitviewer(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeTwoFloats *ntf= node->storage; - - /* alpha type */ - uiDefButS(block, TOG, B_NODE_EXEC, "ConvertPremul", - butr->xmin, butr->ymin+19, butr->xmax-butr->xmin, 19, - &node->custom1, 0, 0, 0, 0, ""); - /* mix factor */ - uiDefButF(block, NUM, B_NODE_EXEC, "Premul: ", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 19, - &ntf->x, 0.0f, 1.0f, 100, 0, ""); - } - return 38; + uiLayout *row, *col; + + col= uiLayoutColumn(layout, 0); + row= uiLayoutRow(col, 0); + uiItemR(row, NULL, 0, ptr, "axis", UI_ITEM_R_EXPAND); + uiItemR(col, NULL, 0, ptr, "factor", 0); } -static int node_composit_buts_hue_sat(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_map_value(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeHueSat *nhs= node->storage; - - uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_NODE_EXEC, "Hue: ", - butr->xmin, butr->ymin+40.0f, butr->xmax-butr->xmin, 20, - &nhs->hue, 0.0f, 1.0f, 100, 0, ""); - uiDefButF(block, NUMSLI, B_NODE_EXEC, "Sat: ", - butr->xmin, butr->ymin+20.0f, butr->xmax-butr->xmin, 20, - &nhs->sat, 0.0f, 2.0f, 100, 0, ""); - uiDefButF(block, NUMSLI, B_NODE_EXEC, "Val: ", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &nhs->val, 0.0f, 2.0f, 100, 0, ""); - } - return 60; + uiLayout *sub, *col; + + col =uiLayoutColumn(layout, 1); + uiItemR(col, NULL, 0, ptr, "offset", 0); + uiItemR(col, NULL, 0, ptr, "size", 0); + + col =uiLayoutColumn(layout, 1); + uiItemR(col, NULL, 0, ptr, "use_min", 0); + sub =uiLayoutColumn(col, 0); + uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min")); + uiItemR(sub, "", 0, ptr, "min", 0); + + col =uiLayoutColumn(layout, 1); + uiItemR(col, NULL, 0, ptr, "use_max", 0); + sub =uiLayoutColumn(col, 0); + uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max")); + uiItemR(sub, "", 0, ptr, "max", 0); } -static int node_composit_buts_dilateerode(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_alphaover(uiLayout *layout, PointerRNA *ptr) +{ + uiLayout *col; + + col =uiLayoutColumn(layout, 1); + /* alpha type */ + uiItemR(col, NULL, 0, ptr, "convert_premul", 0); + /* mix factor */ + uiItemR(col, NULL, 0, ptr, "premul", 0); +} + +static void node_composit_buts_hue_sat(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiDefButS(block, NUM, B_NODE_EXEC, "Distance:", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &node->custom2, -100, 100, 0, 0, "Distance to grow/shrink (number of iterations)"); - } - return 20; + uiLayout *col; + + col =uiLayoutColumn(layout, 0); + uiItemR(col, NULL, 0, ptr, "hue", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "sat", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "val", UI_ITEM_R_SLIDER); } -static int node_composit_buts_diff_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_dilateerode(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeChroma *c= node->storage; - - uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Tolerance: ", - butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20, - &c->t1, 0.0f, 1.0f, 100, 0, "Color differences below this threshold are keyed."); - uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Falloff: ", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &c->t2, 0.0f, 1.0f, 100, 0, "Color differences below this additional threshold are partially keyed."); - uiBlockEndAlign(block); - } - return 40; + uiItemR(layout, NULL, 0, ptr, "distance", 0); } -static int node_composit_buts_distance_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_diff_matte(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeChroma *c= node->storage; - - uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Tolerance: ", - butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20, - &c->t1, 0.0f, 1.0f, 100, 0, "Color distances below this threshold are keyed."); - uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Falloff: ", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &c->t2, 0.0f, 1.0f, 100, 0, "Color distances below this additional threshold are partially keyed."); - uiBlockEndAlign(block); - } - return 40; + uiLayout *col; + + col =uiLayoutColumn(layout, 1); + uiItemR(col, NULL, 0, ptr, "tolerance", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "falloff", UI_ITEM_R_SLIDER); } -static int node_composit_buts_color_spill(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_distance_matte(uiLayout *layout, PointerRNA *ptr) { - if(block) { - short dx= (butr->xmax-butr->xmin)/3; + uiLayout *col; + + col =uiLayoutColumn(layout, 1); + uiItemR(col, NULL, 0, ptr, "tolerance", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "falloff", UI_ITEM_R_SLIDER); +} - NodeChroma *c=node->storage; - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_NODE_EXEC, "Enhance: ", - butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20, - &c->t1, 0.0f, 0.5f, 100, 2, "Adjusts how much selected channel is affected by color spill algorithm"); - uiDefButS(block, ROW, B_NODE_EXEC, "R", - butr->xmin,butr->ymin,dx,20, - &node->custom1,1,1, 0, 0, "Red Spill Suppression"); - uiDefButS(block, ROW, B_NODE_EXEC, "G", - butr->xmin+dx,butr->ymin,dx,20, - &node->custom1,1,2, 0, 0, "Green Spill Suppression"); - uiDefButS(block, ROW, B_NODE_EXEC, "B", - butr->xmin+2*dx,butr->ymin,dx,20, - &node->custom1, 1, 3, 0, 0, "Blue Spill Suppression"); - uiBlockEndAlign(block); - } - return 60; +static void node_composit_buts_color_spill(uiLayout *layout, PointerRNA *ptr) +{ + uiLayout *row, *col; + + col =uiLayoutColumn(layout, 0); + uiItemR(col, NULL, 0, ptr, "factor", 0); + row= uiLayoutRow(col, 0); + uiItemR(row, NULL, 0, ptr, "channel", UI_ITEM_R_EXPAND); } -static int node_composit_buts_chroma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_chroma_matte(uiLayout *layout, PointerRNA *ptr) { - if(block) { - short dx=(butr->xmax-butr->xmin)/2; - NodeChroma *c= node->storage; - uiBlockBeginAlign(block); + uiLayout *col; + + col= uiLayoutColumn(layout, 0); + uiItemR(col, NULL, 0, ptr, "acceptance", 0); + uiItemR(col, NULL, 0, ptr, "cutoff", 0); + + col= uiLayoutColumn(layout, 1); + uiItemR(col, NULL, 0, ptr, "lift", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "gain", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "shadow_adjust", UI_ITEM_R_SLIDER); - uiDefButF(block, NUMSLI, B_NODE_EXEC, "Acceptance ", - butr->xmin, butr->ymin+60, butr->xmax-butr->xmin, 20, - &c->t1, 1.0f, 80.0f, 100, 0, "Tolerance for colors to be considered a keying color"); - uiDefButF(block, NUMSLI, B_NODE_EXEC, "Cutoff ", - butr->xmin, butr->ymin+40, butr->xmax-butr->xmin, 20, - &c->t2, 0.0f, 30.0f, 100, 0, "Colors below this will be considered as exact matches for keying color"); - - uiDefButF(block, NUMSLI, B_NODE_EXEC, "Lift ", - butr->xmin, butr->ymin+20, dx, 20, - &c->fsize, 0.0f, 1.0f, 100, 0, "Alpha Lift"); - uiDefButF(block, NUMSLI, B_NODE_EXEC, "Gain ", - butr->xmin+dx, butr->ymin+20, dx, 20, - &c->fstrength, 0.0f, 1.0f, 100, 0, "Alpha Gain"); - - uiDefButF(block, NUMSLI, B_NODE_EXEC, "Shadow Adjust ", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &c->t3, 0.0f, 1.0f, 100, 0, "Adjusts the brightness of any shadows captured"); - uiBlockEndAlign(block); +// uiBlock *block= uiLayoutFreeBlock(layout); +// bNode *node= ptr->data; +// rctf *butr= &node->butr; +// short dx=(butr->xmax-butr->xmin)/2; +// NodeChroma *c= node->storage; - if(c->t2 > c->t1) - c->t2=c->t1; - } - return 80; +// uiBlockBeginAlign(block); +// +// uiDefButF(block, NUMSLI, B_NODE_EXEC, "Acceptance ", butr->xmin, butr->ymin+60, butr->xmax-butr->xmin, 20, &c->t1, 1.0f, 80.0f, 100, 0, "Tolerance for colors to be considered a keying color"); +// uiDefButF(block, NUMSLI, B_NODE_EXEC, "Cutoff ", butr->xmin, butr->ymin+40, butr->xmax-butr->xmin, 20, &c->t2, 0.0f, 30.0f, 100, 0, "Colors below this will be considered as exact matches for keying color"); +// +// uiDefButF(block, NUMSLI, B_NODE_EXEC, "Lift ", butr->xmin, butr->ymin+20, dx, 20, &c->fsize, 0.0f, 1.0f, 100, 0, "Alpha Lift"); +// uiDefButF(block, NUMSLI, B_NODE_EXEC, "Gain ", butr->xmin+dx, butr->ymin+20, dx, 20, &c->fstrength, 0.0f, 1.0f, 100, 0, "Alpha Gain"); +// +// uiDefButF(block, NUMSLI, B_NODE_EXEC, "Shadow Adjust ", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &c->t3, 0.0f, 1.0f, 100, 0, "Adjusts the brightness of any shadows captured"); +// uiBlockEndAlign(block); +// +// if(c->t2 > c->t1) +// c->t2=c->t1; } -static int node_composit_buts_color_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_color_matte(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeChroma *c= node->storage; - uiBlockBeginAlign(block); - - uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "H: ", - butr->xmin, butr->ymin+40, butr->xmax-butr->xmin, 20, - &c->t1, 0.0f, 0.25f, 100, 0, "Hue tolerance for colors to be considered a keying color"); - uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "S: ", - butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20, - &c->t2, 0.0f, 1.0f, 100, 0, "Saturation Tolerance for the color"); - uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "V: ", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &c->t3, 0.0f, 1.0f, 100, 0, "Value Tolerance for the color"); - - uiBlockEndAlign(block); - } - return 60; + uiLayout *col; + + col= uiLayoutColumn(layout, 1); + uiItemR(col, NULL, 0, ptr, "h", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "s", UI_ITEM_R_SLIDER); + uiItemR(col, NULL, 0, ptr, "v", UI_ITEM_R_SLIDER); } - -static int node_composit_buts_channel_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_channel_matte(uiLayout *layout, PointerRNA *ptr) { - if(block) { - short sx= (butr->xmax-butr->xmin)/4; - short cx= (butr->xmax-butr->xmin)/3; - NodeChroma *c=node->storage; - char *c1, *c2, *c3; - - /*color space selectors*/ - uiBlockBeginAlign(block); - uiDefButS(block, ROW,B_NODE_EXEC,"RGB", - butr->xmin,butr->ymin+60,sx,20,&node->custom1,1,1, 0, 0, "RGB Color Space"); - uiDefButS(block, ROW,B_NODE_EXEC,"HSV", - butr->xmin+sx,butr->ymin+60,sx,20,&node->custom1,1,2, 0, 0, "HSV Color Space"); - uiDefButS(block, ROW,B_NODE_EXEC,"YUV", - butr->xmin+2*sx,butr->ymin+60,sx,20,&node->custom1,1,3, 0, 0, "YUV Color Space"); - uiDefButS(block, ROW,B_NODE_EXEC,"YCC", - butr->xmin+3*sx,butr->ymin+60,sx,20,&node->custom1,1,4, 0, 0, "YCbCr Color Space"); - - if (node->custom1==1) { - c1="R"; c2="G"; c3="B"; - } - else if(node->custom1==2){ - c1="H"; c2="S"; c3="V"; - } - else if(node->custom1==3){ - c1="Y"; c2="U"; c3="V"; - } - else { // if(node->custom1==4){ - c1="Y"; c2="Cb"; c3="Cr"; - } - - /*channel selector */ - uiDefButS(block, ROW, B_NODE_EXEC, c1, - butr->xmin,butr->ymin+40,cx,20,&node->custom2,1, 1, 0, 0, "Channel 1"); - uiDefButS(block, ROW, B_NODE_EXEC, c2, - butr->xmin+cx,butr->ymin+40,cx,20,&node->custom2,1, 2, 0, 0, "Channel 2"); - uiDefButS(block, ROW, B_NODE_EXEC, c3, - butr->xmin+cx+cx,butr->ymin+40,cx,20,&node->custom2, 1, 3, 0, 0, "Channel 3"); - - /*tolerance sliders */ - uiDefButF(block, NUMSLI, B_NODE_EXEC, "High ", - butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20, - &c->t1, 0.0f, 1.0f, 100, 0, "Values higher than this setting are 100% opaque"); - uiDefButF(block, NUMSLI, B_NODE_EXEC, "Low ", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &c->t2, 0.0f, 1.0f, 100, 0, "Values lower than this setting are 100% keyed"); - uiBlockEndAlign(block); - - /*keep t2 (low) less than t1 (high) */ - if(c->t2 > c->t1) { - c->t2=c->t1; - } + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + short sx= (butr->xmax-butr->xmin)/4; + short cx= (butr->xmax-butr->xmin)/3; + NodeChroma *c=node->storage; + char *c1, *c2, *c3; + + /*color space selectors*/ + uiBlockBeginAlign(block); + uiDefButS(block, ROW,B_NODE_EXEC,"RGB", + butr->xmin,butr->ymin+60,sx,20,&node->custom1,1,1, 0, 0, "RGB Color Space"); + uiDefButS(block, ROW,B_NODE_EXEC,"HSV", + butr->xmin+sx,butr->ymin+60,sx,20,&node->custom1,1,2, 0, 0, "HSV Color Space"); + uiDefButS(block, ROW,B_NODE_EXEC,"YUV", + butr->xmin+2*sx,butr->ymin+60,sx,20,&node->custom1,1,3, 0, 0, "YUV Color Space"); + uiDefButS(block, ROW,B_NODE_EXEC,"YCC", + butr->xmin+3*sx,butr->ymin+60,sx,20,&node->custom1,1,4, 0, 0, "YCbCr Color Space"); + + if (node->custom1==1) { + c1="R"; c2="G"; c3="B"; + } + else if(node->custom1==2){ + c1="H"; c2="S"; c3="V"; + } + else if(node->custom1==3){ + c1="Y"; c2="U"; c3="V"; + } + else { // if(node->custom1==4){ + c1="Y"; c2="Cb"; c3="Cr"; + } + + /*channel selector */ + uiDefButS(block, ROW, B_NODE_EXEC, c1, + butr->xmin,butr->ymin+40,cx,20,&node->custom2,1, 1, 0, 0, "Channel 1"); + uiDefButS(block, ROW, B_NODE_EXEC, c2, + butr->xmin+cx,butr->ymin+40,cx,20,&node->custom2,1, 2, 0, 0, "Channel 2"); + uiDefButS(block, ROW, B_NODE_EXEC, c3, + butr->xmin+cx+cx,butr->ymin+40,cx,20,&node->custom2, 1, 3, 0, 0, "Channel 3"); + + /*tolerance sliders */ + uiDefButF(block, NUMSLI, B_NODE_EXEC, "High ", + butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20, + &c->t1, 0.0f, 1.0f, 100, 0, "Values higher than this setting are 100% opaque"); + uiDefButF(block, NUMSLI, B_NODE_EXEC, "Low ", + butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, + &c->t2, 0.0f, 1.0f, 100, 0, "Values lower than this setting are 100% keyed"); + uiBlockEndAlign(block); + + /*keep t2 (low) less than t1 (high) */ + if(c->t2 > c->t1) { + c->t2=c->t1; } - return 80; } -static int node_composit_buts_luma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_luma_matte(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeChroma *c=node->storage; - - /*tolerance sliders */ - uiDefButF(block, NUMSLI, B_NODE_EXEC, "High ", - butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20, - &c->t1, 0.0f, 1.0f, 100, 0, "Values higher than this setting are 100% opaque"); - uiDefButF(block, NUMSLI, B_NODE_EXEC, "Low ", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &c->t2, 0.0f, 1.0f, 100, 0, "Values lower than this setting are 100% keyed"); - uiBlockEndAlign(block); - - /*keep t2 (low) less than t1 (high) */ - if(c->t2 > c->t1) { - c->t2=c->t1; - } + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + NodeChroma *c=node->storage; + + /*tolerance sliders */ + uiDefButF(block, NUMSLI, B_NODE_EXEC, "High ", + butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20, + &c->t1, 0.0f, 1.0f, 100, 0, "Values higher than this setting are 100% opaque"); + uiDefButF(block, NUMSLI, B_NODE_EXEC, "Low ", + butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, + &c->t2, 0.0f, 1.0f, 100, 0, "Values lower than this setting are 100% keyed"); + uiBlockEndAlign(block); + + /*keep t2 (low) less than t1 (high) */ + if(c->t2 > c->t1) { + c->t2=c->t1; } - return 40; } -static int node_composit_buts_map_uv(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_map_uv(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiDefButS(block, NUM, B_NODE_EXEC, "Alpha:", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &node->custom1, 0, 100, 0, 0, "Conversion percentage of UV differences to Alpha"); - } - return 20; + uiItemR(layout, NULL, 0, ptr, "alpha", 0); } -static int node_composit_buts_id_mask(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_id_mask(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiDefButS(block, NUM, B_NODE_EXEC, "ID:", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &node->custom1, 0, 10000, 0, 0, "Pass Index number to convert to Alpha"); - } - return 20; + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + + uiDefButS(block, NUM, B_NODE_EXEC, "ID:", + butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, + &node->custom1, 0, 10000, 0, 0, "Pass Index number to convert to Alpha"); } /* allocate sufficient! */ @@ -1880,58 +1551,58 @@ static void node_set_image_cb(bContext *C, void *ntree_v, void *node_v) nodeSetActive(ntree, node); } -static int node_composit_buts_file_output(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_file_output(uiLayout *layout, PointerRNA *ptr) { - if(block) { - NodeImageFile *nif= node->storage; - uiBut *bt; - short x= (short)butr->xmin; - short y= (short)butr->ymin; - short w= (short)butr->xmax-butr->xmin; - char str[320]; - - node_imagetype_string(str); - - uiBlockBeginAlign(block); - - bt = uiDefIconBut(block, BUT, B_NODE_SETIMAGE, ICON_FILESEL, - x, y+60, 20, 20, - 0, 0, 0, 0, 0, "Open Fileselect to get Backbuf image"); - uiButSetFunc(bt, node_set_image_cb, ntree, node); - - uiDefBut(block, TEX, B_NOP, "", - 20+x, y+60, w-20, 20, - nif->name, 0.0f, 240.0f, 0, 0, ""); - - uiDefButS(block, MENU, B_NOP, str, - x, y+40, w, 20, - &nif->imtype, 0.0f, 1.0f, 0, 0, ""); - - if(nif->imtype==R_OPENEXR) { - uiDefButBitS(block, TOG, R_OPENEXR_HALF, B_REDR, "Half", - x, y+20, w/2, 20, - &nif->subimtype, 0, 0, 0, 0, ""); - - uiDefButS(block, MENU,B_NOP, "Codec %t|None %x0|Pxr24 (lossy) %x1|ZIP (lossless) %x2|PIZ (lossless) %x3|RLE (lossless) %x4", - x+w/2, y+20, w/2, 20, - &nif->codec, 0, 0, 0, 0, ""); - } - else { - uiDefButS(block, NUM, B_NOP, "Quality: ", - x, y+20, w, 20, - &nif->quality, 10.0f, 100.0f, 10, 0, ""); - } - - /* start frame, end frame */ - uiDefButI(block, NUM, B_NODE_EXEC, "SFra: ", - x, y, w/2, 20, - &nif->sfra, 1, MAXFRAMEF, 10, 0, ""); - uiDefButI(block, NUM, B_NODE_EXEC, "EFra: ", - x+w/2, y, w/2, 20, - &nif->efra, 1, MAXFRAMEF, 10, 0, ""); - + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + bNodeTree *ntree= ptr->id.data; + rctf *butr= &node->butr; + NodeImageFile *nif= node->storage; + uiBut *bt; + short x= (short)butr->xmin; + short y= (short)butr->ymin; + short w= (short)butr->xmax-butr->xmin; + char str[320]; + + node_imagetype_string(str); + + uiBlockBeginAlign(block); + + bt = uiDefIconBut(block, BUT, B_NODE_SETIMAGE, ICON_FILESEL, + x, y+60, 20, 20, + 0, 0, 0, 0, 0, "Open Fileselect to get Backbuf image"); + uiButSetFunc(bt, node_set_image_cb, ntree, node); + + uiDefBut(block, TEX, B_NOP, "", + 20+x, y+60, w-20, 20, + nif->name, 0.0f, 240.0f, 0, 0, ""); + + uiDefButS(block, MENU, B_NOP, str, + x, y+40, w, 20, + &nif->imtype, 0.0f, 1.0f, 0, 0, ""); + + if(nif->imtype==R_OPENEXR) { + uiDefButBitS(block, TOG, R_OPENEXR_HALF, B_REDR, "Half", + x, y+20, w/2, 20, + &nif->subimtype, 0, 0, 0, 0, ""); + + uiDefButS(block, MENU,B_NOP, "Codec %t|None %x0|Pxr24 (lossy) %x1|ZIP (lossless) %x2|PIZ (lossless) %x3|RLE (lossless) %x4", + x+w/2, y+20, w/2, 20, + &nif->codec, 0, 0, 0, 0, ""); } - return 80; + else { + uiDefButS(block, NUM, B_NOP, "Quality: ", + x, y+20, w, 20, + &nif->quality, 10.0f, 100.0f, 10, 0, ""); + } + + /* start frame, end frame */ + uiDefButI(block, NUM, B_NODE_EXEC, "SFra: ", + x, y, w/2, 20, + &nif->sfra, 1, MAXFRAMEF, 10, 0, ""); + uiDefButI(block, NUM, B_NODE_EXEC, "EFra: ", + x+w/2, y, w/2, 20, + &nif->efra, 1, MAXFRAMEF, 10, 0, ""); } static void node_scale_cb(bContext *C, void *node_v, void *unused_v) @@ -1952,68 +1623,36 @@ static void node_scale_cb(bContext *C, void *node_v, void *unused_v) } } -static int node_composit_buts_scale(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_scale(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiBut *bt= uiDefButS(block, MENU, B_NODE_EXEC, "Relative %x0|Absolute %x1|Scene Size % %x2|", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &node->custom1, 0, 0, 0, 0, "Scale new image to absolute pixel size, size relative to the incoming image, or using the 'percent' size of the scene"); - uiButSetFunc(bt, node_scale_cb, node, NULL); - } - return 20; + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + uiBut *bt= uiDefButS(block, MENU, B_NODE_EXEC, "Relative %x0|Absolute %x1|Scene Size % %x2|", + butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, + &node->custom1, 0, 0, 0, 0, "Scale new image to absolute pixel size, size relative to the incoming image, or using the 'percent' size of the scene"); + uiButSetFunc(bt, node_scale_cb, node, NULL); } -static int node_composit_buts_invert(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_invert(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, CMP_CHAN_RGB, B_NODE_EXEC, "RGB", - butr->xmin, butr->ymin, (butr->xmax-butr->xmin)/2, 20, - &node->custom1, 0, 0, 0, 0, ""); - uiDefButBitS(block, TOG, CMP_CHAN_A, B_NODE_EXEC, "A", - butr->xmin+(butr->xmax-butr->xmin)/2, butr->ymin, (butr->xmax-butr->xmin)/2, 20, - &node->custom1, 0, 0, 0, 0, ""); - uiBlockEndAlign(block); - } - return 20; + uiLayout *col; + + col= uiLayoutColumn(layout, 0); + uiItemR(col, NULL, 0, ptr, "rgb", 0); + uiItemR(col, NULL, 0, ptr, "alpha", 0); } -static int node_composit_buts_premulkey(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_premulkey(uiLayout *layout, PointerRNA *ptr) { - if(block) { - uiBut *bt; - - /* blend type */ - bt=uiDefButS(block, MENU, B_NODE_EXEC, "Key to Premul %x0|Premul to Key %x1", - butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, - &node->custom1, 0, 0, 0, 0, "Conversion between premultiplied alpha and key alpha"); - } - return 20; + uiItemR(layout, "", 0, ptr, "mapping", 0); } -static int node_composit_buts_view_levels(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_composit_buts_view_levels(uiLayout *layout, PointerRNA *ptr) { - if(block) { - short sx= (butr->xmax-butr->xmin)/5; - - /*color space selectors*/ - uiBlockBeginAlign(block); - uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"C", - butr->xmin,butr->ymin,sx,20,&node->custom1,1,1, 0, 0, "Combined RGB"); - uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"R", - butr->xmin+sx,butr->ymin,sx,20,&node->custom1,1,2, 0, 0, "Red Channel"); - uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"G", - butr->xmin+2*sx,butr->ymin,sx,20,&node->custom1,1,3, 0, 0, "Green Channel"); - uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"B", - butr->xmin+3*sx,butr->ymin,sx,20,&node->custom1,1,4, 0, 0, "Blue Channel"); - uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"L", - butr->xmin+4*sx,butr->ymin,sx,20,&node->custom1,1,5, 0, 0, "Luminenc Channel"); - uiBlockEndAlign(block); - } - return 20; + uiItemR(layout, NULL, 0, ptr, "color_space", UI_ITEM_R_EXPAND); } - /* only once called */ static void node_composit_set_butfunc(bNodeType *ntype) { @@ -2021,181 +1660,181 @@ static void node_composit_set_butfunc(bNodeType *ntype) /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */ case CMP_NODE_IMAGE: - ntype->butfunc= node_composit_buts_image; + ntype->uifunc= node_composit_buts_image; break; case CMP_NODE_R_LAYERS: - ntype->butfunc= node_composit_buts_renderlayers; + ntype->uifunc= node_composit_buts_renderlayers; break; case CMP_NODE_NORMAL: - ntype->butfunc= node_buts_normal; + ntype->uifunc= node_buts_normal; break; case CMP_NODE_CURVE_VEC: - ntype->butfunc= node_buts_curvevec; + ntype->uifunc= node_buts_curvevec; break; case CMP_NODE_CURVE_RGB: - ntype->butfunc= node_buts_curvecol; + ntype->uifunc= node_buts_curvecol; break; case CMP_NODE_VALUE: - ntype->butfunc= node_buts_value; + ntype->uifunc= node_buts_value; break; case CMP_NODE_RGB: - ntype->butfunc= node_buts_rgb; + ntype->uifunc= node_buts_rgb; break; case CMP_NODE_FLIP: - ntype->butfunc= node_composit_buts_flip; + ntype->uifunc= node_composit_buts_flip; break; case CMP_NODE_SPLITVIEWER: - ntype->butfunc= node_composit_buts_splitviewer; + ntype->uifunc= node_composit_buts_splitviewer; break; case CMP_NODE_MIX_RGB: - ntype->butfunc= node_buts_mix_rgb; + ntype->uifunc= node_buts_mix_rgb; break; case CMP_NODE_VALTORGB: - ntype->butfunc= node_buts_valtorgb; + ntype->uifunc= node_buts_valtorgb; break; case CMP_NODE_CROP: - ntype->butfunc= node_composit_buts_crop; + ntype->uifunc= node_composit_buts_crop; break; case CMP_NODE_BLUR: - ntype->butfunc= node_composit_buts_blur; + ntype->uifunc= node_composit_buts_blur; break; case CMP_NODE_DBLUR: - ntype->butfunc= node_composit_buts_dblur; + ntype->uifunc= node_composit_buts_dblur; break; case CMP_NODE_BILATERALBLUR: - ntype->butfunc= node_composit_buts_bilateralblur; + ntype->uifunc= node_composit_buts_bilateralblur; break; /* qdn: defocus node */ case CMP_NODE_DEFOCUS: - ntype->butfunc = node_composit_buts_defocus; + ntype->uifunc = node_composit_buts_defocus; break; /* qdn: glare node */ case CMP_NODE_GLARE: - ntype->butfunc = node_composit_buts_glare; + ntype->uifunc = node_composit_buts_glare; break; /* qdn: tonemap node */ case CMP_NODE_TONEMAP: - ntype->butfunc = node_composit_buts_tonemap; + ntype->uifunc = node_composit_buts_tonemap; break; /* qdn: lens distortion node */ case CMP_NODE_LENSDIST: - ntype->butfunc = node_composit_buts_lensdist; + ntype->uifunc = node_composit_buts_lensdist; break; case CMP_NODE_VECBLUR: - ntype->butfunc= node_composit_buts_vecblur; + ntype->uifunc= node_composit_buts_vecblur; break; case CMP_NODE_FILTER: - ntype->butfunc= node_composit_buts_filter; + ntype->uifunc= node_composit_buts_filter; break; case CMP_NODE_MAP_VALUE: - ntype->butfunc= node_composit_buts_map_value; + ntype->uifunc= node_composit_buts_map_value; break; case CMP_NODE_TIME: - ntype->butfunc= node_buts_time; + ntype->uifunc= node_buts_time; break; case CMP_NODE_ALPHAOVER: - ntype->butfunc= node_composit_buts_alphaover; + ntype->uifunc= node_composit_buts_alphaover; break; case CMP_NODE_HUE_SAT: - ntype->butfunc= node_composit_buts_hue_sat; + ntype->uifunc= node_composit_buts_hue_sat; break; case CMP_NODE_TEXTURE: - ntype->butfunc= node_buts_texture; + ntype->uifunc= node_buts_texture; break; case CMP_NODE_DILATEERODE: - ntype->butfunc= node_composit_buts_dilateerode; + ntype->uifunc= node_composit_buts_dilateerode; break; case CMP_NODE_OUTPUT_FILE: - ntype->butfunc= node_composit_buts_file_output; + ntype->uifunc= node_composit_buts_file_output; break; case CMP_NODE_DIFF_MATTE: - ntype->butfunc=node_composit_buts_diff_matte; + ntype->uifunc=node_composit_buts_diff_matte; break; case CMP_NODE_DIST_MATTE: - ntype->butfunc=node_composit_buts_distance_matte; + ntype->uifunc=node_composit_buts_distance_matte; break; case CMP_NODE_COLOR_SPILL: - ntype->butfunc=node_composit_buts_color_spill; + ntype->uifunc=node_composit_buts_color_spill; break; case CMP_NODE_CHROMA_MATTE: - ntype->butfunc=node_composit_buts_chroma_matte; + ntype->uifunc=node_composit_buts_chroma_matte; break; case CMP_NODE_COLOR_MATTE: - ntype->butfunc=node_composit_buts_color_matte; + ntype->uifunc=node_composit_buts_color_matte; break; case CMP_NODE_SCALE: - ntype->butfunc= node_composit_buts_scale; + ntype->uifunc= node_composit_buts_scale; break; case CMP_NODE_CHANNEL_MATTE: - ntype->butfunc= node_composit_buts_channel_matte; + ntype->uifunc= node_composit_buts_channel_matte; break; case CMP_NODE_LUMA_MATTE: - ntype->butfunc= node_composit_buts_luma_matte; + ntype->uifunc= node_composit_buts_luma_matte; break; case CMP_NODE_MAP_UV: - ntype->butfunc= node_composit_buts_map_uv; + ntype->uifunc= node_composit_buts_map_uv; break; case CMP_NODE_ID_MASK: - ntype->butfunc= node_composit_buts_id_mask; + ntype->uifunc= node_composit_buts_id_mask; break; case CMP_NODE_MATH: - ntype->butfunc= node_buts_math; + ntype->uifunc= node_buts_math; break; case CMP_NODE_INVERT: - ntype->butfunc= node_composit_buts_invert; + ntype->uifunc= node_composit_buts_invert; break; case CMP_NODE_PREMULKEY: - ntype->butfunc= node_composit_buts_premulkey; + ntype->uifunc= node_composit_buts_premulkey; break; case CMP_NODE_VIEW_LEVELS: - ntype->butfunc=node_composit_buts_view_levels; + ntype->uifunc=node_composit_buts_view_levels; break; default: - ntype->butfunc= NULL; + ntype->uifunc= NULL; } } /* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */ -static int node_texture_buts_bricks(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_texture_buts_bricks(uiLayout *layout, PointerRNA *ptr) { - if(block) { - short w = butr->xmax-butr->xmin; - short ofw = 32; - - uiBlockBeginAlign(block); - - /* Offset */ - uiDefButF( - block, NUM, B_NODE_EXEC, "Offset", - butr->xmin, butr->ymin+20, w-ofw, 20, - &node->custom3, - 0, 1, 0.25, 2, - "Offset amount" ); - uiDefButS( - block, NUM, B_NODE_EXEC, "", - butr->xmin+w-ofw, butr->ymin+20, ofw, 20, - &node->custom1, - 2, 99, 0, 0, - "Offset every N rows" ); - - /* Squash */ - uiDefButF( - block, NUM, B_NODE_EXEC, "Squash", - butr->xmin, butr->ymin+0, w-ofw, 20, - &node->custom4, - 0, 99, 0.25, 2, - "Stretch amount" ); - uiDefButS( - block, NUM, B_NODE_EXEC, "", - butr->xmin+w-ofw, butr->ymin+0, ofw, 20, - &node->custom2, - 2, 99, 0, 0, - "Stretch every N rows" ); - - uiBlockEndAlign(block); - } - return 40; + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + short w = butr->xmax-butr->xmin; + short ofw = 32; + + uiBlockBeginAlign(block); + + /* Offset */ + uiDefButF( + block, NUM, B_NODE_EXEC, "Offset", + butr->xmin, butr->ymin+20, w-ofw, 20, + &node->custom3, + 0, 1, 0.25, 2, + "Offset amount" ); + uiDefButS( + block, NUM, B_NODE_EXEC, "", + butr->xmin+w-ofw, butr->ymin+20, ofw, 20, + &node->custom1, + 2, 99, 0, 0, + "Offset every N rows" ); + + /* Squash */ + uiDefButF( + block, NUM, B_NODE_EXEC, "Squash", + butr->xmin, butr->ymin+0, w-ofw, 20, + &node->custom4, + 0, 99, 0.25, 2, + "Stretch amount" ); + uiDefButS( + block, NUM, B_NODE_EXEC, "", + butr->xmin+w-ofw, butr->ymin+0, ofw, 20, + &node->custom2, + 2, 99, 0, 0, + "Stretch every N rows" ); + + uiBlockEndAlign(block); } /* Copied from buttons_shading.c -- needs unifying */ @@ -2206,208 +1845,196 @@ static char* noisebasis_menu() return nbmenu; } -static int node_texture_buts_proc(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_texture_buts_proc(uiLayout *layout, PointerRNA *ptr) { + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; Tex *tex = (Tex *)node->storage; short x,y,w,h; - if( block ) { - x = butr->xmin; - y = butr->ymin; - w = butr->xmax - x; - h = butr->ymax - y; - } - else - return 0; + x = butr->xmin; + y = butr->ymin; + w = butr->xmax - x; + h = butr->ymax - y; switch( tex->type ) { case TEX_BLEND: - if( block ) { - uiBlockBeginAlign( block ); - uiDefButS( block, MENU, B_NODE_EXEC, - "Linear %x0|Quad %x1|Ease %x2|Diag %x3|Sphere %x4|Halo %x5|Radial %x6", - x, y+20, w, 20, &tex->stype, 0, 1, 0, 0, "Blend Type" ); - uiDefButBitS(block, TOG, TEX_FLIPBLEND, B_NODE_EXEC, "Flip XY", x, y, w, 20, - &tex->flag, 0, 0, 0, 0, "Flips the direction of the progression 90 degrees"); - uiBlockEndAlign( block ); - } - return 40; - + uiBlockBeginAlign( block ); + uiDefButS( block, MENU, B_NODE_EXEC, + "Linear %x0|Quad %x1|Ease %x2|Diag %x3|Sphere %x4|Halo %x5|Radial %x6", + x, y+20, w, 20, &tex->stype, 0, 1, 0, 0, "Blend Type" ); + uiDefButBitS(block, TOG, TEX_FLIPBLEND, B_NODE_EXEC, "Flip XY", x, y, w, 20, + &tex->flag, 0, 0, 0, 0, "Flips the direction of the progression 90 degrees"); + uiBlockEndAlign( block ); + break; case TEX_MARBLE: - if( block ) { - uiBlockBeginAlign(block); + uiBlockBeginAlign(block); + + uiDefButS(block, ROW, B_NODE_EXEC, "Soft", 0*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SOFT, 0, 0, "Uses soft marble"); + uiDefButS(block, ROW, B_NODE_EXEC, "Sharp", 1*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARP, 0, 0, "Uses more clearly defined marble"); + uiDefButS(block, ROW, B_NODE_EXEC, "Sharper", 2*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARPER, 0, 0, "Uses very clearly defined marble"); - uiDefButS(block, ROW, B_NODE_EXEC, "Soft", 0*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SOFT, 0, 0, "Uses soft marble"); - uiDefButS(block, ROW, B_NODE_EXEC, "Sharp", 1*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARP, 0, 0, "Uses more clearly defined marble"); - uiDefButS(block, ROW, B_NODE_EXEC, "Sharper", 2*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARPER, 0, 0, "Uses very clearly defined marble"); - - uiDefButS(block, ROW, B_NODE_EXEC, "Soft noise", 0*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise"); - uiDefButS(block, ROW, B_NODE_EXEC, "Hard noise", 1*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise"); - - uiDefButS(block, ROW, B_NODE_EXEC, "Sin", 0*w/3+x, 0+y, w/3, 18, &tex->noisebasis2, 8.0, 0.0, 0, 0, "Uses a sine wave to produce bands."); - uiDefButS(block, ROW, B_NODE_EXEC, "Saw", 1*w/3+x, 0+y, w/3, 18, &tex->noisebasis2, 8.0, 1.0, 0, 0, "Uses a saw wave to produce bands"); - uiDefButS(block, ROW, B_NODE_EXEC, "Tri", 2*w/3+x, 0+y, w/3, 18, &tex->noisebasis2, 8.0, 2.0, 0, 0, "Uses a triangle wave to produce bands"); - - uiBlockEndAlign(block); - } - return 60; + uiDefButS(block, ROW, B_NODE_EXEC, "Soft noise", 0*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise"); + uiDefButS(block, ROW, B_NODE_EXEC, "Hard noise", 1*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise"); + + uiDefButS(block, ROW, B_NODE_EXEC, "Sin", 0*w/3+x, 0+y, w/3, 18, &tex->noisebasis2, 8.0, 0.0, 0, 0, "Uses a sine wave to produce bands."); + uiDefButS(block, ROW, B_NODE_EXEC, "Saw", 1*w/3+x, 0+y, w/3, 18, &tex->noisebasis2, 8.0, 1.0, 0, 0, "Uses a saw wave to produce bands"); + uiDefButS(block, ROW, B_NODE_EXEC, "Tri", 2*w/3+x, 0+y, w/3, 18, &tex->noisebasis2, 8.0, 2.0, 0, 0, "Uses a triangle wave to produce bands"); + + uiBlockEndAlign(block); + break; case TEX_WOOD: - if( block ) { - uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+64, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis used for turbulence"); - - uiBlockBeginAlign(block); - uiDefButS(block, ROW, B_TEXPRV, "Bands", x, 40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_BANDNOISE, 0, 0, "Uses standard noise"); - uiDefButS(block, ROW, B_TEXPRV, "Rings", w/2+x, 40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_RINGNOISE, 0, 0, "Lets Noise return RGB value"); - - uiDefButS(block, ROW, B_NODE_EXEC, "Sin", 0*w/3+x, 20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_SIN, 0, 0, "Uses a sine wave to produce bands."); - uiDefButS(block, ROW, B_NODE_EXEC, "Saw", 1*w/3+x, 20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_SAW, 0, 0, "Uses a saw wave to produce bands"); - uiDefButS(block, ROW, B_NODE_EXEC, "Tri", 2*w/3+x, 20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_TRI, 0, 0, "Uses a triangle wave to produce bands"); - - uiDefButS(block, ROW, B_NODE_EXEC, "Soft noise", 0*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise"); - uiDefButS(block, ROW, B_NODE_EXEC, "Hard noise", 1*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise"); - uiBlockEndAlign(block); - } - return 80; + uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+64, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis used for turbulence"); + + uiBlockBeginAlign(block); + uiDefButS(block, ROW, B_TEXPRV, "Bands", x, 40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_BANDNOISE, 0, 0, "Uses standard noise"); + uiDefButS(block, ROW, B_TEXPRV, "Rings", w/2+x, 40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_RINGNOISE, 0, 0, "Lets Noise return RGB value"); + + uiDefButS(block, ROW, B_NODE_EXEC, "Sin", 0*w/3+x, 20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_SIN, 0, 0, "Uses a sine wave to produce bands."); + uiDefButS(block, ROW, B_NODE_EXEC, "Saw", 1*w/3+x, 20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_SAW, 0, 0, "Uses a saw wave to produce bands"); + uiDefButS(block, ROW, B_NODE_EXEC, "Tri", 2*w/3+x, 20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_TRI, 0, 0, "Uses a triangle wave to produce bands"); + + uiDefButS(block, ROW, B_NODE_EXEC, "Soft noise", 0*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise"); + uiDefButS(block, ROW, B_NODE_EXEC, "Hard noise", 1*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise"); + uiBlockEndAlign(block); + break; case TEX_CLOUDS: - if( block ) { - uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+60, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis used for turbulence"); - - uiBlockBeginAlign(block); - uiDefButS(block, ROW, B_TEXPRV, "B/W", x, y+38, w/2, 18, &tex->stype, 2.0, (float)TEX_DEFAULT, 0, 0, "Uses standard noise"); - uiDefButS(block, ROW, B_TEXPRV, "Color", w/2+x, y+38, w/2, 18, &tex->stype, 2.0, (float)TEX_COLOR, 0, 0, "Lets Noise return RGB value"); - uiDefButS(block, ROW, B_TEXPRV, "Soft", x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise"); - uiDefButS(block, ROW, B_TEXPRV, "Hard", w/2+x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise"); - uiBlockEndAlign(block); - - uiDefButS(block, NUM, B_TEXPRV, "Depth:", x, y, w, 18, &tex->noisedepth, 0.0, 6.0, 0, 0, "Sets the depth of the cloud calculation"); - } - return 80; + uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+60, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis used for turbulence"); + + uiBlockBeginAlign(block); + uiDefButS(block, ROW, B_TEXPRV, "B/W", x, y+38, w/2, 18, &tex->stype, 2.0, (float)TEX_DEFAULT, 0, 0, "Uses standard noise"); + uiDefButS(block, ROW, B_TEXPRV, "Color", w/2+x, y+38, w/2, 18, &tex->stype, 2.0, (float)TEX_COLOR, 0, 0, "Lets Noise return RGB value"); + uiDefButS(block, ROW, B_TEXPRV, "Soft", x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise"); + uiDefButS(block, ROW, B_TEXPRV, "Hard", w/2+x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise"); + uiBlockEndAlign(block); + + uiDefButS(block, NUM, B_TEXPRV, "Depth:", x, y, w, 18, &tex->noisedepth, 0.0, 6.0, 0, 0, "Sets the depth of the cloud calculation"); + break; case TEX_DISTNOISE: - if( block ) { - uiBlockBeginAlign(block); - uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+18, w, 18, &tex->noisebasis2, 0,0,0,0, "Sets the noise basis to distort"); - uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis which does the distortion"); - uiBlockEndAlign(block); - } - return 36; + uiBlockBeginAlign(block); + uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+18, w, 18, &tex->noisebasis2, 0,0,0,0, "Sets the noise basis to distort"); + uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis which does the distortion"); + uiBlockEndAlign(block); + break; } - return 0; } -static int node_texture_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_texture_buts_image(uiLayout *layout, PointerRNA *ptr) { + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + bNodeTree *ntree= ptr->id.data; + rctf *butr= &node->butr; char *strp; uiBut *bt; + + uiBlockBeginAlign(block); - if( block ) { - uiBlockBeginAlign(block); - - /* browse button */ - IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL); - node->menunr= 0; - bt= uiDefButS(block, MENU, B_NOP, strp, - butr->xmin, butr->ymin, 19, 19, - &node->menunr, 0, 0, 0, 0, "Browses existing choices"); - uiButSetFunc(bt, node_browse_image_cb, ntree, node); - if(strp) MEM_freeN(strp); + /* browse button */ + IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL); + node->menunr= 0; + bt= uiDefButS(block, MENU, B_NOP, strp, + butr->xmin, butr->ymin, 19, 19, + &node->menunr, 0, 0, 0, 0, "Browses existing choices"); + uiButSetFunc(bt, node_browse_image_cb, ntree, node); + if(strp) MEM_freeN(strp); + + /* Add New button */ + if(node->id==NULL) { + bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New", + butr->xmin+19, butr->ymin, (short)(butr->xmax-butr->xmin-19.0f), 19, + NULL, 0.0, 0.0, 0, 0, "Add new Image"); + uiButSetFunc(bt, node_active_cb, ntree, node); + } + else { + /* name button */ + short xmin= (short)butr->xmin, xmax= (short)butr->xmax; + short width= xmax - xmin - 19; - /* Add New button */ - if(node->id==NULL) { - bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New", - butr->xmin+19, butr->ymin, (short)(butr->xmax-butr->xmin-19.0f), 19, - NULL, 0.0, 0.0, 0, 0, "Add new Image"); - uiButSetFunc(bt, node_active_cb, ntree, node); - } - else { - /* name button */ - short xmin= (short)butr->xmin, xmax= (short)butr->xmax; - short width= xmax - xmin - 19; - - bt= uiDefBut(block, TEX, B_NOP, "IM:", - xmin+19, butr->ymin, width, 19, - node->id->name+2, 0.0, 19.0, 0, 0, "Image name"); - uiButSetFunc(bt, node_ID_title_cb, node, NULL); - } + bt= uiDefBut(block, TEX, B_NOP, "IM:", + xmin+19, butr->ymin, width, 19, + node->id->name+2, 0.0, 19.0, 0, 0, "Image name"); + uiButSetFunc(bt, node_ID_title_cb, node, NULL); } - return 20; } -static int node_texture_buts_output(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) +static void node_texture_buts_output(uiLayout *layout, PointerRNA *ptr) { - if( block ) { - uiBut *bt; - short width; - char *name = ((TexNodeOutput*)node->storage)->name; - - uiBlockBeginAlign(block); - - width = (short)(butr->xmax - butr->xmin); - - bt = uiDefBut( - block, TEX, B_NOP, - "Name:", - butr->xmin, butr->ymin, - width, 19, - name, 0, 31, - 0, 0, - "Name this output" - ); - - uiBlockEndAlign(block); - } - return 19; + uiBlock *block= uiLayoutFreeBlock(layout); + bNode *node= ptr->data; + rctf *butr= &node->butr; + uiBut *bt; + short width; + char *name = ((TexNodeOutput*)node->storage)->name; + + uiBlockBeginAlign(block); + + width = (short)(butr->xmax - butr->xmin); + + bt = uiDefBut( + block, TEX, B_NOP, + "Name:", + butr->xmin, butr->ymin, + width, 19, + name, 0, 31, + 0, 0, + "Name this output" + ); + + uiBlockEndAlign(block); } /* only once called */ static void node_texture_set_butfunc(bNodeType *ntype) { if( ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX ) { - ntype->butfunc = node_texture_buts_proc; + ntype->uifunc = node_texture_buts_proc; } else switch(ntype->type) { case TEX_NODE_MATH: - ntype->butfunc = node_buts_math; + ntype->uifunc = node_buts_math; break; case TEX_NODE_MIX_RGB: - ntype->butfunc = node_buts_mix_rgb; + ntype->uifunc = node_buts_mix_rgb; break; case TEX_NODE_VALTORGB: - ntype->butfunc = node_buts_valtorgb; + ntype->uifunc = node_buts_valtorgb; break; case TEX_NODE_CURVE_RGB: - ntype->butfunc= node_buts_curvecol; + ntype->uifunc= node_buts_curvecol; break; case TEX_NODE_CURVE_TIME: - ntype->butfunc = node_buts_time; + ntype->uifunc = node_buts_time; break; case TEX_NODE_TEXTURE: - ntype->butfunc = node_buts_texture; + ntype->uifunc = node_buts_texture; break; case TEX_NODE_BRICKS: - ntype->butfunc = node_texture_buts_bricks; + ntype->uifunc = node_texture_buts_bricks; break; case TEX_NODE_IMAGE: - ntype->butfunc = node_texture_buts_image; + ntype->uifunc = node_texture_buts_image; break; case TEX_NODE_OUTPUT: - ntype->butfunc = node_texture_buts_output; + ntype->uifunc = node_texture_buts_output; break; default: - ntype->butfunc= NULL; + ntype->uifunc= NULL; } } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index f3df7a29c2e..1d57f4e0d4c 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -81,6 +81,8 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "RNA_access.h" + #include "CMP_node.h" #include "SHD_node.h" @@ -91,6 +93,50 @@ extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select); extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad); extern void ui_draw_tria_icon(float x, float y, float aspect, char dir); +void ED_node_changed_update(bContext *C, bNode *node) +{ + SpaceNode *snode= CTX_wm_space_node(C); + + if(!snode) + return; + + if(snode->treetype==NTREE_SHADER) { + WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, snode->id); + } + else if(snode->treetype==NTREE_COMPOSIT) { + NodeTagChanged(snode->edittree, node); + /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */ + + /* not the best implementation of the world... but we need it to work now :) */ + if(node->type==CMP_NODE_R_LAYERS && node->custom2) { + /* add event for this window (after render curarea can be changed) */ + //addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); + + //composite_node_render(snode, node); + //snode_handle_recalc(snode); + + /* add another event, a render can go fullscreen and open new window */ + //addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); + } + else { + node= node_tree_get_editgroup(snode->nodetree); + if(node) + NodeTagIDChanged(snode->nodetree, node->id); + } + WM_event_add_notifier(C, NC_SCENE|ND_NODES, CTX_data_scene(C)); + } + else if(snode->treetype==NTREE_TEXTURE) { + WM_event_add_notifier(C, NC_TEXTURE|ND_NODES, snode->id); + } + +} + +static void do_node_internal_buttons(bContext *C, void *node_v, int event) +{ + if(event==B_NODE_EXEC) + ED_node_changed_update(C, node_v); +} + static void node_scaling_widget(int color_id, float aspect, float xmin, float ymin, float xmax, float ymax) { @@ -110,10 +156,14 @@ static void node_scaling_widget(int color_id, float aspect, float xmin, float ym } /* based on settings in node, sets drawing rect info. each redraw! */ -static void node_update(bNode *node) +static void node_update(const bContext *C, bNodeTree *ntree, bNode *node) { + uiLayout *layout; + PointerRNA ptr; bNodeSocket *nsock; float dy= node->locy; + int buty; + char str[32]; /* header */ dy-= NODE_DY; @@ -121,7 +171,7 @@ static void node_update(bNode *node) /* little bit space in top */ if(node->outputs.first) dy-= NODE_DYS/2; - + /* output sockets */ for(nsock= node->outputs.first; nsock; nsock= nsock->next) { if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { @@ -130,9 +180,9 @@ static void node_update(bNode *node) dy-= NODE_DY; } } - - node->prvr.xmin= node->butr.xmin= node->locx + NODE_DYS; - node->prvr.xmax= node->butr.xmax= node->locx + node->width- NODE_DYS; + + node->prvr.xmin= node->locx + NODE_DYS; + node->prvr.xmax= node->locx + node->width- NODE_DYS; /* preview rect? */ if(node->flag & NODE_PREVIEW) { @@ -176,16 +226,35 @@ static void node_update(bNode *node) /* XXX ugly hack, typeinfo for group is generated */ if(node->type == NODE_GROUP) - ; // XXX node->typeinfo->butfunc= node_buts_group; + ; // XXX node->typeinfo->uifunc= node_buts_group; + + /* ui block */ + sprintf(str, "node buttons %p", node); + node->block= uiBeginBlock(C, CTX_wm_region(C), str, UI_EMBOSS); + uiBlockSetHandleFunc(node->block, do_node_internal_buttons, node); /* buttons rect? */ - if((node->flag & NODE_OPTIONS) && node->typeinfo->butfunc) { + if((node->flag & NODE_OPTIONS) && node->typeinfo->uifunc) { dy-= NODE_DYS/2; - node->butr.ymax= dy; - node->butr.ymin= dy - (float)node->typeinfo->butfunc(NULL, NULL, node, NULL); - dy= node->butr.ymin - NODE_DYS/2; + + /* set this for uifunc() that don't use layout engine yet */ + node->butr.xmin= 0; + node->butr.xmax= node->width - 2*NODE_DYS; + node->butr.ymin= 0; + node->butr.ymax= 0; + + RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr); + + layout= uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, + node->locx+NODE_DYS, dy, node->butr.xmax, 20, U.uistyles.first); + + node->typeinfo->uifunc(layout, &ptr); + uiBlockEndAlign(node->block); + uiBlockLayoutResolve(node->block, NULL, &buty); + + dy= buty - NODE_DYS/2; } - + /* input sockets */ for(nsock= node->inputs.first; nsock; nsock= nsock->next) { if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { @@ -198,7 +267,7 @@ static void node_update(bNode *node) /* little bit space in end */ if(node->inputs.first || (node->flag & (NODE_OPTIONS|NODE_PREVIEW))==0 ) dy-= NODE_DYS/2; - + node->totr.xmin= node->locx; node->totr.xmax= node->locx + node->width; node->totr.ymax= node->locy; @@ -206,11 +275,12 @@ static void node_update(bNode *node) } /* based on settings in node, sets drawing rect info. each redraw! */ -static void node_update_hidden(bNode *node) +static void node_update_hidden(const bContext *C, bNode *node) { bNodeSocket *nsock; float rad, drad, hiddenrad= HIDDEN_RAD; int totin=0, totout=0, tot; + char str[32]; /* calculate minimal radius */ for(nsock= node->inputs.first; nsock; nsock= nsock->next) @@ -251,6 +321,11 @@ static void node_update_hidden(bNode *node) rad+= drad; } } + + /* ui block */ + sprintf(str, "node buttons %p", node); + node->block= uiBeginBlock(C, CTX_wm_region(C), str, UI_EMBOSS); + uiBlockSetHandleFunc(node->block, do_node_internal_buttons, node); } static int node_get_colorid(bNode *node) @@ -275,7 +350,7 @@ static int node_get_colorid(bNode *node) /* based on settings in node, sets drawing rect info. each redraw! */ /* note: this assumes only 1 group at a time is drawn (linked data) */ /* in node->totr the entire boundbox for the group is stored */ -static void node_update_group(bNode *gnode) +static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode) { bNodeTree *ngroup= (bNodeTree *)gnode->id; bNode *node; @@ -288,9 +363,9 @@ static void node_update_group(bNode *gnode) node->locx+= gnode->locx; node->locy+= gnode->locy; if(node->flag & NODE_HIDDEN) - node_update_hidden(node); + node_update_hidden(C, node); else - node_update(node); + node_update(C, ntree, node); node->locx-= gnode->locx; node->locy-= gnode->locy; } @@ -492,6 +567,7 @@ static uiBlock *socket_vector_menu(bContext *C, ARegion *ar, void *socket_v) } block= uiBeginBlock(C, ar, "socket menu", UI_EMBOSS); + uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN); /* use this for a fake extra empy space around the buttons */ uiDefBut(block, LABEL, 0, "", -4, -4, 188, 68, NULL, 0, 0, 0, 0, ""); @@ -575,61 +651,15 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) } -static void do_node_internal_buttons(bContext *C, void *node_v, int event) -{ - SpaceNode *snode= CTX_wm_space_node(C); - - if(event==B_NODE_EXEC) { - if(snode->treetype==NTREE_SHADER) { - WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, snode->id); - } - else if(snode->treetype==NTREE_COMPOSIT) { - bNode *node= node_v; - - NodeTagChanged(snode->edittree, node); - /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */ - - /* not the best implementation of the world... but we need it to work now :) */ - if(node->type==CMP_NODE_R_LAYERS && node->custom2) { - /* add event for this window (after render curarea can be changed) */ - //addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); - - //composite_node_render(snode, node); - //snode_handle_recalc(snode); - - /* add another event, a render can go fullscreen and open new window */ - //addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); - } - else { - node= snode_get_editgroup(snode); - if(node) - NodeTagIDChanged(snode->nodetree, node->id); - } - WM_event_add_notifier(C, NC_SCENE|ND_NODES, CTX_data_scene(C)); - } - else if(snode->treetype==NTREE_TEXTURE) { - WM_event_add_notifier(C, NC_TEXTURE|ND_NODES, snode->id); - } - } - -} - static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNode *node) { bNodeSocket *sock; - uiBlock *block; uiBut *bt; rctf *rct= &node->totr; float /*slen,*/ iconofs; int /*ofs,*/ color_id= node_get_colorid(node); char showname[128]; /* 128 used below */ View2D *v2d = &ar->v2d; - char str[32]; - - /* make unique block name, also used for handling blocks in editnode.c */ - sprintf(str, "node buttons %p", node); - block= uiBeginBlock(C, ar, str, UI_EMBOSS); - uiBlockSetHandleFunc(block, do_node_internal_buttons, node); uiSetRoundBox(15-4); ui_dropshadow(rct, BASIS_RAD, snode->aspect, node->flag & SELECT); @@ -715,7 +745,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN else BLI_strncpy(showname, node->name, 128); - uiDefBut(block, LABEL, 0, showname, (short)(rct->xmin+15), (short)(rct->ymax-NODE_DY), + uiDefBut(node->block, LABEL, 0, showname, (short)(rct->xmin+15), (short)(rct->ymax-NODE_DY), (int)(iconofs - rct->xmin-18.0f), NODE_DY, NULL, 0, 0, 0, 0, ""); /* body */ @@ -743,7 +773,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN /* hurmf... another candidate for callback, have to see how this works first */ - if(node->id && block && snode->treetype==NTREE_SHADER) + if(node->id && node->block && snode->treetype==NTREE_SHADER) nodeShaderSynchronizeID(node, 0); /* socket inputs, buttons */ @@ -751,38 +781,38 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { socket_circle_draw(sock, NODE_SOCKSIZE); - if(block && sock->link==NULL) { + if(node->block && sock->link==NULL) { float *butpoin= sock->ns.vec; if(sock->type==SOCK_VALUE) { - bt= uiDefButF(block, NUM, B_NODE_EXEC, sock->name, + bt= uiDefButF(node->block, NUM, B_NODE_EXEC, sock->name, (short)sock->locx+NODE_DYS, (short)(sock->locy)-9, (short)node->width-NODE_DY, 17, butpoin, sock->ns.min, sock->ns.max, 10, 2, ""); uiButSetFunc(bt, node_sync_cb, snode, node); } else if(sock->type==SOCK_VECTOR) { - uiDefBlockBut(block, socket_vector_menu, sock, sock->name, + uiDefBlockBut(node->block, socket_vector_menu, sock, sock->name, (short)sock->locx+NODE_DYS, (short)sock->locy-9, (short)node->width-NODE_DY, 17, ""); } - else if(block && sock->type==SOCK_RGBA) { + else if(node->block && sock->type==SOCK_RGBA) { short labelw= (short)node->width-NODE_DY-40, width; if(labelw>0) width= 40; else width= (short)node->width-NODE_DY; - bt= uiDefButF(block, COL, B_NODE_EXEC, "", + bt= uiDefButF(node->block, COL, B_NODE_EXEC, "", (short)(sock->locx+NODE_DYS), (short)sock->locy-8, width, 15, butpoin, 0, 0, 0, 0, ""); uiButSetFunc(bt, node_sync_cb, snode, node); - if(labelw>0) uiDefBut(block, LABEL, 0, sock->name, + if(labelw>0) uiDefBut(node->block, LABEL, 0, sock->name, (short)(sock->locx+NODE_DYS) + 40, (short)sock->locy-8, labelw, 15, NULL, 0, 0, 0, 0, ""); } } else { - uiDefBut(block, LABEL, 0, sock->name, (short)(sock->locx+3.0f), (short)(sock->locy-9.0f), + uiDefBut(node->block, LABEL, 0, sock->name, (short)(sock->locx+3.0f), (short)(sock->locy-9.0f), (short)(node->width-NODE_DY), NODE_DY, NULL, 0, 0, 0, 0, ""); } } @@ -803,7 +833,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN slen= snode->aspect*UI_GetStringWidth(sock->name+ofs); } - uiDefBut(block, LABEL, 0, sock->name+ofs, (short)(sock->locx-15.0f-slen), (short)(sock->locy-9.0f), + uiDefBut(node->block, LABEL, 0, sock->name+ofs, (short)(sock->locx-15.0f-slen), (short)(sock->locy-9.0f), (short)(node->width-NODE_DY), NODE_DY, NULL, 0, 0, 0, 0, ""); } } @@ -813,33 +843,19 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN if(node->preview && node->preview->rect) node_draw_preview(node->preview, &node->prvr); - /* buttons */ - if(node->flag & NODE_OPTIONS) { - if(block) { - if(node->typeinfo->butfunc) { - node->typeinfo->butfunc(block, snode->nodetree, node, &node->butr); - } - } - } - - uiEndBlock(C, block); - uiDrawBlock(C, block); + uiEndBlock(C, node->block); + uiDrawBlock(C, node->block); + node->block= NULL; } static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNode *node) { - uiBlock *block; bNodeSocket *sock; rctf *rct= &node->totr; float dx, centy= 0.5f*(rct->ymax+rct->ymin); float hiddenrad= 0.5f*(rct->ymax-rct->ymin); int color_id= node_get_colorid(node); - char str[32], showname[128]; /* 128 is used below */ - - /* make unique block name, also used for handling blocks in editnode.c */ - sprintf(str, "node buttons %p", node); - block= uiBeginBlock(C, ar, str, UI_EMBOSS); - uiBlockSetHandleFunc(block, do_node_internal_buttons, node); + char showname[128]; /* 128 is used below */ /* shadow */ uiSetRoundBox(15); @@ -884,7 +900,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b else BLI_strncpy(showname, node->name, 128); - uiDefBut(block, LABEL, 0, showname, (short)(rct->xmin+15), (short)(centy-10), + uiDefBut(node->block, LABEL, 0, showname, (short)(rct->xmin+15), (short)(centy-10), (int)(rct->xmax - rct->xmin-18.0f -12.0f), NODE_DY, NULL, 0, 0, 0, 0, ""); } @@ -910,9 +926,9 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b socket_circle_draw(sock, NODE_SOCKSIZE); } - uiEndBlock(C, block); - uiDrawBlock(C, block); - + uiEndBlock(C, node->block); + uiDrawBlock(C, node->block); + node->block= NULL; } static void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree) @@ -1081,11 +1097,11 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d) /* for now, we set drawing coordinates on each redraw */ for(node= snode->nodetree->nodes.first; node; node= node->next) { if(node->flag & NODE_GROUP_EDIT) - node_update_group(node); + node_update_group(C, snode->nodetree, node); else if(node->flag & NODE_HIDDEN) - node_update_hidden(node); + node_update_hidden(C, node); else - node_update(node); + node_update(C, snode->nodetree, node); } node_draw_nodetree(C, ar, snode, snode->nodetree); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 159a4036914..5fc09408229 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -58,6 +58,7 @@ #include "BKE_material.h" #include "BKE_paint.h" #include "BKE_texture.h" +#include "BKE_report.h" #include "BKE_scene.h" #include "BKE_utildefines.h" @@ -84,6 +85,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "UI_interface.h" #include "UI_view2d.h" #include "node_intern.h" @@ -327,12 +329,12 @@ static void set_node_imagepath(char *str) /* called from fileselect */ #endif /* 0 */ -bNode *snode_get_editgroup(SpaceNode *snode) +bNode *node_tree_get_editgroup(bNodeTree *nodetree) { bNode *gnode; /* get the groupnode */ - for(gnode= snode->nodetree->nodes.first; gnode; gnode= gnode->next) + for(gnode= nodetree->nodes.first; gnode; gnode= gnode->next) if(gnode->flag & NODE_GROUP_EDIT) break; return gnode; @@ -441,7 +443,7 @@ static void composit_node_event(SpaceNode *snode, short event) addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); } else { - node= snode_get_editgroup(snode); + node= node_tree_get_editgroup(snode->nodetree); if(node) NodeTagIDChanged(snode->nodetree, node->id); @@ -722,7 +724,7 @@ void node_set_active(SpaceNode *snode, bNode *node) NodeTagChanged(snode->edittree, node); /* if inside group, tag entire group */ - gnode= snode_get_editgroup(snode); + gnode= node_tree_get_editgroup(snode->nodetree); if(gnode) NodeTagIDChanged(snode->nodetree, gnode->id); @@ -753,6 +755,8 @@ void node_set_active(SpaceNode *snode, bNode *node) #endif /* 0 */ } +/* ***************** Edit Group operator ************* */ + void snode_make_group_editable(SpaceNode *snode, bNode *gnode) { bNode *node; @@ -768,12 +772,9 @@ void snode_make_group_editable(SpaceNode *snode, bNode *gnode) } if(gnode && gnode->type==NODE_GROUP && gnode->id) { - if(gnode->id->lib) { - // XXX if(okee("Make Group Local")) - // ntreeMakeLocal((bNodeTree *)gnode->id); - // else - return; - } + if(gnode->id->lib) + ntreeMakeLocal((bNodeTree *)gnode->id); + gnode->flag |= NODE_GROUP_EDIT; snode->edittree= (bNodeTree *)gnode->id; @@ -794,43 +795,102 @@ void snode_make_group_editable(SpaceNode *snode, bNode *gnode) // XXX BIF_preview_changed(-1); /* temp hack to force texture preview to update */ } +} + +static int node_group_edit_exec(bContext *C, wmOperator *op) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNode *gnode; + + gnode= nodeGetActive(snode->edittree); + snode_make_group_editable(snode, gnode); + + WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); + + return OPERATOR_FINISHED; +} + +static int node_group_edit_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNode *gnode; + + gnode= nodeGetActive(snode->edittree); + if(gnode && gnode->type==NODE_GROUP && gnode->id && gnode->id->lib) { + uiPupMenuOkee(C, op->type->idname, "Make group local?"); + return OPERATOR_CANCELLED; + } + + return node_group_edit_exec(C, op); +} + +void NODE_OT_group_edit(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Edit Group"; + ot->description = "Edit node group."; + ot->idname = "NODE_OT_group_edit"; - // allqueue(REDRAWNODE, 0); + /* api callbacks */ + ot->invoke = node_group_edit_invoke; + ot->exec = node_group_edit_exec; + ot->poll = ED_operator_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; } -#if 0 +/* ******************** Ungroup operator ********************** */ -void node_ungroup(SpaceNode *snode) +static int node_group_ungroup_exec(bContext *C, wmOperator *op) { + SpaceNode *snode = CTX_wm_space_node(C); bNode *gnode; /* are we inside of a group? */ - gnode= snode_get_editgroup(snode); + gnode= node_tree_get_editgroup(snode->nodetree); if(gnode) snode_make_group_editable(snode, NULL); gnode= nodeGetActive(snode->edittree); - if(gnode==NULL) return; + if(gnode==NULL) + return OPERATOR_CANCELLED; - if(gnode->type!=NODE_GROUP) - error("Not a group"); - else { - if(nodeGroupUnGroup(snode->edittree, gnode)) { - - // allqueue(REDRAWNODE, 0); - } - else - error("Can't ungroup"); + if(gnode->type!=NODE_GROUP) { + BKE_report(op->reports, RPT_ERROR, "Not a group"); + return OPERATOR_CANCELLED; + } + else if(!nodeGroupUnGroup(snode->edittree, gnode)) { + BKE_report(op->reports, RPT_ERROR, "Can't ungroup"); + return OPERATOR_CANCELLED; } + + WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); + + return OPERATOR_FINISHED; +} + +void NODE_OT_group_ungroup(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Ungroup"; + ot->description = "Ungroup selected nodes."; + ot->idname = "NODE_OT_group_ungroup"; + + /* api callbacks */ + ot->exec = node_group_ungroup_exec; + ot->poll = ED_operator_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; } -#endif /* 0 */ /* when links in groups change, inputs/outputs change, nodes added/deleted... */ -static void snode_verify_groups(SpaceNode *snode) +static void node_tree_verify_groups(bNodeTree *nodetree) { bNode *gnode; - gnode= snode_get_editgroup(snode); + gnode= node_tree_get_editgroup(nodetree); /* does all materials */ if(gnode) @@ -1156,7 +1216,7 @@ static int node_resize_invoke(bContext *C, wmOperator *op, wmEvent *event) nsw->oldwidth= node->width; /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -1263,7 +1323,7 @@ static void node_hide_unhide_sockets(SpaceNode *snode, bNode *node) sock->flag &= ~SOCK_HIDDEN; } else { - bNode *gnode= snode_get_editgroup(snode); + bNode *gnode= node_tree_get_editgroup(snode->nodetree); /* hiding inside group should not break links in other group users */ if(gnode) { @@ -1291,7 +1351,7 @@ static void node_hide_unhide_sockets(SpaceNode *snode, bNode *node) } // allqueue(REDRAWNODE, 1); - snode_verify_groups(snode); + node_tree_verify_groups(snode->nodetree); } @@ -1418,7 +1478,7 @@ void node_active_link_viewer(SpaceNode *snode) float mx=0, my=0; // XXX short mval[2]; - gnode= snode_get_editgroup(snode); + gnode= node_tree_get_editgroup(snode->nodetree); if(gnode==NULL) return 0; // XXX getmouseco_areawin(mval); @@ -1618,13 +1678,13 @@ bNode *node_add_node(SpaceNode *snode, Scene *scene, int type, float locx, float node->locy= locy + 60.0f; // arbitrary.. so its visible node->flag |= SELECT; - gnode= snode_get_editgroup(snode); + gnode= node_tree_get_editgroup(snode->nodetree); if(gnode) { node->locx -= gnode->locx; node->locy -= gnode->locy; } - snode_verify_groups(snode); + node_tree_verify_groups(snode->nodetree); node_set_active(snode, node); if(snode->nodetree->type==NTREE_COMPOSIT) { @@ -1654,7 +1714,7 @@ void node_mute(SpaceNode *snode) bNode *node; /* no disabling inside of groups */ - if(snode_get_editgroup(snode)) + if(node_tree_get_editgroup(snode->nodetree)) return; for(node= snode->edittree->nodes.first; node; node= node->next) { @@ -1680,7 +1740,7 @@ int node_duplicate_exec(bContext *C, wmOperator *op) ntreeCopyTree(snode->edittree, 1); /* 1 == internally selected nodes */ ntreeSolveOrder(snode->edittree); - snode_verify_groups(snode); + node_tree_verify_groups(snode->nodetree); snode_handle_recalc(C, snode); return OPERATOR_FINISHED; @@ -1891,7 +1951,7 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event) } ntreeSolveOrder(snode->edittree); - snode_verify_groups(snode); + node_tree_verify_groups(snode->nodetree); snode_handle_recalc(C, snode); MEM_freeN(op->customdata); @@ -1973,7 +2033,7 @@ static int node_link_invoke(bContext *C, wmOperator *op, wmEvent *event) nldrag->link= nodeAddLink(snode->edittree, NULL, NULL, nldrag->node, nldrag->sock); /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -2000,35 +2060,6 @@ void NODE_OT_link(wmOperatorType *ot) } -void node_delete(SpaceNode *snode) -{ - bNode *node, *next; - bNodeSocket *sock; - - for(node= snode->edittree->nodes.first; node; node= next) { - next= node->next; - if(node->flag & SELECT) { - /* set selin and selout NULL if the sockets belong to a node to be deleted */ - for(sock= node->inputs.first; sock; sock= sock->next) - if(snode->edittree->selin == sock) snode->edittree->selin= NULL; - - for(sock= node->outputs.first; sock; sock= sock->next) - if(snode->edittree->selout == sock) snode->edittree->selout= NULL; - - /* check id user here, nodeFreeNode is called for free dbase too */ - if(node->id) - node->id->us--; - nodeFreeNode(snode->edittree, node); - } - } - - snode_verify_groups(snode); - // NODE_FIX_ME - // snode_handle_recalc(snode); - // allqueue(REDRAWNODE, 1); -} - - void node_hide(SpaceNode *snode) { bNode *node; @@ -2098,7 +2129,7 @@ void node_make_link(SpaceNode *snode) else return; ntreeSolveOrder(snode->edittree); - snode_verify_groups(snode); + node_tree_verify_groups(snode->nodetree); // XXX snode_handle_recalc(snode); } @@ -2153,7 +2184,7 @@ static int cut_links_exec(bContext *C, wmOperator *op) } ntreeSolveOrder(snode->edittree); - snode_verify_groups(snode); + node_tree_verify_groups(snode->nodetree); snode_handle_recalc(C, snode); return OPERATOR_FINISHED; @@ -2253,15 +2284,16 @@ void imagepaint_composite_tags(bNodeTree *ntree, Image *image, ImageUser *iuser) } } -/* ********************** */ +/* ****************** Make Group operator ******************* */ -void node_make_group(SpaceNode *snode) +static int node_group_make_exec(bContext *C, wmOperator *op) { + SpaceNode *snode = CTX_wm_space_node(C); bNode *gnode; if(snode->edittree!=snode->nodetree) { -// XXX error("Can not add a new Group in a Group"); - return; + BKE_report(op->reports, RPT_ERROR, "Can not add a new Group in a Group"); + return OPERATOR_CANCELLED; } /* for time being... is too complex to handle */ @@ -2271,20 +2303,39 @@ void node_make_group(SpaceNode *snode) if(gnode->type==CMP_NODE_R_LAYERS) break; } + if(gnode) { -// XXX error("Can not add RenderLayer in a Group"); - return; + BKE_report(op->reports, RPT_ERROR, "Can not add RenderLayer in a Group"); + return OPERATOR_CANCELLED; } } gnode= nodeMakeGroupFromSelected(snode->nodetree); if(gnode==NULL) { -// XXX error("Can not make Group"); + BKE_report(op->reports, RPT_ERROR, "Can not make Group"); + return OPERATOR_CANCELLED; } else { nodeSetActive(snode->nodetree, gnode); ntreeSolveOrder(snode->nodetree); } + + return OPERATOR_FINISHED; +} + +void NODE_OT_group_make(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Group"; + ot->description = "Make group from selected nodes."; + ot->idname = "NODE_OT_group_make"; + + /* api callbacks */ + ot->exec = node_group_make_exec; + ot->poll = ED_operator_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; } #if 0 @@ -2498,29 +2549,50 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt) } #endif -static int node_delete_selection_exec(bContext *C, wmOperator *op) +/* ****************** Delete operator ******************* */ + +static int node_delete_exec(bContext *C, wmOperator *op) { SpaceNode *snode= CTX_wm_space_node(C); - ARegion *ar= CTX_wm_region(C); + bNode *node, *next; + bNodeSocket *sock; + + for(node= snode->edittree->nodes.first; node; node= next) { + next= node->next; + if(node->flag & SELECT) { + /* set selin and selout NULL if the sockets belong to a node to be deleted */ + for(sock= node->inputs.first; sock; sock= sock->next) + if(snode->edittree->selin == sock) snode->edittree->selin= NULL; + + for(sock= node->outputs.first; sock; sock= sock->next) + if(snode->edittree->selout == sock) snode->edittree->selout= NULL; + + /* check id user here, nodeFreeNode is called for free dbase too */ + if(node->id) + node->id->us--; + nodeFreeNode(snode->edittree, node); + } + } - node_delete(snode); - ED_region_tag_redraw(ar); + node_tree_verify_groups(snode->nodetree); + + // NODE_FIX_ME + // snode_handle_recalc(snode); + WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); /* Do we need to pass the scene? */ return OPERATOR_FINISHED; } -/* operators */ - void NODE_OT_delete(wmOperatorType *ot) { - /* identifiers */ ot->name= "Delete"; + ot->description = "Delete selected nodes."; ot->idname= "NODE_OT_delete"; /* api callbacks */ - ot->exec= node_delete_selection_exec; + ot->exec= node_delete_exec; ot->poll= ED_operator_node_active; /* flags */ diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 6fdaeca7701..2a929472c68 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -81,7 +81,7 @@ void snode_home(ScrArea *sa, ARegion *ar, SpaceNode *snode); void node_set_active(SpaceNode *snode, bNode *node); void node_deselectall(SpaceNode *snode); void snode_composite_job(const struct bContext *C, ScrArea *sa); -bNode *snode_get_editgroup(SpaceNode *snode); +bNode *node_tree_get_editgroup(bNodeTree *ntree); void snode_autoconnect(SpaceNode *snode, bNode *node_to, int flag); void NODE_OT_duplicate(struct wmOperatorType *ot); @@ -89,6 +89,9 @@ void NODE_OT_link(struct wmOperatorType *ot); void NODE_OT_delete(struct wmOperatorType *ot); void NODE_OT_resize(struct wmOperatorType *ot); void NODE_OT_links_cut(struct wmOperatorType *ot); +void NODE_OT_group_make(struct wmOperatorType *ot); +void NODE_OT_group_ungroup(struct wmOperatorType *ot); +void NODE_OT_group_edit(struct wmOperatorType *ot); // XXXXXX diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index af857d57634..f47e9aa2a6f 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -62,11 +62,14 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_resize); WM_operatortype_append(NODE_OT_links_cut); WM_operatortype_append(NODE_OT_duplicate); + WM_operatortype_append(NODE_OT_group_make); + WM_operatortype_append(NODE_OT_group_ungroup); + WM_operatortype_append(NODE_OT_group_edit); } void node_keymap(struct wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Node", SPACE_NODE, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Node", SPACE_NODE, 0); /* mouse select in nodes used to be both keys, it's UI elements... */ RNA_enum_set(WM_keymap_add_item(keymap, "NODE_OT_select", ACTIONMOUSE, KM_PRESS, 0, 0)->ptr, "select_type", NODE_SELECT_MOUSE); @@ -84,10 +87,15 @@ void node_keymap(struct wmWindowManager *wm) WM_keymap_add_item(keymap, "NODE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_select_border", BKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NODE_OT_delete", DELKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_select_all", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_select_linked_to", LKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "NODE_OT_select_linked_from", LKEY, KM_PRESS, 0, 0); + + WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0); transform_keymap_for_space(wm, keymap, SPACE_NODE); } diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 94e17b56a02..5e482758c9d 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -140,7 +140,7 @@ static int node_select_modal(bContext *C, wmOperator *op, wmEvent *event) printf("%d %d\n", event->x, event->y); break; case SELECTMOUSE: - //if (event->val==0) { + //if (event->val==KM_RELEASE) { /* calculate overall delta mouse-movement for redo */ printf("done translating\n"); //WM_cursor_restore(CTX_wm_window(C)); @@ -224,12 +224,6 @@ void NODE_OT_select(wmOperatorType *ot) /* ****** Border Select ****** */ -static EnumPropertyItem prop_select_types[] = { - {NODE_EXCLUSIVE, "EXCLUSIVE", 0, "Exclusive", ""}, /* right mouse */ - {NODE_EXTEND, "EXTEND", 0, "Extend", ""}, /* left mouse */ - {0, NULL, 0, NULL, NULL} -}; - static int node_borderselect_exec(bContext *C, wmOperator *op) { SpaceNode *snode= CTX_wm_space_node(C); @@ -288,8 +282,6 @@ void NODE_OT_select_border(wmOperatorType *ot) RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); - - RNA_def_enum(ot->srna, "type", prop_select_types, 0, "Type", ""); } /* ****** Select/Deselect All ****** */ diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index d3a445b18c0..12a5f33e119 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -245,12 +245,12 @@ static void node_channel_area_draw(const bContext *C, ARegion *ar) /* Initialise main area, setting handlers. */ static void node_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "Node", SPACE_NODE, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "Node", SPACE_NODE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index a3b47d505fd..a1fdbab9ccc 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -5049,6 +5049,8 @@ static char *keymap_mouse_menu(void) str += sprintf(str, formatstr, "Left Mouse", LEFTMOUSE); str += sprintf(str, formatstr, "Middle Mouse", MIDDLEMOUSE); str += sprintf(str, formatstr, "Right Mouse", RIGHTMOUSE); + str += sprintf(str, formatstr, "Button4 Mouse ", BUTTON4MOUSE); + str += sprintf(str, formatstr, "Button5 Mouse ", BUTTON5MOUSE); str += sprintf(str, formatstr, "Action Mouse", ACTIONMOUSE); str += sprintf(str, formatstr, "Select Mouse", SELECTMOUSE); str += sprintf(str, formatstr, "Mouse Move", MOUSEMOVE); @@ -5071,6 +5073,8 @@ static char *keymap_tweak_menu(void) str += sprintf(str, formatstr, "Left Mouse", EVT_TWEAK_L); str += sprintf(str, formatstr, "Middle Mouse", EVT_TWEAK_M); str += sprintf(str, formatstr, "Right Mouse", EVT_TWEAK_R); + str += sprintf(str, formatstr, "Button4 Mouse ", BUTTON4MOUSE); + str += sprintf(str, formatstr, "Button5 Mouse ", BUTTON5MOUSE); str += sprintf(str, formatstr, "Action Mouse", EVT_TWEAK_A); str += sprintf(str, formatstr, "Select Mouse", EVT_TWEAK_S); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index 2e11eb379b4..a35b91249db 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -76,7 +76,7 @@ void outliner_operatortypes(void) void outliner_keymap(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Outliner", SPACE_OUTLINER, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Outliner", SPACE_OUTLINER, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "extend", 0); RNA_boolean_set(WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1); diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 5058a167a29..e7e6c2d0128 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -72,12 +72,12 @@ static void outliner_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "Outliner", SPACE_OUTLINER, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "Outliner", SPACE_OUTLINER, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } diff --git a/source/blender/editors/space_script/script_ops.c b/source/blender/editors/space_script/script_ops.c index 270cc1ffd8f..0e6ea9cf4fd 100644 --- a/source/blender/editors/space_script/script_ops.c +++ b/source/blender/editors/space_script/script_ops.c @@ -65,7 +65,7 @@ void script_operatortypes(void) void script_keymap(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Script", SPACE_SCRIPT, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Script", SPACE_SCRIPT, 0); /* TODO - this is just while we have no way to load a text datablock */ RNA_string_set(WM_keymap_add_item(keymap, "SCRIPT_OT_python_file_run", PKEY, KM_PRESS, KM_CTRL|KM_SHIFT|KM_ALT, 0)->ptr, "path", "test.py"); diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c index 99233cc5020..a0e73082701 100644 --- a/source/blender/editors/space_script/space_script.c +++ b/source/blender/editors/space_script/space_script.c @@ -133,12 +133,12 @@ static SpaceLink *script_duplicate(SpaceLink *sl) /* add handlers, stuff you only do once or on area/region changes */ static void script_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "Script", SPACE_SCRIPT, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "Script", SPACE_SCRIPT, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c index 789843f5490..72cbacd9b6d 100644 --- a/source/blender/editors/space_sequencer/sequencer_buttons.c +++ b/source/blender/editors/space_sequencer/sequencer_buttons.c @@ -112,13 +112,9 @@ static int sequencer_properties(bContext *C, wmOperator *op) ScrArea *sa= CTX_wm_area(C); ARegion *ar= sequencer_has_buttons_region(sa); - if(ar) { - ar->flag ^= RGN_FLAG_HIDDEN; - ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */ - - ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); - ED_area_tag_redraw(sa); - } + if(ar) + ED_region_toggle_hidden(C, ar); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index 74f22b86b75..ac125c10b2d 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -105,7 +105,7 @@ void sequencer_operatortypes(void) void sequencer_keymap(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Sequencer", SPACE_SEQ, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Sequencer", SPACE_SEQ, 0); wmKeymapItem *kmi; WM_keymap_add_item(keymap, "SEQUENCER_OT_properties", NKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 26ffd88ae67..c2756b05946 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -185,12 +185,12 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) /* add handlers, stuff you only do once or on area/region changes */ static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "Sequencer", SPACE_SEQ, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "Sequencer", SPACE_SEQ, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } diff --git a/source/blender/editors/space_sound/space_sound.c b/source/blender/editors/space_sound/space_sound.c index f8ef2b21ae7..6713e19b6de 100644 --- a/source/blender/editors/space_sound/space_sound.c +++ b/source/blender/editors/space_sound/space_sound.c @@ -142,12 +142,12 @@ static SpaceLink *sound_duplicate(SpaceLink *sl) /* add handlers, stuff you only do once or on area/region changes */ static void sound_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "Sound", SPACE_SOUND, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "Sound", SPACE_SOUND, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 1f919fc9cd7..e068c1a70bb 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -208,7 +208,9 @@ static void text_operatortypes(void) static void text_keymap(struct wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Text", SPACE_TEXT, 0); + wmKeyMap *keymap; + + keymap= WM_keymap_find(wm, "Text", SPACE_TEXT, 0); #ifdef __APPLE__ RNA_enum_set(WM_keymap_add_item(keymap, "TEXT_OT_move", LEFTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN); @@ -329,12 +331,12 @@ static int text_context(const bContext *C, const char *member, bContextDataResul /* add handlers, stuff you only do once or on area/region changes */ static void text_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "Text", SPACE_TEXT, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "Text", SPACE_TEXT, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 9721fbc2b9c..5996770c206 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -425,60 +425,6 @@ static void format_draw_color(char formatchar) } } -/*********************** utilities ************************/ - -int text_check_bracket(char ch) -{ - int a; - char opens[] = "([{"; - char close[] = ")]}"; - - for(a=0; a<3; a++) { - if(ch==opens[a]) - return a+1; - else if(ch==close[a]) - return -(a+1); - } - return 0; -} - -int text_check_delim(char ch) -{ - int a; - char delims[] = "():\"\' ~!%^&*-+=[]{};/<>|.#\t,"; - - for(a=0; a<28; a++) { - if(ch==delims[a]) - return 1; - } - return 0; -} - -int text_check_digit(char ch) -{ - if(ch < '0') return 0; - if(ch <= '9') return 1; - return 0; -} - -int text_check_identifier(char ch) -{ - if(ch < '0') return 0; - if(ch <= '9') return 1; - if(ch < 'A') return 0; - if(ch <= 'Z' || ch == '_') return 1; - if(ch < 'a') return 0; - if(ch <= 'z') return 1; - return 0; -} - -int text_check_whitespace(char ch) -{ - if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') - return 1; - return 0; -} - /************************** draw text *****************************/ /***********************/ /* diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c index 089436cfcf9..d0a02f558e1 100644 --- a/source/blender/editors/space_text/text_header.c +++ b/source/blender/editors/space_text/text_header.c @@ -186,15 +186,6 @@ ARegion *text_has_properties_region(ScrArea *sa) return arnew; } -void text_toggle_properties_region(bContext *C, ScrArea *sa, ARegion *ar) -{ - ar->flag ^= RGN_FLAG_HIDDEN; - ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */ - - ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); - ED_area_tag_redraw(sa); -} - static int properties_poll(bContext *C) { return (CTX_wm_space_text(C) != NULL); @@ -206,7 +197,7 @@ static int properties_exec(bContext *C, wmOperator *op) ARegion *ar= text_has_properties_region(sa); if(ar) - text_toggle_properties_region(C, sa, ar); + ED_region_toggle_hidden(C, ar); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 3568f50dfe1..8e81336912b 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -1731,7 +1731,7 @@ static int scroll_invoke(bContext *C, wmOperator *op, wmEvent *event) st->flags|= ST_SCROLL_SELECT; - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -1860,7 +1860,7 @@ static int scroll_bar_invoke(bContext *C, wmOperator *op, wmEvent *event) st->flags|= ST_SCROLL_SELECT; - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -2115,7 +2115,7 @@ static int set_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event) scu->sell= txt_get_span(st->text->lines.first, st->text->sell); scu->selc= st->text->selc; - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); set_cursor_apply(C, op, event); diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 8f7486f81d9..0f05eb0149d 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -202,12 +202,12 @@ static void time_draw_keyframes(const bContext *C, SpaceTime *stime, ARegion *ar /* add handlers, stuff you only do once or on area/region changes */ static void time_main_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymap */ - keymap= WM_keymap_listbase(wm, "TimeLine", SPACE_TIME, 0); /* XXX weak? */ + keymap= WM_keymap_find(wm, "TimeLine", SPACE_TIME, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } diff --git a/source/blender/editors/space_time/time_ops.c b/source/blender/editors/space_time/time_ops.c index a833cca095c..2b073f269bf 100644 --- a/source/blender/editors/space_time/time_ops.c +++ b/source/blender/editors/space_time/time_ops.c @@ -142,7 +142,7 @@ void time_operatortypes(void) void time_keymap(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "TimeLine", SPACE_TIME, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "TimeLine", SPACE_TIME, 0); WM_keymap_add_item(keymap, "TIME_OT_start_frame_set", SKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "TIME_OT_end_frame_set", EKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_view3d/Makefile b/source/blender/editors/space_view3d/Makefile index 07102157854..9204f2482c6 100644 --- a/source/blender/editors/space_view3d/Makefile +++ b/source/blender/editors/space_view3d/Makefile @@ -53,6 +53,9 @@ CPPFLAGS += -I../../render/extern/include CPPFLAGS += -I../../blenfont CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I$(NAN_SMOKE)/include -# own include +ifneq ($(NAN_NO_KETSJI),true) + CPPFLAGS += -I../../../kernel/gen_system +endif +# own include CPPFLAGS += -I../include diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index fa810677fe8..028d666dc71 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -639,7 +639,7 @@ static void draw_sphere_bone_dist(float smat[][4], float imat[][4], int boneflag /* figure out the sizes of spheres */ if (ebone) { - /* this routine doesn't call set_matrix_editbone() that calculates it */ + /* this routine doesn't call get_matrix_editbone() that calculates it */ ebone->length = VecLenf(ebone->head, ebone->tail); length= ebone->length; @@ -749,7 +749,7 @@ static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag, /* figure out the sizes of spheres */ if (ebone) { - /* this routine doesn't call set_matrix_editbone() that calculates it */ + /* this routine doesn't call get_matrix_editbone() that calculates it */ ebone->length = VecLenf(ebone->head, ebone->tail); length= ebone->length; @@ -1516,15 +1516,25 @@ static void draw_pose_dofs(Object *ob) } } +static void bone_matrix_translate_y(float mat[][4], float y) +{ + float trans[3]; + + VECCOPY(trans, mat[1]); + VecMulf(trans, y); + VecAddf(mat[3], mat[3], trans); +} + /* assumes object is Armature with pose */ -static void draw_pose_channels(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt) +static void draw_pose_channels(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt) { + RegionView3D *rv3d= ar->regiondata; Object *ob= base->object; bArmature *arm= ob->data; bPoseChannel *pchan; Bone *bone; GLfloat tmp; - float smat[4][4], imat[4][4]; + float smat[4][4], imat[4][4], bmat[4][4]; int index= -1; short do_dashed= 3, draw_wire= 0; short flag, constflag; @@ -1809,15 +1819,21 @@ static void draw_pose_channels(Scene *scene, View3D *v3d, RegionView3D *rv3d, Ba /* Draw names of bone */ if (arm->flag & ARM_DRAWNAMES) { VecMidf(vec, pchan->pose_head, pchan->pose_tail); - view3d_object_text_draw_add(vec[0], vec[1], vec[2], pchan->name, 10); + view3d_cached_text_draw_add(vec[0], vec[1], vec[2], pchan->name, 10); } /* Draw additional axes on the bone tail */ if ( (arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE) ) { glPushMatrix(); - glMultMatrixf(pchan->pose_mat); - glTranslatef(0.0f, pchan->bone->length, 0.0f); - drawaxes(0.25f*pchan->bone->length, 0, OB_ARROWS); + Mat4CpyMat4(bmat, pchan->pose_mat); + bone_matrix_translate_y(bmat, pchan->bone->length); + glMultMatrixf(bmat); + + /* do cached text draw immediate to include transform */ + view3d_cached_text_draw_begin(); + drawaxes(pchan->bone->length*0.25f, 0, OB_ARROWS); + view3d_cached_text_draw_end(v3d, ar, 1, bmat); + glPopMatrix(); } } @@ -1830,32 +1846,28 @@ static void draw_pose_channels(Scene *scene, View3D *v3d, RegionView3D *rv3d, Ba } /* in editmode, we don't store the bone matrix... */ -static void set_matrix_editbone(EditBone *eBone) +static void get_matrix_editbone(EditBone *eBone, float bmat[][4]) { - float delta[3],offset[3]; - float mat[3][3], bmat[4][4]; + float delta[3]; + float mat[3][3]; /* Compose the parent transforms (i.e. their translations) */ - VECCOPY(offset, eBone->head); - - glTranslatef(offset[0],offset[1],offset[2]); - VecSubf(delta, eBone->tail, eBone->head); eBone->length = (float)sqrt(delta[0]*delta[0] + delta[1]*delta[1] +delta[2]*delta[2]); vec_roll_to_mat3(delta, eBone->roll, mat); Mat4CpyMat3(bmat, mat); - - glMultMatrixf(bmat); - + + VecAddf(bmat[3], bmat[3], eBone->head); } -static void draw_ebones(View3D *v3d, RegionView3D *rv3d, Object *ob, int dt) +static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt) { + RegionView3D *rv3d= ar->regiondata; EditBone *eBone; bArmature *arm= ob->data; - float smat[4][4], imat[4][4]; + float smat[4][4], imat[4][4], bmat[4][4]; unsigned int index; int flag; @@ -1893,7 +1905,8 @@ static void draw_ebones(View3D *v3d, RegionView3D *rv3d, Object *ob, int dt) if (eBone->layer & arm->layer) { if ((eBone->flag & BONE_HIDDEN_A)==0) { glPushMatrix(); - set_matrix_editbone(eBone); + get_matrix_editbone(eBone, bmat); + glMultMatrixf(bmat); /* catch exception for bone with hidden parent */ flag= eBone->flag; @@ -1941,7 +1954,8 @@ static void draw_ebones(View3D *v3d, RegionView3D *rv3d, Object *ob, int dt) } else { glPushMatrix(); - set_matrix_editbone(eBone); + get_matrix_editbone(eBone, bmat); + glMultMatrixf(bmat); if (arm->drawtype == ARM_LINE) draw_line_bone(arm->flag, flag, 0, index, NULL, eBone); @@ -1994,14 +2008,20 @@ static void draw_ebones(View3D *v3d, RegionView3D *rv3d, Object *ob, int dt) if (arm->flag & ARM_DRAWNAMES) { VecMidf(vec, eBone->head, eBone->tail); glRasterPos3fv(vec); - view3d_object_text_draw_add(vec[0], vec[1], vec[2], eBone->name, 10); + view3d_cached_text_draw_add(vec[0], vec[1], vec[2], eBone->name, 10); } /* Draw additional axes */ if (arm->flag & ARM_DRAWAXES) { glPushMatrix(); - set_matrix_editbone(eBone); - glTranslatef(0.0f, eBone->length, 0.0f); + get_matrix_editbone(eBone, bmat); + bone_matrix_translate_y(bmat, eBone->length); + glMultMatrixf(bmat); + + /* do cached text draw immediate to include transform */ + view3d_cached_text_draw_begin(); drawaxes(eBone->length*0.25f, 0, OB_ARROWS); + view3d_cached_text_draw_end(v3d, ar, 1, bmat); + glPopMatrix(); } @@ -2021,8 +2041,9 @@ static void draw_ebones(View3D *v3d, RegionView3D *rv3d, Object *ob, int dt) /* draw bone paths * - in view space */ -static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) +static void draw_pose_paths(Scene *scene, View3D *v3d, ARegion *ar, Object *ob) { + RegionView3D *rv3d= ar->regiondata; AnimData *adt= BKE_animdata_from_id(&ob->id); bArmature *arm= ob->data; bPoseChannel *pchan; @@ -2155,12 +2176,12 @@ static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec /* only draw framenum if several consecutive highlighted points don't occur on same point */ if (a == 0) { sprintf(str, "%d", (a+sfra)); - view3d_object_text_draw_add(fp[0], fp[1], fp[2], str, 0); + view3d_cached_text_draw_add(fp[0], fp[1], fp[2], str, 0); } else if ((a > stepsize) && (a < len-stepsize)) { if ((VecEqual(fp, fp-(stepsize*3))==0) || (VecEqual(fp, fp+(stepsize*3))==0)) { sprintf(str, "%d", (a+sfra)); - view3d_object_text_draw_add(fp[0], fp[1], fp[2], str, 0); + view3d_cached_text_draw_add(fp[0], fp[1], fp[2], str, 0); } } } @@ -2202,7 +2223,7 @@ static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec char str[32]; sprintf(str, "%d", (a+sfra)); - view3d_object_text_draw_add(fp[0], fp[1], fp[2], str, 0); + view3d_cached_text_draw_add(fp[0], fp[1], fp[2], str, 0); } } } @@ -2253,7 +2274,7 @@ static void ghost_poses_tag_unselected(Object *ob, short unset) /* draw ghosts that occur within a frame range * note: object should be in posemode */ -static void draw_ghost_poses_range(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base) +static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base) { Object *ob= base->object; AnimData *adt= BKE_animdata_from_id(&ob->id); @@ -2295,7 +2316,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, RegionView3D *rv3d BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); where_is_pose(scene, ob); - draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE); + draw_pose_channels(scene, v3d, ar, base, OB_WIRE); } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -2315,7 +2336,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, RegionView3D *rv3d /* draw ghosts on keyframes in action within range * - object should be in posemode */ -static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base) +static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base) { Object *ob= base->object; AnimData *adt= BKE_animdata_from_id(&ob->id); @@ -2374,7 +2395,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d, BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); where_is_pose(scene, ob); - draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE); + draw_pose_channels(scene, v3d, ar, base, OB_WIRE); } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -2394,7 +2415,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, RegionView3D *rv3d, /* draw ghosts around current frame * - object is supposed to be armature in posemode */ -static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base) +static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) { Object *ob= base->object; AnimData *adt= BKE_animdata_from_id(&ob->id); @@ -2444,7 +2465,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base if (CFRA != cfrao) { BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); where_is_pose(scene, ob); - draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE); + draw_pose_channels(scene, v3d, ar, base, OB_WIRE); } } @@ -2459,7 +2480,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base if (CFRA != cfrao) { BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL); where_is_pose(scene, ob); - draw_pose_channels(scene, v3d, rv3d, base, OB_WIRE); + draw_pose_channels(scene, v3d, ar, base, OB_WIRE); } } } @@ -2480,7 +2501,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base /* ********************************** Armature Drawing - Main ************************* */ /* called from drawobject.c, return 1 if nothing was drawn */ -int draw_armature(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag) +int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, int flag) { Object *ob= base->object; bArmature *arm= ob->data; @@ -2504,7 +2525,7 @@ int draw_armature(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int /* editmode? */ if(arm->edbo) { arm->flag |= ARM_EDITMODE; - draw_ebones(v3d, rv3d, ob, dt); + draw_ebones(v3d, ar, ob, dt); arm->flag &= ~ARM_EDITMODE; } else{ @@ -2513,32 +2534,36 @@ int draw_armature(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int /* drawing posemode selection indices or colors only in these cases */ if(!(base->flag & OB_FROMDUPLI)) { if(G.f & G_PICKSEL) { - if(ob->mode & OB_MODE_POSE) + if(OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) { + if(ob==modifiers_isDeformedByArmature(OBACT)) + arm->flag |= ARM_POSEMODE; + } + else if(ob->mode & OB_MODE_POSE) arm->flag |= ARM_POSEMODE; } else if(ob->mode & OB_MODE_POSE) { if (arm->ghosttype == ARM_GHOST_RANGE) { - draw_ghost_poses_range(scene, v3d, rv3d, base); + draw_ghost_poses_range(scene, v3d, ar, base); } else if (arm->ghosttype == ARM_GHOST_KEYS) { - draw_ghost_poses_keys(scene, v3d, rv3d, base); + draw_ghost_poses_keys(scene, v3d, ar, base); } else if (arm->ghosttype == ARM_GHOST_CUR) { if (arm->ghostep) - draw_ghost_poses(scene, v3d, rv3d, base); + draw_ghost_poses(scene, v3d, ar, base); } if ((flag & DRAW_SCENESET)==0) { if(ob==OBACT) arm->flag |= ARM_POSEMODE; - else if(ob->mode & OB_MODE_WEIGHT_PAINT) { - if(OBACT && ob==modifiers_isDeformedByArmature(OBACT)) + else if(OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) { + if(ob==modifiers_isDeformedByArmature(OBACT)) arm->flag |= ARM_POSEMODE; } - draw_pose_paths(scene, v3d, rv3d, ob); + draw_pose_paths(scene, v3d, ar, ob); } } } - draw_pose_channels(scene, v3d, rv3d, base, dt); + draw_pose_channels(scene, v3d, ar, base, dt); arm->flag &= ~ARM_POSEMODE; if(ob->mode & OB_MODE_POSE) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index c02d45ca798..60ae91e7a89 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -434,11 +434,11 @@ void drawaxes(float size, int flag, char drawtype) // patch for 3d cards crashing on glSelect for text drawing (IBM) if((flag & DRAW_PICKING) == 0) { if (axis==0) - view3d_object_text_draw_add(v2[0], v2[1], v2[2], "x", 0); + view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "x", 0); else if (axis==1) - view3d_object_text_draw_add(v2[0], v2[1], v2[2], "y", 0); + view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "y", 0); else - view3d_object_text_draw_add(v2[0], v2[1], v2[2], "z", 0); + view3d_cached_text_draw_add(v2[0], v2[1], v2[2], "z", 0); } } break; @@ -496,23 +496,32 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, float *vec, int se if(v3d->zbuf) glDepthFunc(GL_LEQUAL); } -/* *********** text drawing for object ************* */ -static ListBase strings= {NULL, NULL}; +/* *********** text drawing for object/particles/armature ************* */ -typedef struct ViewObjectString { - struct ViewObjectString *next, *prev; +static ListBase CachedText[3]; +static int CachedTextLevel= 0; + +typedef struct ViewCachedString { + struct ViewCachedString *next, *prev; float vec[3], col[4]; char str[128]; short mval[2]; short xoffs; -} ViewObjectString; +} ViewCachedString; +void view3d_cached_text_draw_begin() +{ + ListBase *strings= &CachedText[CachedTextLevel]; + strings->first= strings->last= NULL; + CachedTextLevel++; +} -void view3d_object_text_draw_add(float x, float y, float z, char *str, short xoffs) +void view3d_cached_text_draw_add(float x, float y, float z, char *str, short xoffs) { - ViewObjectString *vos= MEM_callocN(sizeof(ViewObjectString), "ViewObjectString"); + ListBase *strings= &CachedText[CachedTextLevel-1]; + ViewCachedString *vos= MEM_callocN(sizeof(ViewCachedString), "ViewCachedString"); - BLI_addtail(&strings, vos); + BLI_addtail(strings, vos); BLI_strncpy(vos->str, str, 128); vos->vec[0]= x; vos->vec[1]= y; @@ -521,22 +530,23 @@ void view3d_object_text_draw_add(float x, float y, float z, char *str, short xof vos->xoffs= xoffs; } -static void view3d_object_text_draw(View3D *v3d, ARegion *ar) +void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4]) { - ViewObjectString *vos; - int tot= 0; + RegionView3D *rv3d= ar->regiondata; + ListBase *strings= &CachedText[CachedTextLevel-1]; + ViewCachedString *vos; + int a, tot= 0; /* project first and test */ - for(vos= strings.first; vos; vos= vos->next) { + for(vos= strings->first; vos; vos= vos->next) { + if(mat) + Mat4MulVecfl(mat, vos->vec); view3d_project_short_clip(ar, vos->vec, vos->mval); if(vos->mval[0]!=IS_CLIPPED) tot++; } - + if(tot) { - RegionView3D *rv3d= ar->regiondata; - int a; - if(rv3d->rflag & RV3D_CLIPPING) for(a=0; a<6; a++) glDisable(GL_CLIP_PLANE0+a); @@ -544,16 +554,22 @@ static void view3d_object_text_draw(View3D *v3d, ARegion *ar) wmPushMatrix(); ED_region_pixelspace(ar); - if(v3d->zbuf) glDisable(GL_DEPTH_TEST); + if(depth_write) { + if(v3d->zbuf) glDisable(GL_DEPTH_TEST); + } + else glDepthMask(0); - for(vos= strings.first; vos; vos= vos->next) { + for(vos= strings->first; vos; vos= vos->next) { if(vos->mval[0]!=IS_CLIPPED) { glColor3fv(vos->col); - BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], 0.0, vos->str); + BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], (depth_write)? 0.0f: 2.0f, vos->str); } } - if(v3d->zbuf) glEnable(GL_DEPTH_TEST); + if(depth_write) { + if(v3d->zbuf) glEnable(GL_DEPTH_TEST); + } + else glDepthMask(1); wmPopMatrix(); @@ -562,10 +578,14 @@ static void view3d_object_text_draw(View3D *v3d, ARegion *ar) glEnable(GL_CLIP_PLANE0+a); } - if(strings.first) - BLI_freelistN(&strings); + if(strings->first) + BLI_freelistN(strings); + + CachedTextLevel--; } +/* ******************** primitive drawing ******************* */ + static void drawcube(void) { @@ -1912,7 +1932,7 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E else sprintf(val, conv_float, VecLenf(v1, v2)); - view3d_object_text_draw_add(x, y, z, val, 0); + view3d_cached_text_draw_add(x, y, z, val, 0); } } } @@ -1951,7 +1971,7 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E else sprintf(val, conv_float, area); - view3d_object_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0); + view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0); } } } @@ -1991,31 +2011,31 @@ static void draw_em_measure_stats(View3D *v3d, RegionView3D *rv3d, Object *ob, E if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) { /* Vec 1 */ - sprintf(val,"%.3f", VecAngle3(v4, v1, v2)); + sprintf(val,"%.3f", RAD2DEG(VecAngle3(v4, v1, v2))); VecLerpf(fvec, efa->cent, efa->v1->co, 0.8f); - view3d_object_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0); + view3d_cached_text_draw_add(efa->cent[0], efa->cent[1], efa->cent[2], val, 0); } if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) { /* Vec 2 */ - sprintf(val,"%.3f", VecAngle3(v1, v2, v3)); + sprintf(val,"%.3f", RAD2DEG(VecAngle3(v1, v2, v3))); VecLerpf(fvec, efa->cent, efa->v2->co, 0.8f); - view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0); + view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0); } if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) { /* Vec 3 */ if(efa->v4) - sprintf(val,"%.3f", VecAngle3(v2, v3, v4)); + sprintf(val,"%.3f", RAD2DEG(VecAngle3(v2, v3, v4))); else - sprintf(val,"%.3f", VecAngle3(v2, v3, v1)); + sprintf(val,"%.3f", RAD2DEG(VecAngle3(v2, v3, v1))); VecLerpf(fvec, efa->cent, efa->v3->co, 0.8f); - view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0); + view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0); } /* Vec 4 */ if(efa->v4) { if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) { - sprintf(val,"%.3f", VecAngle3(v3, v4, v1)); + sprintf(val,"%.3f", RAD2DEG(VecAngle3(v3, v4, v1))); VecLerpf(fvec, efa->cent, efa->v4->co, 0.8f); - view3d_object_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0); + view3d_cached_text_draw_add(fvec[0], fvec[1], fvec[2], val, 0); } } } @@ -2905,82 +2925,8 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas return retval; } -/* *********** text drawing for particles ************* */ -static ListBase pstrings= {NULL, NULL}; - -typedef struct ViewParticleString { - struct ViewParticleString *next, *prev; - float vec[3], col[4]; - char str[128]; - short mval[2]; - short xoffs; -} ViewParticleString; - - -void view3d_particle_text_draw_add(float x, float y, float z, char *str, short xoffs) -{ - ViewObjectString *vos= MEM_callocN(sizeof(ViewObjectString), "ViewObjectString"); - - BLI_addtail(&pstrings, vos); - BLI_strncpy(vos->str, str, 128); - vos->vec[0]= x; - vos->vec[1]= y; - vos->vec[2]= z; - glGetFloatv(GL_CURRENT_COLOR, vos->col); - vos->xoffs= xoffs; -} - -static void view3d_particle_text_draw(View3D *v3d, ARegion *ar) -{ - ViewObjectString *vos; - int tot= 0; - - /* project first and test */ - for(vos= pstrings.first; vos; vos= vos->next) { - project_short(ar, vos->vec, vos->mval); - if(vos->mval[0]!=IS_CLIPPED) - tot++; - } - - if(tot) { - RegionView3D *rv3d= ar->regiondata; - int a; - - if(rv3d->rflag & RV3D_CLIPPING) - for(a=0; a<6; a++) - glDisable(GL_CLIP_PLANE0+a); - - wmPushMatrix(); - ED_region_pixelspace(ar); - - if(v3d->zbuf) glDepthMask(0); - - for(vos= pstrings.first; vos; vos= vos->next) { - if(vos->mval[0]!=IS_CLIPPED) { - glColor3fv(vos->col); - BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], 2.0, vos->str); - } - } - - if(v3d->zbuf) glDepthMask(1); - - wmPopMatrix(); +/* *********** drawing for particles ************* */ - if(rv3d->rflag & RV3D_CLIPPING) - for(a=0; a<6; a++) - glEnable(GL_CLIP_PLANE0+a); - } - - if(pstrings.first) - BLI_freelistN(&pstrings); -} -typedef struct ParticleDrawData { - float *vdata, *vd; - float *ndata, *nd; - float *cdata, *cd; - float *vedata, *ved; - float *ma_r, *ma_g, *ma_b; -} ParticleDrawData; static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, float imat[4][4], float *draw_line, ParticleBillboardData *bb, ParticleDrawData *pdd) { float vec[3], vec2[3]; @@ -3145,7 +3091,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv ParticleData *pars, *pa; ParticleKey state, *states=0; ParticleBillboardData bb; - ParticleDrawData pdd; + ParticleSimulationData sim = {scene, ob, psys, NULL}; + ParticleDrawData *pdd = psys->pdd; Material *ma; float vel[3], imat[4][4]; float timestep, pixsize=1.0, pa_size, r_tilt, r_length; @@ -3176,9 +3123,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if(part->draw_as==PART_DRAW_NOT) return; /* 2. */ + sim.psmd = psmd = psys_get_modifier(ob,psys); + if(part->phystype==PART_PHYS_KEYED){ if(psys->flag&PSYS_KEYED){ - psys_count_keyed_targets(ob,psys); + psys_count_keyed_targets(&sim); if(psys->totkeyed==0) return; } @@ -3196,8 +3145,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv totchild=0; else totchild=psys->totchild*part->disp/100; - - memset(&pdd, 0, sizeof(ParticleDrawData)); ma= give_current_material(ob,part->omat); @@ -3212,18 +3159,16 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv ma_g = ma->g; ma_b = ma->b; - pdd.ma_r = &ma_r; - pdd.ma_g = &ma_g; - pdd.ma_b = &ma_b; + pdd->ma_r = &ma_r; + pdd->ma_g = &ma_g; + pdd->ma_b = &ma_b; create_cdata = 1; } else cpack(0); - psmd= psys_get_modifier(ob,psys); - - timestep= psys_get_timestep(part); + timestep= psys_get_timestep(&sim); if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) { float mat[4][4]; @@ -3317,54 +3262,65 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv /* 4. */ if(draw_as && draw_as!=PART_DRAW_PATH) { int tot_vec_size = (totpart + totchild) * 3 * sizeof(float); - + + if(!pdd) + pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticlDrawData"); + if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) { tot_vec_size *= part->trail_count; psys_make_temp_pointcache(ob, psys); } + if(pdd->tot_vec_size != tot_vec_size) + psys_free_pdd(psys); + if(draw_as!=PART_DRAW_CIRC) { switch(draw_as) { case PART_DRAW_AXIS: case PART_DRAW_CROSS: if(draw_as != PART_DRAW_CROSS || create_cdata) - pdd.cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata"); - pdd.vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata"); + if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata"); + if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata"); break; case PART_DRAW_LINE: if(create_cdata) - pdd.cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata"); - pdd.vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata"); + if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata"); + if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata"); break; case PART_DRAW_BB: if(create_cdata) - pdd.cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata"); - pdd.vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata"); - pdd.ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata"); + if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata"); + if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata"); + if(!pdd->ndata) pdd->ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata"); break; default: if(create_cdata) - pdd.cdata=MEM_callocN(tot_vec_size, "particle_cdata"); - pdd.vdata=MEM_callocN(tot_vec_size, "particle_vdata"); + if(!pdd->cdata) pdd->cdata=MEM_callocN(tot_vec_size, "particle_cdata"); + if(!pdd->vdata) pdd->vdata=MEM_callocN(tot_vec_size, "particle_vdata"); } } if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) { - pdd.vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata"); + if(!pdd->vedata) pdd->vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata"); need_v = 1; } - pdd.vd= pdd.vdata; - pdd.ved= pdd.vedata; - pdd.cd= pdd.cdata; - pdd.nd= pdd.ndata; + pdd->vd= pdd->vdata; + pdd->ved= pdd->vedata; + pdd->cd= pdd->cdata; + pdd->nd= pdd->ndata; + pdd->tot_vec_size= tot_vec_size; - psys->lattice= psys_get_lattice(scene, ob, psys); + psys->lattice= psys_get_lattice(&sim); } if(draw_as){ /* 5. */ - for(a=0,pa=pars; a<totpart+totchild; a++, pa++){ + if((pdd->flag & PARTICLE_DRAW_DATA_UPDATED) + && (pdd->vedata || part->draw & (PART_DRAW_SIZE|PART_DRAW_NUM|PART_DRAW_HEALTH))==0) { + totpoint = pdd->totpoint; /* draw data is up to date */ + } + else for(a=0,pa=pars; a<totpart+totchild; a++, pa++){ /* setup per particle individual stuff */ if(a<totpart){ if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue; @@ -3374,9 +3330,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pa_birthtime=pa->time; pa_dietime = pa->dietime; pa_size=pa->size; - if(part->phystype==PART_PHYS_BOIDS) { + if(part->phystype==PART_PHYS_BOIDS) pa_health = pa->boid->data.health; - } else pa_health = -1.0; @@ -3411,10 +3366,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } #endif // XXX old animation system - BLI_srandom(psys->seed+a); - - r_tilt = 2.0f*(BLI_frand() - 0.5f); - r_length = BLI_frand(); + r_tilt = 2.0f*(PSYS_FRAND(a + 21) - 0.5f); + r_length = PSYS_FRAND(a + 22); } else{ ChildParticle *cpa= &psys->child[a-totpart]; @@ -3445,8 +3398,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pa_health = -1.0; - r_tilt = 2.0f * cpa->rand[2]; - r_length = cpa->rand[1]; + r_tilt = 2.0f*(PSYS_FRAND(a + 21) - 0.5f); + r_length = PSYS_FRAND(a + 22); } if(draw_as!=PART_DRAW_PATH){ @@ -3468,7 +3421,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv continue; state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime)); - psys_get_particle_on_path(scene,ob,psys,a,&state,need_v); + psys_get_particle_on_path(&sim,a,&state,need_v); if(psys->parent) Mat4MulVecfl(psys->parent->obmat, state.co); @@ -3480,7 +3433,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv bb.time = ct; } - draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, &pdd); + draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd); totpoint++; drawn = 1; @@ -3489,7 +3442,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv else { state.time=cfra; - if(psys_get_particle_state(scene,ob,psys,a,&state,0)){ + if(psys_get_particle_state(&sim,a,&state,0)){ if(psys->parent) Mat4MulVecfl(psys->parent->obmat, state.co); @@ -3500,7 +3453,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv bb.time = pa_time; } - draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, &pdd); + draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd); totpoint++; drawn = 1; @@ -3510,13 +3463,13 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if(drawn) { /* additional things to draw for each particle */ /* (velocity, size and number) */ - if(pdd.vedata){ - VECCOPY(pdd.ved,state.co); - pdd.ved+=3; + if(pdd->vedata){ + VECCOPY(pdd->ved,state.co); + pdd->ved+=3; VECCOPY(vel,state.vel); VecMulf(vel,timestep); - VECADD(pdd.ved,state.co,vel); - pdd.ved+=3; + VECADD(pdd->ved,state.co,vel); + pdd->ved+=3; totve++; } @@ -3540,7 +3493,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv sprintf(val, "%s %.2f", val, pa_health); /* in path drawing state.co is the end point */ - view3d_particle_text_draw_add(state.co[0], state.co[1], state.co[2], val, 0); + view3d_cached_text_draw_add(state.co[0], state.co[1], state.co[2], val, 0); } } } @@ -3628,17 +3581,17 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDisableClientState(GL_COLOR_ARRAY); /* setup created data arrays */ - if(pdd.vdata){ + if(pdd->vdata){ glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pdd.vdata); + glVertexPointer(3, GL_FLOAT, 0, pdd->vdata); } else glDisableClientState(GL_VERTEX_ARRAY); /* billboards are drawn this way */ - if(pdd.ndata && ob_dt>OB_WIRE){ + if(pdd->ndata && ob_dt>OB_WIRE){ glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(GL_FLOAT, 0, pdd.ndata); + glNormalPointer(GL_FLOAT, 0, pdd->ndata); glEnable(GL_LIGHTING); } else{ @@ -3646,9 +3599,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDisable(GL_LIGHTING); } - if(pdd.cdata){ + if(pdd->cdata){ glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(3, GL_FLOAT, 0, pdd.cdata); + glColorPointer(3, GL_FLOAT, 0, pdd->cdata); } /* draw created data arrays */ @@ -3670,14 +3623,17 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDrawArrays(GL_POINTS, 0, totpoint); break; } + + pdd->flag |= PARTICLE_DRAW_DATA_UPDATED; + pdd->totpoint = totpoint; } - if(pdd.vedata){ + if(pdd->vedata){ glDisableClientState(GL_COLOR_ARRAY); cpack(0xC0C0C0); glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pdd.vedata); + glVertexPointer(3, GL_FLOAT, 0, pdd->vedata); glDrawArrays(GL_LINES, 0, 2*totve); } @@ -3694,14 +3650,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if(states) MEM_freeN(states); - if(pdd.vdata) - MEM_freeN(pdd.vdata); - if(pdd.vedata) - MEM_freeN(pdd.vedata); - if(pdd.cdata) - MEM_freeN(pdd.cdata); - if(pdd.ndata) - MEM_freeN(pdd.ndata); psys->flag &= ~PSYS_DRAWING; @@ -3728,10 +3676,8 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obj float *pathcol = NULL, *pcol; - if(edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED) { + if(edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED) PE_update_object(scene, ob, 0); - edit->psys->flag &= ~PSYS_HAIR_UPDATED; - } /* create path and child path cache if it doesn't exist already */ if(edit->pathcache==0) @@ -4762,8 +4708,9 @@ static void drawtexspace(Object *ob) } /* draws wire outline */ -static void drawSolidSelect(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base) +static void drawSolidSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base) { + RegionView3D *rv3d= ar->regiondata; Object *ob= base->object; glLineWidth(2.0); @@ -4782,7 +4729,7 @@ static void drawSolidSelect(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base } else if(ob->type==OB_ARMATURE) { if(!(ob->mode & OB_MODE_POSE)) - draw_armature(scene, v3d, rv3d, base, OB_WIRE, 0); + draw_armature(scene, v3d, ar, base, OB_WIRE, 0); } glLineWidth(1.0); @@ -4892,11 +4839,11 @@ void drawRBpivot(bRigidBodyJointConstraint *data) glVertex3fv(v); glEnd(); if (axis==0) - view3d_object_text_draw_add(v[0], v[1], v[2], "px", 0); + view3d_cached_text_draw_add(v[0], v[1], v[2], "px", 0); else if (axis==1) - view3d_object_text_draw_add(v[0], v[1], v[2], "py", 0); + view3d_cached_text_draw_add(v[0], v[1], v[2], "py", 0); else - view3d_object_text_draw_add(v[0], v[1], v[2], "pz", 0); + view3d_cached_text_draw_add(v[0], v[1], v[2], "pz", 0); } glLineWidth (1.0f); setlinestyle(0); @@ -4939,6 +4886,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) } } + /* no return after this point, otherwise leaks */ + view3d_cached_text_draw_begin(); + /* draw keys? */ #if 0 // XXX old animation system if(base==(scene->basact) || (base->flag & (SELECT+BA_WAS_SEL))) { @@ -5123,7 +5073,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) if(dt>OB_WIRE && dt<OB_TEXTURE && ob!=scene->obedit && (flag && DRAW_SCENESET)==0) { if (!(ob->dtx&OB_DRAWWIRE) && (ob->flag&SELECT) && !(flag&DRAW_PICKING)) { - drawSolidSelect(scene, v3d, rv3d, base); + drawSolidSelect(scene, v3d, ar, base); } } } @@ -5269,7 +5219,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) break; case OB_ARMATURE: if(dt>OB_WIRE) GPU_enable_material(0, NULL); // we use default material - empty_object= draw_armature(scene, v3d, rv3d, base, dt, flag); + empty_object= draw_armature(scene, v3d, ar, base, dt, flag); if(dt>OB_WIRE) GPU_disable_material(); break; default: @@ -5289,10 +5239,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) wmLoadMatrix(rv3d->viewmat); + view3d_cached_text_draw_begin(); + for(psys=ob->particlesystem.first; psys; psys=psys->next) draw_new_particle_system(scene, v3d, rv3d, base, psys, dt); - view3d_particle_text_draw(v3d, ar); + view3d_cached_text_draw_end(v3d, ar, 0, NULL); wmMultMatrix(ob->obmat); @@ -5360,12 +5312,57 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) { if(!smd->domain->wt || !(smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { +// #if 0 smd->domain->tex = NULL; GPU_create_smoke(smd, 0); draw_volume(scene, ar, v3d, base, smd->domain->tex, smd->domain->p0, smd->domain->p1, smd->domain->res, smd->domain->dx, smd->domain->tex_shadow); GPU_free_smoke(smd); +// #endif +#if 0 + int x, y, z; + float *density = smoke_get_density(smd->domain->fluid); + + wmLoadMatrix(rv3d->viewmat); + // wmMultMatrix(ob->obmat); + + if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); + glDepthMask(GL_FALSE); + glEnable(GL_BLEND); + + + // glPointSize(3.0); + bglBegin(GL_POINTS); + + for(x = 0; x < smd->domain->res[0]; x++) + for(y = 0; y < smd->domain->res[1]; y++) + for(z = 0; z < smd->domain->res[2]; z++) + { + float tmp[3]; + int index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z); + + if(density[index] > FLT_EPSILON) + { + float color[3]; + VECCOPY(tmp, smd->domain->p0); + tmp[0] += smd->domain->dx * x + smd->domain->dx * 0.5; + tmp[1] += smd->domain->dx * y + smd->domain->dx * 0.5; + tmp[2] += smd->domain->dx * z + smd->domain->dx * 0.5; + color[0] = color[1] = color[2] = density[index]; + glColor3fv(color); + bglVertex3fv(tmp); + } + } + + bglEnd(); + glPointSize(1.0); + + wmMultMatrix(ob->obmat); + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); + if(col) cpack(col); +#endif } - else if(smd->domain->wt || (smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) + else if(smd->domain->wt && (smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { smd->domain->tex = NULL; GPU_create_smoke(smd, 1); @@ -5399,7 +5396,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) /* patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing */ /* but, we also dont draw names for sets or duplicators */ if(flag == 0) { - view3d_object_text_draw_add(0.0f, 0.0f, 0.0f, ob->id.name+2, 10); + view3d_cached_text_draw_add(0.0f, 0.0f, 0.0f, ob->id.name+2, 10); } } /*if(dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/ @@ -5422,7 +5419,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) } /* return warning, this is cached text draw */ - view3d_object_text_draw(v3d, ar); + view3d_cached_text_draw_end(v3d, ar, 1, NULL); wmLoadMatrix(rv3d->viewmat); diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index cc4cb4771e7..ef3627e2b12 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -169,7 +169,6 @@ static int larger_pow2(int n) void draw_volume(Scene *scene, ARegion *ar, View3D *v3d, Base *base, GPUTexture *tex, float *min, float *max, int res[3], float dx, GPUTexture *tex_shadow) { - Object *ob = base->object; RegionView3D *rv3d= ar->regiondata; float viewnormal[3]; @@ -223,7 +222,7 @@ void draw_volume(Scene *scene, ARegion *ar, View3D *v3d, Base *base, GPUTexture "MUL temp.b, temp.b, shadow.r;\n" "MOV result.color, temp;\n" "END\n"; - unsigned int prog; + GLuint prog; float size[3]; @@ -328,10 +327,10 @@ void draw_volume(Scene *scene, ARegion *ar, View3D *v3d, Base *base, GPUTexture // printf("i: %d\n", i); - if(GLEW_ARB_fragment_program) + if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) { - glGenProgramsARB(1, &prog); glEnable(GL_FRAGMENT_PROGRAM_ARB); + glGenProgramsARB(1, &prog); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text); @@ -342,11 +341,13 @@ void draw_volume(Scene *scene, ARegion *ar, View3D *v3d, Base *base, GPUTexture glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0); } else - printf("Your gfx card does not support 3dview smoke drawing."); + printf("Your gfx card does not support 3dview smoke drawing.\n"); GPU_texture_bind(tex, 0); if(tex_shadow) GPU_texture_bind(tex_shadow, 1); + else + printf("No volume shadow\n"); if (!GLEW_ARB_texture_non_power_of_two) { cor[0] = (float)res[0]/(float)larger_pow2(res[0]); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 2250c2e7718..6e415ec731d 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -190,6 +190,8 @@ static SpaceLink *view3d_new(const bContext *C) v3d->lens= 35.0f; v3d->near= 0.01f; v3d->far= 500.0f; + + v3d->twtype= V3D_MANIP_TRANSLATE; /* header */ ar= MEM_callocN(sizeof(ARegion), "header for view3d"); @@ -257,7 +259,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) if(v3do->localvd) { v3do->localvd= NULL; v3do->properties_storage= NULL; - v3do->localview= 0; v3do->lay= v3dn->localvd->lay; v3do->lay &= 0xFFFFFF; } @@ -273,101 +274,68 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) return (SpaceLink *)v3dn; } -static void view3d_modal_keymaps(wmWindowManager *wm, ARegion *ar, int stype) -{ - RegionView3D *rv3d= ar->regiondata; - ListBase *keymap; - - /* copy last mode, then we can re-init the region maps */ - rv3d->lastmode= stype; - - keymap= WM_keymap_listbase(wm, "Object Mode", 0, 0); - if(ELEM(stype, 0, NS_MODE_OBJECT)) - WM_event_add_keymap_handler(&ar->handlers, keymap); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); - - keymap= WM_keymap_listbase(wm, "EditMesh", 0, 0); - if(stype==NS_EDITMODE_MESH) - WM_event_add_keymap_handler(&ar->handlers, keymap); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); - - keymap= WM_keymap_listbase(wm, "Curve", 0, 0); - if(stype==NS_EDITMODE_CURVE) - WM_event_add_keymap_handler(&ar->handlers, keymap); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); - - keymap= WM_keymap_listbase(wm, "Armature", 0, 0); - if(stype==NS_EDITMODE_ARMATURE) - WM_event_add_keymap_handler(&ar->handlers, keymap); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); - - keymap= WM_keymap_listbase(wm, "Pose", 0, 0); - if(stype==NS_MODE_POSE) - WM_event_add_keymap_handler(&ar->handlers, keymap); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); - - keymap= WM_keymap_listbase(wm, "Metaball", 0, 0); - if(stype==NS_EDITMODE_MBALL) - WM_event_add_keymap_handler(&ar->handlers, keymap); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); - - keymap= WM_keymap_listbase(wm, "Lattice", 0, 0); - if(stype==NS_EDITMODE_LATTICE) - WM_event_add_keymap_handler(&ar->handlers, keymap); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); - - /* armature sketching needs to take over mouse */ - keymap= WM_keymap_listbase(wm, "Armature_Sketch", 0, 0); - if(stype==NS_EDITMODE_ARMATURE) - WM_event_add_keymap_handler_priority(&ar->handlers, keymap, 10); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); - - keymap= WM_keymap_listbase(wm, "Particle", 0, 0); - if(stype==NS_MODE_PARTICLE) - WM_event_add_keymap_handler(&ar->handlers, keymap); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); - - /* editfont keymap swallows all... */ - keymap= WM_keymap_listbase(wm, "Font", 0, 0); - if(stype==NS_EDITMODE_TEXT) - WM_event_add_keymap_handler_priority(&ar->handlers, keymap, 10); - else - WM_event_remove_keymap_handler(&ar->handlers, keymap); -} - /* add handlers, stuff you only do once or on area/region changes */ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar) { - RegionView3D *rv3d= ar->regiondata; - ListBase *keymap; + wmKeyMap *keymap; + + /* object ops. */ + keymap= WM_keymap_find(wm, "Object Non-modal", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + /* pose is not modal, operator poll checks for this */ + keymap= WM_keymap_find(wm, "Pose", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - /* own keymap */ - keymap= WM_keymap_listbase(wm, "View3D Generic", SPACE_VIEW3D, 0); + keymap= WM_keymap_find(wm, "Object Mode", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + keymap= WM_keymap_find(wm, "Image Paint", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + keymap= WM_keymap_find(wm, "Vertex Paint", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + keymap= WM_keymap_find(wm, "Weight Paint", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + keymap= WM_keymap_find(wm, "Sculpt", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap= WM_keymap_listbase(wm, "View3D", SPACE_VIEW3D, 0); + + keymap= WM_keymap_find(wm, "EditMesh", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); - /* object ops. */ - keymap= WM_keymap_listbase(wm, "Object Non-modal", 0, 0); + keymap= WM_keymap_find(wm, "Curve", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); - /* pose is not modal, operator poll checks for this */ - keymap= WM_keymap_listbase(wm, "Pose", 0, 0); + keymap= WM_keymap_find(wm, "Armature", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + keymap= WM_keymap_find(wm, "Pose", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + keymap= WM_keymap_find(wm, "Metaball", 0, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); - /* modal ops keymaps */ - view3d_modal_keymaps(wm, ar, rv3d->lastmode); - /* operator poll checks for modes */ - keymap= WM_keymap_listbase(wm, "ImagePaint", 0, 0); + keymap= WM_keymap_find(wm, "Lattice", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + /* armature sketching needs to take over mouse */ + keymap= WM_keymap_find(wm, "Armature_Sketch", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + keymap= WM_keymap_find(wm, "Particle", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + /* editfont keymap swallows all... */ + keymap= WM_keymap_find(wm, "Font", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + /* own keymap, last so modes can override it */ + keymap= WM_keymap_find(wm, "View3D Generic", SPACE_VIEW3D, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + + keymap= WM_keymap_find(wm, "View3D", SPACE_VIEW3D, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } @@ -442,7 +410,6 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) ED_region_tag_redraw(ar); break; case ND_MODE: - view3d_modal_keymaps(wmn->wm, ar, wmn->subtype); ED_region_tag_redraw(ar); break; } @@ -452,6 +419,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) case ND_BONE_ACTIVE: case ND_BONE_SELECT: case ND_TRANSFORM: + case ND_POSE: case ND_DRAW: case ND_MODIFIER: case ND_CONSTRAINT: @@ -514,7 +482,7 @@ static void view3d_main_area_cursor(wmWindow *win, ScrArea *sa, ARegion *ar) /* add handlers, stuff you only do once or on area/region changes */ static void view3d_header_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap= WM_keymap_listbase(wm, "View3D Generic", SPACE_VIEW3D, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "View3D Generic", SPACE_VIEW3D, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); @@ -550,11 +518,11 @@ static void view3d_header_area_listener(ARegion *ar, wmNotifier *wmn) /* add handlers, stuff you only do once or on area/region changes */ static void view3d_buttons_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; ED_region_panels_init(wm, ar); - keymap= WM_keymap_listbase(wm, "View3D Generic", SPACE_VIEW3D, 0); + keymap= WM_keymap_find(wm, "View3D Generic", SPACE_VIEW3D, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } @@ -592,6 +560,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) case ND_BONE_ACTIVE: case ND_BONE_SELECT: case ND_TRANSFORM: + case ND_POSE: case ND_DRAW: case ND_KEYS: ED_region_tag_redraw(ar); @@ -606,6 +575,10 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) break; } break; + case NC_BRUSH: + if(wmn->action==NA_EDITED) + ED_region_tag_redraw(ar); + break; case NC_SPACE: if(wmn->data == ND_SPACE_VIEW3D) ED_region_tag_redraw(ar); @@ -616,16 +589,14 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) /* add handlers, stuff you only do once or on area/region changes */ static void view3d_tools_area_init(wmWindowManager *wm, ARegion *ar) { - ListBase *keymap; + wmKeyMap *keymap; ED_region_panels_init(wm, ar); - keymap= WM_keymap_listbase(wm, "View3D Generic", SPACE_VIEW3D, 0); + keymap= WM_keymap_find(wm, "View3D Generic", SPACE_VIEW3D, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); } - - static void view3d_tools_area_draw(const bContext *C, ARegion *ar) { ED_region_panels(C, ar, 1, CTX_data_mode_string(C), -1); @@ -910,7 +881,7 @@ void ED_spacetype_view3d(void) /* regions: listview/buttons */ art= MEM_callocN(sizeof(ARegionType), "spacetype view3d region"); art->regionid = RGN_TYPE_UI; - art->minsizex= 220; // XXX + art->minsizex= 180; // XXX art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; art->listener= view3d_buttons_area_listener; art->init= view3d_buttons_area_init; diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 54a8c375e69..496db8c00f8 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -302,60 +302,68 @@ static void v3d_editvertex_buts(const bContext *C, uiBlock *block, View3D *v3d, if((ob->parent) && (ob->partype == PARBONE)) but_y = 135; else but_y = 150; - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 20, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values"); - uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 20, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values"); - uiBlockEndAlign(block); + memcpy(tfp->ve_median, median, sizeof(tfp->ve_median)); uiBlockBeginAlign(block); if(tot==1) { uiDefBut(block, LABEL, 0, "Vertex:", 0, 130, 200, 20, 0, 0, 0, 0, 0, ""); + uiBlockBeginAlign(block); uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, ""); uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:", 0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, ""); uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:", 0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, ""); - if(totw==1) - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex W:", 0, 50, 200, 19, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, ""); - uiBlockEndAlign(block); - - if(defstr[0]) { - uiDefBut(block, LABEL, 1, "Vertex Deform Groups", 0, 40, 200, 20, NULL, 0.0, 0.0, 0, 0, ""); - + + if(totw==1) { + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, ""); + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values"); + uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values"); + uiBlockEndAlign(block); + if(totweight) + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, ""); + } + else { uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_NOP, "Weight:", 10, 20, 150, 20, tfp->defweightp, 0.0f, 1.0f, 10, 3, "Weight value"); - uiDefButI(block, MENU, B_REDR, defstr, 160, 20, 140, 20, &tfp->curdef, 0.0, 0.0, 0, 0, "Current Vertex Group"); + uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values"); + uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values"); uiBlockEndAlign(block); + if(totweight) + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, ""); } - else if(totweight) - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, ""); - } else { - uiDefBut(block, LABEL, 0, "Median:", 0, 130, 200, 20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Median:", 0, 130, 200, 20, 0, 0, 0, 0, 0, ""); + uiBlockBeginAlign(block); uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, ""); uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:", 0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, ""); uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:", 0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, ""); - if(totw==tot) + if(totw==tot) { uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, ""); - uiBlockEndAlign(block); - if(totweight) - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal"); - } - - if(ob->type==OB_CURVE && (totw==0)) { /* bez curves have no w */ - uiBlockBeginAlign(block); - uiDefBut(block, BUT,B_SETPT_AUTO,"Auto", 10, 44, 72, 19, 0, 0, 0, 0, 0, "Auto handles (Shift H)"); - uiDefBut(block, BUT,B_SETPT_VECTOR,"Vector",82, 44, 73, 19, 0, 0, 0, 0, 0, "Vector handles (V)"); - uiDefBut(block, BUT,B_SETPT_ALIGN,"Align",155, 44, 73, 19, 0, 0, 0, 0, 0, "Align handles (H Toggles)"); - uiDefBut(block, BUT,B_SETPT_FREE,"Free", 227, 44, 72, 19, 0, 0, 0, 0, 0, "Align handles (H Toggles)"); - uiBlockEndAlign(block); + uiBlockEndAlign(block); + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values"); + uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values"); + uiBlockEndAlign(block); + if(totweight) + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal"); + uiBlockEndAlign(block); + } + else { + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global", 0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values"); + uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local", 100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values"); + uiBlockEndAlign(block); + if(totweight) + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal"); + uiBlockEndAlign(block); + } } - + if(totedge==1) - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease W:", 0, 45, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease:", 0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, ""); else if(totedge>1) - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Crease W:", 0, 45, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Crease:", 0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, ""); } else { // apply @@ -468,6 +476,7 @@ static void v3d_editvertex_buts(const bContext *C, uiBlock *block, View3D *v3d, } } +#if 0 /* assumes armature active */ static void validate_bonebutton_cb(bContext *C, void *bonev, void *namev) { @@ -486,10 +495,10 @@ static void validate_bonebutton_cb(bContext *C, void *bonev, void *namev) ED_armature_bone_rename(ob->data, oldname, newname); // editarmature.c } } +#endif static void v3d_posearmature_buts(uiBlock *block, View3D *v3d, Object *ob, float lim) { - uiBut *but; bArmature *arm; bPoseChannel *pchan; Bone *bone= NULL; @@ -503,22 +512,18 @@ static void v3d_posearmature_buts(uiBlock *block, View3D *v3d, Object *ob, float if(bone && (bone->flag & BONE_ACTIVE) && (bone->layer & arm->layer)) break; } - if (!pchan || !bone) return; - - if((ob->parent) && (ob->partype == PARBONE)) - but= uiDefBut (block, TEX, B_NOP, "Bone:", 160, 130, 140, 19, bone->name, 1, 31, 0, 0, ""); - else - but= uiDefBut(block, TEX, B_NOP, "Bone:", 160, 140, 140, 19, bone->name, 1, 31, 0, 0, ""); - uiButSetFunc(but, validate_bonebutton_cb, bone, NULL); - uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob); + if (!pchan) { + uiDefBut(block, LABEL, 0, "No Bone Active", 0, 240, 100, 20, 0, 0, 0, 0, 0, ""); + return; + } - if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + if (pchan->rotmode == ROT_MODE_AXISANGLE) { float quat[4]; /* convert to euler, passing through quats... */ AxisAngleToQuat(quat, &pchan->quat[1], pchan->quat[0]); QuatToEul(quat, tfp->ob_eul); } - else if (pchan->rotmode == PCHAN_ROT_QUAT) + else if (pchan->rotmode == ROT_MODE_QUAT) QuatToEul(pchan->quat, tfp->ob_eul); else VecCopyf(tfp->ob_eul, pchan->eul); @@ -526,29 +531,43 @@ static void v3d_posearmature_buts(uiBlock *block, View3D *v3d, Object *ob, float tfp->ob_eul[1]*= 180.0/M_PI; tfp->ob_eul[2]*= 180.0/M_PI; + uiDefBut(block, LABEL, 0, "Location:", 0, 240, 100, 20, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, B_REDR, ICON_UNLOCKED, 10,140,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocX:", 30, 140, 120, 19, pchan->loc, -lim, lim, 100, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, B_REDR, ICON_UNLOCKED, 10,120,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocY:", 30, 120, 120, 19, pchan->loc+1, -lim, lim, 100, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, B_REDR, ICON_UNLOCKED, 10,100,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_ARMATUREPANEL2, "LocZ:", 30, 100, 120, 19, pchan->loc+2, -lim, lim, 100, 3, ""); - + uiDefButF(block, NUM, B_ARMATUREPANEL2, "X:", 0, 220, 120, 19, pchan->loc, -lim, lim, 100, 3, ""); + uiDefButF(block, NUM, B_ARMATUREPANEL2, "Y:", 0, 200, 120, 19, pchan->loc+1, -lim, lim, 100, 3, ""); + uiDefButF(block, NUM, B_ARMATUREPANEL2, "Z:", 0, 180, 120, 19, pchan->loc+2, -lim, lim, 100, 3, ""); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, B_REDR, ICON_UNLOCKED, 125, 220, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects X Location value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, B_REDR, ICON_UNLOCKED, 125, 200, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Y Location value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, B_REDR, ICON_UNLOCKED, 125, 180, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Z Location value from being Transformed"); + uiBlockEndAlign(block); + + uiDefBut(block, LABEL, 0, "Rotation:", 0, 160, 100, 20, 0, 0, 0, 0, 0, ""); + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_ARMATUREPANEL3, "X:", 0, 140, 120, 19, tfp->ob_eul, -1000.0, 1000.0, 100, 3, ""); + uiDefButF(block, NUM, B_ARMATUREPANEL3, "Y:", 0, 120, 120, 19, tfp->ob_eul+1, -1000.0, 1000.0, 100, 3, ""); + uiDefButF(block, NUM, B_ARMATUREPANEL3, "Z:", 0, 100, 120, 19, tfp->ob_eul+2, -1000.0, 1000.0, 100, 3, ""); + uiBlockEndAlign(block); + uiBlockBeginAlign(block); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED, 10,70,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotX:", 30, 70, 120, 19, tfp->ob_eul, -1000.0, 1000.0, 100, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED, 10,50,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotY:", 30, 50, 120, 19, tfp->ob_eul+1, -1000.0, 1000.0, 100, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED, 10,30,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_ARMATUREPANEL3, "RotZ:", 30, 30, 120, 19, tfp->ob_eul+2, -1000.0, 1000.0, 100, 3, ""); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED, 125, 140, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects X Rotation value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED, 125, 120, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Y Rotation value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED, 125, 100, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Z Rotation value from being Transformed"); + uiBlockEndAlign(block); + + uiDefBut(block, LABEL, 0, "Scale:", 0, 80, 100, 20, 0, 0, 0, 0, 0, ""); + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_ARMATUREPANEL2, "X:", 0, 60, 120, 19, pchan->size, -lim, lim, 10, 3, ""); + uiDefButF(block, NUM, B_ARMATUREPANEL2, "Y:", 0, 40, 120, 19, pchan->size+1, -lim, lim, 10, 3, ""); + uiDefButF(block, NUM, B_ARMATUREPANEL2, "Z:", 0, 20, 120, 19, pchan->size+2, -lim, lim, 10, 3, ""); + uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, B_REDR, ICON_UNLOCKED, 160,70,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleX:", 180, 70, 120, 19, pchan->size, -lim, lim, 10, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, B_REDR, ICON_UNLOCKED, 160,50,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleY:", 180, 50, 120, 19, pchan->size+1, -lim, lim, 10, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, B_REDR, ICON_UNLOCKED, 160,30,20,19, &(pchan->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_ARMATUREPANEL2, "ScaleZ:", 180, 30, 120, 19, pchan->size+2, -lim, lim, 10, 3, ""); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, B_REDR, ICON_UNLOCKED, 125, 60, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects X Scale value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, B_REDR, ICON_UNLOCKED, 125, 40, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Y Scale value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, B_REDR, ICON_UNLOCKED, 125, 20, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects z Scale value from being Transformed"); uiBlockEndAlign(block); } @@ -572,7 +591,6 @@ static void v3d_editarmature_buts(uiBlock *block, View3D *v3d, Object *ob, float { bArmature *arm= ob->data; EditBone *ebone; - uiBut *but; TransformProperties *tfp= v3d->properties_storage; ebone= arm->edbo->first; @@ -585,34 +603,31 @@ static void v3d_editarmature_buts(uiBlock *block, View3D *v3d, Object *ob, float if (!ebone) return; - if((ob->parent) && (ob->partype == PARBONE)) - but= uiDefBut(block, TEX, B_NOP, "Bone:", 160, 130, 140, 19, ebone->name, 1, 31, 0, 0, ""); - else - but= uiDefBut(block, TEX, B_NOP, "Bone:", 160, 150, 140, 19, ebone->name, 1, 31, 0, 0, ""); - uiButSetFunc(but, validate_editbonebutton_cb, ebone, NULL); - + uiDefBut(block, LABEL, 0, "Head:", 0, 210, 100, 20, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadX:", 10, 70, 140, 19, ebone->head, -lim, lim, 10, 3, ""); - uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadY:", 10, 50, 140, 19, ebone->head+1, -lim, lim, 10, 3, ""); - uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadZ:", 10, 30, 140, 19, ebone->head+2, -lim, lim, 10, 3, ""); + uiDefButF(block, NUM, B_ARMATUREPANEL1, "X:", 0, 190, 100, 19, ebone->head, -lim, lim, 10, 3, "X Location of the head end of the bone"); + uiDefButF(block, NUM, B_ARMATUREPANEL1, "Y:", 0, 170, 100, 19, ebone->head+1, -lim, lim, 10, 3, "Y Location of the head end of the bone"); + uiDefButF(block, NUM, B_ARMATUREPANEL1, "Z:", 0, 150, 100, 19, ebone->head+2, -lim, lim, 10, 3, "Z Location of the head end of the bone"); + if (ebone->parent && ebone->flag & BONE_CONNECTED ) + uiDefButF(block, NUM, B_ARMATUREPANEL1, "Radius:", 0, 130, 100, 19, &ebone->parent->rad_tail, 0, lim, 10, 3, "Head radius. Visualize with the Envelope display option"); + else + uiDefButF(block, NUM, B_ARMATUREPANEL1, "Radius:", 0, 130, 100, 19, &ebone->rad_head, 0, lim, 10, 3, "Head radius. Visualize with the Envelope display option"); + uiBlockEndAlign(block); + + uiBlockEndAlign(block); + uiDefBut(block, LABEL, 0, "Tail:", 0, 110, 100, 20, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailX:", 160, 70, 140, 19, ebone->tail, -lim, lim, 10, 3, ""); - uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailY:", 160, 50, 140, 19, ebone->tail+1, -lim, lim, 10, 3, ""); - uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailZ:", 160, 30, 140, 19, ebone->tail+2, -lim, lim, 10, 3, ""); + uiDefButF(block, NUM, B_ARMATUREPANEL1, "X:", 0, 90, 100, 19, ebone->tail, -lim, lim, 10, 3, "X Location of the tail end of the bone"); + uiDefButF(block, NUM, B_ARMATUREPANEL1, "Y:", 0, 70, 100, 19, ebone->tail+1, -lim, lim, 10, 3, "Y Location of the tail end of the bone"); + uiDefButF(block, NUM, B_ARMATUREPANEL1, "Z:", 0, 50, 100, 19, ebone->tail+2, -lim, lim, 10, 3, "Z Location of the tail end of the bone"); + uiDefButF(block, NUM, B_ARMATUREPANEL1, "Radius:", 0, 30, 100, 19, &ebone->rad_tail, 0, lim, 10, 3, "Tail radius. Visualize with the Envelope display option"); uiBlockEndAlign(block); tfp->ob_eul[0]= 180.0*ebone->roll/M_PI; - uiDefButF(block, NUM, B_ARMATUREPANEL1, "Roll:", 10, 100, 140, 19, tfp->ob_eul, -lim, lim, 1000, 3, ""); - - uiDefButBitI(block, TOG, BONE_EDITMODE_LOCKED, B_REDR, "Lock", 160, 100, 140, 19, &(ebone->flag), 0, 0, 0, 0, "Prevents bone from being transformed in edit mode"); - + uiDefButF(block, NUM, B_ARMATUREPANEL1, "Roll:", 0, 0, 100, 19, tfp->ob_eul, -lim, lim, 1000, 3, "Bone rotation around head-tail axis"); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_ARMATUREPANEL1, "TailRadius:", 10, 150, 140, 19, &ebone->rad_tail, 0, lim, 10, 3, ""); - if (ebone->parent && ebone->flag & BONE_CONNECTED ) - uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadRadius:", 10, 130, 140, 19, &ebone->parent->rad_tail, 0, lim, 10, 3, ""); - else - uiDefButF(block, NUM, B_ARMATUREPANEL1, "HeadRadius:", 10, 130, 140, 19, &ebone->rad_head, 0, lim, 10, 3, ""); - uiBlockEndAlign(block); + + } static void v3d_editmetaball_buts(uiBlock *block, Object *ob, float lim) @@ -851,13 +866,13 @@ static void do_view3d_region_buttons(bContext *C, void *arg, int event) eul[1]= M_PI*tfp->ob_eul[1]/180.0; eul[2]= M_PI*tfp->ob_eul[2]/180.0; - if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + if (pchan->rotmode == ROT_MODE_AXISANGLE) { float quat[4]; /* convert to axis-angle, passing through quats */ EulToQuat(eul, quat); QuatToAxisAngle(quat, &pchan->quat[1], &pchan->quat[0]); } - else if (pchan->rotmode == PCHAN_ROT_QUAT) + else if (pchan->rotmode == ROT_MODE_QUAT) EulToQuat(eul, pchan->quat); else VecCopyf(pchan->eul, eul); @@ -1083,19 +1098,8 @@ static void view3d_panel_object(const bContext *C, Panel *pa) if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT)) { } else { - //bt= uiDefBut(block, TEX, B_IDNAME, "OB: ", 10,180,140,20, ob->id.name+2, 0.0, 21.0, 0, 0, ""); - //uiButSetFunc(bt, test_idbutton_cb, ob->id.name, NULL); - if((ob->mode & OB_MODE_PARTICLE_EDIT)==0) { - // uiBlockBeginAlign(block); - // uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_OBJECTPANELPARENT, "Par:", 160, 180, 140, 20, &ob->parent, "Parent Object"); - if((ob->parent) && (ob->partype == PARBONE)) { - // bt= uiDefBut(block, TEX, B_OBJECTPANELPARENT, "ParBone:", 160, 160, 140, 20, ob->parsubstr, 0, 30, 0, 0, ""); - // uiButSetCompleteFunc(bt, autocomplete_bone, (void *)ob->parent); - } - else { - strcpy(ob->parsubstr, ""); - } + strcpy(ob->parsubstr, ""); uiBlockEndAlign(block); } } @@ -1113,14 +1117,18 @@ static void view3d_panel_object(const bContext *C, Panel *pa) else { BoundBox *bb = NULL; - uiDefBut(block, LABEL, 0, "Location:", 10, 170, 100, 20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Location:", 0, 300, 100, 20, 0, 0, 0, 0, 0, ""); + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_OBJECTPANEL, "X:", 0, 280, 120, 19, &(ob->loc[0]), -lim, lim, 100, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANEL, "Y:", 0, 260, 120, 19, &(ob->loc[1]), -lim, lim, 100, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANEL, "Z:", 0, 240, 120, 19, &(ob->loc[2]), -lim, lim, 100, 3, ""); + uiBlockEndAlign(block); + uiBlockBeginAlign(block); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, B_REDR, ICON_UNLOCKED, 10,150,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANEL, "X:", 30, 150, 120, 19, &(ob->loc[0]), -lim, lim, 100, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, B_REDR, ICON_UNLOCKED, 10,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANEL, "Y:", 30, 130, 120, 19, &(ob->loc[1]), -lim, lim, 100, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, B_REDR, ICON_UNLOCKED, 10,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANEL, "Z:", 30, 110, 120, 19, &(ob->loc[2]), -lim, lim, 100, 3, ""); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, B_REDR, ICON_UNLOCKED, 125, 280, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects X Location value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, B_REDR, ICON_UNLOCKED, 125, 260, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects Y Location value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, B_REDR, ICON_UNLOCKED, 125, 240, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects Z Location value from being Transformed"); + uiBlockEndAlign(block); tfp->ob_eul[0]= 180.0*ob->rot[0]/M_PI; tfp->ob_eul[1]= 180.0*ob->rot[1]/M_PI; @@ -1128,40 +1136,53 @@ static void view3d_panel_object(const bContext *C, Panel *pa) uiBlockBeginAlign(block); if ((ob->parent) && (ob->partype == PARBONE)) { - uiDefBut(block, LABEL, 0, "Rotation:", 160, 170, 100, 20, 0, 0, 0, 0, 0, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED, 160,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANELROT, "X:", 180, 130, 120, 19, &(tfp->ob_eul[0]), -lim, lim, 1000, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED, 160,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANELROT, "Y:", 180, 110, 120, 19, &(tfp->ob_eul[1]), -lim, lim, 1000, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED, 160,90,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANELROT, "Z:", 180, 90, 120, 19, &(tfp->ob_eul[2]), -lim, lim, 1000, 3, ""); + uiDefBut(block, LABEL, 0, "Rotation:", 0, 220, 100, 20, 0, 0, 0, 0, 0, ""); + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_OBJECTPANELROT, "X:", 0, 200, 120, 19, &(tfp->ob_eul[0]), -lim, lim, 1000, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANELROT, "Y:", 0, 180, 120, 19, &(tfp->ob_eul[1]), -lim, lim, 1000, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANELROT, "Z:", 0, 160, 120, 19, &(tfp->ob_eul[2]), -lim, lim, 1000, 3, ""); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED, 125, 200, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects X Rotation from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED, 125, 180, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects Y Rotation value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED, 125, 160, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects Z Rotation value from being Transformed"); + uiBlockEndAlign(block); } else { - uiDefBut(block, LABEL, 0, "Rotation:", 160, 170, 100, 20, 0, 0, 0, 0, 0, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED, 160,150,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANELROT, "X:", 180, 150, 120, 19, &(tfp->ob_eul[0]), -lim, lim, 1000, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED, 160,130,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANELROT, "Y:", 180, 130, 120, 19, &(tfp->ob_eul[1]), -lim, lim, 1000, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED, 160,110,20,19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANELROT, "Z:", 180, 110, 120, 19, &(tfp->ob_eul[2]), -lim, lim, 1000, 3, ""); + uiDefBut(block, LABEL, 0, "Rotation:", 0, 220, 100, 20, 0, 0, 0, 0, 0, ""); + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_OBJECTPANELROT, "X:", 0, 200, 120, 19, &(tfp->ob_eul[0]), -lim, lim, 1000, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANELROT, "Y:", 0, 180, 120, 19, &(tfp->ob_eul[1]), -lim, lim, 1000, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANELROT, "Z:", 0, 160, 120, 19, &(tfp->ob_eul[2]), -lim, lim, 1000, 3, ""); + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED, 125, 200, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects X Rotation value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED, 125, 180, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects Y Rotation value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED, 125, 160, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects Z Rotation value from being Transformed"); + uiBlockEndAlign(block); } tfp->ob_scale[0]= ob->size[0]; tfp->ob_scale[1]= ob->size[1]; tfp->ob_scale[2]= ob->size[2]; - uiDefBut(block, LABEL, 0, "Scale:", 10, 90, 100, 20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Scale:", 0, 140, 100, 20, 0, 0, 0, 0, 0, ""); + uiDefButS(block, OPTION, B_REDR, "Link", 60, 140, 50, 19, &(tfp->link_scale), 0, 1, 0, 0, "Scale values vary proportionally in all directions"); uiBlockBeginAlign(block); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, B_REDR, ICON_UNLOCKED, 10, 70, 20, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANELSCALE, "X:", 30, 70, 120, 19, &(tfp->ob_scale[0]), -lim, lim, 10, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, B_REDR, ICON_UNLOCKED, 10, 50, 20, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANELSCALE, "Y:", 30, 50, 120, 19, &(tfp->ob_scale[1]), -lim, lim, 10, 3, ""); - uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, B_REDR, ICON_UNLOCKED, 10, 30, 20, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects this value from being Transformed"); - uiDefButF(block, NUM, B_OBJECTPANELSCALE, "Z:", 30, 30, 120, 19, &(tfp->ob_scale[2]), -lim, lim, 10, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANELSCALE, "X:", 0, 120, 120, 19, &(tfp->ob_scale[0]), -lim, lim, 10, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANELSCALE, "Y:", 0, 100, 120, 19, &(tfp->ob_scale[1]), -lim, lim, 10, 3, ""); + uiDefButF(block, NUM, B_OBJECTPANELSCALE, "Z:", 0, 80, 120, 19, &(tfp->ob_scale[2]), -lim, lim, 10, 3, ""); uiBlockEndAlign(block); - uiDefButS(block, TOG, B_REDR, "Link Scale", 10, 0, 140, 19, &(tfp->link_scale), 0, 1, 0, 0, "Scale values vary proportionally in all directions"); + uiBlockBeginAlign(block); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, B_REDR, ICON_UNLOCKED, 125, 120, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects X Scale value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, B_REDR, ICON_UNLOCKED, 125, 100, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects Y Scale value from being Transformed"); + uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, B_REDR, ICON_UNLOCKED, 125, 80, 25, 19, &(ob->protectflag), 0, 0, 0, 0, "Protects Z Scale value from being Transformed"); + + bb= object_get_boundbox(ob); if (bb) { @@ -1175,19 +1196,19 @@ static void view3d_panel_object(const bContext *C, Panel *pa) if ((ob->parent) && (ob->partype == PARBONE)) { - uiDefBut(block, LABEL, 0, "Dimensions:", 160, 90, 100, 20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Dimensions:", 0, 60, 100, 20, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_OBJECTPANELDIMS, "X:", 160, 70, 140, 19, &(tfp->ob_dims[0]), 0.0, lim, 10, 3, "Manipulate bounding box size"); - uiDefButF(block, NUM, B_OBJECTPANELDIMS, "Y:", 160, 50, 140, 19, &(tfp->ob_dims[1]), 0.0, lim, 10, 3, "Manipulate bounding box size"); - uiDefButF(block, NUM, B_OBJECTPANELDIMS, "Z:", 160, 30, 140, 19, &(tfp->ob_dims[2]), 0.0, lim, 10, 3, "Manipulate bounding box size"); + uiDefButF(block, NUM, B_OBJECTPANELDIMS, "X:", 0, 40, 150, 19, &(tfp->ob_dims[0]), 0.0, lim, 10, 3, "Manipulate X bounding box size"); + uiDefButF(block, NUM, B_OBJECTPANELDIMS, "Y:", 0, 20, 150, 19, &(tfp->ob_dims[1]), 0.0, lim, 10, 3, "Manipulate Y bounding box size"); + uiDefButF(block, NUM, B_OBJECTPANELDIMS, "Z:", 0, 0, 150, 19, &(tfp->ob_dims[2]), 0.0, lim, 10, 3, "Manipulate Z bounding box size"); } else { - uiDefBut(block, LABEL, 0, "Dimensions:", 160, 90, 100, 20, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Dimensions:", 0, 60, 100, 20, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_OBJECTPANELDIMS, "X:", 160, 70, 140, 19, &(tfp->ob_dims[0]), 0.0, lim, 10, 3, "Manipulate bounding box size"); - uiDefButF(block, NUM, B_OBJECTPANELDIMS, "Y:", 160, 50, 140, 19, &(tfp->ob_dims[1]), 0.0, lim, 10, 3, "Manipulate bounding box size"); - uiDefButF(block, NUM, B_OBJECTPANELDIMS, "Z:", 160, 30, 140, 19, &(tfp->ob_dims[2]), 0.0, lim, 10, 3, "Manipulate bounding box size"); + uiDefButF(block, NUM, B_OBJECTPANELDIMS, "X:", 0, 40, 150, 19, &(tfp->ob_dims[0]), 0.0, lim, 10, 3, "Manipulate X bounding box size"); + uiDefButF(block, NUM, B_OBJECTPANELDIMS, "Y:", 0, 20, 150, 19, &(tfp->ob_dims[1]), 0.0, lim, 10, 3, "Manipulate Y bounding box size"); + uiDefButF(block, NUM, B_OBJECTPANELDIMS, "Z:", 0, 0, 150, 19, &(tfp->ob_dims[2]), 0.0, lim, 10, 3, "Manipulate Z bounding box size"); } uiBlockEndAlign(block); @@ -1430,25 +1451,12 @@ void view3d_buttons_register(ARegionType *art) pt->draw= view3d_panel_transform_spaces; BLI_addtail(&art->paneltypes, pt); - pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil"); - strcpy(pt->idname, "VIEW3D_PT_gpencil"); - strcpy(pt->label, "Greas Pencil"); - pt->draw= view3d_panel_gpencil; - BLI_addtail(&art->paneltypes, pt);*/ - pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel bonesketch spaces"); strcpy(pt->idname, "VIEW3D_PT_bonesketch_spaces"); strcpy(pt->label, "Bone Sketching"); pt->draw= view3d_panel_bonesketch_spaces; pt->poll= view3d_panel_bonesketch_spaces_poll; BLI_addtail(&art->paneltypes, pt); - - /* - pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel redo"); - strcpy(pt->idname, "VIEW3D_PT_redo"); - strcpy(pt->label, "Last Operator"); - pt->draw= view3d_panel_operator_redo; - BLI_addtail(&art->paneltypes, pt); */ // XXX view3d_panel_preview(C, ar, 0); } @@ -1458,13 +1466,9 @@ static int view3d_properties(bContext *C, wmOperator *op) ScrArea *sa= CTX_wm_area(C); ARegion *ar= view3d_has_buttons_region(sa); - if(ar) { - ar->flag ^= RGN_FLAG_HIDDEN; - ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */ - - ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); - ED_area_tag_redraw(sa); - } + if(ar) + ED_region_toggle_hidden(C, ar); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 918aebda8e1..5612e60e899 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -732,7 +732,7 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d) char *name = view3d_get_name(v3d, rv3d); char *printable = NULL; - if (v3d->localview) { + if (v3d->localvd) { printable = malloc(strlen(name) + strlen(" (Local)_")); /* '_' gives space for '\0' */ strcpy(printable, name); strcat(printable, " (Local)"); @@ -745,7 +745,7 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d) BLF_draw_default(22, ar->winy-17, 0.0f, printable); } - if (v3d->localview) { + if (v3d->localvd) { free(printable); } } @@ -1416,12 +1416,9 @@ static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - -// glaDefine2DArea(&ar->winrct); + /* need to use wm push/pop matrix because ED_region_pixelspace + uses the wm functions too, otherwise gets out of sync */ + wmPushMatrix(); ED_region_pixelspace(ar); glEnable(GL_BLEND); @@ -1433,10 +1430,7 @@ static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d) glPixelZoom(1.0, 1.0); glPixelTransferf(GL_ALPHA_SCALE, 1.0f); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + wmPopMatrix(); glDisable(GL_BLEND); if(v3d->zbuf) glEnable(GL_DEPTH_TEST); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index bbcee0415f8..c07d9108993 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -239,9 +239,10 @@ typedef struct ViewOpsData { float ofs[3], obofs[3]; float reverse, dist0; float grid, far; + short axis_snap; /* view rotate only */ int origx, origy, oldx, oldy; - int origkey; + int origkey; /* the key that triggered the operator */ } ViewOpsData; @@ -289,7 +290,7 @@ static void viewops_data(bContext *C, wmOperator *op, wmEvent *event) QUATCOPY(vod->oldquat, rv3d->viewquat); vod->origx= vod->oldx= event->x; vod->origy= vod->oldy= event->y; - vod->origkey= event->type; + vod->origkey= event->type; /* the key that triggered the operator. */ /* lookup, we dont pass on v3d to prevent confusement */ vod->grid= v3d->grid; @@ -357,11 +358,52 @@ static float snapquats[39][6] = { {0.0, 0.0, 0.0, 1.0, 0, 0} }; +enum { + VIEW_PASS= 0, + VIEW_APPLY, + VIEW_CONFIRM +}; + +/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ +#define VIEW_MODAL_CONFIRM 1 /* used for all view operations */ +#define VIEWROT_MODAL_AXIS_SNAP_ENABLE 2 +#define VIEWROT_MODAL_AXIS_SNAP_DISABLE 3 + + +/* called in transform_ops.c, on each regeneration of keymaps */ +void viewrotate_modal_keymap(wmWindowManager *wm) +{ + static EnumPropertyItem modal_items[] = { + {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Cancel", ""}, + + {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Enable Axis Snap", ""}, + {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Enable Axis Snap", ""}, + + {0, NULL, 0, NULL, NULL}}; + + wmKeyMap *keymap= WM_modalkeymap_get(wm, "View3D Rotate Modal"); -static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl) + /* this function is called for each spacetype, only needs to add map once */ + if(keymap) return; + + keymap= WM_modalkeymap_add(wm, "View3D Rotate Modal", modal_items); + + /* items for modal map */ + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); + + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_ENABLE); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_AXIS_SNAP_DISABLE); + + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate"); + +} + +static void viewrotate_apply(ViewOpsData *vod, int x, int y) { RegionView3D *rv3d= vod->rv3d; - int use_sel= 0; /* XXX */ + int use_sel= U.uiflag & USER_ORBIT_SELECTION; rv3d->view= 0; /* need to reset everytime because of view snapping */ @@ -462,7 +504,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl) } /* check for view snap */ - if (ctrl){ + if (vod->axis_snap){ int i; float viewmat[3][3]; @@ -496,23 +538,41 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl) static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event) { ViewOpsData *vod= op->customdata; + short event_code= VIEW_PASS; /* execute the events */ - switch(event->type) { - case MOUSEMOVE: - viewrotate_apply(vod, event->x, event->y, event->ctrl); - break; + if(event->type==MOUSEMOVE) { + event_code= VIEW_APPLY; + } + else if(event->type==EVT_MODAL_MAP) { + switch (event->val) { + case VIEW_MODAL_CONFIRM: + event_code= VIEW_CONFIRM; + break; + case VIEWROT_MODAL_AXIS_SNAP_ENABLE: + vod->axis_snap= TRUE; + event_code= VIEW_APPLY; + break; + case VIEWROT_MODAL_AXIS_SNAP_DISABLE: + vod->axis_snap= FALSE; + event_code= VIEW_APPLY; + break; + } + } + else if(event->type==vod->origkey && event->val==KM_RELEASE) { + event_code= VIEW_CONFIRM; + } - default: - /* origkey may be zero when invoked from a button */ - if(ELEM3(event->type, ESCKEY, LEFTMOUSE, RIGHTMOUSE) || (event->type==vod->origkey && event->val==0)) { - request_depth_update(CTX_wm_region_view3d(C)); + if(event_code==VIEW_APPLY) { + viewrotate_apply(vod, event->x, event->y); + } + else if (event_code==VIEW_CONFIRM) { + request_depth_update(CTX_wm_region_view3d(C)); - MEM_freeN(vod); - op->customdata= NULL; + MEM_freeN(vod); + op->customdata= NULL; - return OPERATOR_FINISHED; - } + return OPERATOR_FINISHED; } return OPERATOR_RUNNING_MODAL; @@ -541,19 +601,19 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) } /* add temp handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } -void VIEW3D_OT_viewrotate(wmOperatorType *ot) +void VIEW3D_OT_rotate(wmOperatorType *ot) { /* identifiers */ ot->name= "Rotate view"; ot->description = "Rotate the view."; - ot->idname= "VIEW3D_OT_viewrotate"; + ot->idname= "VIEW3D_OT_rotate"; /* api callbacks */ ot->invoke= viewrotate_invoke; @@ -566,6 +626,33 @@ void VIEW3D_OT_viewrotate(wmOperatorType *ot) /* ************************ viewmove ******************************** */ + +/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ + +/* called in transform_ops.c, on each regeneration of keymaps */ +void viewmove_modal_keymap(wmWindowManager *wm) +{ + static EnumPropertyItem modal_items[] = { + {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + + {0, NULL, 0, NULL, NULL}}; + + wmKeyMap *keymap= WM_modalkeymap_get(wm, "View3D Move Modal"); + + /* this function is called for each spacetype, only needs to add map once */ + if(keymap) return; + + keymap= WM_modalkeymap_add(wm, "View3D Move Modal", modal_items); + + /* items for modal map */ + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); + + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_move"); +} + + static void viewmove_apply(ViewOpsData *vod, int x, int y) { if(vod->rv3d->persp==V3D_CAMOB) { @@ -596,24 +683,35 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y) static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) { + ViewOpsData *vod= op->customdata; + short event_code= VIEW_PASS; /* execute the events */ - switch(event->type) { - case MOUSEMOVE: - viewmove_apply(vod, event->x, event->y); - break; + if(event->type==MOUSEMOVE) { + event_code= VIEW_APPLY; + } + else if(event->type==EVT_MODAL_MAP) { + switch (event->val) { + case VIEW_MODAL_CONFIRM: + event_code= VIEW_CONFIRM; + break; + } + } + else if(event->type==vod->origkey && event->val==KM_RELEASE) { + event_code= VIEW_CONFIRM; + } - default: - /* origkey may be zero when invoked from a button */ - if(ELEM3(event->type, ESCKEY, LEFTMOUSE, RIGHTMOUSE) || (event->type==vod->origkey && event->val==0)) { - request_depth_update(CTX_wm_region_view3d(C)); + if(event_code==VIEW_APPLY) { + viewmove_apply(vod, event->x, event->y); + } + else if (event_code==VIEW_CONFIRM) { + request_depth_update(CTX_wm_region_view3d(C)); - MEM_freeN(vod); - op->customdata= NULL; + MEM_freeN(vod); + op->customdata= NULL; - return OPERATOR_FINISHED; - } + return OPERATOR_FINISHED; } return OPERATOR_RUNNING_MODAL; @@ -625,19 +723,19 @@ static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) viewops_data(C, op, event); /* add temp handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } -void VIEW3D_OT_viewmove(wmOperatorType *ot) +void VIEW3D_OT_move(wmOperatorType *ot) { /* identifiers */ ot->name= "Move view"; ot->description = "Move the view."; - ot->idname= "VIEW3D_OT_viewmove"; + ot->idname= "VIEW3D_OT_move"; /* api callbacks */ ot->invoke= viewmove_invoke; @@ -650,6 +748,29 @@ void VIEW3D_OT_viewmove(wmOperatorType *ot) /* ************************ viewzoom ******************************** */ +/* called in transform_ops.c, on each regeneration of keymaps */ +void viewzoom_modal_keymap(wmWindowManager *wm) +{ + static EnumPropertyItem modal_items[] = { + {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + + {0, NULL, 0, NULL, NULL}}; + + wmKeyMap *keymap= WM_modalkeymap_get(wm, "View3D Zoom Modal"); + + /* this function is called for each spacetype, only needs to add map once */ + if(keymap) return; + + keymap= WM_modalkeymap_add(wm, "View3D Zoom Modal", modal_items); + + /* items for modal map */ + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); + + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom"); +} + static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) { RegionView3D *rv3d= ar->regiondata; @@ -758,23 +879,33 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y) static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event) { ViewOpsData *vod= op->customdata; + short event_code= VIEW_PASS; /* execute the events */ - switch(event->type) { - case MOUSEMOVE: - viewzoom_apply(vod, event->x, event->y); - break; + if(event->type==MOUSEMOVE) { + event_code= VIEW_APPLY; + } + else if(event->type==EVT_MODAL_MAP) { + switch (event->val) { + case VIEW_MODAL_CONFIRM: + event_code= VIEW_CONFIRM; + break; + } + } + else if(event->type==vod->origkey && event->val==KM_RELEASE) { + event_code= VIEW_CONFIRM; + } - default: - /* origkey may be zero when invoked from a button */ - if(ELEM3(event->type, ESCKEY, LEFTMOUSE, RIGHTMOUSE) || (event->type==vod->origkey && event->val==0)) { - request_depth_update(CTX_wm_region_view3d(C)); + if(event_code==VIEW_APPLY) { + viewzoom_apply(vod, event->x, event->y); + } + else if (event_code==VIEW_CONFIRM) { + request_depth_update(CTX_wm_region_view3d(C)); - MEM_freeN(vod); - op->customdata= NULL; + MEM_freeN(vod); + op->customdata= NULL; - return OPERATOR_FINISHED; - } + return OPERATOR_FINISHED; } return OPERATOR_RUNNING_MODAL; @@ -823,7 +954,7 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) viewops_data(C, op, event); /* add temp handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -925,7 +1056,7 @@ static int viewhome_exec(bContext *C, wmOperator *op) /* was view3d_home() in 2. void VIEW3D_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name= "View home"; + ot->name= "View All"; ot->description = "View all objects in scene."; ot->idname= "VIEW3D_OT_view_all"; @@ -1064,7 +1195,7 @@ void VIEW3D_OT_view_center(wmOperatorType *ot) { /* identifiers */ - ot->name= "View center"; + ot->name= "View Selected"; ot->description = "Move the view to the selection center."; ot->idname= "VIEW3D_OT_view_center"; @@ -1628,7 +1759,7 @@ static int viewpersportho_exec(bContext *C, wmOperator *op) void VIEW3D_OT_view_persportho(wmOperatorType *ot) { /* identifiers */ - ot->name= "View persp/ortho"; + ot->name= "View Persp/Ortho"; ot->description = "Switch the current view from perspective/orthographic."; ot->idname= "VIEW3D_OT_view_persportho"; @@ -1850,8 +1981,7 @@ static int set_3dcursor_invoke(bContext *C, wmOperator *op, wmEvent *event) // XXX notifier for scene */ ED_area_tag_redraw(CTX_wm_area(C)); - /* prevent other mouse ops to fail */ - return OPERATOR_PASS_THROUGH; + return OPERATOR_FINISHED; } void VIEW3D_OT_cursor3d(wmOperatorType *ot) @@ -2339,7 +2469,7 @@ void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode) if (use_sel) { QuatConj(q1); /* conj == inv for unit quat */ - VecSubf(v3d->ofs, v3d->ofs, obofs); + VecSubf(rv3d->ofs, rv3d->ofs, obofs); QuatMulVecf(q1, rv3d->ofs); VecAddf(rv3d->ofs, rv3d->ofs, obofs); } diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index a633969d557..45828d654aa 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -177,7 +177,7 @@ static void handle_view3d_lock(bContext *C) View3D *v3d= CTX_wm_view3d(C); if (v3d != NULL && sa != NULL) { - if(v3d->localview==0 && v3d->scenelock && sa->spacetype==SPACE_VIEW3D) { + if(v3d->localvd==NULL && v3d->scenelock && sa->spacetype==SPACE_VIEW3D) { /* copy to scene */ scene->lay= v3d->lay; @@ -195,27 +195,38 @@ static int layers_exec(bContext *C, wmOperator *op) View3D *v3d= sa->spacedata.first; int nr= RNA_int_get(op->ptr, "nr"); - if(nr<=0) + if(nr < 0) return OPERATOR_CANCELLED; - nr--; - - if(RNA_boolean_get(op->ptr, "extend")) - v3d->lay |= (1<<nr); - else - v3d->lay = (1<<nr); - - /* set active layer, ensure to always have one */ - if(v3d->lay & (1<<nr)) - v3d->layact= 1<<nr; - else if((v3d->lay & v3d->layact)==0) { - int bit= 0; + + + if(nr == 0) { + /* all layers */ + v3d->lay |= (1<<20)-1; + + if(!v3d->layact) + v3d->layact= 1; + } + else { + nr--; + + if(RNA_boolean_get(op->ptr, "extend")) + v3d->lay |= (1<<nr); + else + v3d->lay = (1<<nr); - while(bit<32) { - if(v3d->lay & (1<<bit)) { - v3d->layact= 1<<bit; - break; + /* set active layer, ensure to always have one */ + if(v3d->lay & (1<<nr)) + v3d->layact= 1<<nr; + else if((v3d->lay & v3d->layact)==0) { + int bit= 0; + + while(bit<32) { + if(v3d->lay & (1<<bit)) { + v3d->layact= 1<<bit; + break; + } + bit++; } - bit++; } } @@ -263,8 +274,8 @@ void VIEW3D_OT_layers(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - RNA_def_int(ot->srna, "nr", 1, 0, 20, "Number", "", 0, 20); - RNA_def_boolean(ot->srna, "extend", 0, "Extend", ""); + RNA_def_int(ot->srna, "nr", 1, 0, 20, "Number", "The layer number to set, zero for all layers", 0, 20); + RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Add this layer to the current view layers"); } #if 0 @@ -1801,8 +1812,10 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event) ED_area_tag_redraw(sa); break; case B_NDOF: + ED_area_tag_redraw(sa); break; case B_MAN_MODE: + ED_area_tag_redraw(sa); break; case B_VIEW_BUTSEDIT: break; @@ -2076,7 +2089,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) } /* LAYERS */ - if(obedit==NULL && v3d->localview==0) { + if(obedit==NULL && v3d->localvd==NULL) { int ob_lay = ob ? ob->lay : 0; uiBlockBeginAlign(block); for(a=0; a<5; a++) { diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 7dbea44b68b..e7ab79ab955 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -66,8 +66,8 @@ void view3d_keymap(struct wmWindowManager *wm); /* view3d_edit.c */ void VIEW3D_OT_zoom(struct wmOperatorType *ot); -void VIEW3D_OT_viewmove(struct wmOperatorType *ot); -void VIEW3D_OT_viewrotate(struct wmOperatorType *ot); +void VIEW3D_OT_move(struct wmOperatorType *ot); +void VIEW3D_OT_rotate(struct wmOperatorType *ot); void VIEW3D_OT_view_all(struct wmOperatorType *ot); void VIEW3D_OT_viewnumpad(struct wmOperatorType *ot); void VIEW3D_OT_view_center(struct wmOperatorType *ot); @@ -89,10 +89,13 @@ int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt); void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int dt, int outline); void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob); void drawaxes(float size, int flag, char drawtype); -void view3d_object_text_draw_add(float x, float y, float z, char *str, short xoffs); + +void view3d_cached_text_draw_begin(void); +void view3d_cached_text_draw_add(float x, float y, float z, char *str, short xoffs); +void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, float mat[][4]); /* drawarmature.c */ -int draw_armature(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt, int flag); +int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, int flag); /* drawmesh.c */ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, struct DerivedMesh *dm, int faceselect); @@ -121,6 +124,7 @@ void VIEW3D_OT_smoothview(struct wmOperatorType *ot); void VIEW3D_OT_setcameratoview(struct wmOperatorType *ot); void VIEW3D_OT_localview(struct wmOperatorType *ot); void VIEW3D_OT_game_start(struct wmOperatorType *ot); +void VIEW3D_OT_fly(struct wmOperatorType *ot); int boundbox_clip(RegionView3D *rv3d, float obmat[][4], struct BoundBox *bb); @@ -132,6 +136,11 @@ void smooth_view(struct bContext *C, Object *, Object *, float *ofs, float *quat void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect); /* rect: for picking */ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d); +void fly_modal_keymap(struct wmWindowManager *wm); +void viewrotate_modal_keymap(struct wmWindowManager *wm); +void viewmove_modal_keymap(struct wmWindowManager *wm); +void viewzoom_modal_keymap(struct wmWindowManager *wm); + /* view3d_buttons.c */ void VIEW3D_OT_properties(struct wmOperatorType *ot); void view3d_buttons_register(struct ARegionType *art); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 7da2e591b10..f9cedbd28a1 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -62,8 +62,8 @@ void view3d_operatortypes(void) { - WM_operatortype_append(VIEW3D_OT_viewrotate); - WM_operatortype_append(VIEW3D_OT_viewmove); + WM_operatortype_append(VIEW3D_OT_rotate); + WM_operatortype_append(VIEW3D_OT_move); WM_operatortype_append(VIEW3D_OT_zoom); WM_operatortype_append(VIEW3D_OT_view_all); WM_operatortype_append(VIEW3D_OT_viewnumpad); @@ -85,6 +85,7 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_drawtype); WM_operatortype_append(VIEW3D_OT_localview); WM_operatortype_append(VIEW3D_OT_game_start); + WM_operatortype_append(VIEW3D_OT_fly); WM_operatortype_append(VIEW3D_OT_layers); WM_operatortype_append(VIEW3D_OT_properties); @@ -103,44 +104,28 @@ void view3d_operatortypes(void) void view3d_keymap(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "View3D Generic", SPACE_VIEW3D, 0); + wmKeyMap *keymap; wmKeymapItem *km; + keymap= WM_keymap_find(wm, "View3D Generic", SPACE_VIEW3D, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_properties", NKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_toolbar", TKEY, KM_PRESS, 0, 0); /* only for region 3D window */ - keymap= WM_keymap_listbase(wm, "View3D", SPACE_VIEW3D, 0); - - /* paint poll checks mode */ - WM_keymap_verify_item(keymap, "PAINT_OT_vertex_paint", LEFTMOUSE, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "PAINT_OT_weight_paint", LEFTMOUSE, KM_PRESS, 0, 0); - - WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "PAINT_OT_sample_color", RIGHTMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "PAINT_OT_clone_cursor_set", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); - - WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - - /* sketch poll checks mode */ - WM_keymap_add_item(keymap, "SKETCH_OT_gesture", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, 0, 0); - km = WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0); - RNA_boolean_set(km->ptr, "snap", 1); - WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, 0, 0); - km = WM_keymap_add_item(keymap, "SKETCH_OT_draw_preview", MOUSEMOVE, KM_ANY, KM_CTRL, 0); - RNA_boolean_set(km->ptr, "snap", 1); + keymap= WM_keymap_find(wm, "View3D", SPACE_VIEW3D, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, 0, 0); /* manipulator always on left mouse, not on action mouse*/ WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "VIEW3D_OT_viewrotate", MIDDLEMOUSE, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "VIEW3D_OT_viewmove", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); + WM_keymap_verify_item(keymap, "VIEW3D_OT_rotate", MIDDLEMOUSE, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "VIEW3D_OT_move", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_view_center", PADPERIOD, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "VIEW3D_OT_fly", FKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0); RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_zoom", PADPLUSKEY, KM_PRESS, 0, 0)->ptr, "delta", 1); @@ -175,6 +160,7 @@ void view3d_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "VIEW3D_OT_game_start", PKEY, KM_PRESS, 0, 0); /* layers, shift + alt are properties set in invoke() */ + RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ACCENTGRAVEKEY, KM_PRESS, 0, 0)->ptr, "nr", 0); RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ONEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 1); RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", TWOKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 2); RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", THREEKEY, KM_PRESS, KM_ANY, 0)->ptr, "nr", 3); @@ -201,7 +187,25 @@ void view3d_keymap(wmWindowManager *wm) /* selection*/ WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); - RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1); + RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", TRUE); + RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "center", TRUE); + RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "enumerate", TRUE); + + /* selection key-combinations */ + km = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0); + RNA_boolean_set(km->ptr, "center", TRUE); + RNA_boolean_set(km->ptr, "extend", TRUE); + km = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL|KM_ALT, 0); + RNA_boolean_set(km->ptr, "center", TRUE); + RNA_boolean_set(km->ptr, "enumerate", TRUE); + km = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_ALT, 0); + RNA_boolean_set(km->ptr, "extend", TRUE); + RNA_boolean_set(km->ptr, "enumerate", TRUE); + km = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL|KM_ALT, 0); + RNA_boolean_set(km->ptr, "center", TRUE); + RNA_boolean_set(km->ptr, "extend", TRUE); + RNA_boolean_set(km->ptr, "enumerate", TRUE); + WM_keymap_add_item(keymap, "VIEW3D_OT_select_border", BKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT|KM_CTRL, 0)->ptr, "deselect", 1); @@ -214,20 +218,12 @@ void view3d_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "VIEW3D_OT_camera_to_view", PAD0, KM_PRESS, KM_ALT|KM_CTRL, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_snap_menu", SKEY, KM_PRESS, KM_SHIFT, 0); - - /* radial control */ - RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE); - RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH); - RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", WM_RADIALCONTROL_ANGLE); - - RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_vertex_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE); - RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE); - RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_texture_paint_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE); - RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_vertex_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH); - RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_weight_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH); - RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_texture_paint_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH); transform_keymap_for_space(wm, keymap, SPACE_VIEW3D); + fly_modal_keymap(wm); + viewrotate_modal_keymap(wm); + viewmove_modal_keymap(wm); + viewzoom_modal_keymap(wm); } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index a7696d9fe31..a37e916064c 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -53,6 +53,7 @@ #include "BLI_blenlib.h" #include "BLI_editVert.h" #include "BLI_rand.h" +#include "BLI_linklist.h" #include "BKE_action.h" #include "BKE_context.h" @@ -845,56 +846,87 @@ static void deselectall_except(Scene *scene, Base *b) /* deselect all except b } } -static Base *mouse_select_menu(ViewContext *vc, unsigned int *buffer, int hits, short *mval) +static Base *mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, short *mval, short extend) { - Scene *scene= vc->scene; - View3D *v3d= vc->v3d; - Base *baseList[SEL_MENU_SIZE]={NULL}; /*baseList is used to store all possible bases to bring up a menu */ - Base *base; short baseCount = 0; - char menuText[20 + SEL_MENU_SIZE*32] = "Select Object%t"; /* max ob name = 22 */ - char str[32]; - - for(base=FIRSTBASE; base; base= base->next) { - if (BASE_SELECTABLE(v3d, base)) { - baseList[baseCount] = NULL; - - /* two selection methods, the CTRL select uses max dist of 15 */ - if(buffer) { - int a; - for(a=0; a<hits; a++) { - /* index was converted */ - if(base->selcol==buffer[ (4 * a) + 3 ]) baseList[baseCount] = base; - } - } - else { - int temp, dist=15; - - project_short(vc->ar, base->object->obmat[3], &base->sx); - - temp= abs(base->sx -mval[0]) + abs(base->sy -mval[1]); - if(temp<dist ) baseList[baseCount] = base; + short ok; + LinkNode *linklist= NULL; + + CTX_DATA_BEGIN(C, Base*, base, selectable_bases) { + ok= FALSE; + + /* two selection methods, the CTRL select uses max dist of 15 */ + if(buffer) { + int a; + for(a=0; a<hits; a++) { + /* index was converted */ + if(base->selcol==buffer[ (4 * a) + 3 ]) + ok= TRUE; } + } + else { + int temp, dist=15; + + project_short(vc->ar, base->object->obmat[3], &base->sx); - if(baseList[baseCount]) { - if (baseCount < SEL_MENU_SIZE) { - baseList[baseCount] = base; - sprintf(str, "|%s %%x%d", base->object->id.name+2, baseCount+1); /* max ob name == 22 */ - strcat(menuText, str); - baseCount++; - } - } + temp= abs(base->sx -mval[0]) + abs(base->sy -mval[1]); + if(temp < dist) + ok= TRUE; + } + + if(ok) { + baseCount++; + BLI_linklist_prepend(&linklist, base); + + if (baseCount==SEL_MENU_SIZE) + break; } } + CTX_DATA_END; + + if(baseCount) - if(baseCount<=1) return baseList[0]; + + if(baseCount==0) { + return NULL; + } + if(baseCount == 1) { + Base *base= (Base *)linklist->link; + BLI_linklist_free(linklist, NULL); + return base; + } else { - baseCount = -1; // XXX = pupmenu(menuText); - - if (baseCount != -1) { /* If nothing is selected then dont do anything */ - return baseList[baseCount-1]; + /* UI */ + uiPopupMenu *pup= uiPupMenuBegin(C, "Select Object", 0); + uiLayout *layout= uiPupMenuLayout(pup); + uiLayout *split= uiLayoutSplit(layout, 0); + uiLayout *column= uiLayoutColumn(split, 0); + LinkNode *node; + + node= linklist; + while(node) { + Base *base=node->link; + Object *ob= base->object; + char *name= ob->id.name+2; + /* annoying!, since we need to set 2 props cant use this. */ + /* uiItemStringO(column, name, 0, "OBJECT_OT_select_name", "name", name); */ + + { + PointerRNA ptr; + + WM_operator_properties_create(&ptr, "OBJECT_OT_select_name"); + RNA_string_set(&ptr, "name", name); + RNA_boolean_set(&ptr, "extend", extend); + uiItemFullO(column, name, uiIconFromID((ID *)ob), "OBJECT_OT_select_name", ptr.data, WM_OP_EXEC_DEFAULT, 0); + } + + node= node->next; } - else return NULL; + + uiPupMenuEnd(C, pup); + + BLI_linklist_free(linklist, NULL); + return NULL; } } @@ -958,14 +990,13 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff /* mval is region coords */ -static void mouse_select(bContext *C, short *mval, short extend, short obcenter) +static void mouse_select(bContext *C, short *mval, short extend, short obcenter, short enumerate) { ViewContext vc; ARegion *ar= CTX_wm_region(C); View3D *v3d= CTX_wm_view3d(C); Scene *scene= CTX_data_scene(C); Base *base, *startbase=NULL, *basact=NULL, *oldbasact=NULL; - unsigned int buffer[4*MAXPICKBUF]; int temp, a, dist=100; short hits; @@ -981,10 +1012,9 @@ static void mouse_select(bContext *C, short *mval, short extend, short obcenter) if(vc.obedit==NULL && obcenter) { /* note; shift+alt goes to group-flush-selecting */ - /* XXX solve */ - if(0) - basact= mouse_select_menu(&vc, NULL, 0, mval); - else { + if(enumerate) { + basact= mouse_select_menu(C, &vc, NULL, 0, mval, extend); + } else { base= startbase; while(base) { if (BASE_SELECTABLE(v3d, base)) { @@ -1006,6 +1036,8 @@ static void mouse_select(bContext *C, short *mval, short extend, short obcenter) } } else { + unsigned int buffer[4*MAXPICKBUF]; + /* if objects have posemode set, the bones are in the same selection buffer */ hits= mixed_bones_object_selectbuffer(&vc, buffer, mval); @@ -1016,9 +1048,9 @@ static void mouse_select(bContext *C, short *mval, short extend, short obcenter) for(a=0; a<hits; a++) if(buffer[4*a+3] & 0xFFFF0000) has_bones= 1; /* note; shift+alt goes to group-flush-selecting */ - if(has_bones==0 && 0) - basact= mouse_select_menu(&vc, buffer, hits, mval); - else { + if(has_bones==0 && enumerate) { + basact= mouse_select_menu(C, &vc, buffer, hits, mval, extend); + } else { static short lastmval[2]={-100, -100}; int donearest= 0; @@ -1116,7 +1148,7 @@ static void mouse_select(bContext *C, short *mval, short extend, short obcenter) WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, basact->object); /* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */ - if(basact->object->mode & OB_MODE_WEIGHT_PAINT) { + if(BASACT && BASACT->object->mode & OB_MODE_WEIGHT_PAINT) { /* prevent activating */ basact= NULL; } @@ -1560,7 +1592,7 @@ void VIEW3D_OT_select_border(wmOperatorType *ot) RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); - RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everyting first."); + RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first."); } /* ****** Mouse Select ****** */ @@ -1571,6 +1603,8 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event) Object *obedit= CTX_data_edit_object(C); Object *obact= CTX_data_active_object(C); short extend= RNA_boolean_get(op->ptr, "extend"); + short center= RNA_boolean_get(op->ptr, "center"); + short enumerate= RNA_boolean_get(op->ptr, "enumerate"); view3d_operator_needs_opengl(C); @@ -1590,7 +1624,7 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event) else if(obact && obact->mode & OB_MODE_PARTICLE_EDIT) PE_mouse_particles(C, event->mval, extend); else - mouse_select(C, event->mval, extend, 0); + mouse_select(C, event->mval, extend, center, enumerate); /* allowing tweaks */ return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED; @@ -1611,7 +1645,9 @@ void VIEW3D_OT_select(wmOperatorType *ot) ot->flag= OPTYPE_UNDO; /* properties */ - RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everyting first."); + RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first."); + RNA_def_boolean(ot->srna, "center", 0, "Center", "Use the object center when selecting (object mode only)."); + RNA_def_boolean(ot->srna, "enumerate", 0, "Enumerate", "List objects under the mouse (object mode only)."); } diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index b4b54cd1d88..767f18649fa 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -1122,13 +1122,13 @@ static int snap_menu_invoke(bContext *C, wmOperator *unused, wmEvent *event) uiPopupMenu *pup= uiPupMenuBegin(C, "Snap", 0); uiLayout *layout= uiPupMenuLayout(pup); - uiItemO(layout, NULL, 0, "VIEW3D_OT_snap_selected_to_grid"); - uiItemO(layout, NULL, 0, "VIEW3D_OT_snap_selected_to_cursor"); - uiItemO(layout, NULL, 0, "VIEW3D_OT_snap_selected_to_center"); + uiItemO(layout, "Selected to Grid", 0, "VIEW3D_OT_snap_selected_to_grid"); + uiItemO(layout, "Selected to Cursor", 0, "VIEW3D_OT_snap_selected_to_cursor"); + uiItemO(layout, "Selected to Center", 0, "VIEW3D_OT_snap_selected_to_center"); uiItemS(layout); - uiItemO(layout, NULL, 0, "VIEW3D_OT_snap_cursor_to_selected"); - uiItemO(layout, NULL, 0, "VIEW3D_OT_snap_cursor_to_grid"); - uiItemO(layout, NULL, 0, "VIEW3D_OT_snap_cursor_to_active"); + uiItemO(layout, "Cursor to Selected", 0, "VIEW3D_OT_snap_cursor_to_selected"); + uiItemO(layout, "Cursor to Grid", 0, "VIEW3D_OT_snap_cursor_to_grid"); + uiItemO(layout, "Cursor to Active", 0, "VIEW3D_OT_snap_cursor_to_active"); uiPupMenuEnd(C, pup); diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index 58248f675da..e1c6f70bde0 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -163,7 +163,7 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa) if(op==NULL) return; - if(op->type->poll && op->type->poll((bContext *)C)==0) + if(WM_operator_poll((bContext*)C, op->type) == 0) return; block= uiLayoutGetBlock(pa->layout); @@ -208,7 +208,7 @@ static void operator_search_cb(const struct bContext *C, void *arg, char *str, u for(; ot; ot= ot->next) { if(BLI_strcasestr(ot->name, str)) { - if(ot->poll==NULL || ot->poll((bContext *)C)) { + if(WM_operator_poll((bContext*)C, ot)) { if(0==uiSearchItemAdd(items, ot->name, ot, 0)) break; @@ -309,13 +309,9 @@ static int view3d_toolbar(bContext *C, wmOperator *op) ScrArea *sa= CTX_wm_area(C); ARegion *ar= view3d_has_tools_region(sa); - if(ar) { - ar->flag ^= RGN_FLAG_HIDDEN; - ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */ - - ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa); - ED_area_tag_redraw(sa); - } + if(ar) + ED_region_toggle_hidden(C, ar); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 7831d604ddf..f722a97963d 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -56,9 +56,11 @@ #include "BKE_object.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_utildefines.h" +#include "BKE_depsgraph.h" /* for fly mode updating */ #include "RE_pipeline.h" // make_stars @@ -110,7 +112,7 @@ void view3d_operator_needs_opengl(const bContext *C) float *give_cursor(Scene *scene, View3D *v3d) { - if(v3d && v3d->localview) return v3d->cursor; + if(v3d && v3d->localvd) return v3d->cursor; else return scene->cursor; } @@ -384,26 +386,31 @@ void VIEW3D_OT_smoothview(wmOperatorType *ot) ot->poll= ED_operator_view3d_active; } -static int view3d_setcameratoview_exec(bContext *C, wmOperator *op) +static void setcameratoview3d(View3D *v3d, RegionView3D *rv3d, Object *ob) { - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d= CTX_wm_region_view3d(C); - Object *ob; float dvec[3]; - ob= v3d->camera; 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); - VecSubf(ob->loc, ob->loc, v3d->ofs); + VecSubf(ob->loc, ob->loc, rv3d->ofs); rv3d->viewquat[0]= -rv3d->viewquat[0]; QuatToEul(rv3d->viewquat, ob->rot); rv3d->viewquat[0]= -rv3d->viewquat[0]; ob->recalc= OB_RECALC_OB; +} + + +static int view3d_setcameratoview_exec(bContext *C, wmOperator *op) +{ + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d= CTX_wm_region_view3d(C); + + setcameratoview3d(v3d, rv3d, v3d->camera); WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, CTX_data_scene(C)); @@ -1303,7 +1310,6 @@ static void initlocalview(Scene *scene, ScrArea *sa) base->object->lay= base->lay; } } - v3d->localview= 0; } } @@ -1325,7 +1331,6 @@ static void restore_localviewdata(ScrArea *sa, int free) if(free) { MEM_freeN(v3d->localvd); v3d->localvd= NULL; - v3d->localview= 0; } for(ar= sa->regionbase.first; ar; ar= ar->next) { @@ -1416,8 +1421,6 @@ static void SaveState(bContext *C) glPushAttrib(GL_ALL_ATTRIB_BITS); - GPU_state_init(); - if(obact && obact->mode & OB_MODE_TEXTURE_PAINT) GPU_paint_set_mipmap(1); @@ -1446,6 +1449,8 @@ static void RestoreState(bContext *C) win->queue= queue_back; + GPU_state_init(); + glPopAttrib(); } @@ -1574,6 +1579,802 @@ void VIEW3D_OT_game_start(wmOperatorType *ot) ot->poll= game_engine_poll; } + +/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ +#define FLY_MODAL_CANCEL 1 +#define FLY_MODAL_CONFIRM 2 +#define FLY_MODAL_ACCELERATE 3 +#define FLY_MODAL_DECELERATE 4 +#define FLY_MODAL_PAN_ENABLE 5 +#define FLY_MODAL_PAN_DISABLE 6 +#define FLY_MODAL_DIR_FORWARD 7 +#define FLY_MODAL_DIR_BACKWARD 8 +#define FLY_MODAL_DIR_LEFT 9 +#define FLY_MODAL_DIR_RIGHT 10 +#define FLY_MODAL_DIR_UP 11 +#define FLY_MODAL_DIR_DOWN 12 +#define FLY_MODAL_AXIS_LOCK_X 13 +#define FLY_MODAL_AXIS_LOCK_Z 14 +#define FLY_MODAL_PRECISION_ENABLE 15 +#define FLY_MODAL_PRECISION_DISABLE 16 + +/* called in transform_ops.c, on each regeneration of keymaps */ +void fly_modal_keymap(wmWindowManager *wm) +{ + static EnumPropertyItem modal_items[] = { + {FLY_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, + {FLY_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + {FLY_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""}, + {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, + + {FLY_MODAL_PAN_ENABLE, "PAN_ENABLE", 0, "Pan Enable", ""}, + {FLY_MODAL_PAN_DISABLE, "PAN_DISABLE", 0, "Pan Disable", ""}, + + {FLY_MODAL_DIR_FORWARD, "FORWARD", 0, "Fly Forward", ""}, + {FLY_MODAL_DIR_BACKWARD,"BACKWARD", 0, "Fly Backward", ""}, + {FLY_MODAL_DIR_LEFT, "LEFT", 0, "Fly Left", ""}, + {FLY_MODAL_DIR_RIGHT, "RIGHT", 0, "Fly Right", ""}, + {FLY_MODAL_DIR_UP, "UP", 0, "Fly Up", ""}, + {FLY_MODAL_DIR_DOWN, "DOWN", 0, "Fly Down", ""}, + + {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"}, + {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"}, + + {FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision Enable", ""}, + {FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision Disable", ""}, + + {0, NULL, 0, NULL, NULL}}; + + wmKeyMap *keymap= WM_modalkeymap_get(wm, "View3D Fly Modal"); + + /* this function is called for each spacetype, only needs to add map once */ + if(keymap) return; + + keymap= WM_modalkeymap_add(wm, "View3D Fly Modal", modal_items); + + /* items for modal map */ + WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, FLY_MODAL_CANCEL); + WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_ANY, KM_ANY, 0, FLY_MODAL_CANCEL); + + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_ANY, KM_ANY, 0, FLY_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, FLY_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, FLY_MODAL_CONFIRM); + + WM_modalkeymap_add_item(keymap, PADPLUSKEY, KM_PRESS, 0, 0, FLY_MODAL_ACCELERATE); + WM_modalkeymap_add_item(keymap, PADMINUS, KM_PRESS, 0, 0, FLY_MODAL_DECELERATE); + WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, FLY_MODAL_ACCELERATE); + WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, FLY_MODAL_DECELERATE); + + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_PRESS, KM_ANY, 0, FLY_MODAL_PAN_ENABLE); + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, FLY_MODAL_PAN_DISABLE); /* XXX - Bug in the event system, middle mouse release doesnt work */ + + /* WASD */ + WM_modalkeymap_add_item(keymap, WKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_FORWARD); + WM_modalkeymap_add_item(keymap, SKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_BACKWARD); + WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_LEFT); + WM_modalkeymap_add_item(keymap, DKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_RIGHT); + WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_UP); + WM_modalkeymap_add_item(keymap, FKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_DOWN); + + WM_modalkeymap_add_item(keymap, XKEY, KM_PRESS, 0, 0, FLY_MODAL_AXIS_LOCK_X); + WM_modalkeymap_add_item(keymap, ZKEY, KM_PRESS, 0, 0, FLY_MODAL_AXIS_LOCK_Z); + + WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, FLY_MODAL_PRECISION_ENABLE); + WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, FLY_MODAL_PRECISION_DISABLE); + + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly"); + +} + +typedef struct FlyInfo { + /* context stuff */ + RegionView3D *rv3d; + View3D *v3d; + ARegion *ar; + Scene *scene; + + wmTimer *timer; /* needed for redraws */ + + short state; + short use_precision; + short redraw; + short mval[2]; + + /* fly state state */ + float speed; /* the speed the view is moving per redraw */ + short axis; /* Axis index to move allong by default Z to move allong the view */ + short pan_view; /* when true, pan the view instead of rotating */ + + /* relative view axis locking - xlock, zlock + 0; disabled + 1; enabled but not checking because mouse hasnt moved outside the margin since locking was checked an not needed + when the mouse moves, locking is set to 2 so checks are done. + 2; mouse moved and checking needed, if no view altering is donem its changed back to 1 */ + short xlock, zlock; + float xlock_momentum, zlock_momentum; /* nicer dynamics */ + float grid; /* world scale 1.0 default */ + + /* 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 */ + + /* compare between last state */ + double time_lastwheel; /* used to accelerate when using the mousewheel a lot */ + double time_lastdraw; /* time between draws */ + + /* use for some lag */ + float dvec_prev[3]; /* old for some lag */ + +} FlyInfo; + +/* FlyInfo->state */ +#define FLY_RUNNING 0 +#define FLY_CANCEL 1 +#define FLY_CONFIRM 2 + +int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event) +{ + float upvec[3]; // tmp + float mat[3][3]; + + fly->rv3d= CTX_wm_region_view3d(C); + fly->v3d = CTX_wm_view3d(C); + fly->ar = CTX_wm_region(C); + fly->scene= CTX_data_scene(C); + + if(fly->rv3d->persp==V3D_CAMOB && fly->v3d->camera->id.lib) { + BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); + return FALSE; + } + + if(fly->v3d->ob_centre) { + BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view is locked to an object"); + return FALSE; + } + + if(fly->rv3d->persp==V3D_CAMOB && fly->v3d->camera->constraints.first) { + BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints"); + return FALSE; + } + + fly->state= FLY_RUNNING; + fly->speed= 0.0f; + fly->axis= 2; + fly->pan_view= FALSE; + fly->xlock= FALSE; + fly->zlock= TRUE; + fly->xlock_momentum=0.0f; + fly->zlock_momentum=0.0f; + fly->grid= 1.0f; + fly->use_precision= 0; + + fly->dvec_prev[0]= fly->dvec_prev[1]= fly->dvec_prev[2]= 0.0f; + + fly->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f); + + + /* we have to rely on events to give proper mousecoords after a warp_pointer */ +//XXX2.5 warp_pointer(cent_orig[0], cent_orig[1]); + //fly->mval[0]= (fly->sa->winx)/2; + //fly->mval[1]= (fly->sa->winy)/2; + + fly->mval[0] = event->x - fly->ar->winrct.xmin; + fly->mval[1] = event->y - fly->ar->winrct.ymin; + + + fly->time_lastdraw= fly->time_lastwheel= PIL_check_seconds_timer(); + + fly->rv3d->rflag |= RV3D_FLYMODE; /* so we draw the corner margins */ + + /* detect weather to start with Z locking */ + upvec[0]=1.0f; upvec[1]=0.0f; upvec[2]=0.0f; + Mat3CpyMat4(mat, fly->rv3d->viewinv); + Mat3MulVecfl(mat, upvec); + if (fabs(upvec[2]) < 0.1) + fly->zlock = 1; + upvec[0]=0; upvec[1]=0; upvec[2]=0; + + fly->persp_backup= fly->rv3d->persp; + fly->dist_backup= fly->rv3d->dist; + if (fly->rv3d->persp==V3D_CAMOB) { + /* store the origoinal camera loc and rot */ + VECCOPY(fly->ofs_backup, fly->v3d->camera->loc); + VECCOPY(fly->rot_backup, fly->v3d->camera->rot); + + where_is_object(fly->scene, fly->v3d->camera); + VECCOPY(fly->rv3d->ofs, fly->v3d->camera->obmat[3]); + VecMulf(fly->rv3d->ofs, -1.0f); /*flip the vector*/ + + fly->rv3d->dist=0.0; + fly->rv3d->viewbut=0; + + /* used for recording */ +//XXX2.5 if(v3d->camera->ipoflag & OB_ACTION_OB) +//XXX2.5 actname= "Object"; + + } else { + /* perspective or ortho */ + if (fly->rv3d->persp==V3D_ORTHO) + fly->rv3d->persp= V3D_PERSP; /*if ortho projection, make perspective */ + QUATCOPY(fly->rot_backup, fly->rv3d->viewquat); + VECCOPY(fly->ofs_backup, fly->rv3d->ofs); + fly->rv3d->dist= 0.0; + + upvec[2]= fly->dist_backup; /*x and y are 0*/ + Mat3MulVecfl(mat, upvec); + VecSubf(fly->rv3d->ofs, fly->rv3d->ofs, upvec); + /*Done with correcting for the dist*/ + } + + return 1; +} + +static int flyEnd(bContext *C, FlyInfo *fly) +{ + RegionView3D *rv3d= fly->rv3d; + View3D *v3d = fly->v3d; + + float upvec[3]; + + if(fly->state == FLY_RUNNING) + return OPERATOR_RUNNING_MODAL; + + WM_event_remove_window_timer(CTX_wm_window(C), fly->timer); + + rv3d->dist= fly->dist_backup; + + if (fly->state == FLY_CANCEL) { + /* Revert to original view? */ + if (fly->persp_backup==V3D_CAMOB) { /* a camera view */ + rv3d->viewbut=1; + VECCOPY(v3d->camera->loc, fly->ofs_backup); + VECCOPY(v3d->camera->rot, fly->rot_backup); + DAG_id_flush_update(&v3d->camera->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); + VECCOPY(rv3d->ofs, fly->ofs_backup); + rv3d->persp= fly->persp_backup; + } + } + else if (fly->persp_backup==V3D_CAMOB) { /* camera */ + float mat3[3][3]; + Mat3CpyMat4(mat3, v3d->camera->obmat); + Mat3ToCompatibleEul(mat3, v3d->camera->rot, fly->rot_backup); + + DAG_id_flush_update(&v3d->camera->id, OB_RECALC_OB); +#if 0 //XXX2.5 + if (IS_AUTOKEY_MODE(NORMAL)) { + allqueue(REDRAWIPO, 0); + allspace(REMAKEIPO, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWTIME, 0); + } +#endif + } + else { /* not camera */ + /* Apply the fly mode view */ + /*restore the dist*/ + float mat[3][3]; + upvec[0]= upvec[1]= 0; + upvec[2]= fly->dist_backup; /*x and y are 0*/ + Mat3CpyMat4(mat, rv3d->viewinv); + Mat3MulVecfl(mat, upvec); + VecAddf(rv3d->ofs, rv3d->ofs, upvec); + /*Done with correcting for the dist */ + } + + rv3d->rflag &= ~RV3D_FLYMODE; +//XXX2.5 BIF_view3d_previewrender_signal(fly->sa, PR_DBASE|PR_DISPRECT); /* not working at the moment not sure why */ + + + if(fly->state == FLY_CONFIRM) { + MEM_freeN(fly); + return OPERATOR_FINISHED; + } + + MEM_freeN(fly); + return OPERATOR_CANCELLED; +} + +void flyEvent(FlyInfo *fly, wmEvent *event) +{ + if (event->type == TIMER) { + fly->redraw = 1; + } + else if (event->type == MOUSEMOVE) { + fly->mval[0] = event->x - fly->ar->winrct.xmin; + fly->mval[1] = event->y - fly->ar->winrct.ymin; + } /* handle modal keymap first */ + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case FLY_MODAL_CANCEL: + fly->state = FLY_CANCEL; + break; + case FLY_MODAL_CONFIRM: + fly->state = FLY_CONFIRM; + break; + + case FLY_MODAL_ACCELERATE: + { + double time_currwheel; + float time_wheel; + + time_currwheel= PIL_check_seconds_timer(); + time_wheel = (float)(time_currwheel - fly->time_lastwheel); + fly->time_lastwheel = time_currwheel; + /*printf("Wheel %f\n", time_wheel);*/ + /*Mouse wheel delays range from 0.5==slow to 0.01==fast*/ + time_wheel = 1+ (10 - (20*MIN2(time_wheel, 0.5))); /* 0-0.5 -> 0-5.0 */ + + if (fly->speed<0.0f) fly->speed= 0.0f; + else { + if (event->shift) + fly->speed+= fly->grid*time_wheel*0.1; + else + fly->speed+= fly->grid*time_wheel; + } + break; + } + case FLY_MODAL_DECELERATE: + { + double time_currwheel; + float time_wheel; + + time_currwheel= PIL_check_seconds_timer(); + time_wheel = (float)(time_currwheel - fly->time_lastwheel); + fly->time_lastwheel = time_currwheel; + time_wheel = 1+ (10 - (20*MIN2(time_wheel, 0.5))); /* 0-0.5 -> 0-5.0 */ + + if (fly->speed>0) fly->speed=0; + else { + if (event->shift) + fly->speed-= fly->grid*time_wheel*0.1; + else + fly->speed-= fly->grid*time_wheel; + } + break; + } + case FLY_MODAL_PAN_ENABLE: + fly->pan_view= TRUE; + break; + case FLY_MODAL_PAN_DISABLE: +//XXX2.5 warp_pointer(cent_orig[0], cent_orig[1]); + fly->pan_view= FALSE; + break; + + /* impliment WASD keys */ + case FLY_MODAL_DIR_FORWARD: + if (fly->speed < 0.0f) fly->speed= -fly->speed; /* flip speed rather then stopping, game like motion */ + else fly->speed += fly->grid; /* increse like mousewheel if were alredy moving in that difection*/ + fly->axis= 2; + break; + case FLY_MODAL_DIR_BACKWARD: + if (fly->speed>0) fly->speed= -fly->speed; + else fly->speed -= fly->grid; + fly->axis= 2; + break; + case FLY_MODAL_DIR_LEFT: + if (fly->speed < 0.0f) fly->speed= -fly->speed; + fly->axis= 0; + break; + case FLY_MODAL_DIR_RIGHT: + if (fly->speed > 0.0f) fly->speed= -fly->speed; + fly->axis= 0; + break; + + case FLY_MODAL_DIR_UP: + if (fly->speed < 0.0f) fly->speed= -fly->speed; + fly->axis= 1; + break; + + case FLY_MODAL_DIR_DOWN: + if (fly->speed > 0.0f) fly->speed= -fly->speed; + fly->axis= 1; + break; + + case FLY_MODAL_AXIS_LOCK_X: + if (fly->xlock) fly->xlock=0; + else { + fly->xlock = 2; + fly->xlock_momentum = 0.0; + } + break; + case FLY_MODAL_AXIS_LOCK_Z: + if (fly->zlock) fly->zlock=0; + else { + fly->zlock = 2; + fly->zlock_momentum = 0.0; + } + break; + + case FLY_MODAL_PRECISION_ENABLE: + fly->use_precision= TRUE; + break; + case FLY_MODAL_PRECISION_DISABLE: + fly->use_precision= FALSE; + break; + + } + } +} + +//int fly_exec(bContext *C, wmOperator *op) +int flyApply(FlyInfo *fly) +{ + /* + fly mode - Shift+F + a fly loop where the user can move move the view as if they are flying + */ + RegionView3D *rv3d= fly->rv3d; + View3D *v3d = fly->v3d; + ARegion *ar = fly->ar; + Scene *scene= fly->scene; + + 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 */ + + /* Camera Uprighting variables */ + upvec[3]={0,0,0}, /* stores the view's up vector */ + + moffset[2], /* mouse offset from the views center */ + tmp_quat[4]; /* used for rotating the view */ + + int cent_orig[2], /* view center */ +//XXX- can avoid using // cent[2], /* view center modified */ + xmargin, ymargin; /* x and y margin are define the safe area where the mouses movement wont rotate the view */ + unsigned char + apply_rotation= 1; /* if the user presses shift they can look about without movinf the direction there looking*/ + + /* for recording */ +#if 0 //XXX2.5 todo, get animation recording working again. + int playing_anim = 0; //XXX has_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM); + int cfra = -1; /*so the first frame always has a key added */ + char *actname=""; +#endif + /* 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 + want to rotate about the viewers center. + but to correct the dist removal we must + alter offset so the view doesn't jump. */ + + xmargin= ar->winx/20.0f; + ymargin= ar->winy/20.0f; + + cent_orig[0]= ar->winrct.xmin + ar->winx/2; + cent_orig[1]= ar->winrct.ymin + ar->winy/2; + + { + + /* mouse offset from the center */ + moffset[0]= fly->mval[0]- ar->winx/2; + moffset[1]= fly->mval[1]- ar->winy/2; + + /* enforce a view margin */ + if (moffset[0]>xmargin) moffset[0]-=xmargin; + else if (moffset[0] < -xmargin) moffset[0]+=xmargin; + else moffset[0]=0; + + if (moffset[1]>ymargin) moffset[1]-=ymargin; + else if (moffset[1] < -ymargin) moffset[1]+=ymargin; + else moffset[1]=0; + + + /* scale the mouse movement by this value - scales mouse movement to the view size + * moffset[0]/(ar->winx-xmargin*2) - window size minus margin (same for y) + * + * the mouse moves isnt linear */ + + if(moffset[0]) { + moffset[0] /= ar->winx - (xmargin*2); + moffset[0] *= fabs(moffset[0]); + } + + if(moffset[1]) { + moffset[1] /= ar->winy - (ymargin*2); + moffset[1] *= fabs(moffset[1]); + } + + /* Should we redraw? */ + if(fly->speed != 0.0f || moffset[0] || moffset[1] || fly->zlock || fly->xlock || dvec[0] || dvec[1] || dvec[2] ) { + float dvec_tmp[3]; + double time_current, time_redraw; /*time how fast it takes for us to redraw, this is so simple scenes dont fly too fast */ + float time_redraw_clamped; + + time_current= PIL_check_seconds_timer(); + time_redraw= (float)(time_current - fly->time_lastdraw); + time_redraw_clamped= MIN2(0.05f, time_redraw); /* clamt the redraw time to avoid jitter in roll correction */ + fly->time_lastdraw= time_current; + /*fprintf(stderr, "%f\n", time_redraw);*/ /* 0.002 is a small redraw 0.02 is larger */ + + /* Scale the time to use shift to scale the speed down- just like + shift slows many other areas of blender down */ + if (fly->use_precision) + fly->speed= fly->speed * (1.0f-time_redraw_clamped); + + Mat3CpyMat4(mat, rv3d->viewinv); + + if (fly->pan_view==TRUE) { + /* pan only */ + dvec_tmp[0]= -moffset[0]; + dvec_tmp[1]= -moffset[1]; + dvec_tmp[2]= 0; + + if (fly->use_precision) { + dvec_tmp[0] *= 0.1; + dvec_tmp[1] *= 0.1; + } + + Mat3MulVecfl(mat, dvec_tmp); + VecMulf(dvec_tmp, time_redraw*200.0 * fly->grid); + + } else { + float roll; /* similar to the angle between the camera's up and the Z-up, but its very rough so just roll*/ + + /* rotate about the X axis- look up/down */ + if (moffset[1]) { + upvec[0]=1; + upvec[1]=0; + upvec[2]=0; + Mat3MulVecfl(mat, upvec); + VecRotToQuat( upvec, (float)moffset[1]*-time_redraw*20, tmp_quat); /* Rotate about the relative up vec */ + QuatMul(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + if (fly->xlock) fly->xlock = 2; /*check for rotation*/ + if (fly->zlock) fly->zlock = 2; + fly->xlock_momentum= 0.0f; + } + + /* rotate about the Y axis- look left/right */ + if (moffset[0]) { + + /* if we're upside down invert the moffset */ + upvec[0]=0; + upvec[1]=1; + upvec[2]=0; + Mat3MulVecfl(mat, upvec); + + if(upvec[2] < 0.0f) + moffset[0]= -moffset[0]; + + /* make the lock vectors */ + if (fly->zlock) { + upvec[0]=0; + upvec[1]=0; + upvec[2]=1; + } else { + upvec[0]=0; + upvec[1]=1; + upvec[2]=0; + Mat3MulVecfl(mat, upvec); + } + + VecRotToQuat( upvec, (float)moffset[0]*time_redraw*20, tmp_quat); /* Rotate about the relative up vec */ + QuatMul(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + if (fly->xlock) fly->xlock = 2;/*check for rotation*/ + if (fly->zlock) fly->zlock = 2; + } + + if (fly->zlock==2) { + upvec[0]=1; + upvec[1]=0; + upvec[2]=0; + Mat3MulVecfl(mat, upvec); + + /*make sure we have some z rolling*/ + if (fabs(upvec[2]) > 0.00001f) { + roll= upvec[2]*5; + upvec[0]=0; /*rotate the view about this axis*/ + upvec[1]=0; + upvec[2]=1; + + Mat3MulVecfl(mat, upvec); + VecRotToQuat( upvec, roll*time_redraw_clamped*fly->zlock_momentum*0.1, tmp_quat); /* Rotate about the relative up vec */ + QuatMul(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + fly->zlock_momentum += 0.05f; + } else { + fly->zlock=1; /* dont check until the view rotates again */ + fly->zlock_momentum= 0.0f; + } + } + + if (fly->xlock==2 && moffset[1]==0) { /*only apply xcorrect when mouse isnt applying x rot*/ + upvec[0]=0; + upvec[1]=0; + upvec[2]=1; + Mat3MulVecfl(mat, upvec); + /*make sure we have some z rolling*/ + if (fabs(upvec[2]) > 0.00001) { + roll= upvec[2] * -5; + + upvec[0]= 1.0f; /*rotate the view about this axis*/ + upvec[1]= 0.0f; + upvec[2]= 0.0f; + + Mat3MulVecfl(mat, upvec); + + VecRotToQuat( upvec, roll*time_redraw_clamped*fly->xlock_momentum*0.1f, tmp_quat); /* Rotate about the relative up vec */ + QuatMul(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + fly->xlock_momentum += 0.05f; + } else { + fly->xlock=1; /* see above */ + fly->xlock_momentum= 0.0f; + } + } + + + if (apply_rotation) { + /* Normal operation */ + /* define dvec, view direction vector */ + dvec_tmp[0]= dvec_tmp[1]= dvec_tmp[2]= 0.0f; + /* move along the current axis */ + dvec_tmp[fly->axis]= 1.0f; + + Mat3MulVecfl(mat, dvec_tmp); + + VecMulf(dvec_tmp, fly->speed * time_redraw * 0.25f); + } + } + + /* impose a directional lag */ + VecLerpf(dvec, dvec_tmp, fly->dvec_prev, (1.0f/(1.0f+(time_redraw*5.0f)))); + + if (rv3d->persp==V3D_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; + } + + VecAddf(rv3d->ofs, rv3d->ofs, dvec); +#if 0 //XXX2.5 + 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"); + else if (fly->zlock) + headerprint("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"); + else + headerprint("FlyKeys Speed:(+/- | Wheel), Upright Axis:X off/Z off, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); +#endif + +//XXX2.5 do_screenhandlers(G.curscreen); /* advance the next frame */ + + /* 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==V3D_CAMOB) { + rv3d->persp= V3D_PERSP; /*set this so setviewmatrixview3d uses the ofs and quat instead of the camera */ + setviewmatrixview3d(scene, v3d, rv3d); + + setcameratoview3d(v3d, rv3d, v3d->camera); + + { //XXX - some reason setcameratoview3d doesnt copy, shouldnt not be needed! + VECCOPY(v3d->camera->loc, rv3d->ofs); + VecNegf(v3d->camera->loc); + } + + rv3d->persp= V3D_CAMOB; +#if 0 //XXX2.5 + /* record the motion */ + if (IS_AUTOKEY_MODE(NORMAL) && (!playing_anim || cfra != G.scene->r.cfra)) { + cfra = G.scene->r.cfra; + + if (fly->xlock || fly->zlock || moffset[0] || moffset[1]) { + insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_ROT_X, 0); + insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_ROT_Y, 0); + insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_ROT_Z, 0); + } + if (fly->speed) { + insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_LOC_X, 0); + insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_LOC_Y, 0); + insertkey(&v3d->camera->id, ID_OB, actname, NULL, OB_LOC_Z, 0); + } + } +#endif + } +//XXX2.5 scrarea_do_windraw(curarea); +//XXX2.5 screen_swapbuffers(); + } else + /*were not redrawing but we need to update the time else the view will jump */ + fly->time_lastdraw= PIL_check_seconds_timer(); + /* end drawing */ + VECCOPY(fly->dvec_prev, dvec); + } + +/* moved to flyEnd() */ + + return OPERATOR_FINISHED; +} + + + +static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + RegionView3D *rv3d= CTX_wm_region_view3d(C); + FlyInfo *fly; + + if(rv3d->viewlock) + return OPERATOR_CANCELLED; + + fly= MEM_callocN(sizeof(FlyInfo), "FlyOperation"); + + op->customdata= fly; + + if(initFlyInfo(C, fly, op, event)==FALSE) { + MEM_freeN(op->customdata); + return OPERATOR_CANCELLED; + } + + flyEvent(fly, event); + + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; +} + +static int fly_cancel(bContext *C, wmOperator *op) +{ + FlyInfo *fly = op->customdata; + + fly->state = FLY_CANCEL; + flyEnd(C, fly); + op->customdata= NULL; + + return OPERATOR_CANCELLED; +} + +static int fly_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + int exit_code; + + FlyInfo *fly = op->customdata; + + fly->redraw= 0; + + flyEvent(fly, event); + + if(event->type==TIMER) + flyApply(fly); + + if(fly->redraw) {; + ED_region_tag_redraw(CTX_wm_region(C)); + } + + exit_code = flyEnd(C, fly); + + if(exit_code!=OPERATOR_RUNNING_MODAL) + ED_region_tag_redraw(CTX_wm_region(C)); + + return exit_code; +} + +void VIEW3D_OT_fly(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Fly Navigation"; + ot->description= "Interactively fly around the scene."; + ot->idname= "VIEW3D_OT_fly"; + + /* api callbacks */ + ot->invoke= fly_invoke; + ot->cancel= fly_cancel; + ot->modal= fly_modal; + ot->poll= ED_operator_view3d_active; + + /* flags */ + ot->flag= OPTYPE_BLOCKING; + +} + /* ************************************** */ void view3d_align_axis_to_vector(View3D *v3d, RegionView3D *rv3d, int axisidx, float vec[3]) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index e877f1fecae..84e42294946 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -100,6 +100,7 @@ #include "ED_markers.h" #include "ED_util.h" #include "ED_view3d.h" +#include "ED_mesh.h" #include "UI_view2d.h" #include "WM_types.h" @@ -108,6 +109,8 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_editVert.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" #include "PIL_time.h" /* sleep */ @@ -1318,7 +1321,12 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if (t->flag & T_MODAL) { ts->prop_mode = t->prop_mode; - ts->proportional = proportional; + + /* only save back if it wasn't automatically disabled */ + if ((t->options & CTX_NO_PET) == 0) + { + ts->proportional = proportional; + } if(t->spacetype == SPACE_VIEW3D) { @@ -1428,6 +1436,9 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int case TFM_BONE_ENVELOPE: initBoneEnvelope(t); break; + case TFM_EDGE_SLIDE: + initEdgeSlide(t); + break; case TFM_BONE_ROLL: initBoneRoll(t); break; @@ -1705,38 +1716,30 @@ static void constraintTransLim(TransInfo *t, TransData *td) bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT); bConstraintOb cob; bConstraint *con; - + /* Make a temporary bConstraintOb for using these limit constraints * - they only care that cob->matrix is correctly set ;-) * - current space should be local */ memset(&cob, 0, sizeof(bConstraintOb)); Mat4One(cob.matrix); - if (td->tdi) { - TransDataIpokey *tdi= td->tdi; - cob.matrix[3][0]= tdi->locx[0]; - cob.matrix[3][1]= tdi->locy[0]; - cob.matrix[3][2]= tdi->locz[0]; - } - else { - VECCOPY(cob.matrix[3], td->loc); - } - + VECCOPY(cob.matrix[3], td->loc); + /* Evaluate valid constraints */ for (con= td->con; con; con= con->next) { float tmat[4][4]; - + /* only consider constraint if enabled */ if (con->flag & CONSTRAINT_DISABLE) continue; if (con->enforce == 0.0f) continue; - + /* only use it if it's tagged for this purpose (and the right type) */ if (con->type == CONSTRAINT_TYPE_LOCLIMIT) { bLocLimitConstraint *data= con->data; - + if ((data->flag2 & LIMIT_TRANSFORM)==0) continue; - + /* do space conversions */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { /* just multiply by td->mtx (this should be ok) */ @@ -1747,10 +1750,10 @@ static void constraintTransLim(TransInfo *t, TransData *td) /* skip... incompatable spacetype */ continue; } - + /* do constraint */ cti->evaluate_constraint(con, &cob, NULL); - + /* convert spaces again */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { /* just multiply by td->mtx (this should be ok) */ @@ -1759,17 +1762,9 @@ static void constraintTransLim(TransInfo *t, TransData *td) } } } - + /* copy results from cob->matrix */ - if (td->tdi) { - TransDataIpokey *tdi= td->tdi; - tdi->locx[0]= cob.matrix[3][0]; - tdi->locy[0]= cob.matrix[3][1]; - tdi->locz[0]= cob.matrix[3][2]; - } - else { - VECCOPY(td->loc, cob.matrix[3]); - } + VECCOPY(td->loc, cob.matrix[3]); } } @@ -1785,25 +1780,14 @@ static void constraintRotLim(TransInfo *t, TransData *td) * - current space should be local */ memset(&cob, 0, sizeof(bConstraintOb)); - if (td->flag & TD_USEQUAT) { + if (td->rotOrder == ROT_MODE_QUAT) { /* quats */ if (td->ext) QuatToMat4(td->ext->quat, cob.matrix); else return; } - else if (td->tdi) { // XXX depreceated - /* ipo-keys eulers */ - TransDataIpokey *tdi= td->tdi; - float eul[3]; - - eul[0]= tdi->rotx[0]; - eul[1]= tdi->roty[0]; - eul[2]= tdi->rotz[0]; - - EulOToMat4(eul, td->rotOrder, cob.matrix); - } - else if (td->rotOrder == PCHAN_ROT_AXISANGLE) { + else if (td->rotOrder == ROT_MODE_AXISANGLE) { /* axis angle */ if (td->ext) AxisAngleToMat4(&td->ext->quat[1], td->ext->quat[0], cob.matrix); @@ -1857,22 +1841,11 @@ static void constraintRotLim(TransInfo *t, TransData *td) } /* copy results from cob->matrix */ - if (td->flag & TD_USEQUAT) { + if (td->rotOrder == ROT_MODE_QUAT) { /* quats */ Mat4ToQuat(cob.matrix, td->ext->quat); } - else if (td->tdi) { - /* ipo-keys eulers */ - TransDataIpokey *tdi= td->tdi; - float eul[3]; - - Mat4ToEulO(cob.matrix, eul, td->rotOrder); - - tdi->rotx[0]= eul[0]; - tdi->roty[0]= eul[1]; - tdi->rotz[0]= eul[2]; - } - else if (td->rotOrder == PCHAN_ROT_AXISANGLE) { + else if (td->rotOrder == ROT_MODE_AXISANGLE) { /* axis angle */ Mat4ToAxisAngle(cob.matrix, &td->ext->quat[1], &td->ext->quat[0]); } @@ -1889,22 +1862,13 @@ static void constraintSizeLim(TransInfo *t, TransData *td) bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT); bConstraintOb cob; bConstraint *con; - + /* Make a temporary bConstraintOb for using these limit constraints * - they only care that cob->matrix is correctly set ;-) * - current space should be local */ memset(&cob, 0, sizeof(bConstraintOb)); - if (td->tdi) { - TransDataIpokey *tdi= td->tdi; - float size[3]; - - size[0]= tdi->sizex[0]; - size[1]= tdi->sizey[0]; - size[2]= tdi->sizez[0]; - SizeToMat4(size, cob.matrix); - } - else if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { + if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { /* scale val and reset size */ return; // TODO: fix this case } @@ -1912,25 +1876,25 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* Reset val if SINGLESIZE but using a constraint */ if (td->flag & TD_SINGLESIZE) return; - + SizeToMat4(td->ext->size, cob.matrix); } - + /* Evaluate valid constraints */ for (con= td->con; con; con= con->next) { /* only consider constraint if enabled */ if (con->flag & CONSTRAINT_DISABLE) continue; if (con->enforce == 0.0f) continue; - + /* we're only interested in Limit-Scale constraints */ if (con->type == CONSTRAINT_TYPE_SIZELIMIT) { bSizeLimitConstraint *data= con->data; float tmat[4][4]; - + /* only use it if it's tagged for this purpose */ if ((data->flag2 & LIMIT_TRANSFORM)==0) continue; - + /* do space conversions */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { /* just multiply by td->mtx (this should be ok) */ @@ -1941,10 +1905,10 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* skip... incompatable spacetype */ continue; } - + /* do constraint */ cti->evaluate_constraint(con, &cob, NULL); - + /* convert spaces again */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { /* just multiply by td->mtx (this should be ok) */ @@ -1953,19 +1917,9 @@ static void constraintSizeLim(TransInfo *t, TransData *td) } } } - + /* copy results from cob->matrix */ - if (td->tdi) { - TransDataIpokey *tdi= td->tdi; - float size[3]; - - Mat4ToSize(cob.matrix, size); - - tdi->sizex[0]= size[0]; - tdi->sizey[0]= size[1]; - tdi->sizez[0]= size[2]; - } - else if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { + if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { /* scale val and reset size */ return; // TODO: fix this case } @@ -1973,7 +1927,7 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* Reset val if SINGLESIZE but using a constraint */ if (td->flag & TD_SINGLESIZE) return; - + Mat4ToSize(cob.matrix, td->ext->size); } } @@ -1985,21 +1939,21 @@ void initWarp(TransInfo *t) { float max[3], min[3]; int i; - + t->mode = TFM_WARP; t->transform = Warp; t->handleEvent = handleEventWarp; - + initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); - + t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; t->snap[1] = 5.0f; t->snap[2] = 1.0f; - + t->flag |= T_NO_CONSTRAINT; - + /* we need min/max in view space */ for(i = 0; i < t->total; i++) { float center[3]; @@ -2014,7 +1968,7 @@ void initWarp(TransInfo *t) VECCOPY(min, center); } } - + t->center[0]= (min[0]+max[0])/2.0f; t->center[1]= (min[1]+max[1])/2.0f; t->center[2]= (min[2]+max[2])/2.0f; @@ -2026,7 +1980,7 @@ void initWarp(TransInfo *t) int handleEventWarp(TransInfo *t, wmEvent *event) { int status = 0; - + if (event->type == MIDDLEMOUSE && event->val==KM_PRESS) { // Use customData pointer to signal warp direction @@ -2034,10 +1988,10 @@ int handleEventWarp(TransInfo *t, wmEvent *event) t->customData = (void*)1; else t->customData = 0; - + status = 1; } - + return status; } @@ -2047,7 +2001,7 @@ int Warp(TransInfo *t, short mval[2]) float vec[3], circumfac, dist, phi0, co, si, *curs, cursor[3], gcursor[3]; int i; char str[50]; - + curs= give_cursor(t->scene, t->view); /* * gcursor is the one used for helpline. @@ -2068,73 +2022,73 @@ int Warp(TransInfo *t, short mval[2]) } Mat4MulVecfl(t->viewmat, cursor); VecSubf(cursor, cursor, t->viewmat[3]); - + /* amount of degrees for warp */ circumfac = 360.0f * t->values[0]; - + if (t->customData) /* non-null value indicates reversed input */ { circumfac *= -1; } - + snapGrid(t, &circumfac); applyNumInput(&t->num, &circumfac); - + /* header print for NumInput */ if (hasNumInput(&t->num)) { char c[20]; - + outputNumInput(&(t->num), c); - + sprintf(str, "Warp: %s", c); } else { /* default header print */ sprintf(str, "Warp: %.3f", circumfac); } - + circumfac*= (float)(-M_PI/360.0); - + for(i = 0; i < t->total; i++, td++) { float loc[3]; if (td->flag & TD_NOACTION) break; - + if (td->flag & TD_SKIP) continue; - + /* translate point to center, rotate in such a way that outline==distance */ VECCOPY(vec, td->iloc); Mat3MulVecfl(td->mtx, vec); Mat4MulVecfl(t->viewmat, vec); VecSubf(vec, vec, t->viewmat[3]); - + dist= vec[0]-cursor[0]; - + /* t->val is X dimension projected boundbox */ phi0= (circumfac*dist/t->val); - + vec[1]= (vec[1]-cursor[1]); - + co= (float)cos(phi0); si= (float)sin(phi0); loc[0]= -si*vec[1]+cursor[0]; loc[1]= co*vec[1]+cursor[1]; loc[2]= vec[2]; - + Mat4MulVecfl(t->viewinv, loc); VecSubf(loc, loc, t->viewinv[3]); Mat3MulVecfl(td->smtx, loc); - + VecSubf(loc, loc, td->iloc); VecMulf(loc, td->factor); VecAddf(td->loc, td->iloc, loc); } - + recalcData(t); - + ED_area_headerprint(t->sa, str); - + return 1; } @@ -2145,22 +2099,22 @@ void initShear(TransInfo *t) t->mode = TFM_SHEAR; t->transform = Shear; t->handleEvent = handleEventShear; - + initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE); - + t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - + t->flag |= T_NO_CONSTRAINT; } int handleEventShear(TransInfo *t, wmEvent *event) { int status = 0; - + if (event->type == MIDDLEMOUSE && event->val==KM_PRESS) { // Use customData pointer to signal Shear direction @@ -2174,10 +2128,10 @@ int handleEventShear(TransInfo *t, wmEvent *event) initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE); t->customData = 0; } - + status = 1; } - + return status; } @@ -2190,47 +2144,47 @@ int Shear(TransInfo *t, short mval[2]) float value; int i; char str[50]; - + Mat3CpyMat4(persmat, t->viewmat); Mat3Inv(persinv, persmat); - + value = 0.05f * t->values[0]; - + snapGrid(t, &value); - + applyNumInput(&t->num, &value); - + /* header print for NumInput */ if (hasNumInput(&t->num)) { char c[20]; - + outputNumInput(&(t->num), c); - + sprintf(str, "Shear: %s %s", c, t->proptext); } else { /* default header print */ sprintf(str, "Shear: %.3f %s", value, t->proptext); } - + Mat3One(smat); - + // Custom data signals shear direction if (t->customData == 0) smat[1][0] = value; else smat[0][1] = value; - + Mat3MulMat3(tmat, smat, persmat); Mat3MulMat3(totmat, persinv, tmat); - + for(i = 0 ; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; - + if (td->flag & TD_SKIP) continue; - + if (t->obedit) { float mat3[3][3]; Mat3MulMat3(mat3, totmat, td->mtx); @@ -2240,19 +2194,19 @@ int Shear(TransInfo *t, short mval[2]) Mat3CpyMat3(tmat, totmat); } VecSubf(vec, td->center, t->center); - + Mat3MulVecfl(tmat, vec); - + VecAddf(vec, vec, t->center); VecSubf(vec, vec, td->center); - + VecMulf(vec, td->factor); - + VecAddf(td->loc, td->iloc, vec); } - + recalcData(t); - + ED_area_headerprint(t->sa, str); return 1; @@ -2264,9 +2218,9 @@ void initResize(TransInfo *t) { t->mode = TFM_RESIZE; t->transform = Resize; - + initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); - + t->flag |= T_NULL_ONE; t->num.flag |= NUM_NULL_ONE; t->num.flag |= NUM_AFFECT_ALL; @@ -2274,7 +2228,7 @@ void initResize(TransInfo *t) t->flag |= T_NO_ZERO; t->num.flag |= NUM_NO_ZERO; } - + t->idx_max = 2; t->num.idx_max = 2; t->snap[0] = 0.0f; @@ -2292,7 +2246,7 @@ static void headerResize(TransInfo *t, float vec[3], char *str) { sprintf(&tvec[20], "%.4f", vec[1]); sprintf(&tvec[40], "%.4f", vec[2]); } - + if (t->con.mode & CON_APPLY) { switch(t->num.idx_max) { case 0: @@ -2320,14 +2274,14 @@ static void headerResize(TransInfo *t, float vec[3], char *str) { static void TransMat3ToSize( float mat[][3], float smat[][3], float *size) { float vec[3]; - + VecCopyf(vec, mat[0]); size[0]= Normalize(vec); VecCopyf(vec, mat[1]); size[1]= Normalize(vec); VecCopyf(vec, mat[2]); size[2]= Normalize(vec); - + /* first tried with dotproduct... but the sign flip is crucial */ if( VECSIGNFLIP(mat[0], smat[0]) ) size[0]= -size[0]; if( VECSIGNFLIP(mat[1], smat[1]) ) size[1]= -size[1]; @@ -2338,7 +2292,7 @@ static void TransMat3ToSize( float mat[][3], float smat[][3], float *size) static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { float tmat[3][3], smat[3][3], center[3]; float vec[3]; - + if (t->flag & T_EDIT) { Mat3MulMat3(smat, mat, td->mtx); Mat3MulMat3(tmat, td->smtx, smat); @@ -2346,18 +2300,18 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { else { Mat3CpyMat3(tmat, mat); } - + if (t->con.applySize) { t->con.applySize(t, td, tmat); } - + /* local constraint shouldn't alter center */ if (t->around == V3D_LOCAL) { if (t->flag & T_OBJECT) { VECCOPY(center, td->center); } else if (t->flag & T_EDIT) { - + if(t->around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) { VECCOPY(center, td->center); } @@ -2372,10 +2326,10 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { else { VECCOPY(center, t->center); } - + if (td->ext) { float fsize[3]; - + if (t->flag & (T_OBJECT|T_TEXTURE|T_POSE)) { float obsizemat[3][3]; // Reorient the size mat to fit the oriented object. @@ -2387,28 +2341,14 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { else { Mat3ToSize(tmat, fsize); } - + protectedSizeBits(td->protectflag, fsize); - + if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't resize objects itself - /* handle ipokeys? */ - if(td->tdi) { - TransDataIpokey *tdi= td->tdi; - /* calculate delta size (equal for size and dsize) */ - - vec[0]= (tdi->oldsize[0])*(fsize[0] -1.0f) * td->factor; - vec[1]= (tdi->oldsize[1])*(fsize[1] -1.0f) * td->factor; - vec[2]= (tdi->oldsize[2])*(fsize[2] -1.0f) * td->factor; - - add_tdi_poin(tdi->sizex, tdi->oldsize, vec[0]); - add_tdi_poin(tdi->sizey, tdi->oldsize+1, vec[1]); - add_tdi_poin(tdi->sizez, tdi->oldsize+2, vec[2]); - - } - else if((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)){ + if((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)){ /* scale val and reset size */ *td->val = td->ival * fsize[0] * td->factor; - + td->ext->size[0] = td->ext->isize[0]; td->ext->size[1] = td->ext->isize[1]; td->ext->size[2] = td->ext->isize[2]; @@ -2417,46 +2357,39 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) { /* Reset val if SINGLESIZE but using a constraint */ if (td->flag & TD_SINGLESIZE) *td->val = td->ival; - + td->ext->size[0] = td->ext->isize[0] * (fsize[0]) * td->factor; td->ext->size[1] = td->ext->isize[1] * (fsize[1]) * td->factor; td->ext->size[2] = td->ext->isize[2] * (fsize[2]) * td->factor; } } - + constraintSizeLim(t, td); } - + /* For individual element center, Editmode need to use iloc */ if (t->flag & T_POINTS) VecSubf(vec, td->iloc, center); else VecSubf(vec, td->center, center); - + Mat3MulVecfl(tmat, vec); - + VecAddf(vec, vec, center); if (t->flag & T_POINTS) VecSubf(vec, vec, td->iloc); else VecSubf(vec, vec, td->center); - + VecMulf(vec, td->factor); - + if (t->flag & (T_OBJECT|T_POSE)) { Mat3MulVecfl(td->smtx, vec); } - + protectedTransBits(td->protectflag, vec); - - if(td->tdi) { - TransDataIpokey *tdi= td->tdi; - add_tdi_poin(tdi->locx, tdi->oldloc, vec[0]); - add_tdi_poin(tdi->locy, tdi->oldloc+1, vec[1]); - add_tdi_poin(tdi->locz, tdi->oldloc+2, vec[2]); - } - else VecAddf(td->loc, td->iloc, vec); - + VecAddf(td->loc, td->iloc, vec); + constraintTransLim(t, td); } @@ -2467,7 +2400,7 @@ int Resize(TransInfo *t, short mval[2]) float ratio; int i; char str[200]; - + /* for manipulator, center handle, the scaling can't be done relative to center */ if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0) { @@ -2477,60 +2410,60 @@ int Resize(TransInfo *t, short mval[2]) { ratio = t->values[0]; } - + size[0] = size[1] = size[2] = ratio; - + snapGrid(t, size); - + if (hasNumInput(&t->num)) { applyNumInput(&t->num, size); constraintNumInput(t, size); } - + applySnapping(t, size); - + if (t->flag & T_AUTOVALUES) { VECCOPY(size, t->auto_values); } - + VECCOPY(t->values, size); - + SizeToMat3(size, mat); - + if (t->con.applySize) { t->con.applySize(t, NULL, mat); } - + Mat3CpyMat3(t->mat, mat); // used in manipulator - + headerResize(t, size, str); - + for(i = 0, td=t->data; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; - + if (td->flag & TD_SKIP) continue; - + ElementResize(t, td, mat); } - + /* evil hack - redo resize if cliping needed */ if (t->flag & T_CLIP_UV && clipUVTransform(t, size, 1)) { SizeToMat3(size, mat); - + if (t->con.applySize) t->con.applySize(t, NULL, mat); - + for(i = 0, td=t->data; i < t->total; i++, td++) ElementResize(t, td, mat); } - + recalcData(t); - + ED_area_headerprint(t->sa, str); - + return 1; } @@ -2540,26 +2473,26 @@ void initToSphere(TransInfo *t) { TransData *td = t->data; int i; - + t->mode = TFM_TOSPHERE; t->transform = ToSphere; - + initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); - + t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - + t->num.flag |= NUM_NULL_ONE | NUM_NO_NEGATIVE; t->flag |= T_NO_CONSTRAINT; - + // Calculate average radius for(i = 0 ; i < t->total; i++, td++) { t->val += VecLenf(t->center, td->iloc); } - + t->val /= (float)t->total; } @@ -2570,56 +2503,56 @@ int ToSphere(TransInfo *t, short mval[2]) int i; char str[64]; TransData *td = t->data; - + ratio = t->values[0]; - + snapGrid(t, &ratio); - + applyNumInput(&t->num, &ratio); - + if (ratio < 0) ratio = 0.0f; else if (ratio > 1) ratio = 1.0f; - + /* header print for NumInput */ if (hasNumInput(&t->num)) { char c[20]; - + outputNumInput(&(t->num), c); - + sprintf(str, "To Sphere: %s %s", c, t->proptext); } else { /* default header print */ sprintf(str, "To Sphere: %.4f %s", ratio, t->proptext); } - - + + for(i = 0 ; i < t->total; i++, td++) { float tratio; if (td->flag & TD_NOACTION) break; - + if (td->flag & TD_SKIP) continue; - + VecSubf(vec, td->iloc, t->center); - + radius = Normalize(vec); - + tratio = ratio * td->factor; - + VecMulf(vec, radius * (1.0f - tratio) + t->val * tratio); - + VecAddf(td->loc, t->center, vec); } - - + + recalcData(t); - + ED_area_headerprint(t->sa, str); - + return 1; } @@ -2630,19 +2563,19 @@ void initRotation(TransInfo *t) { t->mode = TFM_ROTATION; t->transform = Rotation; - + initMouseInputMode(t, &t->mouse, INPUT_ANGLE); - + t->ndof.axis = 16; /* Scale down and flip input for rotation */ t->ndof.factor[0] = -0.2f; - + t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; t->snap[1] = (float)((5.0/180)*M_PI); t->snap[2] = t->snap[1] * 0.2f; - + if (t->flag & T_2D_EDIT) t->flag |= T_NO_CONSTRAINT; } @@ -2651,7 +2584,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short float vec[3], totmat[3][3], smat[3][3]; float eul[3], fmat[3][3], quat[4]; float *center = t->center; - + /* local constraint shouldn't alter center */ if (around == V3D_LOCAL) { if (t->flag & (T_OBJECT|T_POSE)) { @@ -2664,27 +2597,28 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short } } } - + if (t->flag & T_POINTS) { Mat3MulMat3(totmat, mat, td->mtx); Mat3MulMat3(smat, td->smtx, totmat); - + VecSubf(vec, td->iloc, center); Mat3MulVecfl(smat, vec); - + VecAddf(td->loc, vec, center); - + VecSubf(vec,td->loc,td->iloc); protectedTransBits(td->protectflag, vec); VecAddf(td->loc, td->iloc, vec); - + + if(td->flag & TD_USEQUAT) { Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0); Mat3ToQuat(fmat, quat); // Actual transform - + if(td->ext->quat){ QuatMul(td->ext->quat, quat, td->ext->iquat); - + /* is there a reason not to have this here? -jahka */ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); } @@ -2704,48 +2638,48 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short */ else if (t->flag & T_POSE) { float pmtx[3][3], imtx[3][3]; - + // Extract and invert armature object matrix Mat3CpyMat4(pmtx, t->poseobj->obmat); Mat3Inv(imtx, pmtx); - + if ((td->flag & TD_NO_LOC) == 0) { VecSubf(vec, td->center, center); - + Mat3MulVecfl(pmtx, vec); // To Global space Mat3MulVecfl(mat, vec); // Applying rotation Mat3MulVecfl(imtx, vec); // To Local space - + VecAddf(vec, vec, center); /* vec now is the location where the object has to be */ - + VecSubf(vec, vec, td->center); // Translation needed from the initial location - + Mat3MulVecfl(pmtx, vec); // To Global space Mat3MulVecfl(td->smtx, vec);// To Pose space - + protectedTransBits(td->protectflag, vec); - + VecAddf(td->loc, td->iloc, vec); - + constraintTransLim(t, td); } - + /* rotation */ if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself /* euler or quaternion/axis-angle? */ - if (td->flag & TD_USEQUAT) { + if (td->rotOrder == ROT_MODE_QUAT) { Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0); - + Mat3ToQuat(fmat, quat); // Actual transform - + QuatMul(td->ext->quat, quat, td->ext->iquat); /* this function works on end result */ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); } - else if (td->rotOrder == PCHAN_ROT_AXISANGLE) { + else if (td->rotOrder == ROT_MODE_AXISANGLE) { /* calculate effect based on quats */ float iquat[4]; @@ -2797,93 +2731,67 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short /* vec now is the location where the object has to be */ VecSubf(vec, vec, td->center); Mat3MulVecfl(td->smtx, vec); - + protectedTransBits(td->protectflag, vec); - - if(td->tdi) { - TransDataIpokey *tdi= td->tdi; - add_tdi_poin(tdi->locx, tdi->oldloc, vec[0]); - add_tdi_poin(tdi->locy, tdi->oldloc+1, vec[1]); - add_tdi_poin(tdi->locz, tdi->oldloc+2, vec[2]); - } - else VecAddf(td->loc, td->iloc, vec); + + VecAddf(td->loc, td->iloc, vec); } - - + + constraintTransLim(t, td); - + /* rotation */ if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself /* euler or quaternion? */ - if (td->flag & TD_USEQUAT) { + if ((td->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) { Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0); Mat3ToQuat(fmat, quat); // Actual transform - + QuatMul(td->ext->quat, quat, td->ext->iquat); /* this function works on end result */ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); } + else if (td->rotOrder == ROT_MODE_AXISANGLE) { + /* calculate effect based on quats */ + float iquat[4]; + + /* td->ext->(i)quat is in axis-angle form, not quats! */ + AxisAngleToQuat(iquat, &td->ext->iquat[1], td->ext->iquat[0]); + + Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0); + Mat3ToQuat(fmat, quat); // Actual transform + + QuatMul(td->ext->quat, quat, iquat); + + /* make temp copy (since stored in same place) */ + QUATCOPY(quat, td->ext->quat); // this is just a 4d vector copying macro + QuatToAxisAngle(quat, &td->ext->quat[1], &td->ext->quat[0]); + + /* this function works on end result */ + protectedAxisAngleBits(td->protectflag, td->ext->quat, td->ext->iquat); + } else { float obmat[3][3]; - - /* are there ipo keys? */ - if(td->tdi) { - TransDataIpokey *tdi= td->tdi; - float current_rot[3]; - float rot[3]; - - /* current IPO value for compatible euler */ - current_rot[0] = (tdi->rotx) ? tdi->rotx[0] : 0.0f; - current_rot[1] = (tdi->roty) ? tdi->roty[0] : 0.0f; - current_rot[2] = (tdi->rotz) ? tdi->rotz[0] : 0.0f; - VecMulf(current_rot, (float)(M_PI_2 / 9.0)); - - /* calculate the total rotatation in eulers */ - VecAddf(eul, td->ext->irot, td->ext->drot); - EulToMat3(eul, obmat); - /* mat = transform, obmat = object rotation */ - Mat3MulMat3(fmat, mat, obmat); - - Mat3ToCompatibleEul(fmat, eul, current_rot); - - /* correct back for delta rot */ - if(tdi->flag & TOB_IPODROT) { - VecSubf(rot, eul, td->ext->irot); - } - else { - VecSubf(rot, eul, td->ext->drot); - } - - VecMulf(rot, (float)(9.0/M_PI_2)); - VecSubf(rot, rot, tdi->oldrot); - - protectedRotateBits(td->protectflag, rot, tdi->oldrot); - - add_tdi_poin(tdi->rotx, tdi->oldrot, rot[0]); - add_tdi_poin(tdi->roty, tdi->oldrot+1, rot[1]); - add_tdi_poin(tdi->rotz, tdi->oldrot+2, rot[2]); - } - else { - Mat3MulMat3(totmat, mat, td->mtx); - Mat3MulMat3(smat, td->smtx, totmat); - - /* calculate the total rotatation in eulers */ - VecAddf(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */ - EulToMat3(eul, obmat); - /* mat = transform, obmat = object rotation */ - Mat3MulMat3(fmat, smat, obmat); - - Mat3ToCompatibleEul(fmat, eul, td->ext->rot); - - /* correct back for delta rot */ - VecSubf(eul, eul, td->ext->drot); - - /* and apply */ - protectedRotateBits(td->protectflag, eul, td->ext->irot); - VECCOPY(td->ext->rot, eul); - } + + Mat3MulMat3(totmat, mat, td->mtx); + Mat3MulMat3(smat, td->smtx, totmat); + + /* calculate the total rotatation in eulers */ + VecAddf(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */ + EulOToMat3(eul, td->rotOrder, obmat); + /* mat = transform, obmat = object rotation */ + Mat3MulMat3(fmat, smat, obmat); + + Mat3ToCompatibleEulO(fmat, eul, td->ext->rot, td->rotOrder); + + /* correct back for delta rot */ + VecSubf(eul, eul, td->ext->drot); + + /* and apply */ + protectedRotateBits(td->protectflag, eul, td->ext->irot); + VECCOPY(td->ext->rot, eul); } - + constraintRotLim(t, td); } } @@ -2894,17 +2802,17 @@ static void applyRotation(TransInfo *t, float angle, float axis[3]) TransData *td = t->data; float mat[3][3]; int i; - + VecRotToMat3(axis, angle, mat); - + for(i = 0 ; i < t->total; i++, td++) { - + if (td->flag & TD_NOACTION) break; - + if (td->flag & TD_SKIP) continue; - + if (t->con.applyRot) { t->con.applyRot(t, td, axis, NULL); VecRotToMat3(axis, angle * td->factor, mat); @@ -2912,7 +2820,7 @@ static void applyRotation(TransInfo *t, float angle, float axis[3]) else if (t->flag & T_PROP_EDIT) { VecRotToMat3(axis, angle * td->factor, mat); } - + ElementRotation(t, td, mat, t->around); } } @@ -2920,62 +2828,62 @@ static void applyRotation(TransInfo *t, float angle, float axis[3]) int Rotation(TransInfo *t, short mval[2]) { char str[64]; - + float final; - + float axis[3]; float mat[3][3]; - + VECCOPY(axis, t->viewinv[2]); VecMulf(axis, -1.0f); Normalize(axis); - + final = t->values[0]; - + applyNDofInput(&t->ndof, &final); - + snapGrid(t, &final); - + if (t->con.applyRot) { t->con.applyRot(t, NULL, axis, &final); } - + applySnapping(t, &final); - + if (hasNumInput(&t->num)) { char c[20]; - + applyNumInput(&t->num, &final); - + outputNumInput(&(t->num), c); - + sprintf(str, "Rot: %s %s %s", &c[0], t->con.text, t->proptext); - + /* Clamp between -180 and 180 */ while (final >= 180.0) final -= 360.0; - + while (final <= -180.0) final += 360.0; - + final *= (float)(M_PI / 180.0); } else { sprintf(str, "Rot: %.2f%s %s", 180.0*final/M_PI, t->con.text, t->proptext); } - + VecRotToMat3(axis, final, mat); - + // TRANSFORM_FIX_ME // t->values[0] = final; // used in manipulator // Mat3CpyMat3(t->mat, mat); // used in manipulator - + applyRotation(t, final, axis); - + recalcData(t); - + ED_area_headerprint(t->sa, str); - + return 1; } @@ -3193,10 +3101,10 @@ static void applyTranslation(TransInfo *t, float vec[3]) { for(i = 0 ; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; - + if (td->flag & TD_SKIP) continue; - + /* handle snapping rotation before doing the translation */ if (usingSnappingNormal(t)) { @@ -3207,26 +3115,26 @@ static void applyTranslation(TransInfo *t, float vec[3]) { float quat[4]; float mat[3][3]; float angle; - + Crossf(axis, original_normal, t->tsnap.snapNormal); angle = saacos(Inpf(original_normal, t->tsnap.snapNormal)); - + AxisAngleToQuat(quat, axis, angle); - + QuatToMat3(quat, mat); - + ElementRotation(t, td, mat, V3D_LOCAL); } else { float mat[3][3]; - + Mat3One(mat); - + ElementRotation(t, td, mat, V3D_LOCAL); } } - + if (t->con.applyVec) { float pvec[3]; t->con.applyVec(t, td, vec, tvec, pvec); @@ -3234,21 +3142,14 @@ static void applyTranslation(TransInfo *t, float vec[3]) { else { VECCOPY(tvec, vec); } - + Mat3MulVecfl(td->smtx, tvec); VecMulf(tvec, td->factor); - + protectedTransBits(td->protectflag, tvec); - - /* transdata ipokey */ - if(td->tdi) { - TransDataIpokey *tdi= td->tdi; - add_tdi_poin(tdi->locx, tdi->oldloc, tvec[0]); - add_tdi_poin(tdi->locy, tdi->oldloc+1, tvec[1]); - add_tdi_poin(tdi->locz, tdi->oldloc+2, tvec[2]); - } - else VecAddf(td->loc, td->iloc, tvec); - + + VecAddf(td->loc, td->iloc, tvec); + constraintTransLim(t, td); } } @@ -3915,7 +3816,7 @@ int BoneSize(TransInfo *t, short mval[2]) float ratio; int i; char str[60]; - + // TRANSFORM_FIX_ME MOVE TO MOUSE INPUT /* for manipulator, center handle, the scaling can't be done relative to center */ if( (t->flag & T_USES_MANIPULATOR) && t->con.mode==0) @@ -3926,40 +3827,40 @@ int BoneSize(TransInfo *t, short mval[2]) { ratio = t->values[0]; } - + size[0] = size[1] = size[2] = ratio; - + snapGrid(t, size); - + if (hasNumInput(&t->num)) { applyNumInput(&t->num, size); constraintNumInput(t, size); } - + SizeToMat3(size, mat); - + if (t->con.applySize) { t->con.applySize(t, NULL, mat); } - + Mat3CpyMat3(t->mat, mat); // used in manipulator - + headerBoneSize(t, size, str); - + for(i = 0 ; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; - + if (td->flag & TD_SKIP) continue; - + ElementBoneSize(t, td, mat); } - + recalcData(t); - + ED_area_headerprint(t->sa, str); - + return 1; } @@ -3970,15 +3871,15 @@ void initBoneEnvelope(TransInfo *t) { t->mode = TFM_BONE_ENVELOPE; t->transform = BoneEnvelope; - + initMouseInputMode(t, &t->mouse, INPUT_SPRING); - + t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; t->snap[1] = 0.1f; t->snap[2] = t->snap[1] * 0.1f; - + t->flag |= T_NO_CONSTRAINT; } @@ -3988,31 +3889,31 @@ int BoneEnvelope(TransInfo *t, short mval[2]) float ratio; int i; char str[50]; - + ratio = t->values[0]; - + snapGrid(t, &ratio); - + applyNumInput(&t->num, &ratio); - + /* header print for NumInput */ if (hasNumInput(&t->num)) { char c[20]; - + outputNumInput(&(t->num), c); sprintf(str, "Envelope: %s", c); } else { sprintf(str, "Envelope: %3f", ratio); } - + for(i = 0 ; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; - + if (td->flag & TD_SKIP) continue; - + if (td->val) { /* if the old/original value was 0.0f, then just use ratio */ if (td->ival) @@ -4021,6 +3922,693 @@ int BoneEnvelope(TransInfo *t, short mval[2]) *td->val= ratio; } } + + recalcData(t); + + ED_area_headerprint(t->sa, str); + + return 1; +} + +/* ******************** Edge Slide *************** */ + +static int createSlideVerts(TransInfo *t) +{ + Mesh *me = t->obedit->data; + EditMesh *em = me->edit_mesh; + EditFace *efa; + EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL; + EditVert *ev, *nearest = NULL; + LinkNode *edgelist = NULL, *vertlist=NULL, *look; + GHash *vertgh; + TransDataSlideVert *tempsv; + float perc = 0, percp = 0,vertdist; // XXX, projectMat[4][4]; + float shiftlabda= 0.0f,len = 0.0f; + int i, j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0; + int wasshift = 0; + /* UV correction vars */ + GHash **uvarray= NULL; + SlideData *sld = MEM_callocN(sizeof(*sld), "sld"); + int uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE); + int uvlay_idx; + TransDataSlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL; + RegionView3D *v3d = t->ar->regiondata; + float projectMat[4][4]; + float start[3] = {0.0f, 0.0f, 0.0f}, end[3] = {0.0f, 0.0f, 0.0f}; + float vec[3]; + //short mval[2], mvalo[2]; + float labda = 0.0f, totvec=0.0; + + if (!v3d) { + /*ok, let's try to survive this*/ + Mat4One(projectMat); + } else { + view3d_get_object_project_mat(v3d, t->obedit, projectMat); + } + + //mvalo[0] = -1; mvalo[1] = -1; + numsel =0; + + // Get number of selected edges and clear some flags + for(eed=em->edges.first;eed;eed=eed->next) { + eed->f1 = 0; + eed->f2 = 0; + if(eed->f & SELECT) numsel++; + } + + for(ev=em->verts.first;ev;ev=ev->next) { + ev->f1 = 0; + } + + //Make sure each edge only has 2 faces + // make sure loop doesn't cross face + for(efa=em->faces.first;efa;efa=efa->next) { + int ct = 0; + if(efa->e1->f & SELECT) { + ct++; + efa->e1->f1++; + if(efa->e1->f1 > 2) { + //BKE_report(op->reports, RPT_ERROR, "3+ face edge"); + return 0; + } + } + if(efa->e2->f & SELECT) { + ct++; + efa->e2->f1++; + if(efa->e2->f1 > 2) { + //BKE_report(op->reports, RPT_ERROR, "3+ face edge"); + return 0; + } + } + if(efa->e3->f & SELECT) { + ct++; + efa->e3->f1++; + if(efa->e3->f1 > 2) { + //BKE_report(op->reports, RPT_ERROR, "3+ face edge"); + return 0; + } + } + if(efa->e4 && efa->e4->f & SELECT) { + ct++; + efa->e4->f1++; + if(efa->e4->f1 > 2) { + //BKE_report(op->reports, RPT_ERROR, "3+ face edge"); + return 0; + } + } + // Make sure loop is not 2 edges of same face + if(ct > 1) { + //BKE_report(op->reports, RPT_ERROR, "Loop crosses itself"); + return 0; + } + } + + // Get # of selected verts + for(ev=em->verts.first;ev;ev=ev->next) { + if(ev->f & SELECT) vertsel++; + } + + // Test for multiple segments + if(vertsel > numsel+1) { + //BKE_report(op->reports, RPT_ERROR, "Please choose a single edge loop"); + return 0; + } + + // Get the edgeloop in order - mark f1 with SELECT once added + for(eed=em->edges.first;eed;eed=eed->next) { + if((eed->f & SELECT) && !(eed->f1 & SELECT)) { + // If this is the first edge added, just put it in + if(!edgelist) { + BLI_linklist_prepend(&edgelist,eed); + numadded++; + first = eed; + last = eed; + eed->f1 = SELECT; + } else { + if(editedge_getSharedVert(eed, last)) { + BLI_linklist_append(&edgelist,eed); + eed->f1 = SELECT; + numadded++; + last = eed; + } else if(editedge_getSharedVert(eed, first)) { + BLI_linklist_prepend(&edgelist,eed); + eed->f1 = SELECT; + numadded++; + first = eed; + } + } + } + if(eed->next == NULL && numadded != numsel) { + eed=em->edges.first; + timesthrough++; + } + + // It looks like there was an unexpected case - Hopefully should not happen + if(timesthrough >= numsel*2) { + BLI_linklist_free(edgelist,NULL); + //BKE_report(op->reports, RPT_ERROR, "Could not order loop"); + return 0; + } + } + + // Put the verts in order in a linklist + look = edgelist; + while(look) { + eed = look->link; + if(!vertlist) { + if(look->next) { + temp = look->next->link; + + //This is the first entry takes care of extra vert + if(eed->v1 != temp->v1 && eed->v1 != temp->v2) { + BLI_linklist_append(&vertlist,eed->v1); + eed->v1->f1 = 1; + } else { + BLI_linklist_append(&vertlist,eed->v2); + eed->v2->f1 = 1; + } + } else { + //This is the case that we only have 1 edge + BLI_linklist_append(&vertlist,eed->v1); + eed->v1->f1 = 1; + } + } + // for all the entries + if(eed->v1->f1 != 1) { + BLI_linklist_append(&vertlist,eed->v1); + eed->v1->f1 = 1; + } else if(eed->v2->f1 != 1) { + BLI_linklist_append(&vertlist,eed->v2); + eed->v2->f1 = 1; + } + look = look->next; + } + + // populate the SlideVerts + + vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + look = vertlist; + while(look) { + i=0; + j=0; + ev = look->link; + tempsv = (struct TransDataSlideVert*)MEM_mallocN(sizeof(struct TransDataSlideVert),"SlideVert"); + tempsv->up = NULL; + tempsv->down = NULL; + tempsv->origvert.co[0] = ev->co[0]; + tempsv->origvert.co[1] = ev->co[1]; + tempsv->origvert.co[2] = ev->co[2]; + tempsv->origvert.no[0] = ev->no[0]; + tempsv->origvert.no[1] = ev->no[1]; + tempsv->origvert.no[2] = ev->no[2]; + // i is total edges that vert is on + // j is total selected edges that vert is on + + for(eed=em->edges.first;eed;eed=eed->next) { + if(eed->v1 == ev || eed->v2 == ev) { + i++; + if(eed->f & SELECT) { + j++; + } + } + } + // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges + if(i == 4 && j == 2) { + for(eed=em->edges.first;eed;eed=eed->next) { + if(editedge_containsVert(eed, ev)) { + if(!(eed->f & SELECT)) { + if(!tempsv->up) { + tempsv->up = eed; + } else if (!(tempsv->down)) { + tempsv->down = eed; + } + } + } + } + } + // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected + if(i >= 3 && j == 1) { + for(eed=em->edges.first;eed;eed=eed->next) { + if(editedge_containsVert(eed, ev) && eed->f & SELECT) { + for(efa = em->faces.first;efa;efa=efa->next) { + if(editface_containsEdge(efa, eed)) { + if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) { + if(!tempsv->up) { + tempsv->up = efa->e1; + } else if (!(tempsv->down)) { + tempsv->down = efa->e1; + } + } + if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) { + if(!tempsv->up) { + tempsv->up = efa->e2; + } else if (!(tempsv->down)) { + tempsv->down = efa->e2; + } + } + if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) { + if(!tempsv->up) { + tempsv->up = efa->e3; + } else if (!(tempsv->down)) { + tempsv->down = efa->e3; + } + } + if(efa->e4) { + if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) { + if(!tempsv->up) { + tempsv->up = efa->e4; + } else if (!(tempsv->down)) { + tempsv->down = efa->e4; + } + } + } + + } + } + } + } + } + if(i > 4 && j == 2) { + BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN); + BLI_linklist_free(vertlist,NULL); + BLI_linklist_free(edgelist,NULL); + return 0; + } + BLI_ghash_insert(vertgh,ev,tempsv); + + look = look->next; + } + + // make sure the UPs nad DOWNs are 'faceloops' + // Also find the nearest slidevert to the cursor + + look = vertlist; + nearest = NULL; + vertdist = -1; + while(look) { + tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link); + + if(!tempsv->up || !tempsv->down) { + //BKE_report(op->reports, RPT_ERROR, "Missing rails"); + BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN); + BLI_linklist_free(vertlist,NULL); + BLI_linklist_free(edgelist,NULL); + return 0; + } + + if(me->drawflag & ME_DRAW_EDGELEN) { + if(!(tempsv->up->f & SELECT)) { + tempsv->up->f |= SELECT; + tempsv->up->f2 |= 16; + } else { + tempsv->up->f2 |= ~16; + } + if(!(tempsv->down->f & SELECT)) { + tempsv->down->f |= SELECT; + tempsv->down->f2 |= 16; + } else { + tempsv->down->f2 |= ~16; + } + } + + if(look->next != NULL) { + TransDataSlideVert *sv; + + ev = (EditVert*)look->next->link; + sv = BLI_ghash_lookup(vertgh, ev); + + if(sv) { + float co[3], co2[3], vec[3]; + + ev = (EditVert*)look->link; + + if(!sharesFace(em, tempsv->up,sv->up)) { + EditEdge *swap; + swap = sv->up; + sv->up = sv->down; + sv->down = swap; + } + + if (v3d) { + view3d_project_float(t->ar, tempsv->up->v1->co, co, projectMat); + view3d_project_float(t->ar, tempsv->up->v2->co, co2, projectMat); + } + + if (ev == tempsv->up->v1) { + VecSubf(vec, co, co2); + } else { + VecSubf(vec, co2, co); + } + + VecAddf(start, start, vec); + + if (v3d) { + view3d_project_float(t->ar, tempsv->down->v1->co, co, projectMat); + view3d_project_float(t->ar, tempsv->down->v2->co, co2, projectMat); + } + + if (ev == tempsv->down->v1) { + VecSubf(vec, co2, co); + } else { + VecSubf(vec, co, co2); + } + + VecAddf(end, end, vec); + + totvec += 1.0f; + nearest = (EditVert*)look->link; + } + } + + + + look = look->next; + } + + VecAddf(start, start, end); + VecMulf(start, 0.5*(1.0/totvec)); + VECCOPY(vec, start); + start[0] = t->mval[0]; + start[1] = t->mval[1]; + VecAddf(end, start, vec); + + sld->start[0] = (short) start[0]; + sld->start[1] = (short) start[1]; + sld->end[0] = (short) end[0]; + sld->end[1] = (short) end[1]; + + if (uvlay_tot) { // XXX && (scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { + int maxnum = 0; + + uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array"); + sld->totuv = uvlay_tot; + suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(TransDataSlideUv), "SlideUVs"); /* uvLayers * verts */ + suv = NULL; + + for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) { + + uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + for(ev=em->verts.first;ev;ev=ev->next) { + ev->tmp.l = 0; + } + look = vertlist; + while(look) { + float *uv_new; + tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link); + + ev = look->link; + suv = NULL; + for(efa = em->faces.first;efa;efa=efa->next) { + if (ev->tmp.l != -1) { /* test for self, in this case its invalid */ + int k=-1; /* face corner */ + + /* Is this vert in the faces corner? */ + if (efa->v1==ev) k=0; + else if (efa->v2==ev) k=1; + else if (efa->v3==ev) k=2; + else if (efa->v4 && efa->v4==ev) k=3; + + if (k != -1) { + MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx); + EditVert *ev_up, *ev_down; + + uv_new = tf->uv[k]; + + if (ev->tmp.l) { + if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) { + ev->tmp.l = -1; /* Tag as invalid */ + BLI_linklist_free(suv->fuv_list,NULL); + suv->fuv_list = NULL; + BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL); + suv = NULL; + break; + } + } else { + ev->tmp.l = 1; + suv = suv_last; + + suv->fuv_list = NULL; + suv->uv_up = suv->uv_down = NULL; + suv->origuv[0] = uv_new[0]; + suv->origuv[1] = uv_new[1]; + + BLI_linklist_prepend(&suv->fuv_list, uv_new); + BLI_ghash_insert(uvarray[uvlay_idx],ev,suv); + + suv_last++; /* advance to next slide UV */ + maxnum++; + } + + /* Now get the uvs along the up or down edge if we can */ + if (suv) { + if (!suv->uv_up) { + ev_up = editedge_getOtherVert(tempsv->up,ev); + if (efa->v1==ev_up) suv->uv_up = tf->uv[0]; + else if (efa->v2==ev_up) suv->uv_up = tf->uv[1]; + else if (efa->v3==ev_up) suv->uv_up = tf->uv[2]; + else if (efa->v4 && efa->v4==ev_up) suv->uv_up = tf->uv[3]; + } + if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */ + ev_down = editedge_getOtherVert(tempsv->down,ev); + if (efa->v1==ev_down) suv->uv_down = tf->uv[0]; + else if (efa->v2==ev_down) suv->uv_down = tf->uv[1]; + else if (efa->v3==ev_down) suv->uv_down = tf->uv[2]; + else if (efa->v4 && efa->v4==ev_down) suv->uv_down = tf->uv[3]; + } + + /* Copy the pointers to the face UV's */ + BLI_linklist_prepend(&suv->fuv_list, uv_new); + } + } + } + } + look = look->next; + } + } /* end uv layer loop */ + } /* end uvlay_tot */ + + sld->uvhash = uvarray; + sld->slideuv = slideuvs; + sld->vhash = vertgh; + sld->nearest = nearest; + sld->vertlist = vertlist; + sld->edgelist = edgelist; + sld->suv_last = suv_last; + sld->uvlay_tot = uvlay_tot; + + // we should have enough info now to slide + + t->customData = sld; + + return 1; +} + +void freeSlideVerts(TransInfo *t) +{ + TransDataSlideUv *suv; + SlideData *sld = t->customData; + int uvlay_idx; + + //BLI_ghash_free(edgesgh, freeGHash, NULL); + BLI_ghash_free(sld->vhash, NULL, (GHashValFreeFP)MEM_freeN); + BLI_linklist_free(sld->vertlist, NULL); + BLI_linklist_free(sld->edgelist, NULL); + + if (sld->uvlay_tot) { + for (uvlay_idx=0; uvlay_idx<sld->uvlay_tot; uvlay_idx++) { + BLI_ghash_free(sld->uvhash[uvlay_idx], NULL, NULL); + } + + suv = sld->suv_last-1; + while (suv >= sld->slideuv) { + if (suv->fuv_list) { + BLI_linklist_free(suv->fuv_list,NULL); + } + suv--; + } + + MEM_freeN(sld->slideuv); + MEM_freeN(sld->uvhash); + } + + MEM_freeN(sld); + t->customData = NULL; +} + +void initEdgeSlide(TransInfo *t) +{ + SlideData *sld; + + t->mode = TFM_EDGE_SLIDE; + t->transform = EdgeSlide; + + createSlideVerts(t); + sld = t->customData; + + if (!sld) + return; + + t->customFree = freeSlideVerts; + + initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); + setCustomPoints(t, &t->mouse, sld->end, sld->start); + + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = (float)((5.0/180)*M_PI); + t->snap[2] = t->snap[1] * 0.2f; + + t->flag |= T_NO_CONSTRAINT; +} + +int doEdgeSlide(TransInfo *t, float perc) +{ + Mesh *me= t->obedit->data; + EditMesh *em = me->edit_mesh; + SlideData *sld = t->customData; + EditEdge *first=NULL,*last=NULL, *temp = NULL; + EditVert *ev, *nearest = sld->nearest; + EditVert *centerVert, *upVert, *downVert; + LinkNode *edgelist = sld->edgelist, *vertlist=sld->vertlist, *look; + GHash *vertgh = sld->vhash; + TransDataSlideVert *tempsv; + float shiftlabda= 0.0f,len = 0.0f; + int i = 0, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0; + int wasshift = 0; + /* UV correction vars */ + GHash **uvarray= sld->uvhash; + int uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE); + int uvlay_idx; + TransDataSlideUv *slideuvs=sld->slideuv, *suv=sld->slideuv, *suv_last=NULL; + float uv_tmp[2]; + LinkNode *fuv_link; + float labda = 0.0f; + + len = 0.0f; + + tempsv = BLI_ghash_lookup(vertgh,nearest); + + centerVert = editedge_getSharedVert(tempsv->up, tempsv->down); + upVert = editedge_getOtherVert(tempsv->up, centerVert); + downVert = editedge_getOtherVert(tempsv->down, centerVert); + + len = MIN2(perc, VecLenf(upVert->co,downVert->co)); + len = MAX2(len, 0); + + //Adjust Edgeloop + if(prop) { + look = vertlist; + while(look) { + EditVert *tempev; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + + tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev); + VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc)); + + if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) { + suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev ); + if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->origuv, (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + + look = look->next; + } + } + else { + //Non prop code + look = vertlist; + while(look) { + float newlen; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co)); + if(newlen > 1.0) {newlen = 1.0;} + if(newlen < 0.0) {newlen = 0.0;} + if(flip == 0) { + VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen)); + if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + /* dont do anything if no UVs */ + for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) { + suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev ); + if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + } else{ + VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen)); + + if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + /* dont do anything if no UVs */ + for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) { + suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev ); + if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + } + look = look->next; + } + + } + + return 1; +} + +int EdgeSlide(TransInfo *t, short mval[2]) +{ + TransData *td = t->data; + char str[50]; + float final; + + final = t->values[0]; + + snapGrid(t, &final); + + if (hasNumInput(&t->num)) { + char c[20]; + + applyNumInput(&t->num, &final); + + outputNumInput(&(t->num), c); + + sprintf(str, "Edge Slide Percent: %s", &c[0]); + } + else { + sprintf(str, "Edge Slide Percent: %.2f", final); + } + + CLAMP(final, -1.0f, 1.0f); + + /*do stuff here*/ + if (t->customData) + doEdgeSlide(t, final); + else { + strcpy(str, "Invalid Edge Selection"); + t->state = TRANS_CANCEL; + } recalcData(t); @@ -4029,7 +4617,6 @@ int BoneEnvelope(TransInfo *t, short mval[2]) return 1; } - /* ******************** EditBone roll *************** */ void initBoneRoll(TransInfo *t) diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index e5bd405c0cd..abe73a755dc 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -32,6 +32,8 @@ #include "ED_transform.h" +#include "BLI_editVert.h" + /* ************************** Types ***************************** */ struct TransInfo; @@ -118,20 +120,9 @@ typedef struct TransCon { /* Apply function pointer for rotation transformation */ } TransCon; -typedef struct TransDataIpokey { - int flag; /* which keys */ - float *locx, *locy, *locz; /* channel pointers */ - float *rotx, *roty, *rotz; - float *quatx, *quaty, *quatz, *quatw; - float *sizex, *sizey, *sizez; - float oldloc[9]; /* storage old values */ - float oldrot[9]; - float oldsize[9]; - float oldquat[12]; -} TransDataIpokey; - typedef struct TransDataExtension { float drot[3]; /* Initial object drot */ + float dquat[4]; /* Initial object dquat */ float dsize[3]; /* Initial object dsize */ float *rot; /* Rotation of the data to transform (Faculative) */ float irot[3]; /* Initial rotation */ @@ -179,6 +170,31 @@ typedef struct TransDataNla { int handle; /* handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends */ } TransDataNla; +struct LinkNode; +struct EditEdge; +struct EditVert; +struct GHash; +typedef struct TransDataSlideUv { + float origuv[2]; + float *uv_up, *uv_down; + //float *fuv[4]; + struct LinkNode *fuv_list; +} TransDataSlideUv; + +typedef struct TransDataSlideVert { + struct EditEdge *up, *down; + struct EditVert origvert; +} TransDataSlideVert; + +typedef struct SlideData { + TransDataSlideUv *slideuv, *suv_last; + int totuv, uvlay_tot; + struct GHash *vhash, **uvhash; + struct EditVert *nearest; + struct LinkNode *edgelist, *vertlist; + short start[2], end[2]; +} SlideData; + typedef struct TransData { float dist; /* Distance needed to affect element (for Proportionnal Editing) */ float rdist; /* Distance to the nearest element (for Proportionnal Editing) */ @@ -194,7 +210,6 @@ typedef struct TransData { struct Object *ob; struct bConstraint *con; /* for objects/bones, the first constraint in its constraint stack */ TransDataExtension *ext; /* for objects, poses. 1 single malloc per TransInfo! */ - TransDataIpokey *tdi; /* for objects, ipo keys. per transdata a malloc */ TransDataCurveHandleFlags *hdata; /* for curves, stores handle flags for modification/cancel */ void *extra; /* extra data (mirrored element pointer, in editmode mesh to EditVert) (editbone for roll fixing) (...) */ short flag; /* Various flags */ @@ -210,6 +225,7 @@ typedef struct MouseInput { short precision_mval[2]; /* mouse position when precision key was pressed */ int center[2]; float factor; + void *data; /* additional data, if needed by the particular function */ } MouseInput; typedef struct TransInfo { @@ -263,6 +279,7 @@ typedef struct TransInfo { struct Object *poseobj; /* if t->flag & T_POSE, this denotes pose object */ void *customData; /* Per Transform custom data */ + void (*customFree)(struct TransInfo *); /* if a special free function is needed */ /*************** NEW STUFF *********************/ @@ -466,6 +483,9 @@ int BoneEnvelope(TransInfo *t, short mval[2]); void initBoneRoll(TransInfo *t); int BoneRoll(TransInfo *t, short mval[2]); +void initEdgeSlide(TransInfo *t); +int EdgeSlide(TransInfo *t, short mval[2]); + void initTimeTranslate(TransInfo *t); int TimeTranslate(TransInfo *t, short mval[2]); @@ -575,7 +595,8 @@ typedef enum { INPUT_HORIZONTAL_RATIO, INPUT_HORIZONTAL_ABSOLUTE, INPUT_VERTICAL_RATIO, - INPUT_VERTICAL_ABSOLUTE + INPUT_VERTICAL_ABSOLUTE, + INPUT_CUSTOM_RATIO } MouseInputMode; void initMouseInput(TransInfo *t, MouseInput *mi, int center[2], short mval[2]); @@ -583,6 +604,8 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode); int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, struct wmEvent *event); void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, short mval[2], float output[3]); +void setCustomPoints(TransInfo *t, MouseInput *mi, short start[2], short end[2]); + /*********************** Generics ********************************/ int initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, struct wmEvent *event); @@ -663,6 +686,8 @@ int getTransformOrientation(const struct bContext *C, float normal[3], float pla int createSpaceNormal(float mat[3][3], float normal[3]); int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]); +void freeSlideVerts(TransInfo *t); + #endif diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 776f2e47d1e..a49950f15f1 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -379,7 +379,6 @@ static void createTransEdge(bContext *C, TransInfo *t) { Mat3CpyMat3(td->mtx, mtx); td->ext = NULL; - td->tdi = NULL; if (t->mode == TFM_BWEIGHT) { td->val = &(eed->bweight); td->ival = eed->bweight; @@ -509,7 +508,7 @@ static short apply_targetless_ik(Object *ob) /* rotation */ if (parchan->rotmode > 0) Mat3ToEulO(rmat3, parchan->eul, parchan->rotmode); - else if (parchan->rotmode == PCHAN_ROT_AXISANGLE) + else if (parchan->rotmode == ROT_MODE_AXISANGLE) Mat3ToAxisAngle(rmat3, &parchan->quat[1], &parchan->quat[0]); else Mat3ToQuat(rmat3, parchan->quat); @@ -519,7 +518,7 @@ static short apply_targetless_ik(Object *ob) if (data->flag & CONSTRAINT_IK_STRETCH) { if (parchan->rotmode > 0) EulOToMat3(parchan->eul, parchan->rotmode, qrmat); - else if (parchan->rotmode == PCHAN_ROT_AXISANGLE) + else if (parchan->rotmode == ROT_MODE_AXISANGLE) AxisAngleToMat3(&parchan->quat[1], parchan->quat[0], qrmat); else QuatToMat3(parchan->quat, qrmat); @@ -556,10 +555,6 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr td->ob = ob; td->flag = TD_SELECTED; - if (pchan->rotmode == PCHAN_ROT_QUAT) - { - td->flag |= TD_USEQUAT; - } if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) { td->flag |= TD_NOCENTER; @@ -584,15 +579,14 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr td->ext->quat= NULL; VECCOPY(td->ext->irot, pchan->eul); - td->rotOrder= pchan->rotmode; } else { td->ext->rot= NULL; td->ext->quat= pchan->quat; QUATCOPY(td->ext->iquat, pchan->quat); - td->rotOrder= pchan->rotmode; } + td->rotOrder= pchan->rotmode; /* proper way to get parent transform + own transform + constraints transform */ @@ -1016,7 +1010,6 @@ static void createTransPose(bContext *C, TransInfo *t, Object *ob) tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt"); for(i=0; i<t->total; i++, td++, tdx++) { td->ext= tdx; - td->tdi = NULL; td->val = NULL; } @@ -1100,7 +1093,6 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td->loc = NULL; td->ext = NULL; - td->tdi = NULL; td++; } @@ -1116,7 +1108,6 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td->loc = NULL; td->ext = NULL; - td->tdi = NULL; td++; } @@ -1151,7 +1142,6 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) Mat3Ortho(td->axismtx); td->ext = NULL; - td->tdi = NULL; td++; } @@ -1168,7 +1158,6 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td->flag= TD_SELECTED; td->ext = NULL; - td->tdi = NULL; td++; } @@ -1196,7 +1185,6 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) } td->ext = NULL; - td->tdi = NULL; td->val = NULL; td++; @@ -1219,7 +1207,6 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t) td->extra = ebo; /* to fix roll */ td->ext = NULL; - td->tdi = NULL; td->val = NULL; td++; @@ -1272,7 +1259,6 @@ static void createTransMBallVerts(bContext *C, TransInfo *t) Mat3CpyMat3(td->mtx, mtx); td->ext = tx; - td->tdi = NULL; /* Radius of MetaElem (mass of MetaElem influence) */ if(ml->flag & MB_SCALE_RAD){ @@ -1437,7 +1423,6 @@ static void createTransCurveVerts(bContext *C, TransInfo *t) else td->flag= 0; } td->ext = NULL; - td->tdi = NULL; td->val = NULL; hdata = initTransDataCurveHandes(td, bezt); @@ -1458,7 +1443,6 @@ static void createTransCurveVerts(bContext *C, TransInfo *t) if(bezt->f2 & SELECT) td->flag= TD_SELECTED; else td->flag= 0; td->ext = NULL; - td->tdi = NULL; if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */ td->val = &(bezt->radius); @@ -1498,7 +1482,6 @@ static void createTransCurveVerts(bContext *C, TransInfo *t) else td->flag= 0; } td->ext = NULL; - td->tdi = NULL; td->val = NULL; if (hdata==NULL) { /* if the handle was not saved by the previous handle */ @@ -1538,7 +1521,6 @@ static void createTransCurveVerts(bContext *C, TransInfo *t) if(bp->f1 & SELECT) td->flag= TD_SELECTED; else td->flag= 0; td->ext = NULL; - td->tdi = NULL; if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) { td->val = &(bp->radius); @@ -1614,7 +1596,6 @@ static void createTransLatticeVerts(bContext *C, TransInfo *t) Mat3CpyMat3(td->mtx, mtx); td->ext = NULL; - td->tdi = NULL; td->val = NULL; td++; @@ -1725,7 +1706,6 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) td->ob = ob; td->ext = tx; - td->tdi = NULL; if(t->mode == TFM_BAKE_TIME) { td->val = key->time; td->ival = *(key->time); @@ -1949,7 +1929,6 @@ static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert td->axismtx[1][2] = 0.0f; td->ext = NULL; - td->tdi = NULL; td->val = NULL; td->extra = NULL; if (t->mode == TFM_BWEIGHT) { @@ -2429,7 +2408,7 @@ static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, f memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; - td->ext= NULL; td->tdi= NULL; td->val= NULL; + td->ext= NULL; td->val= NULL; if(selected) { td->flag |= TD_SELECTED; @@ -2729,7 +2708,7 @@ static void createTransNlaData(bContext *C, TransInfo *t) memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; - td->ext= NULL; td->tdi= NULL; td->val= NULL; + td->ext= NULL; td->val= NULL; td->flag |= TD_SELECTED; td->dist= 0.0f; @@ -2760,7 +2739,7 @@ static void createTransNlaData(bContext *C, TransInfo *t) memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; - td->ext= NULL; td->tdi= NULL; td->val= NULL; + td->ext= NULL; td->val= NULL; td->flag |= TD_SELECTED; td->dist= 0.0f; @@ -3311,7 +3290,7 @@ static void bezt_to_transdata (TransData *td, TransData2D *td2d, AnimData *adt, memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; - td->ext= NULL; td->tdi= NULL; td->val= NULL; + td->ext= NULL; td->val= NULL; /* store AnimData info in td->extra, for applying mapping when flushing */ td->extra= adt; @@ -3744,98 +3723,6 @@ void flushTransGraphData(TransInfo *t) } } -/* **************** IpoKey stuff, for Object TransData ********** */ - -/* while transforming */ -void add_tdi_poin(float *poin, float *old, float delta) -{ - if(poin) { - poin[0]= old[0]+delta; - poin[-3]= old[3]+delta; - poin[3]= old[6]+delta; - } -} - -#if 0 // TRANSFORM_FIX_ME -/* storage of bezier triple. thats why -3 and +3! */ -static void set_tdi_old(float *old, float *poin) -{ - old[0]= *(poin); - old[3]= *(poin-3); - old[6]= *(poin+3); -} - -/* fill ipokey transdata with old vals and pointers */ -static void ipokey_to_transdata(IpoKey *ik, TransData *td) -{ - extern int ob_ar[]; // blenkernel ipo.c - TransDataIpokey *tdi= td->tdi; - BezTriple *bezt; - int a, delta= 0; - - td->val= NULL; // is read on ESC - - for(a=0; a<OB_TOTIPO; a++) { - if(ik->data[a]) { - bezt= ik->data[a]; - - switch( ob_ar[a] ) { - case OB_LOC_X: - case OB_DLOC_X: - tdi->locx= &(bezt->vec[1][1]); break; - case OB_LOC_Y: - case OB_DLOC_Y: - tdi->locy= &(bezt->vec[1][1]); break; - case OB_LOC_Z: - case OB_DLOC_Z: - tdi->locz= &(bezt->vec[1][1]); break; - - case OB_DROT_X: - delta= 1; - case OB_ROT_X: - tdi->rotx= &(bezt->vec[1][1]); break; - case OB_DROT_Y: - delta= 1; - case OB_ROT_Y: - tdi->roty= &(bezt->vec[1][1]); break; - case OB_DROT_Z: - delta= 1; - case OB_ROT_Z: - tdi->rotz= &(bezt->vec[1][1]); break; - - case OB_SIZE_X: - case OB_DSIZE_X: - tdi->sizex= &(bezt->vec[1][1]); break; - case OB_SIZE_Y: - case OB_DSIZE_Y: - tdi->sizey= &(bezt->vec[1][1]); break; - case OB_SIZE_Z: - case OB_DSIZE_Z: - tdi->sizez= &(bezt->vec[1][1]); break; - } - } - } - - /* oldvals for e.g. undo */ - if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx); - if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy); - if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz); - - /* remember, for mapping curves ('1'=10 degrees) */ - if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx); - if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty); - if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz); - - /* this is not allowed to be dsize! */ - if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex); - if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey); - if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez); - - tdi->flag= TOB_IPO; - if(delta) tdi->flag |= TOB_IPODROT; -} -#endif - /* *************************** Object Transform data ******************* */ /* Little helper function for ObjectToTransData used to give certain @@ -4053,7 +3940,7 @@ static TransData *SeqToTransData(TransInfo *t, TransData *td, TransData2D *td2d, memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; - td->ext= NULL; td->tdi= NULL; td->val= NULL; + td->ext= NULL; td->val= NULL; td->flag |= TD_SELECTED; td->dist= 0.0; @@ -4194,20 +4081,20 @@ static void ObjectToTransData(bContext *C, TransInfo *t, TransData *td, Object * if (skip_invert == 0 && (ob->track || constinv==0)) { track= ob->track; ob->track= NULL; - + if (constinv == 0) { fakecons.first = ob->constraints.first; fakecons.last = ob->constraints.last; ob->constraints.first = ob->constraints.last = NULL; } - + where_is_object(t->scene, ob); - + if (constinv == 0) { ob->constraints.first = fakecons.first; ob->constraints.last = fakecons.last; } - + ob->track= track; } else @@ -4221,6 +4108,10 @@ static void ObjectToTransData(bContext *C, TransInfo *t, TransData *td, Object * td->ext->rot = ob->rot; VECCOPY(td->ext->irot, ob->rot); VECCOPY(td->ext->drot, ob->drot); + + td->ext->quat = ob->quat; + QUATCOPY(td->ext->iquat, ob->quat); + QUATCOPY(td->ext->dquat, ob->dquat); td->ext->size = ob->size; VECCOPY(td->ext->isize, ob->size); @@ -4262,7 +4153,7 @@ static void ObjectToTransData(bContext *C, TransInfo *t, TransData *td, Object * /* it deselects Bases, so we have to call the clear function always after */ static void set_trans_object_base_flags(bContext *C, TransInfo *t) { - Scene *sce = CTX_data_scene(C); + Scene *scene = CTX_data_scene(C); View3D *v3d = t->view; /* @@ -4279,15 +4170,15 @@ static void set_trans_object_base_flags(bContext *C, TransInfo *t) copy_baseflags(t->scene); /* handle pending update events, otherwise they got copied below */ - for (base= sce->base.first; base; base= base->next) { + for (base= scene->base.first; base; base= base->next) { if(base->object->recalc) object_handle_update(t->scene, base->object); } - for (base= sce->base.first; base; base= base->next) { + for (base= scene->base.first; base; base= base->next) { base->flag &= ~BA_WAS_SEL; - if(TESTBASELIB(v3d, base)) { + if(TESTBASELIB_BGMODE(v3d, base)) { Object *ob= base->object; Object *parsel= ob->parent; @@ -4319,7 +4210,7 @@ static void set_trans_object_base_flags(bContext *C, TransInfo *t) /* and we store them temporal in base (only used for transform code) */ /* this because after doing updates, the object->recalc is cleared */ - for (base= sce->base.first; base; base= base->next) { + for (base= scene->base.first; base; base= base->next) { if(base->object->recalc & OB_RECALC_OB) base->flag |= BA_HAS_RECALC_OB; if(base->object->recalc & OB_RECALC_DATA) @@ -4516,15 +4407,16 @@ void autokeyframe_pose_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode, insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); } if (doRot) { - if (pchan->rotmode == PCHAN_ROT_QUAT) { - sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name); + // FIXME: better to just use the keyingsets for this instead... + if (pchan->rotmode == ROT_MODE_QUAT) { + sprintf(buf, "pose.pose_channels[\"%s\"].rotation_quaternion", pchan->name); insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); insert_keyframe(id, NULL, pchan->name, buf, 3, cfra, flag); } else { - sprintf(buf, "pose.pose_channels[\"%s\"].euler_rotation", pchan->name); + sprintf(buf, "pose.pose_channels[\"%s\"].rotation_euler", pchan->name); insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); @@ -4544,7 +4436,8 @@ void autokeyframe_pose_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode, insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); - if (pchan->rotmode == PCHAN_ROT_QUAT) { + // FIXME: better to just use the keyingsets for this instead... + if (pchan->rotmode == ROT_MODE_QUAT) { sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name); insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); @@ -4552,7 +4445,7 @@ void autokeyframe_pose_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode, insert_keyframe(id, NULL, pchan->name, buf, 3, cfra, flag); } else { - sprintf(buf, "pose.pose_channels[\"%s\"].euler_rotation", pchan->name); + sprintf(buf, "pose.pose_channels[\"%s\"].rotation_euler", pchan->name); insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); @@ -5001,30 +4894,7 @@ static void createTransObject(bContext *C, TransInfo *t) set_trans_object_base_flags(C, t); /* count */ -#if 0 // TRANSFORM_FIX_ME - CTX_DATA_BEGIN(C, Object*, ob, selected_objects) - { - /* store ipo keys? */ - if ((ob->id.lib == 0) && (ob->ipo) && (ob->ipo->showkey) && (ob->ipoflag & OB_DRAWKEY)) { - elems.first= elems.last= NULL; - make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */ - - pushdata(&elems, sizeof(ListBase)); - - for(ik= elems.first; ik; ik= ik->next) - t->total++; - - if(elems.first==NULL) - t->total++; - } -// else { - t->total++; -// } - } - CTX_DATA_END; -#else t->total= CTX_DATA_COUNT(C, selected_objects); -#endif if(!t->total) { /* clear here, main transform function escapes too */ @@ -5038,92 +4908,27 @@ static void createTransObject(bContext *C, TransInfo *t) CTX_DATA_BEGIN(C, Base*, base, selected_bases) { Object *ob= base->object; - + td->flag = TD_SELECTED; td->protectflag= ob->protectflag; td->ext = tx; - + td->rotOrder= ob->rotmode; + if (base->flag & BA_TRANSFORM_CHILD) { td->flag |= TD_NOCENTER; td->flag |= TD_NO_LOC; } - + /* select linked objects, but skip them later */ if (ob->id.lib != 0) { td->flag |= TD_SKIP; } - - /* store ipo keys? */ - // TRANSFORM_FIX_ME -#if 0 - if((ob->id.lib == 0) && (ob->ipo) && (ob->ipo->showkey) && (ob->ipoflag & OB_DRAWKEY)) { - - popfirst(&elems); // bring back pushed listbase - - if(elems.first) { - int cfraont; - int ipoflag; - - base->flag |= BA_DO_IPO+BA_WAS_SEL; - base->flag &= ~SELECT; - - cfraont= CFRA; - set_no_parent_ipo(1); - ipoflag= ob->ipoflag; - ob->ipoflag &= ~OB_OFFS_OB; - - /* - * This is really EVIL code that pushes down Object values - * (loc, dloc, orig, size, dsize, rot, drot) - * */ - - pushdata((void*)ob->loc, 7 * 3 * sizeof(float)); // tsk! tsk! - - for(ik= elems.first; ik; ik= ik->next) { - - /* weak... this doesn't correct for floating values, giving small errors */ - CFRA= (int)(ik->val/t->scene->r.framelen); - - do_ob_ipo(ob); - ObjectToTransData(C, t, td, ob); // does where_is_object() - - td->flag= TD_SELECTED; - - td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey"); - /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */ - ipokey_to_transdata(ik, td); - - td++; - tx++; - if(ik->next) td->ext= tx; // prevent corrupting mem! - } - free_ipokey(&elems); - - poplast(ob->loc); - set_no_parent_ipo(0); - - CFRA= cfraont; - ob->ipoflag= ipoflag; - - where_is_object(t->scene, ob); // restore - } - else { - ObjectToTransData(C, t, td, ob); - td->tdi = NULL; - td->val = NULL; - td++; - tx++; - } - } -#endif -// else { - ObjectToTransData(C, t, td, ob); - td->tdi = NULL; - td->val = NULL; - td++; - tx++; -// } + + ObjectToTransData(C, t, td, ob); + td->val = NULL; + td++; + tx++; } CTX_DATA_END; } @@ -5145,7 +4950,7 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node) memset(td->axismtx, 0, sizeof(td->axismtx)); td->axismtx[2][2] = 1.0f; - td->ext= NULL; td->tdi= NULL; td->val= NULL; + td->ext= NULL; td->val= NULL; td->flag |= TD_SELECTED; td->dist= 0.0; @@ -5289,7 +5094,7 @@ void createTransData(bContext *C, TransInfo *t) { if(ob_armature->type==OB_ARMATURE) { - if(ob_armature->mode & OB_MODE_POSE) + if((ob_armature->mode & OB_MODE_POSE) && ob_armature == modifiers_isDeformedByArmature(ob)) { createTransPose(C, t, ob_armature); break; @@ -5312,6 +5117,8 @@ void createTransData(bContext *C, TransInfo *t) } else { t->flag &= ~T_PROP_EDIT; /* no proportional edit in object mode */ + t->options |= CTX_NO_PET; + createTransObject(C, t); t->flag |= T_OBJECT; @@ -5319,7 +5126,7 @@ void createTransData(bContext *C, TransInfo *t) { View3D *v3d = t->view; RegionView3D *rv3d = CTX_wm_region_view3d(C); - if((t->flag & T_OBJECT) && v3d->camera == OBACT && rv3d->persp==V3D_CAMOB) + if(rv3d && (t->flag & T_OBJECT) && v3d->camera == OBACT && rv3d->persp==V3D_CAMOB) { t->flag |= T_CAMERA; } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 0b7029adde0..88469794e5d 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -125,19 +125,19 @@ void getViewVector(TransInfo *t, float coord[3], float vec[3]) if (t->persp != V3D_ORTHO) { float p1[4], p2[4]; - + VECCOPY(p1, coord); p1[3] = 1.0f; VECCOPY(p2, p1); p2[3] = 1.0f; Mat4MulVec4fl(t->viewmat, p2); - + p2[0] = 2.0f * p2[0]; p2[1] = 2.0f * p2[1]; p2[2] = 2.0f * p2[2]; - + Mat4MulVec4fl(t->viewinv, p2); - + VecSubf(vec, p1, p2); } else { @@ -153,11 +153,11 @@ static void clipMirrorModifier(TransInfo *t, Object *ob) ModifierData *md= ob->modifiers.first; float tolerance[3] = {0.0f, 0.0f, 0.0f}; int axis = 0; - + for (; md; md=md->next) { if (md->type==eModifierType_Mirror) { MirrorModifierData *mmd = (MirrorModifierData*) md; - + if(mmd->flag & MOD_MIR_CLIPPING) { axis = 0; if(mmd->flag & MOD_MIR_AXIS_X) { @@ -176,35 +176,35 @@ static void clipMirrorModifier(TransInfo *t, Object *ob) float mtx[4][4], imtx[4][4]; int i; TransData *td = t->data; - + if (mmd->mirror_ob) { float obinv[4][4]; - + Mat4Invert(obinv, mmd->mirror_ob->obmat); Mat4MulMat4(mtx, ob->obmat, obinv); Mat4Invert(imtx, mtx); } - + for(i = 0 ; i < t->total; i++, td++) { int clip; float loc[3], iloc[3]; - + if (td->flag & TD_NOACTION) break; if (td->loc==NULL) break; - + if (td->flag & TD_SKIP) continue; - + VecCopyf(loc, td->loc); VecCopyf(iloc, td->iloc); - + if (mmd->mirror_ob) { VecMat4MulVecfl(loc, mtx, loc); VecMat4MulVecfl(iloc, mtx, iloc); } - + clip = 0; if(axis & 1) { if(fabs(iloc[0])<=tolerance[0] || @@ -213,7 +213,7 @@ static void clipMirrorModifier(TransInfo *t, Object *ob) clip = 1; } } - + if(axis & 2) { if(fabs(iloc[1])<=tolerance[1] || loc[1]*iloc[1]<0.0f) { @@ -236,7 +236,7 @@ static void clipMirrorModifier(TransInfo *t, Object *ob) } } } - + } } } @@ -248,7 +248,7 @@ static void editmesh_apply_to_mirror(TransInfo *t) TransData *td = t->data; EditVert *eve; int i; - + for(i = 0 ; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; @@ -256,7 +256,7 @@ static void editmesh_apply_to_mirror(TransInfo *t) break; if (td->flag & TD_SKIP) continue; - + eve = td->extra; if(eve) { eve->co[0]= -td->loc[0]; @@ -620,9 +620,9 @@ void recalcData(TransInfo *t) if ELEM(t->obedit->type, OB_CURVE, OB_SURF) { Curve *cu= t->obedit->data; Nurb *nu= cu->editnurb->first; - + DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */ - + if (t->state == TRANS_CANCEL) { while(nu) { calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */ @@ -648,11 +648,11 @@ void recalcData(TransInfo *t) else if (t->obedit->type == OB_MESH) { if(t->spacetype==SPACE_IMAGE) { SpaceImage *sima= t->sa->spacedata.first; - + flushTransUVs(t); if(sima->flag & SI_LIVE_UNWRAP) ED_uvedit_live_unwrap_re_solve(); - + DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); } else { EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh; @@ -667,9 +667,9 @@ void recalcData(TransInfo *t) } if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR)) editmesh_apply_to_mirror(t); - + DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */ - + recalc_editnormals(em); } } @@ -679,10 +679,10 @@ void recalcData(TransInfo *t) EditBone *ebo; TransData *td = t->data; int i; - + /* Ensure all bones are correctly adjusted */ for (ebo = edbo->first; ebo; ebo = ebo->next){ - + if ((ebo->flag & BONE_CONNECTED) && ebo->parent){ /* If this bone has a parent tip that has been moved */ if (ebo->parent->flag & BONE_TIPSEL){ @@ -695,7 +695,7 @@ void recalcData(TransInfo *t) if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head; } } - + /* on extrude bones, oldlength==0.0f, so we scale radius of points */ ebo->length= VecLenf(ebo->head, ebo->tail); if(ebo->oldlength==0.0f) { @@ -715,8 +715,8 @@ void recalcData(TransInfo *t) ebo->oldlength= ebo->length; } } - - + + if (t->mode != TFM_BONE_ROLL) { /* fix roll */ @@ -726,10 +726,10 @@ void recalcData(TransInfo *t) { float vec[3], up_axis[3]; float qrot[4]; - + ebo = td->extra; VECCOPY(up_axis, td->axismtx[2]); - + if (t->mode != TFM_ROTATION) { VecSubf(vec, ebo->tail, ebo->head); @@ -741,15 +741,15 @@ void recalcData(TransInfo *t) { Mat3MulVecfl(t->mat, up_axis); } - + ebo->roll = ED_rollBoneToVector(ebo, up_axis); } } } - + if(arm->flag & ARM_MIRROR_EDIT) transform_armature_mirror_update(t->obedit); - + } else DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */ @@ -757,7 +757,7 @@ void recalcData(TransInfo *t) else if( (t->flag & T_POSE) && t->poseobj) { Object *ob= t->poseobj; bArmature *arm= ob->data; - + /* if animtimer is running, and the object already has animation data, * check if the auto-record feature means that we should record 'samples' * (i.e. uneditable animation values) @@ -769,7 +769,7 @@ void recalcData(TransInfo *t) animrecord_check_state(t->scene, &ob->id, t->animtimer); autokeyframe_pose_cb_func(t->scene, (View3D *)t->view, ob, t->mode, targetless_ik); } - + /* old optimize trick... this enforces to bypass the depgraph */ if (!(arm->flag & ARM_DELAYDEFORM)) { DAG_id_flush_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ @@ -780,13 +780,13 @@ void recalcData(TransInfo *t) else { for(base= FIRSTBASE; base; base= base->next) { Object *ob= base->object; - + /* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */ if(base->flag & BA_HAS_RECALC_OB) ob->recalc |= OB_RECALC_OB; if(base->flag & BA_HAS_RECALC_DATA) ob->recalc |= OB_RECALC_DATA; - + /* if object/base is selected */ if ((base->flag & SELECT) || (ob->flag & SELECT)) { /* if animtimer is running, and the object already has animation data, @@ -799,7 +799,7 @@ void recalcData(TransInfo *t) autokeyframe_ob_cb_func(t->scene, (View3D *)t->view, ob, t->mode); } } - + /* proxy exception */ if(ob->proxy) ob->proxy->recalc |= ob->recalc; @@ -807,7 +807,7 @@ void recalcData(TransInfo *t) group_tag_recalc(ob->proxy_group->dup_group); } } - + /* update shaded drawmode while transform */ if(t->spacetype==SPACE_VIEW3D && ((View3D*)t->view)->drawtype == OB_SHADED) reshadeall_displist(t->scene); @@ -821,18 +821,18 @@ void drawLine(TransInfo *t, float *center, float *dir, char axis, short options) if (t->spacetype == SPACE_VIEW3D) { View3D *v3d = t->view; - + glPushMatrix(); - + //if(t->obedit) glLoadMatrixf(t->obedit->obmat); // sets opengl viewing - - + + VecCopyf(v3, dir); VecMulf(v3, v3d->far); - + VecSubf(v2, center, v3); VecAddf(v1, center, v3); - + if (options & DRAWLIGHT) { col[0] = col[1] = col[2] = 220; } @@ -841,13 +841,13 @@ void drawLine(TransInfo *t, float *center, float *dir, char axis, short options) } UI_make_axis_color(col, col2, axis); glColor3ubv((GLubyte *)col2); - + setlinestyle(0); glBegin(GL_LINE_STRIP); glVertex3fv(v1); glVertex3fv(v2); glEnd(); - + glPopMatrix(); } } @@ -864,33 +864,33 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) ARegion *ar = CTX_wm_region(C); ScrArea *sa = CTX_wm_area(C); Object *obedit = CTX_data_edit_object(C); - + /* moving: is shown in drawobject() (transform color) */ // TRANSFORM_FIX_ME // if(obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT; // else if(G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE; // else G.moving= G_TRANSFORM_OBJ; - + t->scene = sce; t->sa = sa; t->ar = ar; t->obedit = obedit; t->settings = ts; - + t->data = NULL; t->ext = NULL; - + t->helpline = HLP_NONE; - + t->flag = 0; - + t->redraw = 1; /* redraw first time */ - + if (event) { t->imval[0] = event->x - t->ar->winrct.xmin; t->imval[1] = event->y - t->ar->winrct.ymin; - + t->event_type = event->type; } else @@ -898,45 +898,45 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) t->imval[0] = 0; t->imval[1] = 0; } - + t->con.imval[0] = t->imval[0]; t->con.imval[1] = t->imval[1]; - + t->mval[0] = t->imval[0]; t->mval[1] = t->imval[1]; - + t->transform = NULL; t->handleEvent = NULL; - + t->total = 0; - + t->val = 0.0f; - + t->vec[0] = t->vec[1] = t->vec[2] = 0.0f; - + t->center[0] = t->center[1] = t->center[2] = 0.0f; - + Mat3One(t->mat); - + t->spacetype = sa->spacetype; if(t->spacetype == SPACE_VIEW3D) { View3D *v3d = sa->spacedata.first; - + t->view = v3d; t->animtimer= CTX_wm_screen(C)->animtimer; - + if(v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN; t->around = v3d->around; - + if (op && RNA_struct_find_property(op->ptr, "constraint_axis") && RNA_property_is_set(op->ptr, "constraint_orientation")) { t->current_orientation = RNA_enum_get(op->ptr, "constraint_orientation"); - + if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C) - 1) { t->current_orientation = V3D_MANIP_GLOBAL; @@ -958,10 +958,10 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) { // XXX for now, get View2D from the active region t->view = &ar->v2d; - + t->around = V3D_CENTER; } - + if (op && RNA_struct_find_property(op->ptr, "mirror") && RNA_property_is_set(op->ptr, "mirror")) { if (RNA_boolean_get(op->ptr, "mirror")) @@ -977,57 +977,66 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) t->flag |= T_MIRROR; } } - - /* setting PET flag */ - if (op && RNA_struct_find_property(op->ptr, "proportional") && RNA_property_is_set(op->ptr, "proportional")) + + /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */ + if (op && RNA_struct_find_property(op->ptr, "proportional")) { - switch(RNA_enum_get(op->ptr, "proportional")) + if (RNA_property_is_set(op->ptr, "proportional")) { - case 2: /* XXX connected constant */ - t->flag |= T_PROP_CONNECTED; - case 1: /* XXX prop on constant */ - t->flag |= T_PROP_EDIT; - break; + switch(RNA_enum_get(op->ptr, "proportional")) + { + case 2: /* XXX connected constant */ + t->flag |= T_PROP_CONNECTED; + case 1: /* XXX prop on constant */ + t->flag |= T_PROP_EDIT; + break; + } } - } - else - { - if ((t->options & CTX_NO_PET) == 0 && (ts->proportional)) { - t->flag |= T_PROP_EDIT; - - if(ts->proportional == 2) - t->flag |= T_PROP_CONNECTED; // yes i know, has to become define + else + { + if ((t->options & CTX_NO_PET) == 0 && (ts->proportional)) { + t->flag |= T_PROP_EDIT; + + if(ts->proportional == 2) + t->flag |= T_PROP_CONNECTED; // yes i know, has to become define + } + } + + if (op && RNA_struct_find_property(op->ptr, "proportional_size") && RNA_property_is_set(op->ptr, "proportional_size")) + { + t->prop_size = RNA_float_get(op->ptr, "proportional_size"); + } + else + { + t->prop_size = ts->proportional_size; + } + + + /* TRANSFORM_FIX_ME rna restrictions */ + if (t->prop_size <= 0) + { + t->prop_size = 1.0f; + } + + if (op && RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && RNA_property_is_set(op->ptr, "proportional_editing_falloff")) + { + t->prop_mode = RNA_enum_get(op->ptr, "proportional_editing_falloff"); + } + else + { + t->prop_mode = ts->prop_mode; } } - - if (op && RNA_struct_find_property(op->ptr, "proportional_size") && RNA_property_is_set(op->ptr, "proportional_size")) - { - t->prop_size = RNA_float_get(op->ptr, "proportional_size"); - } - else - { - t->prop_size = ts->proportional_size; - } - - if (op && RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && RNA_property_is_set(op->ptr, "proportional_editing_falloff")) - { - t->prop_mode = RNA_enum_get(op->ptr, "proportional_editing_falloff"); - } - else - { - t->prop_mode = ts->prop_mode; - } - - /* TRANSFORM_FIX_ME rna restrictions */ - if (t->prop_size <= 0) + else /* add not pet option to context when not available */ { - t->prop_size = 1.0f; + t->options |= CTX_NO_PET; } - + + setTransformViewMatrices(t); initNumInput(&t->num); initNDofInput(&t->ndof); - + return 1; } @@ -1035,45 +1044,53 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) void postTrans (TransInfo *t) { TransData *td; - + if (t->draw_handle) { ED_region_draw_cb_exit(t->ar->type, t->draw_handle); } - + /* postTrans can be called when nothing is selected, so data is NULL already */ if (t->data) { int a; - + /* since ipokeys are optional on objects, we mallocced them per trans-data */ for(a=0, td= t->data; a<t->total; a++, td++) { - if(td->tdi) MEM_freeN(td->tdi); - if (td->flag & TD_BEZTRIPLE) MEM_freeN(td->hdata); + if (td->flag & TD_BEZTRIPLE) + MEM_freeN(td->hdata); } MEM_freeN(t->data); } - + if (t->ext) MEM_freeN(t->ext); if (t->data2d) { MEM_freeN(t->data2d); t->data2d= NULL; } - + if(t->spacetype==SPACE_IMAGE) { SpaceImage *sima= t->sa->spacedata.first; if(sima->flag & SI_LIVE_UNWRAP) ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL); } - else if(ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA)) { - if (t->customData) - MEM_freeN(t->customData); + + if (t->mouse.data) + { + MEM_freeN(t->mouse.data); + } + + if (t->customFree) { + t->customFree(t); + } + else if (t->customData) { + MEM_freeN(t->customData); } } void applyTransObjects(TransInfo *t) { TransData *td; - + for (td = t->data; td < t->data + t->total; td++) { VECCOPY(td->iloc, td->loc); if (td->ext->rot) { @@ -1086,16 +1103,6 @@ void applyTransObjects(TransInfo *t) recalcData(t); } -/* helper for below */ -static void restore_ipokey(float *poin, float *old) -{ - if(poin) { - poin[0]= old[0]; - poin[-3]= old[3]; - poin[3]= old[6]; - } -} - static void restoreElement(TransData *td) { /* TransData for crease has no loc */ if (td->loc) { @@ -1111,45 +1118,27 @@ static void restoreElement(TransData *td) { if (td->ext->size) { VECCOPY(td->ext->size, td->ext->isize); } - if(td->flag & TD_USEQUAT) { - if (td->ext->quat) { - QUATCOPY(td->ext->quat, td->ext->iquat); - } + if (td->ext->quat) { + QUATCOPY(td->ext->quat, td->ext->iquat); } } - + if (td->flag & TD_BEZTRIPLE) { *(td->hdata->h1) = td->hdata->ih1; *(td->hdata->h2) = td->hdata->ih2; } - - if(td->tdi) { - TransDataIpokey *tdi= td->tdi; - - restore_ipokey(tdi->locx, tdi->oldloc); - restore_ipokey(tdi->locy, tdi->oldloc+1); - restore_ipokey(tdi->locz, tdi->oldloc+2); - - restore_ipokey(tdi->rotx, tdi->oldrot); - restore_ipokey(tdi->roty, tdi->oldrot+1); - restore_ipokey(tdi->rotz, tdi->oldrot+2); - - restore_ipokey(tdi->sizex, tdi->oldsize); - restore_ipokey(tdi->sizey, tdi->oldsize+1); - restore_ipokey(tdi->sizez, tdi->oldsize+2); - } } void restoreTransObjects(TransInfo *t) { TransData *td; - + for (td = t->data; td < t->data + t->total; td++) { restoreElement(td); } - + Mat3One(t->mat); - + recalcData(t); } @@ -1158,7 +1147,7 @@ void calculateCenter2D(TransInfo *t) if (t->flag & (T_EDIT|T_POSE)) { Object *ob= t->obedit?t->obedit:t->poseobj; float vec[3]; - + VECCOPY(vec, t->center); Mat4MulVecfl(ob->obmat, vec); projectIntView(t, vec, t->center2d); @@ -1171,21 +1160,21 @@ void calculateCenter2D(TransInfo *t) void calculateCenterCursor(TransInfo *t) { float *cursor; - + cursor = give_cursor(t->scene, t->view); VECCOPY(t->center, cursor); - + /* If edit or pose mode, move cursor in local space */ if (t->flag & (T_EDIT|T_POSE)) { Object *ob = t->obedit?t->obedit:t->poseobj; float mat[3][3], imat[3][3]; - + VecSubf(t->center, t->center, ob->obmat[3]); Mat3CpyMat4(mat, ob->obmat); Mat3Inv(imat, mat); Mat3MulVecfl(imat, t->center); } - + calculateCenter2D(t); } @@ -1193,15 +1182,15 @@ void calculateCenterCursor2D(TransInfo *t) { View2D *v2d= t->view; float aspx=1.0, aspy=1.0; - + if(t->spacetype==SPACE_IMAGE) /* only space supported right now but may change */ ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy); - + if (v2d) { t->center[0] = v2d->cursor[0] * aspx; t->center[1] = v2d->cursor[1] * aspy; } - + calculateCenter2D(t); } @@ -1210,7 +1199,7 @@ void calculateCenterMedian(TransInfo *t) float partial[3] = {0.0f, 0.0f, 0.0f}; int total = 0; int i; - + for(i = 0; i < t->total; i++) { if (t->data[i].flag & TD_SELECTED) { if (!(t->data[i].flag & TD_NOCENTER)) @@ -1230,7 +1219,7 @@ void calculateCenterMedian(TransInfo *t) if(i) VecMulf(partial, 1.0f / total); VECCOPY(t->center, partial); - + calculateCenter2D(t); } @@ -1260,7 +1249,7 @@ void calculateCenterBound(TransInfo *t) } VecAddf(t->center, min, max); VecMulf(t->center, 0.5); - + calculateCenter2D(t); } @@ -1296,7 +1285,7 @@ void calculateCenter(TransInfo *t) break; } /* END EDIT MODE ACTIVE ELEMENT */ #endif - + calculateCenterMedian(t); if((t->flag & (T_EDIT|T_POSE))==0) { @@ -1308,10 +1297,10 @@ void calculateCenter(TransInfo *t) projectIntView(t, t->center, t->center2d); } } - + } } - + /* setting constraint center */ VECCOPY(t->con.center, t->center); if(t->flag & (T_EDIT|T_POSE)) @@ -1319,8 +1308,8 @@ void calculateCenter(TransInfo *t) Object *ob= t->obedit?t->obedit:t->poseobj; Mat4MulVecfl(ob->obmat, t->con.center); } - - /* voor panning from cameraview */ + + /* for panning from cameraview */ if(t->flag & T_OBJECT) { if(t->spacetype==SPACE_VIEW3D && t->ar->regiontype == RGN_TYPE_WINDOW) @@ -1328,21 +1317,21 @@ void calculateCenter(TransInfo *t) View3D *v3d = t->view; Scene *scene = t->scene; RegionView3D *rv3d = t->ar->regiondata; - + if(v3d->camera == OBACT && rv3d->persp==V3D_CAMOB) { float axis[3]; /* persinv is nasty, use viewinv instead, always right */ VECCOPY(axis, t->viewinv[2]); Normalize(axis); - + /* 6.0 = 6 grid units */ axis[0]= t->center[0]- 6.0f*axis[0]; axis[1]= t->center[1]- 6.0f*axis[1]; axis[2]= t->center[2]- 6.0f*axis[2]; - + projectIntView(t, axis, t->center2d); - + /* rotate only needs correct 2d center, grab needs initgrabz() value */ if(t->mode==TFM_TRANSLATION) { @@ -1352,14 +1341,14 @@ void calculateCenter(TransInfo *t) } } } - + if(t->spacetype==SPACE_VIEW3D) { /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d_delta() */ if(t->flag & (T_EDIT|T_POSE)) { Object *ob= t->obedit?t->obedit:t->poseobj; float vec[3]; - + VECCOPY(vec, t->center); Mat4MulVecfl(ob->obmat, vec); initgrabz(t->ar->regiondata, vec[0], vec[1], vec[2]); @@ -1399,7 +1388,7 @@ void calculatePropRatio(TransInfo *t) /* Use rdist for falloff calculations, it is the real distance */ td->flag &= ~TD_NOACTION; dist= (t->prop_size-td->rdist)/t->prop_size; - + /* * Clamp to positive numbers. * Certain corner cases with connectivity and individual centers @@ -1407,7 +1396,7 @@ void calculatePropRatio(TransInfo *t) */ if (dist < 0.0f) dist = 0.0f; - + switch(t->prop_mode) { case PROP_SHARP: td->factor= dist*dist; @@ -1474,20 +1463,20 @@ float get_drawsize(ARegion *ar, float *co) { RegionView3D *rv3d= ar->regiondata; float size, vec[3], len1, len2; - + /* size calculus, depending ortho/persp settings, like initgrabz() */ size= rv3d->persmat[0][3]*co[0]+ rv3d->persmat[1][3]*co[1]+ rv3d->persmat[2][3]*co[2]+ rv3d->persmat[3][3]; - + VECCOPY(vec, rv3d->persinv[0]); len1= Normalize(vec); VECCOPY(vec, rv3d->persinv[1]); len2= Normalize(vec); - + size*= 0.01f*(len1>len2?len1:len2); - + /* correct for window size to make widgets appear fixed size */ if(ar->winx > ar->winy) size*= 1000.0f/(float)ar->winx; else size*= 1000.0f/(float)ar->winy; - + return size; } diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 6bd0a8c8d42..83d4a314057 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -34,7 +34,7 @@ #include "transform.h" - +#include "MEM_guardedalloc.h" /* ************************** INPUT FROM MOUSE *************************** */ @@ -163,6 +163,47 @@ void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, short mval[2], float ou output[0] = Inpf(t->viewinv[1], vec) * 2.0f; } +void setCustomPoints(TransInfo *t, MouseInput *mi, short start[2], short end[2]) +{ + short *data = mi->data; + + data[0] = start[0]; + data[1] = start[1]; + data[2] = end[0]; + data[3] = end[1]; +} + +void InputCustomRatio(TransInfo *t, MouseInput *mi, short mval[2], float output[3]) +{ + float length; + float distance; + short *data = mi->data; + short dx, dy; + + dx = data[2] - data[0]; + dy = data[3] - data[1]; + + length = (float)sqrtf(dx*dx + dy*dy); + + if (mi->precision) { + /* deal with Shift key by adding motion / 10 to motion before shift press */ + short mdx, mdy; + mdx = (mi->precision_mval[0] + (float)(mval[0] - mi->precision_mval[0]) / 10.0f) - data[2]; + mdy = (mi->precision_mval[1] + (float)(mval[1] - mi->precision_mval[1]) / 10.0f) - data[3]; + + distance = (mdx*dx + mdy*dy) / length; + } + else { + short mdx, mdy; + mdx = mval[0] - data[2]; + mdy = mval[1] - data[3]; + + distance = (mdx*dx + mdy*dy) / length; + } + + output[0] = distance / length; +} + void InputAngle(TransInfo *t, MouseInput *mi, short mval[2], float output[3]) { double dx2 = mval[0] - mi->center[0]; @@ -291,6 +332,11 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) mi->apply = InputVerticalAbsolute; t->helpline = HLP_VARROW; break; + case INPUT_CUSTOM_RATIO: + mi->apply = InputCustomRatio; + t->helpline = HLP_NONE; + mi->data = MEM_callocN(sizeof(short) * 4, "custom points"); + break; case INPUT_NONE: default: mi->apply = NULL; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 8d7e8f20ad5..f369fba79df 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -99,6 +99,7 @@ char OP_SHRINK_FATTEN[] = "TFM_OT_shrink_fatten"; char OP_TILT[] = "TFM_OT_tilt"; char OP_TRACKBALL[] = "TFM_OT_trackball"; char OP_MIRROR[] = "TFM_OT_mirror"; +char OP_EDGE_SLIDE[] = "TFM_OT_edge_slide"; TransformModeItem transform_modes[] = @@ -113,6 +114,7 @@ TransformModeItem transform_modes[] = {OP_TILT, TFM_TILT}, {OP_TRACKBALL, TFM_TRACKBALL}, {OP_MIRROR, TFM_MIRROR}, + {OP_EDGE_SLIDE, TFM_EDGE_SLIDE}, {NULL, 0} }; @@ -270,7 +272,7 @@ static int transform_invoke(bContext *C, wmOperator *op, wmEvent *event) TransInfo *t = op->customdata; /* add temp handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); t->flag |= T_MODAL; // XXX meh maybe somewhere else @@ -523,7 +525,7 @@ void TFM_OT_tosphere(struct wmOperatorType *ot) ot->cancel = transform_cancel; ot->poll = ED_operator_areaactive; - RNA_def_float_percentage(ot->srna, "value", 0, 0, 1, "Percentage", "", 0, 1); + RNA_def_float_factor(ot->srna, "value", 0, 0, 1, "Factor", "", 0, 1); Properties_Proportional(ot); @@ -549,6 +551,26 @@ void TFM_OT_mirror(struct wmOperatorType *ot) Properties_Constraints(ot); } +void TFM_OT_edge_slide(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Edge Slide"; + ot->description= "Slide an edge loop along a mesh."; + ot->idname = OP_EDGE_SLIDE; + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; + + /* api callbacks */ + ot->invoke = transform_invoke; + ot->exec = transform_exec; + ot->modal = transform_modal; + ot->cancel = transform_cancel; + ot->poll = ED_operator_editmesh; + + RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f); + + RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", ""); +} + void TFM_OT_transform(struct wmOperatorType *ot) { static EnumPropertyItem transform_mode_types[] = { @@ -578,6 +600,7 @@ void TFM_OT_transform(struct wmOperatorType *ot) {TFM_BEVEL, "BEVEL", 0, "Bevel", ""}, {TFM_BWEIGHT, "BWEIGHT", 0, "Bweight", ""}, {TFM_ALIGN, "ALIGN", 0, "Align", ""}, + {TFM_EDGE_SLIDE, "EDGESLIDE", 0, "Edge Slide", ""}, {0, NULL, 0, NULL, NULL} }; @@ -617,11 +640,12 @@ void transform_operatortypes(void) WM_operatortype_append(TFM_OT_tilt); WM_operatortype_append(TFM_OT_trackball); WM_operatortype_append(TFM_OT_mirror); + WM_operatortype_append(TFM_OT_edge_slide); WM_operatortype_append(TFM_OT_select_orientation); } -void transform_keymap_for_space(struct wmWindowManager *wm, struct ListBase *keymap, int spaceid) +void transform_keymap_for_space(struct wmWindowManager *wm, struct wmKeyMap *keymap, int spaceid) { wmKeymapItem *km; diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 9416425704f..d82be842596 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -353,7 +353,8 @@ void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target) { void BIF_selectTransformOrientationValue(bContext *C, int orientation) { View3D *v3d = CTX_wm_view3d(C); - v3d->twmode = orientation; + if(v3d) /* currently using generic poll */ + v3d->twmode = orientation; } EnumPropertyItem *BIF_enumTransformOrientation(bContext *C) diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index a58ee9772e9..fbd12007c16 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -251,17 +251,17 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac if(efa->v4) { #if 0 /* Simple but slow, better reuse normalized vectors */ - uvang1 = VecAngle3_2D(tf_uv[3], tf_uv[0], tf_uv[1]); - ang1 = VecAngle3(efa->v4->co, efa->v1->co, efa->v2->co); + uvang1 = RAD2DEG(Vec2Angle3(tf_uv[3], tf_uv[0], tf_uv[1])); + ang1 = RAD2DEG(VecAngle3(efa->v4->co, efa->v1->co, efa->v2->co)); - uvang2 = VecAngle3_2D(tf_uv[0], tf_uv[1], tf_uv[2]); - ang2 = VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co); + uvang2 = RAD2DEG(Vec2Angle3(tf_uv[0], tf_uv[1], tf_uv[2])); + ang2 = RAD2DEG(VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co)); - uvang3 = VecAngle3_2D(tf_uv[1], tf_uv[2], tf_uv[3]); - ang3 = VecAngle3(efa->v2->co, efa->v3->co, efa->v4->co); + uvang3 = RAD2DEG(Vec2Angle3(tf_uv[1], tf_uv[2], tf_uv[3])); + ang3 = RAD2DEG(VecAngle3(efa->v2->co, efa->v3->co, efa->v4->co)); - uvang4 = VecAngle3_2D(tf_uv[2], tf_uv[3], tf_uv[0]); - ang4 = VecAngle3(efa->v3->co, efa->v4->co, efa->v1->co); + uvang4 = RAD2DEG(Vec2Angle3(tf_uv[2], tf_uv[3], tf_uv[0])); + ang4 = RAD2DEG(VecAngle3(efa->v3->co, efa->v4->co, efa->v1->co)); #endif /* uv angles */ @@ -315,14 +315,14 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFac } else { #if 0 /* Simple but slow, better reuse normalized vectors */ - uvang1 = VecAngle3_2D(tf_uv[2], tf_uv[0], tf_uv[1]); - ang1 = VecAngle3(efa->v3->co, efa->v1->co, efa->v2->co); + uvang1 = RAD2DEG(Vec2Angle3(tf_uv[2], tf_uv[0], tf_uv[1])); + ang1 = RAD2DEG(VecAngle3(efa->v3->co, efa->v1->co, efa->v2->co)); - uvang2 = VecAngle3_2D(tf_uv[0], tf_uv[1], tf_uv[2]); - ang2 = VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co); + uvang2 = RAD2DEG(Vec2Angle3(tf_uv[0], tf_uv[1], tf_uv[2])); + ang2 = RAD2DEG(VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co)); - uvang3 = 180-(uvang1+uvang2); - ang3 = 180-(ang1+ang2); + uvang3 = M_PI-(uvang1+uvang2); + ang3 = M_PI-(ang1+ang2); #endif /* uv angles */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 9051300e117..9216cfb5cdc 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -77,7 +77,7 @@ int ED_uvedit_test(Object *obedit) EditMesh *em; int ret; - if(obedit->type != OB_MESH) + if(!obedit || obedit->type != OB_MESH) return 0; em = BKE_mesh_get_editmesh(obedit->data); @@ -180,7 +180,13 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist { int width, height; - ED_space_image_size(sima, &width, &height); + if(sima) { + ED_space_image_size(sima, &width, &height); + } + else { + width= 256; + height= 256; + } dist[0]= pixeldist/width; dist[1]= pixeldist/height; @@ -1097,11 +1103,11 @@ static int stitch_exec(bContext *C, wmOperator *op) if(RNA_boolean_get(op->ptr, "use_limit")) { UvVertMap *vmap; UvMapVert *vlist, *iterv; - float newuv[2], limit[2], pixels; + float newuv[2], limit[2]; int a, vtot; - pixels= RNA_float_get(op->ptr, "limit"); - uvedit_pixel_to_float(sima, limit, pixels); + limit[0]= RNA_float_get(op->ptr, "limit"); + limit[1]= limit[0]; EM_init_index_arrays(em, 0, 0, 1); vmap= EM_make_uv_vert_map(em, 1, 0, limit); @@ -1255,7 +1261,7 @@ void UV_OT_stitch(wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "use_limit", 1, "Use Limit", "Stitch UVs within a specified limit distance."); - RNA_def_float(ot->srna, "limit", 20.0, 0.0f, FLT_MAX, "Limit", "Limit distance in image pixels.", -FLT_MAX, FLT_MAX); + RNA_def_float(ot->srna, "limit", 0.01f, 0.0f, FLT_MAX, "Limit", "Limit distance in normalized coordinates.", -FLT_MAX, FLT_MAX); } /* ******************** (de)select all operator **************** */ @@ -1439,7 +1445,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) else { sync= 0; selectmode= ts->uv_selectmode; - sticky= sima->sticky; + sticky= (sima)? sima->sticky: 1; } /* find nearest element */ @@ -2471,13 +2477,18 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit) { EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); - Image *ima= sima->image; + Image *ima; EditFace *efa; MTFace *tface; int width= 0, height= 0; float w, h; short change = 0; + if(!sima) + return 0; + + ima= sima->image; + ED_space_image_size(sima, &width, &height); w = (float)width; h = (float)height; @@ -2657,6 +2668,7 @@ static int hide_exec(bContext *C, wmOperator *op) EditFace *efa; MTFace *tf; int swap= RNA_boolean_get(op->ptr, "unselected"); + int facemode= sima ? sima->flag & SI_SELACTFACE : 0; if(ts->uv_flag & UV_SYNC_SELECTION) { EM_hide_mesh(em, swap); @@ -2670,7 +2682,7 @@ static int hide_exec(bContext *C, wmOperator *op) for(efa= em->faces.first; efa; efa= efa->next) { if(efa->f & SELECT) { tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(sima->flag & SI_SELACTFACE) { + if(facemode) { /* Pretend face mode */ if(( (efa->v4==NULL && ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) || @@ -2715,7 +2727,7 @@ static int hide_exec(bContext *C, wmOperator *op) if(efa->f & SELECT) { tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if(sima->flag & SI_SELACTFACE) { + if(facemode) { if( (efa->v4==NULL && ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) == (TF_SEL1|TF_SEL2|TF_SEL3) ) || ( tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) == (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4) ) { @@ -2799,6 +2811,8 @@ static int reveal_exec(bContext *C, wmOperator *op) EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data); EditFace *efa; MTFace *tf; + int facemode= sima ? sima->flag & SI_SELACTFACE : 0; + int stickymode= sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; /* call the mesh function if we are in mesh sync sel */ if(ts->uv_flag & UV_SYNC_SELECTION) { @@ -2809,7 +2823,7 @@ static int reveal_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - if(sima->flag & SI_SELACTFACE) { + if(facemode) { if(em->selectmode == SCE_SELECT_FACE) { for(efa= em->faces.first; efa; efa= efa->next) { if(!(efa->h) && !(efa->f & SELECT)) { @@ -2821,7 +2835,7 @@ static int reveal_exec(bContext *C, wmOperator *op) } else { /* enable adjacent faces to have disconnected UV selections if sticky is disabled */ - if(sima->sticky == SI_STICKY_DISABLE) { + if(!stickymode) { for(efa= em->faces.first; efa; efa= efa->next) { if(!(efa->h) && !(efa->f & SELECT)) { /* All verts must be unselected for the face to be selected in the UV view */ @@ -3072,7 +3086,10 @@ void ED_operatortypes_uvedit(void) void ED_keymap_uvedit(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "UVEdit", 0, 0); + wmKeyMap *keymap; + + keymap= WM_keymap_find(wm, "UVEdit", 0, 0); + keymap->poll= ED_operator_uvedit; /* pick selection */ WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index ccdc51430bc..c7258e616fa 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -342,7 +342,7 @@ static int minimize_stretch_invoke(bContext *C, wmOperator *op, wmEvent *event) minimize_stretch_iteration(C, op, 1); ms= op->customdata; - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); ms->timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER, 0.01f); return OPERATOR_RUNNING_MODAL; @@ -423,7 +423,7 @@ void UV_OT_minimize_stretch(wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry."); - RNA_def_float_percentage(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original.", 0.0f, 1.0f); + RNA_def_float_factor(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original.", 0.0f, 1.0f); RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively.", 0, 100); } diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index d7b54e425fd..55e4b337a77 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -346,25 +346,34 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels) tex->number = 0; glBindTexture(tex->target, tex->bindcode); + GPU_print_error("3D glBindTexture"); + type = GL_FLOAT; // GL_UNSIGNED_BYTE format = GL_RED; - internalformat = GL_RED; + internalformat = GL_INTENSITY; //if (fpixels) // pixels = GPU_texture_convert_pixels(w*h*depth, fpixels); glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, 0); + GPU_print_error("3D glTexImage3D"); + if (fpixels) { glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels); + GPU_print_error("3D glTexSubImage3D"); } + glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor); + GPU_print_error("3D GL_TEXTURE_BORDER_COLOR"); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + GPU_print_error("3D GL_LINEAR"); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER); + GPU_print_error("3D GL_CLAMP_TO_BORDER"); if (pixels) MEM_freeN(pixels); diff --git a/source/blender/ikplugin/BIK_api.h b/source/blender/ikplugin/BIK_api.h new file mode 100644 index 00000000000..a259d0aa62a --- /dev/null +++ b/source/blender/ikplugin/BIK_api.h @@ -0,0 +1,93 @@ +/** + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Original author: Benoit Bolsee + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BIK_API_H +#define BIK_API_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct Object; +struct bPoseChannel; +struct bPose; +struct bArmature; +struct Scene; +struct bConstraint; + +enum BIK_ParamType { + BIK_PARAM_TYPE_FLOAT = 0, + BIK_PARAM_TYPE_INT, + BIK_PARAM_TYPE_STRING, +}; + +struct BIK_ParamValue { + short type; /* BIK_PARAM_TYPE_.. */ + short length; /* for string, does not include terminating 0 */ + union { + float f[8]; + int i[8]; + char s[32]; + } value; +}; +typedef struct BIK_ParamValue BIK_ParamValue; + +void BIK_initialize_tree(struct Scene *scene, struct Object *ob, float ctime); +void BIK_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime); +void BIK_release_tree(struct Scene *scene, struct Object *ob, float ctime); +void BIK_clear_data(struct bPose *pose); +void BIK_clear_cache(struct bPose *pose); +void BIK_update_param(struct bPose *pose); +void BIK_test_constraint(struct Object *ob, struct bConstraint *cons); +// not yet implemented +int BIK_get_constraint_param(struct bPose *pose, struct bConstraint *cons, int id, BIK_ParamValue *value); +int BIK_get_channel_param(struct bPose *pose, struct bPoseChannel *pchan, int id, BIK_ParamValue *value); +int BIK_get_solver_param(struct bPose *pose, struct bPoseChannel *pchan, int id, BIK_ParamValue *value); + +// number of solver available +// 0 = iksolver +// 1 = iTaSC +#define BIK_SOLVER_COUNT 2 + +/* for use in BIK_get_constraint_param */ +#define BIK_PARAM_CONSTRAINT_ERROR 0 + +/* for use in BIK_get_channel_param */ +#define BIK_PARAM_CHANNEL_JOINT 0 + +/* for use in BIK_get_solver_param */ +#define BIK_PARAM_SOLVER_RANK 0 +#define BIK_PARAM_SOLVER_ITERATION 1 + +#ifdef __cplusplus +} +#endif + +#endif // BIK_API_H + diff --git a/source/blender/ikplugin/CMakeLists.txt b/source/blender/ikplugin/CMakeLists.txt new file mode 100644 index 00000000000..5790d4ef12f --- /dev/null +++ b/source/blender/ikplugin/CMakeLists.txt @@ -0,0 +1,35 @@ +# $Id: CMakeLists.txt 20156 2009-05-11 16:31:30Z ben2610 $ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2006, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Jacques Beaurain. +# +# ***** END GPL LICENSE BLOCK ***** + +FILE(GLOB SRC intern/*.c intern/*.cpp) + +SET(INC + ../../../intern/guardedalloc ../../../intern/iksolver/extern + ../../../intern/itasc ../../../extern/Eigen2 + ../blenlib ../makesdna ../blenkernel ../include ../ikplugin +) + +BLENDERLIB(bf_ikplugin "${SRC}" "${INC}") diff --git a/source/blender/ikplugin/Makefile b/source/blender/ikplugin/Makefile new file mode 100644 index 00000000000..370ed418464 --- /dev/null +++ b/source/blender/ikplugin/Makefile @@ -0,0 +1,31 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL LICENSE BLOCK ***** +# +# Bounces make to subdirectories. + +SOURCEDIR = source/blender/ikplugin +DIRS = intern + +include nan_subdirs.mk diff --git a/source/blender/ikplugin/SConscript b/source/blender/ikplugin/SConscript new file mode 100644 index 00000000000..a745a93077a --- /dev/null +++ b/source/blender/ikplugin/SConscript @@ -0,0 +1,9 @@ +#!/usr/bin/python +Import ('env') + +sources = env.Glob('intern/*.c') + env.Glob('intern/*.cpp') + +incs = '#/intern/guardedalloc #/intern/iksolver/extern ../makesdna ../blenlib' +incs += ' ../blenkernel ../include ../ikplugin #/intern/itasc #/extern/Eigen2' + +env.BlenderLib ( 'bf_ikplugin', sources, Split(incs), [], libtype=['core','player'], priority=[180, 190] ) diff --git a/source/blender/ikplugin/intern/Makefile b/source/blender/ikplugin/intern/Makefile new file mode 100644 index 00000000000..0c54e5d1264 --- /dev/null +++ b/source/blender/ikplugin/intern/Makefile @@ -0,0 +1,51 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL LICENSE BLOCK ***** +# +# + +LIBNAME = ikplugin +DIR = $(OCGDIR)/blender/ikplugin + +include nan_compile.mk + +CFLAGS += $(LEVEL_1_C_WARNINGS) +CFLAGS += -I$(NAN_GUARDEDALLOC)/include +CFLAGS += -I../../makesdna +CFLAGS += -I../../blenkernel +CFLAGS += -I../../blenlib +CFLAGS += -I../../include +CFLAGS += -I../../../../intern/itasc +CFLAGS += -I../../../../extern/Eigen2 +CFLAGS += -I.. + +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I$(NAN_IKSOLVER)/include +CPPFLAGS += -I../../makesdna +CPPFLAGS += -I../../blenkernel +CPPFLAGS += -I../../blenlib +CPPFLAGS += -I../../include +CPPFLAGS += -I../../../../intern/itasc +CPPFLAGS += -I../../../../extern/Eigen2 +CPPFLAGS += -I.. diff --git a/source/blender/ikplugin/intern/ikplugin_api.c b/source/blender/ikplugin/intern/ikplugin_api.c new file mode 100644 index 00000000000..f106302dbaf --- /dev/null +++ b/source/blender/ikplugin/intern/ikplugin_api.c @@ -0,0 +1,138 @@ +/** + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Original author: Benoit Bolsee + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "MEM_guardedalloc.h" + +#include "BIK_api.h" +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "BKE_armature.h" +#include "BKE_utildefines.h" +#include "DNA_object_types.h" +#include "DNA_action_types.h" +#include "DNA_scene_types.h" +#include "DNA_constraint_types.h" +#include "DNA_armature_types.h" + +#include "ikplugin_api.h" +#include "iksolver_plugin.h" +#include "itasc_plugin.h" + + +static IKPlugin ikplugin_tab[BIK_SOLVER_COUNT] = { + /* Legacy IK solver */ + { + iksolver_initialize_tree, + iksolver_execute_tree, + NULL, + NULL, + NULL, + NULL, + NULL, + }, + /* iTaSC IK solver */ + { + itasc_initialize_tree, + itasc_execute_tree, + itasc_release_tree, + itasc_clear_data, + itasc_clear_cache, + itasc_update_param, + itasc_test_constraint, + } +}; + + +static IKPlugin *get_plugin(bPose *pose) +{ + if (!pose || pose->iksolver < 0 || pose->iksolver >= BIK_SOLVER_COUNT) + return NULL; + + return &ikplugin_tab[pose->iksolver]; +} + +/*----------------------------------------*/ +/* Plugin API */ + +void BIK_initialize_tree(Scene *scene, Object *ob, float ctime) +{ + IKPlugin *plugin = get_plugin(ob->pose); + + if (plugin && plugin->initialize_tree_func) + plugin->initialize_tree_func(scene, ob, ctime); +} + +void BIK_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan, float ctime) +{ + IKPlugin *plugin = get_plugin(ob->pose); + + if (plugin && plugin->execute_tree_func) + plugin->execute_tree_func(scene, ob, pchan, ctime); +} + +void BIK_release_tree(struct Scene *scene, Object *ob, float ctime) +{ + IKPlugin *plugin = get_plugin(ob->pose); + + if (plugin && plugin->release_tree_func) + plugin->release_tree_func(scene, ob, ctime); +} + +void BIK_clear_data(struct bPose *pose) +{ + IKPlugin *plugin = get_plugin(pose); + + if (plugin && plugin->remove_armature_func) + plugin->remove_armature_func(pose); +} + +void BIK_clear_cache(struct bPose *pose) +{ + IKPlugin *plugin = get_plugin(pose); + + if (plugin && plugin->clear_cache) + plugin->clear_cache(pose); +} + +void BIK_update_param(struct bPose *pose) +{ + IKPlugin *plugin = get_plugin(pose); + + if (plugin && plugin->update_param) + plugin->update_param(pose); +} + +void BIK_test_constraint(struct Object *ob, struct bConstraint *cons) +{ + IKPlugin *plugin = get_plugin(ob->pose); + + if (plugin && plugin->test_constraint) + plugin->test_constraint(ob, cons); +} diff --git a/source/blender/ikplugin/intern/ikplugin_api.h b/source/blender/ikplugin/intern/ikplugin_api.h new file mode 100644 index 00000000000..cc4dff4ec75 --- /dev/null +++ b/source/blender/ikplugin/intern/ikplugin_api.h @@ -0,0 +1,60 @@ +/** + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Original author: Benoit Bolsee + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef IKPLUGIN_API_H +#define IKPLUGIN_API_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct Object; +struct bPoseChannel; +struct bArmature; +struct Scene; + + +struct IKPlugin { + void (*initialize_tree_func)(struct Scene *scene, struct Object *ob, float ctime); + void (*execute_tree_func)(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime); + void (*release_tree_func)(struct Scene *scene, struct Object *ob, float ctime); + void (*remove_armature_func)(struct bPose *pose); + void (*clear_cache)(struct bPose *pose); + void (*update_param)(struct bPose *pose); + void (*test_constraint)(struct Object *ob, struct bConstraint *cons); +}; + +typedef struct IKPlugin IKPlugin; + +#ifdef __cplusplus +} +#endif + +#endif // IKPLUGIN_API_H + diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c new file mode 100644 index 00000000000..68afbcd0db2 --- /dev/null +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -0,0 +1,530 @@ +/** + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Original author: Benoit Bolsee + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "MEM_guardedalloc.h" + +#include "BIK_api.h" +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "BKE_armature.h" +#include "BKE_constraint.h" +#include "BKE_utildefines.h" +#include "DNA_object_types.h" +#include "DNA_action_types.h" +#include "DNA_constraint_types.h" +#include "DNA_armature_types.h" + +#include "IK_solver.h" +#include "iksolver_plugin.h" + +#include <string.h> /* memcpy */ + +/* ********************** THE IK SOLVER ******************* */ + +/* allocates PoseTree, and links that to root bone/channel */ +/* Note: detecting the IK chain is duplicate code... in drawarmature.c and in transform_conversions.c */ +static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) +{ + bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256], **oldchan; + PoseTree *tree; + PoseTarget *target; + bConstraint *con; + bKinematicConstraint *data; + int a, segcount= 0, size, newsize, *oldparent, parent; + + /* find IK constraint, and validate it */ + for(con= pchan_tip->constraints.first; con; con= con->next) { + if(con->type==CONSTRAINT_TYPE_KINEMATIC) { + data=(bKinematicConstraint*)con->data; + if (data->flag & CONSTRAINT_IK_AUTO) break; + if (data->tar==NULL) continue; + if (data->tar->type==OB_ARMATURE && data->subtarget[0]==0) continue; + if ((con->flag & (CONSTRAINT_DISABLE|CONSTRAINT_OFF))==0 && (con->enforce!=0.0)) break; + } + } + if(con==NULL) return; + + /* exclude tip from chain? */ + if(!(data->flag & CONSTRAINT_IK_TIP)) + pchan_tip= pchan_tip->parent; + + /* Find the chain's root & count the segments needed */ + for (curchan = pchan_tip; curchan; curchan=curchan->parent){ + pchan_root = curchan; + + curchan->flag |= POSE_CHAIN; // don't forget to clear this + chanlist[segcount]=curchan; + segcount++; + + if(segcount==data->rootbone || segcount>255) break; // 255 is weak + } + if (!segcount) return; + + /* setup the chain data */ + + /* we make tree-IK, unless all existing targets are in this chain */ + for(tree= pchan_root->iktree.first; tree; tree= tree->next) { + for(target= tree->targets.first; target; target= target->next) { + curchan= tree->pchan[target->tip]; + if(curchan->flag & POSE_CHAIN) + curchan->flag &= ~POSE_CHAIN; + else + break; + } + if(target) break; + } + + /* create a target */ + target= MEM_callocN(sizeof(PoseTarget), "posetarget"); + target->con= con; + pchan_tip->flag &= ~POSE_CHAIN; + + if(tree==NULL) { + /* make new tree */ + tree= MEM_callocN(sizeof(PoseTree), "posetree"); + + tree->iterations= data->iterations; + tree->totchannel= segcount; + tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH); + + tree->pchan= MEM_callocN(segcount*sizeof(void*), "ik tree pchan"); + tree->parent= MEM_callocN(segcount*sizeof(int), "ik tree parent"); + for(a=0; a<segcount; a++) { + tree->pchan[a]= chanlist[segcount-a-1]; + tree->parent[a]= a-1; + } + target->tip= segcount-1; + + /* AND! link the tree to the root */ + BLI_addtail(&pchan_root->iktree, tree); + } + else { + tree->iterations= MAX2(data->iterations, tree->iterations); + tree->stretch= tree->stretch && !(data->flag & CONSTRAINT_IK_STRETCH); + + /* skip common pose channels and add remaining*/ + size= MIN2(segcount, tree->totchannel); + for(a=0; a<size && tree->pchan[a]==chanlist[segcount-a-1]; a++); + parent= a-1; + + segcount= segcount-a; + target->tip= tree->totchannel + segcount - 1; + + if (segcount > 0) { + /* resize array */ + newsize= tree->totchannel + segcount; + oldchan= tree->pchan; + oldparent= tree->parent; + + tree->pchan= MEM_callocN(newsize*sizeof(void*), "ik tree pchan"); + tree->parent= MEM_callocN(newsize*sizeof(int), "ik tree parent"); + memcpy(tree->pchan, oldchan, sizeof(void*)*tree->totchannel); + memcpy(tree->parent, oldparent, sizeof(int)*tree->totchannel); + MEM_freeN(oldchan); + MEM_freeN(oldparent); + + /* add new pose channels at the end, in reverse order */ + for(a=0; a<segcount; a++) { + tree->pchan[tree->totchannel+a]= chanlist[segcount-a-1]; + tree->parent[tree->totchannel+a]= tree->totchannel+a-1; + } + tree->parent[tree->totchannel]= parent; + + tree->totchannel= newsize; + } + + /* move tree to end of list, for correct evaluation order */ + BLI_remlink(&pchan_root->iktree, tree); + BLI_addtail(&pchan_root->iktree, tree); + } + + /* add target to the tree */ + BLI_addtail(&tree->targets, target); + /* mark root channel having an IK tree */ + pchan_root->flag |= POSE_IKTREE; +} + + +/* transform from bone(b) to bone(b+1), store in chan_mat */ +static void make_dmats(bPoseChannel *pchan) +{ + if (pchan->parent) { + float iR_parmat[4][4]; + Mat4Invert(iR_parmat, pchan->parent->pose_mat); + Mat4MulMat4(pchan->chan_mat, pchan->pose_mat, iR_parmat); // delta mat + } + else Mat4CpyMat4(pchan->chan_mat, pchan->pose_mat); +} + +/* applies IK matrix to pchan, IK is done separated */ +/* formula: pose_mat(b) = pose_mat(b-1) * diffmat(b-1, b) * ik_mat(b) */ +/* to make this work, the diffmats have to be precalculated! Stored in chan_mat */ +static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = to detect if this is first bone +{ + float vec[3], ikmat[4][4]; + + Mat4CpyMat3(ikmat, ik_mat); + + if (pchan->parent) + Mat4MulSerie(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat, NULL, NULL, NULL, NULL, NULL); + else + Mat4MulMat4(pchan->pose_mat, ikmat, pchan->chan_mat); + + /* calculate head */ + VECCOPY(pchan->pose_head, pchan->pose_mat[3]); + /* calculate tail */ + VECCOPY(vec, pchan->pose_mat[1]); + VecMulf(vec, pchan->bone->length); + VecAddf(pchan->pose_tail, pchan->pose_head, vec); + + pchan->flag |= POSE_DONE; +} + + +/* called from within the core where_is_pose loop, all animsystems and constraints +were executed & assigned. Now as last we do an IK pass */ +static void execute_posetree(Object *ob, PoseTree *tree) +{ + float R_parmat[3][3], identity[3][3]; + float iR_parmat[3][3]; + float R_bonemat[3][3]; + float goalrot[3][3], goalpos[3]; + float rootmat[4][4], imat[4][4]; + float goal[4][4], goalinv[4][4]; + float irest_basis[3][3], full_basis[3][3]; + float end_pose[4][4], world_pose[4][4]; + float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL; + float resultinf=0.0f; + int a, flag, hasstretch=0, resultblend=0; + bPoseChannel *pchan; + IK_Segment *seg, *parent, **iktree, *iktarget; + IK_Solver *solver; + PoseTarget *target; + bKinematicConstraint *data, *poleangledata=NULL; + Bone *bone; + + if (tree->totchannel == 0) + return; + + iktree= MEM_mallocN(sizeof(void*)*tree->totchannel, "ik tree"); + + for(a=0; a<tree->totchannel; a++) { + pchan= tree->pchan[a]; + bone= pchan->bone; + + /* set DoF flag */ + flag= 0; + if(!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP)) + flag |= IK_XDOF; + if(!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP)) + flag |= IK_YDOF; + if(!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP)) + flag |= IK_ZDOF; + + if(tree->stretch && (pchan->ikstretch > 0.0)) { + flag |= IK_TRANS_YDOF; + hasstretch = 1; + } + + seg= iktree[a]= IK_CreateSegment(flag); + + /* find parent */ + if(a == 0) + parent= NULL; + else + parent= iktree[tree->parent[a]]; + + IK_SetParent(seg, parent); + + /* get the matrix that transforms from prevbone into this bone */ + Mat3CpyMat4(R_bonemat, pchan->pose_mat); + + /* gather transformations for this IK segment */ + + if (pchan->parent) + Mat3CpyMat4(R_parmat, pchan->parent->pose_mat); + else + Mat3One(R_parmat); + + /* bone offset */ + if (pchan->parent && (a > 0)) + VecSubf(start, pchan->pose_head, pchan->parent->pose_tail); + else + /* only root bone (a = 0) has no parent */ + start[0]= start[1]= start[2]= 0.0f; + + /* change length based on bone size */ + length= bone->length*VecLength(R_bonemat[1]); + + /* compute rest basis and its inverse */ + Mat3CpyMat3(rest_basis, bone->bone_mat); + Mat3CpyMat3(irest_basis, bone->bone_mat); + Mat3Transp(irest_basis); + + /* compute basis with rest_basis removed */ + Mat3Inv(iR_parmat, R_parmat); + Mat3MulMat3(full_basis, iR_parmat, R_bonemat); + Mat3MulMat3(basis, irest_basis, full_basis); + + /* basis must be pure rotation */ + Mat3Ortho(basis); + + /* transform offset into local bone space */ + Mat3Ortho(iR_parmat); + Mat3MulVecfl(iR_parmat, start); + + IK_SetTransform(seg, start, rest_basis, basis, length); + + if (pchan->ikflag & BONE_IK_XLIMIT) + IK_SetLimit(seg, IK_X, pchan->limitmin[0], pchan->limitmax[0]); + if (pchan->ikflag & BONE_IK_YLIMIT) + IK_SetLimit(seg, IK_Y, pchan->limitmin[1], pchan->limitmax[1]); + if (pchan->ikflag & BONE_IK_ZLIMIT) + IK_SetLimit(seg, IK_Z, pchan->limitmin[2], pchan->limitmax[2]); + + IK_SetStiffness(seg, IK_X, pchan->stiffness[0]); + IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]); + IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]); + + if(tree->stretch && (pchan->ikstretch > 0.0)) { + float ikstretch = pchan->ikstretch*pchan->ikstretch; + IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0-ikstretch, 0.99)); + IK_SetLimit(seg, IK_TRANS_Y, 0.001, 1e10); + } + } + + solver= IK_CreateSolver(iktree[0]); + + /* set solver goals */ + + /* first set the goal inverse transform, assuming the root of tree was done ok! */ + pchan= tree->pchan[0]; + if (pchan->parent) + /* transform goal by parent mat, so this rotation is not part of the + segment's basis. otherwise rotation limits do not work on the + local transform of the segment itself. */ + Mat4CpyMat4(rootmat, pchan->parent->pose_mat); + else + Mat4One(rootmat); + VECCOPY(rootmat[3], pchan->pose_head); + + Mat4MulMat4 (imat, rootmat, ob->obmat); + Mat4Invert (goalinv, imat); + + for (target=tree->targets.first; target; target=target->next) { + float polepos[3]; + int poleconstrain= 0; + + data= (bKinematicConstraint*)target->con->data; + + /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though + * strictly speaking, it is a posechannel) + */ + get_constraint_target_matrix(target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); + + /* and set and transform goal */ + Mat4MulMat4(goal, rootmat, goalinv); + + VECCOPY(goalpos, goal[3]); + Mat3CpyMat4(goalrot, goal); + + /* same for pole vector target */ + if(data->poletar) { + get_constraint_target_matrix(target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); + + if(data->flag & CONSTRAINT_IK_SETANGLE) { + /* don't solve IK when we are setting the pole angle */ + break; + } + else { + Mat4MulMat4(goal, rootmat, goalinv); + VECCOPY(polepos, goal[3]); + poleconstrain= 1; + + /* for pole targets, we blend the result of the ik solver + * instead of the target position, otherwise we can't get + * a smooth transition */ + resultblend= 1; + resultinf= target->con->enforce; + + if(data->flag & CONSTRAINT_IK_GETANGLE) { + poleangledata= data; + data->flag &= ~CONSTRAINT_IK_GETANGLE; + } + } + } + + /* do we need blending? */ + if (!resultblend && target->con->enforce!=1.0) { + float q1[4], q2[4], q[4]; + float fac= target->con->enforce; + float mfac= 1.0-fac; + + pchan= tree->pchan[target->tip]; + + /* end effector in world space */ + Mat4CpyMat4(end_pose, pchan->pose_mat); + VECCOPY(end_pose[3], pchan->pose_tail); + Mat4MulSerie(world_pose, goalinv, ob->obmat, end_pose, 0, 0, 0, 0, 0); + + /* blend position */ + goalpos[0]= fac*goalpos[0] + mfac*world_pose[3][0]; + goalpos[1]= fac*goalpos[1] + mfac*world_pose[3][1]; + goalpos[2]= fac*goalpos[2] + mfac*world_pose[3][2]; + + /* blend rotation */ + Mat3ToQuat(goalrot, q1); + Mat4ToQuat(world_pose, q2); + QuatInterpol(q, q1, q2, mfac); + QuatToMat3(q, goalrot); + } + + iktarget= iktree[target->tip]; + + if(data->weight != 0.0) { + if(poleconstrain) + IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, + polepos, data->poleangle*M_PI/180, (poleangledata == data)); + IK_SolverAddGoal(solver, iktarget, goalpos, data->weight); + } + if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0)) + if((data->flag & CONSTRAINT_IK_AUTO)==0) + IK_SolverAddGoalOrientation(solver, iktarget, goalrot, + data->orientweight); + } + + /* solve */ + IK_Solve(solver, 0.0f, tree->iterations); + + if(poleangledata) + poleangledata->poleangle= IK_SolverGetPoleAngle(solver)*180/M_PI; + + IK_FreeSolver(solver); + + /* gather basis changes */ + tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change"); + if(hasstretch) + ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch"); + + for(a=0; a<tree->totchannel; a++) { + IK_GetBasisChange(iktree[a], tree->basis_change[a]); + + if(hasstretch) { + /* have to compensate for scaling received from parent */ + float parentstretch, stretch; + + pchan= tree->pchan[a]; + parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0; + + if(tree->stretch && (pchan->ikstretch > 0.0)) { + float trans[3], length; + + IK_GetTranslationChange(iktree[a], trans); + length= pchan->bone->length*VecLength(pchan->pose_mat[1]); + + ikstretch[a]= (length == 0.0)? 1.0: (trans[1]+length)/length; + } + else + ikstretch[a] = 1.0; + + stretch= (parentstretch == 0.0)? 1.0: ikstretch[a]/parentstretch; + + VecMulf(tree->basis_change[a][0], stretch); + VecMulf(tree->basis_change[a][1], stretch); + VecMulf(tree->basis_change[a][2], stretch); + } + + if(resultblend && resultinf!=1.0f) { + Mat3One(identity); + Mat3BlendMat3(tree->basis_change[a], identity, + tree->basis_change[a], resultinf); + } + + IK_FreeSegment(iktree[a]); + } + + MEM_freeN(iktree); + if(ikstretch) MEM_freeN(ikstretch); +} + +static void free_posetree(PoseTree *tree) +{ + BLI_freelistN(&tree->targets); + if(tree->pchan) MEM_freeN(tree->pchan); + if(tree->parent) MEM_freeN(tree->parent); + if(tree->basis_change) MEM_freeN(tree->basis_change); + MEM_freeN(tree); +} + +///---------------------------------------- +/// Plugin API for legacy iksolver + +void iksolver_initialize_tree(struct Scene *scene, struct Object *ob, float ctime) +{ + bPoseChannel *pchan; + + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if(pchan->constflag & PCHAN_HAS_IK) // flag is set on editing constraints + initialize_posetree(ob, pchan); // will attach it to root! + } + ob->pose->flag &= ~POSE_WAS_REBUILT; +} + +void iksolver_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime) +{ + while(pchan->iktree.first) { + PoseTree *tree= pchan->iktree.first; + int a; + + /* 4. walk over the tree for regular solving */ + for(a=0; a<tree->totchannel; a++) { + if(!(tree->pchan[a]->flag & POSE_DONE)) // successive trees can set the flag + where_is_pose_bone(scene, ob, tree->pchan[a], ctime); + // tell blender that this channel was controlled by IK, it's cleared on each where_is_pose() + tree->pchan[a]->flag |= POSE_CHAIN; + } + /* 5. execute the IK solver */ + execute_posetree(ob, tree); + + /* 6. apply the differences to the channels, + we need to calculate the original differences first */ + for(a=0; a<tree->totchannel; a++) + make_dmats(tree->pchan[a]); + + for(a=0; a<tree->totchannel; a++) + /* sets POSE_DONE */ + where_is_ik_bone(tree->pchan[a], tree->basis_change[a]); + + /* 7. and free */ + BLI_remlink(&pchan->iktree, tree); + free_posetree(tree); + } +} + diff --git a/source/blender/ikplugin/intern/iksolver_plugin.h b/source/blender/ikplugin/intern/iksolver_plugin.h new file mode 100644 index 00000000000..d5d1d9a77da --- /dev/null +++ b/source/blender/ikplugin/intern/iksolver_plugin.h @@ -0,0 +1,47 @@ +/** + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Original author: Benoit Bolsee + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef IKSOLVER_PLUGIN_H +#define IKSOLVER_PLUGIN_H + +#include "ikplugin_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void iksolver_initialize_tree(struct Scene *scene, struct Object *ob, float ctime); +void iksolver_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime); + +#ifdef __cplusplus +} +#endif + +#endif // IKSOLVER_PLUGIN_H + diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp new file mode 100644 index 00000000000..dc0c2c4c12f --- /dev/null +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -0,0 +1,1777 @@ +/** + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Original author: Benoit Bolsee + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <string.h> +#include <vector> + +// iTaSC headers +#include "Armature.hpp" +#include "MovingFrame.hpp" +#include "CopyPose.hpp" +#include "WSDLSSolver.hpp" +#include "WDLSSolver.hpp" +#include "Scene.hpp" +#include "Cache.hpp" +#include "Distance.hpp" + +#include "MEM_guardedalloc.h" + +extern "C" { +#include "BIK_api.h" +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "BKE_global.h" +#include "BKE_armature.h" +#include "BKE_action.h" +#include "BKE_utildefines.h" +#include "BKE_constraint.h" +#include "DNA_object_types.h" +#include "DNA_action_types.h" +#include "DNA_constraint_types.h" +#include "DNA_armature_types.h" +#include "DNA_scene_types.h" +}; + +#include "itasc_plugin.h" + +// default parameters +bItasc DefIKParam; + +// in case of animation mode, feedback and timestep is fixed +#define ANIM_TIMESTEP 1.0 +#define ANIM_FEEDBACK 0.8 +#define ANIM_QMAX 0.52 + + +// Structure pointed by bPose.ikdata +// It contains everything needed to simulate the armatures +// There can be several simulation islands independent to each other +struct IK_Data +{ + struct IK_Scene* first; +}; + +typedef float Vector3[3]; +typedef float Vector4[4]; +struct IK_Target; +typedef void (*ErrorCallback)(const iTaSC::ConstraintValues* values, unsigned int nvalues, IK_Target* iktarget); +// For some reason, gcc doesn't find the declaration of this function in linux +void KDL::SetToZero(JntArray& array); + +// one structure for each target in the scene +struct IK_Target +{ + iTaSC::MovingFrame* target; + iTaSC::ConstraintSet* constraint; + struct bConstraint* blenderConstraint; + struct bPoseChannel* rootChannel; + Object* owner; //for auto IK + ErrorCallback errorCallback; + std::string targetName; + std::string constraintName; + unsigned short controlType; + short channel; //index in IK channel array of channel on which this target is defined + short ee; //end effector number + bool simulation; //true when simulation mode is used (update feedback) + bool eeBlend; //end effector affected by enforce blending + float eeRest[4][4]; //end effector initial pose relative to armature + + IK_Target() { + target = NULL; + constraint = NULL; + blenderConstraint = NULL; + rootChannel = NULL; + owner = NULL; + controlType = 0; + channel = 0; + ee = 0; + eeBlend = true; + simulation = true; + targetName.reserve(32); + constraintName.reserve(32); + } + ~IK_Target() { + if (constraint) + delete constraint; + if (target) + delete target; + } +}; + +struct IK_Channel { + bPoseChannel* pchan; // channel where we must copy matrix back + KDL::Frame frame; // frame of the bone relative to object base, not armature base + std::string tail; // segment name of the joint from which we get the bone tail + std::string head; // segment name of the joint from which we get the bone head + int parent; // index in this array of the parent channel + short jointType; // type of joint, combination of IK_SegmentFlag + char ndof; // number of joint angles for this channel + char jointValid; // set to 1 when jointValue has been computed + // for joint constraint + Object* owner; // for pose and IK param + double jointValue[4]; // computed joint value + + IK_Channel() { + pchan = NULL; + parent = -1; + jointType = 0; + ndof = 0; + jointValid = 0; + owner = NULL; + jointValue[0] = 0.0; + jointValue[1] = 0.0; + jointValue[2] = 0.0; + jointValue[3] = 0.0; + } +}; + +struct IK_Scene +{ + IK_Scene* next; + int numchan; // number of channel in pchan + int numjoint; // number of joint in jointArray + // array of bone information, one per channel in the tree + IK_Channel* channels; + iTaSC::Armature* armature; + iTaSC::Cache* cache; + iTaSC::Scene* scene; + iTaSC::MovingFrame* base; // armature base object + KDL::Frame baseFrame; // frame of armature base relative to blArmature + KDL::JntArray jointArray; // buffer for storing temporary joint array + iTaSC::Solver* solver; + Object* blArmature; + struct bConstraint* polarConstraint; + std::vector<IK_Target*> targets; + + IK_Scene() { + next = NULL; + channels = NULL; + armature = NULL; + cache = NULL; + scene = NULL; + base = NULL; + solver = NULL; + blArmature = NULL; + numchan = 0; + numjoint = 0; + polarConstraint = NULL; + } + + ~IK_Scene() { + // delete scene first + if (scene) + delete scene; + for(std::vector<IK_Target*>::iterator it = targets.begin(); it != targets.end(); ++it) + delete (*it); + targets.clear(); + if (channels) + delete [] channels; + if (solver) + delete solver; + if (armature) + delete armature; + if (base) + delete base; + // delete cache last + if (cache) + delete cache; + } +}; + +// type of IK joint, can be combined to list the joints corresponding to a bone +enum IK_SegmentFlag { + IK_XDOF = 1, + IK_YDOF = 2, + IK_ZDOF = 4, + IK_SWING = 8, + IK_REVOLUTE = 16, + IK_TRANSY = 32, +}; + +enum IK_SegmentAxis { + IK_X = 0, + IK_Y = 1, + IK_Z = 2, + IK_TRANS_X = 3, + IK_TRANS_Y = 4, + IK_TRANS_Z = 5 +}; + +static int initialize_chain(Object *ob, bPoseChannel *pchan_tip, bConstraint *con) +{ + bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256], **oldchan; + PoseTree *tree; + PoseTarget *target; + bKinematicConstraint *data; + int a, t, segcount= 0, size, newsize, *oldparent, parent, rootbone, treecount; + + data=(bKinematicConstraint*)con->data; + + /* exclude tip from chain? */ + if(!(data->flag & CONSTRAINT_IK_TIP)) + pchan_tip= pchan_tip->parent; + + rootbone = data->rootbone; + /* Find the chain's root & count the segments needed */ + for (curchan = pchan_tip; curchan; curchan=curchan->parent){ + pchan_root = curchan; + + if (++segcount > 255) // 255 is weak + break; + + if(segcount==rootbone){ + // reached this end of the chain but if the chain is overlapping with a + // previous one, we must go back up to the root of the other chain + if ((curchan->flag & POSE_CHAIN) && curchan->iktree.first == NULL){ + rootbone++; + continue; + } + break; + } + + if (curchan->iktree.first != NULL) + // Oh oh, there is already a chain starting from this channel and our chain is longer... + // Should handle this by moving the previous chain up to the begining of our chain + // For now we just stop here + break; + } + if (!segcount) return 0; + // we reached a limit and still not the end of a previous chain, quit + if ((pchan_root->flag & POSE_CHAIN) && pchan_root->iktree.first == NULL) return 0; + + // now that we know how many segment we have, set the flag + for (rootbone = segcount, segcount = 0, curchan = pchan_tip; segcount < rootbone; segcount++, curchan=curchan->parent) { + chanlist[segcount]=curchan; + curchan->flag |= POSE_CHAIN; + } + + /* setup the chain data */ + /* create a target */ + target= (PoseTarget*)MEM_callocN(sizeof(PoseTarget), "posetarget"); + target->con= con; + // by contruction there can be only one tree per channel and each channel can be part of at most one tree. + tree = (PoseTree*)pchan_root->iktree.first; + + if(tree==NULL) { + /* make new tree */ + tree= (PoseTree*)MEM_callocN(sizeof(PoseTree), "posetree"); + + tree->iterations= data->iterations; + tree->totchannel= segcount; + tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH); + + tree->pchan= (bPoseChannel**)MEM_callocN(segcount*sizeof(void*), "ik tree pchan"); + tree->parent= (int*)MEM_callocN(segcount*sizeof(int), "ik tree parent"); + for(a=0; a<segcount; a++) { + tree->pchan[a]= chanlist[segcount-a-1]; + tree->parent[a]= a-1; + } + target->tip= segcount-1; + + /* AND! link the tree to the root */ + BLI_addtail(&pchan_root->iktree, tree); + // new tree + treecount = 1; + } + else { + tree->iterations= MAX2(data->iterations, tree->iterations); + tree->stretch= tree->stretch && !(data->flag & CONSTRAINT_IK_STRETCH); + + /* skip common pose channels and add remaining*/ + size= MIN2(segcount, tree->totchannel); + a = t = 0; + while (a<size && t<tree->totchannel) { + // locate first matching channel + for (;t<tree->totchannel && tree->pchan[t]!=chanlist[segcount-a-1];t++); + if (t>=tree->totchannel) + break; + for(; a<size && t<tree->totchannel && tree->pchan[t]==chanlist[segcount-a-1]; a++, t++); + } + parent= a-1; + segcount= segcount-a; + target->tip= tree->totchannel + segcount - 1; + + if (segcount > 0) { + /* resize array */ + newsize= tree->totchannel + segcount; + oldchan= tree->pchan; + oldparent= tree->parent; + + tree->pchan= (bPoseChannel**)MEM_callocN(newsize*sizeof(void*), "ik tree pchan"); + tree->parent= (int*)MEM_callocN(newsize*sizeof(int), "ik tree parent"); + memcpy(tree->pchan, oldchan, sizeof(void*)*tree->totchannel); + memcpy(tree->parent, oldparent, sizeof(int)*tree->totchannel); + MEM_freeN(oldchan); + MEM_freeN(oldparent); + + /* add new pose channels at the end, in reverse order */ + for(a=0; a<segcount; a++) { + tree->pchan[tree->totchannel+a]= chanlist[segcount-a-1]; + tree->parent[tree->totchannel+a]= tree->totchannel+a-1; + } + tree->parent[tree->totchannel]= parent; + + tree->totchannel= newsize; + } + // reusing tree + treecount = 0; + } + + /* add target to the tree */ + BLI_addtail(&tree->targets, target); + /* mark root channel having an IK tree */ + pchan_root->flag |= POSE_IKTREE; + return treecount; +} + +static bool is_cartesian_constraint(bConstraint *con) +{ + //bKinematicConstraint* data=(bKinematicConstraint*)con->data; + + return true; +} + +static bool constraint_valid(bConstraint *con) +{ + bKinematicConstraint* data=(bKinematicConstraint*)con->data; + + if (data->flag & CONSTRAINT_IK_AUTO) + return true; + if (con->flag & CONSTRAINT_DISABLE) + return false; + if (is_cartesian_constraint(con)) { + /* cartesian space constraint */ + if (data->tar==NULL) + return false; + if (data->tar->type==OB_ARMATURE && data->subtarget[0]==0) + return false; + } + return true; +} + +int initialize_scene(Object *ob, bPoseChannel *pchan_tip) +{ + bConstraint *con; + int treecount; + + /* find all IK constraints and validate them */ + treecount = 0; + for(con= (bConstraint *)pchan_tip->constraints.first; con; con= (bConstraint *)con->next) { + if(con->type==CONSTRAINT_TYPE_KINEMATIC) { + if (constraint_valid(con)) + treecount += initialize_chain(ob, pchan_tip, con); + } + } + return treecount; +} + +static IK_Data* get_ikdata(bPose *pose) +{ + if (pose->ikdata) + return (IK_Data*)pose->ikdata; + pose->ikdata = MEM_callocN(sizeof(IK_Data), "iTaSC ikdata"); + // here init ikdata if needed + // now that we have scene, make sure the default param are initialized + if (!DefIKParam.iksolver) + init_pose_itasc(&DefIKParam); + + return (IK_Data*)pose->ikdata; +} +static double EulerAngleFromMatrix(const KDL::Rotation& R, int axis) +{ + double t = KDL::sqrt(R(0,0)*R(0,0) + R(0,1)*R(0,1)); + + if (t > 16.0*KDL::epsilon) { + if (axis == 0) return -KDL::atan2(R(1,2), R(2,2)); + else if(axis == 1) return KDL::atan2(-R(0,2), t); + else return -KDL::atan2(R(0,1), R(0,0)); + } else { + if (axis == 0) return -KDL::atan2(-R(2,1), R(1,1)); + else if(axis == 1) return KDL::atan2(-R(0,2), t); + else return 0.0f; + } +} + +static double ComputeTwist(const KDL::Rotation& R) +{ + // qy and qw are the y and w components of the quaternion from R + double qy = R(0,2) - R(2,0); + double qw = R(0,0) + R(1,1) + R(2,2) + 1; + + double tau = 2*KDL::atan2(qy, qw); + + return tau; +} + +static void RemoveEulerAngleFromMatrix(KDL::Rotation& R, double angle, int axis) +{ + // compute twist parameter + KDL::Rotation T; + switch (axis) { + case 0: + T = KDL::Rotation::RotX(-angle); + break; + case 1: + T = KDL::Rotation::RotY(-angle); + break; + case 2: + T = KDL::Rotation::RotZ(-angle); + break; + default: + return; + } + // remove angle + R = R*T; +} + +#if 0 +static void GetEulerXZY(const KDL::Rotation& R, double& X,double& Z,double& Y) +{ + if (fabs(R(0,1)) > 1.0 - KDL::epsilon ) { + X = -KDL::sign(R(0,1)) * KDL::atan2(R(1,2), R(1,0)); + Z = -KDL::sign(R(0,1)) * KDL::PI / 2; + Y = 0.0 ; + } else { + X = KDL::atan2(R(2,1), R(1,1)); + Z = KDL::atan2(-R(0,1), KDL::sqrt( KDL::sqr(R(0,0)) + KDL::sqr(R(0,2)))); + Y = KDL::atan2(R(0,2), R(0,0)); + } +} + +static void GetEulerXYZ(const KDL::Rotation& R, double& X,double& Y,double& Z) +{ + if (fabs(R(0,2)) > 1.0 - KDL::epsilon ) { + X = KDL::sign(R(0,2)) * KDL::atan2(-R(1,0), R(1,1)); + Y = KDL::sign(R(0,2)) * KDL::PI / 2; + Z = 0.0 ; + } else { + X = KDL::atan2(-R(1,2), R(2,2)); + Y = KDL::atan2(R(0,2), KDL::sqrt( KDL::sqr(R(0,0)) + KDL::sqr(R(0,1)))); + Z = KDL::atan2(-R(0,1), R(0,0)); + } +} +#endif + +static void GetJointRotation(KDL::Rotation& boneRot, int type, double* rot) +{ + switch (type & ~IK_TRANSY) + { + default: + // fixed bone, no joint + break; + case IK_XDOF: + // RX only, get the X rotation + rot[0] = EulerAngleFromMatrix(boneRot, 0); + break; + case IK_YDOF: + // RY only, get the Y rotation + rot[0] = ComputeTwist(boneRot); + break; + case IK_ZDOF: + // RZ only, get the Z rotation + rot[0] = EulerAngleFromMatrix(boneRot, 2); + break; + case IK_XDOF|IK_YDOF: + rot[1] = ComputeTwist(boneRot); + RemoveEulerAngleFromMatrix(boneRot, rot[1], 1); + rot[0] = EulerAngleFromMatrix(boneRot, 0); + break; + case IK_SWING: + // RX+RZ + boneRot.GetXZRot().GetValue(rot); + break; + case IK_YDOF|IK_ZDOF: + // RZ+RY + rot[1] = ComputeTwist(boneRot); + RemoveEulerAngleFromMatrix(boneRot, rot[1], 1); + rot[0] = EulerAngleFromMatrix(boneRot, 2); + break; + case IK_SWING|IK_YDOF: + rot[2] = ComputeTwist(boneRot); + RemoveEulerAngleFromMatrix(boneRot, rot[2], 1); + boneRot.GetXZRot().GetValue(rot); + break; + case IK_REVOLUTE: + boneRot.GetRot().GetValue(rot); + break; + } +} + +static bool target_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param) +{ + IK_Target* target = (IK_Target*)param; + // compute next target position + // get target matrix from constraint. + bConstraint* constraint = (bConstraint*)target->blenderConstraint; + float tarmat[4][4]; + + get_constraint_target_matrix(constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0); + + // rootmat contains the target pose in world coordinate + // if enforce is != 1.0, blend the target position with the end effector position + // if the armature was in rest position. This information is available in eeRest + if (constraint->enforce != 1.0f && target->eeBlend) { + // eeRest is relative to the reference frame of the IK root + // get this frame in world reference + float restmat[4][4]; + bPoseChannel* pchan = target->rootChannel; + if (pchan->parent) { + pchan = pchan->parent; + float chanmat[4][4]; + Mat4CpyMat4(chanmat, pchan->pose_mat); + VECCOPY(chanmat[3], pchan->pose_tail); + Mat4MulSerie(restmat, target->owner->obmat, chanmat, target->eeRest, NULL, NULL, NULL, NULL, NULL); + } + else { + Mat4MulMat4(restmat, target->eeRest, target->owner->obmat); + } + // blend the target + Mat4BlendMat4(tarmat, restmat, tarmat, constraint->enforce); + } + next.setValue(&tarmat[0][0]); + return true; +} + +static bool base_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param) +{ + IK_Scene* ikscene = (IK_Scene*)param; + // compute next armature base pose + // algorithm: + // ikscene->pchan[0] is the root channel of the tree + // if it has a parent, get the pose matrix from it and replace [3] by parent pchan->tail + // then multiply by the armature matrix to get ikscene->armature base position + bPoseChannel* pchan = ikscene->channels[0].pchan; + float rootmat[4][4]; + if (pchan->parent) { + pchan = pchan->parent; + float chanmat[4][4]; + Mat4CpyMat4(chanmat, pchan->pose_mat); + VECCOPY(chanmat[3], pchan->pose_tail); + // save the base as a frame too so that we can compute deformation + // after simulation + ikscene->baseFrame.setValue(&chanmat[0][0]); + Mat4MulMat4(rootmat, chanmat, ikscene->blArmature->obmat); + } + else { + Mat4CpyMat4(rootmat, ikscene->blArmature->obmat); + ikscene->baseFrame = iTaSC::F_identity; + } + next.setValue(&rootmat[0][0]); + // if there is a polar target (only during solving otherwise we don't have end efffector) + if (ikscene->polarConstraint && timestamp.update) { + // compute additional rotation of base frame so that armature follows the polar target + float imat[4][4]; // IK tree base inverse matrix + float polemat[4][4]; // polar target in IK tree base frame + float goalmat[4][4]; // target in IK tree base frame + float mat[4][4]; // temp matrix + bKinematicConstraint* poledata = (bKinematicConstraint*)ikscene->polarConstraint->data; + + Mat4Invert(imat, rootmat); + // polar constraint imply only one target + IK_Target *iktarget = ikscene->targets[0]; + // root channel from which we take the bone initial orientation + IK_Channel &rootchan = ikscene->channels[0]; + + // get polar target matrix in world space + get_constraint_target_matrix(ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0); + // convert to armature space + Mat4MulMat4(polemat, mat, imat); + // get the target in world space (was computed before as target object are defined before base object) + iktarget->target->getPose().getValue(mat[0]); + // convert to armature space + Mat4MulMat4(goalmat, mat, imat); + // take position of target, polar target, end effector, in armature space + KDL::Vector goalpos(goalmat[3]); + KDL::Vector polepos(polemat[3]); + KDL::Vector endpos = ikscene->armature->getPose(iktarget->ee).p; + // get root bone orientation + KDL::Frame rootframe; + ikscene->armature->getRelativeFrame(rootframe, rootchan.tail); + KDL::Vector rootx = rootframe.M.UnitX(); + KDL::Vector rootz = rootframe.M.UnitZ(); + // and compute root bone head + double q_rest[3], q[3], length; + const KDL::Joint* joint; + const KDL::Frame* tip; + ikscene->armature->getSegment(rootchan.tail, 3, joint, q_rest[0], q[0], tip); + length = (joint->getType() == KDL::Joint::TransY) ? q[0] : tip->p(1); + KDL::Vector rootpos = rootframe.p - length*rootframe.M.UnitY(); + + // compute main directions + KDL::Vector dir = KDL::Normalize(endpos - rootpos); + KDL::Vector poledir = KDL::Normalize(goalpos-rootpos); + // compute up directions + KDL::Vector poleup = KDL::Normalize(polepos-rootpos); + KDL::Vector up = rootx*KDL::cos(poledata->poleangle) + rootz*KDL::sin(poledata->poleangle); + // from which we build rotation matrix + KDL::Rotation endrot, polerot; + // for the armature, using the root bone orientation + KDL::Vector x = KDL::Normalize(dir*up); + endrot.UnitX(x); + endrot.UnitY(KDL::Normalize(x*dir)); + endrot.UnitZ(-dir); + // for the polar target + x = KDL::Normalize(poledir*poleup); + polerot.UnitX(x); + polerot.UnitY(KDL::Normalize(x*poledir)); + polerot.UnitZ(-poledir); + // the difference between the two is the rotation we want to apply + KDL::Rotation result(polerot*endrot.Inverse()); + // apply on base frame as this is an artificial additional rotation + next.M = next.M*result; + ikscene->baseFrame.M = ikscene->baseFrame.M*result; + } + return true; +} + +static bool copypose_callback(const iTaSC::Timestamp& timestamp, iTaSC::ConstraintValues* const _values, unsigned int _nvalues, void* _param) +{ + IK_Target* iktarget =(IK_Target*)_param; + bKinematicConstraint *condata = (bKinematicConstraint *)iktarget->blenderConstraint->data; + iTaSC::ConstraintValues* values = _values; + bItasc* ikparam = (bItasc*) iktarget->owner->pose->ikparam; + + // we need default parameters + if (!ikparam) + ikparam = &DefIKParam; + + if (iktarget->blenderConstraint->flag & CONSTRAINT_OFF) { + if (iktarget->controlType & iTaSC::CopyPose::CTL_POSITION) { + values->alpha = 0.0; + values->action = iTaSC::ACT_ALPHA; + values++; + } + if (iktarget->controlType & iTaSC::CopyPose::CTL_ROTATION) { + values->alpha = 0.0; + values->action = iTaSC::ACT_ALPHA; + values++; + } + } else { + if (iktarget->controlType & iTaSC::CopyPose::CTL_POSITION) { + // update error + values->alpha = condata->weight; + values->action = iTaSC::ACT_ALPHA|iTaSC::ACT_FEEDBACK; + values->feedback = (iktarget->simulation) ? ikparam->feedback : ANIM_FEEDBACK; + values++; + } + if (iktarget->controlType & iTaSC::CopyPose::CTL_ROTATION) { + // update error + values->alpha = condata->orientweight; + values->action = iTaSC::ACT_ALPHA|iTaSC::ACT_FEEDBACK; + values->feedback = (iktarget->simulation) ? ikparam->feedback : ANIM_FEEDBACK; + values++; + } + } + return true; +} + +static void copypose_error(const iTaSC::ConstraintValues* values, unsigned int nvalues, IK_Target* iktarget) +{ + iTaSC::ConstraintSingleValue* value; + double error; + int i; + + if (iktarget->controlType & iTaSC::CopyPose::CTL_POSITION) { + // update error + for (i=0, error=0.0, value=values->values; i<values->number; ++i, ++value) + error += KDL::sqr(value->y - value->yd); + iktarget->blenderConstraint->lin_error = (float)KDL::sqrt(error); + values++; + } + if (iktarget->controlType & iTaSC::CopyPose::CTL_ROTATION) { + // update error + for (i=0, error=0.0, value=values->values; i<values->number; ++i, ++value) + error += KDL::sqr(value->y - value->yd); + iktarget->blenderConstraint->rot_error = (float)KDL::sqrt(error); + values++; + } +} + +static bool distance_callback(const iTaSC::Timestamp& timestamp, iTaSC::ConstraintValues* const _values, unsigned int _nvalues, void* _param) +{ + IK_Target* iktarget =(IK_Target*)_param; + bKinematicConstraint *condata = (bKinematicConstraint *)iktarget->blenderConstraint->data; + iTaSC::ConstraintValues* values = _values; + bItasc* ikparam = (bItasc*) iktarget->owner->pose->ikparam; + // we need default parameters + if (!ikparam) + ikparam = &DefIKParam; + + // update weight according to mode + if (iktarget->blenderConstraint->flag & CONSTRAINT_OFF) { + values->alpha = 0.0; + } else { + switch (condata->mode) { + case LIMITDIST_INSIDE: + values->alpha = (values->values[0].y > condata->dist) ? condata->weight : 0.0; + break; + case LIMITDIST_OUTSIDE: + values->alpha = (values->values[0].y < condata->dist) ? condata->weight : 0.0; + break; + default: + values->alpha = condata->weight; + break; + } + if (!timestamp.substep) { + // only update value on first timestep + switch (condata->mode) { + case LIMITDIST_INSIDE: + values->values[0].yd = condata->dist*0.95; + break; + case LIMITDIST_OUTSIDE: + values->values[0].yd = condata->dist*1.05; + break; + default: + values->values[0].yd = condata->dist; + break; + } + values->values[0].action = iTaSC::ACT_VALUE|iTaSC::ACT_FEEDBACK; + values->feedback = (iktarget->simulation) ? ikparam->feedback : ANIM_FEEDBACK; + } + } + values->action |= iTaSC::ACT_ALPHA; + return true; +} + +static void distance_error(const iTaSC::ConstraintValues* values, unsigned int _nvalues, IK_Target* iktarget) +{ + iktarget->blenderConstraint->lin_error = (float)(values->values[0].y - values->values[0].yd); +} + +static bool joint_callback(const iTaSC::Timestamp& timestamp, iTaSC::ConstraintValues* const _values, unsigned int _nvalues, void* _param) +{ + IK_Channel* ikchan = (IK_Channel*)_param; + bItasc* ikparam = (bItasc*)ikchan->owner->pose->ikparam; + bPoseChannel* chan = ikchan->pchan; + int dof; + + // a channel can be splitted into multiple joints, so we get called multiple + // times for one channel (this callback is only for 1 joint in the armature) + // the IK_JointTarget structure is shared between multiple joint constraint + // and the target joint values is computed only once, remember this in jointValid + // Don't forget to reset it before each frame + if (!ikchan->jointValid) { + float rmat[3][3]; + + if (chan->rotmode > 0) { + /* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */ + EulOToMat3(chan->eul, chan->rotmode, rmat); + } + else if (chan->rotmode == ROT_MODE_AXISANGLE) { + /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ + AxisAngleToMat3(&chan->quat[1], chan->quat[0], rmat); + } + else { + /* quats are normalised before use to eliminate scaling issues */ + NormalQuat(chan->quat); + QuatToMat3(chan->quat, rmat); + } + KDL::Rotation jointRot( + rmat[0][0], rmat[1][0], rmat[2][0], + rmat[0][1], rmat[1][1], rmat[2][1], + rmat[0][2], rmat[1][2], rmat[2][2]); + GetJointRotation(jointRot, ikchan->jointType, ikchan->jointValue); + ikchan->jointValid = 1; + } + // determine which part of jointValue is used for this joint + // closely related to the way the joints are defined + switch (ikchan->jointType & ~IK_TRANSY) + { + case IK_XDOF: + case IK_YDOF: + case IK_ZDOF: + dof = 0; + break; + case IK_XDOF|IK_YDOF: + // X + Y + dof = (_values[0].id == iTaSC::Armature::ID_JOINT_RX) ? 0 : 1; + break; + case IK_SWING: + // XZ + dof = 0; + break; + case IK_YDOF|IK_ZDOF: + // Z + Y + dof = (_values[0].id == iTaSC::Armature::ID_JOINT_RZ) ? 0 : 1; + break; + case IK_SWING|IK_YDOF: + // XZ + Y + dof = (_values[0].id == iTaSC::Armature::ID_JOINT_RY) ? 2 : 0; + break; + case IK_REVOLUTE: + dof = 0; + break; + default: + dof = -1; + break; + } + if (dof >= 0) { + for (unsigned int i=0; i<_nvalues; i++, dof++) { + _values[i].values[0].yd = ikchan->jointValue[dof]; + _values[i].alpha = chan->ikrotweight; + _values[i].feedback = ikparam->feedback; + } + } + return true; +} + +// build array of joint corresponding to IK chain +static int convert_channels(IK_Scene *ikscene, PoseTree *tree) +{ + IK_Channel *ikchan; + bPoseChannel *pchan; + Bone *bone; + int a, flag, njoint; + + njoint = 0; + for(a=0, ikchan = ikscene->channels; a<ikscene->numchan; ++a, ++ikchan) { + pchan= tree->pchan[a]; + bone= pchan->bone; + ikchan->pchan = pchan; + ikchan->parent = (a>0) ? tree->parent[a] : -1; + ikchan->owner = ikscene->blArmature; + + /* set DoF flag */ + flag = 0; + if(!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP) && + (!(pchan->ikflag & BONE_IK_XLIMIT) || pchan->limitmin[0]<0.f || pchan->limitmax[0]>0.f)) + flag |= IK_XDOF; + if(!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP) && + (!(pchan->ikflag & BONE_IK_YLIMIT) || pchan->limitmin[1]<0.f || pchan->limitmax[1]>0.f)) + flag |= IK_YDOF; + if(!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP) && + (!(pchan->ikflag & BONE_IK_ZLIMIT) || pchan->limitmin[2]<0.f || pchan->limitmax[2]>0.f)) + flag |= IK_ZDOF; + + if(tree->stretch && (pchan->ikstretch > 0.0)) { + flag |= IK_TRANSY; + } + /* + Logic to create the segments: + RX,RY,RZ = rotational joints with no length + RY(tip) = rotational joints with a fixed length arm = (0,length,0) + TY = translational joint on Y axis + F(pos) = fixed joint with an arm at position pos + Conversion rule of the above flags: + - ==> F(tip) + X ==> RX(tip) + Y ==> RY(tip) + Z ==> RZ(tip) + XY ==> RX+RY(tip) + XZ ==> RX+RZ(tip) + YZ ==> RZ+RY(tip) + XYZ ==> full spherical unless there are limits, in which case RX+RZ+RY(tip) + In case of stretch, tip=(0,0,0) and there is an additional TY joint + The frame at last of these joints represents the tail of the bone. + The head is computed by a reverse translation on Y axis of the bone length + or in case of TY joint, by the frame at previous joint. + In case of separation of bones, there is an additional F(head) joint + + Computing rest pose and length is complicated: the solver works in world space + Here is the logic: + rest position is computed only from bone->bone_mat. + bone length is computed from bone->length multiplied by the scaling factor of + the armature. Non-uniform scaling will give bad result! + + */ + switch (flag & (IK_XDOF|IK_YDOF|IK_ZDOF)) + { + default: + ikchan->jointType = 0; + ikchan->ndof = 0; + break; + case IK_XDOF: + // RX only, get the X rotation + ikchan->jointType = IK_XDOF; + ikchan->ndof = 1; + break; + case IK_YDOF: + // RY only, get the Y rotation + ikchan->jointType = IK_YDOF; + ikchan->ndof = 1; + break; + case IK_ZDOF: + // RZ only, get the Zz rotation + ikchan->jointType = IK_ZDOF; + ikchan->ndof = 1; + break; + case IK_XDOF|IK_YDOF: + ikchan->jointType = IK_XDOF|IK_YDOF; + ikchan->ndof = 2; + break; + case IK_XDOF|IK_ZDOF: + // RX+RZ + ikchan->jointType = IK_SWING; + ikchan->ndof = 2; + break; + case IK_YDOF|IK_ZDOF: + // RZ+RY + ikchan->jointType = IK_ZDOF|IK_YDOF; + ikchan->ndof = 2; + break; + case IK_XDOF|IK_YDOF|IK_ZDOF: + // spherical joint + if (pchan->ikflag & (BONE_IK_XLIMIT|BONE_IK_YLIMIT|BONE_IK_ZLIMIT)) + // decompose in a Swing+RotY joint + ikchan->jointType = IK_SWING|IK_YDOF; + else + ikchan->jointType = IK_REVOLUTE; + ikchan->ndof = 3; + break; + } + if (flag & IK_TRANSY) { + ikchan->jointType |= IK_TRANSY; + ikchan->ndof++; + } + njoint += ikchan->ndof; + } + // njoint is the joint coordinate, create the Joint Array + ikscene->jointArray.resize(njoint); + ikscene->numjoint = njoint; + return njoint; +} + +// compute array of joint value corresponding to current pose +static void convert_pose(IK_Scene *ikscene) +{ + KDL::Rotation boneRot; + bPoseChannel *pchan; + IK_Channel *ikchan; + Bone *bone; + float rmat[4][4]; // rest pose of bone with parent taken into account + float bmat[4][4]; // difference + float scale; + double *rot; + int a, joint; + + // assume uniform scaling and take Y scale as general scale for the armature + scale = VecLength(ikscene->blArmature->obmat[1]); + rot = &ikscene->jointArray(0); + for(joint=a=0, ikchan = ikscene->channels; a<ikscene->numchan && joint<ikscene->numjoint; ++a, ++ikchan) { + pchan= ikchan->pchan; + bone= pchan->bone; + + if (pchan->parent) { + Mat4One(bmat); + Mat4MulMat43(bmat, pchan->parent->pose_mat, bone->bone_mat); + } else { + Mat4CpyMat4(bmat, bone->arm_mat); + } + Mat4Invert(rmat, bmat); + Mat4MulMat4(bmat, pchan->pose_mat, rmat); + Mat4Ortho(bmat); + boneRot.setValue(bmat[0]); + GetJointRotation(boneRot, ikchan->jointType, rot); + if (ikchan->jointType & IK_TRANSY) { + // compute actual length + rot[ikchan->ndof-1] = VecLenf(pchan->pose_tail, pchan->pose_head) * scale; + } + rot += ikchan->ndof; + joint += ikchan->ndof; + } +} + +// compute array of joint value corresponding to current pose +static void rest_pose(IK_Scene *ikscene) +{ + bPoseChannel *pchan; + IK_Channel *ikchan; + Bone *bone; + float scale; + double *rot; + int a, joint; + + // assume uniform scaling and take Y scale as general scale for the armature + scale = VecLength(ikscene->blArmature->obmat[1]); + // rest pose is 0 + KDL::SetToZero(ikscene->jointArray); + // except for transY joints + rot = &ikscene->jointArray(0); + for(joint=a=0, ikchan = ikscene->channels; a<ikscene->numchan && joint<ikscene->numjoint; ++a, ++ikchan) { + pchan= ikchan->pchan; + bone= pchan->bone; + + if (ikchan->jointType & IK_TRANSY) + rot[ikchan->ndof-1] = bone->length*scale; + rot += ikchan->ndof; + joint += ikchan->ndof; + } +} + +static IK_Scene* convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan) +{ + PoseTree *tree = (PoseTree*)pchan->iktree.first; + PoseTarget *target; + bKinematicConstraint *condata; + bConstraint *polarcon; + bItasc *ikparam; + iTaSC::Armature* arm; + iTaSC::Scene* scene; + IK_Scene* ikscene; + IK_Channel* ikchan; + KDL::Frame initPose; + KDL::Rotation boneRot; + Bone *bone; + int a, numtarget; + unsigned int t; + float length; + bool ret = true, ingame; + double *rot; + + if (tree->totchannel == 0) + return NULL; + + ikscene = new IK_Scene; + arm = new iTaSC::Armature(); + scene = new iTaSC::Scene(); + ikscene->channels = new IK_Channel[tree->totchannel]; + ikscene->numchan = tree->totchannel; + ikscene->armature = arm; + ikscene->scene = scene; + ikparam = (bItasc*)ob->pose->ikparam; + ingame = (ob->pose->flag & POSE_GAME_ENGINE); + if (!ikparam) { + // you must have our own copy + ikparam = &DefIKParam; + } else if (ingame) { + // tweak the param when in game to have efficient stepping + // using fixed substep is not effecient since frames in the GE are often + // shorter than in animation => move to auto step automatically and set + // the target substep duration via min/max + if (!(ikparam->flag & ITASC_AUTO_STEP)) { + float timestep = blscene->r.frs_sec_base/blscene->r.frs_sec; + if (ikparam->numstep > 0) + timestep /= ikparam->numstep; + // with equal min and max, the algorythm will take this step and the indicative substep most of the time + ikparam->minstep = ikparam->maxstep = timestep; + ikparam->flag |= ITASC_AUTO_STEP; + } + } + if ((ikparam->flag & ITASC_SIMULATION) && !ingame) + // no cache in animation mode + ikscene->cache = new iTaSC::Cache(); + + switch (ikparam->solver) { + case ITASC_SOLVER_SDLS: + ikscene->solver = new iTaSC::WSDLSSolver(); + break; + case ITASC_SOLVER_DLS: + ikscene->solver = new iTaSC::WDLSSolver(); + break; + default: + delete ikscene; + return NULL; + } + ikscene->blArmature = ob; + + std::string joint; + std::string root("root"); + std::string parent; + std::vector<double> weights; + double weight[3]; + // assume uniform scaling and take Y scale as general scale for the armature + float scale = VecLength(ob->obmat[1]); + // build the array of joints corresponding to the IK chain + convert_channels(ikscene, tree); + if (ingame) { + // in the GE, set the initial joint angle to match the current pose + // this will update the jointArray in ikscene + convert_pose(ikscene); + } else { + // in Blender, the rest pose is always 0 for joints + rest_pose(ikscene); + } + rot = &ikscene->jointArray(0); + for(a=0, ikchan = ikscene->channels; a<tree->totchannel; ++a, ++ikchan) { + pchan= ikchan->pchan; + bone= pchan->bone; + + KDL::Frame tip(iTaSC::F_identity); + Vector3 *fl = bone->bone_mat; + KDL::Frame head(KDL::Rotation( + fl[0][0], fl[1][0], fl[2][0], + fl[0][1], fl[1][1], fl[2][1], + fl[0][2], fl[1][2], fl[2][2]), + KDL::Vector(bone->head[0], bone->head[1], bone->head[2])*scale); + + // rest pose length of the bone taking scaling into account + length= bone->length*scale; + parent = (a > 0) ? ikscene->channels[tree->parent[a]].tail : root; + // first the fixed segment to the bone head + if (head.p.Norm() > KDL::epsilon || head.M.GetRot().Norm() > KDL::epsilon) { + joint = bone->name; + joint += ":H"; + ret = arm->addSegment(joint, parent, KDL::Joint::None, 0.0, head); + parent = joint; + } + if (!(ikchan->jointType & IK_TRANSY)) { + // fixed length, put it in tip + tip.p[1] = length; + } + joint = bone->name; + weight[0] = (1.0-pchan->stiffness[0]); + weight[1] = (1.0-pchan->stiffness[1]); + weight[2] = (1.0-pchan->stiffness[2]); + switch (ikchan->jointType & ~IK_TRANSY) + { + case 0: + // fixed bone + if (!(ikchan->jointType & IK_TRANSY)) { + joint += ":F"; + ret = arm->addSegment(joint, parent, KDL::Joint::None, 0.0, tip); + } + break; + case IK_XDOF: + // RX only, get the X rotation + joint += ":RX"; + ret = arm->addSegment(joint, parent, KDL::Joint::RotX, rot[0], tip); + weights.push_back(weight[0]); + break; + case IK_YDOF: + // RY only, get the Y rotation + joint += ":RY"; + ret = arm->addSegment(joint, parent, KDL::Joint::RotY, rot[0], tip); + weights.push_back(weight[1]); + break; + case IK_ZDOF: + // RZ only, get the Zz rotation + joint += ":RZ"; + ret = arm->addSegment(joint, parent, KDL::Joint::RotZ, rot[0], tip); + weights.push_back(weight[2]); + break; + case IK_XDOF|IK_YDOF: + joint += ":RX"; + ret = arm->addSegment(joint, parent, KDL::Joint::RotX, rot[0]); + weights.push_back(weight[0]); + if (ret) { + parent = joint; + joint = bone->name; + joint += ":RY"; + ret = arm->addSegment(joint, parent, KDL::Joint::RotY, rot[1], tip); + weights.push_back(weight[1]); + } + break; + case IK_SWING: + joint += ":SW"; + ret = arm->addSegment(joint, parent, KDL::Joint::Swing, rot[0], tip); + weights.push_back(weight[0]); + weights.push_back(weight[2]); + break; + case IK_YDOF|IK_ZDOF: + // RZ+RY + joint += ":RZ"; + ret = arm->addSegment(joint, parent, KDL::Joint::RotZ, rot[0]); + weights.push_back(weight[2]); + if (ret) { + parent = joint; + joint = bone->name; + joint += ":RY"; + ret = arm->addSegment(joint, parent, KDL::Joint::RotY, rot[1], tip); + weights.push_back(weight[1]); + } + break; + case IK_SWING|IK_YDOF: + // decompose in a Swing+RotY joint + joint += ":SW"; + ret = arm->addSegment(joint, parent, KDL::Joint::Swing, rot[0]); + weights.push_back(weight[0]); + weights.push_back(weight[2]); + if (ret) { + parent = joint; + joint = bone->name; + joint += ":RY"; + ret = arm->addSegment(joint, parent, KDL::Joint::RotY, rot[2], tip); + weights.push_back(weight[1]); + } + break; + case IK_REVOLUTE: + joint += ":SJ"; + ret = arm->addSegment(joint, parent, KDL::Joint::Sphere, rot[0], tip); + weights.push_back(weight[0]); + weights.push_back(weight[1]); + weights.push_back(weight[2]); + break; + } + if (ret && (ikchan->jointType & IK_TRANSY)) { + parent = joint; + joint = bone->name; + joint += ":TY"; + ret = arm->addSegment(joint, parent, KDL::Joint::TransY, rot[ikchan->ndof-1]); + float ikstretch = pchan->ikstretch*pchan->ikstretch; + weight[1] = (1.0-MIN2(1.0-ikstretch, 0.99)); + weights.push_back(weight[1]); + } + if (!ret) + // error making the armature?? + break; + // joint points to the segment that correspond to the bone per say + ikchan->tail = joint; + ikchan->head = parent; + // in case of error + ret = false; + if ((ikchan->jointType & IK_XDOF) && (pchan->ikflag & (BONE_IK_XLIMIT|BONE_IK_ROTCTL))) { + joint = bone->name; + joint += ":RX"; + if (pchan->ikflag & BONE_IK_XLIMIT) { + if (arm->addLimitConstraint(joint, 0, pchan->limitmin[0], pchan->limitmax[0]) < 0) + break; + } + if (pchan->ikflag & BONE_IK_ROTCTL) { + if (arm->addConstraint(joint, joint_callback, ikchan, false, false) < 0) + break; + } + } + if ((ikchan->jointType & IK_YDOF) && (pchan->ikflag & (BONE_IK_YLIMIT|BONE_IK_ROTCTL))) { + joint = bone->name; + joint += ":RY"; + if (pchan->ikflag & BONE_IK_YLIMIT) { + if (arm->addLimitConstraint(joint, 0, pchan->limitmin[1], pchan->limitmax[1]) < 0) + break; + } + if (pchan->ikflag & BONE_IK_ROTCTL) { + if (arm->addConstraint(joint, joint_callback, ikchan, false, false) < 0) + break; + } + } + if ((ikchan->jointType & IK_ZDOF) && (pchan->ikflag & (BONE_IK_ZLIMIT|BONE_IK_ROTCTL))) { + joint = bone->name; + joint += ":RZ"; + if (pchan->ikflag & BONE_IK_ZLIMIT) { + if (arm->addLimitConstraint(joint, 0, pchan->limitmin[2], pchan->limitmax[2]) < 0) + break; + } + if (pchan->ikflag & BONE_IK_ROTCTL) { + if (arm->addConstraint(joint, joint_callback, ikchan, false, false) < 0) + break; + } + } + if ((ikchan->jointType & IK_SWING) && (pchan->ikflag & (BONE_IK_XLIMIT|BONE_IK_ZLIMIT|BONE_IK_ROTCTL))) { + joint = bone->name; + joint += ":SW"; + if (pchan->ikflag & BONE_IK_XLIMIT) { + if (arm->addLimitConstraint(joint, 0, pchan->limitmin[0], pchan->limitmax[0]) < 0) + break; + } + if (pchan->ikflag & BONE_IK_ZLIMIT) { + if (arm->addLimitConstraint(joint, 1, pchan->limitmin[2], pchan->limitmax[2]) < 0) + break; + } + if (pchan->ikflag & BONE_IK_ROTCTL) { + if (arm->addConstraint(joint, joint_callback, ikchan, false, false) < 0) + break; + } + } + if ((ikchan->jointType & IK_REVOLUTE) && (pchan->ikflag & BONE_IK_ROTCTL)) { + joint = bone->name; + joint += ":SJ"; + if (arm->addConstraint(joint, joint_callback, ikchan, false, false) < 0) + break; + } + // no error, so restore + ret = true; + rot += ikchan->ndof; + } + if (!ret) { + delete ikscene; + return NULL; + } + // for each target, we need to add an end effector in the armature + for (numtarget=0, polarcon=NULL, ret = true, target=(PoseTarget*)tree->targets.first; target; target=(PoseTarget*)target->next) { + condata= (bKinematicConstraint*)target->con->data; + pchan = tree->pchan[target->tip]; + + if (is_cartesian_constraint(target->con)) { + // add the end effector + IK_Target* iktarget = new IK_Target(); + ikscene->targets.push_back(iktarget); + iktarget->ee = arm->addEndEffector(ikscene->channels[target->tip].tail); + if (iktarget->ee == -1) { + ret = false; + break; + } + // initialize all the fields that we can set at this time + iktarget->blenderConstraint = target->con; + iktarget->channel = target->tip; + iktarget->simulation = (ikparam->flag & ITASC_SIMULATION); + iktarget->rootChannel = ikscene->channels[0].pchan; + iktarget->owner = ob; + iktarget->targetName = pchan->bone->name; + iktarget->targetName += ":T:"; + iktarget->targetName += target->con->name; + iktarget->constraintName = pchan->bone->name; + iktarget->constraintName += ":C:"; + iktarget->constraintName += target->con->name; + numtarget++; + if (condata->poletar) + // this constraint has a polar target + polarcon = target->con; + } + } + // deal with polar target if any + if (numtarget == 1 && polarcon) { + ikscene->polarConstraint = polarcon; + } + // we can now add the armature + // the armature is based on a moving frame. + // initialize with the correct position in case there is no cache + base_callback(iTaSC::Timestamp(), iTaSC::F_identity, initPose, ikscene); + ikscene->base = new iTaSC::MovingFrame(initPose); + ikscene->base->setCallback(base_callback, ikscene); + std::string armname; + armname = ob->id.name; + armname += ":B"; + ret = scene->addObject(armname, ikscene->base); + armname = ob->id.name; + armname += ":AR"; + if (ret) + ret = scene->addObject(armname, ikscene->armature, ikscene->base); + if (!ret) { + delete ikscene; + return NULL; + } + // set the weight + e_matrix& Wq = arm->getWq(); + assert(Wq.cols() == (int)weights.size()); + for (int q=0; q<Wq.cols(); q++) + Wq(q,q)=weights[q]; + // get the inverse rest pose frame of the base to compute relative rest pose of end effectors + // this is needed to handle the enforce parameter + // ikscene->pchan[0] is the root channel of the tree + // if it has no parent, then it's just the identify Frame + float invBaseFrame[4][4]; + pchan = ikscene->channels[0].pchan; + if (pchan->parent) { + // it has a parent, get the pose matrix from it + float baseFrame[4][4]; + pchan = pchan->parent; + Mat4CpyMat4(baseFrame, pchan->bone->arm_mat); + // move to the tail and scale to get rest pose of armature base + VecCopyf(baseFrame[3], pchan->bone->arm_tail); + Mat4Invert(invBaseFrame, baseFrame); + } else { + Mat4One(invBaseFrame); + } + // finally add the constraint + for (t=0; t<ikscene->targets.size(); t++) { + IK_Target* iktarget = ikscene->targets[t]; + condata= (bKinematicConstraint*)iktarget->blenderConstraint->data; + pchan = tree->pchan[iktarget->channel]; + unsigned int controltype, bonecnt; + double bonelen; + float mat[4][4]; + + // add the end effector + // estimate the average bone length, used to clamp feedback error + for (bonecnt=0, bonelen=0.f, a=iktarget->channel; a>=0; a=tree->parent[a], bonecnt++) + bonelen += scale*tree->pchan[a]->bone->length; + bonelen /= bonecnt; + + // store the rest pose of the end effector to compute enforce target + Mat4CpyMat4(mat, pchan->bone->arm_mat); + VecCopyf(mat[3], pchan->bone->arm_tail); + // get the rest pose relative to the armature base + Mat4MulMat4(iktarget->eeRest, mat, invBaseFrame); + iktarget->eeBlend = (!ikscene->polarConstraint && condata->type==CONSTRAINT_IK_COPYPOSE) ? true : false; + // use target_callback to make sure the initPose includes enforce coefficient + target_callback(iTaSC::Timestamp(), iTaSC::F_identity, initPose, iktarget); + iktarget->target = new iTaSC::MovingFrame(initPose); + iktarget->target->setCallback(target_callback, iktarget); + ret = scene->addObject(iktarget->targetName, iktarget->target); + if (!ret) + break; + + switch (condata->type) { + case CONSTRAINT_IK_COPYPOSE: + controltype = 0; + if ((condata->flag & CONSTRAINT_IK_ROT) && (condata->orientweight != 0.0)) + controltype |= iTaSC::CopyPose::CTL_ROTATION; + if ((condata->weight != 0.0)) + controltype |= iTaSC::CopyPose::CTL_POSITION; + if (controltype) { + iktarget->constraint = new iTaSC::CopyPose(controltype, controltype, bonelen); + // set the gain + if (controltype & iTaSC::CopyPose::CTL_POSITION) + iktarget->constraint->setControlParameter(iTaSC::CopyPose::ID_POSITION, iTaSC::ACT_ALPHA, condata->weight); + if (controltype & iTaSC::CopyPose::CTL_ROTATION) + iktarget->constraint->setControlParameter(iTaSC::CopyPose::ID_ROTATION, iTaSC::ACT_ALPHA, condata->orientweight); + iktarget->constraint->registerCallback(copypose_callback, iktarget); + iktarget->errorCallback = copypose_error; + iktarget->controlType = controltype; + // add the constraint + ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, armname, iktarget->targetName, ikscene->channels[iktarget->channel].tail); + } + break; + case CONSTRAINT_IK_DISTANCE: + iktarget->constraint = new iTaSC::Distance(bonelen); + iktarget->constraint->setControlParameter(iTaSC::Distance::ID_DISTANCE, iTaSC::ACT_VALUE, condata->dist); + iktarget->constraint->registerCallback(distance_callback, iktarget); + iktarget->errorCallback = distance_error; + // we can update the weight on each substep + iktarget->constraint->substep(true); + // add the constraint + ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, armname, iktarget->targetName, ikscene->channels[iktarget->channel].tail); + break; + } + if (!ret) + break; + } + if (!ret || + !scene->addCache(ikscene->cache) || + !scene->addSolver(ikscene->solver) || + !scene->initialize()) { + delete ikscene; + ikscene = NULL; + } + return ikscene; +} + +static void create_scene(Scene *scene, Object *ob) +{ + bPoseChannel *pchan; + + // create the IK scene + for(pchan= (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan= (bPoseChannel *)pchan->next) { + // by construction there is only one tree + PoseTree *tree = (PoseTree*)pchan->iktree.first; + if (tree) { + IK_Data* ikdata = get_ikdata(ob->pose); + // convert tree in iTaSC::Scene + IK_Scene* ikscene = convert_tree(scene, ob, pchan); + if (ikscene) { + ikscene->next = ikdata->first; + ikdata->first = ikscene; + } + // delete the trees once we are done + while(tree) { + BLI_remlink(&pchan->iktree, tree); + BLI_freelistN(&tree->targets); + if(tree->pchan) MEM_freeN(tree->pchan); + if(tree->parent) MEM_freeN(tree->parent); + if(tree->basis_change) MEM_freeN(tree->basis_change); + MEM_freeN(tree); + tree = (PoseTree*)pchan->iktree.first; + } + } + } +} + +static void init_scene(Object *ob) +{ + if (ob->pose->ikdata) { + for(IK_Scene* scene = ((IK_Data*)ob->pose->ikdata)->first; + scene != NULL; + scene = scene->next) { + scene->channels[0].pchan->flag |= POSE_IKTREE; + } + } +} + +static void execute_scene(Scene* blscene, IK_Scene* ikscene, bItasc* ikparam, float ctime, float frtime) +{ + int i; + IK_Channel* ikchan; + if (ikparam->flag & ITASC_SIMULATION) { + for (i=0, ikchan=ikscene->channels; i<ikscene->numchan; i++, ++ikchan) { + // In simulation mode we don't allow external contraint to change our bones, mark the channel done + // also tell Blender that this channel is part of IK tree (cleared on each where_is_pose() + ikchan->pchan->flag |= (POSE_DONE|POSE_CHAIN); + ikchan->jointValid = 0; + } + } else { + // in animation mode, we must get the bone position from action and constraints + for(i=0, ikchan=ikscene->channels; i<ikscene->numchan; i++, ++ikchan) { + if (!(ikchan->pchan->flag & POSE_DONE)) + where_is_pose_bone(blscene, ikscene->blArmature, ikchan->pchan, ctime); + // tell blender that this channel was controlled by IK, it's cleared on each where_is_pose() + ikchan->pchan->flag |= (POSE_DONE|POSE_CHAIN); + ikchan->jointValid = 0; + } + } + // only run execute the scene if at least one of our target is enabled + for (i=ikscene->targets.size(); i > 0; --i) { + IK_Target* iktarget = ikscene->targets[i-1]; + if (!(iktarget->blenderConstraint->flag & CONSTRAINT_OFF)) + break; + } + if (i == 0 && ikscene->armature->getNrOfConstraints() == 0) + // all constraint disabled + return; + + // compute timestep + double timestamp = ctime * frtime + 2147483.648; + double timestep = frtime; + bool reiterate = (ikparam->flag & ITASC_REITERATION) ? true : false; + int numstep = (ikparam->flag & ITASC_AUTO_STEP) ? 0 : ikparam->numstep; + bool simulation = true; + + if (ikparam->flag & ITASC_SIMULATION) { + ikscene->solver->setParam(iTaSC::Solver::DLS_QMAX, ikparam->maxvel); + } + else { + // in animation mode we start from the pose after action and constraint + convert_pose(ikscene); + ikscene->armature->setJointArray(ikscene->jointArray); + // and we don't handle velocity + reiterate = true; + simulation = false; + // time is virtual, so take fixed value for velocity parameters (see itasc_update_param) + // and choose 1s timestep to allow having velocity parameters in radiant + timestep = 1.0; + // use auto setup to let the solver test the variation of the joints + numstep = 0; + } + + if (ikscene->cache && !reiterate && simulation) { + iTaSC::CacheTS sts, cts; + sts = cts = (iTaSC::CacheTS)(timestamp*1000.0+0.5); + if (ikscene->cache->getPreviousCacheItem(ikscene->armature, 0, &cts) == NULL || cts == 0) { + // the cache is empty before this time, reiterate + if (ikparam->flag & ITASC_INITIAL_REITERATION) + reiterate = true; + } else { + // can take the cache as a start point. + sts -= cts; + timestep = sts/1000.0; + } + } + // don't cache if we are reiterating because we don't want to distroy the cache unnecessarily + ikscene->scene->update(timestamp, timestep, numstep, false, !reiterate, simulation); + if (reiterate) { + // how many times do we reiterate? + for (i=0; i<ikparam->numiter; i++) { + if (ikscene->armature->getMaxJointChange() < ikparam->precision || + ikscene->armature->getMaxEndEffectorChange() < ikparam->precision) + break; + ikscene->scene->update(timestamp, timestep, numstep, true, false, simulation); + } + if (simulation) { + // one more fake iteration to cache + ikscene->scene->update(timestamp, 0.0, 1, true, true, true); + } + } + // compute constraint error + for (i=ikscene->targets.size(); i > 0; --i) { + IK_Target* iktarget = ikscene->targets[i-1]; + if (!(iktarget->blenderConstraint->flag & CONSTRAINT_OFF)) { + unsigned int nvalues; + const iTaSC::ConstraintValues* values; + values = iktarget->constraint->getControlParameters(&nvalues); + iktarget->errorCallback(values, nvalues, iktarget); + } + } + // Apply result to bone: + // walk the ikscene->channels + // for each, get the Frame of the joint corresponding to the bone relative to its parent + // combine the parent and the joint frame to get the frame relative to armature + // a backward translation of the bone length gives the head + // if TY, compute the scale as the ratio of the joint length with rest pose length + iTaSC::Armature* arm = ikscene->armature; + KDL::Frame frame; + double q_rest[3], q[3]; + const KDL::Joint* joint; + const KDL::Frame* tip; + bPoseChannel* pchan; + float scale; + float length; + float yaxis[3]; + for (i=0, ikchan=ikscene->channels; i<ikscene->numchan; ++i, ++ikchan) { + if (i == 0) { + if (!arm->getRelativeFrame(frame, ikchan->tail)) + break; + // this frame is relative to base, make it relative to object + ikchan->frame = ikscene->baseFrame * frame; + } + else { + if (!arm->getRelativeFrame(frame, ikchan->tail, ikscene->channels[ikchan->parent].tail)) + break; + // combine with parent frame to get frame relative to object + ikchan->frame = ikscene->channels[ikchan->parent].frame * frame; + } + // ikchan->frame is the tail frame relative to object + // get bone length + if (!arm->getSegment(ikchan->tail, 3, joint, q_rest[0], q[0], tip)) + break; + if (joint->getType() == KDL::Joint::TransY) { + // stretch bones have a TY joint, compute the scale + scale = (float)(q[0]/q_rest[0]); + // the length is the joint itself + length = (float)q[0]; + } + else { + scale = 1.0f; + // for fixed bone, the length is in the tip (always along Y axis) + length = tip->p(1); + } + // ready to compute the pose mat + pchan = ikchan->pchan; + // tail mat + ikchan->frame.getValue(&pchan->pose_mat[0][0]); + VECCOPY(pchan->pose_tail, pchan->pose_mat[3]); + // shift to head + VECCOPY(yaxis, pchan->pose_mat[1]); + VecMulf(yaxis, length); + VecSubf(pchan->pose_mat[3], pchan->pose_mat[3], yaxis); + VECCOPY(pchan->pose_head, pchan->pose_mat[3]); + // add scale + VecMulf(pchan->pose_mat[0], scale); + VecMulf(pchan->pose_mat[1], scale); + VecMulf(pchan->pose_mat[2], scale); + } + if (i<ikscene->numchan) { + // big problem + ; + } +} + +//--------------------------------------------------- +// plugin interface +// +void itasc_initialize_tree(struct Scene *scene, Object *ob, float ctime) +{ + bPoseChannel *pchan; + int count = 0; + + if (ob->pose->ikdata != NULL && !(ob->pose->flag & POSE_WAS_REBUILT)) { + init_scene(ob); + return; + } + // first remove old scene + itasc_clear_data(ob->pose); + // we should handle all the constraint and mark them all disabled + // for blender but we'll start with the IK constraint alone + for(pchan= (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan= (bPoseChannel *)pchan->next) { + if(pchan->constflag & PCHAN_HAS_IK) + count += initialize_scene(ob, pchan); + } + // if at least one tree, create the scenes from the PoseTree stored in the channels + if (count) + create_scene(scene, ob); + itasc_update_param(ob->pose); + // make sure we don't rebuilt until the user changes something important + ob->pose->flag &= ~POSE_WAS_REBUILT; +} + +void itasc_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime) +{ + if (ob->pose->ikdata) { + IK_Data* ikdata = (IK_Data*)ob->pose->ikdata; + bItasc* ikparam = (bItasc*) ob->pose->ikparam; + // we need default parameters + if (!ikparam) ikparam = &DefIKParam; + + for (IK_Scene* ikscene = ikdata->first; ikscene; ikscene = ikscene->next) { + if (ikscene->channels[0].pchan == pchan) { + float timestep = scene->r.frs_sec_base/scene->r.frs_sec; + if (ob->pose->flag & POSE_GAME_ENGINE) { + timestep = ob->pose->ctime; + // limit the timestep to avoid excessive number of iteration + if (timestep > 0.2f) + timestep = 0.2f; + } + execute_scene(scene, ikscene, ikparam, ctime, timestep); + break; + } + } + } +} + +void itasc_release_tree(struct Scene *scene, struct Object *ob, float ctime) +{ + // not used for iTaSC +} + +void itasc_clear_data(struct bPose *pose) +{ + if (pose->ikdata) { + IK_Data* ikdata = (IK_Data*)pose->ikdata; + for (IK_Scene* scene = ikdata->first; scene; scene = ikdata->first) { + ikdata->first = scene->next; + delete scene; + } + MEM_freeN(ikdata); + pose->ikdata = NULL; + } +} + +void itasc_clear_cache(struct bPose *pose) +{ + if (pose->ikdata) { + IK_Data* ikdata = (IK_Data*)pose->ikdata; + for (IK_Scene* scene = ikdata->first; scene; scene = scene->next) { + if (scene->cache) + // clear all cache but leaving the timestamp 0 (=rest pose) + scene->cache->clearCacheFrom(NULL, 1); + } + } +} + +void itasc_update_param(struct bPose *pose) +{ + if (pose->ikdata && pose->ikparam) { + IK_Data* ikdata = (IK_Data*)pose->ikdata; + bItasc* ikparam = (bItasc*)pose->ikparam; + for (IK_Scene* ikscene = ikdata->first; ikscene; ikscene = ikscene->next) { + double armlength = ikscene->armature->getArmLength(); + ikscene->solver->setParam(iTaSC::Solver::DLS_LAMBDA_MAX, ikparam->dampmax*armlength); + ikscene->solver->setParam(iTaSC::Solver::DLS_EPSILON, ikparam->dampeps*armlength); + if (ikparam->flag & ITASC_SIMULATION) { + ikscene->scene->setParam(iTaSC::Scene::MIN_TIMESTEP, ikparam->minstep); + ikscene->scene->setParam(iTaSC::Scene::MAX_TIMESTEP, ikparam->maxstep); + ikscene->solver->setParam(iTaSC::Solver::DLS_QMAX, ikparam->maxvel); + ikscene->armature->setControlParameter(CONSTRAINT_ID_ALL, iTaSC::Armature::ID_JOINT, iTaSC::ACT_FEEDBACK, ikparam->feedback); + } else { + // in animation mode timestep is 1s by convention => + // qmax becomes radiant and feedback becomes fraction of error gap corrected in one iteration + ikscene->scene->setParam(iTaSC::Scene::MIN_TIMESTEP, 1.0); + ikscene->scene->setParam(iTaSC::Scene::MAX_TIMESTEP, 1.0); + ikscene->solver->setParam(iTaSC::Solver::DLS_QMAX, 0.52); + ikscene->armature->setControlParameter(CONSTRAINT_ID_ALL, iTaSC::Armature::ID_JOINT, iTaSC::ACT_FEEDBACK, 0.8); + } + } + } +} + +void itasc_test_constraint(struct Object *ob, struct bConstraint *cons) +{ + struct bKinematicConstraint *data = (struct bKinematicConstraint *)cons->data; + + /* only for IK constraint */ + if (cons->type != CONSTRAINT_TYPE_KINEMATIC || data == NULL) + return; + + switch (data->type) { + case CONSTRAINT_IK_COPYPOSE: + case CONSTRAINT_IK_DISTANCE: + /* cartesian space constraint */ + break; + } +} + diff --git a/source/blender/ikplugin/intern/itasc_plugin.h b/source/blender/ikplugin/intern/itasc_plugin.h new file mode 100644 index 00000000000..25e48965a52 --- /dev/null +++ b/source/blender/ikplugin/intern/itasc_plugin.h @@ -0,0 +1,52 @@ +/** + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Original author: Benoit Bolsee + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef ITASC_PLUGIN_H +#define ITASC_PLUGIN_H + +#include "ikplugin_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void itasc_initialize_tree(struct Scene *scene, struct Object *ob, float ctime); +void itasc_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime); +void itasc_release_tree(struct Scene *scene, struct Object *ob, float ctime); +void itasc_clear_data(struct bPose *pose); +void itasc_clear_cache(struct bPose *pose); +void itasc_update_param(struct bPose *pose); +void itasc_test_constraint(struct Object *ob, struct bConstraint *cons); + +#ifdef __cplusplus +} +#endif + +#endif // ITASC_PLUGIN_H + diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 6e1a176a5d2..e84a9302bbf 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -190,7 +190,11 @@ void IMB_rect_from_float(struct ImBuf *ibuf) to = (unsigned char *) ibuf->rect; } - if (profile == IB_PROFILE_SRGB && (channels == 3 || channels == 4)) { + if(channels==1) { + for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++) + to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]); + } + else if (profile == IB_PROFILE_SRGB) { if(channels == 3) { for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) { srgb[0]= linearrgb_to_srgb(tof[0]); @@ -207,12 +211,8 @@ void IMB_rect_from_float(struct ImBuf *ibuf) floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x); } } - else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_LINEAR_RGB) && (dither==0.0f || channels!=4)) { - if(channels==1) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++) - to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]); - } - else if(channels==3) { + else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_LINEAR_RGB) && dither==0.0f) { + if(channels==3) { for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) { to[0] = FTOCHAR(tof[0]); to[1] = FTOCHAR(tof[1]); diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 9e5212e159f..0c38421a3f5 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -155,40 +155,37 @@ typedef struct PreviewImage { #endif /* ID from database */ -#define ID_SCE MAKE_ID2('S', 'C') -#define ID_LI MAKE_ID2('L', 'I') -#define ID_OB MAKE_ID2('O', 'B') -#define ID_ME MAKE_ID2('M', 'E') -#define ID_CU MAKE_ID2('C', 'U') -#define ID_MB MAKE_ID2('M', 'B') -#define ID_MA MAKE_ID2('M', 'A') -#define ID_TE MAKE_ID2('T', 'E') -#define ID_IM MAKE_ID2('I', 'M') -#define ID_IK MAKE_ID2('I', 'K') -#define ID_WV MAKE_ID2('W', 'V') -#define ID_LT MAKE_ID2('L', 'T') -#define ID_SE MAKE_ID2('S', 'E') -#define ID_LF MAKE_ID2('L', 'F') -#define ID_LA MAKE_ID2('L', 'A') -#define ID_CA MAKE_ID2('C', 'A') -#define ID_IP MAKE_ID2('I', 'P') -#define ID_KE MAKE_ID2('K', 'E') -#define ID_WO MAKE_ID2('W', 'O') -#define ID_SCR MAKE_ID2('S', 'R') -#define ID_SCRN MAKE_ID2('S', 'N') -#define ID_VF MAKE_ID2('V', 'F') -#define ID_TXT MAKE_ID2('T', 'X') -#define ID_SO MAKE_ID2('S', 'O') -#define ID_GR MAKE_ID2('G', 'R') -#define ID_ID MAKE_ID2('I', 'D') -#define ID_AR MAKE_ID2('A', 'R') -#define ID_AC MAKE_ID2('A', 'C') -#define ID_SCRIPT MAKE_ID2('P', 'Y') -#define ID_NT MAKE_ID2('N', 'T') -#define ID_BR MAKE_ID2('B', 'R') -#define ID_PA MAKE_ID2('P', 'A') -#define ID_GD MAKE_ID2('G', 'D') -#define ID_WM MAKE_ID2('W', 'M') +#define ID_SCE MAKE_ID2('S', 'C') /* Scene */ +#define ID_LI MAKE_ID2('L', 'I') /* Library */ +#define ID_OB MAKE_ID2('O', 'B') /* Object */ +#define ID_ME MAKE_ID2('M', 'E') /* Mesh */ +#define ID_CU MAKE_ID2('C', 'U') /* Curve */ +#define ID_MB MAKE_ID2('M', 'B') /* MetaBall */ +#define ID_MA MAKE_ID2('M', 'A') /* Material */ +#define ID_TE MAKE_ID2('T', 'E') /* Texture */ +#define ID_IM MAKE_ID2('I', 'M') /* Image */ +#define ID_WV MAKE_ID2('W', 'V') /* Wave (unused) */ +#define ID_LT MAKE_ID2('L', 'T') /* Lattice */ +#define ID_LA MAKE_ID2('L', 'A') /* Lamp */ +#define ID_CA MAKE_ID2('C', 'A') /* Camera */ +#define ID_IP MAKE_ID2('I', 'P') /* Ipo (depreciated, replaced by FCurves) */ +#define ID_KE MAKE_ID2('K', 'E') /* Key (shape key) */ +#define ID_WO MAKE_ID2('W', 'O') /* World */ +#define ID_SCR MAKE_ID2('S', 'R') /* Screen */ +#define ID_SCRN MAKE_ID2('S', 'N') /* (depreciated?) */ +#define ID_VF MAKE_ID2('V', 'F') /* VectorFont */ +#define ID_TXT MAKE_ID2('T', 'X') /* Text */ +#define ID_SO MAKE_ID2('S', 'O') /* Sound */ +#define ID_GR MAKE_ID2('G', 'R') /* Group */ +#define ID_ID MAKE_ID2('I', 'D') /* (internal use only) */ +#define ID_AR MAKE_ID2('A', 'R') /* Armature */ +#define ID_AC MAKE_ID2('A', 'C') /* Action */ +#define ID_SCRIPT MAKE_ID2('P', 'Y') /* Script (depreciated) */ +#define ID_NT MAKE_ID2('N', 'T') /* NodeTree */ +#define ID_BR MAKE_ID2('B', 'R') /* Brush */ +#define ID_PA MAKE_ID2('P', 'A') /* ParticleSettings */ +#define ID_GD MAKE_ID2('G', 'D') /* GreasePencil */ +#define ID_WM MAKE_ID2('W', 'M') /* WindowManager */ /* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */ #define ID_SEQ MAKE_ID2('S', 'Q') diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 318204e3dd8..2853b2cb029 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -146,7 +146,9 @@ typedef struct bPoseChannel { float limitmin[3], limitmax[3]; /* DOF constraint */ float stiffness[3]; /* DOF stiffness */ float ikstretch; - + float ikrotweight; /* weight of joint rotation constraint */ + float iklinweight; /* weight of joint stretch constraint */ + float *path; /* totpath x 3 x float */ struct Object *custom; /* draws custom object instead of this channel */ } bPoseChannel; @@ -166,7 +168,8 @@ typedef enum ePchan_Flag { POSE_CHAIN = 0x0200, POSE_DONE = 0x0400, POSE_KEY = 0x1000, - POSE_STRIDE = 0x2000 + POSE_STRIDE = 0x2000, + POSE_IKTREE = 0x4000, } ePchan_Flag; /* PoseChannel constflag (constraint detection) */ @@ -190,28 +193,34 @@ typedef enum ePchan_IkFlag { BONE_IK_YLIMIT = (1<<4), BONE_IK_ZLIMIT = (1<<5), + BONE_IK_ROTCTL = (1<<6), + BONE_IK_LINCTL = (1<<7), + BONE_IK_NO_XDOF_TEMP = (1<<10), BONE_IK_NO_YDOF_TEMP = (1<<11), - BONE_IK_NO_ZDOF_TEMP = (1<<12) + BONE_IK_NO_ZDOF_TEMP = (1<<12), + } ePchan_IkFlag; -/* PoseChannel->rotmode */ -typedef enum ePchan_RotMode { +/* PoseChannel->rotmode and Object->rotmode */ +typedef enum eRotationModes { /* quaternion rotations (default, and for older Blender versions) */ - PCHAN_ROT_QUAT = 0, + ROT_MODE_QUAT = 0, /* euler rotations - keep in sync with enum in BLI_arithb.h */ - PCHAN_ROT_XYZ = 1, /* Blender 'default' (classic) - must be as 1 to sync with PoseChannel rotmode */ - PCHAN_ROT_XZY, - PCHAN_ROT_YXZ, - PCHAN_ROT_YZX, - PCHAN_ROT_ZXY, - PCHAN_ROT_ZYX, + ROT_MODE_EUL = 1, /* Blender 'default' (classic) - must be as 1 to sync with arithb defines */ + ROT_MODE_XYZ = 1, /* Blender 'default' (classic) - must be as 1 to sync with arithb defines */ + ROT_MODE_XZY, + ROT_MODE_YXZ, + ROT_MODE_YZX, + ROT_MODE_ZXY, + ROT_MODE_ZYX, /* NOTE: space is reserved here for 18 other possible * euler rotation orders not implemented */ + ROT_MODE_MAX, /* sentinel for Py API */ /* axis angle rotations */ - PCHAN_ROT_AXISANGLE = -1 -} ePchan_RotMode; + ROT_MODE_AXISANGLE = -1 +} eRotationModes; /* Pose ------------------------------------ */ @@ -233,7 +242,9 @@ typedef struct bPose { ListBase agroups; /* list of bActionGroups */ int active_group; /* index of active group (starts from 1) */ - int pad; + int iksolver; /* ik solver to use, see ePose_IKSolverType */ + void *ikdata; /* temporary IK data, depends on the IK solver. Not saved in file */ + void *ikparam; /* IK solver parameters, structure depends on iksolver */ } bPose; @@ -249,8 +260,55 @@ typedef enum ePose_Flags { POSE_CONSTRAINTS_TIMEDEPEND = (1<<3), /* recalculate bone paths */ POSE_RECALCPATHS = (1<<4), + /* set by armature_rebuild_pose to give a chance to the IK solver to rebuild IK tree */ + POSE_WAS_REBUILT = (1<<5), + /* set by game_copy_pose to indicate that this pose is used in the game engine */ + POSE_GAME_ENGINE = (1<<6), } ePose_Flags; +/* IK Solvers ------------------------------------ */ + +/* bPose->iksolver and bPose->ikparam->iksolver */ +typedef enum { + IKSOLVER_LEGACY = 0, + IKSOLVER_ITASC, +} ePose_IKSolverType; + +/* header for all bPose->ikparam structures */ +typedef struct bIKParam { + int iksolver; +} bIKParam; + +/* bPose->ikparam when bPose->iksolver=1 */ +typedef struct bItasc { + int iksolver; + float precision; + short numiter; + short numstep; + float minstep; + float maxstep; + short solver; + short flag; + float feedback; + float maxvel; /* max velocity to SDLS solver */ + float dampmax; /* maximum damping for DLS solver */ + float dampeps; /* threshold of singular value from which the damping start progressively */ +} bItasc; + +/* bItasc->flag */ +typedef enum { + ITASC_AUTO_STEP = (1<<0), + ITASC_INITIAL_REITERATION = (1<<1), + ITASC_REITERATION = (1<<2), + ITASC_SIMULATION = (1<<3), +} eItasc_Flags; + +/* bItasc->solver */ +typedef enum { + ITASC_SOLVER_SDLS = 0, /* selective damped least square, suitable for CopyPose constraint */ + ITASC_SOLVER_DLS /* damped least square with numerical filtering of damping */ +} eItasc_Solver; + /* ************************************************ */ /* Action */ @@ -372,12 +430,13 @@ typedef enum DOPESHEET_FILTERFLAG { ADS_FILTER_NOSCE = (1<<15), ADS_FILTER_NOPART = (1<<16), ADS_FILTER_NOMBA = (1<<17), + ADS_FILTER_NOARM = (1<<18), /* NLA-specific filters */ ADS_FILTER_NLA_NOACT = (1<<20), /* if the AnimData block has no NLA data, don't include to just show Action-line */ /* combination filters (some only used at runtime) */ - ADS_FILTER_NOOBDATA = (ADS_FILTER_NOCAM|ADS_FILTER_NOMAT|ADS_FILTER_NOLAM|ADS_FILTER_NOCUR|ADS_FILTER_NOPART), + ADS_FILTER_NOOBDATA = (ADS_FILTER_NOCAM|ADS_FILTER_NOMAT|ADS_FILTER_NOLAM|ADS_FILTER_NOCUR|ADS_FILTER_NOPART|ADS_FILTER_NOARM), } DOPESHEET_FILTERFLAG; /* DopeSheet general flags */ @@ -494,5 +553,13 @@ typedef enum ACHAN_FLAG { ACHAN_MOVED = (1<<31), } ACHAN_FLAG; +// XXX Incorrect, Temp for building +#define PCHAN_ROT_QUAT -1 +#define PCHAN_ROT_XYZ -1 +#define PCHAN_ROT_XZY -1 +#define PCHAN_ROT_YXZ -1 +#define PCHAN_ROT_YZX -1 +#define PCHAN_ROT_ZXY -1 +#define PCHAN_ROT_ZYX -1 #endif diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 278da27faf9..58fa38ae159 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -142,7 +142,7 @@ typedef struct bGroupActuator { char name[32]; /* property or groupkey */ short pad[3], cur, butsta, butend;/* not referenced, can remove? */ - struct Group *group; /* only during game */ + /* struct Group *group; not used, remove */ } bGroupActuator; @@ -224,6 +224,15 @@ typedef struct bStateActuator { unsigned int mask; /* the bits to change */ } bStateActuator; +typedef struct bArmatureActuator { + char posechannel[32]; + char constraint[32]; + int type; /* 0=run, 1=enable, 2=disable, 3=set target, 4=set weight */ + float weight; + struct Object *target; + struct Object *subtarget; +} bArmatureActuator; + typedef struct bActuator { struct bActuator *next, *prev, *mynew; short type; @@ -295,6 +304,7 @@ typedef struct FreeCamera { #define ACT_PARENT 20 #define ACT_SHAPEACTION 21 #define ACT_STATE 22 +#define ACT_ARMATURE 23 /* actuator flag */ #define ACT_SHOW 1 @@ -484,6 +494,15 @@ typedef struct FreeCamera { #define ACT_PARENT_COMPOUND 1 #define ACT_PARENT_GHOST 2 +/* armatureactuator->type */ +#define ACT_ARM_RUN 0 +#define ACT_ARM_ENABLE 1 +#define ACT_ARM_DISABLE 2 +#define ACT_ARM_SETTARGET 3 +#define ACT_ARM_SETWEIGHT 4 +/* update this define if more type are addedd */ +#define ACT_ARM_MAXTYPE 4 + #endif diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index f75ed273164..9921878e926 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -632,7 +632,7 @@ typedef enum eKSP_TemplateTypes { KSP_TEMPLATE_CONSTRAINT = (1<<2), /* #con - active only */ KSP_TEMPLATE_NODE = (1<<3), /* #nod - selected node */ - KSP_TEMPLATE_PCHAN_ROT = (1<<16), /* modify rotation paths based on rotation mode of Pose Channel */ + KSP_TEMPLATE_ROT = (1<<16), /* modify rotation paths based on rotation mode of Object or Pose Channel */ } eKSP_TemplateTypes; /* ---------------- */ @@ -763,6 +763,11 @@ typedef enum eAnimData_Flag { /* don't execute drivers */ ADT_DRIVERS_DISABLED = (1<<11), + /* AnimData block is selected in UI */ + ADT_UI_SELECTED = (1<<14), + /* AnimData block is active in UI */ + ADT_UI_ACTIVE = (1<<15), + /* F-Curves from this AnimData block are not visible in the Graph Editor */ ADT_CURVES_NOT_VISIBLE = (1<<16), } eAnimData_Flag; diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index bb60fb107ff..590e7dadcdc 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -31,6 +31,8 @@ #include "DNA_listBase.h" #include "DNA_ID.h" +struct AnimData; + /* this system works on different transformation space levels; 1) Bone Space; with each Bone having own (0,0,0) origin @@ -69,6 +71,7 @@ typedef struct Bone { typedef struct bArmature { ID id; + struct AnimData *adt; ListBase bonebase; ListBase chainbase; ListBase *edbo; /* editbone listbase, we use pointer so we can check state */ @@ -102,7 +105,8 @@ typedef enum eArmature_Flag { ARM_AUTO_IK = (1<<9), ARM_NO_CUSTOM = (1<<10), /* made option negative, for backwards compat */ ARM_COL_CUSTOM = (1<<11), /* draw custom colours */ - ARM_GHOST_ONLYSEL = (1<<12) /* when ghosting, only show selected bones (this should belong to ghostflag instead) */ + ARM_GHOST_ONLYSEL = (1<<12), /* when ghosting, only show selected bones (this should belong to ghostflag instead) */ + ARM_DS_EXPAND = (1<<13) } eArmature_Flag; /* armature->drawtype */ diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index a3a1a342584..1bbccd20486 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -56,7 +56,7 @@ typedef struct Brush { short flag, blend; /* general purpose flag, blend mode */ int size; /* brush diameter */ - float innerradius; /* inner radius after which the falloff starts */ + float jitter; /* jitter the position of the brush */ float spacing; /* spacing of paint operations */ int smooth_stroke_radius; /* turning radius (in pixels) for smooth stroke */ float smooth_stroke_factor; /* higher values limit fast changes in the stroke direction */ @@ -76,7 +76,7 @@ typedef struct Brush { #define BRUSH_TORUS 2 #define BRUSH_ALPHA_PRESSURE 4 #define BRUSH_SIZE_PRESSURE 8 -#define BRUSH_RAD_PRESSURE 16 +#define BRUSH_JITTER_PRESSURE 16 /* was BRUSH_RAD_PRESSURE */ #define BRUSH_SPACING_PRESSURE 32 #define BRUSH_FIXED_TEX 64 #define BRUSH_RAKE 128 diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 70430af3fc8..fccec7a556f 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -66,6 +66,9 @@ typedef struct bConstraint { int pad; struct Ipo *ipo; /* local influence ipo or driver */ // XXX depreceated for 2.5... old animation system hack + /* below are readonly fields that are set at runtime by the solver for use in the GE (only IK atm) */ + float lin_error; /* residual error on constraint expressed in blender unit*/ + float rot_error; /* residual error on constraint expressed in radiant */ } bConstraint; @@ -119,24 +122,34 @@ typedef struct bPythonConstraint { } bPythonConstraint; -/* Inverse-Kinematics (IK) constraint */ +/* inverse-Kinematics (IK) constraint + This constraint supports a variety of mode determine by the type field + according to B_CONSTRAINT_IK_TYPE. + Some fields are used by all types, some are specific to some types + This is indicated in the comments for each field + */ typedef struct bKinematicConstraint { - Object *tar; - short iterations; /* Maximum number of iterations to try */ - short flag; /* Like CONSTRAINT_IK_TIP */ - short rootbone; /* index to rootbone, if zero go all the way to mother bone */ - short max_rootbone; /* for auto-ik, maximum length of chain */ - char subtarget[32]; /* String to specify sub-object target */ - - Object *poletar; /* Pole vector target */ - char polesubtarget[32]; /* Pole vector sub-object target */ - float poleangle; /* Pole vector rest angle */ - - float weight; /* Weight of goal in IK tree */ - float orientweight; /* Amount of rotation a target applies on chain */ - float grabtarget[3]; /* for target-less IK */ + Object *tar; /* All: target object in case constraint needs a target */ + short iterations; /* All: Maximum number of iterations to try */ + short flag; /* All & CopyPose: some options Like CONSTRAINT_IK_TIP */ + short rootbone; /* All: index to rootbone, if zero go all the way to mother bone */ + short max_rootbone; /* CopyPose: for auto-ik, maximum length of chain */ + char subtarget[32]; /* All: String to specify sub-object target */ + Object *poletar; /* All: Pole vector target */ + char polesubtarget[32]; /* All: Pole vector sub-object target */ + float poleangle; /* All: Pole vector rest angle */ + float weight; /* All: Weight of constraint in IK tree */ + float orientweight; /* CopyPose: Amount of rotation a target applies on chain */ + float grabtarget[3]; /* CopyPose: for target-less IK */ + short type; /* subtype of IK constraint: B_CONSTRAINT_IK_TYPE */ + short mode; /* Distance: how to limit in relation to clamping sphere: LIMITDIST_.. */ + float dist; /* Distance: distance (radius of clamping sphere) from target */ } bKinematicConstraint; +typedef enum B_CONSTRAINT_IK_TYPE { + CONSTRAINT_IK_COPYPOSE = 0, /* 'standard' IK constraint: match position and/or orientation of target */ + CONSTRAINT_IK_DISTANCE /* maintain distance with target */ +} B_CONSTRAINT_IK_TYPE; /* Single-target subobject constraints --------------------- */ /* Track To Constraint */ @@ -376,7 +389,9 @@ typedef enum B_CONSTRAINT_FLAG { /* influence ipo is on constraint itself, not in action channel */ CONSTRAINT_OWN_IPO = (1<<7), /* indicates that constraint was added locally (i.e. didn't come from the proxy-lib) */ - CONSTRAINT_PROXY_LOCAL = (1<<8) + CONSTRAINT_PROXY_LOCAL = (1<<8), + /* indicates that constraint is temporarily disabled (only used in GE) */ + CONSTRAINT_OFF = (1<<9) } B_CONSTRAINT_FLAG; /* bConstraint->ownspace/tarspace */ diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 109a9528de2..6cfeb646cf2 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -310,6 +310,7 @@ typedef enum eBezTriple_Interpolation { /* types of keyframe (used only for BezTriple->hide when BezTriple is used in F-Curves) */ typedef enum eBezTriple_KeyframeType { BEZT_KEYTYPE_KEYFRAME = 0, /* default - 'proper' Keyframe */ + BEZT_KEYTYPE_EXTREME, /* 'extreme' keyframe */ BEZT_KEYTYPE_BREAKDOWN, /* 'breakdown' keyframe */ } eBezTriple_KeyframeType; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 54433fd4254..bcb85b5f87e 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -438,9 +438,7 @@ typedef struct CollisionModifierData { unsigned int numverts; unsigned int numfaces; - short absorption; /* used for forces, in % */ - short pad; - float time; /* cfra time of modifier */ + float time, pad; /* cfra time of modifier */ struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */ } CollisionModifierData; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index b10de02dbb4..e70221df9ab 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -40,6 +40,7 @@ struct bNodeLink; struct bNodeType; struct bNodeGroup; struct AnimData; +struct uiBlock; #define NODE_MAXSTR 32 @@ -131,6 +132,7 @@ typedef struct bNode { rctf butr; /* optional buttons area */ rctf prvr; /* optional preview area */ bNodePreview *preview; /* optional preview image */ + struct uiBlock *block; /* runtime during drawing */ struct bNodeType *typeinfo; /* lookup of callbacks and defaults */ diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h index 09288b24c20..da55fb1d47c 100644 --- a/source/blender/makesdna/DNA_object_fluidsim.h +++ b/source/blender/makesdna/DNA_object_fluidsim.h @@ -41,6 +41,7 @@ struct Ipo; struct MVert; typedef struct FluidsimSettings { + struct FluidsimModifierData *fmd; /* for fast RNA access */ /* domain,fluid or obstacle */ short type; /* display advanced options in fluid sim tab (on=1,off=0)*/ diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 986a75f1a96..468ad35de85 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -62,6 +62,8 @@ typedef struct PartDeflect { float pdef_sbift; /* inner face thickness for softbody deflection */ float pdef_sboft; /* outer face thickness for softbody deflection */ + float absorption, pad; /* used for forces */ + /* variables for guide curve */ float clump_fac, clump_pow; float kink_freq, kink_shape, kink_amp, free_end; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index a89f8e1fb2e..a6532409e6e 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -134,7 +134,7 @@ typedef struct Object { float loc[3], dloc[3], orig[3]; float size[3], dsize[3]; float rot[3], drot[3]; - /* float quat[4], dquat[4]; (not used yet) */ + float quat[4], dquat[4]; float obmat[4][4]; 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 */ @@ -176,9 +176,11 @@ typedef struct Object { float max_vel; /* clamp the maximum velocity 0.0 is disabled */ float min_vel; /* clamp the maximum velocity 0.0 is disabled */ float m_contactProcessingThreshold; - + + short rotmode; /* rotation mode - uses defines set out in DNA_action_types.h for PoseChannel rotations... */ + char dt, dtx; - char empty_drawtype, pad1[5]; + char empty_drawtype, pad1[3]; float empty_drawsize; float dupfacesca; /* dupliface scale */ @@ -243,6 +245,7 @@ typedef struct Object { ListBase gpulamp; /* runtime, for lamps only */ ListBase pc_ids; + ListBase *duplilist; /* for temporary dupli list storage, only for use by RNA API */ } Object; /* Warning, this is not used anymore because hooks are now modifiers */ @@ -263,6 +266,14 @@ typedef struct ObHook { float force; } ObHook; +typedef struct DupliObject { + struct DupliObject *next, *prev; + struct Object *ob; + unsigned int origlay; + int index, no_draw, type, animated; + float mat[4][4], omat[4][4]; + float orco[3], uv[2]; +} DupliObject; /* this work object is defined in object.c */ extern Object workob; @@ -304,6 +315,7 @@ extern Object workob; /* (short) transflag */ #define OB_OFFS_LOCAL 1 + // XXX OB_QUAT was never used, but is now depreceated in favour of standard rotation handling... #define OB_QUAT 2 #define OB_NEG_SCALE 4 #define OB_DUPLI (8+16+256+512+2048) @@ -393,6 +405,7 @@ extern Object workob; #define BA_HAS_RECALC_OB 4 #define BA_HAS_RECALC_DATA 8 + // XXX DEPRECEATED SETTING... #define BA_DO_IPO 32 #define BA_FROMSET 128 diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 6a0a0e1d912..089c1c76bcf 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -67,7 +67,7 @@ typedef struct ChildParticle { int pa[4]; /* nearest particles to the child, used for the interpolation */ float w[4]; /* interpolation weights for the above particles */ float fuv[4], foffset; /* face vertex weights and offset */ - float rand[3]; + float rt; } ChildParticle; typedef struct ParticleTarget { @@ -234,13 +234,17 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in struct ListBase ptcaches; struct KDTree *tree; /* used for interactions with self and other systems */ + + struct ParticleDrawData *pdd; + + float *frand; /* array of 1024 random floats for fast lookups */ }ParticleSystem; /* part->type */ /* hair is allways baked static in object/geometry space */ /* other types (normal particles) are in global space and not static baked */ #define PART_EMITTER 0 -#define PART_REACTOR 1 +//#define PART_REACTOR 1 #define PART_HAIR 2 #define PART_FLUID 3 @@ -325,7 +329,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PART_DRAW_EMITTER 8 /* render emitter also */ #define PART_DRAW_HEALTH 16 #define PART_ABS_PATH_TIME 32 -//#define PART_DRAW_TRAIL 64 +//#define PART_DRAW_TRAIL 64 /* deprecated */ #define PART_DRAW_BB_LOCK 128 #define PART_DRAW_PARENT 256 #define PART_DRAW_NUM 512 @@ -422,13 +426,13 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PSYS_HAIR_DONE 512 #define PSYS_KEYED 1024 #define PSYS_EDITED 2048 -//#define PSYS_PROTECT_CACHE 4096 +//#define PSYS_PROTECT_CACHE 4096 /* deprecated */ #define PSYS_DISABLED 8192 /* pars->flag */ #define PARS_UNEXIST 1 #define PARS_NO_DISP 2 -//#define PARS_STICKY 4 +//#define PARS_STICKY 4 /* deprecated */ #define PARS_REKEY 8 /* pars->alive */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b00500a321a..09e9f599d03 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -93,6 +93,8 @@ typedef struct FFMpegCodecData { int audio_codec; int video_bitrate; int audio_bitrate; + int audio_mixrate; + float audio_volume; int gop_size; int flags; @@ -106,10 +108,13 @@ typedef struct FFMpegCodecData { typedef struct AudioData { - int mixrate; - float main; /* Main mix in dB */ + int mixrate; // 2.5: now in FFMpegCodecData: audio_mixrate + float main; // 2.5: now in FFMpegCodecData: audio_volume + float speed_of_sound; + float doppler_factor; + int distance_model; short flag; - short pad[3]; + short pad; } AudioData; typedef struct SceneRenderLayer { @@ -172,7 +177,6 @@ typedef struct RenderData { struct AviCodecData *avicodecdata; struct QuicktimeCodecData *qtcodecdata; struct FFMpegCodecData ffcodecdata; - struct AudioData audio; /* new in 2.5 */ int cfra, sfra, efra; /* frames as in 'images' */ int psfra, pefra; /* start+end frames of preview range */ @@ -702,7 +706,7 @@ typedef struct Scene { /* migrate or replace? depends on some internal things... */ /* no, is on the right place (ton) */ struct RenderData r; - struct AudioData audio; /* DEPRECATED 2.5 */ + struct AudioData audio; ListBase markers; ListBase transform_spaces; diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h index cc998de7eec..a5ba5886ed5 100644 --- a/source/blender/makesdna/DNA_sensor_types.h +++ b/source/blender/makesdna/DNA_sensor_types.h @@ -126,6 +126,13 @@ typedef struct bRaySensor { int axisflag; } bRaySensor; +typedef struct bArmatureSensor { + char posechannel[32]; + char constraint[32]; + int type; + float value; +} bArmatureSensor; + typedef struct bMessageSensor { /** * (Possible future use) pointer to a single sender object @@ -202,6 +209,15 @@ typedef struct bJoystickSensor { #define SENS_MESG_MESG 0 #define SENS_MESG_PROP 1 +/* bArmatureSensor->type */ +#define SENS_ARM_STATE_CHANGED 0 +#define SENS_ARM_LIN_ERROR_BELOW 1 +#define SENS_ARM_LIN_ERROR_ABOVE 2 +#define SENS_ARM_ROT_ERROR_BELOW 3 +#define SENS_ARM_ROT_ERROR_ABOVE 4 +/* update this when adding new type */ +#define SENS_ARM_MAXTYPE 4 + /* sensor->type */ #define SENS_ALWAYS 0 #define SENS_TOUCH 1 @@ -217,6 +233,7 @@ typedef struct bJoystickSensor { #define SENS_JOYSTICK 11 #define SENS_ACTUATOR 12 #define SENS_DELAY 13 +#define SENS_ARMATURE 14 /* sensor->flag */ #define SENS_SHOW 1 #define SENS_DEL 2 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 806d12815b5..2cd47e340bd 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -569,18 +569,19 @@ typedef struct SpaceUserPref { /* buts->mainb new */ -#define BCONTEXT_SCENE 0 -#define BCONTEXT_WORLD 1 -#define BCONTEXT_OBJECT 2 -#define BCONTEXT_DATA 3 -#define BCONTEXT_MATERIAL 4 -#define BCONTEXT_TEXTURE 5 -#define BCONTEXT_PARTICLE 6 -#define BCONTEXT_PHYSICS 7 -#define BCONTEXT_BONE 9 -#define BCONTEXT_MODIFIER 10 -#define BCONTEXT_CONSTRAINT 12 -#define BCONTEXT_TOT 13 +#define BCONTEXT_SCENE 0 +#define BCONTEXT_WORLD 1 +#define BCONTEXT_OBJECT 2 +#define BCONTEXT_DATA 3 +#define BCONTEXT_MATERIAL 4 +#define BCONTEXT_TEXTURE 5 +#define BCONTEXT_PARTICLE 6 +#define BCONTEXT_PHYSICS 7 +#define BCONTEXT_BONE 9 +#define BCONTEXT_MODIFIER 10 +#define BCONTEXT_CONSTRAINT 12 +#define BCONTEXT_BONE_CONSTRAINT 13 +#define BCONTEXT_TOT 14 /* sbuts->flag */ #define SB_PRV_OSA 1 @@ -833,6 +834,7 @@ enum { #define TIME_SEQ 32 #define TIME_ALL_IMAGE_WIN 64 #define TIME_CONTINUE_PHYSICS 128 +#define TIME_NODES 256 /* sseq->mainb */ #define SEQ_DRAW_SEQUENCE 0 diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index e221524eac2..f67a242b469 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -89,9 +89,7 @@ typedef struct RegionView3D { float camdx, camdy; /* camera view offsets, 1.0 = viewplane moves entire width/height */ float pixsize; float ofs[3]; - short camzoom, viewbut; - - int lastmode; /* for modal keymap switching, int because it stores notifier code */ + short camzoom, viewbut, pad[2]; short rflag, viewlock; short persp; @@ -146,7 +144,7 @@ typedef struct View3D { * The drawing mode for the 3d display. Set to OB_WIRE, OB_SOLID, * OB_SHADED or OB_TEXTURE */ short drawtype; - short localview; + short pad2; short scenelock, around, pad3; short flag, flag2; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 10f83c8b9ec..ea9d0e86c38 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -1,5 +1,5 @@ /** - * $Id: + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -80,6 +80,7 @@ typedef enum ReportType { enum ReportListFlags { RPT_PRINT = 1, RPT_STORE = 2, + RPT_FREE = 4, }; typedef struct Report { struct Report *next, *prev; @@ -161,7 +162,8 @@ typedef struct wmWindow { ListBase timers; ListBase queue; /* all events (ghost level events were handled) */ - ListBase handlers; /* window+screen handlers, overriding all queues */ + ListBase handlers; /* window+screen handlers, handled last */ + ListBase modalhandlers; /* priority handlers, handled first */ ListBase subwindows; /* opengl stuff for sub windows, see notes in wm_subwindow.c */ ListBase gesture; /* gesture stuff */ @@ -226,6 +228,7 @@ typedef struct wmOperatorType { /* only used for operators defined with python * use to store pointers to python functions */ void *pyop_data; + int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot); } wmOperatorType; @@ -264,6 +267,9 @@ typedef struct wmKeyMap { short pad; void *items; /* struct EnumPropertyItem for now */ + + /* verify if the keymap is enabled in the current context */ + int (*poll)(struct bContext *); } wmKeyMap; @@ -297,7 +303,6 @@ typedef struct wmOperator { #define OPERATOR_PASS_THROUGH 8 /* wmOperator flag */ -#define OPERATOR_REPORT_FREE 1 /* ************** wmEvent ************************ */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 05f39d73842..9ea7725b855 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -249,7 +249,6 @@ extern StructRNA RNA_LimitDistanceConstraint; extern StructRNA RNA_LimitLocationConstraint; extern StructRNA RNA_LimitRotationConstraint; extern StructRNA RNA_LimitScaleConstraint; -extern StructRNA RNA_LocalLamp; extern StructRNA RNA_LockedTrackConstraint; extern StructRNA RNA_MagicTexture; extern StructRNA RNA_Main; @@ -329,10 +328,12 @@ extern StructRNA RNA_PointCache; extern StructRNA RNA_PointDensity; extern StructRNA RNA_PointDensityTexture; extern StructRNA RNA_PointerProperty; +extern StructRNA RNA_PointLamp; extern StructRNA RNA_Pose; extern StructRNA RNA_PoseChannel; extern StructRNA RNA_Property; extern StructRNA RNA_PropertySensor; +extern StructRNA RNA_ArmatureSensor; extern StructRNA RNA_PythonConstraint; extern StructRNA RNA_PythonController; extern StructRNA RNA_RadarSensor; @@ -586,6 +587,7 @@ PropertyUnit RNA_property_unit(PropertyRNA *prop); int RNA_property_flag(PropertyRNA *prop); int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop); +int RNA_property_array_check(PointerRNA *ptr, PropertyRNA *prop); int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dimension); int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[]); char RNA_property_array_item_char(PropertyRNA *prop, int index); @@ -691,6 +693,7 @@ char *RNA_path_back(const char *path); int RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop); +char *RNA_path_from_ID_to_struct(PointerRNA *ptr); char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop); #if 0 diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index 595562503aa..37b175fbf12 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -102,6 +102,8 @@ PropertyRNA *RNA_def_float_dynamic_array(StructOrFunctionRNA *cont, const char * */ PropertyRNA *RNA_def_float_percentage(StructOrFunctionRNA *cont, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax); +PropertyRNA *RNA_def_float_factor(StructOrFunctionRNA *cont, const char *identifier, float default_value, float hardmin, float hardmax, + const char *ui_name, const char *ui_description, float softmin, float softmax); PropertyRNA *RNA_def_pointer(StructOrFunctionRNA *cont, const char *identifier, const char *type, const char *ui_name, const char *ui_description); diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index e7fe86afd03..98df8c34d58 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -94,9 +94,10 @@ typedef enum PropertySubType { /* numbers */ PROP_UNSIGNED = 13, PROP_PERCENTAGE = 14, - PROP_ANGLE = 15|PROP_UNIT_ROTATION, - PROP_TIME = 16|PROP_UNIT_TIME, - PROP_DISTANCE = 17|PROP_UNIT_LENGTH, + PROP_FACTOR = 15, + PROP_ANGLE = 16|PROP_UNIT_ROTATION, + PROP_TIME = 17|PROP_UNIT_TIME, + PROP_DISTANCE = 18|PROP_UNIT_LENGTH, /* number arrays */ PROP_COLOR = 20, @@ -107,11 +108,9 @@ typedef enum PropertySubType { PROP_MATRIX = 25, PROP_EULER = 26|PROP_UNIT_ROTATION, PROP_QUATERNION = 27, - PROP_XYZ = 28, - PROP_RGB = 29, - - /* pointers */ - PROP_NEVER_NULL = 30, + PROP_AXISANGLE = 28, + PROP_XYZ = 29, + PROP_RGB = 30, /* booleans */ PROP_LAYER = 40, @@ -149,6 +148,7 @@ typedef enum PropertyFlag { /* pointers */ PROP_ID_REFCOUNT = 64, + PROP_NEVER_NULL = 262144, /* internal flags */ PROP_BUILTIN = 128, diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index 845abf636e2..8fc9df0fbf6 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -7,7 +7,7 @@ o = SConscript('intern/SConscript') objs += o incs = '#/intern/guardedalloc ../blenkernel ../blenlib ../makesdna intern .' -incs += ' ../windowmanager ../editors/include ../imbuf' +incs += ' ../windowmanager ../editors/include ../imbuf ../ikplugin' incs += ' ../render/extern/include' defs = [] diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 709c5d017ec..50cf0b00b84 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -39,7 +39,7 @@ SET(SRC ../../../../intern/guardedalloc/intern/mallocn.c ../../../../intern/guardedalloc/intern/mmap_win.c) -INCLUDE_DIRECTORIES(../../../../intern/guardedalloc .. ../../makesdna ../../blenkernel ../../blenlib ../../windowmanager ../../editors/include ../../imbuf ../../render/extern/include .) +INCLUDE_DIRECTORIES(../../../../intern/guardedalloc .. ../../makesdna ../../blenkernel ../../blenlib ../../ikplugin ../../windowmanager ../../editors/include ../../imbuf ../../render/extern/include .) FILE(GLOB INC_FILES ../*.h ../../makesdna/*.h) IF(WITH_GAMEENGINE) diff --git a/source/blender/makesrna/intern/Makefile b/source/blender/makesrna/intern/Makefile index 4a4e41edd15..7923ea1e7de 100644 --- a/source/blender/makesrna/intern/Makefile +++ b/source/blender/makesrna/intern/Makefile @@ -49,6 +49,7 @@ CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../blenkernel CPPFLAGS += -I../../imbuf +CPPFLAGS += -I../../ikplugin CPPFLAGS += -I../../makesdna CPPFLAGS += -I../../windowmanager CPPFLAGS += -I../../editors/include diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index 569f0547731..0f8bc752f09 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -30,7 +30,7 @@ makesrna_tool.Append(CCFLAGS = '-DBASE_HEADER="\\"source/blender/makesrna/\\"" ' defs = [] incs = '#/intern/guardedalloc ../../blenlib ../../blenkernel' -incs += ' ../../imbuf ../../makesdna ../../makesrna' +incs += ' ../../imbuf ../../makesdna ../../makesrna ../../ikplugin' incs += ' ../../windowmanager ../../editors/include' incs += ' ../../render/extern/include' diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index d0c7824dc9d..63b58f27c53 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -1406,6 +1406,7 @@ static const char *rna_property_subtypename(PropertyType type) case PROP_DIRPATH: return "PROP_DIRPATH"; case PROP_UNSIGNED: return "PROP_UNSIGNED"; case PROP_PERCENTAGE: return "PROP_PERCENTAGE"; + case PROP_FACTOR: return "PROP_FACTOR"; case PROP_ANGLE: return "PROP_ANGLE"; case PROP_TIME: return "PROP_TIME"; case PROP_DISTANCE: return "PROP_DISTANCE"; @@ -1415,11 +1416,11 @@ static const char *rna_property_subtypename(PropertyType type) case PROP_MATRIX: return "PROP_MATRIX"; case PROP_EULER: return "PROP_EULER"; case PROP_QUATERNION: return "PROP_QUATERNION"; + case PROP_AXISANGLE: return "PROP_AXISANGLE"; case PROP_VELOCITY: return "PROP_VELOCITY"; case PROP_ACCELERATION: return "PROP_ACCELERATION"; case PROP_XYZ: return "PROP_XYZ"; case PROP_RGB: return "PROP_RGB"; - case PROP_NEVER_NULL: return "PROP_NEVER_NULL"; case PROP_LAYER: return "PROP_LAYER"; case PROP_LAYER_MEMBER: return "PROP_LAYER_MEMBER"; default: { @@ -1969,7 +1970,7 @@ RNAProcessItem PROCESS_ITEMS[]= { {"rna_rna.c", NULL, RNA_def_rna}, {"rna_ID.c", NULL, RNA_def_ID}, {"rna_texture.c", NULL, RNA_def_texture}, - {"rna_action.c", NULL, RNA_def_action}, + {"rna_action.c", "rna_action_api.c", RNA_def_action}, {"rna_animation.c", "rna_animation_api.c", RNA_def_animation}, {"rna_actuator.c", NULL, RNA_def_actuator}, {"rna_armature.c", NULL, RNA_def_armature}, @@ -1986,12 +1987,12 @@ RNAProcessItem PROCESS_ITEMS[]= { {"rna_fluidsim.c", NULL, RNA_def_fluidsim}, {"rna_gpencil.c", NULL, RNA_def_gpencil}, {"rna_group.c", NULL, RNA_def_group}, - {"rna_image.c", NULL, RNA_def_image}, + {"rna_image.c", "rna_image_api.c", RNA_def_image}, {"rna_key.c", NULL, RNA_def_key}, {"rna_lamp.c", NULL, RNA_def_lamp}, {"rna_lattice.c", NULL, RNA_def_lattice}, {"rna_main.c", "rna_main_api.c", RNA_def_main}, - {"rna_material.c", NULL, RNA_def_material}, + {"rna_material.c", "rna_material_api.c", RNA_def_material}, {"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh}, {"rna_meta.c", NULL, RNA_def_meta}, {"rna_modifier.c", NULL, RNA_def_modifier}, @@ -2001,7 +2002,7 @@ RNAProcessItem PROCESS_ITEMS[]= { {"rna_object_force.c", NULL, RNA_def_object_force}, {"rna_packedfile.c", NULL, RNA_def_packedfile}, {"rna_particle.c", NULL, RNA_def_particle}, - {"rna_pose.c", NULL, RNA_def_pose}, + {"rna_pose.c", "rna_pose_api.c", RNA_def_pose}, {"rna_property.c", NULL, RNA_def_gameproperty}, {"rna_render.c", NULL, RNA_def_render}, {"rna_scene.c", "rna_scene_api.c", RNA_def_scene}, diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index e4bda24cf20..21fbc9fa66d 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -225,6 +225,18 @@ static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop) } } +static int rna_ensure_property_array_check(PointerRNA *ptr, PropertyRNA *prop) +{ + if(prop->magic == RNA_MAGIC) { + return (prop->getlength || prop->totarraylength) ? 1:0; + } + else { + IDProperty *idprop= (IDProperty*)prop; + + return idprop->type == IDP_ARRAY ? 1:0; + } +} + static void rna_ensure_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int length[]) { if(prop->magic == RNA_MAGIC) { @@ -574,6 +586,11 @@ int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop) return rna_ensure_property_array_length(ptr, prop); } +int RNA_property_array_check(PointerRNA *ptr, PropertyRNA *prop) +{ + return rna_ensure_property_array_check(ptr, prop); +} + /* used by BPY to make an array from the python object */ int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[]) { @@ -603,7 +620,7 @@ char RNA_property_array_item_char(PropertyRNA *prop, int index) PropertySubType subtype= rna_ensure_property(prop)->subtype; /* get string to use for array index */ - if ((index < 4) && (subtype == PROP_QUATERNION)) + if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) return quatitem[index]; else if((index < 4) && ELEM6(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION)) return vectoritem[index]; @@ -1392,10 +1409,17 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value) { - PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop; + IDProperty *idprop; - if(pprop->set) - pprop->set(ptr, ptr_value); + if((idprop=rna_idproperty_check(&prop, ptr))) { + /* not supported */ + } + else { + PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop; + + if(pprop->set && !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL)) + pprop->set(ptr, ptr_value); + } } void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop) @@ -2363,12 +2387,11 @@ char *RNA_path_back(const char *path) return result; } -char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) +char *RNA_path_from_ID_to_struct(PointerRNA *ptr) { - char *ptrpath=NULL, *path; - const char *propname; + char *ptrpath=NULL; - if(!ptr->id.data || !ptr->data || !prop) + if(!ptr->id.data || !ptr->data) return NULL; if(!RNA_struct_is_ID(ptr->type)) { @@ -2394,6 +2417,20 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) else return NULL; } + + return ptrpath; +} + +char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) +{ + const char *propname; + char *ptrpath, *path; + + if(!ptr->id.data || !ptr->data || !prop) + return NULL; + + /* path from ID to the struct holding this property */ + ptrpath= RNA_path_from_ID_to_struct(ptr); propname= RNA_property_identifier(prop); diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index e376d3125e3..eaa11b4ad38 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -38,7 +38,7 @@ #else -void rna_def_action_group(BlenderRNA *brna) +static void rna_def_action_group(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -76,7 +76,7 @@ void rna_def_action_group(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Custom Color", "Index of custom color set."); } -void rna_def_action(BlenderRNA *brna) +static void rna_def_action(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -100,6 +100,8 @@ void rna_def_action(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "markers", NULL); RNA_def_property_struct_type(prop, "TimelineMarker"); RNA_def_property_ui_text(prop, "Pose Markers", "Markers specific to this Action, for labeling poses."); + + RNA_api_action(srna); } /* --------- */ diff --git a/source/blender/makesrna/intern/rna_action_api.c b/source/blender/makesrna/intern/rna_action_api.c new file mode 100644 index 00000000000..991a8251cc5 --- /dev/null +++ b/source/blender/makesrna/intern/rna_action_api.c @@ -0,0 +1,80 @@ +/** + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Arystanbek Dyussenov + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "RNA_define.h" +#include "RNA_types.h" + +#include "DNA_action_types.h" + +#ifdef RNA_RUNTIME + +#include "BKE_action.h" + +#include "DNA_anim_types.h" +#include "DNA_curve_types.h" + +/* XXX disabled until RNA allows returning arrays */ +#if 0 +/* return frame range of all curves (min, max) or (0, 1) if there are no keys */ +int *rna_Action_get_frame_range(bAction *act, int *ret_length) +{ + int *ret; + float start, end; + + calc_action_range(act, &start, &end, 1); + + *ret_length= 2; + ret= MEM_callocN(*ret_length * sizeof(int), "rna_Action_get_frame_range"); + + ret[0]= (int)start; + ret[1]= (int)end; + + return ret; +} +#endif + +#else + +void RNA_api_action(StructRNA *srna) +{ +#if 0 + FunctionRNA *func; + PropertyRNA *parm; + + func= RNA_def_function(srna, "get_frame_range", "rna_Action_get_frame_range"); + RNA_def_function_ui_description(func, "Get action frame range as a (min, max) tuple."); + parm= RNA_def_int_array(func, "frame_range", 1, NULL, 0, 0, "", "Action frame range.", 0, 0); + RNA_def_property_flag(parm, PROP_DYNAMIC_ARRAY); + RNA_def_function_return(func, parm); +#endif +} + +#endif diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index 473e726db60..ce83d1c469b 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -58,6 +58,7 @@ void RNA_def_actuator(BlenderRNA *brna) {ACT_PARENT, "PARENT", 0, "Parent", ""}, {ACT_SHAPEACTION, "SHAPE_ACTION", 0, "Shape Action", ""}, {ACT_STATE, "STATE", 0, "State", ""}, + {ACT_ARMATURE, "ARMATURE", 0, "Armature", ""}, {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "Actuator", NULL); diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index e4bea893992..4b2c11c2e0d 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -57,6 +57,12 @@ static int rna_AnimData_action_editable(PointerRNA *ptr) return 1; } +static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value) +{ + AnimData *adt= (AnimData*)(ptr->data); + adt->action= value.data; +} + static void rna_ksPath_RnaPath_get(PointerRNA *ptr, char *value) { KS_Path *ksp= (KS_Path *)ptr->data; @@ -93,7 +99,7 @@ static void rna_ksPath_RnaPath_set(PointerRNA *ptr, const char *value) #else -void rna_def_keyingset_path(BlenderRNA *brna) +static void rna_def_keyingset_path(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -132,7 +138,7 @@ void rna_def_keyingset_path(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Entire Array", "When an 'array/vector' type is chosen (Location, Rotation, Color, etc.), entire array is to be used."); } -void rna_def_keyingset(BlenderRNA *brna) +static void rna_def_keyingset(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -202,8 +208,11 @@ void rna_def_animdata(BlenderRNA *brna) /* Active Action */ prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE); - RNA_def_property_ui_text(prop, "Action", "Active Action for this datablock."); + RNA_def_property_pointer_funcs(prop, NULL, "rna_AnimData_action_set", NULL); + RNA_def_property_flag(prop, PROP_EDITABLE); /* this flag as well as the dynamic test must be defined for this to be editable... */ RNA_def_property_editable_func(prop, "rna_AnimData_action_editable"); + RNA_def_property_ui_text(prop, "Action", "Active Action for this datablock."); + /* Active Action Settings */ prop= RNA_def_property(srna, "action_extrapolation", PROP_ENUM, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 57eb3c1de4a..5dbfdd3e6f1 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -52,6 +52,7 @@ static void rna_Armature_update_data(bContext *C, PointerRNA *ptr) DAG_id_flush_update(id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, id); + //WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL); } static void rna_Armature_redraw_data(bContext *C, PointerRNA *ptr) @@ -61,6 +62,11 @@ static void rna_Armature_redraw_data(bContext *C, PointerRNA *ptr) WM_event_add_notifier(C, NC_GEOM|ND_DATA, id); } +static char *rna_Bone_path(PointerRNA *ptr) +{ + return BLI_sprintfN("bones[\"%s\"]", ((Bone*)ptr->data)->name); +} + static void rna_bone_layer_set(short *layer, const int *values) { int i, tot= 0; @@ -430,6 +436,7 @@ static void rna_def_bone(BlenderRNA *brna) srna= RNA_def_struct(brna, "Bone", NULL); RNA_def_struct_ui_text(srna, "Bone", "Bone in an Armature datablock."); RNA_def_struct_ui_icon(srna, ICON_BONE_DATA); + RNA_def_struct_path_func(srna, "rna_Bone_path"); /* pointers/collections */ /* parent (pointer) */ @@ -457,6 +464,37 @@ static void rna_def_bone(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_SELECTED); RNA_def_property_ui_text(prop, "Selected", ""); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); + + /* XXX better matrix descriptions possible (Arystan) */ + prop= RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "bone_mat"); + RNA_def_property_array(prop, 9); + RNA_def_property_ui_text(prop, "Bone Matrix", "3x3 bone matrix."); + + prop= RNA_def_property(srna, "armature_matrix", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "arm_mat"); + RNA_def_property_array(prop, 16); + RNA_def_property_ui_text(prop, "Bone Armature-Relative Matrix", "4x4 bone matrix relative to armature."); + + prop= RNA_def_property(srna, "tail", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_float_sdna(prop, NULL, "tail"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Tail", "Location of tail end of the bone."); + + prop= RNA_def_property(srna, "armature_tail", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_float_sdna(prop, NULL, "arm_tail"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Armature-Relative Tail", "Location of tail end of the bone relative to armature."); + + prop= RNA_def_property(srna, "head", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_float_sdna(prop, NULL, "head"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Head", "Location of head end of the bone."); + + prop= RNA_def_property(srna, "armature_head", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_float_sdna(prop, NULL, "arm_head"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Armature-Relative Head", "Location of head end of the bone relative to armature."); } static void rna_def_edit_bone(BlenderRNA *brna) @@ -520,29 +558,43 @@ static void rna_def_edit_bone(BlenderRNA *brna) RNA_define_verify_sdna(1); } -void rna_def_armature(BlenderRNA *brna) +static void rna_def_armature(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; static EnumPropertyItem prop_drawtype_items[] = { - {ARM_OCTA, "OCTAHEDRAL", 0, "Octahedral", "Draw bones as octahedral shape (default)."}, - {ARM_LINE, "STICK", 0, "Stick", "Draw bones as simple 2D lines with dots."}, - {ARM_B_BONE, "BBONE", 0, "B-Bone", "Draw bones as boxes, showing subdivision and B-Splines"}, - {ARM_ENVELOPE, "ENVELOPE", 0, "Envelope", "Draw bones as extruded spheres, showing defomation influence volume."}, + {ARM_OCTA, "OCTAHEDRAL", 0, "Octahedral", "Display bones as octahedral shape (default)."}, + {ARM_LINE, "STICK", 0, "Stick", "Display bones as simple 2D lines with dots."}, + {ARM_B_BONE, "BBONE", 0, "B-Bone", "Display bones as boxes, showing subdivision and B-Splines"}, + {ARM_ENVELOPE, "ENVELOPE", 0, "Envelope", "Display bones as extruded spheres, showing defomation influence volume."}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem prop_ghost_type_items[] = { - {ARM_GHOST_CUR, "CURRENT_FRAME", 0, "Around Current Frame", "Draw Ghosts of poses within a fixed number of frames around the current frame."}, - {ARM_GHOST_RANGE, "RANGE", 0, "In Range", "Draw Ghosts of poses within specified range."}, - {ARM_GHOST_KEYS, "KEYS", 0, "On Keyframes", "Draw Ghosts of poses on Keyframes."}, + {ARM_GHOST_CUR, "CURRENT_FRAME", 0, "Around Frame", "Display Ghosts of poses within a fixed number of frames around the current frame."}, + {ARM_GHOST_RANGE, "RANGE", 0, "In Range", "Display Ghosts of poses within specified range."}, + {ARM_GHOST_KEYS, "KEYS", 0, "On Keyframes", "Display Ghosts of poses on Keyframes."}, + {0, NULL, 0, NULL, NULL}}; + static const EnumPropertyItem prop_paths_type_items[]= { + {ARM_PATH_ACFRA, "CURRENT_FRAME", 0, "Around Frame", "Display Paths of poses within a fixed number of frames around the current frame."}, + {0, "RANGE", 0, "In Range", "Display Paths of poses within specified range."}, + {0, NULL, 0, NULL, NULL}}; + static const EnumPropertyItem prop_paths_location_items[]= { + {ARM_PATH_HEADS, "HEADS", 0, "Heads", "Calculate bone paths from heads"}, + {0, "TAILS", 0, "Tails", "Calculate bone paths from tails"}, + {0, NULL, 0, NULL, NULL}}; + static const EnumPropertyItem prop_pose_position_items[]= { + {0, "POSE_POSITION", 0, "Pose Position", "Show armature in posed state."}, + {ARM_RESTPOS, "REST_POSITION", 0, "Rest Position", "Show Armature in binding pose state. No posing possible."}, {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "Armature", "ID"); RNA_def_struct_ui_text(srna, "Armature", "Armature datablock containing a hierarchy of bones, usually used for rigging characters."); RNA_def_struct_ui_icon(srna, ICON_ARMATURE_DATA); - RNA_def_struct_sdna(srna, "bArmature"); + /* Animation Data */ + rna_def_animdata_common(srna); + /* Collections */ prop= RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "bonebase", NULL); @@ -556,6 +608,17 @@ void rna_def_armature(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Edit Bones", ""); /* Enum values */ +// prop= RNA_def_property(srna, "rest_position", PROP_BOOLEAN, PROP_NONE); +// RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_RESTPOS); +// RNA_def_property_ui_text(prop, "Rest Position", "Show Armature in Rest Position. No posing possible."); +// RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + + prop= RNA_def_property(srna, "pose_position", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, prop_pose_position_items); + RNA_def_property_ui_text(prop, "Pose Position", "Show armature in binding pose or final posed state."); + RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + prop= RNA_def_property(srna, "drawtype", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_drawtype_items); RNA_def_property_ui_text(prop, "Draw Type", ""); @@ -564,7 +627,19 @@ void rna_def_armature(BlenderRNA *brna) prop= RNA_def_property(srna, "ghost_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "ghosttype"); RNA_def_property_enum_items(prop, prop_ghost_type_items); - RNA_def_property_ui_text(prop, "Ghost Drawing", "Method of Onion-skinning for active Action"); + RNA_def_property_ui_text(prop, "Ghost Type", "Method of Onion-skinning for active Action"); + RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); + + prop= RNA_def_property(srna, "paths_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "pathflag"); + RNA_def_property_enum_items(prop, prop_paths_type_items); + RNA_def_property_ui_text(prop, "Paths Type", "Type of range to show for Bone Paths"); + RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); + + prop= RNA_def_property(srna, "paths_location", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "pathflag"); + RNA_def_property_enum_items(prop, prop_paths_location_items); + RNA_def_property_ui_text(prop, "Paths Location", "When calculating Bone Paths, use Head or Tips"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); /* Boolean values */ @@ -574,7 +649,7 @@ void rna_def_armature(BlenderRNA *brna) RNA_def_property_array(prop, 16); RNA_def_property_ui_text(prop, "Visible Layers", "Armature layer visibility."); RNA_def_property_boolean_funcs(prop, NULL, "rna_Armature_layer_set"); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, NULL); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); /* layer protection */ @@ -585,10 +660,7 @@ void rna_def_armature(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); /* flag */ - prop= RNA_def_property(srna, "rest_position", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_RESTPOS); - RNA_def_property_ui_text(prop, "Rest Position", "Show Armature in Rest Position. No posing possible."); - RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + prop= RNA_def_property(srna, "draw_axes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_DRAWAXES); @@ -626,8 +698,8 @@ void rna_def_armature(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); prop= RNA_def_property(srna, "ghost_only_selected", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ARM_GHOST_ONLYSEL); - RNA_def_property_ui_text(prop, "Draw Ghosts on Selected Keyframes Only", ""); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_GHOST_ONLYSEL); + RNA_def_property_ui_text(prop, "Draw Ghosts on Selected Bones Only", ""); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); /* deformflag */ @@ -672,15 +744,6 @@ void rna_def_armature(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Paths Show Keyframe Numbers", "When drawing Armature in Pose Mode, show frame numbers of Keyframes on Bone Paths"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - prop= RNA_def_property(srna, "paths_show_around_current_frame", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "pathflag", ARM_PATH_ACFRA); - RNA_def_property_ui_text(prop, "Paths Around Current Frame", "When drawing Armature in Pose Mode, only show section of Bone Paths that falls around current frame"); - RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - - prop= RNA_def_property(srna, "paths_calculate_head_positions", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "pathflag", ARM_PATH_HEADS); - RNA_def_property_ui_text(prop, "Paths Use Heads", "When calculating Bone Paths, use Head locations instead of Tips"); - RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); /* Number fields */ /* ghost/onionskining settings */ diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 612863e1ab9..15125795e01 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * Contributor(s): Blender Foundation (2008), Juho Vepsäläinen + * Contributor(s): Blender Foundation (2008), Juho Veps�l�inen * * ***** END GPL LICENSE BLOCK ***** */ @@ -89,7 +89,7 @@ static void rna_Brush_active_texture_set(PointerRNA *ptr, PointerRNA value) #else -void rna_def_brush(BlenderRNA *brna) +static void rna_def_brush(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -133,11 +133,11 @@ void rna_def_brush(BlenderRNA *brna) RNA_def_property_range(prop, 1, 200); RNA_def_property_ui_text(prop, "Size", "Diameter of the brush."); - prop= RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "innerradius"); + prop= RNA_def_property(srna, "jitter", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "jitter"); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Falloff", "Falloff radius of the brush."); - + RNA_def_property_ui_text(prop, "Jitter", "Jitter the position of the brush while painting."); + prop= RNA_def_property(srna, "spacing", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "spacing"); RNA_def_property_range(prop, 1.0f, 100.0f); @@ -166,51 +166,51 @@ void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Strength", "The amount of pressure on the brush."); /* flag */ - prop= RNA_def_property(srna, "airbrush", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_airbrush", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_AIRBRUSH); RNA_def_property_ui_text(prop, "Airbrush", "Keep applying paint effect while holding mouse (spray)."); - prop= RNA_def_property(srna, "wrap", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_wrap", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_TORUS); RNA_def_property_ui_text(prop, "Wrap", "Enable torus wrapping while painting."); - prop= RNA_def_property(srna, "strength_pressure", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_strength_pressure", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ALPHA_PRESSURE); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Strength Pressure", "Enable tablet pressure sensitivity for strength."); - prop= RNA_def_property(srna, "size_pressure", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_size_pressure", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SIZE_PRESSURE); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Size Pressure", "Enable tablet pressure sensitivity for size."); - prop= RNA_def_property(srna, "falloff_pressure", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RAD_PRESSURE); + prop= RNA_def_property(srna, "use_jitter_pressure", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_JITTER_PRESSURE); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); - RNA_def_property_ui_text(prop, "Falloff Pressure", "Enable tablet pressure sensitivity for falloff."); - - prop= RNA_def_property(srna, "spacing_pressure", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text(prop, "Jitter Pressure", "Enable tablet pressure sensitivity for jitter."); + + prop= RNA_def_property(srna, "use_spacing_pressure", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SPACING_PRESSURE); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text(prop, "Spacing Pressure", "Enable tablet pressure sensitivity for spacing."); - prop= RNA_def_property(srna, "rake", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_rake", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RAKE); RNA_def_property_ui_text(prop, "Rake", "Rotate the brush texture to match the stroke direction."); - prop= RNA_def_property(srna, "anchored", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_anchor", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ANCHORED); RNA_def_property_ui_text(prop, "Anchored", "Keep the brush anchored to the initial location."); - prop= RNA_def_property(srna, "space", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_space", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SPACE); RNA_def_property_ui_text(prop, "Space", "Limit brush application to the distance specified by spacing."); - prop= RNA_def_property(srna, "smooth_stroke", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_smooth_stroke", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SMOOTH_STROKE); RNA_def_property_ui_text(prop, "Smooth Stroke", "Brush lags behind mouse and follows a smoother path."); - prop= RNA_def_property(srna, "persistent", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "use_persistent", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_PERSISTENT); RNA_def_property_ui_text(prop, "Persistent", "Sculpts on a persistent layer of the mesh."); @@ -219,7 +219,8 @@ void rna_def_brush(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_FIXED_TEX); RNA_def_property_ui_text(prop, "Fixed Texture", "Keep texture origin in fixed position.");*/ - prop= RNA_def_property(srna, "curve", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Curve", "Editable falloff curve."); /* texture */ diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 9c33b0afb00..eaf647e02a2 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -62,7 +62,7 @@ void RNA_def_camera(BlenderRNA *brna) /* Number values */ - prop= RNA_def_property(srna, "passepartout_alpha", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "passepartout_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "passepartalpha"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Passepartout Alpha", "Opacity (alpha) of the darkened overlay in Camera view."); diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 420add2622a..4cef6fa481f 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -216,13 +216,15 @@ static void rna_def_curvemapping(BlenderRNA *brna) RNA_def_property_struct_type(prop, "CurveMap"); RNA_def_property_ui_text(prop, "Curves", ""); - prop= RNA_def_property(srna, "black_level", PROP_FLOAT, PROP_COLOR); + prop= RNA_def_property(srna, "black_level", PROP_FLOAT, PROP_RGB); RNA_def_property_float_sdna(prop, NULL, "black"); + RNA_def_property_range(prop, -1000.0f, 1000.0f); RNA_def_property_ui_text(prop, "Black Level", "For RGB curves, the color that black is mapped to"); RNA_def_property_float_funcs(prop, NULL, "rna_CurveMapping_black_level_set", NULL); - prop= RNA_def_property(srna, "white_level", PROP_FLOAT, PROP_COLOR); + prop= RNA_def_property(srna, "white_level", PROP_FLOAT, PROP_RGB); RNA_def_property_float_sdna(prop, NULL, "white"); + RNA_def_property_range(prop, -1000.0f, 1000.0f); RNA_def_property_ui_text(prop, "White Level", "For RGB curves, the color that white is mapped to"); RNA_def_property_float_funcs(prop, NULL, "rna_CurveMapping_white_level_set", NULL); } diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 815023ee315..b630e61a680 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -33,6 +33,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "ED_object.h" #include "WM_types.h" EnumPropertyItem constraint_type_items[] ={ @@ -80,6 +81,19 @@ EnumPropertyItem space_object_items[] = { {1, "LOCAL", 0, "Local (Without Parent) Space", ""}, {0, NULL, 0, NULL, NULL}}; +EnumPropertyItem constraint_ik_type_items[] ={ + {CONSTRAINT_IK_COPYPOSE, "COPY_POSE", 0, "Copy Pose", ""}, + {CONSTRAINT_IK_DISTANCE, "DISTANCE", 0, "Distance", ""}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem constraint_distance_items[] = { + {LIMITDIST_INSIDE, "LIMITDIST_INSIDE", 0, "Inside", ""}, + {LIMITDIST_OUTSIDE, "LIMITDIST_OUTSIDE", 0, "Outside", ""}, + {LIMITDIST_ONSURFACE, "LIMITDIST_ONSURFACE", 0, "On Surface", ""}, + {0, NULL, 0, NULL, NULL} +}; + #ifdef RNA_RUNTIME #include "BKE_action.h" @@ -89,7 +103,7 @@ EnumPropertyItem space_object_items[] = { #include "ED_object.h" -StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr) +static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr) { bConstraint *con= (bConstraint*)ptr->data; @@ -160,24 +174,12 @@ static char *rna_Constraint_path(PointerRNA *ptr) static void rna_Constraint_update(bContext *C, PointerRNA *ptr) { - Object *ob= ptr->id.data; - - if(ob->pose) update_pose_constraint_flags(ob->pose); - - object_test_constraints(ob); - - if(ob->type==OB_ARMATURE) DAG_id_flush_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB); - else DAG_id_flush_update(&ob->id, OB_RECALC_OB); + ED_object_constraint_update(ptr->id.data); } static void rna_Constraint_dependency_update(bContext *C, PointerRNA *ptr) { - Object *ob= ptr->id.data; - - rna_Constraint_update(C, ptr); - - if(ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels - DAG_scene_sort(CTX_data_scene(C)); + ED_object_constraint_dependency_update(CTX_data_scene(C), ptr->id.data); } static void rna_Constraint_influence_update(bContext *C, PointerRNA *ptr) @@ -190,6 +192,24 @@ static void rna_Constraint_influence_update(bContext *C, PointerRNA *ptr) rna_Constraint_update(C, ptr); } +static void rna_Constraint_ik_type_set(struct PointerRNA *ptr, int value) +{ + bConstraint *con = ptr->data; + bKinematicConstraint *ikdata = con->data; + + if (ikdata->type != value) { + // the type of IK constraint has changed, set suitable default values + // in case constraints reuse same fields incompatible + switch (value) { + case CONSTRAINT_IK_COPYPOSE: + break; + case CONSTRAINT_IK_DISTANCE: + break; + } + ikdata->type = value; + } +} + static EnumPropertyItem *rna_Constraint_owner_space_itemf(bContext *C, PointerRNA *ptr, int *free) { Object *ob= (Object*)ptr->id.data; @@ -253,6 +273,22 @@ static EnumPropertyItem *rna_Constraint_target_space_itemf(bContext *C, PointerR return space_object_items; } +static void rna_ActionConstraint_minmax_range(PointerRNA *ptr, float *min, float *max) +{ + bConstraint *con= (bConstraint*)ptr->data; + bActionConstraint *acon = (bActionConstraint *)con->data; + + /* 0, 1, 2 = magic numbers for rotX, rotY, rotZ */ + if (ELEM3(acon->type, 0, 1, 2)) { + *min= -90.f; + *max= 90.f; + } else { + *min= -1000.f; + *max= 1000.f; + } +} + + #else static void rna_def_constrainttarget(BlenderRNA *brna) @@ -440,21 +476,40 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna) prop= RNA_def_property(srna, "tail", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_TIP); RNA_def_property_ui_text(prop, "Use Tail", "Include bone's tail as last element in chain."); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); prop= RNA_def_property(srna, "rotation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_ROT); RNA_def_property_ui_text(prop, "Rotation", "Chain follows rotation of target."); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); prop= RNA_def_property(srna, "targetless", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_AUTO); RNA_def_property_ui_text(prop, "Targetless", "Use targetless IK."); - RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); prop= RNA_def_property(srna, "stretch", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_STRETCH); RNA_def_property_ui_text(prop, "Stretch", "Enable IK Stretching."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "ik_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "type"); + RNA_def_property_enum_funcs(prop, NULL, "rna_Constraint_ik_type_set", NULL); + RNA_def_property_enum_items(prop, constraint_ik_type_items); + RNA_def_property_ui_text(prop, "IK Type", ""); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "limit_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, constraint_distance_items); + RNA_def_property_ui_text(prop, "Limit Mode", "Distances in relation to sphere of influence to allow."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "dist"); + RNA_def_property_range(prop, 0.0, 100.f); + RNA_def_property_ui_text(prop, "Distance", "Radius of limiting sphere."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); } @@ -575,7 +630,7 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna) srna= RNA_def_struct(brna, "CopyLocationConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Copy Location Constraint", "Copies the location of the target."); - prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, "bConstraint", "headtail"); RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); @@ -781,15 +836,17 @@ static void rna_def_constraint_action(BlenderRNA *brna) prop= RNA_def_property(srna, "maximum", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "max"); - RNA_def_property_range(prop, 0.0, 1000.f); + RNA_def_property_range(prop, -1000.f, 1000.f); RNA_def_property_ui_text(prop, "Maximum", "Maximum value for target channel range."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + RNA_def_property_float_funcs(prop, NULL, NULL, "rna_ActionConstraint_minmax_range"); prop= RNA_def_property(srna, "minimum", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "min"); - RNA_def_property_range(prop, 0.0, 1000.f); + RNA_def_property_range(prop, -1000.f, 1000.f); RNA_def_property_ui_text(prop, "Minimum", "Minimum value for target channel range."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); + RNA_def_property_float_funcs(prop, NULL, NULL, "rna_ActionConstraint_minmax_range"); } static void rna_def_constraint_locked_track(BlenderRNA *brna) @@ -875,10 +932,10 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Offset", "Offset from the position corresponding to the time frame."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); - prop= RNA_def_property(srna, "offset_percentage", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "offset_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "offset"); // XXX we might be better with another var or some hackery? RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Offset Percentage", "Percentage value defining target position along length of bone."); + RNA_def_property_ui_text(prop, "Offset Factor", "Percentage value defining target position along length of bone."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); prop= RNA_def_property(srna, "forward", PROP_ENUM, PROP_NONE); @@ -1457,12 +1514,6 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - static EnumPropertyItem distance_items[] = { - {LIMITDIST_INSIDE, "LIMITDIST_INSIDE", 0, "Inside", ""}, - {LIMITDIST_OUTSIDE, "LIMITDIST_OUTSIDE", 0, "Outside", ""}, - {LIMITDIST_ONSURFACE, "LIMITDIST_ONSURFACE", 0, "On Surface", ""}, - {0, NULL, 0, NULL, NULL}}; - srna= RNA_def_struct(brna, "LimitDistanceConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Limit Distance Constraint", "Limits the distance from target object."); RNA_def_struct_sdna_from(srna, "bDistLimitConstraint", "data"); @@ -1486,7 +1537,7 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna) prop= RNA_def_property(srna, "limit_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); - RNA_def_property_enum_items(prop, distance_items); + RNA_def_property_enum_items(prop, constraint_distance_items); RNA_def_property_ui_text(prop, "Limit Mode", "Distances in relation to sphere of influence to allow."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); } @@ -1599,12 +1650,23 @@ void RNA_def_constraint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Proxy Local", "Constraint was added in this proxy instance (i.e. did not belong to source Armature)."); /* values */ - prop= RNA_def_property(srna, "influence", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "enforce"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Influence", "Amount of influence constraint will have on the final solution."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_influence_update"); - + + /* readonly values */ + prop= RNA_def_property(srna, "lin_error", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "lin_error"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Lin error", "Amount of residual error in Blender space unit for constraints that work on position."); + + prop= RNA_def_property(srna, "rot_error", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "rot_error"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Rot error", "Amount of residual error in radiant for constraints that work on orientation."); + /* pointers */ rna_def_constrainttarget(brna); diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 121812c189c..3b6bd2255f2 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -54,6 +54,7 @@ EnumPropertyItem beztriple_interpolation_mode_items[] = { EnumPropertyItem beztriple_keyframe_type_items[] = { {BEZT_KEYTYPE_KEYFRAME, "KEYFRAME", 0, "Keyframe", ""}, {BEZT_KEYTYPE_BREAKDOWN, "BREAKDOWN", 0, "Breakdown", ""}, + {BEZT_KEYTYPE_EXTREME, "EXTREME", 0, "Extreme", ""}, {0, NULL, 0, NULL, NULL}}; #ifdef RNA_RUNTIME @@ -66,7 +67,7 @@ EnumPropertyItem beztriple_keyframe_type_items[] = { #include "WM_api.h" -StructRNA *rna_Curve_refine(PointerRNA *ptr) +static StructRNA *rna_Curve_refine(PointerRNA *ptr) { Curve *cu= (Curve*)ptr->data; short obtype= curve_type(cu); diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 6bca237e02f..cc86da18a0b 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -66,7 +66,7 @@ void rna_addtail(ListBase *listbase, void *vlink) listbase->last = link; } -void rna_remlink(ListBase *listbase, void *vlink) +static void rna_remlink(ListBase *listbase, void *vlink) { Link *link= vlink; @@ -134,7 +134,7 @@ PropertyDefRNA *rna_find_struct_property_def(StructRNA *srna, PropertyRNA *prop) if(!DefRNA.preprocess) { /* we should never get here */ - fprintf(stderr, "rna_find_property_def: only at preprocess time.\n"); + fprintf(stderr, "rna_find_struct_property_def: only at preprocess time.\n"); return NULL; } @@ -155,7 +155,8 @@ PropertyDefRNA *rna_find_struct_property_def(StructRNA *srna, PropertyRNA *prop) return NULL; } -PropertyDefRNA *rna_find_property_def(PropertyRNA *prop) +#if 0 +static PropertyDefRNA *rna_find_property_def(PropertyRNA *prop) { PropertyDefRNA *dprop; @@ -175,6 +176,7 @@ PropertyDefRNA *rna_find_property_def(PropertyRNA *prop) return NULL; } +#endif FunctionDefRNA *rna_find_function_def(FunctionRNA *func) { @@ -239,7 +241,7 @@ PropertyDefRNA *rna_find_parameter_def(PropertyRNA *parm) return NULL; } -ContainerDefRNA *rna_find_container_def(ContainerRNA *cont) +static ContainerDefRNA *rna_find_container_def(ContainerRNA *cont) { StructDefRNA *ds; FunctionDefRNA *dfunc; @@ -888,7 +890,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier fprop->softmin= 0.0f; fprop->softmax= 1.0f; } - else if(subtype == PROP_PERCENTAGE) { + else if(subtype == PROP_FACTOR) { fprop->softmin= fprop->hardmin= 0.0f; fprop->softmax= fprop->hardmax= 1.0f; } @@ -1528,7 +1530,7 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const iprop->softmax= 10000; } - if(prop->subtype == PROP_UNSIGNED || prop->subtype == PROP_PERCENTAGE) + if(prop->subtype == PROP_UNSIGNED || prop->subtype == PROP_PERCENTAGE || prop->subtype == PROP_FACTOR) iprop->hardmin= iprop->softmin= 0; } } @@ -2259,6 +2261,21 @@ PropertyRNA *RNA_def_float_percentage(StructOrFunctionRNA *cont_, const char *id return prop; } +PropertyRNA *RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identifier, float default_value, + float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax) +{ + ContainerRNA *cont= cont_; + PropertyRNA *prop; + + prop= RNA_def_property(cont, identifier, PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_default(prop, default_value); + if(hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax); + RNA_def_property_ui_text(prop, ui_name, ui_description); + RNA_def_property_ui_range(prop, softmin, softmax, 1, 3); + + return prop; +} + PropertyRNA *RNA_def_pointer(StructOrFunctionRNA *cont_, const char *identifier, const char *type, const char *ui_name, const char *ui_description) { diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index bafe83f1812..2802665c639 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -52,7 +52,7 @@ EnumPropertyItem fmodifier_type_items[] = { /* --------- */ -StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr) +static StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr) { FModifier *fcm= (FModifier *)ptr->data; @@ -460,7 +460,7 @@ static void rna_def_fmodifier_noise(BlenderRNA *brna) /* --------- */ -void rna_def_fmodifier(BlenderRNA *brna) +static void rna_def_fmodifier(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -510,7 +510,7 @@ void rna_def_fmodifier(BlenderRNA *brna) /* *********************** */ -void rna_def_drivertarget(BlenderRNA *brna) +static void rna_def_drivertarget(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -536,7 +536,7 @@ void rna_def_drivertarget(BlenderRNA *brna) RNA_def_property_ui_text(prop, "RNA Array Index", "Index to the specific property used (if applicable)"); } -void rna_def_channeldriver(BlenderRNA *brna) +static void rna_def_channeldriver(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -590,7 +590,7 @@ static void rna_def_fpoint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Point", "Point coordinates"); } -void rna_def_fcurve(BlenderRNA *brna) +static void rna_def_fcurve(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index a62002365c9..c415b3d716a 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -151,6 +151,14 @@ static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *ptr) return 32; } +static char *rna_FluidSettings_path(PointerRNA *ptr) +{ + FluidsimSettings *fss = (FluidsimSettings*)ptr->data; + ModifierData *md= (ModifierData *)fss->fmd; + + return BLI_sprintfN("modifiers[%s].settings", md->name); +} + #else static void rna_def_fluidsim_slip(StructRNA *srna) @@ -509,6 +517,7 @@ void RNA_def_fluidsim(BlenderRNA *brna) srna= RNA_def_struct(brna, "FluidSettings", NULL); RNA_def_struct_sdna(srna, "FluidsimSettings"); RNA_def_struct_refine_func(srna, "rna_FluidSettings_refine"); + RNA_def_struct_path_func(srna, "rna_FluidSettings_path"); RNA_def_struct_ui_text(srna, "Fluid Simulation Settings", "Fluid simulation settings for an object taking part in the simulation."); prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 15f5ef7884f..2a4ff112c3c 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -48,7 +48,7 @@ static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr) return 1; } -void rna_GPencilLayer_active_set(PointerRNA *ptr, int value) +static void rna_GPencilLayer_active_set(PointerRNA *ptr, int value) { bGPdata *gpd= ptr->id.data; bGPDlayer *gpl= ptr->data; @@ -68,7 +68,7 @@ void rna_GPencilLayer_active_set(PointerRNA *ptr, int value) #else -void rna_def_gpencil_stroke_point(BlenderRNA *brna) +static void rna_def_gpencil_stroke_point(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -88,7 +88,7 @@ void rna_def_gpencil_stroke_point(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pressure", "Pressure of tablet at point when drawing it."); } -void rna_def_gpencil_stroke(BlenderRNA *brna) +static void rna_def_gpencil_stroke(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -107,7 +107,7 @@ void rna_def_gpencil_stroke(BlenderRNA *brna) // TODO... } -void rna_def_gpencil_frame(BlenderRNA *brna) +static void rna_def_gpencil_frame(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -138,7 +138,7 @@ void rna_def_gpencil_frame(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Selected", "Frame is selected for editing in the DopeSheet."); } -void rna_def_gpencil_layer(BlenderRNA *brna) +static void rna_def_gpencil_layer(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -215,7 +215,7 @@ void rna_def_gpencil_layer(BlenderRNA *brna) } -void rna_def_gpencil_data(BlenderRNA *brna) +static void rna_def_gpencil_data(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c index 31bc6ccc74b..dddc2062f07 100644 --- a/source/blender/makesrna/intern/rna_group.c +++ b/source/blender/makesrna/intern/rna_group.c @@ -33,7 +33,7 @@ #ifdef RNA_RUNTIME -PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter) +static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter) { ListBaseIterator *internal= iter->internal; diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 4d04f4ee1f3..4c2689d4f64 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -37,6 +37,14 @@ #include "WM_types.h" +static EnumPropertyItem image_source_items[]= { + {IMA_SRC_FILE, "FILE", 0, "File", "Single image file"}, + {IMA_SRC_SEQUENCE, "SEQUENCE", 0, "Sequence", "Multiple image files, as a sequence"}, + {IMA_SRC_MOVIE, "MOVIE", 0, "Movie", "Movie file"}, + {IMA_SRC_GENERATED, "GENERATED", 0, "Generated", "Generated image"}, + {IMA_SRC_VIEWER, "VIEWER", 0, "Viewer", "Compositing node viewer"}, + {0, NULL, 0, NULL, NULL}}; + #ifdef RNA_RUNTIME #include "IMB_imbuf_types.h" @@ -66,6 +74,99 @@ static int rna_Image_dirty_get(PointerRNA *ptr) return 0; } +static void rna_Image_source_update(bContext *C, PointerRNA *ptr) +{ + Image *ima= ptr->id.data; + BKE_image_signal(ima, NULL, IMA_SIGNAL_SRC_CHANGE); +} + +static void rna_Image_fields_update(bContext *C, PointerRNA *ptr) +{ + Image *ima= ptr->id.data; + ImBuf *ibuf; + + ibuf= BKE_image_get_ibuf(ima, NULL); + + if(ibuf) { + short nr= 0; + + if(!(ima->flag & IMA_FIELDS) && (ibuf->flags & IB_fields)) nr= 1; + if((ima->flag & IMA_FIELDS) && !(ibuf->flags & IB_fields)) nr= 1; + + if(nr) + BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); + } +} + +static void rna_Image_reload_update(bContext *C, PointerRNA *ptr) +{ + Image *ima= ptr->id.data; + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + printf("reload %p\n", ima); +} + +static void rna_Image_generated_update(bContext *C, PointerRNA *ptr) +{ + Image *ima= ptr->id.data; + BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); +} + +static void rna_ImageUser_update(bContext *C, PointerRNA *ptr) +{ + Scene *scene= CTX_data_scene(C); + ImageUser *iuser= ptr->data; + + BKE_image_user_calc_imanr(iuser, scene->r.cfra, 0); +} + +static EnumPropertyItem *rna_Image_source_itemf(bContext *C, PointerRNA *ptr, int *free) +{ + Image *ima= (Image*)ptr->data; + EnumPropertyItem *item= NULL; + int totitem= 0; + + if(C==NULL) /* needed for doc generation */ + return image_source_items; + + if(ima->source == IMA_SRC_VIEWER) { + RNA_enum_items_add_value(&item, &totitem, image_source_items, IMA_SRC_VIEWER); + } + else { + RNA_enum_items_add_value(&item, &totitem, image_source_items, IMA_SRC_FILE); + RNA_enum_items_add_value(&item, &totitem, image_source_items, IMA_SRC_SEQUENCE); + RNA_enum_items_add_value(&item, &totitem, image_source_items, IMA_SRC_MOVIE); + RNA_enum_items_add_value(&item, &totitem, image_source_items, IMA_SRC_GENERATED); + } + + RNA_enum_item_end(&item, &totitem); + *free= 1; + + return item; +} + +static int rna_Image_has_data_get(PointerRNA *ptr) +{ + Image *im= (Image*)ptr->data; + + if (im->ibufs.first) + return 1; + + return 0; +} + +static int rna_Image_depth_get(PointerRNA *ptr) +{ + Image *im= (Image*)ptr->data; + ImBuf *ibuf= BKE_image_get_ibuf(im, NULL); + + if (!ibuf) return 0; + + if (ibuf->rect_float) + return 128; + + return ibuf->depth; +} + #else static void rna_def_imageuser(BlenderRNA *brna) @@ -79,29 +180,35 @@ static void rna_def_imageuser(BlenderRNA *brna) prop= RNA_def_property(srna, "auto_refresh", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_ANIM_ALWAYS); RNA_def_property_ui_text(prop, "Auto Refresh", "Always refresh image on frame changes."); + RNA_def_property_update(prop, 0, "rna_ImageUser_update"); /* animation */ prop= RNA_def_property(srna, "cyclic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cycl", 0); RNA_def_property_ui_text(prop, "Cyclic", "Cycle the images in the movie."); + RNA_def_property_update(prop, 0, "rna_ImageUser_update"); prop= RNA_def_property(srna, "frames", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, MAXFRAMEF); RNA_def_property_ui_text(prop, "Frames", "Sets the number of images of a movie to use."); + RNA_def_property_update(prop, 0, "rna_ImageUser_update"); prop= RNA_def_property(srna, "offset", PROP_INT, PROP_NONE); RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF); RNA_def_property_ui_text(prop, "Offset", "Offsets the number of the frame to use in the animation."); + RNA_def_property_update(prop, 0, "rna_ImageUser_update"); prop= RNA_def_property(srna, "start_frame", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "sfra"); RNA_def_property_range(prop, 1.0f, MAXFRAMEF); RNA_def_property_ui_text(prop, "Start Frame", "Sets the global starting frame of the movie."); + RNA_def_property_update(prop, 0, "rna_ImageUser_update"); prop= RNA_def_property(srna, "fields_per_frame", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "fie_ima"); RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF); RNA_def_property_ui_text(prop, "Fields per Frame", "The number of fields per rendered frame (2 fields is 1 image)."); + RNA_def_property_update(prop, 0, "rna_ImageUser_update"); prop= RNA_def_property(srna, "multilayer_layer", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "layer"); @@ -121,25 +228,22 @@ static void rna_def_image(BlenderRNA *brna) static const EnumPropertyItem prop_type_items[]= { {IMA_TYPE_IMAGE, "IMAGE", 0, "Image", ""}, {IMA_TYPE_MULTILAYER, "MULTILAYER", 0, "Multilayer", ""}, - {IMA_TYPE_UV_TEST, "UVTEST", 0, "UV Test", ""}, - {IMA_TYPE_R_RESULT, "RENDERRESULT", 0, "Render Result", ""}, + {IMA_TYPE_UV_TEST, "UV_TEST", 0, "UV Test", ""}, + {IMA_TYPE_R_RESULT, "RENDER_RESULT", 0, "Render Result", ""}, {IMA_TYPE_COMPOSITE, "COMPOSITING", 0, "Compositing", ""}, {0, NULL, 0, NULL, NULL}}; - static const EnumPropertyItem prop_source_items[]= { - {IMA_SRC_FILE, "FILE", 0, "File", "Single image file"}, - {IMA_SRC_SEQUENCE, "SEQUENCE", 0, "Sequence", "Multiple image files, as a sequence"}, - {IMA_SRC_MOVIE, "MOVIE", 0, "Movie", "Movie file"}, - {IMA_SRC_GENERATED, "GENERATED", 0, "Generated", "Generated image"}, - {IMA_SRC_VIEWER, "VIEWER", 0, "Viewer", "Compositing node viewer"}, - {0, NULL, 0, NULL, NULL}}; static const EnumPropertyItem prop_generated_type_items[]= { {0, "BLANK", 0, "Blank", "Generate a blank image"}, - {1, "UVTESTGRID", 0, "UV Test Grid", "Generated grid to test UV mappings"}, + {1, "UVGRID", 0, "UV Grid", "Generated grid to test UV mappings"}, {0, NULL, 0, NULL, NULL}}; static const EnumPropertyItem prop_mapping_items[]= { {0, "UV", 0, "UV Coordinates", "Use UV coordinates for mapping the image"}, {IMA_REFLECT, "REFLECTION", 0, "Reflection", "Use reflection mapping for mapping the image"}, {0, NULL, 0, NULL, NULL}}; + static const EnumPropertyItem prop_field_order_items[]= { + {0, "EVEN", 0, "Even", "Even Fields first"}, + {IMA_STD_FIELD, "ODD", 0, "Odd", "Odd Fields first"}, + {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "Image", "ID"); RNA_def_struct_ui_text(srna, "Image", "Image datablock referencing an external or packed image."); @@ -147,36 +251,36 @@ static void rna_def_image(BlenderRNA *brna) prop= RNA_def_property(srna, "filename", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "name"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* imagechanged */ RNA_def_property_ui_text(prop, "Filename", "Image/Movie file name."); - RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); + RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_reload_update"); prop= RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, prop_source_items); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* imagechanged */ + RNA_def_property_enum_items(prop, image_source_items); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Image_source_itemf"); RNA_def_property_ui_text(prop, "Source", "Where the image comes from."); - RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); + RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_source_update"); prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_type_items); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* imagechanged */ + RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Type", "How to generate the image."); RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); prop= RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "packedfile"); RNA_def_property_ui_text(prop, "Packed File", ""); - + + prop= RNA_def_property(srna, "field_order", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, prop_field_order_items); + RNA_def_property_ui_text(prop, "Field Order", "Order of video fields. Select which lines are displayed first."); + RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); + /* booleans */ prop= RNA_def_property(srna, "fields", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_FIELDS); RNA_def_property_ui_text(prop, "Fields", "Use fields of the image."); - RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); - - prop= RNA_def_property(srna, "odd_fields", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_STD_FIELD); - RNA_def_property_ui_text(prop, "Odd Fields", "Standard field toggle."); - RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); + RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_fields_update"); prop= RNA_def_property(srna, "antialias", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_ANTIALI); @@ -198,19 +302,19 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "gen_type"); RNA_def_property_enum_items(prop, prop_generated_type_items); RNA_def_property_ui_text(prop, "Generated Type", "Generated image type."); - RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); + RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_generated_update"); prop= RNA_def_property(srna, "generated_width", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gen_x"); RNA_def_property_range(prop, 1, 16384); RNA_def_property_ui_text(prop, "Generated Width", "Generated image width."); - RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); + RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_generated_update"); prop= RNA_def_property(srna, "generated_height", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gen_y"); RNA_def_property_range(prop, 1, 16384); RNA_def_property_ui_text(prop, "Generated Height", "Generated image height."); - RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); + RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_generated_update"); /* realtime properties */ prop= RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE); @@ -275,6 +379,22 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_CLAMP_V); RNA_def_property_ui_text(prop, "Clamp Y", "Disable texture repeating vertically."); RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL); + + /* + Image.has_data and Image.depth are temporary, + Update import_obj.py when they are replaced (Arystan) + */ + prop= RNA_def_property(srna, "has_data", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_Image_has_data_get", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Has data", "True if this image has data."); + + prop= RNA_def_property(srna, "depth", PROP_INT, PROP_NONE); + RNA_def_property_int_funcs(prop, "rna_Image_depth_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Depth", "Image bit depth."); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + RNA_api_image(srna); } void RNA_def_image(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c new file mode 100644 index 00000000000..2bb7905fc03 --- /dev/null +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -0,0 +1,101 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Arystanbek Dyussenov + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "RNA_define.h" +#include "RNA_types.h" + +#ifdef RNA_RUNTIME + +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_utildefines.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; +} + +char *rna_Image_get_abs_filename(Image *image, bContext *C) +{ + 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); + + return filename; +} + +#else + +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); +} + +#endif + diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 7de80843f27..3723c05ada0 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -200,14 +200,19 @@ void rna_Mesh_update_draw(struct bContext *C, struct PointerRNA *ptr); /* API functions */ +void RNA_api_action(StructRNA *srna); +void RNA_api_image(struct StructRNA *srna); void RNA_api_keyingset(struct StructRNA *srna); void RNA_api_main(struct StructRNA *srna); +void RNA_api_material(StructRNA *srna); void RNA_api_mesh(struct StructRNA *srna); void RNA_api_object(struct StructRNA *srna); -void RNA_api_scene(struct StructRNA *srna); +void RNA_api_scene(struct StructRNA *srna); +void RNA_api_text(struct StructRNA *srna); void RNA_api_ui_layout(struct StructRNA *srna); void RNA_api_wm(struct StructRNA *srna); + /* ID Properties */ extern StringPropertyRNA rna_IDProperty_string; diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index fbe339fe7f3..e1551404438 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -257,6 +257,11 @@ static PointerRNA rna_ShapeKey_data_get(CollectionPropertyIterator *iter) return rna_pointer_inherit_refine(&iter->parent, type, rna_iterator_array_get(iter)); } +static char *rna_ShapeKey_path(PointerRNA *ptr) +{ + return BLI_sprintfN("keys[\"%s\"]", ((KeyBlock*)ptr->data)->name); +} + static void rna_Key_update_data(bContext *C, PointerRNA *ptr) { Main *bmain= CTX_data_main(C); @@ -343,6 +348,7 @@ static void rna_def_keyblock(BlenderRNA *brna) srna= RNA_def_struct(brna, "ShapeKey", NULL); RNA_def_struct_ui_text(srna, "Shape Key", "Shape key in a shape keys datablock."); RNA_def_struct_sdna(srna, "KeyBlock"); + RNA_def_struct_path_func(srna, "rna_ShapeKey_path"); RNA_def_struct_ui_icon(srna, ICON_SHAPEKEY_DATA); prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); @@ -414,7 +420,8 @@ static void rna_def_key(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Key", "Shape keys datablock containing different shapes of geometric datablocks."); RNA_def_struct_ui_icon(srna, ICON_SHAPEKEY_DATA); - prop= RNA_def_property(srna, "reference_key", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "reference_key", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_pointer_sdna(prop, NULL, "refkey"); RNA_def_property_ui_text(prop, "Reference Key", ""); @@ -426,7 +433,8 @@ static void rna_def_key(BlenderRNA *brna) rna_def_animdata_common(srna); - prop= RNA_def_property(srna, "user", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "user", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "from"); RNA_def_property_ui_text(prop, "User", "Datablock using these shape keys."); diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 57aa1ba2736..d00a0d61bf6 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -99,7 +99,7 @@ static StructRNA* rna_Lamp_refine(struct PointerRNA *ptr) switch(la->type) { case LA_LOCAL: - return &RNA_LocalLamp; + return &RNA_PointLamp; case LA_SUN: return &RNA_SunLamp; case LA_SPOT: @@ -431,7 +431,7 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area) prop= RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "shdwr"); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Shadow Color", "Color of shadows casted by the lamp."); + RNA_def_property_ui_text(prop, "Shadow Color", "Color of shadows cast by the lamp."); RNA_def_property_update(prop, NC_LAMP|ND_LIGHTING, NULL); prop= RNA_def_property(srna, "only_shadow", PROP_BOOLEAN, PROP_NONE); @@ -477,13 +477,14 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area) RNA_def_property_update(prop, NC_LAMP|ND_LIGHTING, NULL); } -static void rna_def_local_lamp(BlenderRNA *brna) +static void rna_def_point_lamp(BlenderRNA *brna) { StructRNA *srna; - srna= RNA_def_struct(brna, "LocalLamp", "Lamp"); + srna= RNA_def_struct(brna, "PointLamp", "Lamp"); RNA_def_struct_sdna(srna, "Lamp"); - RNA_def_struct_ui_text(srna, "Local Lamp", "Omnidirectional point lamp."); + RNA_def_struct_ui_text(srna, "Point Lamp", "Omnidirectional point lamp."); + RNA_def_struct_ui_icon(srna, ICON_LAMP_POINT); rna_def_lamp_falloff(srna); rna_def_lamp_shadow(srna, 0, 0); @@ -502,6 +503,7 @@ static void rna_def_area_lamp(BlenderRNA *brna) srna= RNA_def_struct(brna, "AreaLamp", "Lamp"); RNA_def_struct_sdna(srna, "Lamp"); RNA_def_struct_ui_text(srna, "Area Lamp", "Directional area lamp."); + RNA_def_struct_ui_icon(srna, ICON_LAMP_AREA); rna_def_lamp_shadow(srna, 0, 1); @@ -571,6 +573,7 @@ static void rna_def_spot_lamp(BlenderRNA *brna) srna= RNA_def_struct(brna, "SpotLamp", "Lamp"); RNA_def_struct_sdna(srna, "Lamp"); RNA_def_struct_ui_text(srna, "Spot Lamp", "Directional cone lamp."); + RNA_def_struct_ui_icon(srna, ICON_LAMP_SPOT); rna_def_lamp_falloff(srna); rna_def_lamp_shadow(srna, 1, 0); @@ -683,11 +686,13 @@ static void rna_def_sun_lamp(BlenderRNA *brna) srna= RNA_def_struct(brna, "SunLamp", "Lamp"); RNA_def_struct_sdna(srna, "Lamp"); RNA_def_struct_ui_text(srna, "Sun Lamp", "Constant direction parallel ray lamp."); + RNA_def_struct_ui_icon(srna, ICON_LAMP_SUN); rna_def_lamp_shadow(srna, 0, 0); /* sky */ - prop= RNA_def_property(srna, "sky", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "sky", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "LampSkySettings"); RNA_def_property_pointer_funcs(prop, "rna_Lamp_sky_settings_get", NULL, NULL); RNA_def_property_ui_text(prop, "Sky Settings", "Sky related settings for sun lamps."); @@ -702,12 +707,13 @@ static void rna_def_hemi_lamp(BlenderRNA *brna) srna= RNA_def_struct(brna, "HemiLamp", "Lamp"); RNA_def_struct_sdna(srna, "Lamp"); RNA_def_struct_ui_text(srna, "Hemi Lamp", "180 degree constant lamp."); + RNA_def_struct_ui_icon(srna, ICON_LAMP_HEMI); } void RNA_def_lamp(BlenderRNA *brna) { rna_def_lamp(brna); - rna_def_local_lamp(brna); + rna_def_point_lamp(brna); rna_def_area_lamp(brna); rna_def_spot_lamp(brna); rna_def_sun_lamp(brna); diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index 344135acaff..910a15890cb 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -259,9 +259,9 @@ void RNA_def_main(BlenderRNA *brna) {"worlds", "World", "rna_Main_world_begin", "Worlds", "World datablocks.", NULL, NULL}, {"groups", "Group", "rna_Main_group_begin", "Groups", "Group datablocks.", NULL, NULL}, {"keys", "Key", "rna_Main_key_begin", "Keys", "Key datablocks.", NULL, NULL}, - {"scripts", "ID", "rna_Main_script_begin", "Scripts", "Script datablocks.", NULL, NULL}, + {"scripts", "ID", "rna_Main_script_begin", "Scripts", "Script datablocks (DEPRECATED).", NULL, NULL}, {"texts", "Text", "rna_Main_text_begin", "Texts", "Text datablocks.", NULL, NULL}, - {"sounds", "ID", "rna_Main_sound_begin", "Sounds", "Sound datablocks.", NULL, NULL}, + {"sounds", "Sound", "rna_Main_sound_begin", "Sounds", "Sound datablocks.", NULL, NULL}, {"armatures", "Armature", "rna_Main_armature_begin", "Armatures", "Armature datablocks.", NULL, NULL}, {"actions", "Action", "rna_Main_action_begin", "Actions", "Action datablocks.", NULL, NULL}, {"particles", "ParticleSettings", "rna_Main_particle_begin", "Particles", "Particle datablocks.", NULL, NULL}, diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 6d56b2b00f9..379cf75d450 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -31,23 +31,32 @@ #include "RNA_define.h" #include "RNA_types.h" +#include "RNA_enum_types.h" + +#include "DNA_object_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" #ifdef RNA_RUNTIME #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_library.h" +#include "BKE_object.h" +#include "BKE_material.h" +#include "BKE_image.h" +#include "BKE_texture.h" -#include "DNA_mesh_types.h" +#include "DNA_lamp_types.h" -Mesh *rna_Main_add_mesh(Main *main, char *name) +static Mesh *rna_Main_add_mesh(Main *main, char *name) { Mesh *me= add_mesh(name); me->id.us--; return me; } -void rna_Main_remove_mesh(Main *main, ReportList *reports, Mesh *me) +static void rna_Main_remove_mesh(Main *main, ReportList *reports, Mesh *me) { if(me->id.us == 0) free_libblock(&main->mesh, me); @@ -57,24 +66,130 @@ void rna_Main_remove_mesh(Main *main, ReportList *reports, Mesh *me) /* XXX python now has invalid pointer? */ } +static Lamp *rna_Main_add_lamp(Main *main, char *name) +{ + Lamp *la= add_lamp(name); + la->id.us--; + return la; +} + +/* +static void rna_Main_remove_lamp(Main *main, ReportList *reports, Lamp *la) +{ + if(la->id.us == 0) + free_libblock(&main->lamp, la); + else + BKE_report(reports, RPT_ERROR, "Lamp must have zero users to be removed."); +} +*/ + +static Object* rna_Main_add_object(Main *main, int type, char *name) +{ + Object *ob= add_only_object(type, name); + ob->id.us--; + return ob; +} + +/* + NOTE: the following example shows when this function should _not_ be called + + ob = bpy.data.add_object() + scene.add_object(ob) + + # ob is freed here + scene.remove_object(ob) + + # don't do this since ob is already freed! + bpy.data.remove_object(ob) +*/ +static void rna_Main_remove_object(Main *main, ReportList *reports, Object *ob) +{ + if(ob->id.us == 0) + free_libblock(&main->object, ob); + else + BKE_report(reports, RPT_ERROR, "Object must have zero users to be removed."); +} + +static Material *rna_Main_add_material(Main *main, char *name) +{ + return add_material(name); +} + +/* TODO: remove material? */ + +struct Tex *rna_Main_add_texture(Main *main, char *name) +{ + return add_texture(name); +} + +/* TODO: remove texture? */ + +struct Image *rna_Main_add_image(Main *main, char *filename) +{ + return BKE_add_image_file(filename, 0); +} + #else void RNA_api_main(StructRNA *srna) { FunctionRNA *func; - PropertyRNA *prop; + PropertyRNA *parm; + + func= RNA_def_function(srna, "add_object", "rna_Main_add_object"); + RNA_def_function_ui_description(func, "Add a new object."); + parm= RNA_def_enum(func, "type", object_type_items, 0, "", "Type of Object."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_string(func, "name", "Object", 0, "", "New name for the datablock."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "object", "Object", "", "New object."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "remove_object", "rna_Main_remove_object"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove an object if it has zero users."); + parm= RNA_def_pointer(func, "object", "Object", "", "Object to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); func= RNA_def_function(srna, "add_mesh", "rna_Main_add_mesh"); RNA_def_function_ui_description(func, "Add a new mesh."); - prop= RNA_def_string(func, "name", "Mesh", 0, "", "New name for the datablock."); - prop= RNA_def_pointer(func, "mesh", "Mesh", "", "New mesh."); - RNA_def_function_return(func, prop); + parm= RNA_def_string(func, "name", "Mesh", 0, "", "New name for the datablock."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "mesh", "Mesh", "", "New mesh."); + RNA_def_function_return(func, parm); func= RNA_def_function(srna, "remove_mesh", "rna_Main_remove_mesh"); RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a mesh if it has zero users."); - prop= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to remove."); - RNA_def_property_flag(prop, PROP_REQUIRED); + parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); + + func= RNA_def_function(srna, "add_lamp", "rna_Main_add_lamp"); + RNA_def_function_ui_description(func, "Add a new lamp."); + parm= RNA_def_string(func, "name", "Lamp", 0, "", "New name for the datablock."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "mesh", "Lamp", "", "New lamp."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "add_material", "rna_Main_add_material"); + RNA_def_function_ui_description(func, "Add a new material."); + parm= RNA_def_string(func, "name", "Material", 0, "", "New name for the datablock."); /* optional */ + parm= RNA_def_pointer(func, "material", "Material", "", "New material."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "add_texture", "rna_Main_add_texture"); + RNA_def_function_ui_description(func, "Add a new texture."); + parm= RNA_def_string(func, "name", "Tex", 0, "", "New name for the datablock."); /* optional */ + parm= RNA_def_pointer(func, "texture", "Texture", "", "New texture."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "add_image", "rna_Main_add_image"); + RNA_def_function_ui_description(func, "Add a new image."); + parm= RNA_def_string(func, "filename", "", 0, "", "Filename to load image from."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "image", "Image", "", "New image."); + RNA_def_function_return(func, parm); + } #endif diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index cd1159bc138..a6f22017aaa 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -212,7 +212,7 @@ static void rna_Material_use_specular_ramp_set(PointerRNA *ptr, int value) ma->ramp_spec= add_colorband(0); } -void rna_Material_use_nodes_set(PointerRNA *ptr, int value) +static void rna_Material_use_nodes_set(PointerRNA *ptr, int value) { Material *ma= (Material*)ptr->data; @@ -645,12 +645,12 @@ static void rna_def_material_colors(StructRNA *srna) RNA_def_property_ui_text(prop, "Mirror Color", "Mirror color of the material."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Alpha", "Alpha transparency of the material."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING_DRAW, NULL); - prop= RNA_def_property(srna, "specular_alpha", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "specular_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "spectra"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Specular Alpha", "Alpha transparency for specular areas."); @@ -667,6 +667,7 @@ static void rna_def_material_colors(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "ramp_col"); RNA_def_property_struct_type(prop, "ColorRamp"); RNA_def_property_ui_text(prop, "Diffuse Ramp", "Color ramp used to affect diffuse shading."); + RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING_DRAW, NULL); prop= RNA_def_property(srna, "use_specular_ramp", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", MA_RAMP_SPEC); @@ -678,6 +679,7 @@ static void rna_def_material_colors(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "ramp_spec"); RNA_def_property_struct_type(prop, "ColorRamp"); RNA_def_property_ui_text(prop, "Specular Ramp", "Color ramp used to affect specular shading."); + RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING_DRAW, NULL); prop= RNA_def_property(srna, "diffuse_ramp_blend", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "rampblend_col"); @@ -723,7 +725,7 @@ static void rna_def_material_diffuse(StructRNA *srna) RNA_def_property_ui_text(prop, "Diffuse Shader Model", ""); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "diffuse_intensity", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "diffuse_intensity", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "ref"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Diffuse Intensity", "Amount of diffuse reflection."); @@ -740,7 +742,7 @@ static void rna_def_material_diffuse(StructRNA *srna) RNA_def_property_ui_text(prop, "Diffuse Toon Size", "Size of diffuse toon area."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "diffuse_toon_smooth", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "diffuse_toon_smooth", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "param[1]"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Diffuse Toon Smooth", "Smoothness of diffuse toon area."); @@ -784,7 +786,7 @@ static void rna_def_material_raymirror(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Enabled", "Enable raytraced reflections."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "reflect_factor", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "reflect_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "ray_mirror"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Reflectivity", "Sets the amount mirror reflection for raytrace."); @@ -796,19 +798,19 @@ static void rna_def_material_raymirror(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Fresnel", "Power of Fresnel for mirror reflection."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "fresnel_factor", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "fresnel_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "fresnel_mir_i"); RNA_def_property_range(prop, 0.0f, 5.0f); RNA_def_property_ui_text(prop, "Fresnel Factor", "Blending factor for Fresnel."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "gloss_factor", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "gloss_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "gloss_mir"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Gloss Amount", "The shininess of the reflection. Values < 1.0 give diffuse, blurry reflections."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "gloss_anisotropic", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "gloss_anisotropic", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "aniso_gloss_mir"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Gloss Anisotropy", "The shape of the reflection, from 0.0 (circular) to 1.0 (fully stretched along the tangent."); @@ -820,7 +822,7 @@ static void rna_def_material_raymirror(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Gloss Samples", "Number of cone samples averaged for blurry reflections."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "gloss_threshold", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "gloss_threshold", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "adapt_thresh_mir"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Gloss Threshold", "Threshold for adaptive sampling. If a sample contributes less than this amount (as a percentage), sampling is stopped."); @@ -867,13 +869,13 @@ static void rna_def_material_raytra(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Fresnel", "Power of Fresnel for transparency (Ray or ZTransp)."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "fresnel_factor", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "fresnel_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "fresnel_tra_i"); RNA_def_property_range(prop, 1.0f, 5.0f); RNA_def_property_ui_text(prop, "Fresnel Factor", "Blending factor for Fresnel."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "gloss_factor", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "gloss_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "gloss_tra"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Gloss Amount", "The clarity of the refraction. Values < 1.0 give diffuse, blurry refractions."); @@ -885,7 +887,7 @@ static void rna_def_material_raytra(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Gloss Samples", "Number of cone samples averaged for blurry refractions."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "gloss_threshold", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "gloss_threshold", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "adapt_thresh_tra"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Gloss Threshold", "Threshold for adaptive sampling. If a sample contributes less than this amount (as a percentage), sampling is stopped."); @@ -897,7 +899,7 @@ static void rna_def_material_raytra(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Depth", "Maximum allowed number of light inter-refractions."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "filter", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "filter", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "filter"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Filter", "Amount to blend in the material's diffuse color in raytraced transparency (simulating absorption)."); @@ -1009,7 +1011,7 @@ static void rna_def_material_volume(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Depth Cutoff", "Stop ray marching early if transmission drops below this luminance - higher values give speedups in dense volumes at the expense of accuracy."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "density", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "density", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "density"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Density", "The base density of the volume"); @@ -1091,7 +1093,7 @@ static void rna_def_material_halo(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Hardness", "Sets the hardness of the halo."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "add", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "add", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "add"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Add", "Sets the strength of the add effect."); @@ -1237,13 +1239,13 @@ static void rna_def_material_sss(BlenderRNA *brna) RNA_def_property_ui_text(prop, "IOR", "Index of refraction (higher values are denser)."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "color_factor", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "color_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "sss_colfac"); RNA_def_property_ui_range(prop, 0, 1, 10, 3); RNA_def_property_ui_text(prop, "Color Factor", "Blend factor for SSS colors."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "texture_factor", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "texture_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "sss_texfac"); RNA_def_property_ui_range(prop, 0, 1, 10, 3); RNA_def_property_ui_text(prop, "Texture Factor", "Texture scatting blend factor."); @@ -1267,7 +1269,7 @@ static void rna_def_material_sss(BlenderRNA *brna) RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); } -void rna_def_material_specularity(StructRNA *srna) +static void rna_def_material_specularity(StructRNA *srna) { PropertyRNA *prop; @@ -1285,7 +1287,7 @@ void rna_def_material_specularity(StructRNA *srna) RNA_def_property_ui_text(prop, "Specular Shader Model", ""); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "specular_intensity", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "specular_intensity", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "spec"); RNA_def_property_range(prop, 0, 1); RNA_def_property_ui_text(prop, "Specular Intensity", ""); @@ -1314,7 +1316,7 @@ void rna_def_material_specularity(StructRNA *srna) RNA_def_property_ui_text(prop, "Specular Toon Size", "Size of specular toon area."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "specular_toon_smooth", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "specular_toon_smooth", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "param[3]"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Specular Toon Smooth", "Ssmoothness of specular toon area."); @@ -1327,7 +1329,7 @@ void rna_def_material_specularity(StructRNA *srna) RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); } -void rna_def_material_strand(BlenderRNA *brna) +static void rna_def_material_strand(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -1394,7 +1396,7 @@ void rna_def_material_strand(BlenderRNA *brna) RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); } -void rna_def_material_physics(BlenderRNA *brna) +static void rna_def_material_physics(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -1472,7 +1474,7 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Transparency Method", "Method to use for rendering transparency."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "ambient", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "ambient", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "amb"); RNA_def_property_range(prop, 0, 1); RNA_def_property_ui_text(prop, "Ambient", "Amount of global ambient color the material receives."); @@ -1484,7 +1486,7 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Emit", "Amount of light to emit."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); - prop= RNA_def_property(srna, "translucency", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "translucency", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0, 1); RNA_def_property_ui_text(prop, "Translucency", "Amount of diffuse shading on the back side."); RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); @@ -1509,7 +1511,7 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_range(prop, 0, 10); RNA_def_property_ui_text(prop, "Shadow Buffer Bias", "Factor to multiply shadow buffer bias with (0 is ignore.)"); - prop= RNA_def_property(srna, "shadow_casting_alpha", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "shadow_casting_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "shad_alpha"); RNA_def_property_range(prop, 0.001, 1); RNA_def_property_ui_text(prop, "Shadow Casting Alpha", "Shadow casting alpha, only in use for Irregular Shadowbuffer."); @@ -1615,37 +1617,44 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_update(prop, NC_MATERIAL|ND_SHADING, NULL); /* nested structs */ - prop= RNA_def_property(srna, "raytrace_mirror", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "raytrace_mirror", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "MaterialRaytraceMirror"); RNA_def_property_pointer_funcs(prop, "rna_Material_mirror_get", NULL, NULL); RNA_def_property_ui_text(prop, "Raytrace Mirror", "Raytraced reflection settings for the material."); - prop= RNA_def_property(srna, "raytrace_transparency", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "raytrace_transparency", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "MaterialRaytraceTransparency"); RNA_def_property_pointer_funcs(prop, "rna_Material_transp_get", NULL, NULL); RNA_def_property_ui_text(prop, "Raytrace Transparency", "Raytraced reflection settings for the material."); - prop= RNA_def_property(srna, "volume", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "volume", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "vol"); RNA_def_property_struct_type(prop, "MaterialVolume"); RNA_def_property_ui_text(prop, "Volume", "Volume settings for the material."); - prop= RNA_def_property(srna, "halo", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "halo", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "MaterialHalo"); RNA_def_property_pointer_funcs(prop, "rna_Material_halo_get", NULL, NULL); RNA_def_property_ui_text(prop, "Halo", "Halo settings for the material."); - prop= RNA_def_property(srna, "subsurface_scattering", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "subsurface_scattering", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "MaterialSubsurfaceScattering"); RNA_def_property_pointer_funcs(prop, "rna_Material_sss_get", NULL, NULL); RNA_def_property_ui_text(prop, "Subsurface Scattering", "Subsurface scattering settings for the material."); - prop= RNA_def_property(srna, "strand", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "strand", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "MaterialStrand"); RNA_def_property_pointer_funcs(prop, "rna_Material_strand_get", NULL, NULL); RNA_def_property_ui_text(prop, "Strand", "Strand settings for the material."); - prop= RNA_def_property(srna, "physics", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "physics", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "MaterialPhysics"); RNA_def_property_pointer_funcs(prop, "rna_Material_physics_get", NULL, NULL); RNA_def_property_ui_text(prop, "Physics", "Game physics settings."); @@ -1679,6 +1688,8 @@ void RNA_def_material(BlenderRNA *brna) rna_def_material_mtex(brna); rna_def_material_strand(brna); rna_def_material_physics(brna); + + RNA_api_material(srna); } void rna_def_mtex_common(StructRNA *srna, const char *begin, const char *activeget, const char *activeset, const char *structname) diff --git a/source/blender/makesrna/intern/rna_material_api.c b/source/blender/makesrna/intern/rna_material_api.c new file mode 100644 index 00000000000..aa28b6b923c --- /dev/null +++ b/source/blender/makesrna/intern/rna_material_api.c @@ -0,0 +1,126 @@ +/** + * + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "RNA_define.h" +#include "RNA_types.h" + +#include "DNA_material_types.h" + +#ifdef RNA_RUNTIME + +#include "BKE_material.h" +#include "BKE_texture.h" + +/* + Adds material to the first free texture slot. + If all slots are busy, replaces the first. +*/ +static void rna_Material_add_texture(Material *ma, Tex *tex, int mapto, int texco) +{ + int i; + MTex *mtex; + int slot= -1; + + for (i= 0; i < MAX_MTEX; i++) { + if (!ma->mtex[i]) { + slot= i; + break; + } + } + + if (slot == -1) + slot= 0; + + if (ma->mtex[slot]) { + ma->mtex[slot]->tex->id.us--; + } + else { + ma->mtex[slot]= add_mtex(); + } + + mtex= ma->mtex[slot]; + + mtex->tex= tex; + id_us_plus(&tex->id); + + mtex->texco= mapto; + mtex->mapto= texco; +} + +#else + +void RNA_api_material(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + /* copied from rna_def_material_mtex (rna_material.c) */ + static EnumPropertyItem prop_texture_coordinates_items[] = { + {TEXCO_GLOB, "GLOBAL", 0, "Global", "Uses global coordinates for the texture coordinates."}, + {TEXCO_OBJECT, "OBJECT", 0, "Object", "Uses linked object's coordinates for texture coordinates."}, + {TEXCO_UV, "UV", 0, "UV", "Uses UV coordinates for texture coordinates."}, + {TEXCO_ORCO, "ORCO", 0, "Generated", "Uses the original undeformed coordinates of the object."}, + {TEXCO_STRAND, "STRAND", 0, "Strand", "Uses normalized strand texture coordinate (1D)."}, + {TEXCO_STICKY, "STICKY", 0, "Sticky", "Uses mesh's sticky coordinates for the texture coordinates."}, + {TEXCO_WINDOW, "WINDOW", 0, "Window", "Uses screen coordinates as texture coordinates."}, + {TEXCO_NORM, "NORMAL", 0, "Normal", "Uses normal vector as texture coordinates."}, + {TEXCO_REFL, "REFLECTION", 0, "Reflection", "Uses reflection vector as texture coordinates."}, + {TEXCO_STRESS, "STRESS", 0, "Stress", "Uses the difference of edge lengths compared to original coordinates of the mesh."}, + {TEXCO_TANGENT, "TANGENT", 0, "Tangent", "Uses the optional tangent vector as texture coordinates."}, + + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_texture_mapto_items[] = { + {MAP_COL, "COLOR", 0, "Color", "Causes the texture to affect basic color of the material"}, + {MAP_NORM, "NORMAL", 0, "Normal", "Causes the texture to affect the rendered normal"}, + {MAP_COLSPEC, "SPECULAR_COLOR", 0, "Specularity Color", "Causes the texture to affect the specularity color"}, + {MAP_COLMIR, "MIRROR", 0, "Mirror", "Causes the texture to affect the mirror color"}, + {MAP_REF, "REFLECTION", 0, "Reflection", "Causes the texture to affect the value of the materials reflectivity"}, + {MAP_SPEC, "SPECULARITY", 0, "Specularity", "Causes the texture to affect the value of specularity"}, + {MAP_EMIT, "EMIT", 0, "Emit", "Causes the texture to affect the emit value"}, + {MAP_ALPHA, "ALPHA", 0, "Alpha", "Causes the texture to affect the alpha value"}, + {MAP_HAR, "HARDNESS", 0, "Hardness", "Causes the texture to affect the hardness value"}, + {MAP_RAYMIRR, "RAY_MIRROR", 0, "Ray-Mirror", "Causes the texture to affect the ray-mirror value"}, + {MAP_TRANSLU, "TRANSLUCENCY", 0, "Translucency", "Causes the texture to affect the translucency value"}, + {MAP_AMB, "AMBIENT", 0, "Ambient", "Causes the texture to affect the value of ambient"}, + {MAP_DISPLACE, "DISPLACEMENT", 0, "Displacement", "Let the texture displace the surface"}, + {MAP_WARP, "WARP", 0, "Warp", "Let the texture warp texture coordinates of next channels"}, + {0, NULL, 0, NULL, NULL}}; + + func= RNA_def_function(srna, "add_texture", "rna_Material_add_texture"); + RNA_def_function_ui_description(func, "Add a texture to material's free texture slot."); + parm= RNA_def_pointer(func, "texture", "Texture", "", "Texture to add."); + parm= RNA_def_enum(func, "texture_coordinates", prop_texture_coordinates_items, TEXCO_UV, "", "Source of texture coordinate information."); /* optional */ + parm= RNA_def_enum(func, "map_to", prop_texture_mapto_items, MAP_COL, "", "Controls which material property the texture affects."); /* optional */ +} + +#endif + diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 78fb8ede3ee..ecfe59a0142 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -953,6 +953,16 @@ static void rna_def_medge(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_SHARP); RNA_def_property_ui_text(prop, "Sharp", "Sharp edge for the EdgeSplit modifier"); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + + prop= RNA_def_property(srna, "loose", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_LOOSEEDGE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Loose", "Loose edge"); + + prop= RNA_def_property(srna, "fgon", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_FGON); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Fgon", "Fgon edge"); } static void rna_def_mface(BlenderRNA *brna) @@ -972,6 +982,7 @@ static void rna_def_mface(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_DYNAMIC); RNA_def_property_dynamic_array_funcs(prop, "rna_MeshFace_verts_get_length"); RNA_def_property_int_funcs(prop, "rna_MeshFace_verts_get", "rna_MeshFace_verts_set", NULL); + RNA_def_property_ui_text(prop, "Vertices", "Vertex indices"); prop= RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 686d91e4fe2..6e37014a771 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -42,12 +42,19 @@ #include "BKE_DerivedMesh.h" #include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_material.h" +#include "DNA_mesh_types.h" +#include "DNA_scene_types.h" + +#include "BLI_arithb.h" #include "BLI_edgehash.h" #include "WM_api.h" #include "WM_types.h" +#include "MEM_guardedalloc.h" + static void rna_Mesh_calc_edges(Mesh *mesh) { CustomData edata; @@ -111,6 +118,18 @@ static void rna_Mesh_update(Mesh *mesh, bContext *C) WM_event_add_notifier(C, NC_GEOM|ND_DATA, mesh); } +static void rna_Mesh_transform(Mesh *me, float *mat) +{ + + /* TODO: old API transform had recalc_normals option */ + int i; + MVert *mvert= me->mvert; + + for(i= 0; i < me->totvert; i++, mvert++) { + Mat4MulVecfl((float (*)[4])mat, mvert->co); + } +} + static void rna_Mesh_add_verts(Mesh *mesh, int len) { CustomData vdata; @@ -141,6 +160,14 @@ static void rna_Mesh_add_verts(Mesh *mesh, int len) mesh->totvert= totvert; } +Mesh *rna_Mesh_create_copy(Mesh *me) +{ + Mesh *ret= copy_mesh(me); + ret->id.us--; + + return ret; +} + static void rna_Mesh_add_edges(Mesh *mesh, int len) { CustomData edata; @@ -201,6 +228,12 @@ static void rna_Mesh_add_faces(Mesh *mesh, int len) mesh->totface= totface; } +/* +static void rna_Mesh_add_faces(Mesh *mesh) +{ +} +*/ + static void rna_Mesh_add_geometry(Mesh *mesh, int verts, int edges, int faces) { if(verts) @@ -211,6 +244,39 @@ static void rna_Mesh_add_geometry(Mesh *mesh, int verts, int edges, int faces) rna_Mesh_add_faces(mesh, faces); } +static void rna_Mesh_add_uv_texture(Mesh *me) +{ + me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface); +} + +static void rna_Mesh_calc_normals(Mesh *me) +{ + mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); +} + +static void rna_Mesh_add_material(Mesh *me, Material *ma) +{ + int i; + int totcol = me->totcol + 1; + Material **mat; + + /* don't add if mesh already has it */ + for (i = 0; i < me->totcol; i++) + if (me->mat[i] == ma) + return; + + mat= MEM_callocN(sizeof(void*) * totcol, "newmatar"); + + if (me->totcol) memcpy(mat, me->mat, sizeof(void*) * me->totcol); + if (me->mat) MEM_freeN(me->mat); + + me->mat = mat; + me->mat[me->totcol++] = ma; + ma->id.us++; + + test_object_materials((ID*)me); +} + #else void RNA_api_mesh(StructRNA *srna) @@ -218,6 +284,11 @@ void RNA_api_mesh(StructRNA *srna) FunctionRNA *func; PropertyRNA *parm; + func= RNA_def_function(srna, "transform", "rna_Mesh_transform"); + RNA_def_function_ui_description(func, "Transform mesh vertices by a matrix."); + parm= RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix.", 0.0f, 0.0f); + RNA_def_property_flag(parm, PROP_REQUIRED); + func= RNA_def_function(srna, "add_geometry", "rna_Mesh_add_geometry"); parm= RNA_def_int(func, "verts", 0, 0, INT_MAX, "Number", "Number of vertices to add.", 0, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); @@ -226,8 +297,24 @@ void RNA_api_mesh(StructRNA *srna) parm= RNA_def_int(func, "faces", 0, 0, INT_MAX, "Number", "Number of faces to add.", 0, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); + func= RNA_def_function(srna, "create_copy", "rna_Mesh_create_copy"); + RNA_def_function_ui_description(func, "Create a copy of this Mesh datablock."); + parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh, remove it if it is only used for export."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "add_uv_texture", "rna_Mesh_add_uv_texture"); + RNA_def_function_ui_description(func, "Add a UV texture layer to Mesh."); + + func= RNA_def_function(srna, "calc_normals", "rna_Mesh_calc_normals"); + RNA_def_function_ui_description(func, "Calculate vertex normals."); + func= RNA_def_function(srna, "update", "rna_Mesh_update"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); + + func= RNA_def_function(srna, "add_material", "rna_Mesh_add_material"); + RNA_def_function_ui_description(func, "Add a new material to Mesh."); + parm= RNA_def_pointer(func, "material", "Material", "", "Material to add."); + RNA_def_property_flag(parm, PROP_REQUIRED); } #endif diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c index f3160a7bb18..1a4e4da886b 100644 --- a/source/blender/makesrna/intern/rna_meta.c +++ b/source/blender/makesrna/intern/rna_meta.c @@ -67,7 +67,7 @@ static void rna_MetaBall_update_data(bContext *C, PointerRNA *ptr) #else -void rna_def_metaelement(BlenderRNA *brna) +static void rna_def_metaelement(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -143,7 +143,7 @@ void rna_def_metaelement(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); } -void rna_def_metaball(BlenderRNA *brna) +static void rna_def_metaball(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 32e34559f1f..480abff19cb 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -930,12 +930,14 @@ static void rna_def_modifier_softbody(BlenderRNA *brna) RNA_def_struct_sdna(srna, "SoftbodyModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SOFT); - prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "SoftBodySettings"); RNA_def_property_pointer_funcs(prop, "rna_SoftBodyModifier_settings_get", NULL, NULL); RNA_def_property_ui_text(prop, "Soft Body Settings", ""); - prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "PointCache"); RNA_def_property_pointer_funcs(prop, "rna_SoftBodyModifier_point_cache_get", NULL, NULL); RNA_def_property_ui_text(prop, "Soft Body Point Cache", ""); @@ -1551,15 +1553,18 @@ static void rna_def_modifier_cloth(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ClothModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_CLOTH); - prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "sim_parms"); RNA_def_property_ui_text(prop, "Cloth Settings", ""); - prop= RNA_def_property(srna, "collision_settings", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "collision_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "coll_parms"); RNA_def_property_ui_text(prop, "Cloth Collision Settings", ""); - prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Point Cache", ""); } @@ -1609,16 +1614,11 @@ static void rna_def_modifier_collision(BlenderRNA *brna) RNA_def_struct_sdna(srna, "CollisionModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_PHYSICS); - prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "CollisionSettings"); RNA_def_property_pointer_funcs(prop, "rna_CollisionModifier_settings_get", NULL, NULL); RNA_def_property_ui_text(prop, "Settings", ""); - - prop= RNA_def_property(srna, "absorption", PROP_INT, PROP_PERCENTAGE); - RNA_def_property_int_sdna(prop, NULL, "absorption"); - RNA_def_property_ui_range(prop, 0, 100, 1, 2); - RNA_def_property_ui_text(prop, "Absorption %", "How much of effector force gets lost during collision with this object (in percent)."); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); } static void rna_def_modifier_bevel(BlenderRNA *brna) @@ -1780,7 +1780,8 @@ static void rna_def_modifier_fluidsim(BlenderRNA *brna) RNA_def_struct_sdna(srna, "FluidsimModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_FLUIDSIM); - prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "fss"); RNA_def_property_ui_text(prop, "Settings", "Settings for how this object is used in the fluid simulation."); } diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 690a198f12c..20d1a898303 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -47,7 +47,7 @@ /* temp constant defined for these funcs only... */ #define NLASTRIP_MIN_LEN_THRESH 0.1f -void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value) +static void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value) { NlaStrip *data= (NlaStrip *)ptr->data; @@ -280,7 +280,7 @@ EnumPropertyItem nla_mode_extend_items[] = { {NLASTRIP_EXTEND_HOLD_FORWARD, "HOLD_FORWARD", 0, "Hold Forward", "Only hold last frame."}, {0, NULL, 0, NULL, NULL}}; -void rna_def_nlastrip(BlenderRNA *brna) +static void rna_def_nlastrip(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -433,7 +433,7 @@ void rna_def_nlastrip(BlenderRNA *brna) // - sync length } -void rna_def_nlatrack(BlenderRNA *brna) +static void rna_def_nlatrack(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 3fd358a1c16..ebd032bb0b1 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> +#include "RNA_access.h" #include "RNA_define.h" #include "RNA_types.h" @@ -37,9 +38,82 @@ #include "BKE_node.h" #include "BKE_image.h" +static EnumPropertyItem node_blend_type_items[] = { + { 0, "MIX", 0, "Mix", ""}, + { 1, "ADD", 0, "Add", ""}, + { 3, "SUBTRACT", 0, "Subtract", ""}, + { 2, "MULTIPLY", 0, "Multiply", ""}, + { 4, "SCREEN", 0, "Screen", ""}, + { 9, "OVERLAY", 0, "Overlay", ""}, + { 5, "DIVIDE", 0, "Divide", ""}, + { 6, "DIFFERENCE", 0, "Difference", ""}, + { 7, "DARKEN", 0, "Darken", ""}, + { 8, "LIGHTEN", 0, "Lighten", ""}, + {10, "DODGE", 0, "Dodge", ""}, + {11, "BURN", 0, "Burn", ""}, + {15, "COLOR", 0, "Color", ""}, + {14, "VALUE", 0, "Value", ""}, + {13, "SATURATION", 0, "Saturation", ""}, + {12, "HUE", 0, "Hue", ""}, + {16, "SOFT_LIGHT", 0, "Soft Light", ""}, + {17, "LINEAR_LIGHT", 0, "Linear Light",""}, + {0, NULL, 0, NULL, NULL} +}; + +static EnumPropertyItem node_flip_items[] = { + {0, "X", 0, "Flip X", ""}, + {1, "Y", 0, "Flip Y", ""}, + {2, "XY", 0, "Flip X & Y", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static EnumPropertyItem node_math_items[] = { + { 0, "ADD", 0, "Add", ""}, + { 1, "SUBTRACT", 0, "Subtract", ""}, + { 2, "MULTIPLY", 0, "Multiply", ""}, + { 3, "DIVIDE", 0, "Divide", ""}, + { 4, "SINE", 0, "Sine", ""}, + { 5, "COSINE", 0, "Cosine", ""}, + { 6, "TANGENT", 0, "Tangent", ""}, + { 7, "ARCSINE", 0, "Arcsine", ""}, + { 8, "ARCCOSINE", 0, "Arccosine", ""}, + { 9, "ARCTANGENT", 0, "Arctangent", ""}, + {10, "POWER", 0, "Power", ""}, + {11, "LOGARITHM", 0, "Logarithm", ""}, + {12, "MINIMUM", 0, "Minimum", ""}, + {13, "MAXIMUM", 0, "Maximum", ""}, + {14, "ROUND", 0, "Round", ""}, + {15, "LESS_THAN", 0, "Less Than", ""}, + {16, "GREATER_THAN", 0, "Greater Than", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static EnumPropertyItem node_vec_math_items[] = { + {0, "ADD", 0, "Add", ""}, + {1, "SUBTRACT", 0, "Subtract", ""}, + {2, "AVERAGE", 0, "Average", ""}, + {3, "DOT_PRODUCT", 0, "Dot Product", ""}, + {4, "CROSS_PRODUCT", 0, "Cross Product", ""}, + {5, "NORMALIZE", 0, "Normalize", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static EnumPropertyItem node_filter_items[] = { + {0, "SOFTEN", 0, "Soften", ""}, + {1, "SHARPEN", 0, "Sharpen", ""}, + {2, "LAPLACE", 0, "Laplace", ""}, + {3, "SOBEL", 0, "Sobel", ""}, + {4, "PREWITT", 0, "Prewitt", ""}, + {5, "KIRSCH", 0, "Kirsch", ""}, + {6, "SHADOW", 0, "Shadow", ""}, + {0, NULL, 0, NULL, NULL} +}; + #ifdef RNA_RUNTIME -StructRNA *rna_Node_refine(struct PointerRNA *ptr) +#include "ED_node.h" + +static StructRNA *rna_Node_refine(struct PointerRNA *ptr) { bNode *node = (bNode*)ptr->data; @@ -66,6 +140,53 @@ static char *rna_Node_path(PointerRNA *ptr) return BLI_sprintfN("nodes[%d]", index); } +static void rna_Node_update(bContext *C, PointerRNA *ptr) +{ + bNode *node= (bNode*)ptr->data; + + ED_node_changed_update(C, node); +} + +static void rna_Node_update_name(bContext *C, PointerRNA *ptr) +{ + bNode *node= (bNode*)ptr->data; + const char *name; + + if(node->id) { + BLI_strncpy(node->name, node->id->name+2, NODE_MAXSTR); + } + else { + switch(node->typeinfo->type) { + case SH_NODE_MIX_RGB: + case CMP_NODE_MIX_RGB: + case TEX_NODE_MIX_RGB: + if(RNA_enum_name(node_blend_type_items, node->custom1, &name)) + BLI_strncpy(node->name, name, NODE_MAXSTR); + break; + case CMP_NODE_FILTER: + if(RNA_enum_name(node_filter_items, node->custom1, &name)) + BLI_strncpy(node->name, name, NODE_MAXSTR); + break; + case CMP_NODE_FLIP: + if(RNA_enum_name(node_flip_items, node->custom1, &name)) + BLI_strncpy(node->name, name, NODE_MAXSTR); + break; + case SH_NODE_MATH: + case CMP_NODE_MATH: + case TEX_NODE_MATH: + if(RNA_enum_name(node_math_items, node->custom1, &name)) + BLI_strncpy(node->name, name, NODE_MAXSTR); + break; + case SH_NODE_VECT_MATH: + if(RNA_enum_name(node_vec_math_items, node->custom1, &name)) + BLI_strncpy(node->name, name, NODE_MAXSTR); + break; + } + } + + rna_Node_update(C, ptr); +} + #else #define MaxNodes 1000 @@ -183,53 +304,22 @@ static void def_math(StructRNA *srna) { PropertyRNA *prop; - static EnumPropertyItem items[] = { - { 0, "ADD", 0, "Add", ""}, - { 1, "SUBTRACT", 0, "Subtract", ""}, - { 2, "MULTIPLY", 0, "Multiply", ""}, - { 3, "DIVIDE", 0, "Divide", ""}, - { 4, "SINE", 0, "Sine", ""}, - { 5, "COSINE", 0, "Cosine", ""}, - { 6, "TANGENT", 0, "Tangent", ""}, - { 7, "ARCSINE", 0, "Arcsine", ""}, - { 8, "ARCCOSINE", 0, "Arccosine", ""}, - { 9, "ARCTANGENT", 0, "Arctangent", ""}, - {10, "POWER", 0, "Power", ""}, - {11, "LOGARITHM", 0, "Logarithm", ""}, - {12, "MINIMUM", 0, "Minimum", ""}, - {13, "MAXIMUM", 0, "Maximum", ""}, - {14, "ROUND", 0, "Round", ""}, - {15, "LESS_THAN", 0, "Less Than", ""}, - {16, "GREATER_THAN", 0, "Greater Than", ""}, - - {0, NULL, 0, NULL, NULL} - }; - prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, items); + RNA_def_property_enum_items(prop, node_math_items); RNA_def_property_ui_text(prop, "Operation", ""); + RNA_def_property_update(prop, 0, "rna_Node_update_name"); } static void def_vector_math(StructRNA *srna) { PropertyRNA *prop; - static EnumPropertyItem items[] = { - {0, "ADD", 0, "Add", ""}, - {1, "SUBTRACT", 0, "Subtract", ""}, - {2, "AVERAGE", 0, "Average", ""}, - {3, "DOT_PRODUCT", 0, "Dot Product", ""}, - {4, "CROSS_PRODUCT", 0, "Cross Product", ""}, - {5, "NORMALIZE", 0, "Normalize", ""}, - - {0, NULL, 0, NULL, NULL} - }; - prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, items); + RNA_def_property_enum_items(prop, node_vec_math_items); RNA_def_property_ui_text(prop, "Operation", ""); + RNA_def_property_update(prop, 0, "rna_Node_update_name"); } static void def_rgb_curve(StructRNA *srna) @@ -240,6 +330,7 @@ static void def_rgb_curve(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "storage"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Mapping", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_vector_curve(StructRNA *srna) @@ -250,6 +341,7 @@ static void def_vector_curve(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "storage"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Mapping", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_time(StructRNA *srna) @@ -260,59 +352,44 @@ static void def_time(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "storage"); RNA_def_property_struct_type(prop, "CurveMapping"); RNA_def_property_ui_text(prop, "Curve", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "start", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom1"); RNA_def_property_ui_text(prop, "Start Frame", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "end", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); RNA_def_property_ui_text(prop, "End Frame", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_val_to_rgb(StructRNA *srna) { - /*PropertyRNA *prop;*/ + PropertyRNA *prop; - /* TODO: uncomment when ColorBand is wrapped *//* - prop = RNA_def_property(srna, "color_band", PROP_POINTER, PROP_NONE); + prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "storage"); - RNA_def_property_struct_type(prop, "ColorBand"); - RNA_def_property_ui_text(prop, "Color Band", "");*/ + RNA_def_property_struct_type(prop, "ColorRamp"); + RNA_def_property_ui_text(prop, "Color Ramp", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_mix_rgb(StructRNA *srna) { PropertyRNA *prop; - static EnumPropertyItem blend_type_items[] = { - { 0, "MIX", 0, "Mix", ""}, - { 1, "ADD", 0, "Add", ""}, - { 3, "SUBTRACT", 0, "Subtract", ""}, - { 2, "MULTIPLY", 0, "Multiply", ""}, - { 4, "SCREEN", 0, "Screen", ""}, - { 9, "OVERLAY", 0, "Overlay", ""}, - { 5, "DIVIDE", 0, "Divide", ""}, - { 6, "DIFFERENCE", 0, "Difference", ""}, - { 7, "DARKEN", 0, "Darken", ""}, - { 8, "LIGHTEN", 0, "Lighten", ""}, - {10, "DODGE", 0, "Dodge", ""}, - {11, "BURN", 0, "Burn", ""}, - {15, "COLOR", 0, "Color", ""}, - {14, "VALUE", 0, "Value", ""}, - {13, "SATURATION", 0, "Saturation", ""}, - {12, "HUE", 0, "Hue", ""}, - {0, NULL, 0, NULL, NULL} - }; - prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, blend_type_items); + RNA_def_property_enum_items(prop, node_blend_type_items); RNA_def_property_ui_text(prop, "Blend Type", ""); + RNA_def_property_update(prop, 0, "rna_Node_update_name"); prop = RNA_def_property(srna, "alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom2", 1); - RNA_def_property_ui_text(prop, "Diffuse", "Include alpha of second input in this operation"); + RNA_def_property_ui_text(prop, "Alpha", "Include alpha of second input in this operation"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_texture(StructRNA *srna) @@ -324,10 +401,12 @@ static void def_texture(StructRNA *srna) RNA_def_property_struct_type(prop, "Texture"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Texture", ""); + RNA_def_property_update(prop, 0, "rna_Node_update_name"); prop = RNA_def_property(srna, "node_output", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom1"); RNA_def_property_ui_text(prop, "Node Output", "For node-based textures, which output node to use"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } @@ -342,18 +421,22 @@ static void def_sh_material(StructRNA *srna) RNA_def_property_struct_type(prop, "Material"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Material", ""); + RNA_def_property_update(prop, 0, "rna_Node_update_name"); prop = RNA_def_property(srna, "diffuse", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", SH_NODE_MAT_DIFF); RNA_def_property_ui_text(prop, "Diffuse", "Material Node outputs Diffuse"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "specular", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", SH_NODE_MAT_SPEC); RNA_def_property_ui_text(prop, "Specular", "Material Node outputs Specular"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "invert_normal", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", SH_NODE_MAT_NEG); RNA_def_property_ui_text(prop, "Invert Normal", "Material Node uses inverted normal"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_sh_mapping(StructRNA *srna) @@ -364,6 +447,7 @@ static void def_sh_mapping(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "storage"); RNA_def_property_struct_type(prop, "TexMapping"); RNA_def_property_ui_text(prop, "Mapping", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_sh_geometry(StructRNA *srna) @@ -375,10 +459,12 @@ static void def_sh_geometry(StructRNA *srna) prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "uvname"); RNA_def_property_ui_text(prop, "UV Layer", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "color_layer", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "colname"); RNA_def_property_ui_text(prop, "Vertex Color Layer", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } @@ -387,10 +473,12 @@ static void def_sh_geometry(StructRNA *srna) static void def_cmp_alpha_over(StructRNA *srna) { PropertyRNA *prop; - + + // XXX: Tooltip prop = RNA_def_property(srna, "convert_premul", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); - RNA_def_property_ui_text(prop, "convert_premul", "TODO: don't know what this is"); + RNA_def_property_ui_text(prop, "Convert Premul", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); RNA_def_struct_sdna_from(srna, "NodeTwoFloats", "storage"); @@ -398,6 +486,32 @@ static void def_cmp_alpha_over(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "x"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Premul", "Mix Factor"); + RNA_def_property_update(prop, 0, "rna_Node_update"); +} + +static void def_cmp_hue_saturation(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeHueSat", "storage"); + + prop = RNA_def_property(srna, "hue", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "hue"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Hue", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "sat", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "sat"); + RNA_def_property_range(prop, 0.0f, 2.0f); + RNA_def_property_ui_text(prop, "Saturation", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "val", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "val"); + RNA_def_property_range(prop, 0.0f, 2.0f); + RNA_def_property_ui_text(prop, "Value", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_blur(StructRNA *srna) @@ -422,58 +536,70 @@ static void def_cmp_blur(StructRNA *srna) RNA_def_property_int_sdna(prop, NULL, "sizex"); RNA_def_property_range(prop, 0, 256); RNA_def_property_ui_text(prop, "Size X", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "sizey", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "sizey"); - RNA_def_property_range(prop, 1, 256); + RNA_def_property_range(prop, 0, 256); RNA_def_property_ui_text(prop, "Size Y", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "samples"); RNA_def_property_range(prop, 1, 256); RNA_def_property_ui_text(prop, "Samples", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "max_speed", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "maxspeed"); RNA_def_property_range(prop, 1, 1024); RNA_def_property_ui_text(prop, "Max Speed", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "min_speed", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "minspeed"); RNA_def_property_range(prop, 1, 1024); RNA_def_property_ui_text(prop, "Min Speed", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "relative", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "relative", 1); RNA_def_property_ui_text(prop, "Relative", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fac"); RNA_def_property_range(prop, 0.0f, 2.0f); RNA_def_property_ui_text(prop, "Factor", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "factor_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "percentx"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Relative Size X", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "factor_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "percenty"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Relative Size Y", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "filtertype"); RNA_def_property_enum_items(prop, filter_type_items); RNA_def_property_ui_text(prop, "Filter Type", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "bokeh", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "bokeh", 1); RNA_def_property_ui_text(prop, "Bokeh", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "gamma", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gamma", 1); RNA_def_property_ui_text(prop, "Gamma", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* TODO: @@ -490,21 +616,11 @@ static void def_cmp_filter(StructRNA *srna) { PropertyRNA *prop; - static EnumPropertyItem type_items[] = { - {0, "SOFTEN", 0, "Soften", ""}, - {1, "SHARPEN", 0, "Sharpen", ""}, - {2, "LAPLACE", 0, "Laplace", ""}, - {3, "SOBEL", 0, "Sobel", ""}, - {4, "PREWITT", 0, "Prewitt", ""}, - {5, "KIRSCH", 0, "Kirsch", ""}, - {6, "SHADOW", 0, "Shadow", ""}, - {0, NULL, 0, NULL, NULL} - }; - prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, type_items); + RNA_def_property_enum_items(prop, node_filter_items); RNA_def_property_ui_text(prop, "Filter Type", ""); + RNA_def_property_update(prop, 0, "rna_Node_update_name"); } static void def_cmp_map_value(StructRNA *srna) @@ -515,31 +631,41 @@ static void def_cmp_map_value(StructRNA *srna) prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "loc"); + RNA_def_property_array(prop, 1); RNA_def_property_range(prop, -1000.0f, 1000.0f); RNA_def_property_ui_text(prop, "Offset", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "size"); + RNA_def_property_array(prop, 1); RNA_def_property_range(prop, -1000.0f, 1000.0f); RNA_def_property_ui_text(prop, "Size", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "use_min", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEXMAP_CLIP_MIN); RNA_def_property_ui_text(prop, "Use Minimum", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "use_max", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TEXMAP_CLIP_MAX); RNA_def_property_ui_text(prop, "Use Maximum", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "min"); + RNA_def_property_array(prop, 1); RNA_def_property_range(prop, -1000.0f, 1000.0f); RNA_def_property_ui_text(prop, "Minimum", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "max"); + RNA_def_property_array(prop, 1); RNA_def_property_range(prop, -1000.0f, 1000.0f); RNA_def_property_ui_text(prop, "Maximum", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_vector_blur(StructRNA *srna) @@ -551,22 +677,47 @@ static void def_cmp_vector_blur(StructRNA *srna) prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "samples"); RNA_def_property_ui_text(prop, "Samples", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "min_speed", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "minspeed"); RNA_def_property_ui_text(prop, "Min Speed", "Minimum speed for a pixel to be blurred; used to separate background from foreground"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "max_speed", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "maxspeed"); - RNA_def_property_ui_text(prop, "Min Speed", "Maximum speed, or zero for none"); + RNA_def_property_ui_text(prop, "Max Speed", "Maximum speed, or zero for none"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fac"); RNA_def_property_ui_text(prop, "Blur Factor", "Scaling factor for motion vectors; actually 'shutter speed' in frames"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "curved", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "curved", 1); RNA_def_property_ui_text(prop, "Curved", "Interpolate between frames in a bezier curve, rather than linearly"); + RNA_def_property_update(prop, 0, "rna_Node_update"); +} + +static void def_cmp_levels(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem space_items[] = { + {1, "COMNINED_RGB", 0, "C", "Combined RGB"}, + {2, "RED", 0, "R", "Red Channel"}, + {3, "GREEN", 0, "G", "Green Channel"}, + {4, "BLUE", 0, "B", "Blue Channel"}, + {5, "LUMINANCE", 0, "L", "Luminance Channel"}, + {0, NULL, 0, NULL, NULL} + }; + + prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, space_items); + RNA_def_property_ui_text(prop, "Color Space", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_image(StructRNA *srna) @@ -586,6 +737,7 @@ static void def_cmp_image(StructRNA *srna) RNA_def_property_struct_type(prop, "Image"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Image", ""); + RNA_def_property_update(prop, 0, "rna_Node_update_name"); RNA_def_struct_sdna_from(srna, "ImageUser", "storage"); @@ -595,24 +747,29 @@ static void def_cmp_image(StructRNA *srna) RNA_def_property_int_sdna(prop, NULL, "frames"); RNA_def_property_range(prop, 1, MAXFRAMEF); RNA_def_property_ui_text(prop, "Frames", "Number of images used in animation"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "start", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "sfra"); RNA_def_property_range(prop, 1, MAXFRAMEF); RNA_def_property_ui_text(prop, "Start Frame", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "offset", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "offset"); RNA_def_property_range(prop, -MAXFRAMEF, MAXFRAMEF); RNA_def_property_ui_text(prop, "Offset", "Offsets the number of the frame to use in the animation"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "cyclic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cycl", 1); RNA_def_property_ui_text(prop, "Cyclic", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "auto_refresh", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_ANIM_ALWAYS); RNA_def_property_ui_text(prop, "Auto-Refresh", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* } */ @@ -622,6 +779,7 @@ static void def_cmp_image(StructRNA *srna) RNA_def_property_int_sdna(prop, NULL, "layer"); RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "Layer", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* } */ @@ -638,16 +796,19 @@ static void def_cmp_render_layers(StructRNA *srna) RNA_def_property_struct_type(prop, "Scene"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Scene", ""); + RNA_def_property_update(prop, 0, "rna_Node_update_name"); /* TODO: layers in menu */ prop = RNA_def_property(srna, "layer", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom1"); RNA_def_property_ui_text(prop, "Layer", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* TODO: comments indicate this might be a hack */ prop = RNA_def_property(srna, "re_render", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom2", 1); RNA_def_property_ui_text(prop, "Re-render", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_output_file(StructRNA *srna) @@ -711,11 +872,13 @@ static void def_cmp_output_file(StructRNA *srna) RNA_def_property_int_sdna(prop, NULL, "sfra"); RNA_def_property_range(prop, 1, MAXFRAMEF); RNA_def_property_ui_text(prop, "Start Frame", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "end", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "efra"); RNA_def_property_range(prop, 1, MAXFRAMEF); RNA_def_property_ui_text(prop, "End Frame", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_dilate_erode(StructRNA *srna) @@ -724,7 +887,9 @@ static void def_cmp_dilate_erode(StructRNA *srna) prop = RNA_def_property(srna, "distance", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); + RNA_def_property_range(prop, -100, 100); RNA_def_property_ui_text(prop, "Distance", "Distance to grow/shrink (number of iterations)"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_scale(StructRNA *srna) @@ -742,6 +907,7 @@ static void def_cmp_scale(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, space_items); RNA_def_property_ui_text(prop, "Space", "Coordinate space to scale relative to"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_diff_matte(StructRNA *srna) @@ -756,11 +922,13 @@ static void def_cmp_diff_matte(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Tolerance", "Color distances below this threshold are keyed."); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Falloff", "Color distances below this additional threshold are partially keyed."); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_color_matte(StructRNA *srna) @@ -775,16 +943,19 @@ static void def_cmp_color_matte(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "H", "Hue tolerance for colors to be considered a keying color"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "s", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "S", "Saturation Tolerance for the color"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "v", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t3"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "V", "Value Tolerance for the color"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_distance_matte(StructRNA *srna) @@ -799,11 +970,13 @@ static void def_cmp_distance_matte(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Tolerance", "Color distances below this threshold are keyed."); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Falloff", "Color distances below this additional threshold are partially keyed."); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_color_spill(StructRNA *srna) @@ -811,9 +984,9 @@ static void def_cmp_color_spill(StructRNA *srna) PropertyRNA *prop; static EnumPropertyItem channel_items[] = { - {1, "R", 0, "Red", ""}, - {2, "G", 0, "Green", ""}, - {3, "B", 0, "Blue", ""}, + {1, "R", 0, "R", "Red Spill Suppression"}, + {2, "G", 0, "G", "Green Spill Suppression"}, + {3, "B", 0, "B", "Blue Spill Suppression"}, {0, NULL, 0, NULL, NULL} }; @@ -821,6 +994,7 @@ static void def_cmp_color_spill(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, channel_items); RNA_def_property_ui_text(prop, "Channel", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); RNA_def_struct_sdna_from(srna, "NodeChroma", "storage"); @@ -828,6 +1002,7 @@ static void def_cmp_color_spill(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_range(prop, 0.0f, 0.5f); RNA_def_property_ui_text(prop, "Amount", "How much the selected channel is affected by"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_chroma_matte(StructRNA *srna) @@ -840,26 +1015,31 @@ static void def_cmp_chroma_matte(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_range(prop, 1.0f, 80.0f); RNA_def_property_ui_text(prop, "Acceptance", "Tolerance for a color to be considered a keying color"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "cutoff", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_range(prop, 0.0f, 30.0f); RNA_def_property_ui_text(prop, "Cutoff", "Tolerance below which colors will be considered as exact matches"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "lift", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fsize"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Lift", "Alpha lift"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "gain", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fstrength"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Gain", "Alpha gain"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "shadow_adjust", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t3"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Shadow Adjust", "Adjusts the brightness of any shadows captured"); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* TODO: if(c->t2 > c->t1) @@ -883,10 +1063,12 @@ static void def_cmp_channel_matte(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, color_space_items); RNA_def_property_ui_text(prop, "Color Space", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* TODO: channel must be 1, 2 or 3 */ prop = RNA_def_property(srna, "channel", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); + RNA_def_property_update(prop, 0, "rna_Node_update"); RNA_def_property_ui_text(prop, "Channel", ""); RNA_def_struct_sdna_from(srna, "NodeChroma", "storage"); @@ -895,11 +1077,13 @@ static void def_cmp_channel_matte(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "High", "Values higher than this setting are 100% opaque"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "low", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Low", "Values lower than this setting are 100% keyed"); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* TODO: if(c->t2 > c->t1) @@ -911,17 +1095,11 @@ static void def_cmp_flip(StructRNA *srna) { PropertyRNA *prop; - static EnumPropertyItem axis_items[] = { - {0, "X", 0, "X", ""}, - {1, "Y", 0, "Y", ""}, - {2, "XY", 0, "X & Y", ""}, - {0, NULL, 0, NULL, NULL} - }; - prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, axis_items); + RNA_def_property_enum_items(prop, node_flip_items); RNA_def_property_ui_text(prop, "Axis", ""); + RNA_def_property_update(prop, 0, "rna_Node_update_name"); } static void def_cmp_splitviewer(StructRNA *srna) @@ -938,12 +1116,13 @@ static void def_cmp_splitviewer(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "custom2"); RNA_def_property_enum_items(prop, axis_items); RNA_def_property_ui_text(prop, "Axis", ""); - - /* TODO: percentage */ - prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_PERCENTAGE); - RNA_def_property_float_sdna(prop, NULL, "custom1"); - RNA_def_property_range(prop, 0.0f, 100.0f); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "factor", PROP_INT, PROP_FACTOR); + RNA_def_property_int_sdna(prop, NULL, "custom1"); + RNA_def_property_range(prop, 0, 100); RNA_def_property_ui_text(prop, "Factor", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_id_mask(StructRNA *srna) @@ -954,17 +1133,18 @@ static void def_cmp_id_mask(StructRNA *srna) RNA_def_property_int_sdna(prop, NULL, "custom1"); RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "Index", "Pass index number to convert to alpha"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_map_uv(StructRNA *srna) { PropertyRNA *prop; - - /* TODO: percentage */ - prop = RNA_def_property(srna, "alpha", PROP_INT, PROP_PERCENTAGE); + + prop = RNA_def_property(srna, "alpha", PROP_INT, PROP_FACTOR); RNA_def_property_int_sdna(prop, NULL, "custom1"); RNA_def_property_range(prop, 0, 100); RNA_def_property_ui_text(prop, "Alpha", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_defocus(StructRNA *srna) @@ -988,50 +1168,60 @@ static void def_cmp_defocus(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "bktype"); RNA_def_property_enum_items(prop, bokeh_items); RNA_def_property_ui_text(prop, "Bokeh Type", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* TODO: angle in degrees */ prop = RNA_def_property(srna, "angle", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "rotation"); RNA_def_property_range(prop, 0, 90); RNA_def_property_ui_text(prop, "Angle", "Bokeh shape rotation offset in degrees"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "gamma_correction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gamco", 1); RNA_def_property_ui_text(prop, "Gamma Correction", "Enable gamma correction before and after main process"); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* TODO */ prop = RNA_def_property(srna, "f_stop", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fstop"); RNA_def_property_range(prop, 0.0f, 128.0f); RNA_def_property_ui_text(prop, "fStop", "Amount of focal blur, 128=infinity=perfect focus, half the value doubles the blur radius"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "max_blur", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "maxblur"); RNA_def_property_range(prop, 0.0f, 10000.0f); RNA_def_property_ui_text(prop, "Max Blur", "blur limit, maximum CoC radius, 0=no limit"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "bthresh"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Threshold", "CoC radius threshold, prevents background bleed on in-focus midground, 0=off"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "preview", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "preview", 1); RNA_def_property_ui_text(prop, "Preview", "Enable sampling mode, useful for preview when using low samplecounts"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "samples"); RNA_def_property_range(prop, 16, 256); RNA_def_property_ui_text(prop, "Samples", "Number of samples (16=grainy, higher=less noise)"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "use_zbuffer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "no_zbuf", 1); RNA_def_property_ui_text(prop, "Use Z-Buffer", "Disable when using an image as input instead of actual zbuffer (auto enabled if node not image based, eg. time node)"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "z_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "scale"); RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "Z-Scale", "Scales the Z input when not using a zbuffer, controls maximum blur designated by the color white or input value 1"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_luma_matte(StructRNA *srna) @@ -1044,11 +1234,13 @@ static void def_cmp_luma_matte(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "t1"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "High", "Values higher than this setting are 100% opaque"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "low", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "t2"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Low", "Values lower than this setting are 100% keyed"); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* TODO: keep low less than high */ @@ -1061,10 +1253,12 @@ static void def_cmp_invert(StructRNA *srna) prop = RNA_def_property(srna, "rgb", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_CHAN_RGB); RNA_def_property_ui_text(prop, "RGB", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_CHAN_A); RNA_def_property_ui_text(prop, "Alpha", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_crop(StructRNA *srna) @@ -1074,6 +1268,7 @@ static void def_cmp_crop(StructRNA *srna) prop = RNA_def_property(srna, "crop_size", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); RNA_def_property_ui_text(prop, "Crop Image Size", "Whether to crop the size of the input image"); + RNA_def_property_update(prop, 0, "rna_Node_update"); RNA_def_struct_sdna_from(srna, "NodeTwoXYs", "storage"); @@ -1081,21 +1276,25 @@ static void def_cmp_crop(StructRNA *srna) RNA_def_property_int_sdna(prop, NULL, "x1"); RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "X1", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "x2", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "x2"); RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "X2", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "y1", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "y1"); RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "Y1", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "y2", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "y2"); RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "Y2", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_dblur(StructRNA *srna) @@ -1106,42 +1305,50 @@ static void def_cmp_dblur(StructRNA *srna) prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "iter"); - RNA_def_property_range(prop, 1, 128); + RNA_def_property_range(prop, 1, 32); RNA_def_property_ui_text(prop, "Iterations", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "wrap", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "wrap", 1); RNA_def_property_ui_text(prop, "Wrap", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "center_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "center_x"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Center X", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "center_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "center_y"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Center Y", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "distance"); RNA_def_property_range(prop, -1.0f, 1.0f); RNA_def_property_ui_text(prop, "Distance", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "angle"); RNA_def_property_range(prop, 0.0f, 360.0f); RNA_def_property_ui_text(prop, "Angle", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "spin", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "spin"); RNA_def_property_range(prop, -360.0f, 360.0f); RNA_def_property_ui_text(prop, "Spin", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "zoom", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "zoom"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Zoom", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_bilateral_blur(StructRNA *srna) @@ -1154,16 +1361,19 @@ static void def_cmp_bilateral_blur(StructRNA *srna) RNA_def_property_int_sdna(prop, NULL, "iter"); RNA_def_property_range(prop, 1, 128); RNA_def_property_ui_text(prop, "Iterations", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "sigma_color", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sigma_color"); RNA_def_property_range(prop, 0.01f, 3.0f); RNA_def_property_ui_text(prop, "Color Sigma", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "sigma_space", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sigma_space"); RNA_def_property_range(prop, 0.01f, 30.0f); RNA_def_property_ui_text(prop, "Space Sigma", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_premul_key(StructRNA *srna) @@ -1180,6 +1390,7 @@ static void def_cmp_premul_key(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, type_items); RNA_def_property_ui_text(prop, "Mapping", "Conversion between premultiplied alpha and key alpha"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } @@ -1195,12 +1406,12 @@ static void def_cmp_glare(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; - /*static EnumPropertyItem quality_items[] = { + static EnumPropertyItem quality_items[] = { {0, "HIGH", 0, "High", ""}, {1, "MEDIUM", 0, "Medium", ""}, {2, "LOW", 0, "Low", ""}, {0, NULL, 0, NULL, NULL} - };*/ + }; RNA_def_struct_sdna_from(srna, "NodeGlare", "storage"); @@ -1208,55 +1419,66 @@ static void def_cmp_glare(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, type_items); RNA_def_property_ui_text(prop, "Glare Type", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "quality", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "quality"); - RNA_def_property_enum_items(prop, type_items); + RNA_def_property_enum_items(prop, quality_items); RNA_def_property_ui_text(prop, "Quality", "If not set to high quality, the effect will be applied to a low-res copy of the source image"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "iter"); RNA_def_property_range(prop, 2, 5); RNA_def_property_ui_text(prop, "Iterations", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "color_modulation", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "colmod"); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Color Modulation", ""); + RNA_def_property_ui_text(prop, "Color Modulation", "Amount of Color Modulation, modulates colors of streaks and ghosts for a spectral dispersion effect"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "mix", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "mix"); RNA_def_property_range(prop, -1.0f, 1.0f); RNA_def_property_ui_text(prop, "Mix", "-1 is original image only, 0 is exact 50/50 mix, 1 is processed image only"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "threshold"); RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "Threshold", "The glare filter will only be applied to pixels brighter than this value"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "streaks", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "angle"); RNA_def_property_range(prop, 2, 16); RNA_def_property_ui_text(prop, "Streaks", "Total number of streaks"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "angle_offset", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "angle_ofs"); RNA_def_property_range(prop, 0.0f, 180.0f); RNA_def_property_ui_text(prop, "Angle Offset", "Streak angle offset in degrees"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "fade", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fade"); RNA_def_property_range(prop, 0.75f, 1.0f); RNA_def_property_ui_text(prop, "Fade", "Streak fade-out factor"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "rotate_45", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "angle", 1); RNA_def_property_ui_text(prop, "Rotate 45", "Simple star filter: add 45 degree rotation offset"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "size", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "size"); RNA_def_property_range(prop, 6, 9); RNA_def_property_ui_text(prop, "Size", "Glow/glare size (not actual size; relative to initial size of bright area of pixels)"); + RNA_def_property_update(prop, 0, "rna_Node_update"); /* TODO */ } @@ -1277,45 +1499,49 @@ static void def_cmp_tonemap(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, type_items); RNA_def_property_ui_text(prop, "Tonemap Type", ""); - - /* TODO: if type==0 { */ + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "key", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "key"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Key", "The value the average luminance is mapped to"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_range(prop, 0.001f, 10.0f); RNA_def_property_ui_text(prop, "Offset", "Normally always 1, but can be used as an extra control to alter the brightness curve"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "gamma"); RNA_def_property_range(prop, 0.001f, 3.0f); RNA_def_property_ui_text(prop, "Gamma", "If not used, set to 1"); - - /* TODO: } else { */ + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "intensity", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "f"); RNA_def_property_range(prop, -8.0f, 8.0f); RNA_def_property_ui_text(prop, "Intensity", "If less than zero, darkens image; otherwise, makes it brighter"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "m"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Contrast", "Set to 0 to use estimate from input image"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "adaptation", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "a"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Adaptation", "If 0, global; if 1, based on pixel intensity"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "correction", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "c"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Color Correction", "If 0, same for all channels; if 1, each independent"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_cmp_lensdist(StructRNA *srna) @@ -1327,16 +1553,17 @@ static void def_cmp_lensdist(StructRNA *srna) prop = RNA_def_property(srna, "projector", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "proj", 1); RNA_def_property_ui_text(prop, "Projector", "Enable/disable projector mode. Effect is applied in horizontal direction only."); - - /* TODO: if proj mode is off { */ + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "jitter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "jit", 1); RNA_def_property_ui_text(prop, "Jitter", "Enable/disable jittering; faster, but also noisier"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "fit", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "fit", 1); RNA_def_property_ui_text(prop, "Fit", "For positive distortion factor only: scale image such that black areas are not visible"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } @@ -1352,6 +1579,7 @@ static void def_tex_output(StructRNA *srna) prop = RNA_def_property(srna, "output_name", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_ui_text(prop, "Output Name", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_tex_image(StructRNA *srna) @@ -1362,6 +1590,7 @@ static void def_tex_image(StructRNA *srna) RNA_def_property_pointer_sdna(prop, NULL, "storage"); RNA_def_property_struct_type(prop, "ImageUser"); RNA_def_property_ui_text(prop, "Settings", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); } static void def_tex_bricks(StructRNA *srna) @@ -1372,21 +1601,25 @@ static void def_tex_bricks(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "custom3"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Offset Amount", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "offset_frequency", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom1"); RNA_def_property_range(prop, 2, 99); RNA_def_property_ui_text(prop, "Offset Frequency", "Offset every N rows"); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "squash", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "custom4"); RNA_def_property_range(prop, 0.0f, 99.0f); RNA_def_property_ui_text(prop, "Squash Amount", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "squash_frequency", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); RNA_def_property_range(prop, 2, 99); RNA_def_property_ui_text(prop, "Squash Frequency", "Squash every N rows"); + RNA_def_property_update(prop, 0, "rna_Node_update"); } /* -------------------------------------------------------------------------- */ @@ -1478,6 +1711,8 @@ static void rna_def_nodetree(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Node Tree", "Node tree consisting of linked nodes used for materials, textures and compositing."); RNA_def_struct_sdna(srna, "bNodeTree"); RNA_def_struct_ui_icon(srna, ICON_NODE); + + rna_def_animdata_common(srna); prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL); diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index be4f131a6d6..69424649b3b 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -64,7 +64,7 @@ DefNode( CompositorNode, CMP_NODE_VECBLUR, def_cmp_vector_blur, "VECBL DefNode( CompositorNode, CMP_NODE_SEPRGBA, 0, "SEPRGBA", SepRGBA, "Separate RGBA", "" ) DefNode( CompositorNode, CMP_NODE_SEPHSVA, 0, "SEPHSVA", SepHSVA, "Separate HSVA", "" ) DefNode( CompositorNode, CMP_NODE_SETALPHA, 0, "SETALPHA", SetAlpha, "Set Alpha", "" ) -DefNode( CompositorNode, CMP_NODE_HUE_SAT, 0, "HUE_SAT", HueSat, "Hue/Saturation", "" ) +DefNode( CompositorNode, CMP_NODE_HUE_SAT, def_cmp_hue_saturation, "HUE_SAT", HueSat, "Hue/Saturation", "" ) DefNode( CompositorNode, CMP_NODE_IMAGE, def_cmp_image, "IMAGE", Image, "Image", "" ) DefNode( CompositorNode, CMP_NODE_R_LAYERS, def_cmp_render_layers, "R_LAYERS", RLayers, "Render Layers", "" ) DefNode( CompositorNode, CMP_NODE_COMPOSITE, 0, "COMPOSITE", Composite, "Composite", "" ) @@ -104,7 +104,7 @@ DefNode( CompositorNode, CMP_NODE_PREMULKEY, def_cmp_premul_key, "PREMU DefNode( CompositorNode, CMP_NODE_GLARE, def_cmp_glare, "GLARE", Glare, "Glare", "" ) DefNode( CompositorNode, CMP_NODE_TONEMAP, def_cmp_tonemap, "TONEMAP", Tonemap, "Tonemap", "" ) DefNode( CompositorNode, CMP_NODE_LENSDIST, def_cmp_lensdist, "LENSDIST", Lensdist, "Lensdist", "" ) -DefNode( CompositorNode, CMP_NODE_VIEW_LEVELS, 0, "LEVELS", Levels, "Levels", "" ) +DefNode( CompositorNode, CMP_NODE_VIEW_LEVELS, def_cmp_levels, "LEVELS", Levels, "Levels", "" ) DefNode( CompositorNode, CMP_NODE_COLOR_MATTE, def_cmp_color_matte, "COLOR_MATTE", ColorMatte, "Color Matte", "" ) DefNode( CompositorNode, CMP_NODE_DIST_MATTE, def_cmp_distance_matte, "DISTANCE_MATTE", DistanceMatte, "Distance Matte", "" ) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 3d43dfdfc2c..a2b4d6d7335 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -31,6 +31,7 @@ #include "rna_internal.h" +#include "DNA_action_types.h" #include "DNA_customdata_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" @@ -82,6 +83,8 @@ EnumPropertyItem object_type_items[] = { #ifdef RNA_RUNTIME +#include "BLI_arithb.h" + #include "DNA_key_types.h" #include "BKE_armature.h" @@ -103,6 +106,12 @@ void rna_Object_update(bContext *C, PointerRNA *ptr) DAG_id_flush_update(ptr->id.data, OB_RECALC_OB); } +void rna_Object_matrix_update(bContext *C, PointerRNA *ptr) +{ + ED_object_apply_obmat(ptr->id.data); + rna_Object_update(C, ptr); +} + void rna_Object_update_data(bContext *C, PointerRNA *ptr) { DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA); @@ -440,6 +449,43 @@ static void rna_Object_active_particle_system_index_set(struct PointerRNA *ptr, psys_set_current_num(ob, value); } +/* rotation - euler angles */ +static void rna_Object_rotation_euler_get(PointerRNA *ptr, float *value) +{ + Object *ob= ptr->data; + + if(ob->rotmode == ROT_MODE_AXISANGLE) /* default XYZ eulers */ + AxisAngleToEulO(&ob->quat[1], ob->quat[0], value, EULER_ORDER_DEFAULT); + else if(ob->rotmode == ROT_MODE_QUAT) /* default XYZ eulers */ + QuatToEul(ob->quat, value); + else + VECCOPY(value, ob->rot); +} + +/* rotation - euler angles */ +static void rna_Object_rotation_euler_set(PointerRNA *ptr, const float *value) +{ + Object *ob= ptr->data; + + if(ob->rotmode == ROT_MODE_AXISANGLE) /* default XYZ eulers */ + EulOToAxisAngle((float *)value, EULER_ORDER_DEFAULT, &ob->quat[1], &ob->quat[0]); + else if(ob->rotmode == ROT_MODE_QUAT) /* default XYZ eulers */ + EulToQuat((float*)value, ob->quat); + else + VECCOPY(ob->rot, value); +} + +static void rna_Object_rotation_mode_set(PointerRNA *ptr, int value) +{ + Object *ob= ptr->data; + + /* use API Method for conversions... */ + BKE_rotMode_change_values(ob->quat, ob->rot, ob->rotmode, (short)value); + + /* finally, set the new rotation type */ + ob->rotmode= value; +} + static PointerRNA rna_MaterialSlot_material_get(PointerRNA *ptr) { Object *ob= (Object*)ptr->id.data; @@ -1045,6 +1091,18 @@ static void rna_def_object(BlenderRNA *brna) {OB_DUPLIFACES, "FACES", 0, "Faces", "Duplicate child objects on all faces."}, {OB_DUPLIGROUP, "GROUP", 0, "Group", "Enable group instancing."}, {0, NULL, 0, NULL, NULL}}; + + // XXX: this RNA enum define is currently duplicated for objects, since there is some text here which is not applicable + static EnumPropertyItem prop_rotmode_items[] = { + {ROT_MODE_QUAT, "QUATERNION", 0, "Quaternion (WXYZ)", "No Gimbal Lock."}, + {ROT_MODE_XYZ, "XYZ", 0, "XYZ Euler", "XYZ Rotation Order. Prone to Gimbal Lock. (Default)"}, + {ROT_MODE_XZY, "XZY", 0, "XZY Euler", "XZY Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_YXZ, "YXZ", 0, "YXZ Euler", "YXZ Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_YZX, "YZX", 0, "YZX Euler", "YZX Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_ZXY, "ZXY", 0, "ZXY Euler", "ZXY Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_ZYX, "ZYX", 0, "ZYX Euler", "ZYX Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_AXISANGLE, "AXIS_ANGLE", 0, "Axis Angle", "Axis Angle (W+XYZ). Defines a rotation around some axis defined by 3D-Vector."}, + {0, NULL, 0, NULL, NULL}}; int matrix_dimsize[]= {4, 4}; @@ -1161,37 +1219,72 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_SHADING, NULL); /* transform */ - prop= RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_float_sdna(prop, NULL, "loc"); RNA_def_property_ui_text(prop, "Location", "Location of the object."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); - - prop= RNA_def_property(srna, "delta_location", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_float_sdna(prop, NULL, "dloc"); - RNA_def_property_ui_text(prop, "Delta Location", "Extra added translation to object location."); + + prop= RNA_def_property(srna, "rotation_quaternion", PROP_FLOAT, PROP_QUATERNION); + RNA_def_property_float_sdna(prop, NULL, "quat"); + RNA_def_property_ui_text(prop, "Quaternion Rotation", "Rotation in Quaternions."); + RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); + + /* XXX: for axis-angle, it would have been nice to have 2 separate fields for UI purposes, but + * having a single one is better for Keyframing and other property-management situations... + */ + prop= RNA_def_property(srna, "rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE); + RNA_def_property_float_sdna(prop, NULL, "quat"); + // TODO: we may need some validation funcs + RNA_def_property_ui_text(prop, "Axis-Angle Rotation", "Angle of Rotation for Axis-Angle rotation representation."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); - prop= RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER); + prop= RNA_def_property(srna, "rotation_euler", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "rot"); - RNA_def_property_ui_text(prop, "Rotation", "Rotation of the object."); + RNA_def_property_float_funcs(prop, "rna_Object_rotation_euler_get", "rna_Object_rotation_euler_set", NULL); + RNA_def_property_ui_text(prop, "Euler Rotation", "Rotation in Eulers."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); - - prop= RNA_def_property(srna, "delta_rotation", PROP_FLOAT, PROP_EULER); - RNA_def_property_float_sdna(prop, NULL, "drot"); - RNA_def_property_ui_text(prop, "Delta Rotation", "Extra added rotation to the rotation of the object."); + + prop= RNA_def_property(srna, "rotation_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "rotmode"); + RNA_def_property_enum_items(prop, prop_rotmode_items); // XXX move to using a single define of this someday + RNA_def_property_enum_funcs(prop, NULL, "rna_Object_rotation_mode_set", NULL); + RNA_def_property_ui_text(prop, "Rotation Mode", ""); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_ui_text(prop, "Scale", "Scaling of the object."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); - + + /* delta transforms */ + prop= RNA_def_property(srna, "delta_location", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_float_sdna(prop, NULL, "dloc"); + RNA_def_property_ui_text(prop, "Delta Location", "Extra added translation to object location."); + RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); + + prop= RNA_def_property(srna, "delta_rotation_euler", PROP_FLOAT, PROP_EULER); + RNA_def_property_float_sdna(prop, NULL, "drot"); + RNA_def_property_ui_text(prop, "Delta Rotation (Euler)", "Extra added rotation to the rotation of the object (when using Euler rotations)."); + RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); + + prop= RNA_def_property(srna, "delta_rotation_quaternion", PROP_FLOAT, PROP_QUATERNION); + RNA_def_property_float_sdna(prop, NULL, "dquat"); + RNA_def_property_ui_text(prop, "Delta Rotation (Quaternion)", "Extra added rotation to the rotation of the object (when using Quaternion rotations)."); + RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); + +#if 0 // XXX not supported well yet... + prop= RNA_def_property(srna, "delta_rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE); + RNA_def_property_float_sdna(prop, NULL, "dquat"); + RNA_def_property_ui_text(prop, "Delta Rotation (Axis Angle)", "Extra added rotation to the rotation of the object (when using Axis-Angle rotations)."); + RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); +#endif + prop= RNA_def_property(srna, "delta_scale", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "dsize"); RNA_def_property_ui_text(prop, "Delta Scale", "Extra added scaling to the scale of the object."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); - + + /* transform locks */ prop= RNA_def_property(srna, "lock_location", PROP_BOOLEAN, PROP_XYZ); RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_LOCX); RNA_def_property_array(prop, 3); @@ -1201,6 +1294,14 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_ROTX); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Lock Rotation", "Lock editing of rotation in the interface."); + // XXX this is sub-optimal - it really should be included above, but due to technical reasons we can't do this! + prop= RNA_def_property(srna, "lock_rotation_w", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_ROTW); + RNA_def_property_ui_text(prop, "Lock Rotation (4D Angle)", "Lock editing of 'angle' component of four-component rotations in the interface."); + // XXX this needs a better name + prop= RNA_def_property(srna, "lock_rotations_4d", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_ROT4D); + RNA_def_property_ui_text(prop, "Lock Rotations (4D)", "Lock editing of four component rotations by components (instead of as Eulers)."); prop= RNA_def_property(srna, "lock_scale", PROP_BOOLEAN, PROP_XYZ); RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_SCALEX); @@ -1212,6 +1313,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "obmat"); RNA_def_property_multi_array(prop, 2, matrix_dimsize); RNA_def_property_ui_text(prop, "Matrix", "Transformation matrix."); + RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_matrix_update"); /* collections */ prop= RNA_def_property(srna, "constraints", PROP_COLLECTION, PROP_NONE); @@ -1223,14 +1325,13 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting the geometric data of the Object."); /* game engine */ - - prop= RNA_def_property(srna, "game", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "game", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "GameObjectSettings"); RNA_def_property_pointer_funcs(prop, "rna_Object_game_settings_get", NULL, NULL); RNA_def_property_ui_text(prop, "Game Settings", "Game engine related settings for the object."); /* vertex groups */ - prop= RNA_def_property(srna, "vertex_groups", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "defbase", NULL); RNA_def_property_struct_type(prop, "VertexGroup"); @@ -1249,7 +1350,6 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Object_update_data"); /* empty */ - prop= RNA_def_property(srna, "empty_draw_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "empty_drawtype"); RNA_def_property_enum_items(prop, empty_drawtype_items); @@ -1263,7 +1363,6 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); /* render */ - prop= RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "index"); RNA_def_property_ui_text(prop, "Pass Index", "Index # for the IndexOB render pass."); @@ -1274,7 +1373,6 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); /* physics */ - prop= RNA_def_property(srna, "field", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "pd"); RNA_def_property_struct_type(prop, "FieldSettings"); @@ -1308,7 +1406,6 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); /* restrict */ - prop= RNA_def_property(srna, "restrict_view", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_VIEW); RNA_def_property_ui_text(prop, "Restrict View", "Restrict visibility in the viewport."); @@ -1325,20 +1422,9 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); /* anim */ - rna_def_animdata_common(srna); - prop= RNA_def_property(srna, "draw_keys", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "ipoflag", OB_DRAWKEY); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); // update ipo flag indirect - RNA_def_property_ui_text(prop, "Draw Keys", "Draw object as key positions."); - RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_update"); - - prop= RNA_def_property(srna, "draw_keys_selected", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "ipoflag", OB_DRAWKEYSEL); - RNA_def_property_ui_text(prop, "Draw Keys Selected", "Limit the drawing of object keys to selected."); - RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); - + /* duplicates */ prop= RNA_def_property(srna, "track_override_parent", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "transflag", OB_POWERTRACK); RNA_def_property_ui_text(prop, "Track Override Parent", "Override rotation from parenting."); @@ -1406,8 +1492,12 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Dupli Frames Off", "Recurring frames to exclude from the Dupliframes."); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Object_update"); - /* time offset */ + prop= RNA_def_property(srna, "dupli_list", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "duplilist", NULL); + RNA_def_property_struct_type(prop, "DupliObject"); + RNA_def_property_ui_text(prop, "Dupli list", "Object duplis."); + /* time offset */ prop= RNA_def_property(srna, "time_offset", PROP_FLOAT, PROP_NONE|PROP_UNIT_TIME); RNA_def_property_float_sdna(prop, NULL, "sf"); RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); @@ -1434,7 +1524,6 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Object_update"); /* drawing */ - prop= RNA_def_property(srna, "max_draw_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "dt"); RNA_def_property_enum_items(prop, drawtype_items); @@ -1501,7 +1590,6 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pose", "Current pose for armatures."); /* shape keys */ - prop= RNA_def_property(srna, "shape_key_lock", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "shapeflag", OB_SHAPE_LOCK); RNA_def_property_boolean_funcs(prop, NULL, "rna_Object_shape_key_lock_set"); @@ -1523,12 +1611,43 @@ static void rna_def_object(BlenderRNA *brna) RNA_api_object(srna); } +static void rna_def_dupli_object(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "DupliObject", NULL); + RNA_def_struct_sdna(srna, "DupliObject"); + RNA_def_struct_ui_text(srna, "Dupli Object", "Dupli Object data."); + /* RNA_def_struct_ui_icon(srna, ICON_OBJECT_DATA); */ + + prop= RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); + /* RNA_def_property_struct_type(prop, "Object"); */ + RNA_def_property_pointer_sdna(prop, NULL, "ob"); + /* RNA_def_property_pointer_funcs(prop, "rna_DupliObject_object_get", NULL, NULL); */ + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Object", "Object this DupliObject represents."); + + prop= RNA_def_property(srna, "ob_matrix", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "omat"); + RNA_def_property_array(prop, 16); + RNA_def_property_ui_text(prop, "Object Matrix", "Object transformation matrix."); + + prop= RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "mat"); + RNA_def_property_array(prop, 16); + RNA_def_property_ui_text(prop, "DupliObject Matrix", "DupliObject transformation matrix."); + + /* TODO: DupliObject has more properties that can be wrapped */ +} + void RNA_def_object(BlenderRNA *brna) { rna_def_object(brna); rna_def_object_game_settings(brna); rna_def_vertex_group(brna); rna_def_material_slot(brna); + rna_def_dupli_object(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 3541bc2b1b0..098604c1eab 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -28,76 +28,402 @@ #include <stdlib.h> #include <stdio.h> +#include <string.h> +#include <time.h> #include "RNA_define.h" #include "RNA_types.h" +#include "DNA_object_types.h" + +#include "BLO_sys_types.h" /* needed for intptr_t used in ED_mesh.h */ + +#include "ED_mesh.h" + #ifdef RNA_RUNTIME -#include "MEM_guardedalloc.h" +#include "BKE_main.h" +#include "BKE_global.h" +#include "BKE_context.h" +#include "BKE_report.h" +#include "BKE_object.h" +#include "BKE_mesh.h" +#include "BKE_DerivedMesh.h" #include "BKE_customdata.h" -#include "BKE_DerivedMesh.h" +#include "BKE_anim.h" +#include "BKE_depsgraph.h" +#include "BKE_displist.h" +#include "BKE_font.h" +#include "BKE_mball.h" + +#include "BLI_arithb.h" #include "DNA_mesh_types.h" #include "DNA_scene_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_curve_types.h" +#include "DNA_modifier_types.h" + +#include "MEM_guardedalloc.h" -/* copied from init_render_mesh (render code) */ -Mesh *rna_Object_create_render_mesh(Object *ob, Scene *scene) +/* copied from Mesh_getFromObject and adapted to RNA interface */ +/* settings: 0 - preview, 1 - render */ +static Mesh *rna_Object_create_mesh(Object *ob, bContext *C, ReportList *reports, int apply_modifiers, int settings) { - CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; - DerivedMesh *dm; - Mesh *me; + Mesh *tmpmesh; + Curve *tmpcu = NULL; + Object *tmpobj = NULL; + int render = settings, i; + int cage = !apply_modifiers; + Scene *sce = CTX_data_scene(C); + + /* perform the mesh extraction based on type */ + switch (ob->type) { + case OB_FONT: + case OB_CURVE: + case OB_SURF: + + /* copies object and modifiers (but not the data) */ + tmpobj= copy_object(ob); + tmpcu = (Curve *)tmpobj->data; + tmpcu->id.us--; + + /* if getting the original caged mesh, delete object modifiers */ + if( cage ) + object_free_modifiers(tmpobj); + + /* copies the data */ + tmpobj->data = copy_curve( (Curve *) ob->data ); + +#if 0 + /* copy_curve() sets disp.first null, so currently not need */ + { + Curve *cu; + cu = (Curve *)tmpobj->data; + if( cu->disp.first ) + MEM_freeN( cu->disp.first ); + cu->disp.first = NULL; + } - /* TODO: other types */ - if(ob->type != OB_MESH) - return NULL; +#endif + + /* get updated display list, and convert to a mesh */ + makeDispListCurveTypes( sce, tmpobj, 0 ); + nurbs_to_mesh( tmpobj ); + + /* nurbs_to_mesh changes the type to a mesh, check it worked */ + if (tmpobj->type != OB_MESH) { + free_libblock_us( &(CTX_data_main(C)->object), tmpobj ); + BKE_report(reports, RPT_ERROR, "cant convert curve to mesh. Does the curve have any segments?"); + return NULL; + } + tmpmesh = tmpobj->data; + free_libblock_us( &G.main->object, tmpobj ); + break; + + case OB_MBALL: + /* metaballs don't have modifiers, so just convert to mesh */ + ob = find_basis_mball( sce, ob ); + /* todo, re-generatre for render-res */ + /* metaball_polygonize(scene, ob) */ + + tmpmesh = add_mesh("Mesh"); + mball_to_mesh( &ob->disp, tmpmesh ); + break; + + case OB_MESH: + /* copies object and modifiers (but not the data) */ + if (cage) { + /* copies the data */ + tmpmesh = copy_mesh( ob->data ); + /* if not getting the original caged mesh, get final derived mesh */ + } else { + /* Make a dummy mesh, saves copying */ + DerivedMesh *dm; + /* CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; */ + CustomDataMask mask = CD_MASK_MESH; /* this seems more suitable, exporter, + for example, needs CD_MASK_MDEFORMVERT */ + + /* Write the display mesh into the dummy mesh */ + if (render) + dm = mesh_create_derived_render( sce, ob, mask ); + else + dm = mesh_create_derived_view( sce, ob, mask ); + + tmpmesh = add_mesh( "Mesh" ); + DM_to_mesh( dm, tmpmesh ); + dm->release( dm ); + } + + break; + default: + BKE_report(reports, RPT_ERROR, "Object does not have geometry data"); + return NULL; + } + + /* Copy materials to new mesh */ + switch (ob->type) { + case OB_SURF: + tmpmesh->totcol = tmpcu->totcol; + + /* free old material list (if it exists) and adjust user counts */ + if( tmpcu->mat ) { + for( i = tmpcu->totcol; i-- > 0; ) { + /* are we an object material or data based? */ + if (ob->colbits & 1<<i) + tmpmesh->mat[i] = ob->mat[i]; + else + tmpmesh->mat[i] = tmpcu->mat[i]; + + if (tmpmesh->mat[i]) + tmpmesh->mat[i]->id.us++; + } + } + break; + +#if 0 + /* Crashes when assigning the new material, not sure why */ + case OB_MBALL: + tmpmb = (MetaBall *)ob->data; + tmpmesh->totcol = tmpmb->totcol; + + /* free old material list (if it exists) and adjust user counts */ + if( tmpmb->mat ) { + for( i = tmpmb->totcol; i-- > 0; ) { + tmpmesh->mat[i] = tmpmb->mat[i]; /* CRASH HERE ??? */ + if (tmpmesh->mat[i]) { + tmpmb->mat[i]->id.us++; + } + } + } + break; +#endif + + case OB_MESH: + if (!cage) { + Mesh *origmesh= ob->data; + tmpmesh->flag= origmesh->flag; + tmpmesh->mat = MEM_dupallocN(origmesh->mat); + tmpmesh->totcol = origmesh->totcol; + tmpmesh->smoothresh= origmesh->smoothresh; + if( origmesh->mat ) { + for( i = origmesh->totcol; i-- > 0; ) { + /* are we an object material or data based? */ + if (ob->colbits & 1<<i) + tmpmesh->mat[i] = ob->mat[i]; + else + tmpmesh->mat[i] = origmesh->mat[i]; + if (tmpmesh->mat[i]) + tmpmesh->mat[i]->id.us++; + } + } + } + break; + } /* end copy materials */ + + /* we don't assign it to anything */ + tmpmesh->id.us--; - dm= mesh_create_derived_render(scene, ob, mask); + /* make sure materials get updated in objects */ + test_object_materials( ( ID * ) tmpmesh ); + + return tmpmesh; +} + +/* When no longer needed, duplilist should be freed with Object.free_duplilist */ +static void rna_Object_create_duplilist(Object *ob, bContext *C, ReportList *reports) +{ + if (!(ob->transflag & OB_DUPLI)) { + BKE_report(reports, RPT_ERROR, "Object does not have duplis."); + return; + } + + /* free duplilist if a user forgets to */ + if (ob->duplilist) { + BKE_reportf(reports, RPT_WARNING, "Object.dupli_list has not been freed."); + + free_object_duplilist(ob->duplilist); + ob->duplilist= NULL; + } + + ob->duplilist= object_duplilist(CTX_data_scene(C), ob); - if(!dm) - return NULL; + /* ob->duplilist should now be freed with Object.free_duplilist */ +} + +static void rna_Object_free_duplilist(Object *ob, ReportList *reports) +{ + if (ob->duplilist) { + free_object_duplilist(ob->duplilist); + ob->duplilist= NULL; + } +} + +static bDeformGroup *rna_Object_add_vertex_group(Object *ob, char *group_name) +{ + return ED_vgroup_add_name(ob, group_name); +} + +static void rna_Object_add_vertex_to_group(Object *ob, int vertex_index, bDeformGroup *def, float weight, int assignmode) +{ + /* creates dverts if needed */ + ED_vgroup_vert_add(ob, def, vertex_index, weight, assignmode); +} - me= add_mesh("tmp_render_mesh"); - me->id.us--; /* we don't assign it to anything */ - DM_to_mesh(dm, me); - dm->release(dm); +/* copied from old API Object.makeDisplayList (Object.c) */ +static void rna_Object_make_display_list(Object *ob, bContext *C) +{ + Scene *sce= CTX_data_scene(C); + if (ob->type == OB_FONT) { + Curve *cu = ob->data; + freedisplist(&cu->disp); + BKE_text_to_curve(sce, ob, CU_LEFT); + } - { /* update the material */ - short i, *totcol =give_totcolp(ob); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); +} - /* free the current material list */ - if(me->mat) - MEM_freeN((void *)me->mat); +static Object *rna_Object_find_armature(Object *ob) +{ + Object *ob_arm = NULL; - me->mat= (Material **)MEM_callocN(sizeof(void *)*(*totcol), "matarray"); + if (ob->type != OB_MESH) return NULL; - for(i=0; i<*totcol; i++) { - Material *mat= give_current_material(ob, i+1); - if(mat) { - me->mat[i]= mat; - mat->id.us++; + if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { + ob_arm = ob->parent; + } + else { + ModifierData *mod = (ModifierData*)ob->modifiers.first; + while (mod) { + if (mod->type == eModifierType_Armature) { + ob_arm = ((ArmatureModifierData*)mod)->object; } + + mod = mod->next; } } - return me; + return ob_arm; } +int rna_Object_is_visible(Object *ob, bContext *C) +{ + return ob->lay & CTX_data_scene(C)->lay; +} + +/* +static void rna_Mesh_assign_verts_to_group(Object *ob, bDeformGroup *group, int *indices, int totindex, float weight, int assignmode) +{ + if (ob->type != OB_MESH) { + BKE_report(reports, RPT_ERROR, "Object should be of MESH type."); + return; + } + + Mesh *me = (Mesh*)ob->data; + int group_index = get_defgroup_num(ob, group); + if (group_index == -1) { + BKE_report(reports, RPT_ERROR, "No deform groups assigned to mesh."); + return; + } + + if (assignmode != WEIGHT_REPLACE && assignmode != WEIGHT_ADD && assignmode != WEIGHT_SUBTRACT) { + BKE_report(reports, RPT_ERROR, "Bad assignment mode." ); + return; + } + + // makes a set of dVerts corresponding to the mVerts + if (!me->dvert) + create_dverts(&me->id); + + // loop list adding verts to group + for (i= 0; i < totindex; i++) { + if(i < 0 || i >= me->totvert) { + BKE_report(reports, RPT_ERROR, "Bad vertex index in list."); + return; + } + + add_vert_defnr(ob, group_index, i, weight, assignmode); + } +} +*/ + #else void RNA_api_object(StructRNA *srna) { FunctionRNA *func; - PropertyRNA *prop; - - func= RNA_def_function(srna, "create_render_mesh", "rna_Object_create_render_mesh"); - RNA_def_function_ui_description(func, "Create a Mesh datablock with all modifiers applied."); - prop= RNA_def_pointer(func, "scene", "Scene", "", ""); - RNA_def_property_flag(prop, PROP_REQUIRED); - prop= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object, remove it if it is only used for export."); - RNA_def_function_return(func, prop); + PropertyRNA *parm; + + static EnumPropertyItem mesh_type_items[] = { + {0, "PREVIEW", 0, "Preview", "Apply modifier preview settings."}, + {1, "RENDER", 0, "Render", "Apply modifier render settings."}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem assign_mode_items[] = { + {WEIGHT_REPLACE, "REPLACE", 0, "Replace", "Replace."}, /* TODO: more meaningful descriptions */ + {WEIGHT_ADD, "ADD", 0, "Add", "Add."}, + {WEIGHT_SUBTRACT, "SUBTRACT", 0, "Subtract", "Subtract."}, + {0, NULL, 0, NULL, NULL} + }; + + /* mesh */ + func= RNA_def_function(srna, "create_mesh", "rna_Object_create_mesh"); + RNA_def_function_ui_description(func, "Create a Mesh datablock with modifiers applied."); + RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS); + parm= RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Modifier settings to apply."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object, remove it if it is only used for export."); + RNA_def_function_return(func, parm); + + /* duplis */ + func= RNA_def_function(srna, "create_dupli_list", "rna_Object_create_duplilist"); + RNA_def_function_ui_description(func, "Create a list of dupli objects for this object, needs to be freed manually with free_dupli_list."); + RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS); + + func= RNA_def_function(srna, "free_dupli_list", "rna_Object_free_duplilist"); + RNA_def_function_ui_description(func, "Free the list of dupli objects."); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + + /* vertex groups */ + func= RNA_def_function(srna, "add_vertex_group", "rna_Object_add_vertex_group"); + RNA_def_function_ui_description(func, "Add vertex group to object."); + parm= RNA_def_string(func, "name", "Group", 0, "", "Vertex group name."); /* optional */ + parm= RNA_def_pointer(func, "group", "VertexGroup", "", "New vertex group."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "add_vertex_to_group", "rna_Object_add_vertex_to_group"); + RNA_def_function_ui_description(func, "Add vertex to a vertex group."); + parm= RNA_def_int(func, "vertex_index", 0, 0, 0, "", "Vertex index.", 0, 0); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "group", "VertexGroup", "", "Vertex group to add vertex to."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_float(func, "weight", 0, 0.0f, 1.0f, "", "Vertex weight.", 0.0f, 1.0f); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_enum(func, "type", assign_mode_items, 0, "", "Vertex assign mode."); + RNA_def_property_flag(parm, PROP_REQUIRED); + + /* Armature */ + func= RNA_def_function(srna, "find_armature", "rna_Object_find_armature"); + RNA_def_function_ui_description(func, "Find armature influencing this object as a parent or via a modifier."); + parm= RNA_def_pointer(func, "ob_arm", "Object", "", "Armature object influencing this object or NULL."); + RNA_def_function_return(func, parm); + + /* DAG */ + func= RNA_def_function(srna, "make_display_list", "rna_Object_make_display_list"); + RNA_def_function_ui_description(func, "Update object's display data."); /* XXX describe better */ + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + + /* View */ + func= RNA_def_function(srna, "is_visible", "rna_Object_is_visible"); + RNA_def_function_ui_description(func, "Determine if object is visible in active scene."); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + parm= RNA_def_boolean(func, "is_visible", 0, "", "Object visibility."); + RNA_def_function_return(func, parm); } #endif diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 3dfbfcccacf..1f0d01ce784 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -617,6 +617,12 @@ static void rna_def_collision(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Collision from Stack", "Pick collision object from modifier stack (softbody only)"); RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); */ + + prop= RNA_def_property(srna, "absorption", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 2); + RNA_def_property_ui_text(prop, "Absorption", "How much of effector force gets lost during collision with this object (in percent)."); + RNA_def_property_update(prop, 0, "rna_CollisionSettings_update"); } static void rna_def_field(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index e6f0a462f03..04b4b1142be 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -254,7 +254,7 @@ static void rna_Particle_redo_child(bContext *C, PointerRNA *ptr) } static void rna_Particle_hair_dynamics(bContext *C, PointerRNA *ptr) { - Scene *scene = CTX_data_scene(C); + /* Scene *scene = CTX_data_scene(C); */ ParticleSystem *psys = (ParticleSystem*)ptr->data; if(psys && !psys->clmd) { @@ -312,9 +312,10 @@ static void rna_PartSettings_start_set(struct PointerRNA *ptr, float value) if(value > settings->end) value = settings->end; - if(settings->type==PART_REACTOR && value < 1.0) - value = 1.0; - else if (value < MINAFRAMEF) + //if(settings->type==PART_REACTOR && value < 1.0) + // value = 1.0; + //else + if (value < MINAFRAMEF) value = MINAFRAMEF; settings->sta = value; @@ -506,7 +507,7 @@ EnumPropertyItem reactor_from_items[] = { static EnumPropertyItem *rna_Particle_from_itemf(bContext *C, PointerRNA *ptr, int *free) { - ParticleSettings *part = ptr->id.data; + /* ParticleSettings *part = ptr->id.data; */ if(C==NULL) { EnumPropertyItem *item= NULL; @@ -522,9 +523,9 @@ static EnumPropertyItem *rna_Particle_from_itemf(bContext *C, PointerRNA *ptr, i return item; } - if(part->type==PART_REACTOR) - return part_reactor_from_items; - else + //if(part->type==PART_REACTOR) + // return part_reactor_from_items; + //else return part_from_items; } @@ -767,7 +768,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) static EnumPropertyItem type_items[] = { {PART_EMITTER, "EMITTER", 0, "Emitter", ""}, - {PART_REACTOR, "REACTOR", 0, "Reactor", ""}, + //{PART_REACTOR, "REACTOR", 0, "Reactor", ""}, {PART_HAIR, "HAIR", 0, "Hair", ""}, {0, NULL, 0, NULL, NULL} }; @@ -986,10 +987,10 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Children", "Apply effectors to children."); RNA_def_property_update(prop, 0, "rna_Particle_redo"); - prop= RNA_def_property(srna, "child_seams", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_CHILD_SEAMS); - RNA_def_property_ui_text(prop, "Use seams", "Use seams to determine parents"); - RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); + //prop= RNA_def_property(srna, "child_seams", PROP_BOOLEAN, PROP_NONE); + //RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_CHILD_SEAMS); + //RNA_def_property_ui_text(prop, "Use seams", "Use seams to determine parents"); + //RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); /* TODO: used somewhere? */ prop= RNA_def_property(srna, "child_render", PROP_BOOLEAN, PROP_NONE); @@ -1871,10 +1872,10 @@ static void rna_def_particle_system(BlenderRNA *brna) /* access to particle settings is redirected through functions */ /* to allow proper id-buttons functionality */ - prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE); //RNA_def_property_pointer_sdna(prop, NULL, "part"); RNA_def_property_struct_type(prop, "ParticleSettings"); - RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_NULL); RNA_def_property_pointer_funcs(prop, "rna_particle_settings_get", "rna_particle_settings_set", NULL); RNA_def_property_ui_text(prop, "Settings", "Particle system settings."); RNA_def_property_update(prop, 0, "rna_Particle_reset"); @@ -1904,9 +1905,10 @@ static void rna_def_particle_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Hair Dynamics", "Enable hair dynamics using cloth simulation."); RNA_def_property_update(prop, 0, "rna_Particle_hair_dynamics"); - prop= RNA_def_property(srna, "cloth", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "cloth", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "clmd"); RNA_def_property_struct_type(prop, "ClothModifier"); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Cloth", "Cloth dynamics for hair"); @@ -2082,7 +2084,8 @@ static void rna_def_particle_system(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Particle_reset"); /* pointcache */ - prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "pointcache"); RNA_def_property_struct_type(prop, "PointCache"); RNA_def_property_ui_text(prop, "Point Cache", ""); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 3a03e7a624d..03ced839ebe 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -23,6 +23,7 @@ */ #include <stdlib.h> +#include <string.h> #include "RNA_define.h" #include "RNA_types.h" @@ -39,8 +40,9 @@ #ifdef RNA_RUNTIME -#include <string.h> - +#include "BIK_api.h" +#include "BKE_action.h" +#include "BKE_armature.h" #include "BLI_arithb.h" #include "DNA_userdef_types.h" @@ -49,8 +51,11 @@ #include "BKE_depsgraph.h" #include "BKE_idprop.h" +#include "ED_object.h" #include "ED_armature.h" +#include "MEM_guardedalloc.h" + static void rna_Pose_update(bContext *C, PointerRNA *ptr) { // XXX when to use this? ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); @@ -58,6 +63,15 @@ static void rna_Pose_update(bContext *C, PointerRNA *ptr) DAG_id_flush_update(ptr->id.data, OB_RECALC_DATA); } +static void rna_Pose_IK_update(bContext *C, PointerRNA *ptr) +{ + // XXX when to use this? ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); + Object *ob= ptr->id.data; + + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + BIK_clear_data(ob->pose); +} + static char *rna_PoseChannel_path(PointerRNA *ptr) { return BLI_sprintfN("pose.pose_channels[\"%s\"]", ((bPoseChannel*)ptr->data)->name); @@ -98,7 +112,7 @@ static void rna_BoneGroup_color_set_set(PointerRNA *ptr, int value) } } -IDProperty *rna_PoseChannel_idproperties(PointerRNA *ptr, int create) +static IDProperty *rna_PoseChannel_idproperties(PointerRNA *ptr, int create) { bPoseChannel *pchan= ptr->data; @@ -110,106 +124,70 @@ IDProperty *rna_PoseChannel_idproperties(PointerRNA *ptr, int create) return pchan->prop; } +static void rna_Pose_ik_solver_set(struct PointerRNA *ptr, int value) +{ + bPose *pose= (bPose*)ptr->data; + + if (pose->iksolver != value) { + // the solver has changed, must clean any temporary structures + BIK_clear_data(pose); + if (pose->ikparam) { + MEM_freeN(pose->ikparam); + pose->ikparam = NULL; + } + pose->iksolver = value; + init_pose_ikparam(pose); + } +} + +static void rna_Pose_ik_solver_update(bContext *C, PointerRNA *ptr) +{ + Object *ob= ptr->id.data; + bPose *pose = ptr->data; + Scene *scene = CTX_data_scene(C); + + pose->flag |= POSE_RECALC; // checks & sorts pose channels + DAG_scene_sort(scene); + + update_pose_constraint_flags(pose); + + object_test_constraints(ob); + + DAG_id_flush_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB); +} + /* rotation - euler angles */ -static void rna_PoseChannel_euler_rotation_get(PointerRNA *ptr, float *value) +static void rna_PoseChannel_rotation_euler_get(PointerRNA *ptr, float *value) { bPoseChannel *pchan= ptr->data; - if(pchan->rotmode == PCHAN_ROT_AXISANGLE) /* default XYZ eulers */ + if(pchan->rotmode == ROT_MODE_AXISANGLE) /* default XYZ eulers */ AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], value, EULER_ORDER_DEFAULT); - else if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers */ + else if(pchan->rotmode == ROT_MODE_QUAT) /* default XYZ eulers */ QuatToEul(pchan->quat, value); else VECCOPY(value, pchan->eul); } /* rotation - euler angles */ -static void rna_PoseChannel_euler_rotation_set(PointerRNA *ptr, const float *value) +static void rna_PoseChannel_rotation_euler_set(PointerRNA *ptr, const float *value) { bPoseChannel *pchan= ptr->data; - if(pchan->rotmode == PCHAN_ROT_AXISANGLE) /* default XYZ eulers */ + if(pchan->rotmode == ROT_MODE_AXISANGLE) /* default XYZ eulers */ EulOToAxisAngle((float *)value, EULER_ORDER_DEFAULT, &pchan->quat[1], &pchan->quat[0]); - else if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers */ + else if(pchan->rotmode == ROT_MODE_QUAT) /* default XYZ eulers */ EulToQuat((float*)value, pchan->quat); else VECCOPY(pchan->eul, value); } -/* rotation - axis angle only */ -static void rna_PoseChannel_rotation_axis_get(PointerRNA *ptr, float *value) -{ - bPoseChannel *pchan= ptr->data; - - if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { - /* axis is stord in quat for now */ - VecCopyf(value, &pchan->quat[1]); - } -} - -/* rotation - axis angle only */ -static void rna_PoseChannel_rotation_axis_set(PointerRNA *ptr, const float *value) -{ - bPoseChannel *pchan= ptr->data; - - if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { - /* axis is stored in quat for now */ - VecCopyf(&pchan->quat[1], (float *)value); - } -} - static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value) { bPoseChannel *pchan= ptr->data; - /* check if any change - if so, need to convert data */ - // TODO: this needs to be generalised at some point to work for objects too... - if (value > 0) { /* to euler */ - if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { - /* axis-angle to euler */ - AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], pchan->eul, value); - } - else if (pchan->rotmode == PCHAN_ROT_QUAT) { - /* quat to euler */ - QuatToEulO(pchan->quat, pchan->eul, value); - } - /* else { no conversion needed } */ - } - else if (value == PCHAN_ROT_QUAT) { /* to quat */ - if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { - /* axis angle to quat */ - float q[4]; - - /* copy to temp var first, since quats and axis-angle are stored in same place */ - QuatCopy(q, pchan->quat); - AxisAngleToQuat(q, &pchan->quat[1], pchan->quat[0]); - } - else if (pchan->rotmode > 0) { - /* euler to quat */ - EulOToQuat(pchan->eul, pchan->rotmode, pchan->quat); - } - /* else { no conversion needed } */ - } - else { /* to axis-angle */ - if (pchan->rotmode > 0) { - /* euler to axis angle */ - EulOToAxisAngle(pchan->eul, pchan->rotmode, &pchan->quat[1], &pchan->quat[0]); - } - else if (pchan->rotmode == PCHAN_ROT_QUAT) { - /* quat to axis angle */ - float q[4]; - - /* copy to temp var first, since quats and axis-angle are stored in same place */ - QuatCopy(q, pchan->quat); - QuatToAxisAngle(q, &pchan->quat[1], &pchan->quat[0]); - } - - /* when converting to axis-angle, we need a special exception for the case when there is no axis */ - if (IS_EQ(pchan->quat[1], pchan->quat[2]) && IS_EQ(pchan->quat[2], pchan->quat[3])) { - /* for now, rotate around y-axis then (so that it simply becomes the roll) */ - pchan->quat[2]= 1.0f; - } - } + /* use API Method for conversions... */ + BKE_rotMode_change_values(pchan->quat, pchan->eul, pchan->rotmode, (short)value); /* finally, set the new rotation type */ pchan->rotmode= value; @@ -236,6 +214,70 @@ static int rna_PoseChannel_has_ik_get(PointerRNA *ptr) return ED_pose_channel_in_IK_chain(ob, pchan); } +StructRNA *rna_IKParam_refine(PointerRNA *ptr) +{ + bIKParam *param = (bIKParam *)ptr->data; + + switch (param->iksolver) { + case IKSOLVER_ITASC: + return &RNA_Itasc; + default: + return &RNA_IKParam; + } +} + +PointerRNA rna_Pose_ikparam_get(struct PointerRNA *ptr) +{ + bPose *pose= (bPose*)ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_IKParam, pose->ikparam); +} + +static StructRNA *rna_Pose_ikparam_typef(PointerRNA *ptr) +{ + bPose *pose= (bPose*)ptr->data; + + switch (pose->iksolver) { + case IKSOLVER_ITASC: + return &RNA_Itasc; + default: + return &RNA_IKParam; + } +} + +static void rna_Itasc_update(bContext *C, PointerRNA *ptr) +{ + Object *ob = ptr->id.data; + bItasc *itasc = ptr->data; + + /* verify values */ + if (itasc->precision < 0.0001f) + itasc->precision = 0.0001f; + if (itasc->minstep < 0.001f) + itasc->minstep = 0.001f; + if (itasc->maxstep < itasc->minstep) + itasc->maxstep = itasc->minstep; + if (itasc->feedback < 0.01f) + itasc->feedback = 0.01f; + if (itasc->feedback > 100.f) + itasc->feedback = 100.f; + if (itasc->maxvel < 0.01f) + itasc->maxvel = 0.01f; + if (itasc->maxvel > 100.f) + itasc->maxvel = 100.f; + BIK_update_param(ob->pose); + + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); +} + +static void rna_Itasc_update_rebuild(bContext *C, PointerRNA *ptr) +{ + Object *ob= ptr->id.data; + bPose *pose = ob->pose; + + pose->flag |= POSE_RECALC; // checks & sorts pose channels + rna_Itasc_update(C, ptr); +} + static PointerRNA rna_PoseChannel_bone_group_get(PointerRNA *ptr) { Object *ob= (Object*)ptr->id.data; @@ -323,7 +365,8 @@ static void rna_Pose_active_bone_group_index_range(PointerRNA *ptr, int *min, in *max= MAX2(0, *max); } -void rna_pose_bgroup_name_index_get(PointerRNA *ptr, char *value, int index) +#if 0 +static void rna_pose_bgroup_name_index_get(PointerRNA *ptr, char *value, int index) { bPose *pose= (bPose*)ptr->data; bActionGroup *grp; @@ -334,7 +377,7 @@ void rna_pose_bgroup_name_index_get(PointerRNA *ptr, char *value, int index) else BLI_strncpy(value, "", sizeof(grp->name)); // XXX if invalid pointer, won't this crash? } -int rna_pose_bgroup_name_index_length(PointerRNA *ptr, int index) +static int rna_pose_bgroup_name_index_length(PointerRNA *ptr, int index) { bPose *pose= (bPose*)ptr->data; bActionGroup *grp; @@ -343,7 +386,7 @@ int rna_pose_bgroup_name_index_length(PointerRNA *ptr, int index) return (grp)? strlen(grp->name): 0; } -void rna_pose_bgroup_name_index_set(PointerRNA *ptr, const char *value, short *index) +static void rna_pose_bgroup_name_index_set(PointerRNA *ptr, const char *value, short *index) { bPose *pose= (bPose*)ptr->data; bActionGroup *grp; @@ -359,7 +402,7 @@ void rna_pose_bgroup_name_index_set(PointerRNA *ptr, const char *value, short *i *index= 0; } -void rna_pose_pgroup_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen) +static void rna_pose_pgroup_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen) { bPose *pose= (bPose*)ptr->data; bActionGroup *grp; @@ -373,6 +416,7 @@ void rna_pose_pgroup_name_set(PointerRNA *ptr, const char *value, char *result, BLI_strncpy(result, "", maxlen); } +#endif #else @@ -428,24 +472,36 @@ static void rna_def_bone_group(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); // TODO: editing the colors for this should result in changes to the color type... - prop= RNA_def_property(srna, "colors", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "colors", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "ThemeBoneColorSet"); RNA_def_property_pointer_sdna(prop, NULL, "cs"); /* NOTE: the DNA data is not really a pointer, but this code works :) */ RNA_def_property_ui_text(prop, "Colors", "Copy of the colors associated with the group's color set."); RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); } +static EnumPropertyItem prop_iksolver_items[] = { + {IKSOLVER_LEGACY, "LEGACY", 0, "Legacy", "Original IK solver."}, + {IKSOLVER_ITASC, "ITASC", 0, "iTaSC", "Multi constraint, stateful IK solver."}, + {0, NULL, 0, NULL, NULL}}; + +static EnumPropertyItem prop_solver_items[] = { + {ITASC_SOLVER_SDLS, "SDLS", 0, "SDLS", "Selective Damped Least Square"}, + {ITASC_SOLVER_DLS, "DLS", 0, "DLS", "Damped Least Square with Numerical Filtering"}, + {0, NULL, 0, NULL, NULL}}; + static void rna_def_pose_channel(BlenderRNA *brna) { + // XXX: this RNA enum define is currently duplicated for objects, since there is some text here which is not applicable static EnumPropertyItem prop_rotmode_items[] = { - {PCHAN_ROT_QUAT, "QUATERNION", 0, "Quaternion (WXYZ)", "No Gimbal Lock (default)"}, - {PCHAN_ROT_XYZ, "XYZ", 0, "XYZ Euler", "XYZ Rotation Order. Prone to Gimbal Lock"}, - {PCHAN_ROT_XZY, "XZY", 0, "XZY Euler", "XZY Rotation Order. Prone to Gimbal Lock"}, - {PCHAN_ROT_YXZ, "YXZ", 0, "YXZ Euler", "YXZ Rotation Order. Prone to Gimbal Lock"}, - {PCHAN_ROT_YZX, "YZX", 0, "YZX Euler", "YZX Rotation Order. Prone to Gimbal Lock"}, - {PCHAN_ROT_ZXY, "ZXY", 0, "ZXY Euler", "ZXY Rotation Order. Prone to Gimbal Lock"}, - {PCHAN_ROT_ZYX, "ZYX", 0, "ZYX Euler", "ZYX Rotation Order. Prone to Gimbal Lock"}, - {PCHAN_ROT_AXISANGLE, "AXIS_ANGLE", 0, "Axis Angle", "Axis Angle (W+XYZ). Defines a rotation around some axis defined by 3D-Vector."}, + {ROT_MODE_QUAT, "QUATERNION", 0, "Quaternion (WXYZ)", "No Gimbal Lock (default)"}, + {ROT_MODE_XYZ, "XYZ", 0, "XYZ Euler", "XYZ Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_XZY, "XZY", 0, "XZY Euler", "XZY Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_YXZ, "YXZ", 0, "YXZ Euler", "YXZ Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_YZX, "YZX", 0, "YZX Euler", "YZX Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_ZXY, "ZXY", 0, "ZXY Euler", "ZXY Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_ZYX, "ZYX", 0, "ZYX Euler", "ZYX Rotation Order. Prone to Gimbal Lock"}, + {ROT_MODE_AXISANGLE, "AXIS_ANGLE", 0, "Axis Angle", "Axis Angle (W+XYZ). Defines a rotation around some axis defined by 3D-Vector."}, {0, NULL, 0, NULL, NULL}}; StructRNA *srna; @@ -467,7 +523,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_PoseChannel_name_set"); RNA_def_property_ui_text(prop, "Name", ""); RNA_def_struct_name_property(srna, prop); - + prop= RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "selectflag", BONE_SELECTED); RNA_def_property_ui_text(prop, "Selected", ""); @@ -477,16 +533,17 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "pathsf"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Bone Paths Calculation Start Frame", "Starting frame of range of frames to use for Bone Path calculations."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE|ND_TRANSFORM, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); prop= RNA_def_property(srna, "path_end_frame", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "pathef"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Bone Paths Calculation End Frame", "End frame of range of frames to use for Bone Path calculations."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE|ND_TRANSFORM, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); /* Relationships to other bones */ - prop= RNA_def_property(srna, "bone", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "bone", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "Bone"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Bone", "Bone associated with this Pose Channel."); @@ -512,52 +569,53 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Scale", ""); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); - prop= RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_QUATERNION); + prop= RNA_def_property(srna, "rotation_quaternion", PROP_FLOAT, PROP_QUATERNION); RNA_def_property_float_sdna(prop, NULL, "quat"); - RNA_def_property_ui_text(prop, "Rotation", "Rotation in Quaternions."); - RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); - - prop= RNA_def_property(srna, "rotation_angle", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "quat[0]"); - RNA_def_property_ui_text(prop, "Rotation Angle", "Angle of Rotation for Axis-Angle rotation representation."); + RNA_def_property_ui_text(prop, "Quaternion Rotation", "Rotation in Quaternions."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); - prop= RNA_def_property(srna, "rotation_axis", PROP_FLOAT, PROP_XYZ); + /* XXX: for axis-angle, it would have been nice to have 2 separate fields for UI purposes, but + * having a single one is better for Keyframing and other property-management situations... + */ + prop= RNA_def_property(srna, "rotation_axis_angle", PROP_FLOAT, PROP_AXISANGLE); RNA_def_property_float_sdna(prop, NULL, "quat"); - RNA_def_property_float_funcs(prop, "rna_PoseChannel_rotation_axis_get", "rna_PoseChannel_rotation_axis_set", NULL); - RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Rotation Axis", "Axis for Axis-Angle rotation representation."); + // TODO: we may need some validation funcs + RNA_def_property_ui_text(prop, "Axis-Angle Rotation", "Angle of Rotation for Axis-Angle rotation representation."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); - prop= RNA_def_property(srna, "euler_rotation", PROP_FLOAT, PROP_EULER); + prop= RNA_def_property(srna, "rotation_euler", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "eul"); - RNA_def_property_float_funcs(prop, "rna_PoseChannel_euler_rotation_get", "rna_PoseChannel_euler_rotation_set", NULL); - RNA_def_property_ui_text(prop, "Rotation (Euler)", "Rotation in Eulers."); + RNA_def_property_float_funcs(prop, "rna_PoseChannel_rotation_euler_get", "rna_PoseChannel_rotation_euler_set", NULL); + RNA_def_property_ui_text(prop, "Euler Rotation", "Rotation in Eulers."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); prop= RNA_def_property(srna, "rotation_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "rotmode"); - RNA_def_property_enum_items(prop, prop_rotmode_items); + RNA_def_property_enum_items(prop, prop_rotmode_items); // XXX move to using a single define of this someday RNA_def_property_enum_funcs(prop, NULL, "rna_PoseChannel_rotation_mode_set", NULL); RNA_def_property_ui_text(prop, "Rotation Mode", ""); RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); /* These three matrix properties await an implementation of the PROP_MATRIX subtype, which currently doesn't exist. */ -/* prop= RNA_def_property(srna, "channel_matrix", PROP_FLOAT, PROP_MATRIX); - RNA_def_property_struct_type(prop, "chan_mat"); + prop= RNA_def_property(srna, "channel_matrix", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "chan_mat"); + RNA_def_property_array(prop, 16); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Channel Matrix", "4x4 matrix, before constraints.");*/ + RNA_def_property_ui_text(prop, "Channel Matrix", "4x4 matrix, before constraints."); /* kaito says this should be not user-editable; I disagree; power users should be able to force this in python; he's the boss. */ -/* prop= RNA_def_property(srna, "pose_matrix", PROP_FLOAT, PROP_MATRIX); - RNA_def_property_struct_type(prop, "pose_mat"); + prop= RNA_def_property(srna, "pose_matrix", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "pose_mat"); + RNA_def_property_array(prop, 16); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Pose Matrix", "Final 4x4 matrix for this channel."); + /* prop= RNA_def_property(srna, "constraint_inverse_matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_struct_type(prop, "constinv"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Constraint Inverse Matrix", "4x4 matrix, defines transform from final position to unconstrained position."); */ + RNA_def_property_ui_text(prop, "Constraint Inverse Matrix", "4x4 matrix, defines transform from final position to unconstrained position."); + */ /* Head/Tail Coordinates (in Pose Space) - Automatically calculated... */ prop= RNA_def_property(srna, "pose_head", PROP_FLOAT, PROP_TRANSLATION); @@ -573,96 +631,118 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_PoseChannel_has_ik_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Has IK", "Is part of an IK chain."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_dof_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "ikflag", BONE_IK_NO_XDOF); RNA_def_property_ui_text(prop, "IK X DoF", "Allow movement around the X axis."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_dof_y", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "ikflag", BONE_IK_NO_YDOF); RNA_def_property_ui_text(prop, "IK Y DoF", "Allow movement around the Y axis."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE|ND_TRANSFORM, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_dof_z", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "ikflag", BONE_IK_NO_ZDOF); RNA_def_property_ui_text(prop, "IK Z DoF", "Allow movement around the Z axis."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_limit_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ikflag", BONE_IK_XLIMIT); RNA_def_property_ui_text(prop, "IK X Limit", "Limit movement around the X axis."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_limit_y", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ikflag", BONE_IK_YLIMIT); RNA_def_property_ui_text(prop, "IK Y Limit", "Limit movement around the Y axis."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_limit_z", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ikflag", BONE_IK_ZLIMIT); RNA_def_property_ui_text(prop, "IK Z Limit", "Limit movement around the Z axis."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); + + prop= RNA_def_property(srna, "ik_rot_control", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ikflag", BONE_IK_ROTCTL); + RNA_def_property_ui_text(prop, "IK rot control", "Apply channel rotation as IK constraint"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); + + prop= RNA_def_property(srna, "ik_lin_control", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ikflag", BONE_IK_LINCTL); + RNA_def_property_ui_text(prop, "IK rot control", "Apply channel size as IK constraint if stretching is enabled"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_min_x", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "limitmin[0]"); RNA_def_property_range(prop, -180.0f, 0.0f); RNA_def_property_ui_text(prop, "IK X Minimum", "Minimum angles for IK Limit"); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_max_x", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "limitmax[0]"); RNA_def_property_range(prop, 0.0f, 180.0f); RNA_def_property_ui_text(prop, "IK X Maximum", "Maximum angles for IK Limit"); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_min_y", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "limitmin[1]"); RNA_def_property_range(prop, -180.0f, 0.0f); RNA_def_property_ui_text(prop, "IK Y Minimum", "Minimum angles for IK Limit"); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_max_y", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "limitmax[1]"); RNA_def_property_range(prop, 0.0f, 180.0f); RNA_def_property_ui_text(prop, "IK Y Maximum", "Maximum angles for IK Limit"); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_min_z", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "limitmin[2]"); RNA_def_property_range(prop, -180.0f, 0.0f); RNA_def_property_ui_text(prop, "IK Z Minimum", "Minimum angles for IK Limit"); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_max_z", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "limitmax[2]"); RNA_def_property_range(prop, 0.0f, 180.0f); RNA_def_property_ui_text(prop, "IK Z Maximum", "Maximum angles for IK Limit"); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_stiffness_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "stiffness[0]"); RNA_def_property_range(prop, 0.0f, 0.99f); RNA_def_property_ui_text(prop, "IK X Stiffness", "IK stiffness around the X axis."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_stiffness_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "stiffness[1]"); RNA_def_property_range(prop, 0.0f, 0.99f); RNA_def_property_ui_text(prop, "IK Y Stiffness", "IK stiffness around the Y axis."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_stiffness_z", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "stiffness[2]"); RNA_def_property_range(prop, 0.0f, 0.99f); RNA_def_property_ui_text(prop, "IK Z Stiffness", "IK stiffness around the Z axis."); - RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); prop= RNA_def_property(srna, "ik_stretch", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ikstretch"); RNA_def_property_range(prop, 0.0f,1.0f); RNA_def_property_ui_text(prop, "IK Stretch", "Allow scaling of the bone for IK."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_IK_update"); + + prop= RNA_def_property(srna, "ik_rot_weight", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "ikrotweight"); + RNA_def_property_range(prop, 0.0f,1.0f); + RNA_def_property_ui_text(prop, "IK Rot Weight", "Weight of rotation constraint for IK."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + + prop= RNA_def_property(srna, "ik_lin_weight", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "iklinweight"); + RNA_def_property_range(prop, 0.0f,1.0f); + RNA_def_property_ui_text(prop, "IK Lin Weight", "Weight of scale constraint for IK."); RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); /* custom bone shapes */ @@ -719,6 +799,113 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); } +static void rna_def_pose_itasc(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "Itasc", "IKParam"); + RNA_def_struct_sdna(srna, "bItasc"); + RNA_def_struct_ui_text(srna, "bItasc", "Parameters for the iTaSC IK solver."); + + prop= RNA_def_property(srna, "precision", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "precision"); + RNA_def_property_range(prop, 0.0f,0.1f); + RNA_def_property_ui_text(prop, "Precision", "Precision of convergence in case of reiteration."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "num_iter", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "numiter"); + RNA_def_property_range(prop, 1.f,1000.f); + RNA_def_property_ui_text(prop, "Iterations", "Maximum number of iterations for convergence in case of reiteration."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "num_step", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "numstep"); + RNA_def_property_range(prop, 1.f, 50.f); + RNA_def_property_ui_text(prop, "Num steps", "Divides the frame interval into this many steps."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "simulation", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ITASC_SIMULATION); + RNA_def_property_ui_text(prop, "Simulation", "Simulation mode: solver is statefull, runs in real-time context and ignores actions and non-IK constraints (i.e. solver is in full charge of the IK chain)."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update_rebuild"); + + prop= RNA_def_property(srna, "initial_reiteration", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ITASC_INITIAL_REITERATION); + RNA_def_property_ui_text(prop, "Initial Reiteration", "Allow reiteration for initial frame."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "reiteration", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ITASC_REITERATION); + RNA_def_property_ui_text(prop, "Reiteration", "Allow reiteration for all frames."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "auto_step", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ITASC_AUTO_STEP); + RNA_def_property_ui_text(prop, "Auto step", "Automatically determine the optimal number of steps for best performance/accurary trade off."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "min_step", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "minstep"); + RNA_def_property_range(prop, 0.0f,0.1f); + RNA_def_property_ui_text(prop, "Min step", "Lower bound for timestep in second in case of automatic substeps."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "max_step", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "maxstep"); + RNA_def_property_range(prop, 0.0f,1.0f); + RNA_def_property_ui_text(prop, "Max step", "Higher bound for timestep in second in case of automatic substeps."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "feedback", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "feedback"); + RNA_def_property_range(prop, 0.0f,100.0f); + RNA_def_property_ui_text(prop, "Feedback", "Feedback coefficient for error correction. Average response time=1/feedback. Default=20."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "max_velocity", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "maxvel"); + RNA_def_property_range(prop, 0.0f,100.0f); + RNA_def_property_ui_text(prop, "Max Velocity", "Maximum joint velocity in rad/s. Default=50."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "solver", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "solver"); + RNA_def_property_enum_items(prop, prop_solver_items); + RNA_def_property_ui_text(prop, "Solver", "Solving method selection: Automatic damping or manual damping"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update_rebuild"); + + prop= RNA_def_property(srna, "dampmax", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "dampmax"); + RNA_def_property_range(prop, 0.0f,1.0f); + RNA_def_property_ui_text(prop, "Damp", "Maximum damping coefficient when singular value is nearly 0. Higher values=more stability, less reactivity. Default=0.5"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); + + prop= RNA_def_property(srna, "dampeps", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "dampeps"); + RNA_def_property_range(prop, 0.0f,1.0f); + RNA_def_property_ui_text(prop, "Epsilon", "Singular value under which damping is progressively applied. Higher values=more stability, less reactivity. Default=0.1"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Itasc_update"); +} + +static void rna_def_pose_ikparam(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "IKParam", NULL); + RNA_def_struct_sdna(srna, "bIKParam"); + RNA_def_struct_ui_text(srna, "IKParam", "Base type for IK solver parameters."); + RNA_def_struct_refine_func(srna, "rna_IKParam_refine"); + + prop= RNA_def_property(srna, "ik_solver", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "iksolver"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_enum_items(prop, prop_iksolver_items); + RNA_def_property_ui_text(prop, "IK Solver", "IK solver for which these parameters are defined, 0 for Legacy, 1 for iTaSC."); +} + static void rna_def_pose(BlenderRNA *brna) { StructRNA *srna; @@ -753,13 +940,29 @@ static void rna_def_pose(BlenderRNA *brna) RNA_def_property_int_funcs(prop, "rna_Pose_active_bone_group_index_get", "rna_Pose_active_bone_group_index_set", "rna_Pose_active_bone_group_index_range"); RNA_def_property_ui_text(prop, "Active Bone Group Index", "Active index in bone groups array."); RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + + prop= RNA_def_property(srna, "ik_solver", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "iksolver"); + RNA_def_property_enum_funcs(prop, NULL, "rna_Pose_ik_solver_set", NULL); + RNA_def_property_enum_items(prop, prop_iksolver_items); + RNA_def_property_ui_text(prop, "IK Solver", "Selection of IK solver for IK chain, current choice is 0 for Legacy, 1 for iTaSC."); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_ik_solver_update"); + + prop= RNA_def_property(srna, "ik_param", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "IKParam"); + RNA_def_property_pointer_funcs(prop, "rna_Pose_ikparam_get", NULL, "rna_Pose_ikparam_typef"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "IK Param", "Parameters for IK solver."); + + /* RNA_api_pose(srna); */ } void RNA_def_pose(BlenderRNA *brna) { rna_def_pose(brna); rna_def_pose_channel(brna); - + rna_def_pose_ikparam(brna); + rna_def_pose_itasc(brna); rna_def_bone_group(brna); } diff --git a/source/blender/makesrna/intern/rna_pose_api.c b/source/blender/makesrna/intern/rna_pose_api.c new file mode 100644 index 00000000000..40bb131b3f9 --- /dev/null +++ b/source/blender/makesrna/intern/rna_pose_api.c @@ -0,0 +1,56 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "RNA_define.h" +#include "RNA_types.h" + +#include "DNA_object_types.h" + +/* #include "BLO_sys_types.h" */ + +#ifdef RNA_RUNTIME + +/* #include "DNA_anim_types.h" */ +#include "DNA_action_types.h" /* bPose */ + +#else + +void RNA_api_pose(StructRNA *srna) +{ + /* FunctionRNA *func; */ + /* PropertyRNA *parm; */ + +} + +#endif + diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 8df6398f1f4..8dd751cd26a 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -458,6 +458,62 @@ static int rna_IntProperty_default_get(PointerRNA *ptr) rna_idproperty_check(&prop, ptr); return ((IntPropertyRNA*)prop)->defaultvalue; } +/* int/float/bool */ +static int rna_NumberProperty_default_array_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) +{ + PropertyRNA *prop= (PropertyRNA*)ptr->data; + rna_idproperty_check(&prop, ptr); + + length[0]= prop->totarraylength; + + return length[0]; +} +static void rna_IntProperty_default_array_get(PointerRNA *ptr, int *values) +{ + PropertyRNA *prop= (PropertyRNA*)ptr->data; + IntPropertyRNA *nprop= (IntPropertyRNA*)prop; + rna_idproperty_check(&prop, ptr); + + if(nprop->defaultarray) { + memcpy(values, nprop->defaultarray, prop->totarraylength * sizeof(int)); + } + else { + int i; + for(i=0; i < prop->totarraylength; i++) + values[i]= nprop->defaultvalue; + } +} +static void rna_BoolProperty_default_array_get(PointerRNA *ptr, int *values) +{ + PropertyRNA *prop= (PropertyRNA*)ptr->data; + BooleanPropertyRNA *nprop= (BooleanPropertyRNA*)prop; + rna_idproperty_check(&prop, ptr); + + if(nprop->defaultarray) { + memcpy(values, nprop->defaultarray, prop->totarraylength * sizeof(int)); + } + else { + int i; + for(i=0; i < prop->totarraylength; i++) + values[i]= nprop->defaultvalue; + } +} +static void rna_FloatProperty_default_array_get(PointerRNA *ptr, float *values) +{ + PropertyRNA *prop= (PropertyRNA*)ptr->data; + FloatPropertyRNA *nprop= (FloatPropertyRNA*)prop; + rna_idproperty_check(&prop, ptr); + + if(nprop->defaultarray) { + memcpy(values, nprop->defaultarray, prop->totarraylength * sizeof(float)); + } + else { + int i; + for(i=0; i < prop->totarraylength; i++) + values[i]= nprop->defaultvalue; + } +} + static int rna_IntProperty_hard_min_get(PointerRNA *ptr) { PropertyRNA *prop= (PropertyRNA*)ptr->data; @@ -786,6 +842,7 @@ static void rna_def_property(BlenderRNA *brna) {PROP_DIRPATH, "DIRECTORY_PATH", 0, "Directory Path", ""}, {PROP_UNSIGNED, "UNSIGNED", 0, "Unsigned Number", ""}, {PROP_PERCENTAGE, "PERCENTAGE", 0, "Percentage", ""}, + {PROP_FACTOR, "FACTOR", 0, "Factor", ""}, {PROP_ANGLE, "ANGLE", 0, "Angle", ""}, {PROP_TIME, "TIME", 0, "Time", ""}, {PROP_DISTANCE, "DISTANCE", 0, "Distance", ""}, @@ -797,7 +854,6 @@ static void rna_def_property(BlenderRNA *brna) {PROP_QUATERNION, "QUATERNION", 0, "Quaternion", ""}, {PROP_XYZ, "XYZ", 0, "XYZ", ""}, {PROP_RGB, "RGB", 0, "RGB", ""}, - {PROP_NEVER_NULL, "NEVER_NULL", 0, "Never Null", ""}, {PROP_LAYER, "LAYER", 0, "Layer", ""}, {PROP_LAYER_MEMBER, "LAYER_MEMBERSHIP", 0, "Layer Membership", ""}, {0, NULL, 0, NULL, NULL}}; @@ -932,13 +988,27 @@ static void rna_def_number_property(StructRNA *srna, PropertyType type) } -#if 0 // XXX - Variable length arrays prop= RNA_def_property(srna, "default_array", type, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - if(type == PROP_INT) RNA_def_property_int_funcs(prop, "rna_IntProperty_default_array_get", NULL, NULL); - else RNA_def_property_float_funcs(prop, "rna_FloatProperty_default_array_get", NULL, NULL); - RNA_def_property_ui_text(prop, "Default", "Default value for this number"); -#endif + RNA_def_property_array(prop, RNA_MAX_ARRAY_DIMENSION); /* no fixed default length, important its not 0 though */ + RNA_def_property_flag(prop, PROP_DYNAMIC); + RNA_def_property_dynamic_array_funcs(prop, "rna_NumberProperty_default_array_get_length"); /* same for all types */ + + switch(type) { + case PROP_BOOLEAN: + RNA_def_property_boolean_funcs(prop, "rna_BoolProperty_default_array_get", NULL); + break; + case PROP_INT: + RNA_def_property_int_funcs(prop, "rna_IntProperty_default_array_get", NULL, NULL); + break; + case PROP_FLOAT: + RNA_def_property_float_funcs(prop, "rna_FloatProperty_default_array_get", NULL, NULL); + break; + default: + break; + } + RNA_def_property_ui_text(prop, "Default Array", "Default value for this array"); + prop= RNA_def_property(srna, "array_length", PROP_INT, PROP_UNSIGNED); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 90385941356..ffe07d4de62 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -70,7 +70,7 @@ EnumPropertyItem prop_mode_items[] ={ #include "RE_pipeline.h" -PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter) +static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter) { ListBaseIterator *internal= iter->internal; @@ -257,6 +257,41 @@ static void rna_SceneRenderData_file_format_set(PointerRNA *ptr, int value) #endif } +void rna_SceneRenderData_jpeg2k_preset_update(RenderData *rd) +{ + rd->subimtype &= ~(R_JPEG2K_12BIT|R_JPEG2K_16BIT | R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS); + + switch(rd->jp2_depth) { + case 8: break; + case 12: rd->subimtype |= R_JPEG2K_12BIT; break; + case 16: rd->subimtype |= R_JPEG2K_16BIT; break; + } + + switch(rd->jp2_preset) { + case 1: rd->subimtype |= R_JPEG2K_CINE_PRESET; break; + case 2: rd->subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS; break; + case 3: rd->subimtype |= R_JPEG2K_CINE_PRESET; break; + case 4: rd->subimtype |= R_JPEG2K_CINE_PRESET; break; + case 5: rd->subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS; break; + case 6: rd->subimtype |= R_JPEG2K_CINE_PRESET; break; + case 7: rd->subimtype |= R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS; break; + } +} + +static void rna_SceneRenderData_jpeg2k_preset_set(PointerRNA *ptr, int value) +{ + RenderData *rd= (RenderData*)ptr->data; + rd->jp2_preset= value; + rna_SceneRenderData_jpeg2k_preset_update(rd); +} + +static void rna_SceneRenderData_jpeg2k_depth_set(PointerRNA *ptr, int value) +{ + RenderData *rd= (RenderData*)ptr->data; + rd->jp2_depth= value; + rna_SceneRenderData_jpeg2k_preset_update(rd); +} + static int rna_SceneRenderData_active_layer_index_get(PointerRNA *ptr) { RenderData *rd= (RenderData*)ptr->data; @@ -371,7 +406,7 @@ static void rna_SceneRenderLayer_pass_update(bContext *C, PointerRNA *ptr) ntreeCompositForceHidden(scene->nodetree, scene); } -void rna_Scene_use_nodes_set(PointerRNA *ptr, int value) +static void rna_Scene_use_nodes_set(PointerRNA *ptr, int value) { Scene *scene= (Scene*)ptr->data; @@ -523,7 +558,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, mesh_select_mode_items); RNA_def_property_ui_text(prop, "Mesh Selection Mode", "Mesh selection and display mode."); - prop= RNA_def_property(srna, "vertex_group_weight", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "vertex_group_weight", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "vgroup_weight"); RNA_def_property_ui_text(prop, "Vertex Group Weight", "Weight to assign in vertex groups."); } @@ -784,7 +819,7 @@ void rna_def_render_layer_common(StructRNA *srna, int scene) else RNA_def_property_clear_flag(prop, PROP_EDITABLE); } -void rna_def_scene_game_data(BlenderRNA *brna) +static void rna_def_scene_game_data(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -1240,19 +1275,19 @@ static void rna_def_scene_render_data(BlenderRNA *brna) #ifdef WITH_OPENJPEG static EnumPropertyItem jp2_preset_items[] = { {0, "NO_PRESET", 0, "No Preset", ""}, - {1, "R_JPEG2K_CINE_PRESET", 0, "Cinema 24fps 2048x1080", ""}, - {2, "R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS", 0, "Cinema 48fps 2048x1080", ""}, - {3, "R_JPEG2K_CINE_PRESET", 0, "Cinema 24fps 4096x2160", ""}, - {4, "R_JPEG2K_CINE_PRESET", 0, "Cine-Scope 24fps 2048x858", ""}, - {5, "R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS", 0, "Cine-Scope 48fps 2048x858", ""}, - {6, "R_JPEG2K_CINE_PRESET", 0, "Cine-Flat 24fps 1998x1080", ""}, - {7, "R_JPEG2K_CINE_PRESET|R_JPEG2K_CINE_48FPS", 0, "Cine-Flat 48fps 1998x1080", ""}, + {1, "CINE_24FPS", 0, "Cinema 24fps 2048x1080", ""}, + {2, "CINE_48FPS", 0, "Cinema 48fps 2048x1080", ""}, + {3, "CINE_24FPS_4K", 0, "Cinema 24fps 4096x2160", ""}, + {4, "CINE_SCOPE_48FPS", 0, "Cine-Scope 24fps 2048x858", ""}, + {5, "CINE_SCOPE_48FPS", 0, "Cine-Scope 48fps 2048x858", ""}, + {6, "CINE_FLAT_24FPS", 0, "Cine-Flat 24fps 1998x1080", ""}, + {7, "CINE_FLAT_48FPS", 0, "Cine-Flat 48fps 1998x1080", ""}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem jp2_depth_items[] = { - {0, "8", 0, "8", ""}, - {R_JPEG2K_12BIT, "16", 0, "16", ""}, - {R_JPEG2K_16BIT, "32", 0, "32", ""}, + {8, "8", 0, "8", "8 bit color channels"}, + {12, "12", 0, "12", "12 bit color channels"}, + {16, "16", 0, "16", "16 bit color channels"}, {0, NULL, 0, NULL, NULL}}; #endif @@ -1313,23 +1348,25 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_enum_bitflag_sdna(prop, NULL, "planes"); RNA_def_property_enum_items(prop, color_mode_items); RNA_def_property_ui_text(prop, "Color Mode", "Choose BW for saving greyscale images, RGB for saving red, green and blue channels, AND RGBA for saving red, green, blue + alpha channels"); - + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + prop= RNA_def_property(srna, "resolution_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "xsch"); RNA_def_property_range(prop, 4, 10000); RNA_def_property_ui_text(prop, "Resolution X", "Number of horizontal pixels in the rendered image."); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT|ND_DRAW, NULL); prop= RNA_def_property(srna, "resolution_y", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "ysch"); RNA_def_property_range(prop, 4, 10000); RNA_def_property_ui_text(prop, "Resolution Y", "Number of vertical pixels in the rendered image."); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT|ND_DRAW, NULL); prop= RNA_def_property(srna, "resolution_percentage", PROP_INT, PROP_PERCENTAGE); RNA_def_property_int_sdna(prop, NULL, "size"); RNA_def_property_ui_range(prop, 1, 100, 10, 1); RNA_def_property_ui_text(prop, "Resolution %", "Percentage scale for render resolution"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "parts_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "xparts"); @@ -1347,13 +1384,13 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "xasp"); RNA_def_property_range(prop, 1.0f, 200.0f); RNA_def_property_ui_text(prop, "Pixel Aspect X", "Horizontal aspect ratio - for anamorphic or non-square pixel output"); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT|ND_DRAW, NULL); prop= RNA_def_property(srna, "pixel_aspect_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "yasp"); RNA_def_property_range(prop, 1.0f, 200.0f); RNA_def_property_ui_text(prop, "Pixel Aspect Y", "Vertical aspect ratio - for anamorphic or non-square pixel output"); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT, NULL); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT|ND_DRAW, NULL); /* JPEG and AVI JPEG */ @@ -1423,19 +1460,21 @@ static void rna_def_scene_render_data(BlenderRNA *brna) #ifdef WITH_OPENJPEG /* Jpeg 2000 */ - prop= RNA_def_property(srna, "jpeg_preset", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "jp2_preset"); + 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_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, "jpeg_depth", PROP_ENUM, PROP_NONE); + 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_ui_text(prop, "Depth", "Bit depth per channel"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); - prop= RNA_def_property(srna, "jpeg_ycc", PROP_BOOLEAN, PROP_NONE); + prop= RNA_def_property(srna, "jpeg2k_ycc", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "subimtype", R_JPEG2K_YCC); RNA_def_property_ui_text(prop, "YCC", "Save luminance-chrominance-chrominance channels instead of RGB colors"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); @@ -1521,6 +1560,19 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "ffcodecdata.flags", FFMPEG_MULTIPLEX_AUDIO); RNA_def_property_ui_text(prop, "Multiplex Audio", "Interleave audio with the output video"); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "ffmpeg_audio_mixrate", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "ffcodecdata.audio_mixrate"); + RNA_def_property_range(prop, 8000, 192000); + RNA_def_property_ui_text(prop, "Samplerate", "Audio samplerate(samples/s)"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "ffmpeg_audio_volume", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "ffcodecdata.audio_volume"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Volume", "Audio volume"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + #endif prop= RNA_def_property(srna, "fps", PROP_INT, PROP_NONE); @@ -1591,17 +1643,13 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, field_order_items); RNA_def_property_ui_text(prop, "Field Order", "Order of video fields. Select which lines get rendered first, to create smooth motion for TV output"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "fields_still", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_FIELDSTILL); RNA_def_property_ui_text(prop, "Fields Still", "Disable the time difference between fields."); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); - prop= RNA_def_property(srna, "sync_audio", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "audio.flag", AUDIO_SYNC); - RNA_def_property_ui_text(prop, "Sync Audio", "Play back and sync with audio from Sequence Editor"); - RNA_def_property_update(prop, NC_SCENE, NULL); - prop= RNA_def_property(srna, "render_shadows", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_SHADOW); RNA_def_property_ui_text(prop, "Render Shadows", "Calculate shadows while rendering."); @@ -1660,6 +1708,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, threads_mode_items); RNA_def_property_ui_text(prop, "Threads Mode", "Determine the amount of render threads used"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "motion_blur", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_MBLUR); @@ -1670,6 +1719,30 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "mode", R_BORDER); RNA_def_property_ui_text(prop, "Border", "Render a user-defined border region, within the frame size."); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "border_min_x", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "border.xmin"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Border Minimum X", "Sets minimum X value to for the render border."); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "border_min_y", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "border.ymin"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Border Minimum Y", "Sets minimum Y value for the render border"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "border_max_x", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "border.xmax"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Border Maximum X", "Sets maximum X value for the render border"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "border_max_y", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "border.ymax"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Border Maximum Y", "Sets maximum Y value for the render border"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "crop_to_border", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_CROP); @@ -1743,6 +1816,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_enum_bitflag_sdna(prop, NULL, "displaymode"); RNA_def_property_enum_items(prop, display_mode_items); RNA_def_property_ui_text(prop, "Display", "Select where rendered images will be displayed"); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "output_path", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "pic"); @@ -1919,6 +1993,16 @@ void RNA_def_scene(BlenderRNA *brna) PropertyRNA *prop; FunctionRNA *func; + static EnumPropertyItem audio_distance_model_items[] = { + {0, "NONE", 0, "None", "No distance attenuation."}, + {1, "INVERSE", 0, "Inverse", "Inverse distance model."}, + {2, "INVERSE_CLAMPED", 0, "Inverse Clamped", "Inverse distance model with clamping."}, + {3, "LINEAR", 0, "Linear", "Linear distance model."}, + {4, "LINEAR_CLAMPED", 0, "Linear Clamped", "Linear distance model with clamping."}, + {5, "EXPONENT", 0, "Exponent", "Exponent distance model."}, + {6, "EXPONENT_CLAMPED", 0, "Exponent Clamped", "Exponent distance model with clamping."}, + {0, NULL, 0, NULL, NULL}}; + /* Struct definition */ srna= RNA_def_struct(brna, "Scene", "ID"); RNA_def_struct_ui_text(srna, "Scene", "Scene consisting objects and defining time and render related settings."); @@ -2011,6 +2095,9 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Stamp Note", "User define note for the render stamping."); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + /* Animation Data (for Scene) */ + rna_def_animdata_common(srna); + /* Nodes (Compositing) */ prop= RNA_def_property(srna, "nodetree", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Node Tree", "Compositing node tree."); @@ -2049,19 +2136,22 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE|ND_KEYINGSET, NULL); /* Tool Settings */ - prop= RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "toolsettings"); RNA_def_property_struct_type(prop, "ToolSettings"); RNA_def_property_ui_text(prop, "Tool Settings", ""); /* Unit Settings */ - prop= RNA_def_property(srna, "unit_settings", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "unit_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "unit"); RNA_def_property_struct_type(prop, "UnitSettings"); RNA_def_property_ui_text(prop, "Unit Settings", "Unit editing settings"); /* Render Data */ - prop= RNA_def_property(srna, "render_data", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "render_data", 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_ui_text(prop, "Render Data", ""); @@ -2072,8 +2162,43 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_struct_type(prop, "TimelineMarker"); RNA_def_property_ui_text(prop, "Timeline Markers", "Markers used in all timelines for the current scene."); + /* Audio Settings */ + prop= RNA_def_property(srna, "mute_audio", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "audio.flag", AUDIO_MUTE); + RNA_def_property_ui_text(prop, "Audio Muted", "Play back of audio from Sequence Editor will be muted."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "sync_audio", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "audio.flag", AUDIO_SYNC); + RNA_def_property_ui_text(prop, "Audio Sync", "Play back and sync with audio from Sequence Editor."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "scrub_audio", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "audio.flag", AUDIO_SCRUB); + RNA_def_property_ui_text(prop, "Audio Scrubbing", "Play audio from Sequence Editor while scrubbing."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "speed_of_sound", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "audio.speed_of_sound"); + RNA_def_property_range(prop, 0.01f, FLT_MAX); + RNA_def_property_ui_text(prop, "Speed of Sound", "Speed of sound for doppler effect calculation."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "doppler_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "audio.doppler_factor"); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_text(prop, "Doppler Factor", "Pitch factor for doppler effect calculation."); + RNA_def_property_update(prop, NC_SCENE, NULL); + + prop= RNA_def_property(srna, "distance_model", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "audio.distance_model"); + RNA_def_property_enum_items(prop, audio_distance_model_items); + RNA_def_property_ui_text(prop, "Distance Model", "Distance model for distance attenuation calculation."); + RNA_def_property_update(prop, NC_SCENE, NULL); + /* Game Settings */ - prop= RNA_def_property(srna, "game_data", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "game_data", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "gm"); RNA_def_property_struct_type(prop, "SceneGameData"); RNA_def_property_ui_text(prop, "Game Data", ""); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 26047ab5dc3..40f2db6d4a4 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -1,5 +1,5 @@ /** - * $Id: + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -21,7 +21,7 @@ * All rights reserved. * * - * Contributor(s): Joshua Leung + * Contributor(s): Joshua Leung, Arystanbek Dyussenov * * ***** END GPL LICENSE BLOCK ***** */ @@ -40,9 +40,49 @@ #ifdef RNA_RUNTIME #include "BKE_animsys.h" +#include "BKE_scene.h" +#include "BKE_depsgraph.h" -// Scene API stuff from kazanbas branch here... +#include "ED_object.h" +#include "WM_api.h" + +static void rna_Scene_add_object(Scene *sce, ReportList *reports, Object *ob) +{ + Base *base= object_in_scene(ob, sce); + if (base) { + BKE_report(reports, RPT_ERROR, "Object is already in this scene."); + return; + } + base= scene_add_base(sce, ob); + ob->id.us++; + + /* this is similar to what object_add_type and add_object do */ + ob->lay= base->lay= sce->lay; + ob->recalc |= OB_RECALC; + + DAG_scene_sort(sce); +} + +static void rna_Scene_remove_object(Scene *sce, ReportList *reports, Object *ob) +{ + Base *base= object_in_scene(ob, sce); + if (!base) { + BKE_report(reports, RPT_ERROR, "Object is not in this scene."); + return; + } + /* as long as ED_base_object_free_and_unlink calls free_libblock_us, we don't have to decrement ob->id.us */ + ED_base_object_free_and_unlink(sce, base); +} + +static void rna_Scene_set_frame(Scene *sce, bContext *C, int frame) +{ + sce->r.cfra= frame; + CLAMP(sce->r.cfra, MINAFRAME, MAXFRAME); + scene_update_for_newframe(sce, (1<<20) - 1); + + WM_event_add_notifier(C, NC_SCENE|ND_FRAME, sce); +} static KeyingSet *rna_Scene_add_keying_set(Scene *sce, ReportList *reports, char name[], int absolute, int insertkey_needed, int insertkey_visual) @@ -77,21 +117,37 @@ void RNA_api_scene(StructRNA *srna) { FunctionRNA *func; PropertyRNA *parm; - - // Scene API stuff from kazanbas branch here... - + + func= RNA_def_function(srna, "add_object", "rna_Scene_add_object"); + RNA_def_function_ui_description(func, "Add object to scene."); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm= RNA_def_pointer(func, "object", "Object", "", "Object to add to scene."); + RNA_def_property_flag(parm, PROP_REQUIRED); + + func= RNA_def_function(srna, "remove_object", "rna_Scene_remove_object"); + RNA_def_function_ui_description(func, "Remove object from scene."); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm= RNA_def_pointer(func, "object", "Object", "", "Object to remove from scene."); + RNA_def_property_flag(parm, PROP_REQUIRED); + + func= RNA_def_function(srna, "set_frame", "rna_Scene_set_frame"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Set scene frame updating all objects immediately."); + parm= RNA_def_int(func, "frame", 0, MINAFRAME, MAXFRAME, "", "Frame number to set.", MINAFRAME, MAXFRAME); + RNA_def_property_flag(parm, PROP_REQUIRED); + /* Add Keying Set */ func= RNA_def_function(srna, "add_keying_set", "rna_Scene_add_keying_set"); RNA_def_function_ui_description(func, "Add a new Keying Set to Scene."); RNA_def_function_flag(func, FUNC_USE_REPORTS); - /* returns the new KeyingSet */ + /* returns the new KeyingSet */ parm= RNA_def_pointer(func, "keyingset", "KeyingSet", "", "Newly created Keying Set."); - RNA_def_function_return(func, parm); - /* name */ + RNA_def_function_return(func, parm); + /* name */ RNA_def_string(func, "name", "KeyingSet", 64, "Name", "Name of Keying Set"); - /* flags */ + /* flags */ RNA_def_boolean(func, "absolute", 1, "Absolute", "Keying Set defines specific paths/settings to be keyframed (i.e. is not reliant on context info)"); - /* keying flags */ + /* keying flags */ RNA_def_boolean(func, "insertkey_needed", 0, "Insert Keyframes - Only Needed", "Only insert keyframes where they're needed in the relevant F-Curves."); RNA_def_boolean(func, "insertkey_visual", 0, "Insert Keyframes - Visual", "Insert keyframes based on 'visual transforms'."); } diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index 7a243327bd1..2a72845dd42 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -135,10 +135,10 @@ static void rna_def_screen(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Screen", "Screen datablock, defining the layout of areas in a window."); RNA_def_struct_ui_icon(srna, ICON_SPLITSCREEN); - prop= RNA_def_property(srna, "scene", PROP_POINTER, PROP_NEVER_NULL); - RNA_def_property_ui_text(prop, "Scene", "Active scene to be edited in the screen."); - RNA_def_property_flag(prop, PROP_EDITABLE); + prop= RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE|PROP_NEVER_NULL); RNA_def_property_pointer_funcs(prop, NULL, "rna_Screen_scene_set", NULL); + RNA_def_property_ui_text(prop, "Scene", "Active scene to be edited in the screen."); RNA_def_property_update(prop, 0, "rna_Screen_scene_update"); prop= RNA_def_property(srna, "areas", PROP_COLLECTION, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c index 53bd230870f..1003af6d4d1 100644 --- a/source/blender/makesrna/intern/rna_sensor.c +++ b/source/blender/makesrna/intern/rna_sensor.c @@ -48,6 +48,8 @@ static StructRNA* rna_Sensor_refine(struct PointerRNA *ptr) return &RNA_KeyboardSensor; case SENS_PROPERTY: return &RNA_PropertySensor; + case SENS_ARMATURE: + return &RNA_ArmatureSensor; case SENS_MOUSE: return &RNA_MouseSensor; case SENS_COLLISION: @@ -73,7 +75,7 @@ static StructRNA* rna_Sensor_refine(struct PointerRNA *ptr) #else -void rna_def_sensor(BlenderRNA *brna) +static void rna_def_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -92,6 +94,7 @@ void rna_def_sensor(BlenderRNA *brna) {SENS_JOYSTICK, "JOYSTICK", 0, "joystick", ""}, {SENS_ACTUATOR, "ACTUATOR", 0, "Actuator", ""}, {SENS_DELAY, "DELAY", 0, "Delay", ""}, + {SENS_ARMATURE, "ARMATURE", 0, "Armature", ""}, {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "Sensor", NULL); @@ -129,14 +132,14 @@ void rna_def_sensor(BlenderRNA *brna) RNA_def_property_range(prop, 0, 10000); } -void rna_def_always_sensor(BlenderRNA *brna) +static void rna_def_always_sensor(BlenderRNA *brna) { StructRNA *srna; srna= RNA_def_struct(brna, "AlwaysSensor", "Sensor"); RNA_def_struct_ui_text(srna, "Always Sensor", "Sensor to generate continuous pulses."); } -void rna_def_near_sensor(BlenderRNA *brna) +static void rna_def_near_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -160,7 +163,7 @@ void rna_def_near_sensor(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 10000.0f); } -void rna_def_mouse_sensor(BlenderRNA *brna) +static void rna_def_mouse_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -186,7 +189,7 @@ void rna_def_mouse_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Mouse Event", "Specify the type of event this mouse sensor should trigger on."); } -void rna_def_touch_sensor(BlenderRNA *brna) +static void rna_def_touch_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -201,7 +204,7 @@ void rna_def_touch_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Material", "Only look for floors with this material."); } -void rna_def_keyboard_sensor(BlenderRNA *brna) +static void rna_def_keyboard_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -240,7 +243,7 @@ void rna_def_keyboard_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "All Keys", "Trigger this sensor on any keystroke."); } -void rna_def_property_sensor(BlenderRNA *brna) +static void rna_def_property_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -278,7 +281,41 @@ void rna_def_property_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Maximum Value", "Specify maximum value in Interval type."); } -void rna_def_actuator_sensor(BlenderRNA *brna) +static void rna_def_armature_sensor(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + static EnumPropertyItem prop_type_items[] ={ + {SENS_ARM_STATE_CHANGED, "STATECHG", 0, "State Changed", ""}, + {SENS_ARM_LIN_ERROR_BELOW, "LINERRORBELOW", 0, "Lin error below", ""}, + {SENS_ARM_LIN_ERROR_ABOVE, "LINERRORABOVE", 0, "Lin error above", ""}, + {SENS_ARM_ROT_ERROR_BELOW, "ROTERRORBELOW", 0, "Rot error below", ""}, + {SENS_ARM_ROT_ERROR_ABOVE, "ROTERRORBELOW", 0, "Rot error above", ""}, + {0, NULL, 0, NULL, NULL}}; + + srna= RNA_def_struct(brna, "ArmatureSensor", "Sensor"); + RNA_def_struct_ui_text(srna, "Armature Sensor", "Sensor to detect values and changes in values of IK solver."); + RNA_def_struct_sdna_from(srna, "bArmatureSensor", "data"); + + prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "type"); + RNA_def_property_enum_items(prop, prop_type_items); + RNA_def_property_ui_text(prop, "Test Type", "Type of value and test."); + + prop= RNA_def_property(srna, "channel_name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "posechannel"); + RNA_def_property_ui_text(prop, "Bone name", "Identify the bone to check value from"); + + prop= RNA_def_property(srna, "constraint_name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "constraint"); + RNA_def_property_ui_text(prop, "Constraint name", "Identify the bone constraint to check value from."); + + prop= RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "value"); + RNA_def_property_ui_text(prop, "Compare Value", "Specify value to be used in comparison."); +} + +static void rna_def_actuator_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -292,7 +329,7 @@ void rna_def_actuator_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Actuator", "Actuator name, actuator active state modifications will be detected."); } -void rna_def_delay_sensor(BlenderRNA *brna) +static void rna_def_delay_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -314,7 +351,7 @@ void rna_def_delay_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Repeat", "Toggle repeat option. If selected, the sensor restarts after Delay+Dur logic tics."); } -void rna_def_collision_sensor(BlenderRNA *brna) +static void rna_def_collision_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -341,7 +378,7 @@ void rna_def_collision_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Collision Type", "Toggle collision on material or property."); } -void rna_def_radar_sensor(BlenderRNA *brna) +static void rna_def_radar_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -376,7 +413,7 @@ void rna_def_radar_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Distance", "Depth of the radar cone."); } -void rna_def_random_sensor(BlenderRNA *brna) +static void rna_def_random_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -390,7 +427,7 @@ void rna_def_random_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Seed", "Initial seed of the generator. (Choose 0 for not random)."); } -void rna_def_ray_sensor(BlenderRNA *brna) +static void rna_def_ray_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -438,7 +475,7 @@ void rna_def_ray_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Axis", "Specify along which axis the ray is cast."); } -void rna_def_message_sensor(BlenderRNA *brna) +static void rna_def_message_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -451,7 +488,7 @@ void rna_def_message_sensor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Subject", "Optional subject filter: only accept messages with this subject, or empty for all."); } -void rna_def_joystick_sensor(BlenderRNA *brna) +static void rna_def_joystick_sensor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -531,6 +568,7 @@ void RNA_def_sensor(BlenderRNA *brna) rna_def_touch_sensor(brna); rna_def_keyboard_sensor(brna); rna_def_property_sensor(brna); + rna_def_armature_sensor(brna); rna_def_actuator_sensor(brna); rna_def_delay_sensor(brna); rna_def_collision_sensor(brna); diff --git a/source/blender/makesrna/intern/rna_sequence.c b/source/blender/makesrna/intern/rna_sequence.c index 9f016f73694..9404fb775c3 100644 --- a/source/blender/makesrna/intern/rna_sequence.c +++ b/source/blender/makesrna/intern/rna_sequence.c @@ -228,7 +228,15 @@ static char *rna_Sequence_path(PointerRNA *ptr) /* sequencer data comes from scene... * TODO: would be nice to make SequenceEditor data a datablock of its own (for shorter paths) */ - return BLI_sprintfN("sequence_editor.sequences[\"%s\"]", seq->name+2); + if (seq->name+2) + return BLI_sprintfN("sequence_editor.sequences[\"%s\"]", seq->name+2); + else { + /* compromise for the frequent sitation when strips don't have names... */ + Scene *sce= (Scene*)ptr->id.data; + Editing *ed= seq_give_editing(sce, FALSE); + + return BLI_sprintfN("sequence_editor.sequences[%d]", BLI_findindex(&ed->seqbase, seq)); + } } static PointerRNA rna_SequenceEdtior_meta_stack_get(CollectionPropertyIterator *iter) @@ -239,6 +247,35 @@ static PointerRNA rna_SequenceEdtior_meta_stack_get(CollectionPropertyIterator * return rna_pointer_inherit_refine(&iter->parent, &RNA_Sequence, ms->parseq); } +static void rna_MovieSequence_filename_set(PointerRNA *ptr, const char *value) +{ + Sequence *seq= (Sequence*)(ptr->data); + char dir[FILE_MAX], name[FILE_MAX]; + + BLI_split_dirfile_basic(value, dir, name); + BLI_strncpy(seq->strip->dir, dir, sizeof(seq->strip->dir)); + BLI_strncpy(seq->strip->stripdata->name, name, sizeof(seq->strip->stripdata->name)); +} + +static void rna_SoundSequence_filename_set(PointerRNA *ptr, const char *value) +{ + Sequence *seq= (Sequence*)(ptr->data); + char dir[FILE_MAX], name[FILE_MAX]; + + BLI_split_dirfile_basic(value, dir, name); + BLI_strncpy(seq->strip->dir, dir, sizeof(seq->strip->dir)); + BLI_strncpy(seq->strip->stripdata->name, name, sizeof(seq->strip->stripdata->name)); +} + +static void rna_SequenceElement_filename_set(PointerRNA *ptr, const char *value) +{ + StripElem *elem= (StripElem*)(ptr->data); + char name[FILE_MAX]; + + BLI_split_dirfile_basic(value, NULL, name); + BLI_strncpy(elem->name, name, sizeof(elem->name)); +} + #else static void rna_def_strip_element(BlenderRNA *brna) @@ -253,6 +290,7 @@ static void rna_def_strip_element(BlenderRNA *brna) prop= RNA_def_property(srna, "filename", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_ui_text(prop, "Filename", ""); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SequenceElement_filename_set"); } static void rna_def_strip_crop(BlenderRNA *brna) @@ -490,6 +528,7 @@ static void rna_def_sequence(BlenderRNA *brna) prop= RNA_def_property(srna, "channel", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "machine"); + RNA_def_property_range(prop, 0, MAXSEQ-1); RNA_def_property_ui_text(prop, "Channel", "Y position of the sequence strip."); RNA_def_property_int_funcs(prop, NULL, "rna_SequenceEditor_channel_set",NULL); // overlap test RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, NULL); @@ -514,7 +553,7 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_function_return(func, RNA_def_pointer(func, "elem", "SequenceElement", "", "strip element of the current frame")); } -void rna_def_editor(BlenderRNA *brna) +static void rna_def_editor(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -736,6 +775,7 @@ static void rna_def_movie(BlenderRNA *brna) prop= RNA_def_property(srna, "filename", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "strip->stripdata->name"); RNA_def_property_ui_text(prop, "Filename", ""); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MovieSequence_filename_set"); prop= RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "strip->dir"); @@ -762,6 +802,7 @@ static void rna_def_sound(BlenderRNA *brna) prop= RNA_def_property(srna, "filename", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "strip->stripdata->name"); RNA_def_property_ui_text(prop, "Filename", ""); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SoundSequence_filename_set"); prop= RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "strip->dir"); diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 943129c7169..7bccd685c1d 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -211,11 +211,13 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Logarithmic dissolve", "Using 1/x "); RNA_def_property_update(prop, 0, NULL); - prop= RNA_def_property(srna, "point_cache_low", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "point_cache_low", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "point_cache[0]"); RNA_def_property_ui_text(prop, "Point Cache", ""); - prop= RNA_def_property(srna, "point_cache_high", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "point_cache_high", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "point_cache[1]"); RNA_def_property_ui_text(prop, "Point Cache", ""); } diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 542f6e2aeda..df956670eb3 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -38,8 +38,7 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" -#include "BKE_paint.h" - +#include "WM_api.h" #include "WM_types.h" EnumPropertyItem space_type_items[] = { @@ -80,11 +79,15 @@ static EnumPropertyItem dc_all_items[] = {DC_RGB, DC_RGBA, DC_ALPHA, DC_Z, DC_LC #ifdef RNA_RUNTIME +#include "DNA_anim_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BKE_animsys.h" #include "BKE_brush.h" +#include "BKE_colortools.h" #include "BKE_context.h" +#include "BKE_paint.h" #include "ED_image.h" #include "ED_screen.h" @@ -209,9 +212,18 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *C, P return dc_rgb_items; } +static void rna_SpaceImageEditor_curves_update(bContext *C, PointerRNA *ptr) +{ + SpaceImage *sima= (SpaceImage*)ptr->data; + + curvemapping_do_ibuf(sima->cumap, ED_space_image_buffer(sima)); + WM_event_add_notifier(C, NC_IMAGE, sima->image); +} + + /* Space Text Editor */ -void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, int value) +static void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, int value) { SpaceText *st= (SpaceText*)(ptr->data); @@ -219,7 +231,7 @@ void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, int value) st->left= 0; } -void rna_SpaceTextEditor_text_set(PointerRNA *ptr, PointerRNA value) +static void rna_SpaceTextEditor_text_set(PointerRNA *ptr, PointerRNA value) { SpaceText *st= (SpaceText*)(ptr->data); @@ -227,16 +239,9 @@ void rna_SpaceTextEditor_text_set(PointerRNA *ptr, PointerRNA value) st->top= 0; } -void rna_SpaceFileBrowser_params_set(PointerRNA *ptr, PointerRNA value) -{ - SpaceFile *sfile= (SpaceFile*)(ptr->data); - - sfile->params= value.data; -} - /* Space Properties */ -StructRNA *rna_SpaceProperties_pin_id_typef(PointerRNA *ptr) +static StructRNA *rna_SpaceProperties_pin_id_typef(PointerRNA *ptr) { SpaceButs *sbuts= (SpaceButs*)(ptr->data); @@ -246,7 +251,7 @@ StructRNA *rna_SpaceProperties_pin_id_typef(PointerRNA *ptr) return &RNA_ID; } -void rna_SpaceProperties_align_set(PointerRNA *ptr, int value) +static void rna_SpaceProperties_align_set(PointerRNA *ptr, int value) { SpaceButs *sbuts= (SpaceButs*)(ptr->data); @@ -311,12 +316,36 @@ static void rna_View3D_display_background_image_set(PointerRNA *ptr, int value) } /* Space Time */ + static void rna_SpaceTime_redraw_update(bContext *C, PointerRNA *ptr) { SpaceTime *st= (SpaceTime*)ptr->data; ED_screen_animation_timer_update(C, st->redraws); } +/* Space Dopesheet */ + +static void rna_SpaceDopeSheetEditor_action_set(PointerRNA *ptr, PointerRNA value) +{ + SpaceAction *saction= (SpaceAction*)(ptr->data); + saction->action= value.data; +} + +static void rna_SpaceDopeSheetEditor_action_update(bContext *C, PointerRNA *ptr) +{ + SpaceAction *saction= (SpaceAction*)(ptr->data); + Object *obact= CTX_data_active_object(C); + + /* we must set this action to be the one used by active object (if not pinned) */ + if(obact && saction->pin == 0) { + AnimData *adt= BKE_id_add_animdata(&obact->id); /* this only adds if non-existant */ + + /* set action */ + adt->action= saction->action; + id_us_plus(&adt->action->id); + } +} + #else static void rna_def_space(BlenderRNA *brna) @@ -491,7 +520,8 @@ static void rna_def_background_image(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); - prop= RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "iuser"); RNA_def_property_ui_text(prop, "Image User", "Parameters defining which layer, pass and frame of the image is displayed."); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); @@ -572,11 +602,9 @@ static void rna_def_space_3dview(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Viewport Shading", "Method to display/shade objects in the 3D View."); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); - prop= RNA_def_property(srna, "localview", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "localview", 0); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop= RNA_def_property(srna, "local_view", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "localvd"); RNA_def_property_ui_text(prop, "Local View", "Display an isolated sub-set of objects, apart from the scene visibility."); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_VIEW3D, NULL); prop= RNA_def_property(srna, "lens", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "lens"); @@ -717,10 +745,11 @@ static void rna_def_space_buttons(BlenderRNA *brna) {BCONTEXT_SCENE, "SCENE", ICON_SCENE, "Scene", "Scene"}, {BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"}, {BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"}, - {BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraint", "Constraint"}, - {BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifier", "Modifier"}, + {BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraints", "Constraints"}, + {BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifiers", "Modifiers"}, {BCONTEXT_DATA, "DATA", 0, "Data", "Data"}, {BCONTEXT_BONE, "BONE", ICON_BONE_DATA, "Bone", "Bone"}, + {BCONTEXT_BONE_CONSTRAINT, "BONE_CONSTRAINT", ICON_CONSTRAINT, "Bone Constraints", "Bone Constraints"}, {BCONTEXT_MATERIAL, "MATERIAL", ICON_MATERIAL, "Material", "Material"}, {BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"}, {BCONTEXT_PARTICLE, "PARTICLE", ICON_PARTICLES, "Particle", "Particle"}, @@ -779,7 +808,8 @@ static void rna_def_space_image(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_IMAGE, NULL); - prop= RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "iuser"); RNA_def_property_ui_text(prop, "Image User", "Parameters defining which layer, pass and frame of the image is displayed."); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_IMAGE, NULL); @@ -787,7 +817,7 @@ static void rna_def_space_image(BlenderRNA *brna) prop= RNA_def_property(srna, "curves", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "cumap"); RNA_def_property_ui_text(prop, "Curves", "Color curve mapping to use for displaying the image."); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_IMAGE, NULL); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_IMAGE, "rna_SpaceImageEditor_curves_update"); prop= RNA_def_property(srna, "image_pin", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "pin", 0); @@ -808,7 +838,8 @@ static void rna_def_space_image(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE|ND_SPACE_IMAGE, NULL); /* uv */ - prop= RNA_def_property(srna, "uv_editor", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "uv_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "SpaceUVEditor"); RNA_def_property_pointer_funcs(prop, "rna_SpaceImageEditor_uvedit_get", NULL, NULL); RNA_def_property_ui_text(prop, "UV Editor", "UV editor settings."); @@ -1036,6 +1067,13 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) srna= RNA_def_struct(brna, "SpaceDopeSheetEditor", "Space"); RNA_def_struct_sdna(srna, "SpaceAction"); RNA_def_struct_ui_text(srna, "Space DopeSheet Editor", "DopeSheet space data."); + + /* data */ + prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceDopeSheetEditor_action_set", NULL); + RNA_def_property_ui_text(prop, "Action", "Action displayed and edited in this space."); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_DOPESHEET, "rna_SpaceDopeSheetEditor_action_update"); /* mode */ prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); @@ -1199,6 +1237,11 @@ static void rna_def_space_time(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Sequencer Windows", ""); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, "rna_SpaceTime_redraw_update"); + prop= RNA_def_property(srna, "play_nodes", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "redraws", TIME_NODES); + RNA_def_property_ui_text(prop, "Node Windows", ""); + RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, "rna_SpaceTime_redraw_update"); + /* Other options */ prop= RNA_def_property(srna, "continue_physics", PROP_BOOLEAN, PROP_NONE); @@ -1422,7 +1465,6 @@ static void rna_def_space_filebrowser(BlenderRNA *brna) prop= RNA_def_property(srna, "params", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "params"); - RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceFileBrowser_params_set", NULL); RNA_def_property_ui_text(prop, "Filebrowser Parameter", "Parameters and Settings for the Filebrowser."); } diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c index cd39c317bc5..8c9b2b58887 100644 --- a/source/blender/makesrna/intern/rna_text.c +++ b/source/blender/makesrna/intern/rna_text.c @@ -198,7 +198,8 @@ static void rna_def_text(BlenderRNA *brna) RNA_def_property_struct_type(prop, "TextLine"); RNA_def_property_ui_text(prop, "Lines", "Lines of text."); - prop= RNA_def_property(srna, "current_line", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "current_line", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "curl"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "TextLine"); @@ -209,7 +210,8 @@ static void rna_def_text(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Current Character", "Index of current character in current line, and also start index of character in selection if one exists."); - prop= RNA_def_property(srna, "selection_end_line", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "selection_end_line", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "sell"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_struct_type(prop, "TextLine"); @@ -223,6 +225,8 @@ static void rna_def_text(BlenderRNA *brna) prop= RNA_def_property(srna, "markers", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "TextMarker"); RNA_def_property_ui_text(prop, "Markers", "Text markers highlighting part of the text."); + + RNA_api_text(srna); } void RNA_def_text(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_text_api.c b/source/blender/makesrna/intern/rna_text_api.c new file mode 100644 index 00000000000..b048a6b59d0 --- /dev/null +++ b/source/blender/makesrna/intern/rna_text_api.c @@ -0,0 +1,49 @@ +/** + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <stdio.h> + + +#include "RNA_define.h" +#include "RNA_types.h" + +#ifdef RNA_RUNTIME + +#else + +void RNA_api_text(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *prop; + + func= RNA_def_function(srna, "clear", "clear_text"); + RNA_def_function_ui_description(func, "clear the text block."); + + func= RNA_def_function(srna, "write", "write_text"); + RNA_def_function_ui_description(func, "write text at the cursor location and advance to the end of the text block."); + prop= RNA_def_string(func, "text", "Text", 0, "", "New text for this datablock."); + RNA_def_property_flag(prop, PROP_REQUIRED); +} + +#endif diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index f6835f3e7b5..6fb9a9ca57b 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -55,7 +55,7 @@ static EnumPropertyItem texture_filter_items[] = { #include "BKE_texture.h" #include "ED_node.h" -StructRNA *rna_Texture_refine(struct PointerRNA *ptr) +static StructRNA *rna_Texture_refine(struct PointerRNA *ptr) { Tex *tex= (Tex*)ptr->data; @@ -202,7 +202,7 @@ static void rna_Texture_use_color_ramp_set(PointerRNA *ptr, int value) tex->coba= add_colorband(0); } -void rna_Texture_use_nodes_set(PointerRNA *ptr, int v) +static void rna_Texture_use_nodes_set(PointerRNA *ptr, int v) { Tex *tex= (Tex*)ptr->data; @@ -835,6 +835,11 @@ static void rna_def_texture_blend(BlenderRNA *brna) {TEX_RAD, "RADIAL", 0, "Radial", "Creates a radial progression"}, {0, NULL, 0, NULL, NULL}}; + static const EnumPropertyItem prop_flip_axis_items[]= { + {0, "HORIZONTAL", 0, "Horizontal", "Flips the texture's X and Y axis"}, + {TEX_FLIPBLEND, "VERTICAL", 0, "Vertical", "Flips the texture's X and Y axis"}, + {0, NULL, 0, NULL, NULL}}; + srna= RNA_def_struct(brna, "BlendTexture", "Texture"); RNA_def_struct_ui_text(srna, "Blend Texture", "Procedural color blending texture."); RNA_def_struct_sdna(srna, "Tex"); @@ -845,10 +850,12 @@ static void rna_def_texture_blend(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Progression", "Sets the style of the color blending"); RNA_def_property_update(prop, NC_TEXTURE, NULL); - prop= RNA_def_property(srna, "flip_axis", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", TEX_FLIPBLEND); + prop= RNA_def_property(srna, "flip_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, prop_flip_axis_items); RNA_def_property_ui_text(prop, "Flip Axis", "Flips the texture's X and Y axis"); RNA_def_property_update(prop, NC_TEXTURE, NULL); + } static void rna_def_texture_stucci(BlenderRNA *brna) @@ -1066,6 +1073,11 @@ static void rna_def_texture_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Image", ""); RNA_def_property_update(prop, NC_TEXTURE, NULL); + prop= RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "iuser"); + RNA_def_property_ui_text(prop, "Image User", "Parameters defining which layer, pass and frame of the image is displayed."); + RNA_def_property_update(prop, NC_TEXTURE, NULL); + /* filtering */ prop= RNA_def_property(srna, "filter", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "texfilter"); @@ -1109,6 +1121,11 @@ static void rna_def_texture_environment_map(BlenderRNA *brna) rna_def_environment_map_common(srna); + prop= RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "iuser"); + RNA_def_property_ui_text(prop, "Image User", "Parameters defining which layer, pass and frame of the image is displayed."); + RNA_def_property_update(prop, NC_TEXTURE, NULL); + prop= RNA_def_property(srna, "environment_map", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "env"); RNA_def_property_struct_type(prop, "EnvironmentMap"); @@ -1634,9 +1651,7 @@ static void rna_def_texture(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Contrast", ""); RNA_def_property_update(prop, NC_TEXTURE, NULL); - /* XXX: would be nicer to have this as a color selector? - but the values can go past [0,1]. */ - prop= RNA_def_property(srna, "rgb_factor", PROP_FLOAT, PROP_NONE); + prop= RNA_def_property(srna, "rgb_factor", PROP_FLOAT, PROP_RGB); RNA_def_property_float_sdna(prop, NULL, "rfac"); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, 0, 2); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index e3cae8ab453..17846651c3b 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -89,7 +89,7 @@ static void api_ui_item_rna_common(FunctionRNA *func) PropertyRNA *parm; parm= RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property."); - RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR|PROP_NEVER_NULL); parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in data."); RNA_def_property_flag(parm, PROP_REQUIRED); } @@ -146,7 +146,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail."); RNA_def_boolean(func, "slider", 0, "", "Use slider widget for numeric values."); RNA_def_boolean(func, "toggle", 0, "", "Use toggle widget for boolean values."); - RNA_def_boolean(func, "icon_only", 0, "", "Only show the property's icon, with no text"); + RNA_def_boolean(func, "icon_only", 0, "", "Draw only icons in buttons, no text."); func= RNA_def_function(srna, "items_enumR", "uiItemsEnumR"); api_ui_item_rna_common(func); @@ -165,7 +165,7 @@ void RNA_api_ui_layout(StructRNA *srna) api_ui_item_common(func); api_ui_item_rna_common(func); parm= RNA_def_pointer(func, "search_data", "AnyType", "", "Data from which to take collection to search in."); - RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR|PROP_NEVER_NULL); parm= RNA_def_string(func, "search_property", "", 0, "", "Identifier of search collection property."); RNA_def_property_flag(parm, PROP_REQUIRED); @@ -254,31 +254,29 @@ void RNA_api_ui_layout(StructRNA *srna) func= RNA_def_function(srna, "template_modifier", "uiTemplateModifier"); parm= RNA_def_pointer(func, "data", "Modifier", "", "Modifier data."); - RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR|PROP_NEVER_NULL); parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in."); RNA_def_function_return(func, parm); func= RNA_def_function(srna, "template_constraint", "uiTemplateConstraint"); parm= RNA_def_pointer(func, "data", "Constraint", "", "Constraint data."); - RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR|PROP_NEVER_NULL); parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in."); RNA_def_function_return(func, parm); func= RNA_def_function(srna, "template_preview", "uiTemplatePreview"); parm= RNA_def_pointer(func, "id", "ID", "", "ID datablock."); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_pointer(func, "parent", "ID", "", "ID datablock."); - parm= RNA_def_pointer(func, "slot", "TextureSlot", "", "Texture slot."); + RNA_def_pointer(func, "parent", "ID", "", "ID datablock."); + RNA_def_pointer(func, "slot", "TextureSlot", "", "Texture slot."); func= RNA_def_function(srna, "template_curve_mapping", "uiTemplateCurveMapping"); - parm= RNA_def_pointer(func, "curvemap", "CurveMapping", "", "Curve mapping pointer."); - RNA_def_property_flag(parm, PROP_REQUIRED); + api_ui_item_rna_common(func); RNA_def_enum(func, "type", curve_type_items, 0, "Type", "Type of curves to display."); - RNA_def_boolean(func, "compact", 0, "", "Use more compact curve mapping."); + RNA_def_boolean(func, "levels", 0, "", "Show black/white levels."); func= RNA_def_function(srna, "template_color_ramp", "uiTemplateColorRamp"); - parm= RNA_def_pointer(func, "ramp", "ColorRamp", "", "Color ramp pointer."); - RNA_def_property_flag(parm, PROP_REQUIRED); + api_ui_item_rna_common(func); RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail."); func= RNA_def_function(srna, "template_layers", "uiTemplateLayers"); @@ -294,11 +292,21 @@ void RNA_api_ui_layout(StructRNA *srna) parm= RNA_def_pointer(func, "image_user", "ImageUser", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED); - func= RNA_def_function(srna, "template_list", "uiTemplateList"); + func= RNA_def_function(srna, "template_image", "uiTemplateImage"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); api_ui_item_rna_common(func); - parm= RNA_def_pointer(func, "active_data", "AnyType", "", "Data from which to take property for the active element."); + parm= RNA_def_pointer(func, "image_user", "ImageUser", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR); + RNA_def_boolean(func, "compact", 0, "", "Use more compact layout."); + + func= RNA_def_function(srna, "template_list", "uiTemplateList"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + parm= RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property."); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR); + parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in data."); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "active_data", "AnyType", "", "Data from which to take property for the active element."); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR|PROP_NEVER_NULL); parm= RNA_def_string(func, "active_property", "", 0, "", "Identifier of property in data, for the active element."); RNA_def_property_flag(parm, PROP_REQUIRED); parm= RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display.", 0, INT_MAX); @@ -316,11 +324,6 @@ void RNA_api_ui_layout(StructRNA *srna) func= RNA_def_function(srna, "view3d_select_faceselmenu", "uiTemplate_view3d_select_faceselmenu"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); - - func= RNA_def_function(srna, "template_texture_image", "uiTemplateTextureImage"); - RNA_def_function_flag(func, FUNC_USE_CONTEXT); - parm= RNA_def_pointer(func, "texture", "Texture", "", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); } #endif diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 1a000525fda..e9fcb299c53 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -109,11 +109,6 @@ static PointerRNA rna_UserDef_edit_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_UserPreferencesEdit, ptr->data); } -static PointerRNA rna_UserDef_language_get(PointerRNA *ptr) -{ - return rna_pointer_inherit_refine(ptr, &RNA_UserPreferencesLanguage, ptr->data); -} - static PointerRNA rna_UserDef_filepaths_get(PointerRNA *ptr) { return rna_pointer_inherit_refine(ptr, &RNA_UserPreferencesFilePaths, ptr->data); @@ -197,25 +192,29 @@ static void rna_def_userdef_theme_ui_style(BlenderRNA *brna) RNA_def_property_range(prop, 0.5, 2.0); RNA_def_property_ui_text(prop, "Panel Zoom", "Default zoom level for panel areas."); - prop= RNA_def_property(srna, "paneltitle", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "paneltitle", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "paneltitle"); RNA_def_property_struct_type(prop, "ThemeFontStyle"); RNA_def_property_ui_text(prop, "Panel Font", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "grouplabel", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "grouplabel", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "grouplabel"); RNA_def_property_struct_type(prop, "ThemeFontStyle"); RNA_def_property_ui_text(prop, "Group Label Font", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "widgetlabel", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "widgetlabel", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "widgetlabel"); RNA_def_property_struct_type(prop, "ThemeFontStyle"); RNA_def_property_ui_text(prop, "Widget Label Font", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "widget", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "widget", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "widget"); RNA_def_property_struct_type(prop, "ThemeFontStyle"); RNA_def_property_ui_text(prop, "Widget Font", ""); @@ -317,7 +316,7 @@ static void rna_def_userdef_theme_ui_wcol_state(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Driven Selected", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "blend", PROP_FLOAT, PROP_PERCENTAGE); + prop= RNA_def_property(srna, "blend", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "Blend", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); } @@ -334,97 +333,113 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ThemeUI"); RNA_def_struct_ui_text(srna, "Theme User Interface", "Theme settings for user interface elements."); - prop= RNA_def_property(srna, "wcol_regular", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_regular", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_regular"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Regular Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_tool", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_tool", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_tool"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Tool Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_radio", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_radio", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_radio"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Radio Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_text", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_text", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_text"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Text Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_option", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_option", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_option"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Option Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_toggle", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_toggle", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_toggle"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Toggle Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_num", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_num", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_num"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Number Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_numslider", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_numslider", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_numslider"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Slider Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_box", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_box", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_box"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Box Backdrop Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_menu", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_menu", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_menu"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Menu Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_pulldown", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_pulldown", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_pulldown"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Pulldown Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_menu_back", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_menu_back", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_menu_back"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Menu Backdrop Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_menu_item", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_menu_item", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_menu_item"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Menu Item Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_scroll", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_scroll", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_scroll"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "Scroll Widget Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_list_item", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_list_item", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_list_item"); RNA_def_property_struct_type(prop, "ThemeWidgetColors"); RNA_def_property_ui_text(prop, "List Item Colors", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); - prop= RNA_def_property(srna, "wcol_state", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "wcol_state", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "wcol_state"); RNA_def_property_struct_type(prop, "ThemeWidgetStateColors"); RNA_def_property_ui_text(prop, "State Colors", ""); @@ -1380,87 +1395,104 @@ static void rna_def_userdef_themes(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Name", "Name of the theme."); RNA_def_struct_name_property(srna, prop); - prop= RNA_def_property(srna, "user_interface", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "user_interface", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tui"); RNA_def_property_struct_type(prop, "ThemeUserInterface"); RNA_def_property_ui_text(prop, "User Interface", ""); - prop= RNA_def_property(srna, "view_3d", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "view_3d", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tv3d"); RNA_def_property_struct_type(prop, "ThemeView3D"); RNA_def_property_ui_text(prop, "3D View", ""); - prop= RNA_def_property(srna, "graph_editor", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "graph_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tipo"); RNA_def_property_struct_type(prop, "ThemeGraphEditor"); RNA_def_property_ui_text(prop, "Graph Editor", ""); - prop= RNA_def_property(srna, "file_browser", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "file_browser", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tfile"); RNA_def_property_struct_type(prop, "ThemeFileBrowser"); RNA_def_property_ui_text(prop, "File Browser", ""); - prop= RNA_def_property(srna, "nla_editor", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "nla_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tnla"); RNA_def_property_struct_type(prop, "ThemeNLAEditor"); RNA_def_property_ui_text(prop, "NLA Editor", ""); - prop= RNA_def_property(srna, "dopesheet_editor", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "dopesheet_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tact"); RNA_def_property_struct_type(prop, "ThemeDopeSheet"); RNA_def_property_ui_text(prop, "DopeSheet", ""); - prop= RNA_def_property(srna, "image_editor", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "image_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tima"); RNA_def_property_struct_type(prop, "ThemeImageEditor"); RNA_def_property_ui_text(prop, "Image Editor", ""); - prop= RNA_def_property(srna, "sequence_editor", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "sequence_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tseq"); RNA_def_property_struct_type(prop, "ThemeSequenceEditor"); RNA_def_property_ui_text(prop, "Sequence Editor", ""); - prop= RNA_def_property(srna, "properties", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "properties", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tbuts"); RNA_def_property_struct_type(prop, "ThemeProperties"); RNA_def_property_ui_text(prop, "Properties", ""); - prop= RNA_def_property(srna, "text_editor", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "text_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "text"); RNA_def_property_struct_type(prop, "ThemeTextEditor"); RNA_def_property_ui_text(prop, "Text Editor", ""); - prop= RNA_def_property(srna, "timeline", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "timeline", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "ttime"); RNA_def_property_struct_type(prop, "ThemeTimeline"); RNA_def_property_ui_text(prop, "Timeline", ""); - prop= RNA_def_property(srna, "node_editor", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "node_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tnode"); RNA_def_property_struct_type(prop, "ThemeNodeEditor"); RNA_def_property_ui_text(prop, "Node Editor", ""); - prop= RNA_def_property(srna, "logic_editor", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "logic_editor", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tlogic"); RNA_def_property_struct_type(prop, "ThemeLogicEditor"); RNA_def_property_ui_text(prop, "Logic Editor", ""); - prop= RNA_def_property(srna, "outliner", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "outliner", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "toops"); RNA_def_property_struct_type(prop, "ThemeOutliner"); RNA_def_property_ui_text(prop, "Outliner", ""); - prop= RNA_def_property(srna, "info", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "info", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tinfo"); RNA_def_property_struct_type(prop, "ThemeInfo"); RNA_def_property_ui_text(prop, "Info", ""); - prop= RNA_def_property(srna, "user_preferences", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "user_preferences", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "tuserpref"); RNA_def_property_struct_type(prop, "ThemeUserPreferences"); RNA_def_property_ui_text(prop, "User Preferences", ""); - prop= RNA_def_property(srna, "bone_color_sets", PROP_COLLECTION, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "bone_color_sets", PROP_COLLECTION, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_collection_sdna(prop, NULL, "tarm", ""); RNA_def_property_struct_type(prop, "ThemeBoneColorSet"); RNA_def_property_ui_text(prop, "Bone Color Sets", ""); @@ -1531,6 +1563,16 @@ static void rna_def_userdef_view(BlenderRNA *brna) {USER_ZOOM_DOLLY, "DOLLY", 0, "Dolly", "Zooms in and out based on vertical mouse movement."}, {USER_ZOOM_SCALE, "SCALE", 0, "Scale", "Zooms in and out like scaling the view, mouse movements relative to center."}, {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem select_mouse_items[] = { + {USER_LMOUSESELECT, "LEFT", 0, "Left", "Use left Mouse Button for selection."}, + {0, "RIGHT", 0, "Right", "Use Right Mouse Button for selection."}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem middle_mouse_mouse_items[] = { + {0, "PAN", 0, "Pan", "Use the middle mouse button for panning the viewport."}, + {USER_VIEWMOVE, "ROTATE", 0, "Rotate", "Use the middle mouse button for rotation the viewport."}, + {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem view_rotation_items[] = { {0, "TURNTABLE", 0, "Turntable", "Use turntable style rotation in the viewport."}, @@ -1646,15 +1688,11 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Rotate Around Selection", "Use selection as the orbiting center."); /* select with */ - prop= RNA_def_property(srna, "left_mouse_button_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_LMOUSESELECT); - RNA_def_property_boolean_funcs(prop, NULL, "rna_userdef_lmb_select_set"); - RNA_def_property_ui_text(prop, "Left Mouse Button Select", "Use left Mouse Button for selection."); - prop= RNA_def_property(srna, "right_mouse_button_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_LMOUSESELECT); - RNA_def_property_boolean_funcs(prop, NULL, "rna_userdef_rmb_select_set"); - RNA_def_property_ui_text(prop, "Right Mouse Button Select", "Use Right Mouse Button for selection."); + prop= RNA_def_property(srna, "select_mouse", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, select_mouse_items); + RNA_def_property_ui_text(prop, "Select Mouse", "The mouse button used for selection."); prop= RNA_def_property(srna, "emulate_3_button_mouse", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_TWOBUTTONMOUSE); @@ -1683,13 +1721,11 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_userdef_update"); /* middle mouse button */ - prop= RNA_def_property(srna, "middle_mouse_rotate", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_VIEWMOVE); - RNA_def_property_ui_text(prop, "Middle Mouse Rotate", "Use the middle mouse button for rotation the viewport."); - - prop= RNA_def_property(srna, "middle_mouse_pan", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_VIEWMOVE); - RNA_def_property_ui_text(prop, "Middle Mouse Pan", "Use the middle mouse button for panning the viewport."); + + prop= RNA_def_property(srna, "middle_mouse", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, middle_mouse_mouse_items); + RNA_def_property_ui_text(prop, "Middle Mouse", "Use the middle mouse button to pan or zoom the view."); prop= RNA_def_property(srna, "wheel_invert_zoom", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_WHEELZOOMDIR); @@ -1927,87 +1963,6 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Duplicate Particle", "Causes particle systems to be duplicated with the object."); } -static void rna_def_userdef_language(BlenderRNA *brna) -{ - PropertyRNA *prop; - StructRNA *srna; - - /* hardcoded here, could become dynamic somehow */ - static EnumPropertyItem language_items[] = { - {0, "ENGLISH", 0, "English", ""}, - {1, "JAPANESE", 0, "Japanese", ""}, - {2, "DUTCH", 0, "Dutch", ""}, - {3, "ITALIAN", 0, "Italian", ""}, - {4, "GERMAN", 0, "German", ""}, - {5, "FINNISH", 0, "Finnish", ""}, - {6, "SWEDISH", 0, "Swedish", ""}, - {7, "FRENCH", 0, "French", ""}, - {8, "SPANISH", 0, "Spanish", ""}, - {9, "CATALAN", 0, "Catalan", ""}, - {10, "CZECH", 0, "Czech", ""}, - {11, "BRAZILIAN_PORTUGUESE", 0, "Brazilian Portuguese", ""}, - {12, "SIMPLIFIED_CHINESE", 0, "Simplified Chinese", ""}, - {13, "RUSSIAN", 0, "Russian", ""}, - {14, "CROATIAN", 0, "Croatian", ""}, - {15, "SERBIAN", 0, "Serbian", ""}, - {16, "UKRAINIAN", 0, "Ukrainian", ""}, - {17, "POLISH", 0, "Polish", ""}, - {18, "ROMANIAN", 0, "Romanian", ""}, - {19, "ARABIC", 0, "Arabic", ""}, - {20, "BULGARIAN", 0, "Bulgarian", ""}, - {21, "GREEK", 0, "Greek", ""}, - {22, "KOREAN", 0, "Korean", ""}, - {0, NULL, 0, NULL, NULL}}; - - srna= RNA_def_struct(brna, "UserPreferencesLanguage", NULL); - RNA_def_struct_sdna(srna, "UserDef"); - RNA_def_struct_nested(brna, srna, "UserPreferences"); - RNA_def_struct_ui_text(srna, "Language & Font", "User interface translation settings."); - - prop= RNA_def_property(srna, "international_fonts", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_DOTRANSLATE); - RNA_def_property_ui_text(prop, "International Fonts", "Use international fonts."); - RNA_def_property_update(prop, 0, "rna_userdef_update"); - - prop= RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "dpi"); - RNA_def_property_range(prop, 48, 128); - RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display."); - RNA_def_property_update(prop, 0, "rna_userdef_update"); - - prop= RNA_def_property(srna, "scrollback", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "scrollback"); - RNA_def_property_range(prop, 32, 32768); - RNA_def_property_ui_text(prop, "Scrollback", "Maximum number of lines to store for the console buffer."); - - /* Language Selection */ - - prop= RNA_def_property(srna, "language", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, language_items); - RNA_def_property_ui_text(prop, "Language", "Language use for translation."); - RNA_def_property_update(prop, 0, "rna_userdef_update"); - - prop= RNA_def_property(srna, "translate_tooltips", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_TOOLTIPS); - RNA_def_property_ui_text(prop, "Translate Tooltips", "Translate Tooltips."); - RNA_def_property_update(prop, 0, "rna_userdef_update"); - - prop= RNA_def_property(srna, "translate_buttons", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_BUTTONS); - RNA_def_property_ui_text(prop, "Translate Buttons", "Translate button labels."); - RNA_def_property_update(prop, 0, "rna_userdef_update"); - - prop= RNA_def_property(srna, "translate_toolbox", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_MENUS); - RNA_def_property_ui_text(prop, "Translate Toolbox", "Translate toolbox menu."); - RNA_def_property_update(prop, 0, "rna_userdef_update"); - - prop= RNA_def_property(srna, "use_textured_fonts", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_USETEXTUREFONT); - RNA_def_property_ui_text(prop, "Textured Fonts", "Use textures for drawing international fonts."); - RNA_def_property_update(prop, 0, "rna_userdef_update"); -} - static void rna_def_userdef_system(BlenderRNA *brna) { PropertyRNA *prop; @@ -2083,12 +2038,84 @@ static void rna_def_userdef_system(BlenderRNA *brna) {USER_DRAW_OVERLAP, "OVERLAP", 0, "Overlap", "Redraw all overlapping regions, minimal memory usage but more redraws."}, {USER_DRAW_FULL, "FULL", 0, "Full", "Do a full redraw each time, slow, only use for reference or when all else fails."}, {0, NULL, 0, NULL, NULL}}; + + /* hardcoded here, could become dynamic somehow */ + static EnumPropertyItem language_items[] = { + {0, "ENGLISH", 0, "English", ""}, + {1, "JAPANESE", 0, "Japanese", ""}, + {2, "DUTCH", 0, "Dutch", ""}, + {3, "ITALIAN", 0, "Italian", ""}, + {4, "GERMAN", 0, "German", ""}, + {5, "FINNISH", 0, "Finnish", ""}, + {6, "SWEDISH", 0, "Swedish", ""}, + {7, "FRENCH", 0, "French", ""}, + {8, "SPANISH", 0, "Spanish", ""}, + {9, "CATALAN", 0, "Catalan", ""}, + {10, "CZECH", 0, "Czech", ""}, + {11, "BRAZILIAN_PORTUGUESE", 0, "Brazilian Portuguese", ""}, + {12, "SIMPLIFIED_CHINESE", 0, "Simplified Chinese", ""}, + {13, "RUSSIAN", 0, "Russian", ""}, + {14, "CROATIAN", 0, "Croatian", ""}, + {15, "SERBIAN", 0, "Serbian", ""}, + {16, "UKRAINIAN", 0, "Ukrainian", ""}, + {17, "POLISH", 0, "Polish", ""}, + {18, "ROMANIAN", 0, "Romanian", ""}, + {19, "ARABIC", 0, "Arabic", ""}, + {20, "BULGARIAN", 0, "Bulgarian", ""}, + {21, "GREEK", 0, "Greek", ""}, + {22, "KOREAN", 0, "Korean", ""}, + {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "UserPreferencesSystem", NULL); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); RNA_def_struct_ui_text(srna, "System & OpenGL", "Graphics driver and operating system settings."); + /* Language */ + + prop= RNA_def_property(srna, "international_fonts", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_DOTRANSLATE); + RNA_def_property_ui_text(prop, "International Fonts", "Use international fonts."); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop= RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "dpi"); + RNA_def_property_range(prop, 48, 128); + RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display."); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop= RNA_def_property(srna, "scrollback", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "scrollback"); + RNA_def_property_range(prop, 32, 32768); + RNA_def_property_ui_text(prop, "Scrollback", "Maximum number of lines to store for the console buffer."); + + /* Language Selection */ + + prop= RNA_def_property(srna, "language", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, language_items); + RNA_def_property_ui_text(prop, "Language", "Language use for translation."); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop= RNA_def_property(srna, "translate_tooltips", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_TOOLTIPS); + RNA_def_property_ui_text(prop, "Translate Tooltips", "Translate Tooltips."); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop= RNA_def_property(srna, "translate_buttons", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_BUTTONS); + RNA_def_property_ui_text(prop, "Translate Buttons", "Translate button labels."); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop= RNA_def_property(srna, "translate_toolbox", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_TR_MENUS); + RNA_def_property_ui_text(prop, "Translate Toolbox", "Translate toolbox menu."); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop= RNA_def_property(srna, "use_textured_fonts", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "transopts", USER_USETEXTUREFONT); + RNA_def_property_ui_text(prop, "Textured Fonts", "Use textures for drawing international fonts."); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + /* System & OpenGL */ prop= RNA_def_property(srna, "solid_lights", PROP_COLLECTION, PROP_NONE); @@ -2100,7 +2127,8 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_CUSTOM_RANGE); RNA_def_property_ui_text(prop, "Use Weight Color Range", "Enable color range used for weight visualization in weight painting mode."); - prop= RNA_def_property(srna, "weight_color_range", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "weight_color_range", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "coba_weight"); RNA_def_property_struct_type(prop, "ColorRamp"); RNA_def_property_ui_text(prop, "Weight Color Range", "Color range used for weight visualization in weight painting mode."); @@ -2136,14 +2164,6 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_SOUND); RNA_def_property_ui_text(prop, "Game Sound", "Enables sounds to be played in games."); - prop= RNA_def_property(srna, "filter_file_extensions", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_FILTERFILEEXTS); - RNA_def_property_ui_text(prop, "Filter File Extensions", "Display only files with extensions in the image select window."); - - prop= RNA_def_property(srna, "hide_dot_files_datablocks", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_HIDE_DOT); - RNA_def_property_ui_text(prop, "Hide Dot Files/Datablocks", "Hide files/datablocks that start with a dot(.*)"); - prop= RNA_def_property(srna, "clip_alpha", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "glalphaclip"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -2223,7 +2243,15 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); RNA_def_struct_ui_text(srna, "File Paths", "Default paths for external files."); - + + prop= RNA_def_property(srna, "hide_dot_files_datablocks", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_HIDE_DOT); + RNA_def_property_ui_text(prop, "Hide Dot Files/Datablocks", "Hide files/datablocks that start with a dot(.*)"); + + prop= RNA_def_property(srna, "filter_file_extensions", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_FILTERFILEEXTS); + RNA_def_property_ui_text(prop, "Filter File Extensions", "Display only files with extensions in the image select window."); + prop= RNA_def_property(srna, "use_relative_paths", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_RELPATHS); RNA_def_property_ui_text(prop, "Relative Paths", "Default relative path option for the file selector."); @@ -2302,10 +2330,9 @@ void RNA_def_userdef(BlenderRNA *brna) static EnumPropertyItem user_pref_sections[] = { {0, "VIEW_CONTROLS", 0, "View", ""}, {1, "EDIT_METHODS", 0, "Editing", ""}, - {2, "LANGUAGE_COLORS", 0, "Language", ""}, + {2, "FILE_PATHS", 0, "File", ""}, {3, "SYSTEM_OPENGL", 0, "System", ""}, - {4, "FILE_PATHS", 0, "File", ""}, - {5, "THEMES", 0, "Themes", ""}, +// {4, "THEMES", 0, "Themes", ""}, // Leave this out until we figure out a way to manage themes in the prefs. {0, NULL, 0, NULL, NULL}}; rna_def_userdef_dothemes(brna); @@ -2331,34 +2358,32 @@ void RNA_def_userdef(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Styles", ""); /* nested structs */ - prop= RNA_def_property(srna, "view", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "view", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "UserPreferencesView"); RNA_def_property_pointer_funcs(prop, "rna_UserDef_view_get", NULL, NULL); RNA_def_property_ui_text(prop, "View & Controls", "Preferences related to viewing data."); - prop= RNA_def_property(srna, "edit", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "edit", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "UserPreferencesEdit"); RNA_def_property_pointer_funcs(prop, "rna_UserDef_edit_get", NULL, NULL); RNA_def_property_ui_text(prop, "Edit Methods", "Settings for interacting with Blender data."); - prop= RNA_def_property(srna, "language", PROP_POINTER, PROP_NEVER_NULL); - RNA_def_property_struct_type(prop, "UserPreferencesLanguage"); - RNA_def_property_pointer_funcs(prop, "rna_UserDef_language_get", NULL, NULL); - RNA_def_property_ui_text(prop, "Language & Font", "User interface translation settings."); - - prop= RNA_def_property(srna, "filepaths", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "filepaths", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "UserPreferencesFilePaths"); RNA_def_property_pointer_funcs(prop, "rna_UserDef_filepaths_get", NULL, NULL); RNA_def_property_ui_text(prop, "File Paths", "Default paths for external files."); - prop= RNA_def_property(srna, "system", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "system", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "UserPreferencesSystem"); RNA_def_property_pointer_funcs(prop, "rna_UserDef_system_get", NULL, NULL); RNA_def_property_ui_text(prop, "System & OpenGL", "Graphics driver and operating system settings."); rna_def_userdef_view(brna); rna_def_userdef_edit(brna); - rna_def_userdef_language(brna); rna_def_userdef_filepaths(brna); rna_def_userdef_system(brna); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index af3ac4a0a82..0dd9e3aed42 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -46,6 +46,8 @@ EnumPropertyItem event_type_items[] = { {LEFTMOUSE, "LEFTMOUSE", 0, "Left Mouse", ""}, {MIDDLEMOUSE, "MIDDLEMOUSE", 0, "Middle Mouse", ""}, {RIGHTMOUSE, "RIGHTMOUSE", 0, "Right Mouse", ""}, + {BUTTON4MOUSE, "BUTTON4MOUSE", 0, "Button4 Mouse", ""}, + {BUTTON5MOUSE, "BUTTON5MOUSE", 0, "Button5 Mouse", ""}, {ACTIONMOUSE, "ACTIONMOUSE", 0, "Action Mouse", ""}, {SELECTMOUSE, "SELECTMOUSE", 0, "Select Mouse", ""}, @@ -197,7 +199,7 @@ static StructRNA *rna_OperatorProperties_refine(PointerRNA *ptr) return ptr->type; } -IDProperty *rna_OperatorProperties_idproperties(PointerRNA *ptr, int create) +static IDProperty *rna_OperatorProperties_idproperties(PointerRNA *ptr, int create) { if(create && !ptr->data) { IDPropertyTemplate val = {0}; @@ -278,7 +280,8 @@ static void rna_def_operator(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Name", ""); RNA_def_struct_name_property(srna, prop); - prop= RNA_def_property(srna, "properties", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "properties", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "OperatorProperties"); RNA_def_property_ui_text(prop, "Properties", ""); RNA_def_property_pointer_funcs(prop, "rna_Operator_properties_get", NULL, NULL); @@ -404,7 +407,8 @@ static void rna_def_window(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Window", "Open window."); RNA_def_struct_sdna(srna, "wmWindow"); - prop= RNA_def_property(srna, "screen", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "screen", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "Screen"); RNA_def_property_ui_text(prop, "Screen", "Active screen showing in the window."); RNA_def_property_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index 0ed5016ccd2..c6068d0a650 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -431,6 +431,7 @@ void RNA_def_world(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "ambr"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Ambient Color", ""); + RNA_def_property_update(prop, NC_WORLD, NULL); /* exp, range */ prop= RNA_def_property(srna, "exposure", PROP_FLOAT, PROP_NONE); @@ -460,17 +461,20 @@ void RNA_def_world(BlenderRNA *brna) RNA_def_property_update(prop, NC_WORLD, NULL); /* nested structs */ - prop= RNA_def_property(srna, "ambient_occlusion", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "ambient_occlusion", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "WorldAmbientOcclusion"); RNA_def_property_pointer_funcs(prop, "rna_World_ambient_occlusion_get", NULL, NULL); RNA_def_property_ui_text(prop, "Ambient Occlusion", "World ambient occlusion settings."); - prop= RNA_def_property(srna, "mist", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "mist", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "WorldMistSettings"); RNA_def_property_pointer_funcs(prop, "rna_World_mist_get", NULL, NULL); RNA_def_property_ui_text(prop, "Mist", "World mist settings."); - prop= RNA_def_property(srna, "stars", PROP_POINTER, PROP_NEVER_NULL); + prop= RNA_def_property(srna, "stars", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "WorldStarsSettings"); RNA_def_property_pointer_funcs(prop, "rna_World_stars_get", NULL, NULL); RNA_def_property_ui_text(prop, "Stars", "World stars settings."); diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_levels.c b/source/blender/nodes/intern/CMP_nodes/CMP_levels.c index 28b769a8a97..6056e9a28f4 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_levels.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_levels.c @@ -329,8 +329,8 @@ bNodeType cmp_node_view_levels= { /* execfunc */ node_composit_exec_view_levels, /* butfunc */ NULL, /* initfunc */ node_composit_init_view_levels, - /* freestoragefunc */ node_free_standard_storage, - /* copystoragefunc */ node_copy_standard_storage, + /* freestoragefunc */ NULL, + /* copystoragefunc */ NULL, /* id */ NULL }; diff --git a/source/blender/python/epy_doc_gen.py b/source/blender/python/epy_doc_gen.py index c2ef6bbc0d0..4ff5c8102e2 100644 --- a/source/blender/python/epy_doc_gen.py +++ b/source/blender/python/epy_doc_gen.py @@ -225,7 +225,7 @@ def write_func(rna, ident, out, func_type): elif rna_prop_type=='float': if length==0: val_str= '%g' % val - if '.' not in val_str: + if '.' not in val_str and '-' not in val_str: # value could be 1e-05 val_str += '.0' else: # array diff --git a/source/blender/python/generic/Mathutils.c b/source/blender/python/generic/Mathutils.c index 32262276d0a..431f1987383 100644 --- a/source/blender/python/generic/Mathutils.c +++ b/source/blender/python/generic/Mathutils.c @@ -437,7 +437,7 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args) mat[8] = 1.0f; } else if((strcmp(axis, "r") == 0) || (strcmp(axis, "R") == 0)) { //arbitrary rotation - AxisAngleToMat3(vec->vec, angle, (float *)mat); + AxisAngleToMat3(vec->vec, angle, (float (*)[3])mat); } else { PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): unrecognizable axis of rotation type - expected x,y,z or r\n"); @@ -912,7 +912,7 @@ static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args ) PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" ); return NULL; } - if( vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec2->size) { + if( vec1->size != vec2->size || vec1->size != vec3->size || vec3->size != vec2->size) { PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" ); return NULL; } diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index a850809b4a5..d0829acd6cc 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -147,6 +147,17 @@ void bpy_context_clear(bContext *C, PyGILState_STATE *gilstate) } } +static void bpy_import_test(char *modname) +{ + PyObject *mod= PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0); + if(mod) { + Py_DECREF(mod); + } + else { + PyErr_Print(); + PyErr_Clear(); + } +} void BPY_free_compiled_text( struct Text *text ) { @@ -176,7 +187,21 @@ static void bpy_init_modules( void ) PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod); Py_DECREF(mod); - + /* add our own modules dir */ + { + char *modpath= BLI_gethome_folder("scripts/modules", BLI_GETHOME_ALL); + + if(modpath) { + PyObject *sys_path= PySys_GetObject("path"); /* borrow */ + PyObject *py_modpath= PyUnicode_FromString(modpath); + PyList_Insert(sys_path, 0, py_modpath); /* add first */ + Py_DECREF(py_modpath); + } + + bpy_import_test("bpy_ops"); /* adds its self to bpy.ops */ + bpy_import_test("bpy_sys"); /* adds its self to bpy.sys */ + } + /* stand alone utility modules not related to blender directly */ Geometry_Init(); Mathutils_Init(); @@ -232,26 +257,10 @@ static PyObject *CreateGlobalDictionary( bContext *C ) return dict; } -/* Use this so we can include our own python bundle */ -#if 0 -wchar_t* Py_GetPath(void) -{ - int i; - static wchar_t py_path[FILE_MAXDIR] = L""; - char *dirname= BLI_gethome_folder("python"); - if(dirname) { - i= mbstowcs(py_path, dirname, FILE_MAXDIR); - printf("py path %s, %d\n", dirname, i); - } - return py_path; -} -#endif - - /* must be called before Py_Initialize */ void BPY_start_python_path(void) { - char *py_path_bundle= BLI_gethome_folder("python"); + char *py_path_bundle= BLI_gethome_folder("python", BLI_GETHOME_ALL); if(py_path_bundle==NULL) return; @@ -308,6 +317,11 @@ void BPY_start_python( int argc, char **argv ) PyObject *d = PyEval_GetBuiltins( ); PyDict_SetItemString(d, "reload", item=PyCFunction_New(bpy_reload_meth, NULL)); Py_DECREF(item); PyDict_SetItemString(d, "__import__", item=PyCFunction_New(bpy_import_meth, NULL)); Py_DECREF(item); + + /* a bit nasty but this prevents help() and input() from locking blender + * Ideally we could have some way for the console to replace sys.stdin but + * python would lock blender while waiting for a return value, not easy :| */ + PySys_SetObject("stdin", Py_None); } pyrna_alloc_types(); @@ -588,8 +602,9 @@ void BPY_run_ui_scripts(bContext *C, int reload) char *file_extension; char *dirname; char path[FILE_MAX]; - char *dirs[] = {"ui", "io", NULL}; - int a, err; + char *dirs[] = {"scripts/ui", "scripts/io", NULL}; + int path_flags[] = {BLI_GETHOME_LOCAL|BLI_GETHOME_SYSTEM, BLI_GETHOME_USER}; /* SYSTEM / NON-SYSTEM */ + int a, err, flag_iter; PyGILState_STATE gilstate; PyObject *sys_path; @@ -599,56 +614,60 @@ void BPY_run_ui_scripts(bContext *C, int reload) sys_path= PySys_GetObject("path"); /* borrow */ PyList_Insert(sys_path, 0, Py_None); /* place holder, resizes the list */ - for(a=0; dirs[a]; a++) { - dirname= BLI_gethome_folder(dirs[a]); + /* Scan system scripts first, then local/user */ + for(flag_iter=0; flag_iter < sizeof(path_flags)/sizeof(int); flag_iter++) { + + for(a=0; dirs[a]; a++) { + dirname= BLI_gethome_folder(dirs[a], path_flags[flag_iter]); - if(!dirname) - continue; + if(!dirname) + continue; - dir = opendir(dirname); + dir = opendir(dirname); - if(!dir) - continue; - - /* set the first dir in the sys.path for fast importing of modules */ - PyList_SetItem(sys_path, 0, PyUnicode_FromString(dirname)); /* steals the ref */ + if(!dir) + continue; - while((de = readdir(dir)) != NULL) { - /* We could stat the file but easier just to let python - * import it and complain if theres a problem */ - err = 0; - - if (de->d_name[0] == '.') { - /* do nothing, probably .svn */ - } - else if ((file_extension = strstr(de->d_name, ".py"))) { - /* normal py files? */ - if(file_extension && file_extension[3] == '\0') { - de->d_name[(file_extension - de->d_name)] = '\0'; - err= bpy_import_module(de->d_name, reload); + /* set the first dir in the sys.path for fast importing of modules */ + PyList_SetItem(sys_path, 0, PyUnicode_FromString(dirname)); /* steals the ref */ + + while((de = readdir(dir)) != NULL) { + /* We could stat the file but easier just to let python + * import it and complain if theres a problem */ + err = 0; + + if (de->d_name[0] == '.') { + /* do nothing, probably .svn */ + } + else if ((file_extension = strstr(de->d_name, ".py"))) { + /* normal py files? */ + if(file_extension && file_extension[3] == '\0') { + de->d_name[(file_extension - de->d_name)] = '\0'; + err= bpy_import_module(de->d_name, reload); + } } - } #ifndef __linux__ - else if( BLI_join_dirfile(path, dirname, de->d_name), S_ISDIR(BLI_exist(path))) { + else if( BLI_join_dirfile(path, dirname, de->d_name), S_ISDIR(BLI_exist(path))) { #else - else if(de->d_type==DT_DIR) { - BLI_join_dirfile(path, dirname, de->d_name); + else if(de->d_type==DT_DIR) { + BLI_join_dirfile(path, dirname, de->d_name); #endif - /* support packages */ - BLI_join_dirfile(path, path, "__init__.py"); + /* support packages */ + BLI_join_dirfile(path, path, "__init__.py"); - if(BLI_exists(path)) { - err= bpy_import_module(de->d_name, reload); + if(BLI_exists(path)) { + err= bpy_import_module(de->d_name, reload); + } } - } - if(err==-1) { - BPy_errors_to_report(NULL); - fprintf(stderr, "unable to import %s/%s\n", dirname, de->d_name); + if(err==-1) { + BPy_errors_to_report(NULL); + fprintf(stderr, "unable to import %s/%s\n", dirname, de->d_name); + } } - } - closedir(dir); + closedir(dir); + } } PyList_SetSlice(sys_path, 0, 1, NULL); /* remove the first item */ diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 062db42e0e9..301204d3e2b 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -65,7 +65,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args) return NULL; } - if(ot->poll && (ot->poll(C) == FALSE)) { + if(WM_operator_poll((bContext*)C, ot) == FALSE) { PyErr_SetString( PyExc_SystemError, "bpy.__ops__.call: operator poll() function failed, context is incorrect"); return NULL; } @@ -79,16 +79,31 @@ static PyObject *pyop_call( PyObject * self, PyObject * args) if (error_val==0) { - ReportList reports; + ReportList *reports; - BKE_reports_init(&reports, RPT_STORE); + reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); + BKE_reports_init(reports, RPT_STORE); - WM_operator_call_py(C, ot, context, &ptr, &reports); + WM_operator_call_py(C, ot, context, &ptr, reports); - if(BPy_reports_to_error(&reports)) + if(BPy_reports_to_error(reports)) error_val = -1; - BKE_reports_clear(&reports); + /* operator output is nice to have in the terminal/console too */ + if(reports->list.first) { + char *report_str= BKE_reports_string(reports, 0); /* all reports */ + + if(report_str) { + PySys_WriteStdout(report_str); + MEM_freeN(report_str); + } + } + + BKE_reports_clear(reports); + if ((reports->flag & RPT_FREE) == 0) + { + MEM_freeN(reports); + } } WM_operator_properties_free(&ptr); @@ -113,6 +128,58 @@ static PyObject *pyop_call( PyObject * self, PyObject * args) Py_RETURN_NONE; } +static PyObject *pyop_as_string( PyObject * self, PyObject * args) +{ + wmOperatorType *ot; + PointerRNA ptr; + + char *opname; + PyObject *kw= NULL; /* optional args */ + int all_args = 1; + int error_val= 0; + + char *buf; + PyObject *pybuf; + + bContext *C = BPy_GetContext(); + + if (!PyArg_ParseTuple(args, "s|O!i:bpy.__ops__.as_string", &opname, &PyDict_Type, &kw, &all_args)) + return NULL; + + ot= WM_operatortype_find(opname, TRUE); + + if (ot == NULL) { + PyErr_Format( PyExc_SystemError, "bpy.__ops__.as_string: operator \"%s\"could not be found", opname); + return NULL; + } + + /* WM_operator_properties_create(&ptr, opname); */ + /* Save another lookup */ + RNA_pointer_create(NULL, ot->srna, NULL, &ptr); + + if(kw && PyDict_Size(kw)) + error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: "); + + if (error_val==0) + buf= WM_operator_pystring(C, ot, &ptr, all_args); + + WM_operator_properties_free(&ptr); + + if (error_val==-1) { + return NULL; + } + + if(buf) { + pybuf= PyUnicode_FromString(buf); + MEM_freeN(buf); + } + else { + pybuf= PyUnicode_FromString(""); + } + + return pybuf; +} + static PyObject *pyop_dir(PyObject *self) { PyObject *list = PyList_New(0), *name; @@ -157,6 +224,7 @@ static PyObject *pyop_getrna(PyObject *self, PyObject *value) PyObject *BPY_operator_module( void ) { static PyMethodDef pyop_call_meth = {"call", (PyCFunction) pyop_call, METH_VARARGS, NULL}; + static PyMethodDef pyop_as_string_meth ={"as_string", (PyCFunction) pyop_as_string, METH_VARARGS, NULL}; static PyMethodDef pyop_dir_meth = {"dir", (PyCFunction) pyop_dir, METH_NOARGS, NULL}; static PyMethodDef pyop_getrna_meth = {"get_rna", (PyCFunction) pyop_getrna, METH_O, NULL}; static PyMethodDef pyop_add_meth = {"add", (PyCFunction) PYOP_wrap_add, METH_O, NULL}; @@ -166,6 +234,7 @@ PyObject *BPY_operator_module( void ) PyDict_SetItemString(PySys_GetObject("modules"), "bpy.__ops__", submodule); PyModule_AddObject( submodule, "call", PyCFunction_New(&pyop_call_meth, NULL) ); + PyModule_AddObject( submodule, "as_string",PyCFunction_New(&pyop_as_string_meth,NULL) ); PyModule_AddObject( submodule, "dir", PyCFunction_New(&pyop_dir_meth, NULL) ); PyModule_AddObject( submodule, "get_rna", PyCFunction_New(&pyop_getrna_meth, NULL) ); PyModule_AddObject( submodule, "add", PyCFunction_New(&pyop_add_meth, NULL) ); diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 0a487a8dbe8..bbf657d8ce0 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -81,9 +81,9 @@ static struct BPY_flag_def pyop_ret_flags[] = { extern void BPY_update_modules( void ); //XXX temp solution -static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *event) +static int PYTHON_OT_generic(int mode, bContext *C, wmOperatorType *ot, wmOperator *op, wmEvent *event) { - PyObject *py_class = op->type->pyop_data; + PyObject *py_class = ot->pyop_data; PyObject *args; PyObject *ret= NULL, *py_class_instance, *item= NULL; int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED); @@ -105,7 +105,7 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve /* Assign instance attributes from operator properties */ - { + if(op) { const char *arg_name; RNA_STRUCT_BEGIN(op->ptr, prop) { @@ -121,10 +121,12 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve } /* set operator pointer RNA as instance "__operator__" attribute */ - RNA_pointer_create(NULL, &RNA_Operator, op, &ptr_operator); - py_operator= pyrna_struct_CreatePyObject(&ptr_operator); - PyObject_SetAttrString(py_class_instance, "__operator__", py_operator); - Py_DECREF(py_operator); + if(op) { + RNA_pointer_create(NULL, &RNA_Operator, op, &ptr_operator); + py_operator= pyrna_struct_CreatePyObject(&ptr_operator); + PyObject_SetAttrString(py_class_instance, "__operator__", py_operator); + Py_DECREF(py_operator); + } RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context); @@ -148,8 +150,7 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve else if (mode==PYOP_POLL) { item= PyObject_GetAttrString(py_class, "poll"); args = PyTuple_New(2); - //XXX Todo - wrap context in a useful way, None for now. - PyTuple_SET_ITEM(args, 1, Py_None); + PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context)); } PyTuple_SET_ITEM(args, 0, py_class_instance); @@ -160,21 +161,24 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve } if (ret == NULL) { /* covers py_class_instance failing too */ - BPy_errors_to_report(op->reports); + if(op) + BPy_errors_to_report(op->reports); } else { if (mode==PYOP_POLL) { if (PyBool_Check(ret) == 0) { PyErr_SetString(PyExc_ValueError, "Python poll function return value "); - BPy_errors_to_report(op->reports); + if(op) + BPy_errors_to_report(op->reports); } else { ret_flag= ret==Py_True ? 1:0; } } else if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) { - /* the returned value could not be converted into a flag */ - BPy_errors_to_report(op->reports); + /* the returned value could not be converted into a flag */ + if(op) + BPy_errors_to_report(op->reports); ret_flag = OPERATOR_CANCELLED; } @@ -225,19 +229,17 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve static int PYTHON_OT_invoke(bContext *C, wmOperator *op, wmEvent *event) { - return PYTHON_OT_generic(PYOP_INVOKE, C, op, event); + return PYTHON_OT_generic(PYOP_INVOKE, C, op->type, op, event); } static int PYTHON_OT_execute(bContext *C, wmOperator *op) { - return PYTHON_OT_generic(PYOP_EXEC, C, op, NULL); + return PYTHON_OT_generic(PYOP_EXEC, C, op->type, op, NULL); } -static int PYTHON_OT_poll(bContext *C) +static int PYTHON_OT_poll(bContext *C, wmOperatorType *ot) { - // XXX TODO - no way to get the operator type (and therefor class) from the poll function. - //return PYTHON_OT_generic(PYOP_POLL, C, NULL, NULL); - return 1; + return PYTHON_OT_generic(PYOP_POLL, C, ot, NULL, NULL); } void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata) @@ -270,7 +272,7 @@ void PYTHON_OT_wrapper(wmOperatorType *ot, void *userdata) if (PyObject_HasAttrString(py_class, "execute")) ot->exec= PYTHON_OT_execute; if (PyObject_HasAttrString(py_class, "poll")) - ot->poll= PYTHON_OT_poll; + ot->pyop_poll= PYTHON_OT_poll; ot->pyop_data= userdata; diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index dd6bc35fc0a..1f800be266b 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -345,13 +345,33 @@ static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) return result; } +static int pyrna_string_to_enum(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *val, const char *error_prefix) +{ + char *param= _PyUnicode_AsString(item); + + if (param==NULL) { + char *enum_str= pyrna_enum_as_string(ptr, prop); + PyErr_Format(PyExc_TypeError, "%.200s expected a string enum type in (%.200s)", error_prefix, enum_str); + MEM_freeN(enum_str); + return 0; + } else { + if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, val)) { + char *enum_str= pyrna_enum_as_string(ptr, prop); + PyErr_Format(PyExc_TypeError, "%.200s enum \"%.200s\" not found in (%.200s)", error_prefix, param, enum_str); + MEM_freeN(enum_str); + return 0; + } + } + + return 1; +} + PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) { PyObject *ret; int type = RNA_property_type(prop); - int len = RNA_property_array_length(ptr, prop); - if (len > 0) { + if (RNA_property_array_check(ptr, prop)) { return pyrna_py_from_array(ptr, prop); } @@ -521,9 +541,10 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v { /* XXX hard limits should be checked here */ int type = RNA_property_type(prop); - int len = RNA_property_array_length(ptr, prop); - if (len > 0) { + + if (RNA_property_array_check(ptr, prop)) { + /* char error_str[512]; */ int ok= 1; @@ -603,42 +624,52 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v } case PROP_ENUM: { - char *param = _PyUnicode_AsString(value); - - if (param==NULL) { + int val, i; + + if (PyUnicode_Check(value)) { + if (!pyrna_string_to_enum(value, ptr, prop, &val, error_prefix)) + return -1; + } + else if (PyTuple_Check(value)) { + /* tuple of enum items, concatenate all values with OR */ + val= 0; + for (i= 0; i < PyTuple_Size(value); i++) { + int tmpval; + + /* PyTuple_GET_ITEM returns a borrowed reference */ + if (!pyrna_string_to_enum(PyTuple_GET_ITEM(value, i), ptr, prop, &tmpval, error_prefix)) + return -1; + + val |= tmpval; + } + } + else { char *enum_str= pyrna_enum_as_string(ptr, prop); - PyErr_Format(PyExc_TypeError, "%.200s expected a string enum type in (%.200s)", error_prefix, enum_str); + PyErr_Format(PyExc_TypeError, "%.200s expected a string enum or a tuple of strings in (%.200s)", error_prefix, enum_str); MEM_freeN(enum_str); return -1; - } else { - int val; - if (RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, &val)) { - if(data) *((int*)data)= val; - else RNA_property_enum_set(ptr, prop, val); - } else { - char *enum_str= pyrna_enum_as_string(ptr, prop); - PyErr_Format(PyExc_TypeError, "%.200s enum \"%.200s\" not found in (%.200s)", error_prefix, param, enum_str); - MEM_freeN(enum_str); - return -1; - } } + + if(data) *((int*)data)= val; + else RNA_property_enum_set(ptr, prop, val); break; } case PROP_POINTER: { StructRNA *ptype= RNA_property_pointer_type(ptr, prop); + int flag = RNA_property_flag(prop); if(!BPy_StructRNA_Check(value) && value != Py_None) { - PointerRNA tmp; - RNA_pointer_create(NULL, ptype, NULL, &tmp); - PyErr_Format(PyExc_TypeError, "%.200s expected a %.200s type", error_prefix, RNA_struct_identifier(tmp.type)); + PyErr_Format(PyExc_TypeError, "%.200s expected a %.200s type", error_prefix, RNA_struct_identifier(ptype)); + return -1; + } else if((flag & PROP_NEVER_NULL) && value == Py_None) { + PyErr_Format(PyExc_TypeError, "property can't be assigned a None value"); return -1; } else { BPy_StructRNA *param= (BPy_StructRNA*)value; int raise_error= FALSE; if(data) { - int flag = RNA_property_flag(prop); if(flag & PROP_RNAPTR) { if(value == Py_None) @@ -819,13 +850,11 @@ static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self ) if (RNA_property_type(self->prop) == PROP_COLLECTION) { len = RNA_property_collection_length(&self->ptr, self->prop); - } else { + } else if (RNA_property_array_check(&self->ptr, self->prop)) { len = pyrna_prop_array_length(self); - - if (len==0) { /* not an array*/ - PyErr_SetString(PyExc_AttributeError, "len() only available for collection and array RNA types"); - return -1; - } + } else { + PyErr_SetString(PyExc_AttributeError, "len() only available for collection and array RNA types"); + len = -1; /* error value */ } return len; @@ -979,7 +1008,7 @@ static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key ) { if (RNA_property_type(self->prop) == PROP_COLLECTION) { return prop_subscript_collection(self, key); - } else if (RNA_property_array_length(&self->ptr, self->prop)) { /* zero length means its not an array */ + } else if (RNA_property_array_check(&self->ptr, self->prop)) { return prop_subscript_array(self, key); } @@ -1681,32 +1710,32 @@ static PyObject *pyrna_prop_foreach_set(BPy_PropertyRNA *self, PyObject *args) PyObject *pyrna_prop_iter(BPy_PropertyRNA *self) { /* Try get values from a collection */ - PyObject *ret = pyrna_prop_values(self); + PyObject *ret; + PyObject *iter; - if (ret==NULL) { - /* collection did not work, try array */ + if(RNA_property_array_check(&self->ptr, self->prop)) { int len = pyrna_prop_array_length(self); + int i; + PyErr_Clear(); + ret = PyList_New(len); - if (len) { - int i; - PyErr_Clear(); - ret = PyList_New(len); - - for (i=0; i < len; i++) { - PyList_SET_ITEM(ret, i, pyrna_prop_to_py_index(self, i)); - } + for (i=0; i < len; i++) { + PyList_SET_ITEM(ret, i, pyrna_prop_to_py_index(self, i)); } } - - if (ret) { - /* we know this is a list so no need to PyIter_Check */ - PyObject *iter = PyObject_GetIter(ret); - Py_DECREF(ret); - return iter; + else if ((ret = pyrna_prop_values(self))) { + /* do nothing */ + } + else { + PyErr_SetString( PyExc_TypeError, "this BPy_PropertyRNA object is not iterable" ); + return NULL; } - PyErr_SetString( PyExc_TypeError, "this BPy_PropertyRNA object is not iterable" ); - return NULL; + + /* we know this is a list so no need to PyIter_Check */ + iter = PyObject_GetIter(ret); + Py_DECREF(ret); + return iter; } static struct PyMethodDef pyrna_struct_methods[] = { @@ -1776,11 +1805,12 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) { PyObject *ret; int type = RNA_property_type(prop); - int len = RNA_property_array_length(ptr, prop); int a; - if(len > 0) { + if(RNA_property_array_check(ptr, prop)) { + int len = RNA_property_array_length(ptr, prop); + /* resolve the array from a new pytype */ ret = PyTuple_New(len); @@ -1994,8 +2024,10 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw) /* Check if we gave args that dont exist in the function * printing the error is slow but it should only happen when developing. - * the if below is quick, checking if it passed less keyword args then we gave */ - if(kw && (PyDict_Size(kw) > kw_tot)) { + * 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)) { PyObject *key, *value; Py_ssize_t pos = 0; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 99825c0c2ff..48a7c003c9f 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1474,7 +1474,7 @@ static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset) { Object *ob= obr->ob; - Object *tob=0; +// Object *tob=0; Material *ma=0; ParticleSystemModifierData *psmd; ParticleSystem *tpsys=0; @@ -1484,6 +1484,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem ParticleKey state; ParticleCacheKey *cache=0; ParticleBillboardData bb; + ParticleSimulationData sim = {re->scene, ob, psys, NULL}; ParticleStrandData sd; StrandBuffer *strandbuf=0; StrandVert *svert=0; @@ -1517,14 +1518,16 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem return 1; /* 2. start initialising things */ - if(part->phystype==PART_PHYS_KEYED) - psys_count_keyed_targets(ob,psys); /* last possibility to bail out! */ - psmd= psys_get_modifier(ob,psys); + sim.psmd = psmd = psys_get_modifier(ob,psys); if(!(psmd->modifier.mode & eModifierMode_Render)) return 0; + if(part->phystype==PART_PHYS_KEYED) + psys_count_keyed_targets(&sim); + + if(G.rendering == 0) { /* preview render */ totchild = (int)((float)totchild * (float)part->disp / 100.0f); } @@ -1611,14 +1614,14 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem #endif // XXX old animation system cfra = bsystem_time(re->scene, 0, (float)re->scene->r.cfra, 0.0); -/* 2.4 setup reactors */ - if(part->type == PART_REACTOR){ - psys_get_reactor_target(ob, psys, &tob, &tpsys); - if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){ - psmd = psys_get_modifier(tob,tpsys); - tpart = tpsys->part; - } - } +///* 2.4 setup reactors */ +// if(part->type == PART_REACTOR){ +// psys_get_reactor_target(ob, psys, &tob, &tpsys); +// if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){ +// psmd = psys_get_modifier(tob,tpsys); +// tpart = tpsys->part; +// } +// } /* 2.5 setup matrices */ Mat4MulMat4(mat, ob->obmat, re->viewmat); @@ -1695,7 +1698,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem } if(path_nbr == 0) - psys->lattice = psys_get_lattice(re->scene, ob, psys); + psys->lattice = psys_get_lattice(&sim); /* 3. start creating renderable things */ for(a=0,pa=pars; a<totpart+totchild; a++, pa++, seed++) { @@ -1786,8 +1789,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time); - r_tilt = 2.0f * cpa->rand[2]; - r_length = cpa->rand[1]; + r_tilt = 2.0f*(PSYS_FRAND(a + 21) - 0.5f); + r_length = PSYS_FRAND(a + 22); num = cpa->num; @@ -1952,7 +1955,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem continue; state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct; - psys_get_particle_on_path(re->scene,ob,psys,a,&state,1); + psys_get_particle_on_path(&sim,a,&state,1); if(psys->parent) Mat4MulVecfl(psys->parent->obmat, state.co); @@ -1971,7 +1974,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem else { time=0.0f; state.time=cfra; - if(psys_get_particle_state(re->scene,ob,psys,a,&state,0)==0) + if(psys_get_particle_state(&sim,a,&state,0)==0) continue; if(psys->parent) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index b417e07577c..fcfd582a966 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -415,7 +415,7 @@ static int passtype_from_name(char *str) static void render_unique_exr_name(Render *re, char *str, int sample) { - char di[FILE_MAX], name[FILE_MAXFILE], fi[FILE_MAXFILE]; + char di[FILE_MAX], name[FILE_MAXFILE+MAX_ID_NAME+100], fi[FILE_MAXFILE]; BLI_strncpy(di, G.sce, FILE_MAX); BLI_splitdirstring(di, fi); @@ -1537,7 +1537,7 @@ static void threaded_tile_processor(Render *re) if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) { RE_FreeRenderResult(re->result); - if(re->sss_points) + if(re->sss_points && render_display_draw_enabled(re)) re->result= new_render_result(re, &re->disprect, 0, 0); else if(re->r.scemode & R_FULL_SAMPLE) re->result= new_full_sample_buffers_exr(re); diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 5f8cf5504fa..b7832e74cd1 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -92,6 +92,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa { DerivedMesh* dm; ParticleKey state; + ParticleSimulationData sim = {re->scene, ob, psys, NULL}; ParticleData *pa=NULL; float cfra = bsystem_time(re->scene, ob, (float)re->scene->r.cfra, 0.0); int i, childexists; @@ -120,7 +121,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa Mat4Invert(ob->imat, ob->obmat); total_particles = psys->totpart+psys->totchild; - psys->lattice=psys_get_lattice(re->scene,ob,psys); + psys->lattice=psys_get_lattice(&sim); pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6); alloc_point_data(pd, total_particles, data_used); @@ -133,7 +134,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa for (i=0, pa=psys->particles; i < total_particles; i++, pa++) { state.time = cfra; - if(psys_get_particle_state(re->scene, ob, psys, i, &state, 0)) { + if(psys_get_particle_state(&sim, i, &state, 0)) { VECCOPY(partco, state.co); diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 18278d90e72..d84a2d9210a 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -2127,7 +2127,8 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * else max_samples = 1; } else { if (do_soft) max_samples = lar->ray_totsamp; - else max_samples = (R.osa > 4)?R.osa:5; + else if (shi->depth == 0) max_samples = (R.osa > 4)?R.osa:5; + else max_samples = 1; } ray_shadow_jittered_coords(shi, max_samples, jitco, &totjitco); diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index bd022e768f8..29f4d7729fe 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -872,12 +872,17 @@ static void sss_create_tree_mat(Render *re, Material *mat) re->sss_points= &points; re->sss_mat= mat; re->i.partsdone= 0; - re->result= NULL; - RE_TileProcessor(re, 0, !(re->r.mode & R_PREVIEWBUTS)); - RE_FreeRenderResult(re->result); + if(!(re->r.scemode & R_PREVIEWBUTS)) + re->result= NULL; + + RE_TileProcessor(re, 0, 1); + + if(!(re->r.scemode & R_PREVIEWBUTS)) { + RE_FreeRenderResult(re->result); + re->result= rr; + } - re->result= rr; re->i.partsdone= partsdone; re->sss_mat= NULL; re->sss_points= NULL; diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 2d2c01e0bf1..f25a167600f 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -1631,7 +1631,7 @@ void do_material_tex(ShadeInput *shi) float fact, facm, factt, facmm, stencilTin=1.0; float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3], warpvec[3]={0.0f, 0.0f, 0.0f}, Tnor=1.0; int tex_nr, rgbnor= 0, warpdone=0; - float nu[3], nv[3], nn[3] = {0,0,0}, dudnu = 1.f, dudnv = 0.f, dvdnu = 0.f, dvdnv = 1.f; // bump mapping + float nu[3] = {0,0,0}, nv[3] = {0,0,0}, nn[3] = {0,0,0}, dudnu = 1.f, dudnv = 0.f, dvdnu = 0.f, dvdnv = 1.f; // bump mapping int nunvdone= 0; if (R.r.scemode & R_NO_TEX) return; diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index 2808d266d92..0e89a84c8d8 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -419,7 +419,6 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float * float hitco[3], *atten_co; float p; float scatter_fac; - float shade_stepsize = vol_get_stepsize(shi, STEPSIZE_SHADE); if (lar->mode & LA_LAYER) if((lar->lay & shi->obi->lay)==0) return; if ((lar->lay & shi->lay)==0) return; @@ -680,7 +679,6 @@ void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct float hitco[3]; float tr[3] = {1.0,1.0,1.0}; Isect is; - float shade_stepsize = vol_get_stepsize(shi, STEPSIZE_SHADE); float *startco, *endco; float density=0.f; @@ -746,4 +744,4 @@ void shade_volume_inside(ShadeInput *shi, ShadeResult *shr) shi->mat = mat_backup; shi->obi = obi_backup; shi->obr = obi_backup->obr; -}
\ No newline at end of file +} diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index 17858e55e3d..9318d37620c 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -167,12 +167,10 @@ void init_frame_smoke(Render *re, VoxelData *vd, Tex *tex) SmokeModifierData *smd = (SmokeModifierData *)md; if(smd->domain && smd->domain->fluid) { - //int big = (smd->domain->flags & MOD_SMOKE_HIGHRES); - int big=0; - if (big) { - //smoke_turbulence_get_res(smd->domain->wt, vd->resol); - //vd->dataset = smoke_turbulence_get_density(smd->domain->wt); + if (smd->domain->flags & MOD_SMOKE_HIGHRES) { + smoke_turbulence_get_res(smd->domain->wt, vd->resol); + vd->dataset = smoke_turbulence_get_density(smd->domain->wt); } else { VECCOPY(vd->resol, smd->domain->res); vd->dataset = smoke_get_density(smd->domain->fluid); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 6610c5d8931..69c96d0d89d 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -83,12 +83,12 @@ void WM_paint_cursor_end(struct wmWindowManager *wm, void *handle); /* keymap */ void WM_keymap_init (struct bContext *C); -wmKeymapItem *WM_keymap_verify_item(ListBase *lb, char *idname, short type, +wmKeymapItem *WM_keymap_verify_item(wmKeyMap *keymap, char *idname, short type, short val, int modifier, short keymodifier); -wmKeymapItem *WM_keymap_add_item(ListBase *lb, char *idname, short type, +wmKeymapItem *WM_keymap_add_item(wmKeyMap *keymap, char *idname, short type, short val, int modifier, short keymodifier); -void WM_keymap_tweak (ListBase *lb, short type, short val, int modifier, short keymodifier); -ListBase *WM_keymap_listbase (struct wmWindowManager *wm, const char *nameid, +void WM_keymap_tweak (wmKeyMap *keymap, short type, short val, int modifier, short keymodifier); +wmKeyMap *WM_keymap_find (struct wmWindowManager *wm, const char *nameid, short spaceid, short regionid); wmKeyMap *WM_modalkeymap_add(struct wmWindowManager *wm, const char *nameid, struct EnumPropertyItem *items); @@ -104,13 +104,13 @@ void WM_key_event_operator_change(const struct bContext *C, const char *opname, /* handlers */ -struct wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, ListBase *keymap); +struct wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap); /* boundbox, optional subwindow boundbox for offset */ -struct wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, ListBase *keymap, rcti *bb, rcti *swinbb); +struct wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, wmKeyMap *keymap, rcti *bb, rcti *swinbb); /* priority not implemented, it adds in begin */ -struct wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers, ListBase *keymap, int priority); +struct wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers, wmKeyMap *keymap, int priority); -void WM_event_remove_keymap_handler(ListBase *handlers, ListBase *keymap); +void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap); struct wmEventHandler *WM_event_add_ui_handler(const struct bContext *C, ListBase *handlers, int (*func)(struct bContext *C, struct wmEvent *event, void *userdata), @@ -119,7 +119,7 @@ void WM_event_remove_ui_handler(ListBase *handlers, int (*func)(struct bContext *C, struct wmEvent *event, void *userdata), void (*remove)(struct bContext *C, void *userdata), void *userdata); -struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, ListBase *handlers, struct wmOperator *op); +struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op); void WM_event_remove_handlers(struct bContext *C, ListBase *handlers); void WM_event_add_mousemove(struct bContext *C); @@ -162,6 +162,7 @@ wmOperatorType *WM_operatortype_append_macro(char *idname, char *name, int flag) wmOperatorTypeMacro *WM_operatortype_macro_define(wmOperatorType *ot, const char *idname); +int WM_operator_poll (struct bContext *C, struct wmOperatorType *ot); int WM_operator_call (struct bContext *C, struct wmOperator *op); int WM_operator_repeat (struct bContext *C, struct wmOperator *op); int WM_operator_name_call (struct bContext *C, const char *opstring, int context, struct PointerRNA *properties); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 806f5409b0a..c24cf783063 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -276,12 +276,8 @@ typedef struct wmGesture { } wmGesture; /* ************** custom wmEvent data ************** */ - -#define DEV_STYLUS 1 -#define DEV_ERASER 2 - typedef struct wmTabletData { - int Active; /* 0=None, 1=Stylus, 2=Eraser */ + int Active; /* 0=EVT_TABLET_NONE, 1=EVT_TABLET_STYLUS, 2=EVT_TABLET_ERASER */ float Pressure; /* range 0.0 (not touching) to 1.0 (full pressure) */ float Xtilt; /* range 0.0 (upright) to 1.0 (tilted fully against the tablet surface) */ float Ytilt; /* as above */ diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 651394d51af..4405b52888d 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -69,7 +69,7 @@ void WM_operator_free(wmOperator *op) MEM_freeN(op->properties); } - if(op->reports && (op->flag & OPERATOR_REPORT_FREE)) { + if(op->reports && (op->reports->flag & RPT_FREE)) { BKE_reports_clear(op->reports); MEM_freeN(op->reports); } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 79441f33610..846309f1265 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -239,7 +239,7 @@ void wm_event_do_notifiers(bContext *C) if(G.rendering==0) { // XXX make lock in future, or separated derivedmesh users in scene - /* update all objects, ipos, matrices, displists, etc. Flags set by depgraph or manual, + /* update all objects, drivers, matrices, displists, etc. Flags set by depgraph or manual, no layer check here, gets correct flushed */ /* sets first, we allow per definition current scene to have dependencies on sets */ if(scene->set) { @@ -259,20 +259,23 @@ void wm_event_do_notifiers(bContext *C) /* ********************* operators ******************* */ -static int wm_operator_poll(bContext *C, wmOperatorType *ot) +int WM_operator_poll(bContext *C, wmOperatorType *ot) { wmOperatorTypeMacro *otmacro; for(otmacro= ot->macro.first; otmacro; otmacro= otmacro->next) { wmOperatorType *ot= WM_operatortype_find(otmacro->idname, 0); - if(0==wm_operator_poll(C, ot)) + if(0==WM_operator_poll(C, ot)) return 0; } - if(ot->poll) + /* python needs operator type, so we added exception for it */ + if(ot->pyop_poll) + return ot->pyop_poll(C, ot); + else if(ot->poll) return ot->poll(C); - + return 1; } @@ -284,7 +287,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat) if(op==NULL || op->type==NULL) return retval; - if(0==wm_operator_poll(C, op->type)) + if(0==WM_operator_poll(C, op->type)) return retval; if(op->type->exec) @@ -349,8 +352,7 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, P } else { op->reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); - BKE_reports_init(op->reports, RPT_STORE); - op->flag |= OPERATOR_REPORT_FREE; + BKE_reports_init(op->reports, RPT_STORE|RPT_FREE); } /* recursive filling of operator macro list */ @@ -398,7 +400,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P wmWindowManager *wm= CTX_wm_manager(C); int retval= OPERATOR_PASS_THROUGH; - if(wm_operator_poll(C, ot)) { + if(WM_operator_poll(C, ot)) { wmOperator *op= wm_operator_create(wm, ot, properties, reports); /* if reports==NULL, theyll be initialized */ if((G.f & G_DEBUG) && event && event->type!=MOUSEMOVE) @@ -413,7 +415,9 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P else printf("invalid operator call %s\n", ot->idname); /* debug, important to leave a while, should never happen */ - if(!(retval & OPERATOR_RUNNING_MODAL)) { + /* Note, if the report is given as an argument then assume the caller will deal with displaying them + * currently python only uses this */ + if(!(retval & OPERATOR_RUNNING_MODAL) && reports==NULL) { if(op->reports->list.first) /* only show the report if the report list was not given in the function */ uiPupMenuReports(C, op->reports); @@ -555,6 +559,12 @@ int WM_operator_call_py(bContext *C, wmOperatorType *ot, int context, PointerRNA retval= wm_operator_call_internal(C, ot, context, properties, reports); + /* keep the reports around if needed later */ + if (retval & OPERATOR_RUNNING_MODAL || ot->flag & OPTYPE_REGISTER) + { + reports->flag |= RPT_FREE; + } + return retval; } @@ -710,7 +720,7 @@ static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi) /* the matching rules */ if(kmitype==KM_TEXTINPUT) - if(ISKEYBOARD(winevent->type)) return 1; + if(ISTEXTINPUT(winevent->type) && winevent->ascii) return 1; if(kmitype!=KM_ANY) if(winevent->type!=kmitype) return 0; @@ -733,7 +743,7 @@ static int wm_eventmatch(wmEvent *winevent, wmKeymapItem *kmi) /* key modifiers always check when event has it */ /* otherwise regular keypresses with keymodifier still work */ if(winevent->keymodifier) - if(ISKEYBOARD(winevent->type)) + if(ISTEXTINPUT(winevent->type)) if(winevent->keymodifier!=kmi->keymodifier) return 0; return 1; @@ -994,7 +1004,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) int always_pass; if(handlers==NULL) return action; - + /* modal handlers can get removed in this loop, we keep the loop this way */ for(handler= handlers->first; handler; handler= nexthandler) { nexthandler= handler->next; @@ -1009,16 +1019,19 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) action= WM_HANDLER_BREAK; if(handler->keymap) { + wmKeyMap *keymap= handler->keymap; wmKeymapItem *kmi; - for(kmi= handler->keymap->first; kmi; kmi= kmi->next) { - if(wm_eventmatch(event, kmi)) { - - event->keymap_idname= kmi->idname; /* weak, but allows interactive callback to not use rawkey */ - - action= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr); - if(action==WM_HANDLER_BREAK) /* not wm_event_always_pass(event) here, it denotes removed handler */ - break; + if(!keymap->poll || keymap->poll(C)) { + for(kmi= keymap->keymap.first; kmi; kmi= kmi->next) { + if(wm_eventmatch(event, kmi)) { + + event->keymap_idname= kmi->idname; /* weak, but allows interactive callback to not use rawkey */ + + action= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr); + if(action==WM_HANDLER_BREAK) /* not always_pass here, it denotes removed handler */ + break; + } } } } @@ -1034,8 +1047,12 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) action= wm_handler_operator_call(C, handlers, handler, event, NULL); } - if(!always_pass && action==WM_HANDLER_BREAK) - break; + if(action==WM_HANDLER_BREAK) { + if(always_pass) + action= WM_HANDLER_CONTINUE; + else + break; + } } /* fileread case */ @@ -1047,6 +1064,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) static int wm_event_inside_i(wmEvent *event, rcti *rect) { + if(wm_event_always_pass(event)) + return 1; if(BLI_in_rcti(rect, event->x, event->y)) return 1; if(event->type==MOUSEMOVE) { @@ -1138,7 +1157,7 @@ void wm_event_do_handlers(bContext *C) while( (event= win->queue.first) ) { int action; - + CTX_wm_window_set(C, win); /* we let modal handlers get active area/region, also wm_paintcursor_test needs it */ @@ -1148,61 +1167,73 @@ void wm_event_do_handlers(bContext *C) /* MVC demands to not draw in event handlers... but we need to leave it for ogl selecting etc */ wm_window_make_drawable(C, win); - action= wm_handlers_do(C, event, &win->handlers); + /* first we do priority handlers, modal + some limited keymaps */ + action= wm_handlers_do(C, event, &win->modalhandlers); /* fileread case */ - if(CTX_wm_window(C)==NULL) { + if(CTX_wm_window(C)==NULL) return; - } /* builtin tweak, if action is break it removes tweak */ - if(!wm_event_always_pass(event)) - wm_tweakevent_test(C, event, action); - - if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) { + wm_tweakevent_test(C, event, action); + + if(action==WM_HANDLER_CONTINUE) { ScrArea *sa; ARegion *ar; int doit= 0; /* XXX to solve, here screen handlers? */ - if(!wm_event_always_pass(event)) { - if(event->type==MOUSEMOVE) { - /* state variables in screen, cursors */ - ED_screen_set_subwinactive(win, event); - /* for regions having custom cursors */ - wm_paintcursor_test(C, event); - } + if(event->type==MOUSEMOVE) { + /* state variables in screen, cursors */ + ED_screen_set_subwinactive(win, event); + /* for regions having custom cursors */ + wm_paintcursor_test(C, event); } - + for(sa= win->screen->areabase.first; sa; sa= sa->next) { - if(wm_event_always_pass(event) || wm_event_inside_i(event, &sa->totrct)) { - + if(wm_event_inside_i(event, &sa->totrct)) { CTX_wm_area_set(C, sa); - CTX_wm_region_set(C, NULL); - action= wm_handlers_do(C, event, &sa->handlers); - if(wm_event_always_pass(event) || action==WM_HANDLER_CONTINUE) { + if(action==WM_HANDLER_CONTINUE) { for(ar=sa->regionbase.first; ar; ar= ar->next) { - if(wm_event_always_pass(event) || wm_event_inside_i(event, &ar->winrct)) { + if(wm_event_inside_i(event, &ar->winrct)) { CTX_wm_region_set(C, ar); action= wm_handlers_do(C, event, &ar->handlers); doit |= (BLI_in_rcti(&ar->winrct, event->x, event->y)); - if(!wm_event_always_pass(event)) { - if(action==WM_HANDLER_BREAK) - break; - } + if(action==WM_HANDLER_BREAK) + break; } } } + + CTX_wm_region_set(C, NULL); + + if(action==WM_HANDLER_CONTINUE) + action= wm_handlers_do(C, event, &sa->handlers); + + CTX_wm_area_set(C, NULL); + /* NOTE: do not escape on WM_HANDLER_BREAK, mousemove needs handled for previous area */ } } + if(action==WM_HANDLER_CONTINUE) { + /* also some non-modal handlers need active area/region */ + CTX_wm_area_set(C, area_event_inside(C, event->x, event->y)); + CTX_wm_region_set(C, region_event_inside(C, event->x, event->y)); + + action= wm_handlers_do(C, event, &win->handlers); + + /* fileread case */ + if(CTX_wm_window(C)==NULL) + return; + } + /* XXX hrmf, this gives reliable previous mouse coord for area change, feels bad? doing it on ghost queue gives errors when mousemoves go over area borders */ - if(doit && win->screen->subwinactive != win->screen->mainwin) { + if(doit && win->screen && win->screen->subwinactive != win->screen->mainwin) { win->eventstate->prevx= event->x; win->eventstate->prevy= event->y; } @@ -1215,7 +1246,7 @@ void wm_event_do_handlers(bContext *C) } /* only add mousemove when queue was read entirely */ - if(win->addmousemove) { + if(win->addmousemove && win->eventstate) { wmEvent event= *(win->eventstate); event.type= MOUSEMOVE; event.prevx= event.x; @@ -1266,7 +1297,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) handler->op_region= CTX_wm_region(C); handler->filescreen= CTX_wm_screen(C); - BLI_addhead(&win->handlers, handler); + BLI_addhead(&win->modalhandlers, handler); WM_event_fileselect_event(C, op, full?EVT_FILESELECT_FULL_OPEN:EVT_FILESELECT_OPEN); } @@ -1277,9 +1308,10 @@ void WM_event_set_handler_flag(wmEventHandler *handler, int flag) handler->flag= flag; } -wmEventHandler *WM_event_add_modal_handler(bContext *C, ListBase *handlers, wmOperator *op) +wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op) { wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event modal handler"); + wmWindow *win= CTX_wm_window(C); /* operator was part of macro */ if(op->opm) { @@ -1294,15 +1326,20 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, ListBase *handlers, wmOp handler->op_area= CTX_wm_area(C); /* means frozen screen context for modal handlers! */ handler->op_region= CTX_wm_region(C); - BLI_addhead(handlers, handler); + BLI_addhead(&win->modalhandlers, handler); return handler; } -wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, ListBase *keymap) +wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap) { wmEventHandler *handler; + if(!keymap) { + printf("WM_event_add_keymap_handler called with NULL keymap\n"); + return NULL; + } + /* only allow same keymap once */ for(handler= handlers->first; handler; handler= handler->next) if(handler->keymap==keymap) @@ -1316,7 +1353,7 @@ wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, ListBase *keymap } /* priorities not implemented yet, for time being just insert in begin of list */ -wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers, ListBase *keymap, int priority) +wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers, wmKeyMap *keymap, int priority) { wmEventHandler *handler; @@ -1329,7 +1366,7 @@ wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers, ListBas return handler; } -wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, ListBase *keymap, rcti *bblocal, rcti *bbwin) +wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, wmKeyMap *keymap, rcti *bblocal, rcti *bbwin) { wmEventHandler *handler= WM_event_add_keymap_handler(handlers, keymap); @@ -1340,7 +1377,7 @@ wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, ListBase *key return handler; } -void WM_event_remove_keymap_handler(ListBase *handlers, ListBase *keymap) +void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap) { wmEventHandler *handler; @@ -1493,10 +1530,10 @@ static void update_tablet_data(wmWindow *win, wmEvent *event) const GHOST_TabletData *td= GHOST_GetTabletData(win->ghostwin); /* if there's tablet data from an active tablet device then add it */ - if ((td != NULL) && td->Active) { + if ((td != NULL) && td->Active != GHOST_kTabletModeNone) { struct wmTabletData *wmtab= MEM_mallocN(sizeof(wmTabletData), "customdata tablet"); - wmtab->Active = td->Active; + wmtab->Active = (int)td->Active; wmtab->Pressure = td->Pressure; wmtab->Xtilt = td->Xtilt; wmtab->Ytilt = td->Ytilt; @@ -1538,12 +1575,16 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) case GHOST_kEventButtonDown: case GHOST_kEventButtonUp: { GHOST_TEventButtonData *bd= customdata; - event.val= (type==GHOST_kEventButtonDown); + event.val= (type==GHOST_kEventButtonDown) ? KM_PRESS:KM_RELEASE; /* Note!, this starts as 0/1 but later is converted to KM_PRESS/KM_RELEASE by tweak */ if (bd->button == GHOST_kButtonMaskLeft) event.type= LEFTMOUSE; else if (bd->button == GHOST_kButtonMaskRight) event.type= RIGHTMOUSE; + else if (bd->button == GHOST_kButtonMaskButton4) + event.type= BUTTON4MOUSE; + else if (bd->button == GHOST_kButtonMaskButton5) + event.type= BUTTON5MOUSE; else event.type= MIDDLEMOUSE; @@ -1561,7 +1602,7 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) event.val= (type==GHOST_kEventKeyDown)?KM_PRESS:KM_RELEASE; /* exclude arrow keys, esc, etc from text input */ - if(type==GHOST_kEventKeyUp || (event.ascii<32 && event.ascii>14)) + if(type==GHOST_kEventKeyUp || (event.ascii<32 && event.ascii>0)) event.ascii= '\0'; /* modifiers */ @@ -1591,6 +1632,13 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) else if(event.val==KM_RELEASE && event.keymodifier==event.type) event.keymodifier= evt->keymodifier= 0; } + + /* this case happens on some systems that on holding a key pressed, + generate press events without release, we still want to keep the + modifier in win->eventstate, but for the press event of the same + key we don't want the key modifier */ + if(event.keymodifier == event.type) + event.keymodifier= 0; /* if test_break set, it catches this. XXX Keep global for now? */ if(event.type==ESCKEY) diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 9664c6f28ff..bf8568d7480 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -166,6 +166,7 @@ extern wchar_t *copybufinfo; // XXX copy/paste buffer stuff... extern void free_anim_copybuf(); +extern void free_anim_drivers_copybuf(); extern void free_posebuf(); /* called in creator.c even... tsk, split this! */ @@ -186,6 +187,7 @@ void WM_exit(bContext *C) CTX_wm_window_set(C, win); /* needed by operator close callbacks */ WM_event_remove_handlers(C, &win->handlers); + WM_event_remove_handlers(C, &win->modalhandlers); ED_screen_exit(C, win, win->screen); } } @@ -215,6 +217,7 @@ void WM_exit(bContext *C) free_blender(); /* blender.c, does entire library and spacetypes */ // free_matcopybuf(); free_anim_copybuf(); + free_anim_drivers_copybuf(); free_posebuf(); // free_vertexpaint(); // free_imagepaint(); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 5566aeba260..7d25fb8172e 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -96,17 +96,17 @@ static void keymap_properties_set(wmKeymapItem *kmi) } /* if item was added, then bail out */ -wmKeymapItem *WM_keymap_verify_item(ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier) +wmKeymapItem *WM_keymap_verify_item(wmKeyMap *keymap, char *idname, short type, short val, int modifier, short keymodifier) { wmKeymapItem *kmi; - for(kmi= lb->first; kmi; kmi= kmi->next) + for(kmi= keymap->keymap.first; kmi; kmi= kmi->next) if(strncmp(kmi->idname, idname, OP_MAX_TYPENAME)==0) break; if(kmi==NULL) { kmi= MEM_callocN(sizeof(wmKeymapItem), "keymap entry"); - BLI_addtail(lb, kmi); + BLI_addtail(&keymap->keymap, kmi); BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME); keymap_event_set(kmi, type, val, modifier, keymodifier); @@ -116,11 +116,11 @@ wmKeymapItem *WM_keymap_verify_item(ListBase *lb, char *idname, short type, shor } /* always add item */ -wmKeymapItem *WM_keymap_add_item(ListBase *lb, char *idname, short type, short val, int modifier, short keymodifier) +wmKeymapItem *WM_keymap_add_item(wmKeyMap *keymap, char *idname, short type, short val, int modifier, short keymodifier) { wmKeymapItem *kmi= MEM_callocN(sizeof(wmKeymapItem), "keymap entry"); - BLI_addtail(lb, kmi); + BLI_addtail(&keymap->keymap, kmi); BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME); keymap_event_set(kmi, type, val, modifier, keymodifier); @@ -134,14 +134,14 @@ wmKeymapItem *WM_keymap_add_item(ListBase *lb, char *idname, short type, short v space/region ids are same as DNA_space_types.h */ /* gets free'd in wm.c */ -static wmKeyMap *wm_keymap_add(wmWindowManager *wm, const char *nameid, short spaceid, short regionid) +wmKeyMap *WM_keymap_find(wmWindowManager *wm, const char *nameid, short spaceid, short regionid) { wmKeyMap *km; for(km= wm->keymaps.first; km; km= km->next) if(km->spaceid==spaceid && km->regionid==regionid) if(0==strncmp(nameid, km->nameid, KMAP_MAX_NAME)) - break; + return km; if(km==NULL) { km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list"); @@ -154,19 +154,13 @@ static wmKeyMap *wm_keymap_add(wmWindowManager *wm, const char *nameid, short sp return km; } -ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, short spaceid, short regionid) -{ - wmKeyMap *km= wm_keymap_add(wm, nameid, spaceid, regionid); - return &km->keymap; -} - /* ****************** modal keymaps ************ */ /* modal maps get linked to a running operator, and filter the keys before sending to modal() callback */ wmKeyMap *WM_modalkeymap_add(wmWindowManager *wm, const char *nameid, EnumPropertyItem *items) { - wmKeyMap *km= wm_keymap_add(wm, nameid, 0, 0); + wmKeyMap *km= WM_keymap_find(wm, nameid, 0, 0); km->is_modal= 1; km->items= items; @@ -242,15 +236,18 @@ static char *wm_keymap_item_to_string(wmKeymapItem *kmi, char *str, int len) return str; } -static wmKeymapItem *wm_keymap_item_find_handlers(ListBase *handlers, const char *opname, int opcontext, IDProperty *properties, int compare_props) +static wmKeymapItem *wm_keymap_item_find_handlers(const bContext *C, ListBase *handlers, const char *opname, int opcontext, IDProperty *properties, int compare_props) { wmEventHandler *handler; + wmKeyMap *keymap; wmKeymapItem *kmi; /* find keymap item in handlers */ for(handler=handlers->first; handler; handler=handler->next) { - if(handler->keymap) { - for(kmi=handler->keymap->first; kmi; kmi=kmi->next) { + keymap= handler->keymap; + + if(keymap && (!keymap->poll || keymap->poll((bContext*)C))) { + for(kmi=keymap->keymap.first; kmi; kmi=kmi->next) { if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) { if(compare_props) { if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) @@ -272,11 +269,11 @@ static wmKeymapItem *wm_keymap_item_find(const bContext *C, const char *opname, /* look into multiple handler lists to find the item */ if(CTX_wm_window(C)) - found= wm_keymap_item_find_handlers(&CTX_wm_window(C)->handlers, opname, opcontext, properties, compare_props); + found= wm_keymap_item_find_handlers(C, &CTX_wm_window(C)->handlers, opname, opcontext, properties, compare_props); if(CTX_wm_area(C) && found==NULL) - found= wm_keymap_item_find_handlers(&CTX_wm_area(C)->handlers, opname, opcontext, properties, compare_props); + found= wm_keymap_item_find_handlers(C, &CTX_wm_area(C)->handlers, opname, opcontext, properties, compare_props); if(found==NULL) { if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) { @@ -287,12 +284,12 @@ static wmKeymapItem *wm_keymap_item_find(const bContext *C, const char *opname, break; if(ar) - found= wm_keymap_item_find_handlers(&ar->handlers, opname, opcontext, properties, compare_props); + found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props); } } else { if(CTX_wm_region(C)) - found= wm_keymap_item_find_handlers(&CTX_wm_region(C)->handlers, opname, opcontext, properties, compare_props); + found= wm_keymap_item_find_handlers(C, &CTX_wm_region(C)->handlers, opname, opcontext, properties, compare_props); } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index b57edcb4dfc..486a887b354 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -34,6 +34,7 @@ #include <stdio.h> #include "DNA_ID.h" +#include "DNA_object_types.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" #include "DNA_userdef_types.h" @@ -246,7 +247,7 @@ wmOperatorType *WM_operatortype_append_macro(char *idname, char *name, int flag) ot->idname= idname; ot->name= name; - ot->flag= OPTYPE_MACRO | flag; + ot->flag= OPTYPE_MACRO|flag; ot->exec= wm_macro_exec; ot->invoke= wm_macro_invoke; @@ -541,7 +542,7 @@ int WM_operator_winactive(bContext *C) } /* op->invoke */ -static void redo_cb(bContext *C, void *arg_op, void *arg2) +static void redo_cb(bContext *C, void *arg_op, int event) { wmOperator *lastop= arg_op; @@ -563,7 +564,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) block= uiBeginBlock(C, ar, "redo_popup", UI_EMBOSS); uiBlockClearFlag(block, UI_BLOCK_LOOP); uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1); - uiBlockSetFunc(block, redo_cb, arg_op, NULL); + uiBlockSetHandleFunc(block, redo_cb, arg_op); if(!op->properties) { IDPropertyTemplate val = {0}; @@ -681,7 +682,7 @@ static void operator_search_cb(const struct bContext *C, void *arg, char *str, u for(; ot; ot= ot->next) { if(BLI_strcasestr(ot->name, str)) { - if(ot->poll==NULL || ot->poll((bContext *)C)) { + if(WM_operator_poll((bContext*)C, ot)) { char name[256]; int len= strlen(ot->name); @@ -746,11 +747,12 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, wmEvent *event) } /* op->poll */ -int wm_search_menu_poll(bContext *C) +static int wm_search_menu_poll(bContext *C) { if(CTX_wm_window(C)==NULL) return 0; if(CTX_wm_area(C) && CTX_wm_area(C)->spacetype==SPACE_CONSOLE) return 0; // XXX - so we can use the shortcut in the console if(CTX_wm_area(C) && CTX_wm_area(C)->spacetype==SPACE_TEXT) return 0; // XXX - so we can use the spacebar in the text editor + if(CTX_data_edit_object(C) && CTX_data_edit_object(C)->type==OB_CURVE) return 0; // XXX - so we can use the spacebar for entering text return 1; } @@ -879,21 +881,9 @@ static void WM_OT_open_recentfile(wmOperatorType *ot) RNA_def_enum_funcs(prop, open_recentfile_itemf); } -/* ********* main file *********** */ +/* *************** open file **************** */ -static void untitled(char *name) -{ - if (G.save_over == 0 && strlen(name) < FILE_MAX-16) { - char *c= BLI_last_slash(name); - - if (c) - strcpy(&c[1], "untitled.blend"); - else - strcpy(name, "untitled.blend"); - } -} - -static void load_set_load_ui(wmOperator *op) +static void open_set_load_ui(wmOperator *op) { if(!RNA_property_is_set(op->ptr, "load_ui")) RNA_boolean_set(op->ptr, "load_ui", !(U.flag & USER_FILENOUI)); @@ -902,7 +892,7 @@ static void load_set_load_ui(wmOperator *op) static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event) { RNA_string_set(op->ptr, "path", G.sce); - load_set_load_ui(op); + open_set_load_ui(op); WM_event_add_fileselect(C, op); @@ -914,7 +904,7 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op) char path[FILE_MAX]; RNA_string_get(op->ptr, "path", path); - load_set_load_ui(op); + open_set_load_ui(op); if(RNA_boolean_get(op->ptr, "load_ui")) G.fileflags &= ~G_FILE_NO_UI; @@ -945,13 +935,15 @@ static void WM_OT_open_mainfile(wmOperatorType *ot) RNA_def_boolean(ot->srna, "load_ui", 1, "Load UI", "Load user interface setup in the .blend file."); } +/* **************** link/append *************** */ + static int wm_link_append_invoke(bContext *C, wmOperator *op, wmEvent *event) { - if (RNA_property_is_set(op->ptr, "path")) { + if(RNA_property_is_set(op->ptr, "path")) { return WM_operator_call(C, op); } else { - /* XXX solve where to get last linked library from */ + /* XXX TODO solve where to get last linked library from */ RNA_string_set(op->ptr, "path", G.lib); WM_event_add_fileselect(C, op); return OPERATOR_RUNNING_MODAL; @@ -960,27 +952,24 @@ static int wm_link_append_invoke(bContext *C, wmOperator *op, wmEvent *event) static short wm_link_append_flag(wmOperator *op) { - short flag = 0; - if (RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT; - if (RNA_boolean_get(op->ptr, "active_layer")) flag |= FILE_ACTIVELAY; - if (RNA_boolean_get(op->ptr, "relative_paths")) flag |= FILE_STRINGCODE; - if (RNA_boolean_get(op->ptr, "link")) flag |= FILE_LINK; - return flag; -} + short flag= 0; -#define GROUP_MAX 32 + if(RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT; + if(RNA_boolean_get(op->ptr, "active_layer")) flag |= FILE_ACTIVELAY; + if(RNA_boolean_get(op->ptr, "relative_paths")) flag |= FILE_STRINGCODE; + if(RNA_boolean_get(op->ptr, "link")) flag |= FILE_LINK; + return flag; +} -static void make_library_local(const char *libname, Main *main) +static void wm_link_make_library_local(Main *main, const char *libname) { - struct Library *lib; + Library *lib; /* and now find the latest append lib file */ - lib= main->library.first; - while(lib) { - if (BLI_streq(libname, lib->filename)) break; - lib= lib->id.next; - } + for(lib= main->library.first; lib; lib=lib->id.next) + if(BLI_streq(libname, lib->filename)) + break; /* make local */ if(lib) { @@ -993,50 +982,51 @@ static void make_library_local(const char *libname, Main *main) static int wm_link_append_exec(bContext *C, wmOperator *op) { - char name[FILE_MAX], dir[FILE_MAX], libname[FILE_MAX], group[GROUP_MAX]; - int idcode; + Main *bmain= CTX_data_main(C); + Scene *scene= CTX_data_scene(C); + Main *mainl= 0; BlendHandle *bh; - struct Main *main= CTX_data_main(C); - struct Scene *scene= CTX_data_scene(C); - struct Main *mainl= 0; - - struct ScrArea *sa= CTX_wm_area(C); PropertyRNA *prop; - int totfiles=0; + char name[FILE_MAX], dir[FILE_MAX], libname[FILE_MAX], group[GROUP_MAX]; + int idcode, totfiles=0; short flag; name[0] = '\0'; RNA_string_get(op->ptr, "filename", name); RNA_string_get(op->ptr, "directory", dir); - if ( BLO_is_a_library(dir, libname, group)==0 ) { + /* test if we have a valid data */ + if(BLO_is_a_library(dir, libname, group) == 0) { BKE_report(op->reports, RPT_ERROR, "Not a library"); - return OPERATOR_FINISHED; - } else if (group[0]==0) { + return OPERATOR_CANCELLED; + } + else if(group[0] == 0) { BKE_report(op->reports, RPT_ERROR, "Nothing indicated"); - return OPERATOR_FINISHED; - } else if (BLI_streq(main->name, libname)) { + return OPERATOR_CANCELLED; + } + else if(BLI_streq(bmain->name, libname)) { BKE_report(op->reports, RPT_ERROR, "Cannot use current file as library"); - return OPERATOR_FINISHED; + return OPERATOR_CANCELLED; } /* check if something is indicated for append/link */ prop = RNA_struct_find_property(op->ptr, "files"); - if (prop) { + if(prop) { totfiles= RNA_property_collection_length(op->ptr, prop); - if (totfiles == 0) { - if (name[0] == '\0') { + if(totfiles == 0) { + if(name[0] == '\0') { BKE_report(op->reports, RPT_ERROR, "Nothing indicated"); - return OPERATOR_FINISHED; + return OPERATOR_CANCELLED; } } - } else if (name[0] == '\0') { + } + else if(name[0] == '\0') { BKE_report(op->reports, RPT_ERROR, "Nothing indicated"); - return OPERATOR_FINISHED; + return OPERATOR_CANCELLED; } /* now we have or selected, or an indicated file */ - if (RNA_boolean_get(op->ptr, "autoselect")) + if(RNA_boolean_get(op->ptr, "autoselect")) scene_deselect_all(scene); bh = BLO_blendhandle_from_file(libname); @@ -1044,16 +1034,16 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) flag = wm_link_append_flag(op); - if((flag & FILE_LINK)==0) { - /* tag everything, all untagged data can be made local */ + /* tag everything, all untagged data can be made local */ + if((flag & FILE_LINK)==0) flag_all_listbases_ids(LIB_APPEND_TAG, 1); - } /* here appending/linking starts */ mainl = BLO_library_append_begin(C, &bh, libname); - if (totfiles == 0) { + if(totfiles == 0) { BLO_library_append_named_part(C, mainl, &bh, name, idcode, flag); - } else { + } + else { RNA_BEGIN(op->ptr, itemptr, "files") { RNA_string_get(&itemptr, "name", name); BLO_library_append_named_part(C, mainl, &bh, name, idcode, flag); @@ -1062,19 +1052,20 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) } BLO_library_append_end(C, mainl, &bh, idcode, flag); - /* DISPLISTS? */ - recalc_all_library_objects(main); + /* mark all library linked objects to be updated */ + recalc_all_library_objects(bmain); - /* Append, rather than linking */ - if ((flag & FILE_LINK)==0) { - make_library_local(libname, main); - } + /* append, rather than linking */ + if((flag & FILE_LINK)==0) + wm_link_make_library_local(bmain, libname); - /* do we need to do this? */ - if(scene) - DAG_scene_sort(scene); + /* recreate dependency graph to include new objects */ + DAG_scene_sort(scene); + DAG_ids_flush_update(0); BLO_blendhandle_close(bh); + + /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */ BLI_strncpy(G.lib, dir, FILE_MAX); WM_event_add_notifier(C, NC_WINDOW, NULL); @@ -1102,6 +1093,8 @@ static void WM_OT_link_append(wmOperatorType *ot) RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", ""); } +/* *************** recover last session **************** */ + static int wm_recover_last_session_exec(bContext *C, wmOperator *op) { char scestr[FILE_MAX], filename[FILE_MAX]; @@ -1136,6 +1129,20 @@ static void WM_OT_recover_last_session(wmOperatorType *ot) ot->poll= WM_operator_winactive; } +/* *************** save file as **************** */ + +static void untitled(char *name) +{ + if(G.save_over == 0 && strlen(name) < FILE_MAX-16) { + char *c= BLI_last_slash(name); + + if(c) + strcpy(&c[1], "untitled.blend"); + else + strcpy(name, "untitled.blend"); + } +} + static void save_set_compress(wmOperator *op) { if(!RNA_property_is_set(op->ptr, "compress")) { @@ -1198,7 +1205,7 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot) RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file."); } -/* *************** Save file directly ******** */ +/* *************** save file directly ******** */ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *event) { @@ -1361,7 +1368,7 @@ int WM_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event) op->customdata= WM_gesture_new(C, event, WM_GESTURE_CROSS_RECT); /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); wm_gesture_tag_redraw(C); @@ -1425,7 +1432,7 @@ int WM_gesture_circle_invoke(bContext *C, wmOperator *op, wmEvent *event) op->customdata= WM_gesture_new(C, event, WM_GESTURE_CIRCLE); /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); wm_gesture_tag_redraw(C); @@ -1478,7 +1485,7 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, wmEvent *event) case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: - if(event->val==0) { /* key release */ + if(event->val==KM_RELEASE) { /* key release */ wm_gesture_end(C, op); return OPERATOR_FINISHED; } @@ -1561,7 +1568,7 @@ static void tweak_gesture_modal(bContext *C, wmEvent *event) if(gesture->event_type==event->type) { WM_gesture_end(C, gesture); window->tweak= NULL; - + /* when tweak fails we should give the other keymap entries a chance */ event->val= KM_RELEASE; } @@ -1579,7 +1586,7 @@ void wm_tweakevent_test(bContext *C, wmEvent *event, int action) if(win->tweak==NULL) { if(CTX_wm_region(C)) { - if(event->val) { // pressed + if(event->val==KM_PRESS) { // pressed if( ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) ) win->tweak= WM_gesture_new(C, event, WM_GESTURE_TWEAK); } @@ -1602,7 +1609,7 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, wmEvent *event) op->customdata= WM_gesture_new(C, event, WM_GESTURE_LASSO); /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); wm_gesture_tag_redraw(C); @@ -1617,7 +1624,7 @@ int WM_gesture_lines_invoke(bContext *C, wmOperator *op, wmEvent *event) op->customdata= WM_gesture_new(C, event, WM_GESTURE_LINES); /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); wm_gesture_tag_redraw(C); @@ -1679,7 +1686,7 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, wmEvent *event) case LEFTMOUSE: case MIDDLEMOUSE: case RIGHTMOUSE: - if(event->val==0) { /* key release */ + if(event->val==KM_RELEASE) { /* key release */ gesture_lasso_apply(C, op, event->type); return OPERATOR_FINISHED; } @@ -1924,7 +1931,7 @@ int WM_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event) wm_radial_control_paint, op->customdata); /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + WM_event_add_modal_handler(C, op); WM_radial_control_modal(C, op, event); @@ -1972,17 +1979,19 @@ void WM_OT_radial_control_partial(wmOperatorType *ot) /* uses no type defines, fully local testing function anyway... ;) */ -static int ten_timer_exec(bContext *C, wmOperator *op) +static int redraw_timer_exec(bContext *C, wmOperator *op) { ARegion *ar= CTX_wm_region(C); double stime= PIL_check_seconds_timer(); int type = RNA_int_get(op->ptr, "type"); - int a, time; - char tmpstr[128]; + int iter = RNA_int_get(op->ptr, "iterations"); + int a; + float time; + char *infostr= ""; WM_cursor_wait(1); - - for(a=0; a<10; a++) { + + for(a=0; a<iter; a++) { if (type==0) { ED_region_do_draw(C, ar); } @@ -1998,13 +2007,35 @@ static int ten_timer_exec(bContext *C, wmOperator *op) wmWindow *win= CTX_wm_window(C); ScrArea *sa; + ScrArea *sa_back= CTX_wm_area(C); + ARegion *ar_back= CTX_wm_region(C); + + for(sa= CTX_wm_screen(C)->areabase.first; sa; sa= sa->next) { + ARegion *ar_iter; + CTX_wm_area_set(C, sa); + + for(ar_iter= sa->regionbase.first; ar_iter; ar_iter= ar_iter->next) { + CTX_wm_region_set(C, ar_iter); + ED_region_do_draw(C, ar_iter); + } + } + + CTX_wm_window_set(C, win); /* XXX context manipulation warning! */ + + CTX_wm_area_set(C, sa_back); + CTX_wm_region_set(C, ar_back); + } + else if (type==3) { + wmWindow *win= CTX_wm_window(C); + ScrArea *sa; + for(sa= CTX_wm_screen(C)->areabase.first; sa; sa= sa->next) ED_area_tag_redraw(sa); wm_draw_update(C); CTX_wm_window_set(C, win); /* XXX context manipulation warning! */ } - else if (type==3) { + else if (type==4) { Scene *scene= CTX_data_scene(C); if(a & 1) scene->r.cfra--; @@ -2017,40 +2048,43 @@ static int ten_timer_exec(bContext *C, wmOperator *op) } } - time= (int) ((PIL_check_seconds_timer()-stime)*1000); + time= ((PIL_check_seconds_timer()-stime)*1000); - if(type==0) sprintf(tmpstr, "10 x Draw Region: %d ms", time); - if(type==1) sprintf(tmpstr, "10 x Draw Region and Swap: %d ms", time); - if(type==2) sprintf(tmpstr, "10 x Draw Window and Swap: %d ms", time); - if(type==3) sprintf(tmpstr, "Anim Step: %d ms", time); - if(type==4) sprintf(tmpstr, "10 x Undo/Redo: %d ms", time); + if(type==0) infostr= "Draw Region"; + if(type==1) infostr= "Draw Region and Swap"; + if(type==2) infostr= "Draw Window"; + if(type==3) infostr= "Draw Window and Swap"; + if(type==4) infostr= "Animation Steps"; + if(type==5) infostr= "Undo/Redo"; WM_cursor_wait(0); - uiPupMenuNotice(C, tmpstr); + BKE_reportf(op->reports, RPT_INFO, "%d x %s: %.2f ms, average: %.4f", iter, infostr, time, time/iter); return OPERATOR_FINISHED; } -static void WM_OT_ten_timer(wmOperatorType *ot) +static void WM_OT_redraw_timer(wmOperatorType *ot) { static EnumPropertyItem prop_type_items[] = { {0, "DRAW", 0, "Draw Region", ""}, - {1, "DRAWSWAP", 0, "Draw Region + Swap", ""}, - {2, "DRAWWINSWAP", 0, "Draw Window + Swap", ""}, - {3, "ANIMSTEP", 0, "Anim Step", ""}, - {4, "UNDO", 0, "Undo/Redo", ""}, + {1, "DRAW_SWAP", 0, "Draw Region + Swap", ""}, + {2, "DRAW_WIN", 0, "Draw Window", ""}, + {3, "DRAW_WIN_SWAP", 0, "Draw Window + Swap", ""}, + {4, "ANIM_STEP", 0, "Anim Step", ""}, + {5, "UNDO", 0, "Undo/Redo", ""}, {0, NULL, 0, NULL, NULL}}; - ot->name= "Ten Timer"; - ot->idname= "WM_OT_ten_timer"; - ot->description="Ten Timer operator."; + ot->name= "Redraw Timer"; + ot->idname= "WM_OT_redraw_timer"; + ot->description="Simple redraw timer to test the speed of updating the interface."; ot->invoke= WM_menu_invoke; - ot->exec= ten_timer_exec; + ot->exec= redraw_timer_exec; ot->poll= WM_operator_winactive; RNA_def_enum(ot->srna, "type", prop_type_items, 0, "Type", ""); + RNA_def_int(ot->srna, "iterations", 10, 1,INT_MAX, "Iterations", "Number of times to redraw", 1,1000); } @@ -2085,7 +2119,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_jobs_timer); WM_operatortype_append(WM_OT_save_as_mainfile); WM_operatortype_append(WM_OT_save_mainfile); - WM_operatortype_append(WM_OT_ten_timer); + WM_operatortype_append(WM_OT_redraw_timer); WM_operatortype_append(WM_OT_debug_menu); WM_operatortype_append(WM_OT_search_menu); } @@ -2093,7 +2127,7 @@ void wm_operatortype_init(void) /* default keymap for windows and screens, only call once per WM */ void wm_window_keymap(wmWindowManager *wm) { - ListBase *keymap= WM_keymap_listbase(wm, "Window", 0, 0); + wmKeyMap *keymap= WM_keymap_find(wm, "Window", 0, 0); /* items to make WM work */ WM_keymap_verify_item(keymap, "WM_OT_jobs_timer", TIMERJOBS, KM_ANY, KM_ANY, 0); @@ -2112,7 +2146,7 @@ void wm_window_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "WM_OT_save_homefile", UKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "WM_OT_open_recentfile", OKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0); WM_keymap_add_item(keymap, "WM_OT_open_mainfile", OKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "WM_OT_link_append", OKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); + WM_keymap_add_item(keymap, "WM_OT_link_append", OKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); WM_keymap_add_item(keymap, "WM_OT_save_mainfile", SKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "WM_OT_save_as_mainfile", SKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0); @@ -2120,7 +2154,7 @@ void wm_window_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "WM_OT_exit_blender", QKEY, KM_PRESS, KM_CTRL, 0); /* debug/testing */ - WM_keymap_verify_item(keymap, "WM_OT_ten_timer", TKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); + WM_keymap_verify_item(keymap, "WM_OT_redraw_timer", TKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index d70516ef02e..c853afe4507 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -146,6 +146,7 @@ void wm_window_free(bContext *C, wmWindow *win) CTX_wm_window_set(C, NULL); WM_event_remove_handlers(C, &win->handlers); + WM_event_remove_handlers(C, &win->modalhandlers); /* end running jobs, a job end also removes its timer */ for(wt= win->timers.first; wt; wt= wtnext) { @@ -331,7 +332,7 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, char *title, wmWindow /* called in wm_check, also inits stuff after file read */ void wm_window_add_ghostwindows(wmWindowManager *wm) { - ListBase *keymap; + wmKeyMap *keymap; wmWindow *win; /* no commandline prefsize? then we set this */ @@ -367,11 +368,14 @@ void wm_window_add_ghostwindows(wmWindowManager *wm) win->eventstate= MEM_callocN(sizeof(wmEvent), "window event state"); /* add keymap handlers (1 handler for all keys in map!) */ - keymap= WM_keymap_listbase(wm, "Window", 0, 0); + keymap= WM_keymap_find(wm, "Window", 0, 0); WM_event_add_keymap_handler(&win->handlers, keymap); - keymap= WM_keymap_listbase(wm, "Screen", 0, 0); + keymap= WM_keymap_find(wm, "Screen", 0, 0); WM_event_add_keymap_handler(&win->handlers, keymap); + + keymap= WM_keymap_find(wm, "Screen Editing", 0, 0); + WM_event_add_keymap_handler(&win->modalhandlers, keymap); wm_window_title(wm, win); } @@ -623,6 +627,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) if(state!=GHOST_kWindowStateMinimized) { GHOST_RectangleHandle client_rect; int l, t, r, b, scr_w, scr_h; + int sizex, sizey, posx, posy; client_rect= GHOST_GetClientBounds(win->ghostwin); GHOST_GetRectangle(client_rect, &l, &t, &r, &b); @@ -630,37 +635,56 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) GHOST_DisposeRectangle(client_rect); wm_get_screensize(&scr_w, &scr_h); - win->sizex= r-l; - win->sizey= b-t; - win->posx= l; - win->posy= scr_h - t - win->sizey; - - /* debug prints */ - if(0) { - state = GHOST_GetWindowState(win->ghostwin); - - if(state==GHOST_kWindowStateNormal) { - if(G.f & G_DEBUG) printf("window state: normal\n"); - } - else if(state==GHOST_kWindowStateMinimized) { - if(G.f & G_DEBUG) printf("window state: minimized\n"); - } - else if(state==GHOST_kWindowStateMaximized) { - if(G.f & G_DEBUG) printf("window state: maximized\n"); + sizex= r-l; + sizey= b-t; + posx= l; + posy= scr_h - t - win->sizey; + + /* + * Ghost sometimes send size or move events when the window hasn't changed. + * One case of this is using compiz on linux. To alleviate the problem + * we ignore all such event here. + * + * It might be good to eventually do that at Ghost level, but that is for + * another time. + */ + if (win->sizex != sizex || + win->sizey != sizey || + win->posx != posx || + win->posy != posy) + { + win->sizex= sizex; + win->sizey= sizey; + win->posx= posx; + win->posy= posy; + + /* debug prints */ + if(0) { + state = GHOST_GetWindowState(win->ghostwin); + + if(state==GHOST_kWindowStateNormal) { + if(G.f & G_DEBUG) printf("window state: normal\n"); + } + else if(state==GHOST_kWindowStateMinimized) { + if(G.f & G_DEBUG) printf("window state: minimized\n"); + } + else if(state==GHOST_kWindowStateMaximized) { + if(G.f & G_DEBUG) printf("window state: maximized\n"); + } + else if(state==GHOST_kWindowStateFullScreen) { + if(G.f & G_DEBUG) printf("window state: fullscreen\n"); + } + + if(type!=GHOST_kEventWindowSize) { + if(G.f & G_DEBUG) printf("win move event pos %d %d size %d %d\n", win->posx, win->posy, win->sizex, win->sizey); + } + } - else if(state==GHOST_kWindowStateFullScreen) { - if(G.f & G_DEBUG) printf("window state: fullscreen\n"); - } - - if(type!=GHOST_kEventWindowSize) { - if(G.f & G_DEBUG) printf("win move event pos %d %d size %d %d\n", win->posx, win->posy, win->sizex, win->sizey); - } - + + wm_window_make_drawable(C, win); + wm_draw_window_clear(win); + WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); } - - wm_window_make_drawable(C, win); - wm_draw_window_clear(win); - WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); } break; } diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index 9a3bba9af1d..4360e49e371 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -43,7 +43,7 @@ typedef struct wmEventHandler { int type, flag; /* type default=0, rest is custom */ /* keymap handler */ - ListBase *keymap; /* pointer to builtin/custom keymaps */ + wmKeyMap *keymap; /* pointer to builtin/custom keymaps */ rcti *bblocal, *bbwin; /* optional local and windowspace bb */ diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 3da621bda85..cc6041ce529 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -40,7 +40,7 @@ #define EVT_DATA_GESTURE 2 #define EVT_DATA_TIMER 3 -/* tablet active */ +/* tablet active, matches GHOST_TTabletMode */ #define EVT_TABLET_NONE 0 #define EVT_TABLET_STYLUS 1 #define EVT_TABLET_ERASER 2 @@ -56,6 +56,9 @@ /* only use if you want user option switch possible */ #define ACTIONMOUSE 0x005 #define SELECTMOUSE 0x006 +/* Extra mouse buttons */ +#define BUTTON4MOUSE 0x007 +#define BUTTON5MOUSE 0x008 /* defaults from ghost */ #define WHEELUPMOUSE 0x00a #define WHEELDOWNMOUSE 0x00b @@ -191,10 +194,13 @@ /* for event checks */ /* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */ -#define ISKEYBOARD(event) (event >=' ' && event <=255) +#define ISTEXTINPUT(event) (event >=' ' && event <=255) + + /* test wether the event is a key on the keyboard */ +#define ISKEYBOARD(event) (event >=' ' && event <=320) /* test whether event type is acceptable as hotkey, excluding modifiers */ -#define ISHOTKEY(event) (event >=' ' && event <=320 && !(event>=LEFTCTRLKEY && event<=ESCKEY) && !(event>=UNKNOWNKEY && event<=GRLESSKEY)) +#define ISHOTKEY(event) (ISKEYBOARD(event) && !(event>=LEFTCTRLKEY && event<=ESCKEY) && !(event>=UNKNOWNKEY && event<=GRLESSKEY)) /* **************** BLENDER GESTURE EVENTS ********************* */ |